diff --git a/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java b/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java index ab0e011..487c343 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java +++ b/app/src/main/java/com/codigoparallevar/minicards/CanvasView.java @@ -12,6 +12,7 @@ import android.view.MotionEvent; import android.view.View; import com.codigoparallevar.minicards.motion.MotionMode; +import com.codigoparallevar.minicards.types.PartConnection; import com.codigoparallevar.minicards.parts.buttons.RoundButton; import com.codigoparallevar.minicards.parts.samples.ColorBox; import com.codigoparallevar.minicards.parts.samples.Placeholder; @@ -21,6 +22,7 @@ import com.codigoparallevar.minicards.types.Part; import com.codigoparallevar.minicards.types.PartGrid; import com.codigoparallevar.minicards.types.Position; import com.codigoparallevar.minicards.types.Selectable; +import com.codigoparallevar.minicards.types.Tuple2; import com.codigoparallevar.minicards.types.Tuple4; import org.json.JSONArray; @@ -32,6 +34,11 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; class CanvasView extends View implements PartGrid { @@ -82,49 +89,95 @@ class CanvasView extends View implements PartGrid { File filesDir = getContext().getFilesDir(); File file = new File(filesDir + "/" + name); FileReader fileIn = null; + List connections = new LinkedList<>(); + try { fileIn = new FileReader(file); char[] data = new char[(int) file.length()]; fileIn.read(data); JSONArray jsonParts = new JSONArray(new String(data )); for (int i = 0; i < jsonParts.length(); i++){ - deserializeObject(jsonParts.getJSONObject(i)); + connections.addAll(deserializeObject(jsonParts.getJSONObject(i))); } } catch (IOException e) { parts.clear(); - Log.w("PartCanvasView", e.getMessage()); + Log.w("CanvasView", e.getMessage(), e); return false; } catch (JSONException e) { parts.clear(); - Log.w("PartCanvasView", e.getMessage()); + Log.w("CanvasView", e.getMessage(), e); return false; } + resolveConnections(connections); + try { fileIn.close(); } catch (IOException e) { Log.w("PartCanvasView", e.getMessage()); return false; } + return true; } - private void deserializeObject(JSONObject jsonObject) throws JSONException { + private List deserializeObject(JSONObject jsonObject) throws JSONException { String type = jsonObject.getString("_type"); + if(type.equals(RoundButton.class.getName())) { - parts.add(RoundButton.deserialize(this, jsonObject.getJSONObject("_data"))); + Tuple2> buttonInfo = RoundButton.deserialize( + this, + jsonObject.getJSONObject("_data")); + + parts.add(buttonInfo.item1); + return buttonInfo.item2; } else if (type.equals(Placeholder.class.getName())) { parts.add(Placeholder.deserialize(this, jsonObject.getJSONObject("_data"))); + return Collections.emptyList(); } else if (type.equals(ColorBox.class.getName())){ parts.add(ColorBox.deserialize(this, jsonObject.getJSONObject("_data"))); + return Collections.emptyList(); } else { throw new JSONException("Expected known class, found " + type); } } + private void resolveConnections(List connections) { + Map partsById = buildPartsById(); + for (PartConnection connection : connections){ + if (!partsById.containsKey(connection.inputPartId)){ + Log.e("Canvas view", "Key '" + connection.inputPartId + + "' not found on deserialization"); + continue; + } + + Part inputPart = partsById.get(connection.inputPartId); + InputConnector inputConnector = inputPart.getConnectorWithId(connection.inputConnectorId); + + if (inputConnector == null){ + Log.e("Canvas view", "Connector ID '" + connection.inputConnectorId + + "' not found on deserialization"); + continue; + } + + OutputConnector outputConnector = connection.outputConnector; + outputConnector.connectTo(inputConnector); + } + } + + private Map buildPartsById() { + Map partsById = new HashMap<>(parts.size()); + for (Part part : parts) { + partsById.put(part.getId(), part); + Log.w("CanvasView", "Added part ID: " + part.getId() + " - " + part); + } + + return partsById; + } + @Override public void onDraw(Canvas canvas){ final long renderStartTime = System.currentTimeMillis(); diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/buttons/RoundButton.java b/app/src/main/java/com/codigoparallevar/minicards/parts/buttons/RoundButton.java index d5f3807..0c8e957 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/buttons/RoundButton.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/buttons/RoundButton.java @@ -5,6 +5,8 @@ import android.graphics.Color; import android.graphics.Paint; import android.util.Log; +import com.codigoparallevar.minicards.types.PartConnection; +import com.codigoparallevar.minicards.types.Tuple2; import com.codigoparallevar.minicards.types.InputConnector; import com.codigoparallevar.minicards.types.Moveable; import com.codigoparallevar.minicards.types.OutputConnector; @@ -12,16 +14,20 @@ import com.codigoparallevar.minicards.types.Part; import com.codigoparallevar.minicards.types.PartGrid; import com.codigoparallevar.minicards.types.RoundInputConnector; import com.codigoparallevar.minicards.types.RoundOutputConnector; +import com.codigoparallevar.minicards.utils.Serializations; +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.Map; +import java.util.UUID; public class RoundButton implements Part { - + private final String _id; private final PartGrid _partGrid; private int _xCenter; private int _yCenter; @@ -32,7 +38,10 @@ public class RoundButton implements Part { private List _outputConnectors; private final RoundOutputConnector _pressedOuputConnector; - public RoundButton(PartGrid partGrid, int xCenter, int yCenter, int innerRadius, int outerRadius) { + + private RoundButton(String id, PartGrid partGrid, int xCenter, int yCenter, int innerRadius, int outerRadius) { + _id = id; + _partGrid = partGrid; _xCenter = xCenter; _yCenter = yCenter; @@ -48,7 +57,10 @@ public class RoundButton implements Part { _outputConnectors = new LinkedList<>(); _outputConnectors.add(_pressedOuputConnector); + } + public RoundButton(PartGrid partGrid, int xCenter, int yCenter, int innerRadius, int outerRadius) { + this(UUID.randomUUID().toString(), partGrid, xCenter, yCenter, innerRadius, outerRadius); } @Override @@ -153,28 +165,68 @@ public class RoundButton implements Part { public JSONObject serialize() throws JSONException { JSONObject serialized = new JSONObject(); + serialized.put("id", _id); serialized.put("x_center", _xCenter); serialized.put("y_center", _yCenter); serialized.put("inner_radius", _innerRadius); serialized.put("outer_radius", _outerRadius); serialized.put("outer_radius_thickness", _outerRadiusThickness); + serialized.put("on_pressed_output_connector", + Serializations.serialize(serializeConnectionEndpoints())); return serialized; } + private List> serializeConnectionEndpoints() { + List> serializedData = new LinkedList<>(); + + for (Tuple2 endpoint : _pressedOuputConnector.getConnectionEndpoints()){ + serializedData.add(PartConnection.serialize(endpoint.item1, endpoint.item2)); + } + + return serializedData; + } + @Override public void sendSignal(RoundInputConnector roundInputConnector) { // @TODO: REMOVE THE NEED FOR THIS } - public static Part deserialize(PartGrid partGrid, JSONObject data) throws JSONException { + @Override + public String getId() { + return _id; + } + + @Override + public InputConnector getConnectorWithId(String inputConnectorId) { + return null; + } + + @Override + public String getConnectorId(InputConnector inputConnector) { + return null; + } + + public static Tuple2> deserialize(PartGrid partGrid, JSONObject data) throws JSONException { + String id = data.getString("id"); int xCenter = data.getInt("x_center"); int yCenter = data.getInt("y_center"); int innerRadius = data.getInt("inner_radius"); int outerRadius = data.getInt("outer_radius"); - return new RoundButton(partGrid, xCenter, yCenter, innerRadius, outerRadius); + RoundButton button = new RoundButton(id, partGrid, xCenter, yCenter, innerRadius, outerRadius); + + List connections = new LinkedList<>(); + + JSONArray connectorOuts = data.getJSONArray("on_pressed_output_connector"); + for (int i = 0; i < connectorOuts.length(); i++){ + connections.add(PartConnection.deserialize( + button._pressedOuputConnector, + connectorOuts.getJSONObject(i))); + } + + return new Tuple2>(button, connections); } @Override diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/samples/ColorBox.java b/app/src/main/java/com/codigoparallevar/minicards/parts/samples/ColorBox.java index bb28e57..b294ca5 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/samples/ColorBox.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/samples/ColorBox.java @@ -19,8 +19,11 @@ import org.json.JSONObject; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.UUID; public class ColorBox implements Part { + private static final String TOGGLE_INPUT_CONNECTOR_ID = "toggle_input_connector"; + private final String _id; private final PartGrid _partGrid; private boolean _activated; private int _left; @@ -30,7 +33,8 @@ public class ColorBox implements Part { private List inputConnectors; private InputConnector _toggleInputConnector; - public ColorBox(PartGrid partGrid, int left, int top, int right, int bottom) { + private ColorBox(String id, PartGrid partGrid, int left, int top, int right, int bottom) { + _id = id; _partGrid = partGrid; _left = left; _top = top; @@ -45,6 +49,11 @@ public class ColorBox implements Part { getInputConnectRadius()); inputConnectors = new LinkedList<>(); inputConnectors.add(_toggleInputConnector); + + } + + public ColorBox(PartGrid partGrid, int left, int top, int right, int bottom) { + this(UUID.randomUUID().toString(), partGrid, left, top, right, bottom); } @Override @@ -139,6 +148,7 @@ public class ColorBox implements Part { public JSONObject serialize() throws JSONException { JSONObject serialized = new JSONObject(); + serialized.put("id", _id); serialized.put("left", _left); serialized.put("top", _top); serialized.put("right", _right); @@ -152,13 +162,39 @@ public class ColorBox implements Part { _activated = !_activated; } + @Override + public String getId() { + return _id; + } + + @Override + public InputConnector getConnectorWithId(String inputConnectorId) { + switch (inputConnectorId){ + case ColorBox.TOGGLE_INPUT_CONNECTOR_ID: + return _toggleInputConnector; + + default: + return null; + } + } + + @Override + public String getConnectorId(InputConnector inputConnector) { + if (inputConnector == _toggleInputConnector){ + return ColorBox.TOGGLE_INPUT_CONNECTOR_ID; + } + + return null; + } + public static Part deserialize(PartGrid partGrid, JSONObject data) throws JSONException { + String id = data.getString("id"); int left = data.getInt("left"); int top = data.getInt("top"); int right = data.getInt("right"); int bottom = data.getInt("bottom"); - return new ColorBox(partGrid, left, top, right, bottom); + return new ColorBox(id, partGrid, left, top, right, bottom); } @Override diff --git a/app/src/main/java/com/codigoparallevar/minicards/parts/samples/Placeholder.java b/app/src/main/java/com/codigoparallevar/minicards/parts/samples/Placeholder.java index 2631ffd..af6ebe1 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/parts/samples/Placeholder.java +++ b/app/src/main/java/com/codigoparallevar/minicards/parts/samples/Placeholder.java @@ -17,15 +17,18 @@ import org.json.JSONObject; import java.util.Collections; import java.util.List; +import java.util.UUID; public class Placeholder implements Part { + private final String _id; private final PartGrid _partGrid; private int _left; private int _top; private int _right; private int _bottom; - public Placeholder(PartGrid partGrid, int left, int top, int right, int bottom) { + public Placeholder(String id, PartGrid partGrid, int left, int top, int right, int bottom) { + _id = id; _partGrid = partGrid; _left = left; _top = top; @@ -33,6 +36,10 @@ public class Placeholder implements Part { _bottom = bottom; } + public Placeholder(PartGrid partGrid, int left, int top, int right, int bottom) { + this(UUID.randomUUID().toString(), partGrid, left, top, right, bottom); + } + @Override public int getLeft() { return _left; @@ -108,6 +115,7 @@ public class Placeholder implements Part { public JSONObject serialize() throws JSONException { JSONObject serialized = new JSONObject(); + serialized.put("id", _id); serialized.put("left", _left); serialized.put("top", _top); serialized.put("right", _right); @@ -121,13 +129,29 @@ public class Placeholder implements Part { // @TODO: REMOVE THE NEED FOR THIS } + @Override + public String getId() { + return _id; + } + + @Override + public InputConnector getConnectorWithId(String inputConnectorId) { + return null; + } + + @Override + public String getConnectorId(InputConnector inputConnector) { + return null; + } + public static Part deserialize(PartGrid partGrid, JSONObject data) throws JSONException { + String id = data.getString("id"); int left = data.getInt("left"); int top = data.getInt("top"); int right = data.getInt("right"); int bottom = data.getInt("bottom"); - return new Placeholder(partGrid, left, top, right, bottom); + return new Placeholder(id, partGrid, left, top, right, bottom); } @Override diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/InputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/types/InputConnector.java index 1d480ea..a8f84e3 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/InputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/InputConnector.java @@ -9,4 +9,8 @@ public interface InputConnector extends Selectable, Dropper { void sendSignal(); void getAttachment(Wire wire); + + Part getPart(); + + String getId(); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/OutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/types/OutputConnector.java index ddf321b..814bff5 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/OutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/OutputConnector.java @@ -2,7 +2,13 @@ package com.codigoparallevar.minicards.types; import android.graphics.Canvas; +import java.util.List; + public interface OutputConnector extends Selectable, Dropper { void drawWires(Canvas canvas, boolean devMode); void updatePosition(int x, int y); + + List> getConnectionEndpoints(); + + void connectTo(InputConnector inputConnector); } 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 fd6c542..05326e7 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/Part.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/Part.java @@ -21,4 +21,10 @@ public interface Part extends Selectable, Moveable, Drawable { JSONObject serialize() throws JSONException; void sendSignal(RoundInputConnector roundInputConnector); + + String getId(); + + InputConnector getConnectorWithId(String inputConnectorId); + + String getConnectorId(InputConnector inputConnector); } diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/PartConnection.java b/app/src/main/java/com/codigoparallevar/minicards/types/PartConnection.java index a7af930..176662c 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/PartConnection.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/PartConnection.java @@ -1,14 +1,41 @@ -package com.codigoparallevar.minicards.parts; +package com.codigoparallevar.minicards.types; -import com.codigoparallevar.minicards.types.Part; +import com.codigoparallevar.minicards.parts.buttons.RoundButton; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.LinkedHashMap; +import java.util.Map; public class PartConnection { - public final Part outputPart; + private static final String INPUT_CONNECTOR_ID_KEY = "input_connector_id"; + private static final String INPUT_PART_ID_KEY = "input_part_id"; + public final OutputConnector outputConnector; public final String inputPartId; + public final String inputConnectorId; - public PartConnection(Part outputPart, String inputPartId) { - this.outputPart = outputPart; + public PartConnection(OutputConnector outputConnector, String inputPartId, + String inputConnectorId) { + this.outputConnector = outputConnector; this.inputPartId = inputPartId; + this.inputConnectorId = inputConnectorId; + } + + public static PartConnection deserialize(OutputConnector outputConnector, JSONObject metadata) throws JSONException { + String inputConnectorId = metadata.getString(PartConnection.INPUT_CONNECTOR_ID_KEY); + String inputPartId = metadata.getString(PartConnection.INPUT_PART_ID_KEY); + + return new PartConnection(outputConnector, inputPartId, inputConnectorId); + } + + public static Map serialize(final String inputConnectorId, final String inputPartId) { + + Map serialized = new LinkedHashMap<>(2); + serialized.put(PartConnection.INPUT_CONNECTOR_ID_KEY, inputConnectorId); + serialized.put(PartConnection.INPUT_PART_ID_KEY, inputPartId); + + return serialized; } } diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/RoundInputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/types/RoundInputConnector.java index aa8ce90..e34bc5b 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/RoundInputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/RoundInputConnector.java @@ -62,6 +62,16 @@ public class RoundInputConnector implements InputConnector { _attachments.add(wire); } + @Override + public Part getPart() { + return _part; + } + + @Override + public String getId() { + return _part.getConnectorId(this); + } + @Override public void drop(Wire wire) { Log.d("InputConnector", "Dropped wire " + wire); diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/RoundOutputConnector.java b/app/src/main/java/com/codigoparallevar/minicards/types/RoundOutputConnector.java index b2b3251..a5e7b66 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/RoundOutputConnector.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/RoundOutputConnector.java @@ -89,8 +89,28 @@ public class RoundOutputConnector implements OutputConnector, Drawable { } @Override - public void draw(Canvas canvas, boolean devMode) { + public List> getConnectionEndpoints() { + List> endpointIds = new LinkedList<>(); + for (Wire wire : _wires) { + InputConnector inputConnector = wire.getAttachedTo(); + Part endPart = inputConnector.getPart(); + endpointIds.add(new Tuple2<>(inputConnector.getId(), endPart.getId())); + } + + return endpointIds; + } + + @Override + public void connectTo(InputConnector inputConnector) { + Wire wire = new Wire(this, _centerX, _centerY); + wire.attachTo(inputConnector); + _wires.add(wire); + } + + @Override + public void draw(Canvas canvas, boolean devMode) { + // TODO: Complete this part } public void sendSignal() { diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/Tuple2.java b/app/src/main/java/com/codigoparallevar/minicards/types/Tuple2.java index baa4dad..081350a 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/Tuple2.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/Tuple2.java @@ -1,10 +1,10 @@ -package com.codigoparallevar.minicards.parts; +package com.codigoparallevar.minicards.types; -public class Tuple { +public class Tuple2 { public final T1 item1; public final T2 item2; - public Tuple(T1 item1, T2 item2) { + public Tuple2(T1 item1, T2 item2) { this.item1 = item1; this.item2 = item2; } diff --git a/app/src/main/java/com/codigoparallevar/minicards/types/Wire.java b/app/src/main/java/com/codigoparallevar/minicards/types/Wire.java index 8b3cbd5..552d9c8 100644 --- a/app/src/main/java/com/codigoparallevar/minicards/types/Wire.java +++ b/app/src/main/java/com/codigoparallevar/minicards/types/Wire.java @@ -79,4 +79,8 @@ public class Wire implements Moveable, Drawable { _attachedTo.sendSignal(); } } + + public InputConnector getAttachedTo() { + return _attachedTo; + } } diff --git a/app/src/main/java/com/codigoparallevar/minicards/utils/Serializations.java b/app/src/main/java/com/codigoparallevar/minicards/utils/Serializations.java new file mode 100644 index 0000000..1119a08 --- /dev/null +++ b/app/src/main/java/com/codigoparallevar/minicards/utils/Serializations.java @@ -0,0 +1,19 @@ +package com.codigoparallevar.minicards.utils; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.List; +import java.util.Map; + +public class Serializations { + + public static JSONArray serialize(List> data) { + JSONArray array = new JSONArray(); + for (Map dict : data) { + array.put(new JSONObject(dict)); + } + + return array; + } +}