Serialize and save connections.

This commit is contained in:
kenkeiras 2017-07-22 18:35:31 -04:00
parent b37e5e1ae1
commit 9157d2b7ad
13 changed files with 283 additions and 22 deletions

View File

@ -12,6 +12,7 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.codigoparallevar.minicards.motion.MotionMode; import com.codigoparallevar.minicards.motion.MotionMode;
import com.codigoparallevar.minicards.types.PartConnection;
import com.codigoparallevar.minicards.parts.buttons.RoundButton; import com.codigoparallevar.minicards.parts.buttons.RoundButton;
import com.codigoparallevar.minicards.parts.samples.ColorBox; import com.codigoparallevar.minicards.parts.samples.ColorBox;
import com.codigoparallevar.minicards.parts.samples.Placeholder; 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.PartGrid;
import com.codigoparallevar.minicards.types.Position; import com.codigoparallevar.minicards.types.Position;
import com.codigoparallevar.minicards.types.Selectable; import com.codigoparallevar.minicards.types.Selectable;
import com.codigoparallevar.minicards.types.Tuple2;
import com.codigoparallevar.minicards.types.Tuple4; import com.codigoparallevar.minicards.types.Tuple4;
import org.json.JSONArray; import org.json.JSONArray;
@ -32,6 +34,11 @@ import java.io.FileOutputStream;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; 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 { class CanvasView extends View implements PartGrid {
@ -82,49 +89,95 @@ class CanvasView extends View implements PartGrid {
File filesDir = getContext().getFilesDir(); File filesDir = getContext().getFilesDir();
File file = new File(filesDir + "/" + name); File file = new File(filesDir + "/" + name);
FileReader fileIn = null; FileReader fileIn = null;
List<PartConnection> connections = new LinkedList<>();
try { try {
fileIn = new FileReader(file); fileIn = new FileReader(file);
char[] data = new char[(int) file.length()]; char[] data = new char[(int) file.length()];
fileIn.read(data); fileIn.read(data);
JSONArray jsonParts = new JSONArray(new String(data )); JSONArray jsonParts = new JSONArray(new String(data ));
for (int i = 0; i < jsonParts.length(); i++){ for (int i = 0; i < jsonParts.length(); i++){
deserializeObject(jsonParts.getJSONObject(i)); connections.addAll(deserializeObject(jsonParts.getJSONObject(i)));
} }
} catch (IOException e) { } catch (IOException e) {
parts.clear(); parts.clear();
Log.w("PartCanvasView", e.getMessage()); Log.w("CanvasView", e.getMessage(), e);
return false; return false;
} catch (JSONException e) { } catch (JSONException e) {
parts.clear(); parts.clear();
Log.w("PartCanvasView", e.getMessage()); Log.w("CanvasView", e.getMessage(), e);
return false; return false;
} }
resolveConnections(connections);
try { try {
fileIn.close(); fileIn.close();
} catch (IOException e) { } catch (IOException e) {
Log.w("PartCanvasView", e.getMessage()); Log.w("PartCanvasView", e.getMessage());
return false; return false;
} }
return true; return true;
} }
private void deserializeObject(JSONObject jsonObject) throws JSONException { private List<PartConnection> deserializeObject(JSONObject jsonObject) throws JSONException {
String type = jsonObject.getString("_type"); String type = jsonObject.getString("_type");
if(type.equals(RoundButton.class.getName())) { if(type.equals(RoundButton.class.getName())) {
parts.add(RoundButton.deserialize(this, jsonObject.getJSONObject("_data"))); Tuple2<Part, List<PartConnection>> buttonInfo = RoundButton.deserialize(
this,
jsonObject.getJSONObject("_data"));
parts.add(buttonInfo.item1);
return buttonInfo.item2;
} }
else if (type.equals(Placeholder.class.getName())) { else if (type.equals(Placeholder.class.getName())) {
parts.add(Placeholder.deserialize(this, jsonObject.getJSONObject("_data"))); parts.add(Placeholder.deserialize(this, jsonObject.getJSONObject("_data")));
return Collections.emptyList();
} }
else if (type.equals(ColorBox.class.getName())){ else if (type.equals(ColorBox.class.getName())){
parts.add(ColorBox.deserialize(this, jsonObject.getJSONObject("_data"))); parts.add(ColorBox.deserialize(this, jsonObject.getJSONObject("_data")));
return Collections.emptyList();
} }
else { else {
throw new JSONException("Expected known class, found " + type); throw new JSONException("Expected known class, found " + type);
} }
} }
private void resolveConnections(List<PartConnection> connections) {
Map<String, Part> 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<String, Part> buildPartsById() {
Map<String, Part> 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 @Override
public void onDraw(Canvas canvas){ public void onDraw(Canvas canvas){
final long renderStartTime = System.currentTimeMillis(); final long renderStartTime = System.currentTimeMillis();

View File

@ -5,6 +5,8 @@ import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.util.Log; 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.InputConnector;
import com.codigoparallevar.minicards.types.Moveable; import com.codigoparallevar.minicards.types.Moveable;
import com.codigoparallevar.minicards.types.OutputConnector; 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.PartGrid;
import com.codigoparallevar.minicards.types.RoundInputConnector; import com.codigoparallevar.minicards.types.RoundInputConnector;
import com.codigoparallevar.minicards.types.RoundOutputConnector; import com.codigoparallevar.minicards.types.RoundOutputConnector;
import com.codigoparallevar.minicards.utils.Serializations;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID;
public class RoundButton implements Part { public class RoundButton implements Part {
private final String _id;
private final PartGrid _partGrid; private final PartGrid _partGrid;
private int _xCenter; private int _xCenter;
private int _yCenter; private int _yCenter;
@ -32,7 +38,10 @@ public class RoundButton implements Part {
private List<OutputConnector> _outputConnectors; private List<OutputConnector> _outputConnectors;
private final RoundOutputConnector _pressedOuputConnector; 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; _partGrid = partGrid;
_xCenter = xCenter; _xCenter = xCenter;
_yCenter = yCenter; _yCenter = yCenter;
@ -48,7 +57,10 @@ public class RoundButton implements Part {
_outputConnectors = new LinkedList<>(); _outputConnectors = new LinkedList<>();
_outputConnectors.add(_pressedOuputConnector); _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 @Override
@ -153,28 +165,68 @@ public class RoundButton implements Part {
public JSONObject serialize() throws JSONException { public JSONObject serialize() throws JSONException {
JSONObject serialized = new JSONObject(); JSONObject serialized = new JSONObject();
serialized.put("id", _id);
serialized.put("x_center", _xCenter); serialized.put("x_center", _xCenter);
serialized.put("y_center", _yCenter); serialized.put("y_center", _yCenter);
serialized.put("inner_radius", _innerRadius); serialized.put("inner_radius", _innerRadius);
serialized.put("outer_radius", _outerRadius); serialized.put("outer_radius", _outerRadius);
serialized.put("outer_radius_thickness", _outerRadiusThickness); serialized.put("outer_radius_thickness", _outerRadiusThickness);
serialized.put("on_pressed_output_connector",
Serializations.serialize(serializeConnectionEndpoints()));
return serialized; return serialized;
} }
private List<Map<String, String>> serializeConnectionEndpoints() {
List<Map<String, String>> serializedData = new LinkedList<>();
for (Tuple2<String, String> endpoint : _pressedOuputConnector.getConnectionEndpoints()){
serializedData.add(PartConnection.serialize(endpoint.item1, endpoint.item2));
}
return serializedData;
}
@Override @Override
public void sendSignal(RoundInputConnector roundInputConnector) { public void sendSignal(RoundInputConnector roundInputConnector) {
// @TODO: REMOVE THE NEED FOR THIS // @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<Part, List<PartConnection>> deserialize(PartGrid partGrid, JSONObject data) throws JSONException {
String id = data.getString("id");
int xCenter = data.getInt("x_center"); int xCenter = data.getInt("x_center");
int yCenter = data.getInt("y_center"); int yCenter = data.getInt("y_center");
int innerRadius = data.getInt("inner_radius"); int innerRadius = data.getInt("inner_radius");
int outerRadius = data.getInt("outer_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<PartConnection> 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<Part, List<PartConnection>>(button, connections);
} }
@Override @Override

View File

@ -19,8 +19,11 @@ import org.json.JSONObject;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID;
public class ColorBox implements Part { 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 final PartGrid _partGrid;
private boolean _activated; private boolean _activated;
private int _left; private int _left;
@ -30,7 +33,8 @@ public class ColorBox implements Part {
private List<InputConnector> inputConnectors; private List<InputConnector> inputConnectors;
private InputConnector _toggleInputConnector; 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; _partGrid = partGrid;
_left = left; _left = left;
_top = top; _top = top;
@ -45,6 +49,11 @@ public class ColorBox implements Part {
getInputConnectRadius()); getInputConnectRadius());
inputConnectors = new LinkedList<>(); inputConnectors = new LinkedList<>();
inputConnectors.add(_toggleInputConnector); 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 @Override
@ -139,6 +148,7 @@ public class ColorBox implements Part {
public JSONObject serialize() throws JSONException { public JSONObject serialize() throws JSONException {
JSONObject serialized = new JSONObject(); JSONObject serialized = new JSONObject();
serialized.put("id", _id);
serialized.put("left", _left); serialized.put("left", _left);
serialized.put("top", _top); serialized.put("top", _top);
serialized.put("right", _right); serialized.put("right", _right);
@ -152,13 +162,39 @@ public class ColorBox implements Part {
_activated = !_activated; _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 { public static Part deserialize(PartGrid partGrid, JSONObject data) throws JSONException {
String id = data.getString("id");
int left = data.getInt("left"); int left = data.getInt("left");
int top = data.getInt("top"); int top = data.getInt("top");
int right = data.getInt("right"); int right = data.getInt("right");
int bottom = data.getInt("bottom"); int bottom = data.getInt("bottom");
return new ColorBox(partGrid, left, top, right, bottom); return new ColorBox(id, partGrid, left, top, right, bottom);
} }
@Override @Override

View File

@ -17,15 +17,18 @@ import org.json.JSONObject;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID;
public class Placeholder implements Part { public class Placeholder implements Part {
private final String _id;
private final PartGrid _partGrid; private final PartGrid _partGrid;
private int _left; private int _left;
private int _top; private int _top;
private int _right; private int _right;
private int _bottom; 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; _partGrid = partGrid;
_left = left; _left = left;
_top = top; _top = top;
@ -33,6 +36,10 @@ public class Placeholder implements Part {
_bottom = bottom; _bottom = bottom;
} }
public Placeholder(PartGrid partGrid, int left, int top, int right, int bottom) {
this(UUID.randomUUID().toString(), partGrid, left, top, right, bottom);
}
@Override @Override
public int getLeft() { public int getLeft() {
return _left; return _left;
@ -108,6 +115,7 @@ public class Placeholder implements Part {
public JSONObject serialize() throws JSONException { public JSONObject serialize() throws JSONException {
JSONObject serialized = new JSONObject(); JSONObject serialized = new JSONObject();
serialized.put("id", _id);
serialized.put("left", _left); serialized.put("left", _left);
serialized.put("top", _top); serialized.put("top", _top);
serialized.put("right", _right); serialized.put("right", _right);
@ -121,13 +129,29 @@ public class Placeholder implements Part {
// @TODO: REMOVE THE NEED FOR THIS // @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 { public static Part deserialize(PartGrid partGrid, JSONObject data) throws JSONException {
String id = data.getString("id");
int left = data.getInt("left"); int left = data.getInt("left");
int top = data.getInt("top"); int top = data.getInt("top");
int right = data.getInt("right"); int right = data.getInt("right");
int bottom = data.getInt("bottom"); int bottom = data.getInt("bottom");
return new Placeholder(partGrid, left, top, right, bottom); return new Placeholder(id, partGrid, left, top, right, bottom);
} }
@Override @Override

View File

@ -9,4 +9,8 @@ public interface InputConnector extends Selectable, Dropper {
void sendSignal(); void sendSignal();
void getAttachment(Wire wire); void getAttachment(Wire wire);
Part getPart();
String getId();
} }

View File

@ -2,7 +2,13 @@ package com.codigoparallevar.minicards.types;
import android.graphics.Canvas; import android.graphics.Canvas;
import java.util.List;
public interface OutputConnector extends Selectable, Dropper { public interface OutputConnector extends Selectable, Dropper {
void drawWires(Canvas canvas, boolean devMode); void drawWires(Canvas canvas, boolean devMode);
void updatePosition(int x, int y); void updatePosition(int x, int y);
List<Tuple2<String, String>> getConnectionEndpoints();
void connectTo(InputConnector inputConnector);
} }

View File

@ -21,4 +21,10 @@ public interface Part extends Selectable, Moveable, Drawable {
JSONObject serialize() throws JSONException; JSONObject serialize() throws JSONException;
void sendSignal(RoundInputConnector roundInputConnector); void sendSignal(RoundInputConnector roundInputConnector);
String getId();
InputConnector getConnectorWithId(String inputConnectorId);
String getConnectorId(InputConnector inputConnector);
} }

View File

@ -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 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 inputPartId;
public final String inputConnectorId;
public PartConnection(Part outputPart, String inputPartId) { public PartConnection(OutputConnector outputConnector, String inputPartId,
this.outputPart = outputPart; String inputConnectorId) {
this.outputConnector = outputConnector;
this.inputPartId = inputPartId; 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<String, String> serialize(final String inputConnectorId, final String inputPartId) {
Map<String, String> serialized = new LinkedHashMap<>(2);
serialized.put(PartConnection.INPUT_CONNECTOR_ID_KEY, inputConnectorId);
serialized.put(PartConnection.INPUT_PART_ID_KEY, inputPartId);
return serialized;
} }
} }

View File

@ -62,6 +62,16 @@ public class RoundInputConnector implements InputConnector {
_attachments.add(wire); _attachments.add(wire);
} }
@Override
public Part getPart() {
return _part;
}
@Override
public String getId() {
return _part.getConnectorId(this);
}
@Override @Override
public void drop(Wire wire) { public void drop(Wire wire) {
Log.d("InputConnector", "Dropped wire " + wire); Log.d("InputConnector", "Dropped wire " + wire);

View File

@ -89,8 +89,28 @@ public class RoundOutputConnector implements OutputConnector, Drawable {
} }
@Override @Override
public void draw(Canvas canvas, boolean devMode) { public List<Tuple2<String, String>> getConnectionEndpoints() {
List<Tuple2<String, String>> 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() { public void sendSignal() {

View File

@ -1,10 +1,10 @@
package com.codigoparallevar.minicards.parts; package com.codigoparallevar.minicards.types;
public class Tuple<T1, T2> { public class Tuple2<T1, T2> {
public final T1 item1; public final T1 item1;
public final T2 item2; public final T2 item2;
public Tuple(T1 item1, T2 item2) { public Tuple2(T1 item1, T2 item2) {
this.item1 = item1; this.item1 = item1;
this.item2 = item2; this.item2 = item2;
} }

View File

@ -79,4 +79,8 @@ public class Wire implements Moveable, Drawable {
_attachedTo.sendSignal(); _attachedTo.sendSignal();
} }
} }
public InputConnector getAttachedTo() {
return _attachedTo;
}
} }

View File

@ -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<Map<String,String>> data) {
JSONArray array = new JSONArray();
for (Map<String, String> dict : data) {
array.put(new JSONObject(dict));
}
return array;
}
}