2020-05-20 14:53:18 +00:00
|
|
|
package com.codigoparallevar.minicards.parts;
|
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
import android.graphics.Color;
|
|
|
|
import android.graphics.Paint;
|
|
|
|
import android.graphics.Rect;
|
|
|
|
import android.os.AsyncTask;
|
2020-05-20 14:53:18 +00:00
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import com.codigoparallevar.minicards.ScrolledCanvas;
|
2020-05-25 18:20:26 +00:00
|
|
|
import com.codigoparallevar.minicards.parts.connectors.AnyRoundInputConnector;
|
|
|
|
import com.codigoparallevar.minicards.parts.connectors.ConnectorTypeInfo;
|
|
|
|
import com.codigoparallevar.minicards.parts.connectors.RoundOutputConnector;
|
2020-05-20 14:53:18 +00:00
|
|
|
import com.codigoparallevar.minicards.types.Moveable;
|
|
|
|
import com.codigoparallevar.minicards.types.Part;
|
2020-05-25 18:20:26 +00:00
|
|
|
import com.codigoparallevar.minicards.types.PartConnection;
|
2020-05-20 14:53:18 +00:00
|
|
|
import com.codigoparallevar.minicards.types.PartGrid;
|
|
|
|
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;
|
2020-05-25 18:20:26 +00:00
|
|
|
import com.codigoparallevar.minicards.ui_helpers.DoAsync;
|
|
|
|
import com.programaker.api.ProgramakerApi;
|
2020-05-20 14:53:18 +00:00
|
|
|
import com.programaker.api.data.ProgramakerCustomBlock;
|
2020-05-25 18:20:26 +00:00
|
|
|
import com.programaker.api.data.ProgramakerCustomBlockArgument;
|
|
|
|
import com.programaker.api.data.ProgramakerCustomBlockSaveTo;
|
|
|
|
import com.programaker.api.data.ProgramakerFunctionCallResult;
|
2020-05-20 14:53:18 +00:00
|
|
|
|
|
|
|
import org.json.JSONException;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.LinkedList;
|
2020-05-20 14:53:18 +00:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
public class ProgramakerCustomBlockPart implements Part {
|
2020-05-25 18:20:26 +00:00
|
|
|
private static final int WIDTH_PADDING = 50;
|
|
|
|
private static final int HEIGHT_PADDING = 50;
|
|
|
|
private static final int IO_RADIUS = 50;
|
|
|
|
private static final int IO_PADDING = 20;
|
|
|
|
private static final String LogTag = "PM Custom block part";
|
2020-05-20 14:53:18 +00:00
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
private List<Tuple2<ConnectorTypeInfo, AnyRoundInputConnector>> inputConnectors = null;
|
|
|
|
private List<Tuple2<ConnectorTypeInfo, RoundOutputConnector>> outputConnectors = null;
|
2020-05-20 14:53:18 +00:00
|
|
|
|
|
|
|
private final PartGrid _partGrid;
|
|
|
|
private final String _id;
|
|
|
|
private final ProgramakerCustomBlock _block;
|
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
private int _left;
|
|
|
|
private int _top;
|
|
|
|
private int width = 100;
|
|
|
|
private int height = 100;
|
|
|
|
private String token = null;
|
|
|
|
private Object[] lastValues;
|
|
|
|
|
|
|
|
|
2020-05-20 14:53:18 +00:00
|
|
|
public ProgramakerCustomBlockPart(String id, PartGrid grid, Tuple2<Integer, Integer> center, ProgramakerCustomBlock block) {
|
|
|
|
this._id = id;
|
|
|
|
this._partGrid = grid;
|
|
|
|
this._block = block;
|
2020-05-25 18:20:26 +00:00
|
|
|
|
|
|
|
this.updateWidthHeight();
|
|
|
|
|
|
|
|
this._left = center.item1 - width / 2;
|
|
|
|
this._top = center.item2 - height / 2;
|
|
|
|
this.initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
private ProgramakerCustomBlockPart(String id, PartGrid grid, int left, int top, ProgramakerCustomBlock block) {
|
|
|
|
this._id = id;
|
|
|
|
this._partGrid = grid;
|
|
|
|
this._block = block;
|
|
|
|
|
|
|
|
this.updateWidthHeight();
|
|
|
|
|
|
|
|
this._left = left;
|
|
|
|
this._top = top;
|
|
|
|
this.initialize();
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public ProgramakerCustomBlockPart(PartGrid grid, Tuple2<Integer, Integer> center, ProgramakerCustomBlock block) {
|
|
|
|
this(UUID.randomUUID().toString(), grid, center, block);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int get_left() {
|
2020-05-25 18:20:26 +00:00
|
|
|
return _left;
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int get_right() {
|
2020-05-25 18:20:26 +00:00
|
|
|
return _left + width;
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int get_top() {
|
2020-05-25 18:20:26 +00:00
|
|
|
return _top;
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int get_bottom() {
|
2020-05-25 18:20:26 +00:00
|
|
|
return _top + height;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Paint getTextPaint() {
|
|
|
|
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
p.setColor(Color.BLACK);
|
|
|
|
p.setTextSize(50);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateWidthHeight() {
|
|
|
|
Paint p = getTextPaint();
|
|
|
|
String message = getMessage();
|
|
|
|
Rect bounds = new Rect();
|
|
|
|
p.getTextBounds(message, 0, message.length(), bounds);
|
|
|
|
|
|
|
|
this.height = bounds.height() + HEIGHT_PADDING * 2;
|
|
|
|
this.width = bounds.width() + WIDTH_PADDING * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initialize() {
|
|
|
|
this.updatePorts();
|
|
|
|
lastValues = new Object[this.inputConnectors.size()];
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updatePorts() {
|
|
|
|
String type = this._block.getBlock_type() == null ? "" : this._block.getBlock_type();
|
|
|
|
boolean has_pulse_input = type.equals("operation");
|
|
|
|
boolean has_pulse_output = has_pulse_input || type.equals("trigger");
|
|
|
|
boolean hasImplicitOutput = type.equals("getter");
|
|
|
|
|
|
|
|
List<Tuple2<ConnectorTypeInfo, AnyRoundInputConnector>> inputs = new LinkedList<>();
|
|
|
|
List<Tuple2<ConnectorTypeInfo, RoundOutputConnector>> outputs = new LinkedList<>();
|
|
|
|
|
|
|
|
// Add pulses
|
|
|
|
if (has_pulse_input) {
|
|
|
|
inputs.add(new Tuple2<>(new ConnectorTypeInfo(ConnectorTypeInfo.Type.PULSE),
|
|
|
|
new AnyRoundInputConnector(this, 0, 0,
|
|
|
|
IO_RADIUS))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (has_pulse_output) {
|
|
|
|
outputs.add(new Tuple2<>(new ConnectorTypeInfo(ConnectorTypeInfo.Type.PULSE),
|
|
|
|
new RoundOutputConnector(this, this._partGrid, 0, 0,
|
|
|
|
IO_RADIUS))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add block IO
|
|
|
|
ProgramakerCustomBlockArgument savedTo = null;
|
|
|
|
|
|
|
|
if (_block.getArguments() != null) {
|
|
|
|
ProgramakerCustomBlockSaveTo saveTo = _block.getSave_to();
|
|
|
|
int skip = -1;
|
|
|
|
|
|
|
|
if (saveTo != null) {
|
|
|
|
if (saveTo.getType() != null
|
|
|
|
&& saveTo.getType().equals("argument")) {
|
|
|
|
skip = saveTo.getIndex();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Log.w(LogTag, "Unknown save-to type=" + saveTo.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = -1;
|
|
|
|
for (ProgramakerCustomBlockArgument arg : _block.getArguments()) {
|
|
|
|
index++;
|
|
|
|
if (skip == index) {
|
|
|
|
savedTo = arg;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
inputs.add(new Tuple2<>(ConnectorTypeInfo.FromTypeName(arg.getType()),
|
|
|
|
new AnyRoundInputConnector(this, 0, 0, IO_RADIUS)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (savedTo != null) {
|
|
|
|
outputs.add(new Tuple2<>(ConnectorTypeInfo.FromTypeName(savedTo.getType()),
|
|
|
|
new RoundOutputConnector(this, this._partGrid, 0, 0, IO_RADIUS)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasImplicitOutput) {
|
|
|
|
outputs.add(new Tuple2<>(ConnectorTypeInfo.FromTypeName(_block.getBlock_result_type()),
|
|
|
|
new RoundOutputConnector(this, this._partGrid, 0, 0, IO_RADIUS)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tie everything
|
|
|
|
inputConnectors = inputs;
|
|
|
|
outputConnectors = outputs;
|
|
|
|
|
|
|
|
this.updatePortPositions();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updatePortPositions() {
|
|
|
|
{
|
|
|
|
// Update inputs
|
|
|
|
int y = get_top();
|
|
|
|
int x = get_left() + IO_PADDING;
|
|
|
|
for (Tuple2<ConnectorTypeInfo, AnyRoundInputConnector> entry : inputConnectors) {
|
|
|
|
InputConnector input = entry.item2;
|
|
|
|
int new_x = x + IO_PADDING + IO_RADIUS / 2;
|
|
|
|
input.updatePosition(new_x, y);
|
|
|
|
x = x + IO_RADIUS * 2 + IO_PADDING * 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// Update outputs
|
|
|
|
int y = get_bottom();
|
|
|
|
int x = get_left() + IO_PADDING;
|
|
|
|
for (Tuple2<ConnectorTypeInfo, RoundOutputConnector> entry : outputConnectors) {
|
|
|
|
OutputConnector output = entry.item2;
|
|
|
|
int new_x = x + IO_PADDING + IO_RADIUS / 2;
|
|
|
|
output.updatePosition(new_x, y);
|
|
|
|
x = x + IO_RADIUS * 2 + IO_PADDING * 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private String getMessage() {
|
|
|
|
return this._block.getMessage();
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void touched() {
|
2020-05-25 18:20:26 +00:00
|
|
|
Log.i(LogTag, "Part touched (block_fun=" + this._block.getFunction_name() + ")");
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public List<InputConnector> getInputConnectors() {
|
2020-05-25 18:20:26 +00:00
|
|
|
List<InputConnector> result = new ArrayList<>(inputConnectors.size());
|
|
|
|
for (Tuple2<ConnectorTypeInfo, AnyRoundInputConnector> entry : inputConnectors) {
|
|
|
|
result.add(entry.item2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public List<OutputConnector> getOutputConnectors() {
|
2020-05-25 18:20:26 +00:00
|
|
|
List<OutputConnector> result = new ArrayList<>(outputConnectors.size());
|
|
|
|
for (Tuple2<ConnectorTypeInfo, RoundOutputConnector> entry : outputConnectors) {
|
|
|
|
result.add(entry.item2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public JSONObject serialize() throws JSONException {
|
2020-05-25 18:20:26 +00:00
|
|
|
JSONObject serialized = new JSONObject();
|
|
|
|
|
|
|
|
serialized.put("id", _id);
|
|
|
|
serialized.put("left", _left);
|
|
|
|
serialized.put("top", _top);
|
|
|
|
|
|
|
|
JSONObject blockData = _block.serialize();
|
|
|
|
serialized.put("block", blockData);
|
|
|
|
|
|
|
|
// serialized.put("on_string_output_connector",
|
|
|
|
// Serializations.serialize(serializeConnectionEndpoints()));
|
|
|
|
|
|
|
|
return serialized;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Tuple2<Part, List<PartConnection>> deserialize(PartGrid grid, JSONObject data) throws JSONException {
|
|
|
|
String id = data.getString("id");
|
|
|
|
int left = data.getInt("left");
|
|
|
|
int top = data.getInt("top");
|
|
|
|
|
|
|
|
JSONObject el = data.getJSONObject("block");
|
|
|
|
ProgramakerCustomBlock block = ProgramakerCustomBlock.deserialize(el);
|
|
|
|
ProgramakerCustomBlockPart part = new ProgramakerCustomBlockPart(id, grid, left, top, block);
|
|
|
|
|
|
|
|
List<PartConnection> connections = new LinkedList<>();
|
|
|
|
|
|
|
|
// JSONArray connectorOuts = data.getJSONArray("on_string_output_connector");
|
|
|
|
// for (int i = 0; i < connectorOuts.length(); i++) {
|
|
|
|
// connections.add(PartConnection.deserialize(
|
|
|
|
// toggle._stringOutputConnector,
|
|
|
|
// connectorOuts.getJSONObject(i)));
|
|
|
|
// }
|
|
|
|
|
|
|
|
return new Tuple2<>(part, connections);
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
|
2020-05-20 14:53:18 +00:00
|
|
|
@Override
|
|
|
|
public void send(InputConnector inputConnector, WireDataType signal) {
|
2020-05-25 18:20:26 +00:00
|
|
|
Log.i(LogTag, "Received signal from Input="+inputConnector);
|
|
|
|
ConnectorTypeInfo info = getConnectorInfo(inputConnector);
|
|
|
|
if (info == null) {
|
|
|
|
Log.e(LogTag, "Unknown connector" + inputConnector);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.get_type() == ConnectorTypeInfo.Type.PULSE) {
|
|
|
|
wrappedRunOperation();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int index = getConnectorIndex(inputConnector);
|
|
|
|
if (index < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.lastValues[index] = signal.get();
|
|
|
|
}
|
|
|
|
}
|
2020-05-20 14:53:18 +00:00
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
private void wrappedRunOperation() {
|
|
|
|
Log.i(LogTag, "Running block function=" + this._block.getFunction_name());
|
|
|
|
String token = this.prepareStart();
|
|
|
|
|
|
|
|
if (token != null) {
|
|
|
|
try {
|
|
|
|
new DoAsync().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
|
|
|
|
new Tuple2<>(() -> {
|
|
|
|
ProgramakerCustomBlockPart.this.runBlockOperation();
|
|
|
|
|
|
|
|
ProgramakerCustomBlockPart.this.freeBlock(token);
|
|
|
|
}, param -> {
|
|
|
|
Log.e(LogTag, "Error executing function=" + this._block.getFunction_name()
|
|
|
|
+ "; Error=" + param);
|
|
|
|
ProgramakerCustomBlockPart.this.freeBlock(token);
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
catch (Exception ex) {
|
|
|
|
Log.e(LogTag, "Error executing function=" + this._block.getFunction_name()
|
|
|
|
+ "; Error=" + ex);
|
|
|
|
this.freeBlock(token);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// An execution is in progress, so nothing is done
|
|
|
|
}
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
private void runBlockOperation() {
|
|
|
|
ProgramakerApi api = this._partGrid.getApi();
|
|
|
|
List<String> arguments = new LinkedList<>();
|
|
|
|
|
|
|
|
int index = -1;
|
|
|
|
for (Tuple2<ConnectorTypeInfo, AnyRoundInputConnector> entry : inputConnectors) {
|
|
|
|
index++;
|
|
|
|
if (entry.item1.get_type() == ConnectorTypeInfo.Type.PULSE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
arguments.add(lastValues[index].toString()); // TODO: Do proper type formatting
|
|
|
|
}
|
|
|
|
|
|
|
|
ProgramakerFunctionCallResult result = api.callBlock(this._block, arguments);
|
|
|
|
Log.d(LogTag, "Execution result="+result);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void freeBlock(String token) {
|
|
|
|
tryUpdateBlock(token, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
private String prepareStart() {
|
|
|
|
String token = UUID.randomUUID().toString();
|
|
|
|
if (tryUpdateBlock(null, token)) {
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized boolean tryUpdateBlock(String oldVal, String newVal) {
|
|
|
|
if (this.token == oldVal) {
|
|
|
|
this.token = newVal;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-20 14:53:18 +00:00
|
|
|
@Override
|
|
|
|
public String get_id() {
|
|
|
|
return _id;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public InputConnector getConnectorWithId(String inputConnectorId) {
|
2020-05-25 18:20:26 +00:00
|
|
|
if (inputConnectorId.startsWith("index=")) {
|
|
|
|
String[] chunks = inputConnectorId.split("=");
|
|
|
|
if (chunks.length > 1) {
|
|
|
|
Integer index = null;
|
|
|
|
try {
|
|
|
|
index = Integer.parseInt(chunks[1]);
|
|
|
|
}
|
|
|
|
catch (NumberFormatException ex) {
|
|
|
|
Log.e(LogTag, "Error parsing connector id="+inputConnectorId);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index != null && index < inputConnectors.size()) {
|
|
|
|
return inputConnectors.get(index).item2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-20 14:53:18 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-05-25 18:20:26 +00:00
|
|
|
private int getConnectorIndex(InputConnector inputConnector) {
|
|
|
|
int index = 0;
|
|
|
|
for (Tuple2<ConnectorTypeInfo, AnyRoundInputConnector> entry : inputConnectors) {
|
|
|
|
if (entry.item2 == inputConnector) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-05-20 14:53:18 +00:00
|
|
|
@Override
|
|
|
|
public String getConnectorId(InputConnector inputConnector) {
|
2020-05-25 18:20:26 +00:00
|
|
|
int index = getConnectorIndex(inputConnector);
|
|
|
|
if (index < 0 ) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "index=" + index;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ConnectorTypeInfo getConnectorInfo(InputConnector inputConnector) {
|
|
|
|
for (Tuple2<ConnectorTypeInfo, AnyRoundInputConnector> entry : inputConnectors) {
|
|
|
|
if (entry.item2 == inputConnector) {
|
|
|
|
return entry.item1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-20 14:53:18 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void resume() {
|
|
|
|
// Intentionally left empty
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void pause() {
|
|
|
|
// Intentionally left empty
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void draw(ScrolledCanvas canvas, boolean devMode) {
|
2020-05-25 18:20:26 +00:00
|
|
|
|
|
|
|
updateWidthHeight(); // TODO: Remove after the calculations have stabilized
|
|
|
|
|
|
|
|
if (!devMode) {
|
|
|
|
return; // Logic block, don't show on user-mode
|
|
|
|
}
|
|
|
|
|
|
|
|
drawConnectors(canvas);
|
|
|
|
// drawWires(canvas, devMode); // TODO: Implement
|
|
|
|
|
|
|
|
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
paint.setColor(Color.WHITE);
|
|
|
|
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) {
|
|
|
|
if (inputConnectors != null) {
|
|
|
|
for (Tuple2<ConnectorTypeInfo, AnyRoundInputConnector> entry : inputConnectors) {
|
|
|
|
Paint outerInputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
outerInputConnectorPaint.setColor(entry.item1.getOuterColor());
|
|
|
|
|
|
|
|
canvas.drawCircle(
|
|
|
|
entry.item2.getX(),
|
|
|
|
entry.item2.getY(),
|
|
|
|
entry.item2.getRadius(),
|
|
|
|
outerInputConnectorPaint);
|
|
|
|
|
|
|
|
Paint innerInputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
innerInputConnectorPaint.setColor(entry.item1.getInnerColor());
|
|
|
|
|
|
|
|
canvas.drawCircle(
|
|
|
|
entry.item2.getX(),
|
|
|
|
entry.item2.getY(),
|
|
|
|
entry.item2.getRadius() / 2,
|
|
|
|
innerInputConnectorPaint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outputConnectors != null) {
|
|
|
|
for (Tuple2<ConnectorTypeInfo, RoundOutputConnector> entry : outputConnectors) {
|
|
|
|
Paint outerOutputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
outerOutputConnectorPaint.setColor(entry.item1.getOuterColor());
|
|
|
|
|
|
|
|
canvas.drawCircle(
|
|
|
|
entry.item2.getX(),
|
|
|
|
entry.item2.getY(),
|
|
|
|
entry.item2.getRadius(),
|
|
|
|
outerOutputConnectorPaint);
|
|
|
|
|
|
|
|
Paint innerOutputConnectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
innerOutputConnectorPaint.setColor(entry.item1.getInnerColor());
|
|
|
|
|
|
|
|
canvas.drawCircle(
|
|
|
|
entry.item2.getX(),
|
|
|
|
entry.item2.getY(),
|
|
|
|
entry.item2.getRadius() / 2,
|
|
|
|
innerOutputConnectorPaint);
|
|
|
|
}
|
|
|
|
}
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void moveEnd(int x, int y) {
|
2020-05-25 18:20:26 +00:00
|
|
|
_left = x - width / 2;
|
|
|
|
_top = y - height / 2;
|
|
|
|
|
|
|
|
this.updatePortPositions();
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void drop(int x, int y) {
|
|
|
|
moveEnd(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean containsPoint(int x, int y) {
|
2020-05-25 18:20:26 +00:00
|
|
|
Log.d(LogTag, "Contains (" +x+","+y+") in {left=" +get_left()+",right="+get_right()+",top="+get_top()+",bottom=" + get_bottom() + "}");
|
2020-05-20 14:53:18 +00:00
|
|
|
return ((x >= this.get_left()) && (x <= this.get_right())
|
2020-05-25 18:20:26 +00:00
|
|
|
&& (y >= this.get_top()) && (y <= this.get_bottom()));
|
2020-05-20 14:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Moveable getMoveable() {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void unlink() {
|
|
|
|
// TODO: Implement
|
|
|
|
}
|
|
|
|
}
|