1 package net.mograsim.logic.model.editor.handles;
3 import java.util.Optional;
5 import org.eclipse.swt.SWT;
6 import org.eclipse.swt.widgets.Display;
8 import net.haspamelodica.swt.helper.gcs.GeneralGC;
9 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
10 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
11 import net.mograsim.logic.model.editor.states.EditorState;
12 import net.mograsim.logic.model.model.LogicModelModifiable;
13 import net.mograsim.logic.model.model.wires.ModelWire;
15 public class WireHandle extends Handle
17 private boolean selected = false;
18 private final static double WIDTH = 2.0;
19 private final static double WIDTH_SQUARED = WIDTH * WIDTH;
20 private final LogicModelModifiable model;
21 public final ModelWire parent;
23 public WireHandle(LogicModelModifiable model, ModelWire parent)
28 parent.addPathChangedListener(c -> updateBounds());
36 parent.removePathChangedListener(c -> updateBounds());
39 public void updateBounds()
41 Rectangle r = parent.getBounds();
43 setSize(r.width, r.height);
47 public void render(GeneralGC gc)
51 gc.setLineWidth(WIDTH);
52 gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_YELLOW));
53 gc.drawPolyline(parent.getEffectivePath());
58 public void onSelect()
61 callRedrawListeners();
65 public void onDeselect()
68 callRedrawListeners();
72 public void reqDelete()
74 // this wire could already be removed implicitly when removing a selection containing both wires and components
75 if (model.getWireByName(parent.name) != null)
76 model.destroyWire(parent);
80 public boolean contains(double x, double y)
82 return click(parent, x, y).isPresent();
86 public boolean click(double x, double y, int stateMask, EditorState state)
88 Optional<WireClickData> op = click(parent, x, y);
91 WireClickData data = op.get();
92 return state.clickedHandle(new WireHandleClickInfo(this, data.segment, data.pos, stateMask));
95 public static class WireHandleClickInfo extends HandleClickInfo
97 public final int segment;
98 public final Point posOnWire;
100 WireHandleClickInfo(WireHandle clicked, int segment, Point posOnWire, int stateMask)
102 super(clicked, stateMask);
103 this.segment = segment;
104 this.posOnWire = posOnWire;
109 private static Optional<WireClickData> click(ModelWire w, double x, double y)
111 Rectangle modifiedBounds = w.getBounds();
112 modifiedBounds.x -= WIDTH;
113 modifiedBounds.y -= WIDTH;
114 modifiedBounds.width += WIDTH * 2;
115 modifiedBounds.height += WIDTH * 2;
116 if (modifiedBounds.contains(x, y))
118 double[] effectivePath = w.getEffectivePath();
119 for (int i = 3; i < effectivePath.length; i += 2)
121 double a1 = effectivePath[i - 3], a2 = effectivePath[i - 2], b1 = effectivePath[i - 1], b2 = effectivePath[i], r1 = b2 - a2,
124 double f = ((x - a1) * r2 + (a2 - y) * r1) / (-r2 * r2 - r1 * r1);
125 if (f >= 0 && f <= 1)
127 double e1 = a1 + f * (b1 - a1), e2 = a2 + f * (b2 - a2);
130 if (r1 * r1 + r2 * r2 <= WIDTH_SQUARED)
131 return Optional.of(new WireClickData(new Point(e1, e2), (i / 2) - 1));
135 return Optional.empty();
138 private final static class WireClickData
140 WireClickData(Point pos, int segment)
143 this.segment = segment;
147 * Position on the wire that is closest to the click
149 public final Point pos;
151 * Segment of the wire that the {@link Point} pos is on
153 public final int segment;
157 public HandleType getType()
159 return HandleType.WIRE;