From 4ecd4936bd275f9ddb8abddfcf55da3d296e8412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Mon, 1 Jun 2020 20:29:28 +0200 Subject: [PATCH] Add support for static value blocks. --- .../minicards/CanvasView.java | 64 +-- .../codigoparallevar/minicards/CardFile.java | 10 +- .../minicards/SignalListenerManager.java | 1 - .../parts/ProgramakerCustomBlockPart.java | 35 +- .../connectors/AnyRoundOutputConnector.java | 76 ++-- .../BooleanRoundInputConnector.java | 4 +- .../BooleanRoundOutputConnector.java | 2 +- .../parts/connectors/ConnectorTypeInfo.java | 42 ++ ...ProgramakerCustomBlockInputConnector.java} | 40 +- .../parts/connectors/RoundInputConnector.java | 4 +- .../SignalRoundOutputConnector.java | 2 +- .../connectors/StringRoundInputConnector.java | 4 +- .../StringRoundOutputConnector.java | 5 +- .../parts/strings/ConvertToString.java | 10 +- .../parts/values/StaticValuePart.java | 406 ++++++++++++++++++ .../minicards/types/Dropper.java | 2 +- .../minicards/types/Part.java | 2 + .../types/connectors/Wiring/Wire.java | 6 +- .../connectors/input/AnyInputConnector.java | 8 +- .../connectors/input/InputConnector.java | 5 +- .../input/SignalInputConnector.java | 1 + .../connectors/output/OutputConnector.java | 2 + app/src/main/res/values/strings.xml | 3 + 23 files changed, 627 insertions(+), 107 deletions(-) rename app/src/main/java/com/codigoparallevar/minicards/parts/connectors/{AnyRoundInputConnector.java => ProgramakerCustomBlockInputConnector.java} (61%) create mode 100644 app/src/main/java/com/codigoparallevar/minicards/parts/values/StaticValuePart.java diff --git a/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java b/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java index 499a14a..d8789a2 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java +++ b/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java @@ -13,7 +13,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.codigoparallevar.minicards.motion.MotionMode; -import com.codigoparallevar.minicards.parts.connectors.SignalRoundOutputConnector; +import com.codigoparallevar.minicards.parts.connectors.ProgramakerCustomBlockInputConnector; import com.codigoparallevar.minicards.types.Part; import com.codigoparallevar.minicards.types.PartConnection; import com.codigoparallevar.minicards.types.PartGrid; @@ -185,7 +185,15 @@ public class CanvasView extends View implements PartGrid { final int xInCanvas = xInScreen + _viewOrigin.item1; final int yInCanvas = yInScreen + _viewOrigin.item2; - switch (event.getAction()){ + int action = event.getAction(); + if ((action == MotionEvent.ACTION_MOVE) + && _devMode + && (selectedPart instanceof Wire)) { + // Wires cannot be moved, so go into "move canvas" mode + selectedPart = null; + } + + switch (action){ case MotionEvent.ACTION_DOWN: { _mouseDownPoint = new Tuple2<>(xInScreen, yInScreen); @@ -197,18 +205,7 @@ public class CanvasView extends View implements PartGrid { Log.d(LogTag, "Touched part not found"); return false; } - if (selectedPart instanceof Wire) { - // No drag or long-touch, just show the "cut" option - // TODO: - Log.d(LogTag, "Touched Wire"); - Wire selectedWire = (Wire) selectedPart; - selectedPart = null; - - selectedWire.unlink(); - } - else { - Log.d(LogTag, "Touched part FOUND. Part: " + selectedPart); - } + Log.d(LogTag, "Touched part FOUND. Part: " + selectedPart); } break; @@ -222,9 +219,23 @@ public class CanvasView extends View implements PartGrid { if (selectedPart instanceof Part){ ((Part) selectedPart).touched(); } + else if (selectedPart instanceof Wire) { + // TODO: No drag or long-touch, just show the "cut" option + Log.d(LogTag, "Touched Wire"); + Wire selectedWire = (Wire) selectedPart; + selectedPart = null; + + selectedWire.unlink(); + } + else if (selectedPart instanceof ProgramakerCustomBlockInputConnector) { + ((ProgramakerCustomBlockInputConnector) selectedPart).touched(); + } } } else if (motionMode == MotionMode.Type.LongTouch && _devMode) { + if (selectedPart instanceof Wire) { + // Wires cannot be moved, so go into the + } if (selectedPart != null) { selectedPart.getMoveable().drop(xInCanvas, yInCanvas); @@ -351,15 +362,15 @@ public class CanvasView extends View implements PartGrid { } } -// // Then with input ones -// List inputConnectors = part.getInputConnectors(); -// if (inputConnectors != null) { -// for (InputConnector inputConnector : inputConnectors) { -// if (inputConnector.containsPoint(x, y)) { -// return inputConnector; -// } -// } -// } + // Then with input ones + List inputConnectors = part.getInputConnectors(); + if (inputConnectors != null) { + for (InputConnector inputConnector : inputConnectors) { + if (inputConnector.containsPoint(x, y)) { + return inputConnector; + } + } + } } // Finally, try with the wires @@ -545,11 +556,8 @@ public class CanvasView extends View implements PartGrid { @Override public void update() { - parentActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - CanvasView.this.invalidate(); - } + parentActivity.runOnUiThread(() -> { + CanvasView.this.invalidate(); }); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/CardFile.java b/app/src/main/java/com/codigoparallevar/minicards/CardFile.java index 0aa786f..be14bd3 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/CardFile.java +++ b/app/src/main/java/com/codigoparallevar/minicards/CardFile.java @@ -15,6 +15,7 @@ import com.codigoparallevar.minicards.parts.logic.Toggle; import com.codigoparallevar.minicards.parts.samples.ColorBox; import com.codigoparallevar.minicards.parts.samples.Placeholder; import com.codigoparallevar.minicards.parts.strings.ConvertToString; +import com.codigoparallevar.minicards.parts.values.StaticValuePart; import com.codigoparallevar.minicards.types.Part; import com.codigoparallevar.minicards.types.PartConnection; import com.codigoparallevar.minicards.types.PartGrid; @@ -239,7 +240,7 @@ public class CardFile { card.addConnections(info.item2); } } catch (JSONException e) { - throw new ErrorLoadingCardException(ErrorLoadingCardException.Reason.UNKNOWN_FORMAT); + throw new ErrorLoadingCardException(ErrorLoadingCardException.Reason.UNKNOWN_FORMAT); } return card; @@ -293,6 +294,13 @@ public class CardFile { return customBlockPartInfo; } + else if (type.equals(StaticValuePart.class.getName())){ + Tuple2> staticValuePartInfo = StaticValuePart.deserialize( + grid, + jsonObject.getJSONObject("_data")); + + return staticValuePartInfo; + } else { throw new JSONException("Expected known class, found " + type); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/SignalListenerManager.java b/app/src/main/java/com/codigoparallevar/minicards/SignalListenerManager.java index b9b50eb..97a4fcb 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/SignalListenerManager.java +++ b/app/src/main/java/com/codigoparallevar/minicards/SignalListenerManager.java @@ -67,7 +67,6 @@ public class SignalListenerManager implements ProgramakerSignalListener { } private void onDisconnect(String bridgeId, String key) { - Log.w(LogTag, "Connection lost to (bridge="+bridgeId+",key="+key + ")"); Tuple2 id = new Tuple2<>(bridgeId, key); // Check that there is still someone listening diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/ProgramakerCustomBlockPart.java b/app/src/main/java/com/codigoparallevar/minicards/parts/ProgramakerCustomBlockPart.java index 3188268..84edf1a 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/ProgramakerCustomBlockPart.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/ProgramakerCustomBlockPart.java @@ -7,7 +7,7 @@ import android.os.AsyncTask; import android.util.Log; import com.codigoparallevar.minicards.ScrolledCanvas; -import com.codigoparallevar.minicards.parts.connectors.AnyRoundInputConnector; +import com.codigoparallevar.minicards.parts.connectors.ProgramakerCustomBlockInputConnector; import com.codigoparallevar.minicards.parts.connectors.AnyRoundOutputConnector; import com.codigoparallevar.minicards.parts.connectors.ConnectorTypeInfo; import com.codigoparallevar.minicards.parts.connectors.RoundOutputConnector; @@ -48,7 +48,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen private static final int IO_PADDING = 20; private static final String LogTag = "PM Custom block part"; - private List> inputConnectors = null; + private List> inputConnectors = null; private List> outputConnectors = null; private final PartGrid _partGrid; @@ -141,16 +141,18 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen final boolean has_pulse_output = has_pulse_input || type.equals("trigger"); final boolean hasImplicitOutput = type.equals("getter"); - final List> inputs = new LinkedList<>(); + final List> inputs = new LinkedList<>(); final List> outputs = new LinkedList<>(); SignalRoundOutputConnector pulseOutput = null; // Add pulses if (has_pulse_input) { - inputs.add(new Tuple2<>(new ConnectorTypeInfo(ConnectorTypeInfo.Type.PULSE), - new AnyRoundInputConnector(this, 0, 0, - IO_RADIUS)) + ConnectorTypeInfo typeInfo = new ConnectorTypeInfo(ConnectorTypeInfo.Type.PULSE); + inputs.add(new Tuple2<>(typeInfo, + new ProgramakerCustomBlockInputConnector(this, _partGrid, + 0, 0, + IO_RADIUS, typeInfo)) ); } if (has_pulse_output) { @@ -185,8 +187,11 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen savedTo = arg; } else { - inputs.add(new Tuple2<>(ConnectorTypeInfo.FromTypeName(arg.getType()), - new AnyRoundInputConnector(this, 0, 0, IO_RADIUS))); + ConnectorTypeInfo typeInfo = ConnectorTypeInfo.FromTypeName(arg.getType()); + inputs.add(new Tuple2<>(typeInfo, + new ProgramakerCustomBlockInputConnector(this, _partGrid, + 0, 0, + IO_RADIUS, typeInfo))); } } } @@ -218,7 +223,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen // Update inputs int y = get_top(); int x = get_left() + IO_PADDING; - for (Tuple2 entry : inputConnectors) { + for (Tuple2 entry : inputConnectors) { InputConnector input = entry.item2; int new_x = x + IO_PADDING + IO_RADIUS / 2; input.updatePosition(new_x, y); @@ -250,7 +255,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen @Override public List getInputConnectors() { List result = new ArrayList<>(inputConnectors.size()); - for (Tuple2 entry : inputConnectors) { + for (Tuple2 entry : inputConnectors) { result.add(entry.item2); } @@ -385,7 +390,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen List arguments = new LinkedList<>(); int index = -1; - for (Tuple2 entry : inputConnectors) { + for (Tuple2 entry : inputConnectors) { index++; if (entry.item1.get_type() == ConnectorTypeInfo.Type.PULSE) { continue; @@ -480,7 +485,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen private int getConnectorIndex(InputConnector inputConnector) { int index = 0; - for (Tuple2 entry : inputConnectors) { + for (Tuple2 entry : inputConnectors) { if (entry.item2 == inputConnector) { return index; } @@ -501,7 +506,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen } public ConnectorTypeInfo getConnectorInfo(InputConnector inputConnector) { - for (Tuple2 entry : inputConnectors) { + for (Tuple2 entry : inputConnectors) { if (entry.item2 == inputConnector) { return entry.item1; } @@ -579,8 +584,6 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen @Override public void draw(ScrolledCanvas canvas, boolean devMode) { - updateWidthHeight(); // TODO: Remove after the calculations have stabilized - if (!devMode) { return; // Logic block, don't show on user-mode } @@ -611,7 +614,7 @@ public class ProgramakerCustomBlockPart implements Part, ProgramakerSignalListen private void drawConnectors(ScrolledCanvas canvas) { if (inputConnectors != null) { - for (Tuple2 entry : inputConnectors) { + for (Tuple2 entry : inputConnectors) { Paint outerInputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); outerInputConnectorPaint.setColor(entry.item1.getOuterColor()); diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundOutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundOutputConnector.java index e2b9431..3015c7b 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundOutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundOutputConnector.java @@ -4,7 +4,6 @@ import android.util.Log; import com.codigoparallevar.minicards.ScrolledCanvas; import com.codigoparallevar.minicards.types.Drawable; -import com.codigoparallevar.minicards.types.Moveable; import com.codigoparallevar.minicards.types.Part; import com.codigoparallevar.minicards.types.PartGrid; import com.codigoparallevar.minicards.types.connectors.Wiring.AnyWire; @@ -34,7 +33,7 @@ public class AnyRoundOutputConnector implements Drawable, AnyOutputConnector, _partGrid = partGrid; _centerX = centerX; _centerY = centerY; - _radius = radius; + _radius = radius; _wires = new LinkedList<>(); _connections = new HashSet<>(); } @@ -47,7 +46,7 @@ public class AnyRoundOutputConnector implements Drawable, AnyOutputConnector, @Override - public Moveable getMoveable() { + public AnyWire getMoveable() { if (_currentWire == null) { startWire(); } @@ -56,46 +55,61 @@ public class AnyRoundOutputConnector implements Drawable, AnyOutputConnector, } @Override - public void unlink() {} + public void unlink() { + while (_wires.size() > 0) { + _wires.get(0).unlink(); + } + } private void startWire() { _currentWire = new AnyWire(this, _centerX, _centerY); } - @Override - public void drop(AnyWire wire) { - - if (wire == _currentWire){ - _currentWire = null; - - AnyInputConnector resultPoint = _partGrid.getAnyInputConnectorOn( - wire.getXEnd(), wire.getYEnd()); - - Log.d("RoundOutputConnector", "Dropped wire on " + resultPoint); - - // Not connected - if (resultPoint == null){ - return; - } - - // Already connected - if (_connections.contains(resultPoint)) { - return; - } - _connections.add(resultPoint); - - wire.attachTo(resultPoint, this); - _wires.add(wire); - } - else { + public void drop(AnyWire wire, AnyInputConnector resultPoint) { + if (wire != _currentWire) { Log.w("RoundOutputConnector", "Asked to drop non matching wire " + "(expected " + _currentWire + ", got " + wire + ")"); + return ; } + + _currentWire = null; + + Log.d("RoundOutputConnector", "Dropped wire on " + resultPoint); + + // Not connected + if (resultPoint == null) { + return; + } + + // Already connected + if (_connections.contains(resultPoint)) { + return; + } + _connections.add(resultPoint); + + wire.attachTo(resultPoint, this); + _wires.add(wire); } @Override - public void unlinkWire(AnyWire wire) { + public void drop(AnyWire wire) { + + if (wire != _currentWire) { + Log.w("RoundOutputConnector", + "Asked to drop non matching wire " + + "(expected " + _currentWire + ", got " + wire + ")"); + return; + } + + AnyInputConnector resultPoint = _partGrid.getAnyInputConnectorOn( + wire.getXEnd(), wire.getYEnd()); + + drop(wire, resultPoint); + } + + @Override + public void wireUnlinked(AnyWire wire) { _wires.remove(wire); _connections.remove(wire.getAttachedTo()); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundInputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundInputConnector.java index b1d2056..d23a79c 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundInputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundInputConnector.java @@ -72,7 +72,7 @@ public class BooleanRoundInputConnector implements BooleanInputConnector { @Override - public void getAttachment(Wire wire) { + public void addAttachment(Wire wire) { _attachments.add(wire); } @@ -92,7 +92,7 @@ public class BooleanRoundInputConnector implements BooleanInputConnector { } @Override - public void unlinkWire(Wire wire) { + public void wireUnlinked(Wire wire) { _attachments.remove(wire); } } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundOutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundOutputConnector.java index 3d96b7e..a9b1fb4 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundOutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/BooleanRoundOutputConnector.java @@ -94,7 +94,7 @@ public class BooleanRoundOutputConnector implements Drawable, BooleanOutputConne } @Override - public void unlinkWire(BooleanWire wire) { + public void wireUnlinked(BooleanWire wire) { _wires.remove(wire); _connections.remove(wire.getAttachedTo()); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ConnectorTypeInfo.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ConnectorTypeInfo.java index edee041..9ba9bb7 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ConnectorTypeInfo.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ConnectorTypeInfo.java @@ -2,8 +2,12 @@ package com.codigoparallevar.minicards.parts.connectors; import com.codigoparallevar.minicards.parts.style.CardTheme; +import org.json.JSONException; +import org.json.JSONObject; + public class ConnectorTypeInfo { private final Type _type; + private static final String SERIALIZED_TYPE_KEY = "type"; public static ConnectorTypeInfo FromTypeName(String type) { if (type == null) { @@ -37,6 +41,34 @@ public class ConnectorTypeInfo { } } + + private static String typeToString(Type type) { + switch (type) { + case ANY: + return "any"; + case ENUM: + return "enum"; + case FLOAT: + return "float"; + case PULSE: + return "pulse"; + case STRING: + return "string"; + case BOOLEAN: + return "boolean"; + case INTEGER: + return "integer"; + case UNKNOWN: + return "unknown"; + default: + return "unknown"; + } + } + + public static ConnectorTypeInfo deserialize(JSONObject jsonTypeInfo) { + return ConnectorTypeInfo.FromTypeName(jsonTypeInfo.optString(SERIALIZED_TYPE_KEY)); + } + public int getOuterColor() { switch (_type) { case ANY: @@ -84,6 +116,16 @@ public class ConnectorTypeInfo { } } + public JSONObject serialize() { + JSONObject obj = new JSONObject(); + try { + obj.put(SERIALIZED_TYPE_KEY, ConnectorTypeInfo.typeToString(this._type)); + } catch (JSONException e) { + e.printStackTrace(); + } + return obj; + } + public enum Type { PULSE, BOOLEAN, diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundInputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ProgramakerCustomBlockInputConnector.java similarity index 61% rename from app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundInputConnector.java rename to app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ProgramakerCustomBlockInputConnector.java index 17e5142..987c5c3 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/AnyRoundInputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/ProgramakerCustomBlockInputConnector.java @@ -2,9 +2,13 @@ package com.codigoparallevar.minicards.parts.connectors; import android.util.Log; +import com.codigoparallevar.minicards.CanvasView; +import com.codigoparallevar.minicards.parts.values.StaticValuePart; import com.codigoparallevar.minicards.types.Moveable; import com.codigoparallevar.minicards.types.Part; +import com.codigoparallevar.minicards.types.PartGrid; import com.codigoparallevar.minicards.types.connectors.RoundConnector; +import com.codigoparallevar.minicards.types.connectors.Wiring.AnyWire; import com.codigoparallevar.minicards.types.connectors.Wiring.Wire; import com.codigoparallevar.minicards.types.connectors.input.AnyInputConnector; import com.codigoparallevar.minicards.types.wireData.AnySignal; @@ -12,20 +16,25 @@ import com.codigoparallevar.minicards.types.wireData.AnySignal; import java.util.LinkedList; import java.util.List; -public class AnyRoundInputConnector extends AnyInputConnector implements RoundConnector { +public class ProgramakerCustomBlockInputConnector extends AnyInputConnector implements RoundConnector { + private static final int STATIC_VALUE_SEPARATION = 200; private final Part _part; + private final ConnectorTypeInfo _typeInfo; + private final PartGrid _partGrid; private int _xposition; private int _yposition; private final int _radius; private final List _attachments = new LinkedList<>(); - public AnyRoundInputConnector(Part part, - int inputConnectorCenterX, int inputConnectorCenterY, - int inputConnectorRadius) { + public ProgramakerCustomBlockInputConnector(Part part, PartGrid partGrid, + int inputConnectorCenterX, int inputConnectorCenterY, + int inputConnectorRadius, ConnectorTypeInfo typeInfo) { _part = part; + _partGrid = partGrid; _xposition = inputConnectorCenterX; _yposition = inputConnectorCenterY; _radius = inputConnectorRadius; + _typeInfo = typeInfo; } @Override @@ -86,9 +95,8 @@ public class AnyRoundInputConnector extends AnyInputConnector implements RoundCo _part.send(this, signal); } - @Override - public void getAttachment(Wire wire) { + public void addAttachment(Wire wire) { _attachments.add(wire); } @@ -108,7 +116,25 @@ public class AnyRoundInputConnector extends AnyInputConnector implements RoundCo } @Override - public void unlinkWire(Wire wire) { + public void wireUnlinked(Wire wire) { _attachments.remove(wire); } + + public void touched() { + // If it doesn't have wires connected, spawn a value block + if (this._attachments.size() > 0) { + return; + } + + final PartGrid grid = _partGrid; + + if (grid instanceof CanvasView) { + StaticValuePart value = new StaticValuePart(_partGrid, + this._xposition, this._yposition - STATIC_VALUE_SEPARATION, + this._typeInfo); + AnyWire wire = value.getOutputWire(); + value.getValueOutput().drop(wire, this); + ((CanvasView) grid).addPart(value); + } + } } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/RoundInputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/RoundInputConnector.java index 55f55e0..a2968d0 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/RoundInputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/RoundInputConnector.java @@ -75,7 +75,7 @@ public class RoundInputConnector implements SignalInputConnector { } @Override - public void getAttachment(Wire wire) { + public void addAttachment(Wire wire) { _attachments.add(wire); } @@ -95,7 +95,7 @@ public class RoundInputConnector implements SignalInputConnector { } @Override - public void unlinkWire(Wire wire) { + public void wireUnlinked(Wire wire) { _attachments.remove(wire); } } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/SignalRoundOutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/SignalRoundOutputConnector.java index 1d3101f..37d32ba 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/SignalRoundOutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/SignalRoundOutputConnector.java @@ -97,7 +97,7 @@ public class SignalRoundOutputConnector implements Drawable, SignalOutputConnect } @Override - public void unlinkWire(SignalWire wire) { + public void wireUnlinked(SignalWire wire) { _wires.remove(wire); _connections.remove(wire.getAttachedTo()); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundInputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundInputConnector.java index b22426f..f5a4107 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundInputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundInputConnector.java @@ -72,7 +72,7 @@ public class StringRoundInputConnector implements StringInputConnector { @Override - public void getAttachment(Wire wire) { + public void addAttachment(Wire wire) { _attachments.add(wire); } @@ -92,7 +92,7 @@ public class StringRoundInputConnector implements StringInputConnector { } @Override - public void unlinkWire(Wire wire) { + public void wireUnlinked(Wire wire) { _attachments.remove(wire); } } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundOutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundOutputConnector.java index 264f4cd..57c3742 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundOutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/connectors/StringRoundOutputConnector.java @@ -7,11 +7,12 @@ import com.codigoparallevar.minicards.types.Drawable; import com.codigoparallevar.minicards.types.Moveable; import com.codigoparallevar.minicards.types.Part; import com.codigoparallevar.minicards.types.PartGrid; -import com.codigoparallevar.minicards.types.functional.Tuple2; import com.codigoparallevar.minicards.types.connectors.Wiring.StringWire; +import com.codigoparallevar.minicards.types.connectors.Wiring.Wire; import com.codigoparallevar.minicards.types.connectors.input.InputConnector; import com.codigoparallevar.minicards.types.connectors.input.StringInputConnector; import com.codigoparallevar.minicards.types.connectors.output.StringOutputConnector; +import com.codigoparallevar.minicards.types.functional.Tuple2; import com.codigoparallevar.minicards.types.wireData.StringSignal; import java.util.HashSet; @@ -94,7 +95,7 @@ public class StringRoundOutputConnector implements Drawable, StringOutputConnect } @Override - public void unlinkWire(StringWire wire) { + public void wireUnlinked(StringWire wire) { _wires.remove(wire); _connections.remove(wire.getAttachedTo()); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/strings/ConvertToString.java b/app/src/main/java/com/codigoparallevar/minicards/parts/strings/ConvertToString.java index 7ac2087..bf4a3aa 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/strings/ConvertToString.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/strings/ConvertToString.java @@ -7,7 +7,8 @@ import android.util.Log; import com.codigoparallevar.minicards.PartInstantiator; import com.codigoparallevar.minicards.ScrolledCanvas; -import com.codigoparallevar.minicards.parts.connectors.AnyRoundInputConnector; +import com.codigoparallevar.minicards.parts.connectors.ConnectorTypeInfo; +import com.codigoparallevar.minicards.parts.connectors.ProgramakerCustomBlockInputConnector; import com.codigoparallevar.minicards.parts.connectors.StringRoundOutputConnector; import com.codigoparallevar.minicards.parts.style.CardTheme; import com.codigoparallevar.minicards.types.Moveable; @@ -56,11 +57,12 @@ public class ConvertToString implements Part { _lastValue = null; // Input connector - _toggleInputConnector = new AnyRoundInputConnector( - this, + ConnectorTypeInfo typeInfo = new ConnectorTypeInfo(ConnectorTypeInfo.Type.ANY); + _toggleInputConnector = new ProgramakerCustomBlockInputConnector( + this, _partGrid, getInputConnectorCenterX(), getInputConnectorCenterY(), - getInputConnectRadius()); + getInputConnectRadius(), typeInfo); inputConnectors = new LinkedList<>(); inputConnectors.add(_toggleInputConnector); diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/values/StaticValuePart.java b/app/src/main/java/com/codigoparallevar/minicards/parts/values/StaticValuePart.java new file mode 100644 index 0000000..a91bdcd --- /dev/null +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/values/StaticValuePart.java @@ -0,0 +1,406 @@ +package com.codigoparallevar.minicards.parts.values; + +import android.app.AlertDialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.InputType; +import android.util.Log; +import android.view.View; +import android.widget.EditText; + +import com.codigoparallevar.minicards.R; +import com.codigoparallevar.minicards.ScrolledCanvas; +import com.codigoparallevar.minicards.parts.connectors.AnyRoundOutputConnector; +import com.codigoparallevar.minicards.parts.connectors.ConnectorTypeInfo; +import com.codigoparallevar.minicards.types.Moveable; +import com.codigoparallevar.minicards.types.Part; +import com.codigoparallevar.minicards.types.PartConnection; +import com.codigoparallevar.minicards.types.PartGrid; +import com.codigoparallevar.minicards.types.connectors.Wiring.AnyWire; +import com.codigoparallevar.minicards.types.connectors.input.InputConnector; +import com.codigoparallevar.minicards.types.connectors.output.OutputConnector; +import com.codigoparallevar.minicards.types.functional.Tuple2; +import com.codigoparallevar.minicards.types.wireData.WireDataType; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +public class StaticValuePart implements Part { + private static final int WIDTH_PADDING = 25; + private static final int HEIGHT_PADDING = 25; + private static final int MIN_HEIGHT = 100; + private static final int MIN_WIDTH = 100; + private static final String LogTag = "PM StaticValue"; + private static final int IO_RADIUS = 50; + private static final int IO_PADDING = 20; + + private final String _id; + private final AnyRoundOutputConnector _outputConnector; + private final ConnectorTypeInfo _typeInfo; + private final PartGrid _grid; + private int _width; + private int _height; + private int _left; + private int _top; + private String _value = null; + + public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo, String value) { + this._id = id; + this._typeInfo = typeInfo; + this._grid = grid; + this._value = value; + + this.updateWidthHeight(); + + this._left = centerx - this._width / 2; + this._top = centery - this._height / 2; + this._outputConnector = new AnyRoundOutputConnector(this, grid, + this._left + _width / 2, + this._top + _height, IO_RADIUS); + } + + public StaticValuePart(String id, PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo) { + this(id, grid, centerx, centery, typeInfo, null); + } + + public StaticValuePart(PartGrid grid, int centerx, int centery, ConnectorTypeInfo typeInfo) { + this(UUID.randomUUID().toString(), grid, centerx, centery, typeInfo); + } + + @Override + public JSONObject serialize() throws JSONException { + JSONObject serialized = new JSONObject(); + + serialized.put("id", _id); + serialized.put("left", _left); + serialized.put("top", _top); + serialized.put("value", _value == null ? JSONObject.NULL : _value); + + JSONObject jsonTypeInfo = _typeInfo.serialize(); + serialized.put("type_info", jsonTypeInfo); + + serialized.put("on_string_output_connector", serializeConnectionEndpoints()); + + return serialized; + } + + private JSONArray serializeConnectionEndpoints() { + JSONArray serializedData = new JSONArray(); + + for (OutputConnector output : getOutputConnectors()) { + JSONArray elements = new JSONArray(); + + for (Tuple2 endpoint : (List>) output.getConnectionEndpoints()) { + elements.put(PartConnection.serializeToJson(endpoint.item1, endpoint.item2)); + } + + serializedData.put(elements); + } + return serializedData; + } + + public static Tuple2> deserialize(PartGrid grid, JSONObject data) throws JSONException { + String id = data.getString("id"); + int left = data.getInt("left"); + int top = data.getInt("top"); + String value = data.optString("value"); + + JSONObject jsonTypeInfo = data.getJSONObject("type_info"); + ConnectorTypeInfo typeInfo = ConnectorTypeInfo.deserialize(jsonTypeInfo); + StaticValuePart part = new StaticValuePart(id, grid, left, top, typeInfo, value); + + List connections = new LinkedList<>(); + + JSONArray allConnectorOuts = data.optJSONArray("on_string_output_connector"); + if (allConnectorOuts == null) { + allConnectorOuts = new JSONArray(); + } + + for (int i = 0; i < allConnectorOuts.length(); i++) { + JSONArray connectorOuts = allConnectorOuts.getJSONArray(i); + OutputConnector connector = part.getOutputConnectors().get(i); + + for (int j = 0; j < connectorOuts.length(); j++) { + connections.add(PartConnection.deserialize( + connector, connectorOuts.getJSONObject(j))); + } + } + + return new Tuple2<>(part, connections); + } + + public AnyWire getOutputWire() { + return this._outputConnector.getMoveable(); + } + + @Override + public int get_left() { + return _left; + } + + @Override + public int get_right() { + return _left + _width; + } + + @Override + public int get_top() { + return _top; + } + + @Override + public int get_bottom() { + return _top + _height; + } + + private void updateWidthHeight() { + Paint p = getTextPaint(); + String message = getMessage(); + Rect bounds = new Rect(); + p.getTextBounds(message, 0, message.length(), bounds); + + this._height = Math.max(MIN_HEIGHT, bounds.height() + HEIGHT_PADDING * 2); + int newWidth = Math.max(MIN_WIDTH, bounds.width() + WIDTH_PADDING * 2); + + if (this._width > 0) { // Re-center block + this._left -= (newWidth - _width) / 2; + } + this._width = newWidth; + } + + private String getMessage() { + ConnectorTypeInfo.Type type = _typeInfo.get_type(); + if (type == ConnectorTypeInfo.Type.INTEGER || type == ConnectorTypeInfo.Type.FLOAT) { + if (_value == null) { + return "0"; + } + try { + Integer.parseInt(_value); + return _value; + } catch(NumberFormatException ex) { + Log.w(LogTag, "StaticPart (type=number), value found=" + _value, ex); + return "0"; + } + } + else { + if (_value == null) { + return "-"; + } else { + return _value; + } + } + } + + private Paint getTextPaint() { + Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); + p.setColor(Color.BLACK); + p.setTextSize(50); + return p; + } + + @Override + public void touched() { + if (!(this._grid instanceof View)) { + return; // Can't show dialog if can't retrieve context + } + + ConnectorTypeInfo.Type type = this._typeInfo.get_type(); + if (type == ConnectorTypeInfo.Type.PULSE) { + return; // Nothing to do here + } + + Context ctx = ((View) this._grid).getContext(); + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + + builder.setTitle(R.string.set_value); + Runnable prepareOnAccept = () -> {}; + switch (type) { + case BOOLEAN: + break; + case INTEGER: + case FLOAT: + { + final EditText input = new EditText(ctx); + + input.setText(getMessage()); + input.setInputType(InputType.TYPE_CLASS_NUMBER); + builder.setView(input); + prepareOnAccept = () -> { + _value = input.getText().toString(); + }; + break; + } + default: + case ENUM: + // TODO: Show enumerated values + case ANY: + case UNKNOWN: + case STRING: + { + final EditText input = new EditText(ctx); + + input.setText(getMessage()); + input.setInputType(InputType.TYPE_CLASS_TEXT); + builder.setView(input); + prepareOnAccept = () -> { + _value = input.getText().toString(); + }; + break; + } + } + + final Runnable onAccept = prepareOnAccept; + builder + .setPositiveButton(R.string.ok_accept_changes, (dialog, which) -> { + onAccept.run(); + this.updateWidthHeight(); + ((View) this._grid).invalidate(); + }) + .setNegativeButton(R.string.cancel_discard_changes, (dialog, which) -> { + // No change + } ); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + + @Override + public List getInputConnectors() { + // There is not going to be one + return Collections.emptyList(); + } + + @Override + public List getOutputConnectors() { + return new LinkedList() {{ + add(_outputConnector); + }}; + } + + public AnyRoundOutputConnector getValueOutput() { + return _outputConnector; + } + + @Override + public void send(InputConnector inputConnector, WireDataType signal) { + + } + + @Override + public String get_id() { + return _id; + } + + @Override + public InputConnector getConnectorWithId(String inputConnectorId) { + return null; // No inputs + } + + @Override + public String getConnectorId(InputConnector inputConnector) { + return null; // No inputs + } + + @Override + public void resume() { + // Nothing to do + } + + @Override + public void pause() { + // Nothing to do + } + + @Override + public Object query(Object lastValue) { + return this._value; + } + + @Override + public void draw(ScrolledCanvas canvas, boolean devMode) { + this.updateWidthHeight(); // TODO: Remove after calculations stabilize + + if (!devMode) { + return; // Logic block, don't show on user-mode + } + + drawConnectors(canvas); + drawWires(canvas, devMode); + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Color.parseColor("#E3FCFC")); + canvas.drawRect( + new Rect(get_left(), get_top(), + get_right(), get_bottom()), + paint); + + Paint textPaint = getTextPaint(); + canvas.drawText(getMessage(), + get_left() + WIDTH_PADDING, + get_bottom() - HEIGHT_PADDING, + textPaint); + } + + private void drawConnectors(ScrolledCanvas canvas) { + Paint outerOutputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + outerOutputConnectorPaint.setColor(_typeInfo.getOuterColor()); + + canvas.drawCircle( + _outputConnector.getX(), + _outputConnector.getY(), + _outputConnector.getRadius(), + outerOutputConnectorPaint); + + Paint innerOutputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + innerOutputConnectorPaint.setColor(_typeInfo.getInnerColor()); + + canvas.drawCircle( + _outputConnector.getX(), + _outputConnector.getY(), + _outputConnector.getRadius() / 2, + innerOutputConnectorPaint); + } + + private void drawWires(ScrolledCanvas canvas, boolean devMode) { + _outputConnector.drawWires(canvas, devMode); + } + + @Override + public void moveEnd(int x, int y) { + _left = x - _width / 2; + _top = y - _height / 2; + this._outputConnector.updatePosition( + this._left + _width / 2, + this._top + _height); + } + + @Override + public void drop(int x, int y) { + moveEnd(x, y); + } + + @Override + public boolean containsPoint(int x, int y) { + return ((x >= this.get_left()) && (x <= this.get_right()) + && (y >= this.get_top()) && (y <= this.get_bottom())); + } + + @Override + public Moveable getMoveable() { + return this; + } + + @Override + public void unlink() { + // Nothing to do + _outputConnector.unlink(); + } +} diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/Dropper.java b/app/src/main/java/com/codigoparallevar/minicards/types/Dropper.java index 7aea9ee..78cec50 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/Dropper.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/Dropper.java @@ -4,5 +4,5 @@ import com.codigoparallevar.minicards.types.connectors.Wiring.Wire; public interface Dropper { void drop(T wire); - void unlinkWire(T wire); + void wireUnlinked(T wire); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/Part.java b/app/src/main/java/com/codigoparallevar/minicards/types/Part.java index c9a85ab..dc1bf25 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/Part.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/Part.java @@ -4,6 +4,7 @@ import com.codigoparallevar.minicards.types.connectors.input.InputConnector; import com.codigoparallevar.minicards.types.connectors.output.OutputConnector; import com.codigoparallevar.minicards.types.wireData.WireDataType; +import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONObject; @@ -20,6 +21,7 @@ public interface Part extends Selectable, Moveable, Drawable { List getInputConnectors(); List getOutputConnectors(); + @NotNull JSONObject serialize() throws JSONException; void send(InputConnector inputConnector, WireDataType signal); diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/connectors/Wiring/Wire.java b/app/src/main/java/com/codigoparallevar/minicards/types/connectors/Wiring/Wire.java index cefae9f..f58c8f3 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/connectors/Wiring/Wire.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/connectors/Wiring/Wire.java @@ -83,7 +83,7 @@ public class Wire wire); + void addAttachment(Wire wire); Part getPart(); String getId(); void send(T data); + + void wireUnlinked(Wire wire); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/connectors/input/SignalInputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/types/connectors/input/SignalInputConnector.java index 39b1378..bcd4c05 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/connectors/input/SignalInputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/connectors/input/SignalInputConnector.java @@ -1,5 +1,6 @@ package com.codigoparallevar.minicards.types.connectors.input; +import com.codigoparallevar.minicards.types.connectors.Wiring.SignalWire; import com.codigoparallevar.minicards.types.wireData.Signal; public interface SignalInputConnector extends InputConnector { diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/connectors/output/OutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/types/connectors/output/OutputConnector.java index c5811d5..344c357 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/connectors/output/OutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/connectors/output/OutputConnector.java @@ -27,4 +27,6 @@ public interface OutputConnector getWires(); + + void wireUnlinked(T2 wire); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3ef5b93..673cb65 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,4 +26,7 @@ Stop bridge Start bridge Vibration activated + Set block value + OK + Cancel