mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-12 02:02:16 +10:00
Ability to rotate selection
This commit is contained in:
Binary file not shown.
+7
-1
@@ -28,11 +28,12 @@ public class ComponentType {
|
|||||||
private boolean stretchable;
|
private boolean stretchable;
|
||||||
private BomPolicy bomPolicy;
|
private BomPolicy bomPolicy;
|
||||||
private boolean autoEdit;
|
private boolean autoEdit;
|
||||||
|
private boolean rotatable;
|
||||||
|
|
||||||
public ComponentType(String name, String description, CreationMethod creationMethod,
|
public ComponentType(String name, String description, CreationMethod creationMethod,
|
||||||
String category, String namePrefix, String author, Icon icon,
|
String category, String namePrefix, String author, Icon icon,
|
||||||
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean flexibleZOrder,
|
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean flexibleZOrder,
|
||||||
boolean stretchable, BomPolicy bomPolicy, boolean autoEdit) {
|
boolean stretchable, BomPolicy bomPolicy, boolean autoEdit, boolean rotatable) {
|
||||||
super();
|
super();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
@@ -47,6 +48,7 @@ public class ComponentType {
|
|||||||
this.stretchable = stretchable;
|
this.stretchable = stretchable;
|
||||||
this.bomPolicy = bomPolicy;
|
this.bomPolicy = bomPolicy;
|
||||||
this.autoEdit = autoEdit;
|
this.autoEdit = autoEdit;
|
||||||
|
this.rotatable = rotatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -101,6 +103,10 @@ public class ComponentType {
|
|||||||
return autoEdit;
|
return autoEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRotatable() {
|
||||||
|
return rotatable;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
+10
-2
@@ -34,8 +34,8 @@ public interface ISelectionProcessor {
|
|||||||
List<IDIYComponent<?>> findComponentsAt(Point point);
|
List<IDIYComponent<?>> findComponentsAt(Point point);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands the current selection to include surrounding components.
|
* Expands the current selection to include surrounding components. Options
|
||||||
* Options are controlled with <code>expansionMode</code> flag.
|
* are controlled with <code>expansionMode</code> flag.
|
||||||
*
|
*
|
||||||
* @param expansionMode
|
* @param expansionMode
|
||||||
*/
|
*/
|
||||||
@@ -45,4 +45,12 @@ public interface ISelectionProcessor {
|
|||||||
* Selects all components in the project.
|
* Selects all components in the project.
|
||||||
*/
|
*/
|
||||||
void selectAll();
|
void selectAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates selection for 90 degrees.
|
||||||
|
*
|
||||||
|
* @param direction
|
||||||
|
* 1 for clockwise, -1 for counter-clockwise
|
||||||
|
*/
|
||||||
|
void rotateSelection(int direction);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -77,4 +77,10 @@ public @interface ComponentDescriptor {
|
|||||||
*/
|
*/
|
||||||
boolean autoEdit() default true;
|
boolean autoEdit() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if component may be rotated, false otherwise
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean rotatable() default true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -69,6 +69,7 @@ public class ComponentProcessor {
|
|||||||
boolean stretchable;
|
boolean stretchable;
|
||||||
BomPolicy bomPolicy;
|
BomPolicy bomPolicy;
|
||||||
boolean autoEdit;
|
boolean autoEdit;
|
||||||
|
boolean rotatable;
|
||||||
if (clazz.isAnnotationPresent(ComponentDescriptor.class)) {
|
if (clazz.isAnnotationPresent(ComponentDescriptor.class)) {
|
||||||
ComponentDescriptor annotation = clazz.getAnnotation(ComponentDescriptor.class);
|
ComponentDescriptor annotation = clazz.getAnnotation(ComponentDescriptor.class);
|
||||||
name = annotation.name();
|
name = annotation.name();
|
||||||
@@ -82,6 +83,7 @@ public class ComponentProcessor {
|
|||||||
stretchable = annotation.stretchable();
|
stretchable = annotation.stretchable();
|
||||||
bomPolicy = annotation.bomPolicy();
|
bomPolicy = annotation.bomPolicy();
|
||||||
autoEdit = annotation.autoEdit();
|
autoEdit = annotation.autoEdit();
|
||||||
|
rotatable = annotation.rotatable();
|
||||||
} else {
|
} else {
|
||||||
name = clazz.getSimpleName();
|
name = clazz.getSimpleName();
|
||||||
description = "";
|
description = "";
|
||||||
@@ -94,6 +96,7 @@ public class ComponentProcessor {
|
|||||||
stretchable = true;
|
stretchable = true;
|
||||||
bomPolicy = BomPolicy.SHOW_ALL_NAMES;
|
bomPolicy = BomPolicy.SHOW_ALL_NAMES;
|
||||||
autoEdit = true;
|
autoEdit = true;
|
||||||
|
rotatable = true;
|
||||||
}
|
}
|
||||||
icon = null;
|
icon = null;
|
||||||
// Draw component icon.
|
// Draw component icon.
|
||||||
@@ -115,7 +118,7 @@ public class ComponentProcessor {
|
|||||||
}
|
}
|
||||||
ComponentType componentType = new ComponentType(name, description, creationMethod,
|
ComponentType componentType = new ComponentType(name, description, creationMethod,
|
||||||
category, namePrefix, author, icon, clazz, zOrder, flexibleZOrder, stretchable,
|
category, namePrefix, author, icon, clazz, zOrder, flexibleZOrder, stretchable,
|
||||||
bomPolicy, autoEdit);
|
bomPolicy, autoEdit, rotatable);
|
||||||
componentTypeMap.put(clazz.getName(), componentType);
|
componentTypeMap.put(clazz.getName(), componentType);
|
||||||
return componentType;
|
return componentType;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ public class InstantiationManager {
|
|||||||
private static final ComponentType clipboardType = new ComponentType(
|
private static final ComponentType clipboardType = new ComponentType(
|
||||||
"Clipboard contents", "Components from the clipboard",
|
"Clipboard contents", "Components from the clipboard",
|
||||||
CreationMethod.SINGLE_CLICK, "Multi", "", "", null, null, 0, false,
|
CreationMethod.SINGLE_CLICK, "Multi", "", "", null, null, 0, false,
|
||||||
false, null, false);
|
false, null, false, true);
|
||||||
|
|
||||||
public InstantiationManager() {
|
public InstantiationManager() {
|
||||||
}
|
}
|
||||||
|
|||||||
+152
-35
@@ -6,6 +6,7 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.dnd.DnDConstants;
|
import java.awt.dnd.DnDConstants;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Area;
|
import java.awt.geom.Area;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@@ -40,6 +41,8 @@ import org.diylc.common.IComponentFiler;
|
|||||||
import org.diylc.common.IKeyProcessor;
|
import org.diylc.common.IKeyProcessor;
|
||||||
import org.diylc.common.IPlugIn;
|
import org.diylc.common.IPlugIn;
|
||||||
import org.diylc.common.IPlugInPort;
|
import org.diylc.common.IPlugInPort;
|
||||||
|
import org.diylc.common.Orientation;
|
||||||
|
import org.diylc.common.OrientationHV;
|
||||||
import org.diylc.common.PropertyWrapper;
|
import org.diylc.common.PropertyWrapper;
|
||||||
import org.diylc.components.connectivity.SolderPad;
|
import org.diylc.components.connectivity.SolderPad;
|
||||||
import org.diylc.core.ExpansionMode;
|
import org.diylc.core.ExpansionMode;
|
||||||
@@ -625,6 +628,28 @@ public class Presenter implements IPlugInPort {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean snapToGrid = ConfigurationManager.getInstance().readBoolean(
|
||||||
|
IPlugInPort.SNAP_TO_GRID_KEY, true);
|
||||||
|
if (shiftDown) {
|
||||||
|
snapToGrid = !snapToGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (altDown) {
|
||||||
|
Project oldProject = null;
|
||||||
|
if (key == IKeyProcessor.VK_RIGHT) {
|
||||||
|
oldProject = currentProject.clone();
|
||||||
|
rotateComponents(this.selectedComponents, 1, snapToGrid);
|
||||||
|
} else if (key == IKeyProcessor.VK_LEFT) {
|
||||||
|
oldProject = currentProject.clone();
|
||||||
|
rotateComponents(this.selectedComponents, -1, snapToGrid);
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
|
||||||
|
oldProject, currentProject.clone(), "Rotate Selection");
|
||||||
|
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Expand control points to include all stuck components.
|
// Expand control points to include all stuck components.
|
||||||
boolean sticky = ConfigurationManager.getInstance().readBoolean(
|
boolean sticky = ConfigurationManager.getInstance().readBoolean(
|
||||||
IPlugInPort.STICKY_POINTS_KEY, true);
|
IPlugInPort.STICKY_POINTS_KEY, true);
|
||||||
@@ -636,12 +661,6 @@ public class Presenter implements IPlugInPort {
|
|||||||
includeStuckComponents(controlPointMap);
|
includeStuckComponents(controlPointMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean snapToGrid = ConfigurationManager.getInstance().readBoolean(
|
|
||||||
IPlugInPort.SNAP_TO_GRID_KEY, true);
|
|
||||||
if (shiftDown) {
|
|
||||||
snapToGrid = !snapToGrid;
|
|
||||||
}
|
|
||||||
|
|
||||||
int d;
|
int d;
|
||||||
if (snapToGrid) {
|
if (snapToGrid) {
|
||||||
d = (int) currentProject.getGridSpacing().convertToPixels();
|
d = (int) currentProject.getGridSpacing().convertToPixels();
|
||||||
@@ -1025,35 +1044,6 @@ public class Presenter implements IPlugInPort {
|
|||||||
int height = (int) currentProject.getHeight().convertToPixels();
|
int height = (int) currentProject.getHeight().convertToPixels();
|
||||||
|
|
||||||
if (controlPointMap.size() == 1) {
|
if (controlPointMap.size() == 1) {
|
||||||
// Determine how much we should move the components by trying to
|
|
||||||
// move the center point of the affected rectangle to preserve
|
|
||||||
// spacing.
|
|
||||||
// int minX = Integer.MAX_VALUE;
|
|
||||||
// int minY = Integer.MAX_VALUE;
|
|
||||||
// int maxX = Integer.MIN_VALUE;
|
|
||||||
// int maxY = Integer.MIN_VALUE;
|
|
||||||
// for (Map.Entry<IDIYComponent<?>, Set<Integer>> entry :
|
|
||||||
// controlPointMap
|
|
||||||
// .entrySet()) {
|
|
||||||
// for (int i : entry.getValue()) {
|
|
||||||
// Point p = entry.getKey().getControlPoint(i);
|
|
||||||
// if (minX > p.x) {
|
|
||||||
// minX = p.x;
|
|
||||||
// }
|
|
||||||
// if (maxX < p.x) {
|
|
||||||
// maxX = p.x;
|
|
||||||
// }
|
|
||||||
// if (minY > p.y) {
|
|
||||||
// minY = p.y;
|
|
||||||
// }
|
|
||||||
// if (maxY < p.y) {
|
|
||||||
// maxY = p.y;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// int centerX = (maxX + minX) / 2;
|
|
||||||
// int centerY = (maxY + minY) / 2;
|
|
||||||
|
|
||||||
Map.Entry<IDIYComponent<?>, Set<Integer>> entry = controlPointMap
|
Map.Entry<IDIYComponent<?>, Set<Integer>> entry = controlPointMap
|
||||||
.entrySet().iterator().next();
|
.entrySet().iterator().next();
|
||||||
|
|
||||||
@@ -1133,6 +1123,133 @@ public class Presenter implements IPlugInPort {
|
|||||||
return new Point(actualDx, actualDy);
|
return new Point(actualDx, actualDy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rotateSelection(int direction) {
|
||||||
|
if (!selectedComponents.isEmpty()) {
|
||||||
|
Project oldProject = currentProject.clone();
|
||||||
|
rotateComponents(this.selectedComponents, direction, isSnapToGrid());
|
||||||
|
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
|
||||||
|
oldProject, currentProject.clone(), "Rotate Selection");
|
||||||
|
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param direction
|
||||||
|
* 1 for clockwise, -1 for counter-clockwise
|
||||||
|
*/
|
||||||
|
private void rotateComponents(List<IDIYComponent<?>> components,
|
||||||
|
int direction, boolean snapToGrid) {
|
||||||
|
Point center = getCenterOf(components, snapToGrid);
|
||||||
|
|
||||||
|
AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2
|
||||||
|
* direction, center.x, center.y);
|
||||||
|
|
||||||
|
// Update all points to new location.
|
||||||
|
for (IDIYComponent<?> component : components) {
|
||||||
|
drawingManager.invalidateComponent(component);
|
||||||
|
ComponentType type = ComponentProcessor.getInstance()
|
||||||
|
.extractComponentTypeFrom(
|
||||||
|
(Class<? extends IDIYComponent<?>>) component
|
||||||
|
.getClass());
|
||||||
|
if (type.isRotatable()) {
|
||||||
|
for (int index = 0; index < component.getControlPointCount(); index++) {
|
||||||
|
Point p = new Point(component.getControlPoint(index));
|
||||||
|
rotate.transform(p, p);
|
||||||
|
component.setControlPoint(p, index);
|
||||||
|
}
|
||||||
|
// If component has orientation, change it too
|
||||||
|
List<PropertyWrapper> newProperties = ComponentProcessor
|
||||||
|
.getInstance().extractProperties(component.getClass());
|
||||||
|
for (PropertyWrapper property : newProperties) {
|
||||||
|
if (property.getType() == Orientation.class) {
|
||||||
|
try {
|
||||||
|
property.readFrom(component);
|
||||||
|
Orientation orientation = (Orientation) property
|
||||||
|
.getValue();
|
||||||
|
Orientation[] values = Orientation.values();
|
||||||
|
int newIndex = orientation.ordinal() + direction;
|
||||||
|
if (newIndex < 0)
|
||||||
|
newIndex = values.length - 1;
|
||||||
|
else if (newIndex >= values.length)
|
||||||
|
newIndex = 0;
|
||||||
|
property.setValue(values[newIndex]);
|
||||||
|
property.writeTo(component);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(
|
||||||
|
"Could not change component orientation for "
|
||||||
|
+ component.getName(), e);
|
||||||
|
}
|
||||||
|
} else if (property.getType() == OrientationHV.class) {
|
||||||
|
try {
|
||||||
|
property.readFrom(component);
|
||||||
|
OrientationHV orientation = (OrientationHV) property
|
||||||
|
.getValue();
|
||||||
|
property
|
||||||
|
.setValue(OrientationHV.values()[1 - orientation
|
||||||
|
.ordinal()]);
|
||||||
|
property.writeTo(component);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(
|
||||||
|
"Could not change component orientation for "
|
||||||
|
+ component.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Non-rotatable
|
||||||
|
Point componentCenter = getCenterOf(Arrays
|
||||||
|
.asList(new IDIYComponent<?>[] { component }), false);
|
||||||
|
Point rotatedComponentCenter = new Point();
|
||||||
|
rotate.transform(componentCenter, rotatedComponentCenter);
|
||||||
|
for (int index = 0; index < component.getControlPointCount(); index++) {
|
||||||
|
Point p = new Point(component.getControlPoint(index));
|
||||||
|
p.translate(rotatedComponentCenter.x - componentCenter.x,
|
||||||
|
rotatedComponentCenter.y - componentCenter.y);
|
||||||
|
component.setControlPoint(p, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point getCenterOf(List<IDIYComponent<?>> components,
|
||||||
|
boolean snapToGrid) {
|
||||||
|
// Determine center of rotation
|
||||||
|
int minX = Integer.MAX_VALUE;
|
||||||
|
int minY = Integer.MAX_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE;
|
||||||
|
int maxY = Integer.MIN_VALUE;
|
||||||
|
for (IDIYComponent<?> component : components) {
|
||||||
|
for (int i = 0; i < component.getControlPointCount(); i++) {
|
||||||
|
Point p = component.getControlPoint(i);
|
||||||
|
if (minX > p.x) {
|
||||||
|
minX = p.x;
|
||||||
|
}
|
||||||
|
if (maxX < p.x) {
|
||||||
|
maxX = p.x;
|
||||||
|
}
|
||||||
|
if (minY > p.y) {
|
||||||
|
minY = p.y;
|
||||||
|
}
|
||||||
|
if (maxY < p.y) {
|
||||||
|
maxY = p.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int centerX = (maxX + minX) / 2;
|
||||||
|
int centerY = (maxY + minY) / 2;
|
||||||
|
|
||||||
|
if (snapToGrid) {
|
||||||
|
CalcUtils
|
||||||
|
.roundToGrid(centerX, this.currentProject.getGridSpacing());
|
||||||
|
CalcUtils
|
||||||
|
.roundToGrid(centerY, this.currentProject.getGridSpacing());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Point(centerX, centerY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dragEnded(Point point) {
|
public void dragEnded(Point point) {
|
||||||
LOG.debug(String.format("dragEnded(%s)", point));
|
LOG.debug(String.format("dragEnded(%s)", point));
|
||||||
|
|||||||
Reference in New Issue
Block a user