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 BomPolicy bomPolicy;
|
||||
private boolean autoEdit;
|
||||
private boolean rotatable;
|
||||
|
||||
public ComponentType(String name, String description, CreationMethod creationMethod,
|
||||
String category, String namePrefix, String author, Icon icon,
|
||||
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean flexibleZOrder,
|
||||
boolean stretchable, BomPolicy bomPolicy, boolean autoEdit) {
|
||||
boolean stretchable, BomPolicy bomPolicy, boolean autoEdit, boolean rotatable) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -47,6 +48,7 @@ public class ComponentType {
|
||||
this.stretchable = stretchable;
|
||||
this.bomPolicy = bomPolicy;
|
||||
this.autoEdit = autoEdit;
|
||||
this.rotatable = rotatable;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -101,6 +103,10 @@ public class ComponentType {
|
||||
return autoEdit;
|
||||
}
|
||||
|
||||
public boolean isRotatable() {
|
||||
return rotatable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
||||
+10
-2
@@ -34,8 +34,8 @@ public interface ISelectionProcessor {
|
||||
List<IDIYComponent<?>> findComponentsAt(Point point);
|
||||
|
||||
/**
|
||||
* Expands the current selection to include surrounding components.
|
||||
* Options are controlled with <code>expansionMode</code> flag.
|
||||
* Expands the current selection to include surrounding components. Options
|
||||
* are controlled with <code>expansionMode</code> flag.
|
||||
*
|
||||
* @param expansionMode
|
||||
*/
|
||||
@@ -45,4 +45,12 @@ public interface ISelectionProcessor {
|
||||
* Selects all components in the project.
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
BomPolicy bomPolicy;
|
||||
boolean autoEdit;
|
||||
boolean rotatable;
|
||||
if (clazz.isAnnotationPresent(ComponentDescriptor.class)) {
|
||||
ComponentDescriptor annotation = clazz.getAnnotation(ComponentDescriptor.class);
|
||||
name = annotation.name();
|
||||
@@ -82,6 +83,7 @@ public class ComponentProcessor {
|
||||
stretchable = annotation.stretchable();
|
||||
bomPolicy = annotation.bomPolicy();
|
||||
autoEdit = annotation.autoEdit();
|
||||
rotatable = annotation.rotatable();
|
||||
} else {
|
||||
name = clazz.getSimpleName();
|
||||
description = "";
|
||||
@@ -94,6 +96,7 @@ public class ComponentProcessor {
|
||||
stretchable = true;
|
||||
bomPolicy = BomPolicy.SHOW_ALL_NAMES;
|
||||
autoEdit = true;
|
||||
rotatable = true;
|
||||
}
|
||||
icon = null;
|
||||
// Draw component icon.
|
||||
@@ -115,7 +118,7 @@ public class ComponentProcessor {
|
||||
}
|
||||
ComponentType componentType = new ComponentType(name, description, creationMethod,
|
||||
category, namePrefix, author, icon, clazz, zOrder, flexibleZOrder, stretchable,
|
||||
bomPolicy, autoEdit);
|
||||
bomPolicy, autoEdit, rotatable);
|
||||
componentTypeMap.put(clazz.getName(), componentType);
|
||||
return componentType;
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class InstantiationManager {
|
||||
private static final ComponentType clipboardType = new ComponentType(
|
||||
"Clipboard contents", "Components from the clipboard",
|
||||
CreationMethod.SINGLE_CLICK, "Multi", "", "", null, null, 0, false,
|
||||
false, null, false);
|
||||
false, null, false, true);
|
||||
|
||||
public InstantiationManager() {
|
||||
}
|
||||
|
||||
+152
-35
@@ -6,6 +6,7 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.BufferedInputStream;
|
||||
@@ -40,6 +41,8 @@ import org.diylc.common.IComponentFiler;
|
||||
import org.diylc.common.IKeyProcessor;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.Orientation;
|
||||
import org.diylc.common.OrientationHV;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.components.connectivity.SolderPad;
|
||||
import org.diylc.core.ExpansionMode;
|
||||
@@ -625,6 +628,28 @@ public class Presenter implements IPlugInPort {
|
||||
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.
|
||||
boolean sticky = ConfigurationManager.getInstance().readBoolean(
|
||||
IPlugInPort.STICKY_POINTS_KEY, true);
|
||||
@@ -636,12 +661,6 @@ public class Presenter implements IPlugInPort {
|
||||
includeStuckComponents(controlPointMap);
|
||||
}
|
||||
|
||||
boolean snapToGrid = ConfigurationManager.getInstance().readBoolean(
|
||||
IPlugInPort.SNAP_TO_GRID_KEY, true);
|
||||
if (shiftDown) {
|
||||
snapToGrid = !snapToGrid;
|
||||
}
|
||||
|
||||
int d;
|
||||
if (snapToGrid) {
|
||||
d = (int) currentProject.getGridSpacing().convertToPixels();
|
||||
@@ -1025,35 +1044,6 @@ public class Presenter implements IPlugInPort {
|
||||
int height = (int) currentProject.getHeight().convertToPixels();
|
||||
|
||||
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
|
||||
.entrySet().iterator().next();
|
||||
|
||||
@@ -1133,6 +1123,133 @@ public class Presenter implements IPlugInPort {
|
||||
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
|
||||
public void dragEnded(Point point) {
|
||||
LOG.debug(String.format("dragEnded(%s)", point));
|
||||
|
||||
Reference in New Issue
Block a user