allow curve shape control points to overlap

This commit is contained in:
bancika
2011-01-25 21:38:37 +00:00
parent 13e0cec8ad
commit 3a7fdeb792
6 changed files with 71 additions and 42 deletions
@@ -35,6 +35,11 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
@Override
public boolean canControlPointOverlap(int index) {
return false;
}
@Override @Override
public String toString() { public String toString() {
@@ -107,6 +107,12 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
public VisibilityPolicy getControlPointVisibilityPolicy(int index) { public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.WHEN_SELECTED; return VisibilityPolicy.WHEN_SELECTED;
} }
@Override
public boolean canControlPointOverlap(int index) {
// Only shape control points may overlap.
return index == 1 || index == 2;
}
@Override @Override
public Point getControlPoint(int index) { public Point getControlPoint(int index) {
@@ -80,9 +80,22 @@ public interface IDIYComponent<T> extends Serializable {
* @param index * @param index
*/ */
void setControlPoint(Point point, int index); void setControlPoint(Point point, int index);
/**
* @param index
* @return true, if the specified control point may stick to control points
* of other components.
*/
boolean isControlPointSticky(int index); boolean isControlPointSticky(int index);
/**
* @param index
* @return true, if the specified control point may overlap with other
* control points <b>of the same component</b>. The other control
* point must be able to overlap too.
*/
boolean canControlPointOverlap(int index);
VisibilityPolicy getControlPointVisibilityPolicy(int index); VisibilityPolicy getControlPointVisibilityPolicy(int index);
/** /**
@@ -480,11 +480,6 @@ public class Presenter implements IPlugInPort {
} }
} }
} }
// // If CTRL is pressed, we only care about the top most
// component.
// if (altDown && components.size() > 0) {
// break;
// }
} }
} }
@@ -660,7 +655,6 @@ public class Presenter implements IPlugInPort {
return false; return false;
} }
Point scaledPoint = scalePoint(point); Point scaledPoint = scalePoint(point);
boolean repaint = false;
if (!controlPointMap.isEmpty()) { if (!controlPointMap.isEmpty()) {
// We're dragging control point(s). // We're dragging control point(s).
int dx = (scaledPoint.x - previousDragPoint.x); int dx = (scaledPoint.x - previousDragPoint.x);
@@ -670,24 +664,46 @@ public class Presenter implements IPlugInPort {
int actualDx = 0; int actualDx = 0;
int actualDy = 0; int actualDy = 0;
// Do a simulation of the move to see if any of them will // For each component, do a simulation of the move to see if any of
// collide. // them will
// overlap.
boolean isFirst = true;
for (Map.Entry<IDIYComponent<?>, Set<Integer>> entry : controlPointMap.entrySet()) { for (Map.Entry<IDIYComponent<?>, Set<Integer>> entry : controlPointMap.entrySet()) {
IDIYComponent<?> c = entry.getKey(); IDIYComponent<?> component = entry.getKey();
Point[] controlPoints = new Point[c.getControlPointCount()]; Point[] controlPoints = new Point[component.getControlPointCount()];
for (int i = 0; i < controlPoints.length; i++) { for (int index = 0; index < component.getControlPointCount(); index++) {
controlPoints[i] = new Point(c.getControlPoint(i)); controlPoints[index] = new Point(component.getControlPoint(index));
if (entry.getValue().contains(i)) { // When the first point is moved, calculate how much it
controlPoints[i].translate(dx, dy); // actually moved after snapping.
if (snapToGrid) { if (entry.getValue().contains(index)) {
CalcUtils.snapPointToGrid(controlPoints[i], currentProject if (isFirst) {
.getGridSpacing()); isFirst = false;
controlPoints[index].translate(dx, dy);
if (snapToGrid) {
CalcUtils.snapPointToGrid(controlPoints[index], currentProject
.getGridSpacing());
}
actualDx = controlPoints[index].x - component.getControlPoint(index).x;
actualDy = controlPoints[index].y - component.getControlPoint(index).y;
if (actualDx == 0 && actualDy == 0) {
// Nothing to move.
return true;
}
} else {
controlPoints[index].translate(actualDx, actualDy);
} }
} }
// For control points that may overlap, just write null,
// we'll ignore them later.
if (component.canControlPointOverlap(index)) {
controlPoints[index] = null;
}
} }
System.out.println(Arrays.deepToString(controlPoints));
for (int i = 0; i < controlPoints.length - 1; i++) { for (int i = 0; i < controlPoints.length - 1; i++) {
for (int j = i + 1; j < controlPoints.length; j++) { for (int j = i + 1; j < controlPoints.length; j++) {
if (controlPoints[i].equals(controlPoints[j])) { if (controlPoints[i] != null && controlPoints[j] != null
&& controlPoints[i].equals(controlPoints[j])) {
LOG.error("Control points collision detected, cannot make this move."); LOG.error("Control points collision detected, cannot make this move.");
return true; return true;
} }
@@ -696,32 +712,16 @@ public class Presenter implements IPlugInPort {
} }
// Update all points. // Update all points.
boolean isFirst = true;
for (Map.Entry<IDIYComponent<?>, Set<Integer>> entry : controlPointMap.entrySet()) { for (Map.Entry<IDIYComponent<?>, Set<Integer>> entry : controlPointMap.entrySet()) {
IDIYComponent<?> c = entry.getKey(); IDIYComponent<?> c = entry.getKey();
drawingManager.invalidateComponent(c); drawingManager.invalidateComponent(c);
for (Integer index : entry.getValue()) { for (Integer index : entry.getValue()) {
Point p = new Point(c.getControlPoint(index)); Point p = new Point(c.getControlPoint(index));
// When the first point is moved, calculate how much it p.translate(actualDx, actualDy);
// actually moved after snapping.
if (isFirst) {
isFirst = false;
p.translate(dx, dy);
if (snapToGrid) {
CalcUtils.snapPointToGrid(p, currentProject.getGridSpacing());
}
actualDx = p.x - c.getControlPoint(index).x;
actualDy = p.y - c.getControlPoint(index).y;
} else {
p.translate(actualDx, actualDy);
}
c.setControlPoint(p, index); c.setControlPoint(p, index);
} }
} }
if (actualDx != 0 || actualDy != 0) { previousDragPoint.translate(actualDx, actualDy);
previousDragPoint.translate(actualDx, actualDy);
repaint = true;
}
} else if (selectedComponents.isEmpty() } else if (selectedComponents.isEmpty()
&& instantiationManager.getComponentTypeSlot() == null) { && instantiationManager.getComponentTypeSlot() == null) {
// If there's no selection, the only thing to do is update the // If there's no selection, the only thing to do is update the
@@ -729,13 +729,13 @@ public class Presenter implements IPlugInPort {
Rectangle oldSelectionRect = selectionRect == null ? null Rectangle oldSelectionRect = selectionRect == null ? null
: new Rectangle(selectionRect); : new Rectangle(selectionRect);
this.selectionRect = Utils.createRectangle(scaledPoint, previousDragPoint); this.selectionRect = Utils.createRectangle(scaledPoint, previousDragPoint);
repaint = !selectionRect.equals(oldSelectionRect); if (selectionRect.equals(oldSelectionRect)) {
return true;
}
// messageDispatcher.dispatchMessage(EventType.SELECTION_RECT_CHANGED, // messageDispatcher.dispatchMessage(EventType.SELECTION_RECT_CHANGED,
// selectionRect); // selectionRect);
} }
if (repaint) { messageDispatcher.dispatchMessage(EventType.REPAINT);
messageDispatcher.dispatchMessage(EventType.REPAINT);
}
return true; return true;
} }
@@ -45,6 +45,11 @@ public class MockDIYComponent implements IDIYComponent<Capacitance> {
public MockDIYComponent() { public MockDIYComponent() {
super(); super();
} }
@Override
public boolean canControlPointOverlap(int index) {
return false;
}
@EditableProperty @EditableProperty
public String getName() { public String getName() {