mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
Components can be dragged and their points stretched through the Underside Display mirror of a board
This commit is contained in:
@@ -751,9 +751,8 @@ public class DrawingManager {
|
|||||||
public List<IDIYComponent<?>> findMirroredComponentsAt(Point2D point, Project project) {
|
public List<IDIYComponent<?>> findMirroredComponentsAt(Point2D point, Project project) {
|
||||||
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
|
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
|
||||||
for (IBoard board : UndersideMirror.findBoardsMirroredAt(project, point)) {
|
for (IBoard board : UndersideMirror.findBoardsMirroredAt(project, point)) {
|
||||||
Point2D reflected = UndersideMirror.createTransform(board).transform(point, null);
|
for (IDIYComponent<?> component : findMirroredComponentsAt(point, project, board)) {
|
||||||
for (IDIYComponent<?> component : findComponentsAt(reflected, project)) {
|
if (!components.contains(component)) {
|
||||||
if (UndersideMirror.isMirrored(board, component) && !components.contains(component)) {
|
|
||||||
components.add(component);
|
components.add(component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -761,6 +760,30 @@ public class DrawingManager {
|
|||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the components that the underside mirror of the specified board shows at the specified
|
||||||
|
* point, top first, or none when the point is not in that mirror.
|
||||||
|
*
|
||||||
|
* @param point
|
||||||
|
* @param project
|
||||||
|
* @param board
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<IDIYComponent<?>> findMirroredComponentsAt(Point2D point, Project project,
|
||||||
|
IBoard board) {
|
||||||
|
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
|
||||||
|
AffineTransform mirrorTx = UndersideMirror.createTransform(board);
|
||||||
|
if (mirrorTx == null || !UndersideMirror.getMirrorRegion(board).contains(point)) {
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
for (IDIYComponent<?> component : findComponentsAt(mirrorTx.transform(point, null), project)) {
|
||||||
|
if (UndersideMirror.isMirrored(board, component)) {
|
||||||
|
components.add(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
public double getExtraSpace(Project project) {
|
public double getExtraSpace(Project project) {
|
||||||
double width = project.getWidth().convertToPixels();
|
double width = project.getWidth().convertToPixels();
|
||||||
double height = project.getHeight().convertToPixels();
|
double height = project.getHeight().convertToPixels();
|
||||||
|
|||||||
@@ -172,6 +172,11 @@ public class Presenter implements IPlugInPort {
|
|||||||
private Point2D dragStartPoint = null;
|
private Point2D dragStartPoint = null;
|
||||||
private boolean dragShiftDown = false;
|
private boolean dragShiftDown = false;
|
||||||
private AxisLock lockedAxis = null;
|
private AxisLock lockedAxis = null;
|
||||||
|
// The reflection of the Underside Display mirror a drag started in. Every point of that drag goes
|
||||||
|
// through it, so the drag acts on the components themselves; null for a drag in the main view.
|
||||||
|
private AffineTransform dragMirrorTx = null;
|
||||||
|
// the reflection of the mirror that the control points in controlPointMap were found through
|
||||||
|
private AffineTransform hoverMirrorTx = null;
|
||||||
|
|
||||||
private DIYTest test = null;
|
private DIYTest test = null;
|
||||||
|
|
||||||
@@ -279,16 +284,8 @@ public class Presenter implements IPlugInPort {
|
|||||||
if (controlPointMap != null && !controlPointMap.isEmpty()) {
|
if (controlPointMap != null && !controlPointMap.isEmpty()) {
|
||||||
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||||
}
|
}
|
||||||
for (IDIYComponent<?> component : currentProject.getComponents()) {
|
if (scaledPoint != null && !findComponentsAtScaled(scaledPoint, false).isEmpty()) {
|
||||||
if (!isComponentLocked(component) && isComponentVisible(component)
|
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||||
&& operationMode != OperationMode.HIGHLIGHT_CONNECTED_AREAS) {
|
|
||||||
ComponentArea area = drawingManager.getComponentArea(component);
|
|
||||||
// the bounds rule most components out without merging their outline into an area
|
|
||||||
if (area != null && scaledPoint != null && area.getOutlineBounds().contains(scaledPoint)
|
|
||||||
&& area.getOutlineArea().contains(scaledPoint)) {
|
|
||||||
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,8 +566,8 @@ public class Presenter implements IPlugInPort {
|
|||||||
return findComponentsAtScaled(point, includeLocked, true);
|
return findComponentsAtScaled(point, includeLocked, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a drag does not look through the underside mirror, because moving the mouse there moves the
|
// a drag reflects its points out of the underside mirror itself, so its hit tests must not look
|
||||||
// part the other way along the mirrored axis
|
// through the mirror a second time
|
||||||
private List<IDIYComponent<?>> findComponentsAtScaled(Point2D point, boolean includeLocked,
|
private List<IDIYComponent<?>> findComponentsAtScaled(Point2D point, boolean includeLocked,
|
||||||
boolean throughMirror) {
|
boolean throughMirror) {
|
||||||
List<IDIYComponent<?>> components = drawingManager.findComponentsAt(point, currentProject);
|
List<IDIYComponent<?>> components = drawingManager.findComponentsAt(point, currentProject);
|
||||||
@@ -950,6 +947,42 @@ public class Presenter implements IPlugInPort {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the control points of the selected, ungrouped components that can be dragged from the
|
||||||
|
* specified point, one per component. When the point was reflected out of the underside mirror of
|
||||||
|
* a board, only the components that mirror shows are considered.
|
||||||
|
*/
|
||||||
|
private Map<IDIYComponent<?>, Set<Integer>> findControlPointsAt(Point2D point, IBoard mirrorBoard) {
|
||||||
|
Map<IDIYComponent<?>, Set<Integer>> components = new HashMap<IDIYComponent<?>, Set<Integer>>();
|
||||||
|
// Go backwards so we take the highest z-order components first.
|
||||||
|
for (int i = currentProject.getComponents().size() - 1; i >= 0; i--) {
|
||||||
|
IDIYComponent<?> component = currentProject.getComponents().get(i);
|
||||||
|
if (mirrorBoard != null && selectedComponents.contains(component)
|
||||||
|
&& !UndersideMirror.isMirrored(mirrorBoard, component)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int pointIndex = 0; pointIndex < component.getControlPointCount(); pointIndex++) {
|
||||||
|
Point2D controlPoint = component.getControlPoint(pointIndex);
|
||||||
|
// Only consider selected components that are not grouped.
|
||||||
|
if (selectedComponents.contains(component) && component.canPointMoveFreely(pointIndex)
|
||||||
|
&& findAllGroupedComponents(component).size() == 1) {
|
||||||
|
try {
|
||||||
|
if (point.distance(controlPoint) < DrawingManager.CONTROL_POINT_SIZE &&
|
||||||
|
component.getControlPointVisibilityPolicy(pointIndex) != VisibilityPolicy.NEVER) {
|
||||||
|
Set<Integer> indices = new HashSet<Integer>();
|
||||||
|
indices.add(pointIndex);
|
||||||
|
components.put(component, indices);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Error reading control point for component of type: " + component.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown) {
|
public void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown) {
|
||||||
if (point == null)
|
if (point == null)
|
||||||
@@ -996,26 +1029,16 @@ public class Presenter implements IPlugInPort {
|
|||||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Go backwards so we take the highest z-order components first.
|
components = findControlPointsAt(previousScaledPoint, null);
|
||||||
for (int i = currentProject.getComponents().size() - 1; i >= 0; i--) {
|
hoverMirrorTx = null;
|
||||||
IDIYComponent<?> component = currentProject.getComponents().get(i);
|
for (IBoard board : UndersideMirror.findBoardsMirroredAt(currentProject, previousScaledPoint)) {
|
||||||
for (int pointIndex = 0; pointIndex < component.getControlPointCount(); pointIndex++) {
|
if (!components.isEmpty()) {
|
||||||
Point2D controlPoint = component.getControlPoint(pointIndex);
|
break;
|
||||||
// Only consider selected components that are not grouped.
|
}
|
||||||
if (selectedComponents.contains(component) && component.canPointMoveFreely(pointIndex)
|
AffineTransform mirrorTx = UndersideMirror.createTransform(board);
|
||||||
&& findAllGroupedComponents(component).size() == 1) {
|
components = findControlPointsAt(mirrorTx.transform(previousScaledPoint, null), board);
|
||||||
try {
|
if (!components.isEmpty()) {
|
||||||
if (previousScaledPoint.distance(controlPoint) < DrawingManager.CONTROL_POINT_SIZE &&
|
hoverMirrorTx = mirrorTx;
|
||||||
component.getControlPointVisibilityPolicy(pointIndex) != VisibilityPolicy.NEVER) {
|
|
||||||
Set<Integer> indices = new HashSet<Integer>();
|
|
||||||
indices.add(pointIndex);
|
|
||||||
components.put(component, indices);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.warn("Error reading control point for component of type: " + component.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1364,6 +1387,14 @@ public class Presenter implements IPlugInPort {
|
|||||||
this.dragAction = dragAction;
|
this.dragAction = dragAction;
|
||||||
this.preDragProject = currentProject.clone();
|
this.preDragProject = currentProject.clone();
|
||||||
Point2D scaledPoint = scalePoint(point);
|
Point2D scaledPoint = scalePoint(point);
|
||||||
|
if (controlPointMap != null && !controlPointMap.isEmpty()) {
|
||||||
|
this.dragMirrorTx = hoverMirrorTx;
|
||||||
|
} else if (forceSelectionRect || !findComponentsAtScaled(scaledPoint, false, false).isEmpty()) {
|
||||||
|
this.dragMirrorTx = null;
|
||||||
|
} else {
|
||||||
|
this.dragMirrorTx = findMirrorWithComponentAt(scaledPoint);
|
||||||
|
}
|
||||||
|
scaledPoint = toDragSpace(scaledPoint);
|
||||||
this.previousDragPoint = scaledPoint;
|
this.previousDragPoint = scaledPoint;
|
||||||
this.dragStartPoint = new Point2D.Double(scaledPoint.getX(), scaledPoint.getY());
|
this.dragStartPoint = new Point2D.Double(scaledPoint.getX(), scaledPoint.getY());
|
||||||
this.dragShiftDown = shiftDown;
|
this.dragShiftDown = shiftDown;
|
||||||
@@ -1586,7 +1617,7 @@ public class Presenter implements IPlugInPort {
|
|||||||
|
|
||||||
boolean resizeInProgress = false;
|
boolean resizeInProgress = false;
|
||||||
|
|
||||||
Point2D scaledPoint = scalePoint(point);
|
Point2D scaledPoint = toDragSpace(scalePoint(point));
|
||||||
if (controlPointMap != null && !controlPointMap.isEmpty()) {
|
if (controlPointMap != null && !controlPointMap.isEmpty()) {
|
||||||
// We're dragging control point(s).
|
// We're dragging control point(s).
|
||||||
Point2D targetPoint = constrainToAxis(dragStartPoint, scaledPoint, dragShiftDown);
|
Point2D targetPoint = constrainToAxis(dragStartPoint, scaledPoint, dragShiftDown);
|
||||||
@@ -2004,7 +2035,7 @@ public class Presenter implements IPlugInPort {
|
|||||||
test.addStep(DIYTest.DRAG_END, params);
|
test.addStep(DIYTest.DRAG_END, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point2D scaledPoint = scalePoint(point);
|
Point2D scaledPoint = toDragSpace(scalePoint(point));
|
||||||
|
|
||||||
if (!dragInProgress && instantiationManager.getComponentSlot() == null) {
|
if (!dragInProgress && instantiationManager.getComponentSlot() == null) {
|
||||||
return;
|
return;
|
||||||
@@ -2056,6 +2087,7 @@ public class Presenter implements IPlugInPort {
|
|||||||
dragStartPoint = null;
|
dragStartPoint = null;
|
||||||
dragShiftDown = false;
|
dragShiftDown = false;
|
||||||
lockedAxis = null;
|
lockedAxis = null;
|
||||||
|
dragMirrorTx = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -3155,6 +3187,27 @@ public class Presenter implements IPlugInPort {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Point2D toDragSpace(Point2D scaledPoint) {
|
||||||
|
return dragMirrorTx == null || scaledPoint == null ? scaledPoint
|
||||||
|
: dragMirrorTx.transform(scaledPoint, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the reflection of the first underside mirror that shows a selectable component at the
|
||||||
|
* specified point, or null
|
||||||
|
*/
|
||||||
|
private AffineTransform findMirrorWithComponentAt(Point2D scaledPoint) {
|
||||||
|
for (IBoard board : UndersideMirror.findBoardsMirroredAt(currentProject, scaledPoint)) {
|
||||||
|
List<IDIYComponent<?>> components =
|
||||||
|
drawingManager.findMirroredComponentsAt(scaledPoint, currentProject, board);
|
||||||
|
removeUnselectable(components, false);
|
||||||
|
if (!components.isEmpty()) {
|
||||||
|
return UndersideMirror.createTransform(board);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveSelectionAsBlock(String blockName) {
|
public void saveSelectionAsBlock(String blockName) {
|
||||||
buildingBlockManager.saveSelectionAsBlock(blockName, this.getSelectedComponents(), this.currentProject.getComponents());
|
buildingBlockManager.saveSelectionAsBlock(blockName, this.getSelectedComponents(), this.currentProject.getComponents());
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package org.diylc;
|
package org.diylc;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
@@ -17,14 +19,19 @@ import org.diylc.appframework.miscutils.ConfigurationManager;
|
|||||||
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
|
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
|
||||||
import org.diylc.clipboard.ComponentTransferable;
|
import org.diylc.clipboard.ComponentTransferable;
|
||||||
import org.diylc.common.ComponentType;
|
import org.diylc.common.ComponentType;
|
||||||
|
import org.diylc.common.DrawOption;
|
||||||
import org.diylc.common.EventType;
|
import org.diylc.common.EventType;
|
||||||
import org.diylc.common.IPlugIn;
|
import org.diylc.common.IPlugIn;
|
||||||
import org.diylc.common.IPlugInPort;
|
import org.diylc.common.IPlugInPort;
|
||||||
|
import org.diylc.components.boards.BlankBoard;
|
||||||
import org.diylc.components.chassis.ChassisPanel;
|
import org.diylc.components.chassis.ChassisPanel;
|
||||||
import org.diylc.components.composite.CompositeComponent;
|
import org.diylc.components.composite.CompositeComponent;
|
||||||
|
import org.diylc.core.BoardUndersideDisplay;
|
||||||
|
import org.diylc.core.IBoard;
|
||||||
import org.diylc.core.IDIYComponent;
|
import org.diylc.core.IDIYComponent;
|
||||||
import org.diylc.core.Template;
|
import org.diylc.core.Template;
|
||||||
import org.diylc.presenter.Presenter;
|
import org.diylc.presenter.Presenter;
|
||||||
|
import org.diylc.presenter.UndersideMirror;
|
||||||
import org.diylc.swing.ActionFactory;
|
import org.diylc.swing.ActionFactory;
|
||||||
import org.diylc.swing.actions.ComponentCategoryAction;
|
import org.diylc.swing.actions.ComponentCategoryAction;
|
||||||
import org.diylc.swing.actions.ResetCategoriesAction;
|
import org.diylc.swing.actions.ResetCategoriesAction;
|
||||||
@@ -281,6 +288,75 @@ public class PresenterTests extends TestBase {
|
|||||||
presenter.dragEnded(new Point(1300, 1100));
|
presenter.dragEnded(new Point(1300, 1100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStretchThroughUndersideMirror() {
|
||||||
|
instantiateTwoClick("Passive", "Resistor", new Point(1000, 1000), new Point(1200, 1000));
|
||||||
|
IDIYComponent<?> resistor = presenter.getCurrentProject().getComponents().get(0);
|
||||||
|
IBoard board = boardUnder(resistor);
|
||||||
|
Point2D start = new Point2D.Double(resistor.getControlPoint(1).getX(), resistor.getControlPoint(1).getY());
|
||||||
|
Point inMirror = toScreen(UndersideMirror.createTransform(board).transform(start, null));
|
||||||
|
|
||||||
|
presenter.mouseMoved(inMirror, false, false, false);
|
||||||
|
presenter.dragStarted(inMirror, java.awt.dnd.DnDConstants.ACTION_MOVE, false, false);
|
||||||
|
presenter.dragOver(new Point(inMirror.x + 100, inMirror.y + 100));
|
||||||
|
presenter.dragEnded(new Point(inMirror.x + 100, inMirror.y + 100));
|
||||||
|
|
||||||
|
// the mirror is flipped vertically, so moving down in it moves the point up on the board
|
||||||
|
Assert.assertTrue(resistor.getControlPoint(1).getX() > start.getX());
|
||||||
|
Assert.assertTrue(resistor.getControlPoint(1).getY() < start.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDragThroughUndersideMirror() {
|
||||||
|
instantiateTwoClick("Passive", "Resistor", new Point(1000, 1000), new Point(1200, 1000));
|
||||||
|
IDIYComponent<?> resistor = presenter.getCurrentProject().getComponents().get(0);
|
||||||
|
IBoard board = boardUnder(resistor);
|
||||||
|
Point2D start0 = new Point2D.Double(resistor.getControlPoint(0).getX(), resistor.getControlPoint(0).getY());
|
||||||
|
Point2D start1 = new Point2D.Double(resistor.getControlPoint(1).getX(), resistor.getControlPoint(1).getY());
|
||||||
|
// the hit test reads the areas recorded while drawing
|
||||||
|
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
Graphics2D g2d = img.createGraphics();
|
||||||
|
presenter.draw(g2d, EnumSet.of(DrawOption.ZOOM), null, null, null, null);
|
||||||
|
g2d.dispose();
|
||||||
|
Point2D middle = new Point2D.Double((start0.getX() + start1.getX()) / 2, start0.getY());
|
||||||
|
Point inMirror = toScreen(UndersideMirror.createTransform(board).transform(middle, null));
|
||||||
|
|
||||||
|
presenter.mouseMoved(inMirror, false, false, false);
|
||||||
|
presenter.dragStarted(inMirror, java.awt.dnd.DnDConstants.ACTION_MOVE, false, false);
|
||||||
|
presenter.dragOver(new Point(inMirror.x + 100, inMirror.y + 100));
|
||||||
|
presenter.dragEnded(new Point(inMirror.x + 100, inMirror.y + 100));
|
||||||
|
|
||||||
|
Assert.assertTrue(resistor.getControlPoint(0).getX() > start0.getX());
|
||||||
|
Assert.assertTrue(resistor.getControlPoint(0).getY() < start0.getY());
|
||||||
|
Assert.assertEquals(resistor.getControlPoint(0).getY(), resistor.getControlPoint(1).getY());
|
||||||
|
Assert.assertEquals(start1.getX() - start0.getX(),
|
||||||
|
resistor.getControlPoint(1).getX() - resistor.getControlPoint(0).getX());
|
||||||
|
}
|
||||||
|
|
||||||
|
// a board reaching 200px past the component on every side, with its underside mirror below it;
|
||||||
|
// the component stays selected
|
||||||
|
private IBoard boardUnder(IDIYComponent<?> component) {
|
||||||
|
Point2D first = component.getControlPoint(0);
|
||||||
|
Point2D last = component.getControlPoint(component.getControlPointCount() - 1);
|
||||||
|
BlankBoard board = new BlankBoard();
|
||||||
|
board.setControlPoint(new Point2D.Double(first.getX() - 200, first.getY() - 200), 0);
|
||||||
|
board.setControlPoint(new Point2D.Double(last.getX() + 200, last.getY() + 200), 1);
|
||||||
|
board.setUndersideDisplay(BoardUndersideDisplay.BELOW);
|
||||||
|
presenter.getCurrentProject().getComponents().add(0, board);
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the inverse of the zoom and extra-space scaling the presenter applies to mouse points
|
||||||
|
private Point toScreen(Point2D modelPoint) {
|
||||||
|
double zoom = presenter.getZoomLevel();
|
||||||
|
double extraSpace = InMemoryConfigurationManager.getInstance()
|
||||||
|
.readBoolean(IPlugInPort.EXTRA_SPACE_KEY, true)
|
||||||
|
? presenter.getDrawingManager().getExtraSpace(presenter.getCurrentProject())
|
||||||
|
: 0;
|
||||||
|
return new Point((int) Math.round((modelPoint.getX() + extraSpace) * zoom),
|
||||||
|
(int) Math.round((modelPoint.getY() + extraSpace) * zoom));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShiftLocksAxisWhilePlacing() {
|
public void testShiftLocksAxisWhilePlacing() {
|
||||||
Map<String, List<ComponentType>> componentTypes = presenter.getComponentTypes();
|
Map<String, List<ComponentType>> componentTypes = presenter.getComponentTypes();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Gerber layers and the canvas shows it as a part on the far side of the board.
|
|||||||
|
|
||||||
Status: the core Gerber side is done, with tests: `IBoardSideComponent` exists and the export
|
Status: the core Gerber side is done, with tests: `IBoardSideComponent` exists and the export
|
||||||
sends a bottom-side part to the bottom layers, but no component implements it yet. Parts can be
|
sends a bottom-side part to the bottom layers, but no component implements it yet. Parts can be
|
||||||
selected through the Underside Display mirror. The next steps below remain.
|
selected, dragged and stretched through the Underside Display mirror. The next steps below remain.
|
||||||
|
|
||||||
## 1. Current state
|
## 1. Current state
|
||||||
|
|
||||||
@@ -98,14 +98,16 @@ order.
|
|||||||
the main view; locked and hidden parts are filtered out first, so a locked part under the mirror
|
the main view; locked and hidden parts are filtered out first, so a locked part under the mirror
|
||||||
does not block it. Clicking a part in the mirror selects the original, so the property editor,
|
does not block it. Clicking a part in the mirror selects the original, so the property editor,
|
||||||
delete, copy and the popup menu all work unchanged. Selection highlighting and the selected
|
delete, copy and the popup menu all work unchanged. Selection highlighting and the selected
|
||||||
control points are drawn on both copies. A drag still tests the main view only, and so do the
|
control points are drawn on both copies.
|
||||||
hand cursor and control-point hover, because they promise dragging; all three move to stage 2.
|
- **Stage 2: dragging in the mirror (done).** A drag that starts on a part in a mirror, or on a
|
||||||
- **Stage 2: dragging in the mirror.** Dragging, the hand cursor and control-point hover use the
|
control point of a selected part there, keeps that mirror's reflection in
|
||||||
mirror. A drag that starts in a mirror region reflects every
|
`Presenter.dragMirrorTx` and reflects every mouse point of the drag before it reaches the existing
|
||||||
subsequent mouse point before it reaches the existing drag code. Movement along the mirrored axis
|
drag code. Movement along the mirrored axis is therefore reversed, which is what the user sees,
|
||||||
is therefore reversed, which is what the user sees. Snapping applies to the reflected point. Moving
|
and snapping and the shift axis lock apply to the reflected point. Control-point hover
|
||||||
the board, or changing its Underside Offset, cancels nothing; the mirror simply follows.
|
(`Presenter.findControlPointsAt`) and the hand cursor look through the mirror when the main view
|
||||||
Control-point drags (stretching a trace) go through the same mapping.
|
has nothing. A drag that starts on empty mirror space still draws a selection rectangle in
|
||||||
|
screen space. Moving the board, or changing its Underside Offset, cancels nothing; the mirror
|
||||||
|
simply follows.
|
||||||
- **Stage 3: placing in the mirror.** A component instantiated with its first point in a mirror
|
- **Stage 3: placing in the mirror.** A component instantiated with its first point in a mirror
|
||||||
region is created at the reflected point. If it is an `IBoardSideComponent`, it is created with
|
region is created at the reflected point. If it is an `IBoardSideComponent`, it is created with
|
||||||
side `_1` (Bottom) and mirrored, as Flip to Other Side would do. A `PCBLayer` component is created on
|
side `_1` (Bottom) and mirrored, as Flip to Other Side would do. A `PCBLayer` component is created on
|
||||||
@@ -141,7 +143,9 @@ order.
|
|||||||
appears only in `.gbo`, mirrored, and in the right position.
|
appears only in `.gbo`, mirrored, and in the right position.
|
||||||
- `UndersideMirrorTest` covers the mirror region for each `BoardUndersideDisplay` direction and
|
- `UndersideMirrorTest` covers the mirror region for each `BoardUndersideDisplay` direction and
|
||||||
offset, that reflecting a point twice returns it, and which components a mirror shows.
|
offset, that reflecting a point twice returns it, and which components a mirror shows.
|
||||||
`DrawingManagerTest.testComponentFoundThroughUndersideMirror` covers the hit test.
|
`DrawingManagerTest.testComponentFoundThroughUndersideMirror` covers the hit test, and
|
||||||
|
`PresenterTests.testStretchThroughUndersideMirror` and `testDragThroughUndersideMirror` check
|
||||||
|
that a drag through a mirror below the board moves the part up on the board.
|
||||||
- In the app, with Underside Display set to each direction: select, drag and stretch a trace in
|
- In the app, with Underside Display set to each direction: select, drag and stretch a trace in
|
||||||
the mirror and confirm that the original follows correctly. Place a part in the mirror and confirm
|
the mirror and confirm that the original follows correctly. Place a part in the mirror and confirm
|
||||||
that it is bottom-side, mirrored, faded on the main view and solid in the mirror.
|
that it is bottom-side, mirrored, faded on the main view and solid in the mirror.
|
||||||
@@ -154,6 +158,5 @@ order.
|
|||||||
2. Wrap bottom-side painting in `startDrawingSide(getBoardSide())`.
|
2. Wrap bottom-side painting in `startDrawingSide(getBoardSide())`.
|
||||||
3. Add the Flip to Other Side action.
|
3. Add the Flip to Other Side action.
|
||||||
4. Split the silkscreen print-out by side.
|
4. Split the silkscreen print-out by side.
|
||||||
5. Mirror stage 2: dragging through the mirror.
|
5. Mirror stage 3: placing in the mirror, after Flip to Other Side exists.
|
||||||
6. Mirror stage 3: placing in the mirror, after Flip to Other Side exists.
|
6. Run the regression suite.
|
||||||
7. Run the regression suite.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user