refactored instantiation code out the presenter

This commit is contained in:
bancika
2011-01-20 21:19:32 +00:00
parent 2309e80edc
commit a315bc06fa
6 changed files with 261 additions and 181 deletions
@@ -331,7 +331,7 @@ public interface IPlugInPort {
* Sets the new component slot. Specified component type will be used to * Sets the new component slot. Specified component type will be used to
* instantiate new component. * instantiate new component.
*/ */
void setNewComponentSlot(ComponentType componentType); void setNewComponentTypeSlot(ComponentType componentType);
/** /**
* Changes default size notation, true for metric, false for imperial. * Changes default size notation, true for metric, false for imperial.
@@ -91,7 +91,7 @@ class CanvasPanel extends JComponent implements Autoscroll {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
CanvasPanel.this.plugInPort.setNewComponentSlot(null); CanvasPanel.this.plugInPort.setNewComponentTypeSlot(null);
} }
}); });
} }
@@ -44,7 +44,7 @@ class ComponentButton extends JButton {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// plugInPort.setCursorIcon(componentType.getIcon()); // plugInPort.setCursorIcon(componentType.getIcon());
plugInPort.setNewComponentSlot(componentType); plugInPort.setNewComponentTypeSlot(componentType);
// try { // try {
// plugInPort.instantiateComponent(componentType // plugInPort.instantiateComponent(componentType
// .getComponentInstanceClass(), null); // .getComponentInstanceClass(), null);
@@ -0,0 +1,25 @@
package org.diylc.presenter;
import java.awt.Point;
import org.diylc.core.measures.Size;
public class CalcUtils {
/**
* Rounds the number to the closest grid line.
*
* @param x
* @return
*/
public static int roundToGrid(int x, Size gridSpacing) {
int grid = gridSpacing.convertToPixels();
return (Math.round(1f * x / grid) * grid);
}
public static void snapPointToGrid(Point point, Size gridSpacing) {
int x = roundToGrid(point.x, gridSpacing);
int y = roundToGrid(point.y, gridSpacing);
point.setLocation(x, y);
}
}
@@ -0,0 +1,182 @@
package org.diylc.presenter;
import java.awt.Point;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.apache.log4j.Logger;
import org.diylc.common.ComponentType;
import org.diylc.common.PropertyWrapper;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.core.measures.Size;
import com.diyfever.gui.miscutils.ConfigurationManager;
import com.rits.cloning.Cloner;
/**
* Manages component instantiation.
*
* @author Branislav Stojkovic
*/
public class InstantiationManager {
private static final Logger LOG = Logger.getLogger(InstantiationManager.class);
private Cloner cloner;
private ComponentType componentTypeSlot;
private IDIYComponent<?> componentSlot;
private Point firstControlPoint;
private Point potentialControlPoint;
public InstantiationManager() {
// TODO Auto-generated constructor stub
}
public ComponentType getComponentTypeSlot() {
return componentTypeSlot;
}
public IDIYComponent<?> getComponentSlot() {
return componentSlot;
}
public Point getFirstControlPoint() {
return firstControlPoint;
}
public Point getPotentialControlPoint() {
return potentialControlPoint;
}
public void setComponentTypeSlot(ComponentType componentTypeSlot, Project currentProject)
throws Exception {
this.componentTypeSlot = componentTypeSlot;
if (componentTypeSlot == null) {
this.componentSlot = null;
} else {
switch (componentTypeSlot.getCreationMethod()) {
case POINT_BY_POINT:
this.componentSlot = null;
break;
case SINGLE_CLICK:
this.componentSlot = instantiateComponent(componentTypeSlot, new Point(0, 0),
currentProject);
break;
}
}
this.firstControlPoint = null;
this.potentialControlPoint = null;
}
public void instatiatePointByPoint(Point scaledPoint, Project currentProject) throws Exception {
firstControlPoint = scaledPoint;
componentSlot = instantiateComponent(componentTypeSlot, firstControlPoint, currentProject);
// Set the other control point to the same location, we'll
// move it later when mouse moves.
componentSlot.setControlPoint(firstControlPoint, 0);
componentSlot.setControlPoint(firstControlPoint, 1);
}
public void updatePointByPoint(Point scaledPoint) {
potentialControlPoint = scaledPoint;
if (componentSlot != null) {
componentSlot.setControlPoint(scaledPoint, 1);
}
}
public void updateSingleClick(Point scaledPoint, boolean snapToGrid, Size gridSpacing) {
if (potentialControlPoint == null) {
potentialControlPoint = new Point(0, 0);
}
int dx = scaledPoint.x - potentialControlPoint.x;
int dy = scaledPoint.y - potentialControlPoint.y;
if (snapToGrid) {
dx = CalcUtils.roundToGrid(dx, gridSpacing);
dy = CalcUtils.roundToGrid(dy, gridSpacing);
}
// Only repaint if there's an actual change.
if (dx == 0 && dy == 0) {
return;
}
potentialControlPoint.translate(dx, dy);
if (componentSlot == null) {
LOG.error("Component slot should not be null!");
} else {
Point p = new Point();
for (int i = 0; i < componentSlot.getControlPointCount(); i++) {
p.setLocation(componentSlot.getControlPoint(i));
p.translate(dx, dy);
componentSlot.setControlPoint(p, i);
}
}
}
public IDIYComponent<?> instantiateComponent(ComponentType componentType, Point point,
Project currentProject) throws Exception {
LOG.info("Instatiating component of type: " + componentType.getInstanceClass().getName());
// Instantiate the component.
IDIYComponent<?> component = componentType.getInstanceClass().newInstance();
// Find the next available componentName for the component.
int i = 0;
boolean exists = true;
while (exists) {
i++;
String name = componentType.getNamePrefix() + i;
exists = false;
for (IDIYComponent<?> c : currentProject.getComponents()) {
if (c.getName().equals(name)) {
exists = true;
break;
}
}
}
component.setName(componentType.getNamePrefix() + i);
// Translate them to the desired location.
if (point != null) {
for (int j = 0; j < component.getControlPointCount(); j++) {
Point controlPoint = new Point(component.getControlPoint(j));
controlPoint.translate(point.x, point.y);
// snapPointToGrid(controlPoint);
component.setControlPoint(controlPoint, j);
}
}
setDefaultProperties(component);
return component;
}
/**
* Finds any properties that have default values and injects default values.
* Typically it should be used for {@link IDIYComponent} and {@link Project}
* objects.
*
* @param object
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public void setDefaultProperties(Object object) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
// Extract properties.
List<PropertyWrapper> properties = ComponentProcessor.getInstance().extractProperties(
object.getClass());
// Override with default values if available.
for (PropertyWrapper property : properties) {
Object defaultValue = ConfigurationManager.getInstance().readObject(
Presenter.DEFAULTS_KEY_PREFIX + object.getClass().getName() + ":"
+ property.getName(), null);
if (defaultValue != null) {
property.setValue(cloner.deepClone(defaultValue));
property.writeTo(object);
}
}
}
}
@@ -7,7 +7,6 @@ import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -78,6 +77,7 @@ public class Presenter implements IPlugInPort {
private Cloner cloner; private Cloner cloner;
private DrawingManager drawingManager; private DrawingManager drawingManager;
private ProjectFileManager projectFileManager; private ProjectFileManager projectFileManager;
private InstantiationManager instantiationManager;
private Rectangle selectionRect; private Rectangle selectionRect;
@@ -95,12 +95,6 @@ public class Presenter implements IPlugInPort {
private Point previousDragPoint = null; private Point previousDragPoint = null;
private Project preDragProject = null; private Project preDragProject = null;
// Component creation
private ComponentType componentTypeSlot;
private IDIYComponent<?> componentSlot;
private Point controlPointSlot;
private Point potentialControlPoint;
private boolean snapToGrid = true; private boolean snapToGrid = true;
public Presenter(IView view) { public Presenter(IView view) {
@@ -113,6 +107,7 @@ public class Presenter implements IPlugInPort {
cloner = new Cloner(); cloner = new Cloner();
drawingManager = new DrawingManager(messageDispatcher); drawingManager = new DrawingManager(messageDispatcher);
projectFileManager = new ProjectFileManager(messageDispatcher); projectFileManager = new ProjectFileManager(messageDispatcher);
instantiationManager = new InstantiationManager();
// lockedLayers = EnumSet.noneOf(ComponentLayer.class); // lockedLayers = EnumSet.noneOf(ComponentLayer.class);
// visibleLayers = EnumSet.allOf(ComponentLayer.class); // visibleLayers = EnumSet.allOf(ComponentLayer.class);
@@ -155,7 +150,7 @@ public class Presenter implements IPlugInPort {
@Override @Override
public Cursor getCursorAt(Point point) { public Cursor getCursorAt(Point point) {
// Only change the cursor if we're not making a new component. // Only change the cursor if we're not making a new component.
if (componentTypeSlot == null) { if (instantiationManager.getComponentTypeSlot() == null) {
// Scale point to remove zoom factor. // Scale point to remove zoom factor.
Point2D scaledPoint = scalePoint(point); Point2D scaledPoint = scalePoint(point);
if (drawingManager.isCursorOverArea(scaledPoint)) { if (drawingManager.isCursorOverArea(scaledPoint)) {
@@ -193,7 +188,7 @@ public class Presenter implements IPlugInPort {
LOG.info("createNewFile()"); LOG.info("createNewFile()");
try { try {
Project project = new Project(); Project project = new Project();
setDefaultProperties(project); instantiationManager.setDefaultProperties(project);
loadProject(project, true); loadProject(project, true);
projectFileManager.fireFileStatusChanged(); projectFileManager.fireFileStatusChanged();
} catch (Exception e) { } catch (Exception e) {
@@ -292,15 +287,18 @@ public class Presenter implements IPlugInPort {
} }
// Don't draw the component in the slot if both control points match. // Don't draw the component in the slot if both control points match.
IDIYComponent<?> componentSlotToDraw; IDIYComponent<?> componentSlotToDraw;
if (controlPointSlot != null && potentialControlPoint != null if (instantiationManager.getFirstControlPoint() != null
&& potentialControlPoint.equals(controlPointSlot)) { && instantiationManager.getPotentialControlPoint() != null
&& instantiationManager.getFirstControlPoint().equals(
instantiationManager.getPotentialControlPoint())) {
componentSlotToDraw = null; componentSlotToDraw = null;
} else { } else {
componentSlotToDraw = componentSlot; componentSlotToDraw = instantiationManager.getComponentSlot();
} }
drawingManager.drawProject(g2d, currentProject, drawOptions, filter, selectionRect, drawingManager.drawProject(g2d, currentProject, drawOptions, filter, selectionRect,
selectedComponents, groupedComponents, Arrays.asList(controlPointSlot, selectedComponents, groupedComponents, Arrays.asList(instantiationManager
potentialControlPoint), componentSlotToDraw, dragInProgress); .getFirstControlPoint(), instantiationManager.getPotentialControlPoint()),
componentSlotToDraw, dragInProgress);
} }
@Override @Override
@@ -338,15 +336,18 @@ public class Presenter implements IPlugInPort {
LOG.debug(String LOG.debug(String
.format("mouseClicked(%s, %s, %s, %s)", point, ctrlDown, shiftDown, altDown)); .format("mouseClicked(%s, %s, %s, %s)", point, ctrlDown, shiftDown, altDown));
Point scaledPoint = scalePoint(point); Point scaledPoint = scalePoint(point);
if (componentTypeSlot != null) { if (instantiationManager.getComponentTypeSlot() != null) {
// Keep the reference to component type for later. // Keep the reference to component type for later.
ComponentType componentType = componentTypeSlot; ComponentType componentTypeSlot = instantiationManager.getComponentTypeSlot();
Project oldProject = cloner.deepClone(currentProject); Project oldProject = cloner.deepClone(currentProject);
switch (componentTypeSlot.getCreationMethod()) { switch (componentTypeSlot.getCreationMethod()) {
case SINGLE_CLICK: case SINGLE_CLICK:
try { try {
IDIYComponent<?> component = instantiateComponent(componentTypeSlot, if (snapToGrid) {
scaledPoint); CalcUtils.snapPointToGrid(scaledPoint, currentProject.getGridSpacing());
}
IDIYComponent<?> component = instantiationManager.instantiateComponent(
componentTypeSlot, scaledPoint, currentProject);
addComponent(component, componentTypeSlot); addComponent(component, componentTypeSlot);
// Select the new component // Select the new component
selectedComponents.clear(); selectedComponents.clear();
@@ -362,32 +363,28 @@ public class Presenter implements IPlugInPort {
LOG.error("Error instatiating component of type: " LOG.error("Error instatiating component of type: "
+ componentTypeSlot.getInstanceClass().getName(), e); + componentTypeSlot.getInstanceClass().getName(), e);
} }
setNewComponentSlot(null); setNewComponentTypeSlot(null);
break; break;
case POINT_BY_POINT: case POINT_BY_POINT:
// First click is just to set the controlPointSlot and // First click is just to set the controlPointSlot and
// componentSlot. // componentSlot.
if (snapToGrid) { if (snapToGrid) {
snapPointToGrid(scaledPoint); CalcUtils.snapPointToGrid(scaledPoint, currentProject.getGridSpacing());
} }
if (controlPointSlot == null) { if (instantiationManager.getComponentSlot() == null) {
controlPointSlot = scaledPoint;
try { try {
componentSlot = instantiateComponent(componentTypeSlot, controlPointSlot); instantiationManager.instatiatePointByPoint(scaledPoint, currentProject);
} catch (Exception e) { } catch (Exception e) {
view.showMessage("Could not create component. Check log for details.", view.showMessage("Could not create component. Check log for details.",
"Error", JOptionPane.ERROR_MESSAGE); "Error", JOptionPane.ERROR_MESSAGE);
LOG.error("Could not create component", e); LOG.error("Could not create component", e);
} }
// Set the other control point to the same location, we'll
// move it later when mouse moves.
componentSlot.setControlPoint(controlPointSlot, 0);
componentSlot.setControlPoint(controlPointSlot, 1);
messageDispatcher.dispatchMessage(EventType.SLOT_CHANGED, componentTypeSlot, messageDispatcher.dispatchMessage(EventType.SLOT_CHANGED, componentTypeSlot,
controlPointSlot); instantiationManager.getFirstControlPoint());
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} else { } else {
// On the second click, add the component to the project. // On the second click, add the component to the project.
IDIYComponent<?> componentSlot = instantiationManager.getComponentSlot();
componentSlot.setControlPoint(scaledPoint, 1); componentSlot.setControlPoint(scaledPoint, 1);
addComponent(componentSlot, componentTypeSlot); addComponent(componentSlot, componentTypeSlot);
// Select the new component // Select the new component
@@ -395,7 +392,7 @@ public class Presenter implements IPlugInPort {
selectedComponents.add(componentSlot); selectedComponents.add(componentSlot);
fireSelectionChanged(); fireSelectionChanged();
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
setNewComponentSlot(null); setNewComponentTypeSlot(null);
} }
break; break;
default: default:
@@ -404,7 +401,7 @@ public class Presenter implements IPlugInPort {
// Notify the listeners. // Notify the listeners.
if (!oldProject.equals(currentProject)) { if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner
.deepClone(currentProject), "Add " + componentType.getName()); .deepClone(currentProject), "Add " + componentTypeSlot.getName());
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
} }
} else { } else {
@@ -441,42 +438,17 @@ public class Presenter implements IPlugInPort {
public void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown) { public void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown) {
Map<IDIYComponent<?>, Set<Integer>> components = new HashMap<IDIYComponent<?>, Set<Integer>>(); Map<IDIYComponent<?>, Set<Integer>> components = new HashMap<IDIYComponent<?>, Set<Integer>>();
Point scaledPoint = scalePoint(point); Point scaledPoint = scalePoint(point);
if (componentTypeSlot != null) { if (instantiationManager.getComponentTypeSlot() != null) {
if (snapToGrid) { if (snapToGrid) {
snapPointToGrid(scaledPoint); CalcUtils.snapPointToGrid(scaledPoint, currentProject.getGridSpacing());
} }
switch (componentTypeSlot.getCreationMethod()) { switch (instantiationManager.getComponentTypeSlot().getCreationMethod()) {
case POINT_BY_POINT: case POINT_BY_POINT:
potentialControlPoint = scaledPoint; instantiationManager.updatePointByPoint(scaledPoint);
if (componentSlot != null) {
componentSlot.setControlPoint(scaledPoint, 1);
}
break; break;
case SINGLE_CLICK: case SINGLE_CLICK:
if (potentialControlPoint == null) { instantiationManager.updateSingleClick(scaledPoint, snapToGrid, currentProject
potentialControlPoint = new Point(0, 0); .getGridSpacing());
}
int dx = scaledPoint.x - potentialControlPoint.x;
int dy = scaledPoint.y - potentialControlPoint.y;
if (snapToGrid) {
dx = roundToGrid(dx);
dy = roundToGrid(dy);
}
// Only repaint if there's an actual change.
if (dx == 0 && dy == 0) {
return;
}
potentialControlPoint.translate(dx, dy);
if (componentSlot == null) {
LOG.error("Component slot should not be null!");
} else {
Point p = new Point();
for (int i = 0; i < componentSlot.getControlPointCount(); i++) {
p.setLocation(componentSlot.getControlPoint(i));
p.translate(dx, dy);
componentSlot.setControlPoint(p, i);
}
}
break; break;
} }
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
@@ -688,8 +660,8 @@ public class Presenter implements IPlugInPort {
int dx = (scaledPoint.x - previousDragPoint.x); int dx = (scaledPoint.x - previousDragPoint.x);
int dy = (scaledPoint.y - previousDragPoint.y); int dy = (scaledPoint.y - previousDragPoint.y);
if (snapToGrid) { if (snapToGrid) {
dx = roundToGrid(dx); dx = CalcUtils.roundToGrid(dx, currentProject.getGridSpacing());
dy = roundToGrid(dy); dy = CalcUtils.roundToGrid(dy, currentProject.getGridSpacing());
} }
// Only repaint if there's an actual change. // Only repaint if there's an actual change.
repaint = dx != 0 || dy != 0; repaint = dx != 0 || dy != 0;
@@ -748,27 +720,6 @@ public class Presenter implements IPlugInPort {
return true; return true;
} }
/**
* Rounds the number to the closest grid line.
*
* @param x
* @return
*/
private int roundToGrid(int x) {
int grid = currentProject.getGridSpacing().convertToPixels();
return (Math.round(1f * x / grid) * grid);
}
private void snapPointToGrid(Point point) {
int x = point.x;
int y = point.y;
if (snapToGrid) {
x = roundToGrid(x);
y = roundToGrid(y);
}
point.setLocation(x, y);
}
@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));
@@ -1013,71 +964,6 @@ public class Presenter implements IPlugInPort {
} }
} }
private IDIYComponent<?> instantiateComponent(ComponentType componentType, Point point)
throws Exception {
LOG.info("Instatiating component of type: " + componentType.getInstanceClass().getName());
// Instantiate the component.
IDIYComponent<?> component = componentType.getInstanceClass().newInstance();
// Find the next available componentName for the component.
int i = 0;
boolean exists = true;
while (exists) {
i++;
String name = componentType.getNamePrefix() + i;
exists = false;
for (IDIYComponent<?> c : currentProject.getComponents()) {
if (c.getName().equals(name)) {
exists = true;
break;
}
}
}
component.setName(componentType.getNamePrefix() + i);
// Translate them to the desired location.
if (point != null) {
for (int j = 0; j < component.getControlPointCount(); j++) {
Point controlPoint = new Point(component.getControlPoint(j));
controlPoint.translate(point.x, point.y);
snapPointToGrid(controlPoint);
component.setControlPoint(controlPoint, j);
}
}
setDefaultProperties(component);
return component;
}
/**
* Finds any properties that have default values and injects default values.
* Typically it should be used for {@link IDIYComponent} and {@link Project}
* objects.
*
* @param object
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private void setDefaultProperties(Object object) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
// Extract properties.
List<PropertyWrapper> properties = ComponentProcessor.getInstance().extractProperties(
object.getClass());
// Override with default values if available.
for (PropertyWrapper property : properties) {
Object defaultValue = ConfigurationManager.getInstance().readObject(
DEFAULTS_KEY_PREFIX + object.getClass().getName() + ":" + property.getName(),
null);
if (defaultValue != null) {
property.setValue(cloner.deepClone(defaultValue));
property.writeTo(object);
}
}
}
@Override @Override
public List<PropertyWrapper> getMutualSelectionProperties() { public List<PropertyWrapper> getMutualSelectionProperties() {
try { try {
@@ -1158,29 +1044,11 @@ public class Presenter implements IPlugInPort {
} }
@Override @Override
public void setNewComponentSlot(ComponentType componentType) { public void setNewComponentTypeSlot(ComponentType componentType) {
LOG.info(String.format("setNewComponentSlot(%s)", componentType == null ? null LOG.info(String.format("setNewComponentSlot(%s)", componentType == null ? null
: componentType.getName())); : componentType.getName()));
this.componentTypeSlot = componentType;
if (componentTypeSlot == null) {
this.componentSlot = null;
} else {
switch (componentTypeSlot.getCreationMethod()) {
case POINT_BY_POINT:
this.componentSlot = null;
break;
case SINGLE_CLICK:
try { try {
this.componentSlot = instantiateComponent(componentTypeSlot, new Point(0, 0)); instantiationManager.setComponentTypeSlot(componentType, currentProject);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
this.controlPointSlot = null;
this.potentialControlPoint = null;
selectedComponents.clear(); selectedComponents.clear();
fireSelectionChanged(); fireSelectionChanged();
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
@@ -1188,8 +1056,13 @@ public class Presenter implements IPlugInPort {
// selectedComponents); // selectedComponents);
// messageDispatcher.dispatchMessage(EventType.SELECTION_SIZE_CHANGED, // messageDispatcher.dispatchMessage(EventType.SELECTION_SIZE_CHANGED,
// calculateSelectionDimension()); // calculateSelectionDimension());
messageDispatcher.dispatchMessage(EventType.SLOT_CHANGED, componentTypeSlot, messageDispatcher.dispatchMessage(EventType.SLOT_CHANGED, instantiationManager
controlPointSlot); .getComponentTypeSlot(), instantiationManager.getFirstControlPoint());
} catch (Exception e) {
LOG.error("Could not set component type slot", e);
view.showMessage("Could not set component type slot. Check log for details.", "Error",
JOptionPane.ERROR_MESSAGE);
}
} }
/** /**