mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-23 04:11:54 -04:00
Add mouse controller for resizing rect elements
To avoid having to guess which size is needed. When the mouse hovers near the border of a rectangle, the cursor changes for a resizing arrow and dragging it allows resizing the rectangle visually.
This commit is contained in:
parent
822a6f02a4
commit
d73cd785be
@ -13,6 +13,7 @@ import de.neemann.digital.core.io.InValue;
|
||||
import de.neemann.digital.core.io.Out;
|
||||
import de.neemann.digital.core.switching.Switch;
|
||||
import de.neemann.digital.draw.elements.*;
|
||||
import de.neemann.digital.draw.graphics.Polygon;
|
||||
import de.neemann.digital.draw.graphics.Vector;
|
||||
import de.neemann.digital.draw.graphics.*;
|
||||
import de.neemann.digital.draw.library.*;
|
||||
@ -23,6 +24,7 @@ import de.neemann.digital.draw.shapes.InputShape;
|
||||
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||
import de.neemann.digital.gui.Main;
|
||||
import de.neemann.digital.gui.Settings;
|
||||
import de.neemann.digital.gui.components.data.DummyElement;
|
||||
import de.neemann.digital.gui.components.modification.*;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
import de.neemann.digital.testing.TestCaseElement;
|
||||
@ -108,6 +110,8 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
private final MouseControllerMoveSelected mouseMoveSelected;
|
||||
private final MouseController mouseRun;
|
||||
private final MouseControllerInsertCopied mouseInsertList;
|
||||
private final MouseControllerResizeRect mouseResizeRect;
|
||||
private final Cursor normalCursor;
|
||||
private final Cursor moveCursor;
|
||||
private final ToolTipAction copyAction;
|
||||
private final ToolTipAction cutAction;
|
||||
@ -235,7 +239,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
}
|
||||
});
|
||||
|
||||
Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
|
||||
normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
|
||||
moveCursor = new Cursor(Cursor.MOVE_CURSOR);
|
||||
mouseNormal = new MouseControllerNormal(normalCursor);
|
||||
mouseInsertElement = new MouseControllerInsertElement(normalCursor);
|
||||
@ -248,6 +252,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
mouseSelect = new MouseControllerSelect(new Cursor(Cursor.CROSSHAIR_CURSOR));
|
||||
mouseMoveSelected = new MouseControllerMoveSelected(moveCursor);
|
||||
mouseRun = new MouseControllerRun(normalCursor);
|
||||
mouseResizeRect = new MouseControllerResizeRect(normalCursor);
|
||||
|
||||
undoManager = new UndoManager<>(new Circuit());
|
||||
addListener(this);
|
||||
@ -1657,6 +1662,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
private final class MouseControllerNormal extends MouseController {
|
||||
private Vector pos;
|
||||
private MouseEvent downButton;
|
||||
private VisualElement hoveredElement;
|
||||
|
||||
private MouseControllerNormal(Cursor cursor) {
|
||||
super(cursor);
|
||||
@ -1666,6 +1672,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
void activate() {
|
||||
super.activate();
|
||||
pos = null;
|
||||
hoveredElement = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1705,18 +1712,34 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
pos = getPosVector(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
void moved(MouseEvent e) {
|
||||
Vector p = getPosVector(e);
|
||||
hoveredElement = getCircuit().getElementAt(p, false);
|
||||
if (!isLocked() && hoveredElement != null &&
|
||||
hoveredElement.equalsDescription(DummyElement.RECTDESCRIPTION)) {
|
||||
setCursorForResizingRect(hoveredElement, p);
|
||||
} else {
|
||||
setCursor(normalCursor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean dragged(MouseEvent e) {
|
||||
if (mouse.isPrimaryClick(downButton)) {
|
||||
Vector p = getPosVector(e);
|
||||
if (pos == null)
|
||||
pos = p;
|
||||
mouseSelect.activate(pos, p);
|
||||
if (!isLocked() && hoveredElement != null &&
|
||||
hoveredElement.equalsDescription(DummyElement.RECTDESCRIPTION)) {
|
||||
mouseResizeRect.activate(hoveredElement, pos);
|
||||
} else {
|
||||
mouseSelect.activate(pos, p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return !mouse.isSecondaryClick(downButton);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class MouseControllerInsertElement extends MouseController {
|
||||
@ -2563,6 +2586,137 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
}
|
||||
}
|
||||
|
||||
private final class MouseControllerResizeRect extends MouseController {
|
||||
private VisualElement element;
|
||||
private Vector startPos;
|
||||
|
||||
private int rectX;
|
||||
private int rectY;
|
||||
private int rectWidth;
|
||||
private int rectHeight;
|
||||
|
||||
private boolean changeNorth;
|
||||
private boolean changeSouth;
|
||||
private boolean changeWest;
|
||||
private boolean changeEast;
|
||||
|
||||
private MouseControllerResizeRect(Cursor cursor) {
|
||||
super(cursor);
|
||||
}
|
||||
|
||||
void activate(VisualElement element, Vector pos) {
|
||||
super.activate();
|
||||
this.element = element;
|
||||
this.startPos = raster(pos);
|
||||
|
||||
// Get current rectangle attributes.
|
||||
rectX = element.getPos().x;
|
||||
rectY = element.getPos().y;
|
||||
rectWidth = element.getElementAttributes().get(Keys.RECT_WIDTH) * SIZE;
|
||||
rectHeight = element.getElementAttributes().get(Keys.RECT_HEIGHT) * SIZE;
|
||||
|
||||
// Find which directions are being changed.
|
||||
Vector posInRect = raster(pos.sub(element.getPos()));
|
||||
changeNorth = posInRect.y <= 0;
|
||||
changeSouth = posInRect.y == rectHeight;
|
||||
changeEast = posInRect.x == 0;
|
||||
changeWest = posInRect.x == rectWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean dragged(MouseEvent e) {
|
||||
ElementAttributes attributes = element.getElementAttributes();
|
||||
Vector d = raster(getPosVector(e)).sub(startPos);
|
||||
|
||||
if (changeNorth) {
|
||||
rectY = element.getPos().y + d.y;
|
||||
rectHeight = attributes.get(Keys.RECT_HEIGHT) * SIZE - d.y;
|
||||
} else if (changeSouth) {
|
||||
rectHeight = attributes.get(Keys.RECT_HEIGHT) * SIZE + d.y;
|
||||
}
|
||||
if (changeEast) {
|
||||
rectX = element.getPos().x + d.x;
|
||||
rectWidth = attributes.get(Keys.RECT_WIDTH) * SIZE - d.x;
|
||||
} else if (changeWest) {
|
||||
rectWidth = attributes.get(Keys.RECT_WIDTH) * SIZE + d.x;
|
||||
}
|
||||
|
||||
repaint();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void released(MouseEvent e) {
|
||||
// Flip rectangle vertically or horizontally if needed.
|
||||
if (rectWidth < 0) {
|
||||
rectWidth = -rectWidth;
|
||||
rectX -= rectWidth;
|
||||
}
|
||||
if (rectHeight < 0) {
|
||||
rectHeight = -rectHeight;
|
||||
rectY -= rectHeight;
|
||||
}
|
||||
|
||||
// Enforce rectangle min dimensions.
|
||||
rectWidth = Math.max(rectWidth, Keys.RECT_WIDTH.getMin() * SIZE);
|
||||
rectHeight = Math.max(rectHeight, Keys.RECT_HEIGHT.getMin() * SIZE);
|
||||
|
||||
ElementAttributes newAttributes = new ElementAttributes(element.getElementAttributes())
|
||||
.set(Keys.RECT_WIDTH, rectWidth / SIZE)
|
||||
.set(Keys.RECT_HEIGHT, rectHeight / SIZE);
|
||||
modify(new Modifications.Builder<Circuit>(Lang.get("mod_resizeRect"))
|
||||
.add(new ModifyAttributes(element, newAttributes))
|
||||
.add(new ModifyMoveAndRotElement(element, new Vector(rectX, rectY), element.getRotate()))
|
||||
.build());
|
||||
|
||||
mouseNormal.activate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic gr) {
|
||||
gr.drawPolygon(new Polygon(true)
|
||||
.add(rectX, rectY)
|
||||
.add(rectX + rectWidth, rectY)
|
||||
.add(rectX + rectWidth, rectY + rectHeight)
|
||||
.add(rectX, rectY + rectHeight), Style.HIGHLIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the cursor for when the mouse hovers nears the border of a rectangle.
|
||||
*
|
||||
* @param rect The rectangle element.
|
||||
* @param pos Current mouse position in circuit coordinates.
|
||||
*/
|
||||
public void setCursorForResizingRect(VisualElement rect, Vector pos) {
|
||||
Vector posInRect = raster(pos.sub(rect.getPos()));
|
||||
int width = rect.getElementAttributes().get(Keys.RECT_WIDTH) * SIZE;
|
||||
int height = rect.getElementAttributes().get(Keys.RECT_HEIGHT) * SIZE;
|
||||
int cursor;
|
||||
if (posInRect.x == width) {
|
||||
if (posInRect.y <= 0) {
|
||||
cursor = Cursor.NE_RESIZE_CURSOR;
|
||||
} else if (posInRect.y == height) {
|
||||
cursor = Cursor.SE_RESIZE_CURSOR;
|
||||
} else {
|
||||
cursor = Cursor.E_RESIZE_CURSOR;
|
||||
}
|
||||
} else if (posInRect.x == 0) {
|
||||
if (posInRect.y <= 0) {
|
||||
cursor = Cursor.NW_RESIZE_CURSOR;
|
||||
} else if (posInRect.y == height) {
|
||||
cursor = Cursor.SW_RESIZE_CURSOR;
|
||||
} else {
|
||||
cursor = Cursor.W_RESIZE_CURSOR;
|
||||
}
|
||||
} else if (posInRect.y <= 0) {
|
||||
cursor = Cursor.N_RESIZE_CURSOR;
|
||||
} else {
|
||||
cursor = Cursor.S_RESIZE_CURSOR;
|
||||
}
|
||||
setCursor(new Cursor(cursor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate a wizard
|
||||
*
|
||||
|
@ -1655,6 +1655,7 @@
|
||||
<string name="mod_groupEdit">Modified attributes of selected components.</string>
|
||||
<string name="mod_splitWire">Splits a single wire into two wires.</string>
|
||||
<string name="mod_modifiedByRunningModel">Changes made by the running simulation.</string>
|
||||
<string name="mod_resizeRect">Resizes and moves a rectangle.</string>
|
||||
|
||||
<string name="lib_Logic">Logic</string>
|
||||
<string name="lib_arithmetic">Arithmetic</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user