mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-11 01:32:08 +10:00
package renamed
This commit is contained in:
+240
@@ -0,0 +1,240 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.ControlPointWrapper;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.model.IComponentInstance;
|
||||
import org.diylc.model.annotations.BomName;
|
||||
import org.diylc.model.annotations.BomValue;
|
||||
import org.diylc.model.annotations.ControlPoint;
|
||||
import org.diylc.model.annotations.EditableProperty;
|
||||
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
/**
|
||||
* Utility class with component processing methods.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ComponentProcessor {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ComponentProcessor.class);
|
||||
|
||||
private static ComponentProcessor instance;
|
||||
|
||||
private Map<Class<?>, List<PropertyWrapper>> propertyCache;
|
||||
private Map<Class<?>, List<ControlPointWrapper>> controlPointCache;
|
||||
|
||||
private Cloner cloner;
|
||||
|
||||
public static ComponentProcessor getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ComponentProcessor();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ComponentProcessor() {
|
||||
super();
|
||||
this.cloner = new Cloner();
|
||||
this.propertyCache = new HashMap<Class<?>, List<PropertyWrapper>>();
|
||||
this.controlPointCache = new HashMap<Class<?>, List<ControlPointWrapper>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts all editable properties from the component class.
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public List<PropertyWrapper> extractProperties(Class<? extends IComponentInstance> clazz) {
|
||||
if (propertyCache.containsKey(clazz)) {
|
||||
return cloner.deepClone(propertyCache.get(clazz));
|
||||
}
|
||||
List<PropertyWrapper> properties = new ArrayList<PropertyWrapper>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (method.getName().startsWith("get")) {
|
||||
try {
|
||||
Method setter = clazz.getMethod("set" + method.getName().substring(3), method
|
||||
.getReturnType());
|
||||
if (method.isAnnotationPresent(EditableProperty.class)) {
|
||||
EditableProperty annotation = method.getAnnotation(EditableProperty.class);
|
||||
String name;
|
||||
if (annotation.name().equals("")) {
|
||||
name = method.getName().substring(3);
|
||||
} else {
|
||||
name = annotation.name();
|
||||
}
|
||||
PropertyWrapper property = new PropertyWrapper(name,
|
||||
method.getReturnType(), method, setter, annotation.defaultable());
|
||||
properties.add(property);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
LOG.debug("No matching setter found for \"" + method.getName()
|
||||
+ "\". Skipping...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propertyCache.put(clazz, properties);
|
||||
return cloner.deepClone(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all control points from the specified component class. Note than
|
||||
* control points are cached, so it may happen that control points returned
|
||||
* already have their values populated. Always use
|
||||
* {@link ControlPointWrapper#readFrom(IComponentInstance)} to update their
|
||||
* state from an actual component.
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public List<ControlPointWrapper> extractControlPoints(Class<? extends IComponentInstance> clazz) {
|
||||
if (controlPointCache.containsKey(clazz)) {
|
||||
return cloner.deepClone(controlPointCache.get(clazz));
|
||||
}
|
||||
List<ControlPointWrapper> controlPoints = new ArrayList<ControlPointWrapper>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (method.getName().startsWith("get")) {
|
||||
try {
|
||||
Method setter = clazz.getMethod("set" + method.getName().substring(3), method
|
||||
.getReturnType());
|
||||
if (method.isAnnotationPresent(ControlPoint.class)) {
|
||||
if (method.getReturnType().equals(Point.class)) {
|
||||
ControlPoint annotation = method.getAnnotation(ControlPoint.class);
|
||||
ControlPointWrapper controlPoint = new ControlPointWrapper(method
|
||||
.getName().substring(3), method, setter, annotation.editable(),
|
||||
annotation.sticky(), annotation.visibilityPolicy());
|
||||
controlPoints.add(controlPoint);
|
||||
} else {
|
||||
LOG.debug("Control point return type must be java.awt.Point.");
|
||||
}
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
LOG.debug("No matching setter found for \"" + method.getName()
|
||||
+ "\". Skipping...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
controlPointCache.put(clazz, controlPoints);
|
||||
return cloner.deepClone(controlPoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properties mutual for all the selected components.
|
||||
*
|
||||
* @param selectedComponents
|
||||
* @return
|
||||
*/
|
||||
public List<PropertyWrapper> getMutualSelectionProperties(
|
||||
List<IComponentInstance> selectedComponents) {
|
||||
if (selectedComponents.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<PropertyWrapper> properties = new ArrayList<PropertyWrapper>();
|
||||
IComponentInstance firstComponent = selectedComponents.get(0);
|
||||
properties.addAll(extractProperties(firstComponent.getClass()));
|
||||
// Initialize values
|
||||
for (PropertyWrapper property : properties) {
|
||||
try {
|
||||
property.readFrom(firstComponent);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < selectedComponents.size(); i++) {
|
||||
IComponentInstance component = selectedComponents.get(i);
|
||||
List<PropertyWrapper> newProperties = extractProperties(component.getClass());
|
||||
for (PropertyWrapper property : newProperties) {
|
||||
try {
|
||||
property.readFrom(component);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
properties.retainAll(newProperties);
|
||||
// for (PropertyWrapper property : properties) {
|
||||
// try {
|
||||
// property.readUniqueFrom(component);
|
||||
// } catch (Exception e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the method annotated with {@link BomName} annotations and calls it
|
||||
* to retrieve component name.
|
||||
*
|
||||
* @param component
|
||||
* @return
|
||||
*/
|
||||
public String extractBomName(IComponentInstance component) {
|
||||
String name = null;
|
||||
for (Method method : component.getClass().getMethods()) {
|
||||
if (method.isAnnotationPresent(BomName.class)) {
|
||||
try {
|
||||
name = method.invoke(component).toString();
|
||||
} catch (Exception e) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the method annotated with {@link BomName} and it's matching setter
|
||||
* and calls the setter to update the component name.
|
||||
*
|
||||
* @param component
|
||||
* @param newBomName
|
||||
*/
|
||||
public void writeBomName(IComponentInstance component, String newBomName) {
|
||||
for (Method method : component.getClass().getMethods()) {
|
||||
if (method.isAnnotationPresent(BomName.class)) {
|
||||
try {
|
||||
Method setter = component.getClass().getMethod(
|
||||
method.getName().replaceFirst("get", "set"), String.class);
|
||||
setter.invoke(component, newBomName);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the method annotated with {@link BomValue} annotations and calls it
|
||||
* to retrieve component value.
|
||||
*
|
||||
* @param component
|
||||
* @return
|
||||
*/
|
||||
public String extractBomValue(IComponentInstance component) {
|
||||
String value = null;
|
||||
for (Method method : component.getClass().getMethods()) {
|
||||
if (method.isAnnotationPresent(BomValue.class)) {
|
||||
try {
|
||||
value = method.invoke(component).toString();
|
||||
} catch (Exception e) {
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.RenderingHints.Key;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.awt.image.renderable.RenderableImage;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link Graphics2D} wrapper that keeps track of all drawing actions and
|
||||
* creates an {@link Area} that corresponds to drawn objects. Before each
|
||||
* component is drawn, {@link #startedDrawingComponent()} should be called.
|
||||
* After the component is drawn, area may be retrieved using
|
||||
* {@link #finishedDrawingComponent()}.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
class G2DWrapper extends Graphics2D {
|
||||
|
||||
private Graphics2D canvasGraphics;
|
||||
private Stroke originalStroke;
|
||||
private Color originalColor;
|
||||
private Composite originalComposite;
|
||||
private AffineTransform originalTx;
|
||||
private AffineTransform currentTx;
|
||||
private Area currentArea;
|
||||
|
||||
/**
|
||||
* Creates a wrapper around specified {@link Graphics2D} object.
|
||||
*
|
||||
* @param canvasGraphics
|
||||
*/
|
||||
public G2DWrapper(Graphics2D canvasGraphics) {
|
||||
super();
|
||||
this.canvasGraphics = canvasGraphics;
|
||||
startedDrawingComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out the current area and caches canvas settings.
|
||||
*/
|
||||
public void startedDrawingComponent() {
|
||||
currentArea = new Area();
|
||||
originalStroke = canvasGraphics.getStroke();
|
||||
originalColor = canvasGraphics.getColor();
|
||||
originalTx = canvasGraphics.getTransform();
|
||||
originalComposite = canvasGraphics.getComposite();
|
||||
currentTx = new AffineTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts {@link Graphics2D} settings and returns area drawn by component
|
||||
* in the meantime.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Area finishedDrawingComponent() {
|
||||
canvasGraphics.setStroke(originalStroke);
|
||||
canvasGraphics.setColor(originalColor);
|
||||
canvasGraphics.setTransform(originalTx);
|
||||
canvasGraphics.setComposite(originalComposite);
|
||||
return currentArea;
|
||||
}
|
||||
|
||||
private void appendShape(Shape s) {
|
||||
Area area = new Area(s);
|
||||
area.transform(currentTx);
|
||||
currentArea.add(area);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRenderingHints(Map<?, ?> hints) {
|
||||
canvasGraphics.addRenderingHints(hints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clip(Shape s) {
|
||||
canvasGraphics.clip(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Shape s) {
|
||||
canvasGraphics.draw(s);
|
||||
appendShape(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGlyphVector(GlyphVector g, float x, float y) {
|
||||
canvasGraphics.drawGlyphVector(g, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
|
||||
// FIXME: process map
|
||||
return canvasGraphics.drawImage(img, xform, obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
|
||||
canvasGraphics.drawImage(img, op, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
|
||||
canvasGraphics.drawRenderableImage(img, xform);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
|
||||
canvasGraphics.drawRenderedImage(img, xform);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, int x, int y) {
|
||||
canvasGraphics.drawString(str, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, float x, float y) {
|
||||
canvasGraphics.drawString(str, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, int x, int y) {
|
||||
canvasGraphics.drawString(iterator, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, float x, float y) {
|
||||
canvasGraphics.drawString(iterator, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(Shape s) {
|
||||
canvasGraphics.fill(s);
|
||||
appendShape(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
return canvasGraphics.getBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Composite getComposite() {
|
||||
return canvasGraphics.getComposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return canvasGraphics.getDeviceConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontRenderContext getFontRenderContext() {
|
||||
return canvasGraphics.getFontRenderContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint() {
|
||||
return canvasGraphics.getPaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderingHint(Key hintKey) {
|
||||
return canvasGraphics.getRenderingHint(hintKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
return canvasGraphics.getRenderingHints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stroke getStroke() {
|
||||
return canvasGraphics.getStroke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getTransform() {
|
||||
return canvasGraphics.getTransform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
|
||||
return canvasGraphics.hit(rect, s, onStroke);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta) {
|
||||
canvasGraphics.rotate(theta);
|
||||
currentTx.rotate(theta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta, double x, double y) {
|
||||
canvasGraphics.rotate(theta, x, y);
|
||||
currentTx.rotate(theta, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scale(double sx, double sy) {
|
||||
canvasGraphics.scale(sx, sy);
|
||||
currentTx.scale(sx, sy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color color) {
|
||||
canvasGraphics.setBackground(color);
|
||||
// FIXME: fix map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComposite(Composite comp) {
|
||||
canvasGraphics.setComposite(comp);
|
||||
// FIXME: check this.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaint(Paint paint) {
|
||||
canvasGraphics.setPaint(paint);
|
||||
// FIXME: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHint(Key hintKey, Object hintValue) {
|
||||
canvasGraphics.setRenderingHint(hintKey, hintValue);
|
||||
// FIXME: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHints(Map<?, ?> hints) {
|
||||
canvasGraphics.setRenderingHints(hints);
|
||||
// FIXME: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStroke(Stroke s) {
|
||||
canvasGraphics.setStroke(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(AffineTransform Tx) {
|
||||
canvasGraphics.setTransform(Tx);
|
||||
currentTx = Tx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shear(double shx, double shy) {
|
||||
canvasGraphics.shear(shx, shy);
|
||||
currentTx.shear(shx, shy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(AffineTransform Tx) {
|
||||
canvasGraphics.transform(Tx);
|
||||
currentTx.concatenate(Tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(int x, int y) {
|
||||
canvasGraphics.translate(x, y);
|
||||
currentTx.translate(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(double tx, double ty) {
|
||||
canvasGraphics.translate(tx, ty);
|
||||
currentTx.translate(tx, ty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.clearRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.clipRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
|
||||
canvasGraphics.copyArea(x, y, width, height, dx, dy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return canvasGraphics.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
canvasGraphics.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||
canvasGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, width, height, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor,
|
||||
ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, width, height, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
|
||||
int sx2, int sy2, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
|
||||
int sx2, int sy2, Color bgcolor, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(int x1, int y1, int x2, int y2) {
|
||||
canvasGraphics.drawLine(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval(int x, int y, int width, int height) {
|
||||
canvasGraphics.drawOval(x, y, width, height);
|
||||
appendShape(new Ellipse2D.Double(x, y, width, height));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolygon(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.drawPolygon(points, points2, points3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolyline(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.drawPolyline(points, points2, points3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
|
||||
canvasGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
|
||||
appendShape(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||
canvasGraphics.fillArc(x, y, width, height, startAngle, arcAngle);
|
||||
appendShape(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.PIE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillOval(int x, int y, int width, int height) {
|
||||
canvasGraphics.fillOval(x, y, width, height);
|
||||
appendShape(new Ellipse2D.Double(x, y, width, height));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.fillPolygon(points, points2, points3);
|
||||
appendShape(new Polygon(points, points2, points3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.fillRect(x, y, width, height);
|
||||
appendShape(new Rectangle(x, y, width, height));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
|
||||
canvasGraphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
|
||||
appendShape(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getClip() {
|
||||
return canvasGraphics.getClip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getClipBounds() {
|
||||
return canvasGraphics.getClipBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
return canvasGraphics.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font getFont() {
|
||||
return canvasGraphics.getFont();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font f) {
|
||||
return canvasGraphics.getFontMetrics(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(Shape clip) {
|
||||
canvasGraphics.setClip(clip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(int x, int y, int width, int height) {
|
||||
canvasGraphics.setClip(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(Color c) {
|
||||
canvasGraphics.setColor(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont(Font font) {
|
||||
canvasGraphics.setFont(font);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaintMode() {
|
||||
canvasGraphics.setPaintMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXORMode(Color c1) {
|
||||
canvasGraphics.setXORMode(c1);
|
||||
}
|
||||
}
|
||||
+780
@@ -0,0 +1,780 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.BadPositionException;
|
||||
import org.diylc.common.ComponentSelection;
|
||||
import org.diylc.common.ControlPointWrapper;
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.gui.IView;
|
||||
import org.diylc.model.ComponentLayer;
|
||||
import org.diylc.model.ComponentState;
|
||||
import org.diylc.model.IComponentInstance;
|
||||
import org.diylc.model.IComponentType;
|
||||
import org.diylc.model.Project;
|
||||
import org.diylc.model.VisibilityPolicy;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
import com.diyfever.gui.miscutils.JarScanner;
|
||||
import com.diyfever.gui.miscutils.Utils;
|
||||
import com.diyfever.gui.simplemq.MessageDispatcher;
|
||||
import com.diyfever.gui.update.VersionNumber;
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
/**
|
||||
* The main presenter class.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class Presenter implements IPlugInPort {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(Presenter.class);
|
||||
|
||||
private static final VersionNumber CURRENT_VERSION = new VersionNumber(0, 0, 0);
|
||||
private static final String DEFAULTS_KEY = "defaults";
|
||||
private static final int CONTROL_POINT_SENSITIVITY = 4;
|
||||
|
||||
private double zoomLevel = 1;
|
||||
private Map<IComponentInstance, Area> componentAreaMap;
|
||||
private Project currentProject;
|
||||
private Map<String, List<IComponentType>> componentTypes;
|
||||
private List<IPlugIn> plugIns;
|
||||
|
||||
private ComponentSelection selectedComponents;
|
||||
// List of components that have at least one of their control points
|
||||
// under the last recorded mouse position.
|
||||
private Map<IComponentInstance, ControlPointWrapper> componentControlPointMap;
|
||||
|
||||
private Cloner cloner;
|
||||
|
||||
private Rectangle selectionRect;
|
||||
|
||||
private final IView view;
|
||||
|
||||
private MessageDispatcher<EventType> messageDispatcher;
|
||||
|
||||
// Layers
|
||||
private Set<ComponentLayer> lockedLayers;
|
||||
private Set<ComponentLayer> visibleLayers;
|
||||
|
||||
// D&D
|
||||
private boolean dragInProgress = false;
|
||||
// Previous mouse location, not scaled for zoom factor.
|
||||
private Point previousDragPoint = null;
|
||||
private Project preDragProject = null;
|
||||
|
||||
private IComponentType componentSlot;
|
||||
|
||||
public Presenter(IView view) {
|
||||
super();
|
||||
this.view = view;
|
||||
componentAreaMap = new HashMap<IComponentInstance, Area>();
|
||||
plugIns = new ArrayList<IPlugIn>();
|
||||
messageDispatcher = new MessageDispatcher<EventType>();
|
||||
selectedComponents = new ComponentSelection();
|
||||
currentProject = new Project();
|
||||
cloner = new Cloner();
|
||||
|
||||
lockedLayers = EnumSet.noneOf(ComponentLayer.class);
|
||||
visibleLayers = EnumSet.allOf(ComponentLayer.class);
|
||||
}
|
||||
|
||||
public void installPlugin(IPlugIn plugIn) {
|
||||
LOG.debug(String.format("installPlugin(%s)", plugIn.getClass().getSimpleName()));
|
||||
plugIns.add(plugIn);
|
||||
plugIn.connect(this);
|
||||
messageDispatcher.registerListener(plugIn);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
for (IPlugIn plugIn : plugIns) {
|
||||
messageDispatcher.unregisterListener(plugIn);
|
||||
}
|
||||
}
|
||||
|
||||
// IPlugInPort
|
||||
|
||||
@Override
|
||||
public double getZoomLevel() {
|
||||
return zoomLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoomLevel(double zoomLevel) {
|
||||
LOG.debug(String.format("setZoomLevel(%s)", zoomLevel));
|
||||
this.zoomLevel = zoomLevel;
|
||||
messageDispatcher.dispatchMessage(EventType.ZOOM_CHANGED, zoomLevel);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursorAt(Point point) {
|
||||
// Only change the cursor if we're not making a new component.
|
||||
if (componentSlot == null) {
|
||||
// Scale point to remove zoom factor.
|
||||
Point2D scaledPoint = scalePoint(point);
|
||||
for (Map.Entry<IComponentInstance, Area> entry : componentAreaMap.entrySet()) {
|
||||
if (entry.getValue().contains(scaledPoint)) {
|
||||
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||
}
|
||||
}
|
||||
if (componentControlPointMap != null && !componentControlPointMap.isEmpty()) {
|
||||
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||
}
|
||||
}
|
||||
return Cursor.getDefaultCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getCanvasDimensions(boolean useZoom) {
|
||||
double width = currentProject.getWidth().convertToPixels();
|
||||
int height = currentProject.getHeight().convertToPixels();
|
||||
if (useZoom) {
|
||||
width *= zoomLevel;
|
||||
height *= zoomLevel;
|
||||
}
|
||||
return new Dimension((int) width, (int) height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getCurrentProject() {
|
||||
return currentProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadProject(Project project, boolean freshStart) {
|
||||
LOG.info("Loading project: " + project.getTitle());
|
||||
this.currentProject = project;
|
||||
selectedComponents.clear();
|
||||
messageDispatcher.dispatchMessage(EventType.PROJECT_LOADED, project, freshStart);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<IComponentType>> getComponentTypes() {
|
||||
if (componentTypes == null) {
|
||||
LOG.info("Loading component types.");
|
||||
componentTypes = new HashMap<String, List<IComponentType>>();
|
||||
List<Class<?>> componentTypeClasses = JarScanner.getInstance().scanFolder("library/",
|
||||
IComponentType.class);
|
||||
for (Class<?> clazz : componentTypeClasses) {
|
||||
try {
|
||||
IComponentType componentType = (IComponentType) clazz.newInstance();
|
||||
List<IComponentType> nestedList;
|
||||
if (componentTypes.containsKey(componentType.getCategory())) {
|
||||
nestedList = componentTypes.get(componentType.getCategory());
|
||||
} else {
|
||||
nestedList = new ArrayList<IComponentType>();
|
||||
componentTypes.put(componentType.getCategory(), nestedList);
|
||||
}
|
||||
nestedList.add(componentType);
|
||||
} catch (InstantiationException e) {
|
||||
LOG.warn("Could not instantiate: " + clazz.getName());
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG.warn("Could not access: " + clazz.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return componentTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, Set<DrawOption> drawOptions) {
|
||||
if (currentProject == null) {
|
||||
return;
|
||||
}
|
||||
G2DWrapper g2dWrapper = new G2DWrapper(g2d);
|
||||
|
||||
if (drawOptions.contains(DrawOption.ANTIALIASING)) {
|
||||
g2d
|
||||
.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
}
|
||||
|
||||
AffineTransform initialTx = g2d.getTransform();
|
||||
Dimension d = getCanvasDimensions(drawOptions.contains(DrawOption.ZOOM));
|
||||
|
||||
g2dWrapper.setColor(Color.white);
|
||||
g2dWrapper.fillRect(0, 0, d.width, d.height);
|
||||
|
||||
if (drawOptions.contains(DrawOption.GRID)) {
|
||||
double zoomStep = Constants.GRID * zoomLevel;
|
||||
// Point2D p = new Point2D.Double(step, 0);
|
||||
// g2d.getTransform().transform(p, p);
|
||||
// System.out.println(p);
|
||||
|
||||
g2dWrapper.setColor(Constants.GRID_COLOR);
|
||||
for (double i = zoomStep; i < d.width; i += zoomStep) {
|
||||
g2dWrapper.drawLine((int) i, 0, (int) i, d.height - 1);
|
||||
}
|
||||
for (double j = zoomStep; j < d.height; j += zoomStep) {
|
||||
g2dWrapper.drawLine(0, (int) j, d.width - 1, (int) j);
|
||||
}
|
||||
}
|
||||
|
||||
if ((drawOptions.contains(DrawOption.ZOOM)) && (Math.abs(1.0 - zoomLevel) > 1e-4)) {
|
||||
g2dWrapper.scale(zoomLevel, zoomLevel);
|
||||
}
|
||||
|
||||
Composite mainComposite = g2d.getComposite();
|
||||
Composite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
|
||||
|
||||
// g2dWrapper.resetTx();
|
||||
|
||||
List<IComponentInstance> components = getCurrentProject().getComponents();
|
||||
componentAreaMap.clear();
|
||||
if (components != null) {
|
||||
for (IComponentInstance component : components) {
|
||||
g2dWrapper.startedDrawingComponent();
|
||||
ComponentState state = ComponentState.NORMAL;
|
||||
if (drawOptions.contains(DrawOption.SELECTION)
|
||||
&& selectedComponents.contains(component)) {
|
||||
if (dragInProgress) {
|
||||
state = ComponentState.DRAGGING;
|
||||
} else {
|
||||
state = ComponentState.SELECTED;
|
||||
}
|
||||
}
|
||||
// If the component is being dragged, draw it in a separate
|
||||
// composite.
|
||||
if (state == ComponentState.DRAGGING) {
|
||||
g2dWrapper.setComposite(alphaComposite);
|
||||
}
|
||||
// Draw the component through the g2dWrapper.
|
||||
component.draw(g2dWrapper, state);
|
||||
// Restore the composite if needed.
|
||||
if (state == ComponentState.DRAGGING) {
|
||||
g2dWrapper.setComposite(mainComposite);
|
||||
}
|
||||
componentAreaMap.put(component, g2dWrapper.finishedDrawingComponent());
|
||||
|
||||
// Draw control points
|
||||
if (drawOptions.contains(DrawOption.CONTROL_POINTS)) {
|
||||
List<ControlPointWrapper> controlPoints = ComponentProcessor.getInstance()
|
||||
.extractControlPoints(component.getClass());
|
||||
for (ControlPointWrapper controlPoint : controlPoints) {
|
||||
try {
|
||||
controlPoint.readFrom(component);
|
||||
if (shouldShowControlPoint(controlPoint, component)) {
|
||||
g2d.setColor(Color.blue);
|
||||
g2d.setStroke(new BasicStroke(2));
|
||||
g2d.drawOval(controlPoint.getValue().x - 2,
|
||||
controlPoint.getValue().y - 2, 4, 4);
|
||||
// g2d.fillOval(point.getValue().x - 2, point
|
||||
// .getValue().y - 2, 5, 5);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not obtain control points for component of type "
|
||||
+ component.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g2d.setTransform(initialTx);
|
||||
if ((drawOptions.contains(DrawOption.ZOOM)) && (Math.abs(1.0 - zoomLevel) > 1e-4)) {
|
||||
g2d.scale(zoomLevel, zoomLevel);
|
||||
}
|
||||
|
||||
// At the end draw selection rectangle if needed.
|
||||
if (drawOptions.contains(DrawOption.SELECTION) && (selectionRect != null)) {
|
||||
g2d.setColor(Color.white);
|
||||
g2d.draw(selectionRect);
|
||||
g2d.setColor(Color.black);
|
||||
g2d.setStroke(Constants.dashedStroke);
|
||||
g2d.draw(selectionRect);
|
||||
}
|
||||
|
||||
// // Draw component area for test
|
||||
// g2d.setStroke(new BasicStroke());
|
||||
// g2d.setColor(Color.red);
|
||||
// for (Area area : componentAreaMap.values()) {
|
||||
// g2d.draw(area);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGUIComponent(JComponent component, int position) throws BadPositionException {
|
||||
view.addComponent(component, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectMenuAction(Action action, String menuName) {
|
||||
view.addMenuAction(action, menuName);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void setCursorIcon(Icon icon) {
|
||||
// view.setCursorIcon(icon);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Finds all components whose areas include the specified {@link Point}.
|
||||
* Point is <b>not</b> scaled by the zoom factor.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<IComponentInstance> findComponentsAt(Point point) {
|
||||
List<IComponentInstance> components = new ArrayList<IComponentInstance>();
|
||||
for (Map.Entry<IComponentInstance, Area> entry : componentAreaMap.entrySet()) {
|
||||
if (entry.getValue().contains(point)) {
|
||||
components.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown) {
|
||||
LOG.debug(String
|
||||
.format("mouseClicked(%s, %s, %s, %s)", point, ctrlDown, shiftDown, altDown));
|
||||
Point scaledPoint = scalePoint(point);
|
||||
if (componentSlot != null) {
|
||||
try {
|
||||
instantiateComponent(componentSlot.getComponentInstanceClass(), componentSlot
|
||||
.getName(), componentSlot.getInstanceNamePrefix(), scaledPoint);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error instatiating component of type: "
|
||||
+ componentSlot.getComponentInstanceClass().getName());
|
||||
}
|
||||
setNewComponentSlot(null);
|
||||
} else {
|
||||
List<IComponentInstance> components = findComponentsAt(scaledPoint);
|
||||
// If there's nothing under mouse cursor deselect all.
|
||||
if (components.isEmpty()) {
|
||||
selectedComponents.clear();
|
||||
} else {
|
||||
IComponentInstance component = components.get(0);
|
||||
// If ctrl is pressed just toggle the component under mouse
|
||||
// cursor.
|
||||
if (ctrlDown) {
|
||||
if (selectedComponents.contains(component)) {
|
||||
selectedComponents.remove(component);
|
||||
} else {
|
||||
selectedComponents.add(component);
|
||||
}
|
||||
} else {
|
||||
// Otherwise just select that one component.
|
||||
selectedComponents.clear();
|
||||
selectedComponents.add(component);
|
||||
}
|
||||
}
|
||||
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown) {
|
||||
Map<IComponentInstance, ControlPointWrapper> components = new HashMap<IComponentInstance, ControlPointWrapper>();
|
||||
Point scaledPoint = scalePoint(point);
|
||||
for (IComponentInstance component : currentProject.getComponents()) {
|
||||
List<ControlPointWrapper> currentPoints = ComponentProcessor.getInstance()
|
||||
.extractControlPoints(component.getClass());
|
||||
for (ControlPointWrapper controlPoint : currentPoints) {
|
||||
if (shouldShowControlPoint(controlPoint, component)) {
|
||||
try {
|
||||
controlPoint.readFrom(component);
|
||||
if (scaledPoint.distance(controlPoint.getValue()) < CONTROL_POINT_SENSITIVITY) {
|
||||
components.put(component, controlPoint);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Error reading control point for component of type: "
|
||||
+ component.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
// If CTRL is pressed, we only care about the top most component.
|
||||
if (altDown && components.size() > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!components.equals(componentControlPointMap)) {
|
||||
componentControlPointMap = components;
|
||||
messageDispatcher.dispatchMessage(EventType.AVAILABLE_CTRL_POINTS_CHANGED, components);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentSelection getSelectedComponents() {
|
||||
return new ComponentSelection(selectedComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Area getComponentArea(IComponentInstance component) {
|
||||
return componentAreaMap.get(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VersionNumber getCurrentVersionNumber() {
|
||||
return CURRENT_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragStarted(Point point) {
|
||||
LOG.debug(String.format("dragStarted(%s)", point));
|
||||
dragInProgress = true;
|
||||
preDragProject = cloner.deepClone(currentProject);
|
||||
Point scaledPoint = scalePoint(point);
|
||||
previousDragPoint = scaledPoint;
|
||||
List<IComponentInstance> components = findComponentsAt(scaledPoint);
|
||||
if (!componentControlPointMap.isEmpty()) {
|
||||
// If we're dragging control points reset selection.
|
||||
selectedComponents.clear();
|
||||
selectedComponents.addAll(componentControlPointMap.keySet());
|
||||
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
} else if (components.isEmpty()) {
|
||||
// If there are no components are under the cursor, reset selection.
|
||||
selectedComponents.clear();
|
||||
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
} else {
|
||||
IComponentInstance component = components.get(0);
|
||||
// If the component under the cursor is not already selected, make
|
||||
// it into the only selected component.
|
||||
if (!selectedComponents.contains(component)) {
|
||||
selectedComponents.clear();
|
||||
selectedComponents.add(component);
|
||||
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dragOver(Point point) {
|
||||
if (point == null) {
|
||||
return false;
|
||||
}
|
||||
Point scaledPoint = scalePoint(point);
|
||||
if (!componentControlPointMap.isEmpty()) {
|
||||
// We're dragging control point(s).
|
||||
IComponentInstance firstComponent = componentControlPointMap.keySet().iterator().next();
|
||||
ControlPointWrapper controlPoint = componentControlPointMap.get(firstComponent);
|
||||
if (controlPoint == null) {
|
||||
LOG.warn("Control point not found in the map!");
|
||||
}
|
||||
// Re-read the value just in case.
|
||||
try {
|
||||
controlPoint.readFrom(firstComponent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int x = (int) (Math
|
||||
.round((controlPoint.getValue().x + scaledPoint.x - previousDragPoint.x)
|
||||
/ Constants.GRID) * Constants.GRID);
|
||||
int y = (int) (Math
|
||||
.round((controlPoint.getValue().y + scaledPoint.y - previousDragPoint.y)
|
||||
/ Constants.GRID) * Constants.GRID);
|
||||
previousDragPoint.setLocation(x, y);
|
||||
|
||||
for (Entry<IComponentInstance, ControlPointWrapper> entry : componentControlPointMap
|
||||
.entrySet()) {
|
||||
try {
|
||||
controlPoint = entry.getValue();
|
||||
IComponentInstance component = entry.getKey();
|
||||
controlPoint.readFrom(component);
|
||||
if (controlPoint.isEditable()) {
|
||||
controlPoint.getValue().setLocation(x, y);
|
||||
}
|
||||
controlPoint.writeTo(component);
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
// dragStartPoint = point;
|
||||
} else if (selectedComponents.isEmpty()) {
|
||||
// If there's no selection, the only thing to do is update the
|
||||
// selection rectangle and refresh.
|
||||
this.selectionRect = Utils.createRectangle(scaledPoint, previousDragPoint);
|
||||
// messageDispatcher.dispatchMessage(EventType.SELECTION_RECT_CHANGED,
|
||||
// selectionRect);
|
||||
} else {
|
||||
// If there are components selected translate their control points.
|
||||
translateSelectedComponents(previousDragPoint, scaledPoint);
|
||||
// dragStartPoint = point;
|
||||
}
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragEnded(Point point) {
|
||||
LOG.debug(String.format("dragEnded(%s)", point));
|
||||
if (!dragInProgress) {
|
||||
return;
|
||||
}
|
||||
Point scaledPoint = scalePoint(point);
|
||||
if (selectedComponents.isEmpty()) {
|
||||
// If there's no selection finalize selectionRect and see which
|
||||
// components intersect with it.
|
||||
if (scaledPoint != null) {
|
||||
this.selectionRect = Utils.createRectangle(scaledPoint, previousDragPoint);
|
||||
}
|
||||
selectedComponents.clear();
|
||||
for (IComponentInstance component : currentProject.getComponents()) {
|
||||
Area area = componentAreaMap.get(component);
|
||||
if ((area != null) && area.intersects(selectionRect)) {
|
||||
selectedComponents.add(component);
|
||||
}
|
||||
}
|
||||
selectionRect = null;
|
||||
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents);
|
||||
}
|
||||
// There is selection, so we need to finalize the drag&drop
|
||||
// operation.
|
||||
|
||||
if (!preDragProject.equals(currentProject)) {
|
||||
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, preDragProject, cloner
|
||||
.deepClone(currentProject), "Move");
|
||||
}
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
dragInProgress = false;
|
||||
}
|
||||
|
||||
private void translateSelectedComponents(Point fromPoint, Point toPoint) {
|
||||
if (toPoint == null) {
|
||||
LOG.debug("Drag ended outside the drawing area.");
|
||||
return;
|
||||
}
|
||||
int dx = (int) (Math.round((toPoint.x - fromPoint.x) / zoomLevel / Constants.GRID) * Constants.GRID);
|
||||
int dy = (int) (Math.round((toPoint.y - fromPoint.y) / zoomLevel / Constants.GRID) * Constants.GRID);
|
||||
fromPoint.translate(dx, dy);
|
||||
for (IComponentInstance component : selectedComponents) {
|
||||
List<ControlPointWrapper> controlPoints = ComponentProcessor.getInstance()
|
||||
.extractControlPoints(component.getClass());
|
||||
for (ControlPointWrapper controlPoint : controlPoints) {
|
||||
try {
|
||||
controlPoint.readFrom(component);
|
||||
if (controlPoint.isEditable()) {
|
||||
translateControlPoint(controlPoint, dx, dy);
|
||||
}
|
||||
controlPoint.writeTo(component);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not translate control points: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void translateControlPoint(ControlPointWrapper controlPoint, int dx, int dy) {
|
||||
int x = controlPoint.getValue().x + dx;
|
||||
int y = controlPoint.getValue().y + dy;
|
||||
controlPoint.getValue().setLocation(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addComponents(List<IComponentInstance> components, Point preferredPoint) {
|
||||
LOG.debug(String.format("addComponents(%s)", components));
|
||||
Project oldProject = cloner.deepClone(currentProject);
|
||||
currentProject.getComponents().addAll(components);
|
||||
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner
|
||||
.deepClone(currentProject), "Add");
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
|
||||
public boolean isLayerLocked(ComponentLayer layer) {
|
||||
return lockedLayers.contains(layer);
|
||||
}
|
||||
|
||||
public void setLayerLocked(ComponentLayer layer, boolean locked) {
|
||||
LOG.debug(String.format("setLayerLocked(%s, %s)", layer, locked));
|
||||
if (locked) {
|
||||
lockedLayers.add(layer);
|
||||
} else {
|
||||
lockedLayers.remove(layer);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLayerVisible(ComponentLayer layer) {
|
||||
return visibleLayers.contains(layer);
|
||||
}
|
||||
|
||||
public void setLayerVisible(ComponentLayer layer, boolean visible) {
|
||||
LOG.debug(String.format("setLayerVisible(%s, %s)", layer, visible));
|
||||
if (visible) {
|
||||
visibleLayers.add(layer);
|
||||
} else {
|
||||
visibleLayers.remove(layer);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
// @Override
|
||||
// public Object getDefaultPropertyValue(
|
||||
// Class<? extends IComponentInstance> componentClass,
|
||||
// String propertyName) {
|
||||
// return configuration.getDefaultPropertyValues().get(
|
||||
// componentClass.getName() + ":" + propertyName);
|
||||
// }
|
||||
public void setDefaultPropertyValue(String propertyName, Object value) {
|
||||
LOG.debug(String.format("setDefaultPropertyValue(%s, %s)", propertyName, value));
|
||||
Map<String, Object> defaultMap = (Map<String, Object>) ConfigurationManager.getInstance()
|
||||
.getConfigurationItem(DEFAULTS_KEY);
|
||||
if (defaultMap == null) {
|
||||
defaultMap = new HashMap<String, Object>();
|
||||
ConfigurationManager.getInstance().setConfigurationItem(DEFAULTS_KEY, defaultMap);
|
||||
}
|
||||
for (IComponentInstance component : selectedComponents) {
|
||||
String className = component.getClass().getName();
|
||||
LOG.debug("Default property value set for " + className + ":" + propertyName);
|
||||
defaultMap.put(className + ":" + propertyName, value);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void instantiateComponent(Class<? extends IComponentInstance> componentClass,
|
||||
String componentTypeName, String namePrefix, Point point) throws Exception {
|
||||
LOG.info("Instatiating component of type: " + componentClass.getName());
|
||||
|
||||
Project oldProject = cloner.deepClone(currentProject);
|
||||
|
||||
// Instantiate the component.
|
||||
IComponentInstance component = componentClass.newInstance();
|
||||
|
||||
// Find the next available name for the component.
|
||||
int i = 0;
|
||||
boolean exists = true;
|
||||
while (exists) {
|
||||
i++;
|
||||
String name = namePrefix + i;
|
||||
exists = false;
|
||||
for (IComponentInstance c : currentProject.getComponents()) {
|
||||
String cName = ComponentProcessor.getInstance().extractBomName(c);
|
||||
if (cName.equals(name)) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ComponentProcessor.getInstance().writeBomName(component, namePrefix + i);
|
||||
|
||||
// Add it to the project.
|
||||
currentProject.getComponents().add(component);
|
||||
|
||||
// Extract control points.
|
||||
List<ControlPointWrapper> controlPoints = ComponentProcessor.getInstance()
|
||||
.extractControlPoints(componentClass);
|
||||
// Translate them to the desired location.
|
||||
if (point != null) {
|
||||
for (ControlPointWrapper controlPoint : controlPoints) {
|
||||
controlPoint.readFrom(component);
|
||||
int x = controlPoint.getValue().x + point.x;
|
||||
int y = controlPoint.getValue().y + point.y;
|
||||
x = (int) (Math.round(x / Constants.GRID) * Constants.GRID);
|
||||
y = (int) (Math.round(y / Constants.GRID) * Constants.GRID);
|
||||
controlPoint.getValue().setLocation(x, y);
|
||||
controlPoint.writeTo(component);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract properties.
|
||||
List<PropertyWrapper> properties = ComponentProcessor.getInstance().extractProperties(
|
||||
componentClass);
|
||||
// Override with default values if available.
|
||||
for (PropertyWrapper property : properties) {
|
||||
Object defaultValue = null;
|
||||
Map<String, Object> defaultMap = (Map<String, Object>) ConfigurationManager
|
||||
.getInstance().getConfigurationItem(DEFAULTS_KEY);
|
||||
if (defaultMap != null) {
|
||||
defaultValue = defaultMap.get(componentClass.getName() + ":" + property.getName());
|
||||
}
|
||||
if (defaultValue != null) {
|
||||
property.setValue(cloner.deepClone(defaultValue));
|
||||
property.writeTo(component);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the listeners.
|
||||
if (!oldProject.equals(currentProject)) {
|
||||
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner
|
||||
.deepClone(currentProject), "Add " + componentTypeName);
|
||||
}
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyWrapper> getMutualSelectionProperties() {
|
||||
return ComponentProcessor.getInstance().getMutualSelectionProperties(selectedComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyPropertiesToSelection(List<PropertyWrapper> properties) throws Exception {
|
||||
LOG.debug(String.format("applyPropertiesToSelection(%s)", properties));
|
||||
Project oldProject = cloner.deepClone(currentProject);
|
||||
try {
|
||||
for (IComponentInstance component : selectedComponents) {
|
||||
for (PropertyWrapper property : properties) {
|
||||
property.writeTo(component);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Notify the listeners.
|
||||
if (!oldProject.equals(currentProject)) {
|
||||
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner
|
||||
.deepClone(currentProject), "Edit");
|
||||
}
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNewComponentSlot(IComponentType componentType) {
|
||||
LOG.debug(String.format("setNewComponentSlot(%s)", componentType == null ? null
|
||||
: componentType.getName()));
|
||||
this.componentSlot = componentType;
|
||||
selectedComponents.clear();
|
||||
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED);
|
||||
messageDispatcher.dispatchMessage(EventType.SLOT_CHANGED, componentSlot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales point from display base to actual base.
|
||||
*
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
private Point scalePoint(Point point) {
|
||||
return point == null ? null : new Point((int) (point.x / zoomLevel),
|
||||
(int) (point.y / zoomLevel));
|
||||
}
|
||||
|
||||
private boolean shouldShowControlPoint(ControlPointWrapper controlPoint,
|
||||
IComponentInstance component) {
|
||||
return controlPoint.getVisibilityPolicy().equals(VisibilityPolicy.ALWAYS)
|
||||
|| ((controlPoint.getVisibilityPolicy().equals(VisibilityPolicy.WHEN_SELECTED)) && (getSelectedComponents()
|
||||
.contains(component)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user