Highlight connected areas through copper traces, leads, jumpers, etc...

This commit is contained in:
Branislav Stojkovic
2018-12-16 00:52:15 +01:00
parent d506feac27
commit 58a4ff987f
25 changed files with 1685 additions and 1364 deletions
@@ -1,148 +1,150 @@
/* /*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.common;
DIY Layout Creator (DIYLC). import javax.swing.Icon;
Copyright (c) 2009-2018 held jointly by the individual authors.
This file is part of DIYLC. import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.KeywordPolicy;
DIYLC is free software: you can redistribute it and/or modify /**
it under the terms of the GNU General Public License as published by * Entity class used to describe a component type.
the Free Software Foundation, either version 3 of the License, or *
(at your option) any later version. * @author Branislav Stojkovic
*
* @see IDIYComponent
*/
public class ComponentType {
DIYLC is distributed in the hope that it will be useful, private String name;
but WITHOUT ANY WARRANTY; without even the implied warranty of private String description;
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the private CreationMethod creationMethod;
GNU General Public License for more details. private String category;
private String namePrefix;
private String author;
private Icon icon;
private Class<? extends IDIYComponent<?>> instanceClass;
private double zOrder;
private boolean flexibleZOrder;
private boolean stretchable;
private BomPolicy bomPolicy;
private boolean autoEdit;
private IComponentTransformer transformer;
private KeywordPolicy keywordPolicy;
private String keywordTag;
private boolean continuity;
You should have received a copy of the GNU General Public License public ComponentType(String name, String description, CreationMethod creationMethod, String category,
along with DIYLC. If not, see <http://www.gnu.org/licenses/>. String namePrefix, String author, Icon icon, Class<? extends IDIYComponent<?>> instanceClass, double zOrder,
boolean flexibleZOrder, boolean stretchable, BomPolicy bomPolicy, boolean autoEdit,
IComponentTransformer transformer, KeywordPolicy keywordPolicy, String keywordTag, boolean continuity) {
super();
this.name = name;
this.description = description;
this.creationMethod = creationMethod;
this.category = category;
this.namePrefix = namePrefix;
this.author = author;
this.icon = icon;
this.instanceClass = instanceClass;
this.zOrder = zOrder;
this.flexibleZOrder = flexibleZOrder;
this.stretchable = stretchable;
this.bomPolicy = bomPolicy;
this.autoEdit = autoEdit;
this.transformer = transformer;
this.keywordPolicy = keywordPolicy;
this.keywordTag = keywordTag;
this.continuity = continuity;
}
*/ public String getName() {
package org.diylc.common; return name;
}
import javax.swing.Icon;
public String getDescription() {
import org.diylc.core.CreationMethod; return description;
import org.diylc.core.IDIYComponent; }
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.KeywordPolicy; public CreationMethod getCreationMethod() {
return creationMethod;
/** }
* Entity class used to describe a component type.
* public String getCategory() {
* @author Branislav Stojkovic return category;
* }
* @see IDIYComponent
*/ public String getNamePrefix() {
public class ComponentType { return namePrefix;
}
private String name;
private String description; public String getAuthor() {
private CreationMethod creationMethod; return author;
private String category; }
private String namePrefix;
private String author; public Icon getIcon() {
private Icon icon; return icon;
private Class<? extends IDIYComponent<?>> instanceClass; }
private double zOrder;
private boolean flexibleZOrder; public Class<? extends IDIYComponent<?>> getInstanceClass() {
private boolean stretchable; return instanceClass;
private BomPolicy bomPolicy; }
private boolean autoEdit;
private IComponentTransformer transformer; public double getZOrder() {
private KeywordPolicy keywordPolicy; return zOrder;
private String keywordTag; }
public ComponentType(String name, String description, CreationMethod creationMethod, String category, public boolean isFlexibleZOrder() {
String namePrefix, String author, Icon icon, Class<? extends IDIYComponent<?>> instanceClass, double zOrder, return flexibleZOrder;
boolean flexibleZOrder, boolean stretchable, BomPolicy bomPolicy, boolean autoEdit, IComponentTransformer transformer, }
KeywordPolicy keywordPolicy, String keywordTag) {
super(); public boolean isStretchable() {
this.name = name; return stretchable;
this.description = description; }
this.creationMethod = creationMethod;
this.category = category; public BomPolicy getBomPolicy() {
this.namePrefix = namePrefix; return bomPolicy;
this.author = author; }
this.icon = icon;
this.instanceClass = instanceClass; public boolean isAutoEdit() {
this.zOrder = zOrder; return autoEdit;
this.flexibleZOrder = flexibleZOrder; }
this.stretchable = stretchable;
this.bomPolicy = bomPolicy; public IComponentTransformer getTransformer() {
this.autoEdit = autoEdit; return transformer;
this.transformer = transformer; }
this.keywordPolicy = keywordPolicy;
this.keywordTag = keywordTag; public KeywordPolicy getKeywordPolicy() {
} return keywordPolicy;
}
public String getName() {
return name; public String getKeywordTag() {
} return keywordTag;
}
public String getDescription() {
return description; public boolean isContinuity() {
} return continuity;
}
public CreationMethod getCreationMethod() {
return creationMethod; @Override
} public String toString() {
return name;
public String getCategory() { }
return category; }
}
public String getNamePrefix() {
return namePrefix;
}
public String getAuthor() {
return author;
}
public Icon getIcon() {
return icon;
}
public Class<? extends IDIYComponent<?>> getInstanceClass() {
return instanceClass;
}
public double getZOrder() {
return zOrder;
}
public boolean isFlexibleZOrder() {
return flexibleZOrder;
}
public boolean isStretchable() {
return stretchable;
}
public BomPolicy getBomPolicy() {
return bomPolicy;
}
public boolean isAutoEdit() {
return autoEdit;
}
public IComponentTransformer getTransformer() {
return transformer;
}
public KeywordPolicy getKeywordPolicy() {
return keywordPolicy;
}
public String getKeywordTag() {
return keywordTag;
}
@Override
public String toString() {
return name;
}
}
@@ -70,7 +70,8 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
public static final String RECENT_COMPONENTS_KEY = "recentComponents"; public static final String RECENT_COMPONENTS_KEY = "recentComponents";
public static final String RECENT_FILES_KEY = "recentFiles"; public static final String RECENT_FILES_KEY = "recentFiles";
public static final String SHOW_RULERS_KEY = "showRulers"; public static final String SHOW_RULERS_KEY = "showRulers";
public static final String SHOW_GRID_KEY = "showGrid"; public static final String SHOW_GRID_KEY = "showGrid";
public static final String HIGHLIGHT_CONTINUITY_AREA = "highlightContinuityArea";
public static final int DND_TOGGLE_STICKY = 0x1; public static final int DND_TOGGLE_STICKY = 0x1;
public static final int DND_TOGGLE_SNAP = 0x40000000; public static final int DND_TOGGLE_SNAP = 0x40000000;
@@ -61,7 +61,7 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
* @param componentState * @param componentState
* @param theme * @param theme
*/ */
protected abstract void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState); protected abstract void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver);
/** /**
* @return default color. * @return default color.
@@ -110,7 +110,7 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
// g2d.setColor(color); // g2d.setColor(color);
// g2d.setStroke(new BasicStroke(thickness - 2)); // g2d.setStroke(new BasicStroke(thickness - 2));
// g2d.draw(path); // g2d.draw(path);
drawCurve(curve, g2d, componentState); drawCurve(curve, g2d, componentState, drawingObserver);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
@@ -32,7 +32,8 @@ import java.awt.Shape;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.Observable;
import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.Display; import org.diylc.common.Display;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
@@ -84,6 +85,10 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
} catch (NullPointerException e) { } catch (NullPointerException e) {
// This will happen if components do not have any shape. // This will happen if components do not have any shape.
} }
}
protected boolean IsCopperArea() {
return false;
} }
@Override @Override
@@ -93,7 +98,7 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
Shape shape = getBodyShape(); Shape shape = getBodyShape();
// If there's no body, just draw the line connecting the ending points. // If there's no body, just draw the line connecting the ending points.
if (shape == null) { if (shape == null) {
drawLead(g2d, componentState); drawLead(g2d, componentState, drawingObserver, IsCopperArea());
} else if (supportsStandingMode() && length.convertToPixels() > points[0].distance(points[1])) { } else if (supportsStandingMode() && length.convertToPixels() > points[0].distance(points[1])) {
// When ending points are too close draw the component in standing // When ending points are too close draw the component in standing
// mode. // mode.
@@ -124,7 +129,7 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
g2d.setColor(finalBorderColor); g2d.setColor(finalBorderColor);
g2d.draw(body); g2d.draw(body);
if (!outlineMode) { if (!outlineMode) {
drawLead(g2d, componentState); drawLead(g2d, componentState, drawingObserver, false);
} }
} else { } else {
// Normal mode with component body in the center and two lead parts. // Normal mode with component body in the center and two lead parts.
@@ -293,12 +298,17 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
g2d.drawLine(points[1].x, points[1].y, endX, endY); g2d.drawLine(points[1].x, points[1].y, endX, endY);
} }
private void drawLead(Graphics2D g2d, ComponentState componentState) { private void drawLead(Graphics2D g2d, ComponentState componentState, IDrawingObserver observer, boolean isCopperArea) {
if (isCopperArea)
observer.startTrackingContinuityArea(true);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness())); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness()));
Color leadColor = Color leadColor =
shouldShadeLeads() ? getLeadColorForPainting(componentState).darker() : getLeadColorForPainting(componentState); shouldShadeLeads() ? getLeadColorForPainting(componentState).darker() : getLeadColorForPainting(componentState);
g2d.setColor(leadColor); g2d.setColor(leadColor);
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y); g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
if (isCopperArea)
observer.stopTrackingContinuityArea();
if (shouldShadeLeads()) { if (shouldShadeLeads()) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness() - 2)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness() - 2));
@@ -31,5 +31,9 @@ public interface IDrawingObserver {
void stopTracking(); void stopTracking();
void startTracking(); void startTracking();
void stopTrackingContinuityArea();
void startTrackingContinuityArea(boolean positive);
} }
@@ -116,6 +116,13 @@ public @interface ComponentDescriptor {
* *
* @return * @return
*/ */
String keywordTag() default ""; String keywordTag() default "";
/**
* For components that show continuity between the two ending points, e.d. wires, jumpers, etc.
*
* @return
*/
boolean continuity() default false;
} }
@@ -0,0 +1,51 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2018 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.presenter;
import java.awt.geom.Area;
import java.util.List;
public class ComponentArea {
private Area outlineArea;
private List<Area> continuityPositiveAreas;
private List<Area> continuityNegativeAreas;
public ComponentArea(Area outlineArea, List<Area> continuityPositiveAreas, List<Area> continuityNegativeAreas) {
super();
this.outlineArea = outlineArea;
this.continuityPositiveAreas = continuityPositiveAreas;
this.continuityNegativeAreas = continuityNegativeAreas;
}
public Area getOutlineArea() {
return outlineArea;
}
public List<Area> getContinuityPositiveAreas() {
return continuityPositiveAreas;
}
public List<Area> getContinuityNegativeAreas() {
return continuityNegativeAreas;
}
}
@@ -97,7 +97,8 @@ public class ComponentProcessor {
boolean autoEdit; boolean autoEdit;
IComponentTransformer transformer; IComponentTransformer transformer;
KeywordPolicy keywordPolicy; KeywordPolicy keywordPolicy;
String keywordTag; String keywordTag;
boolean continuity;
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();
@@ -113,7 +114,8 @@ public class ComponentProcessor {
autoEdit = annotation.autoEdit(); autoEdit = annotation.autoEdit();
transformer = getComponentTransformer(annotation.transformer()); transformer = getComponentTransformer(annotation.transformer());
keywordPolicy = annotation.keywordPolicy(); keywordPolicy = annotation.keywordPolicy();
keywordTag = annotation.keywordTag(); keywordTag = annotation.keywordTag();
continuity = annotation.continuity();
} else { // default } else { // default
name = clazz.getSimpleName(); name = clazz.getSimpleName();
description = ""; description = "";
@@ -128,7 +130,8 @@ public class ComponentProcessor {
autoEdit = true; autoEdit = true;
transformer = null; transformer = null;
keywordPolicy = KeywordPolicy.NEVER_SHOW; keywordPolicy = KeywordPolicy.NEVER_SHOW;
keywordTag = null; keywordTag = null;
continuity = false;
} }
icon = null; icon = null;
// Draw component icon. // Draw component icon.
@@ -148,7 +151,7 @@ public class ComponentProcessor {
} }
ComponentType componentType = ComponentType componentType =
new ComponentType(name, description, creationMethod, category, namePrefix, author, icon, clazz, zOrder, new ComponentType(name, description, creationMethod, category, namePrefix, author, icon, clazz, zOrder,
flexibleZOrder, stretchable, bomPolicy, autoEdit, transformer, keywordPolicy, keywordTag); flexibleZOrder, stretchable, bomPolicy, autoEdit, transformer, keywordPolicy, keywordTag, continuity);
componentTypeMap.put(clazz.getName(), componentType); componentTypeMap.put(clazz.getName(), componentType);
return componentType; return componentType;
} }
@@ -1,403 +1,591 @@
/* /*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.presenter;
DIY Layout Creator (DIYLC). import java.awt.AlphaComposite;
Copyright (c) 2009-2018 held jointly by the individual authors. import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
This file is part of DIYLC. import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.simplemq.MessageDispatcher;
import org.diylc.common.ComponentType;
import org.diylc.common.DrawOption;
import org.diylc.common.EventType;
import org.diylc.common.GridType;
import org.diylc.common.IComponentFiler;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.core.Theme;
import org.diylc.core.VisibilityPolicy;
import org.diylc.utils.Constants;
DIYLC is free software: you can redistribute it and/or modify /**
it under the terms of the GNU General Public License as published by * Utility that deals with painting {@link Project} on the {@link Graphics2D} and keeps areas taken
the Free Software Foundation, either version 3 of the License, or * by each drawn component.
(at your option) any later version. *
* @author Branislav Stojkovic
*/
public class DrawingManager {
DIYLC is distributed in the hope that it will be useful, private static final Logger LOG = Logger.getLogger(DrawingManager.class);
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License public static int CONTROL_POINT_SIZE = 7;
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ public static final String ZOOM_KEY = "zoom";
package org.diylc.presenter;
public static String DEBUG_COMPONENT_AREAS = "org.diylc.debugComponentAreas";
import java.awt.AlphaComposite; public static String DEBUG_CONTINUITY_AREAS = "org.diylc.debugContinuityAreas";
import java.awt.BasicStroke;
import java.awt.Color; public static Color CONTROL_POINT_COLOR = Color.blue;
import java.awt.Composite; public static Color SELECTED_CONTROL_POINT_COLOR = Color.green;
import java.awt.Dimension;
import java.awt.Graphics2D; private Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY,
import java.awt.Point; Constants.DEFAULT_THEME);
import java.awt.Rectangle;
import java.awt.RenderingHints; // Keeps Area object of each drawn component.
import java.awt.geom.Area; private Map<IDIYComponent<?>, ComponentArea> componentAreaMap;
import java.util.ArrayList; // Maps components to the last state they are drawn in. Also, used to
import java.util.Collection; // determine which components are invalidated when they are not in the map.
import java.util.HashMap; private Map<IDIYComponent<?>, ComponentState> lastDrawnStateMap;
import java.util.List;
import java.util.Map; private Area continuityArea;
import java.util.Set;
private Composite slotComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
import org.apache.log4j.Logger; private Composite lockedComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
import org.diylc.appframework.miscutils.ConfigurationManager; private List<IDIYComponent<?>> failedComponents = new ArrayList<IDIYComponent<?>>();
import org.diylc.appframework.simplemq.MessageDispatcher;
import org.diylc.common.DrawOption; private double zoomLevel = 1d;// ConfigurationManager.getInstance().readDouble(ZOOM_KEY,
import org.diylc.common.EventType; // 1d);
import org.diylc.common.GridType;
import org.diylc.common.IComponentFiler; private MessageDispatcher<EventType> messageDispatcher;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache; private boolean debugComponentAreas;
import org.diylc.core.ComponentState; private boolean debugContinuityAreas;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project; public DrawingManager(MessageDispatcher<EventType> messageDispatcher) {
import org.diylc.core.Theme; super();
import org.diylc.core.VisibilityPolicy; this.messageDispatcher = messageDispatcher;
import org.diylc.utils.Constants; componentAreaMap = new HashMap<IDIYComponent<?>, ComponentArea>();
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
/** String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS);
* Utility that deals with painting {@link Project} on the {@link Graphics2D} and keeps areas taken debugComponentAreas = debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true");
* by each drawn component.
* String debugContinuityAreasStr = System.getProperty(DEBUG_CONTINUITY_AREAS);
* @author Branislav Stojkovic debugContinuityAreas = debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true");
*/ }
public class DrawingManager {
/**
private static final Logger LOG = Logger.getLogger(DrawingManager.class); * Paints the project onto the canvas and returns the list of components that failed to draw.
*
public static int CONTROL_POINT_SIZE = 7; * @param g2d
* @param project
public static final String ZOOM_KEY = "zoom"; * @param drawOptions
* @param filter
public static String DEBUG_COMPONENT_AREAS = "org.diylc.debugComponentAreas"; * @param selectionRect
* @param selectedComponents
public static Color CONTROL_POINT_COLOR = Color.blue; * @param lockedComponents
public static Color SELECTED_CONTROL_POINT_COLOR = Color.green; * @param groupedComponents
* @param controlPointSlot
private Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, * @param componentSlot
Constants.DEFAULT_THEME); * @param dragInProgress
* @return
// Keeps Area object of each drawn component. */
private Map<IDIYComponent<?>, Area> componentAreaMap; public List<IDIYComponent<?>> drawProject(Graphics2D g2d, Project project, Set<DrawOption> drawOptions,
// Maps components to the last state they are drawn in. Also, used to IComponentFiler filter, Rectangle selectionRect, Collection<IDIYComponent<?>> selectedComponents,
// determine which components are invalidated when they are not in the map. Set<IDIYComponent<?>> lockedComponents, Set<IDIYComponent<?>> groupedComponents, List<Point> controlPointSlot,
private Map<IDIYComponent<?>, ComponentState> lastDrawnStateMap; List<IDIYComponent<?>> componentSlot, boolean dragInProgress) {
failedComponents.clear();
private Composite slotComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); if (project == null) {
private Composite lockedComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); return failedComponents;
private List<IDIYComponent<?>> failedComponents = new ArrayList<IDIYComponent<?>>(); }
private double zoomLevel = 1d;// ConfigurationManager.getInstance().readDouble(ZOOM_KEY, double zoom = 1d;
// 1d); if (drawOptions.contains(DrawOption.ZOOM)) {
zoom = zoomLevel;
private MessageDispatcher<EventType> messageDispatcher; } else {
zoom = 1 / Constants.PIXEL_SIZE;
private boolean debugComponentAreas; }
public DrawingManager(MessageDispatcher<EventType> messageDispatcher) { G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
super();
this.messageDispatcher = messageDispatcher; if (drawOptions.contains(DrawOption.ANTIALIASING)) {
componentAreaMap = new HashMap<IDIYComponent<?>, Area>(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>(); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS); } else {
debugComponentAreas = debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true"); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
} g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
/** if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.HI_QUALITY_RENDER_KEY, false)) {
* Paints the project onto the canvas and returns the list of components that failed to draw. g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
* g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
* @param g2d g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
* @param project g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
* @param drawOptions g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
* @param filter // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
* @param selectionRect // RenderingHints.VALUE_STROKE_PURE);
* @param selectedComponents } else {
* @param lockedComponents g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
* @param groupedComponents g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
* @param controlPointSlot g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
* @param componentSlot g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
* @param dragInProgress g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
* @return }
*/
public List<IDIYComponent<?>> drawProject(Graphics2D g2d, Project project, Set<DrawOption> drawOptions, // AffineTransform initialTx = g2d.getTransform();
IComponentFiler filter, Rectangle selectionRect, Collection<IDIYComponent<?>> selectedComponents, Dimension d = getCanvasDimensions(project, zoom, true);
Set<IDIYComponent<?>> lockedComponents, Set<IDIYComponent<?>> groupedComponents, List<Point> controlPointSlot,
List<IDIYComponent<?>> componentSlot, boolean dragInProgress) { g2dWrapper.setColor(theme.getBgColor());
failedComponents.clear(); g2dWrapper.fillRect(0, 0, d.width, d.height);
if (project == null) { g2d.clip(new Rectangle(new Point(0, 0), d));
return failedComponents;
} GridType gridType = GridType.LINES;
if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) {
double zoom = 1d; double zoomStep = project.getGridSpacing().convertToPixels() * zoom;
if (drawOptions.contains(DrawOption.ZOOM)) { if (gridType == GridType.CROSSHAIR) {
zoom = zoomLevel; g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {
} else { (float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4));
zoom = 1 / Constants.PIXEL_SIZE; } else if (gridType == GridType.DOT) {
} g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {1f,
(float) zoomStep - 1}, 0f));
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom); }
if (drawOptions.contains(DrawOption.ANTIALIASING)) { g2dWrapper.setColor(theme.getGridColor());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); for (double i = zoomStep; i < d.width; i += zoomStep) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2dWrapper.drawLine((int) i, 0, (int) i, d.height - 1);
} else { }
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); for (double j = zoomStep; j < d.height; j += zoomStep) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); g2dWrapper.drawLine(0, (int) j, d.width - 1, (int) j);
} }
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.HI_QUALITY_RENDER_KEY, false)) { }
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); if (Math.abs(1.0 - zoom) > 1e-4) {
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2dWrapper.scale(zoom, zoom);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); }
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, // Composite mainComposite = g2d.getComposite();
// RenderingHints.VALUE_STROKE_PURE); // Composite alphaComposite =
} else { // AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED); // g2dWrapper.resetTx();
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); // componentAreaMap.clear();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); for (IDIYComponent<?> component : project.getComponents()) {
} // Do not draw the component if it's filtered out.
if (filter != null && !filter.testComponent(component)) {
// AffineTransform initialTx = g2d.getTransform(); continue;
Dimension d = getCanvasDimensions(project, zoom, true); }
ComponentState state = ComponentState.NORMAL;
g2dWrapper.setColor(theme.getBgColor()); if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) {
g2dWrapper.fillRect(0, 0, d.width, d.height); if (dragInProgress) {
g2d.clip(new Rectangle(new Point(0, 0), d)); state = ComponentState.DRAGGING;
} else {
GridType gridType = GridType.LINES; state = ComponentState.SELECTED;
if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) { }
double zoomStep = project.getGridSpacing().convertToPixels() * zoom; }
if (gridType == GridType.CROSSHAIR) { // Do not track the area if component is not invalidated and was
g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] { // drawn in the same state.
(float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4)); boolean trackArea = lastDrawnStateMap.get(component) != state;
} else if (gridType == GridType.DOT) {
g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {1f, synchronized (g2d) {
(float) zoomStep - 1}, 0f)); g2dWrapper.startedDrawingComponent();
} if (!trackArea) {
g2dWrapper.stopTracking();
g2dWrapper.setColor(theme.getGridColor()); }
for (double i = zoomStep; i < d.width; i += zoomStep) { // Draw locked components in a new composite.
g2dWrapper.drawLine((int) i, 0, (int) i, d.height - 1); if (lockedComponents.contains(component)) {
} g2d.setComposite(lockedComposite);
for (double j = zoomStep; j < d.height; j += zoomStep) { }
g2dWrapper.drawLine(0, (int) j, d.width - 1, (int) j); // Draw the component through the g2dWrapper.
} try {
} component.draw(g2dWrapper, state, drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper);
} catch (Exception e) {
if (Math.abs(1.0 - zoom) > 1e-4) { LOG.error("Error drawing " + component.getName(), e);
g2dWrapper.scale(zoom, zoom); failedComponents.add(component);
} }
ComponentArea area = g2dWrapper.finishedDrawingComponent();
// Composite mainComposite = g2d.getComposite(); if (trackArea && area != null && !area.getOutlineArea().isEmpty()) {
// Composite alphaComposite = componentAreaMap.put(component, area);
// AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); lastDrawnStateMap.put(component, state);
}
// g2dWrapper.resetTx(); }
}
// componentAreaMap.clear();
for (IDIYComponent<?> component : project.getComponents()) { // Draw control points.
// Do not draw the component if it's filtered out. if (drawOptions.contains(DrawOption.CONTROL_POINTS)) {
if (filter != null && !filter.testComponent(component)) { // Draw unselected points first to make sure they are below.
continue; if (dragInProgress || drawOptions.contains(DrawOption.OUTLINE_MODE)) {
} for (IDIYComponent<?> component : project.getComponents()) {
ComponentState state = ComponentState.NORMAL; for (int i = 0; i < component.getControlPointCount(); i++) {
if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) { VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i);
if (dragInProgress) { if ((groupedComponents.contains(component)
state = ComponentState.DRAGGING; && (visibilityPolicy == VisibilityPolicy.ALWAYS || (selectedComponents.contains(component) && visibilityPolicy == VisibilityPolicy.WHEN_SELECTED)) || (!groupedComponents
} else { .contains(component) && !selectedComponents.contains(component) && component
state = ComponentState.SELECTED; .getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) {
} g2dWrapper.setColor(CONTROL_POINT_COLOR);
} Point controlPoint = component.getControlPoint(i);
// Do not track the area if component is not invalidated and was int pointSize = CONTROL_POINT_SIZE - 2;
// drawn in the same state. g2dWrapper.fillOval(controlPoint.x - pointSize / 2, controlPoint.y - pointSize / 2, pointSize, pointSize);
boolean trackArea = lastDrawnStateMap.get(component) != state; }
}
synchronized (g2d) { }
g2dWrapper.startedDrawingComponent(); }
if (!trackArea) { // Then draw the selected ones.
g2dWrapper.stopTracking(); for (IDIYComponent<?> component : selectedComponents) {
} for (int i = 0; i < component.getControlPointCount(); i++) {
// Draw locked components in a new composite. if (!groupedComponents.contains(component)
if (lockedComponents.contains(component)) { && (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED || component
g2d.setComposite(lockedComposite); .getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) {
}
// Draw the component through the g2dWrapper. Point controlPoint = component.getControlPoint(i);
try { int pointSize = CONTROL_POINT_SIZE;
component.draw(g2dWrapper, state, drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper);
} catch (Exception e) { g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
LOG.error("Error drawing " + component.getName(), e); g2dWrapper.fillOval(controlPoint.x - pointSize / 2, controlPoint.y - pointSize / 2, pointSize, pointSize);
failedComponents.add(component); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
} g2dWrapper.fillOval(controlPoint.x - CONTROL_POINT_SIZE / 2 + 1, controlPoint.y - CONTROL_POINT_SIZE / 2
Area area = g2dWrapper.finishedDrawingComponent(); + 1, CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2);
if (trackArea && area != null && !area.isEmpty()) { }
componentAreaMap.put(component, area); }
lastDrawnStateMap.put(component, state); }
} }
}
} // Draw component slot in a separate composite.
if (componentSlot != null) {
// Draw control points. g2dWrapper.startedDrawingComponent();
if (drawOptions.contains(DrawOption.CONTROL_POINTS)) { g2dWrapper.setComposite(slotComposite);
// Draw unselected points first to make sure they are below. for (IDIYComponent<?> component : componentSlot) {
if (dragInProgress || drawOptions.contains(DrawOption.OUTLINE_MODE)) { try {
for (IDIYComponent<?> component : project.getComponents()) {
for (int i = 0; i < component.getControlPointCount(); i++) { component.draw(g2dWrapper, ComponentState.NORMAL, drawOptions.contains(DrawOption.OUTLINE_MODE), project,
VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i); g2dWrapper);
if ((groupedComponents.contains(component)
&& (visibilityPolicy == VisibilityPolicy.ALWAYS || (selectedComponents.contains(component) && visibilityPolicy == VisibilityPolicy.WHEN_SELECTED)) || (!groupedComponents } catch (Exception e) {
.contains(component) && !selectedComponents.contains(component) && component LOG.error("Error drawing " + component.getName(), e);
.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) { failedComponents.add(component);
g2dWrapper.setColor(CONTROL_POINT_COLOR); }
Point controlPoint = component.getControlPoint(i); }
int pointSize = CONTROL_POINT_SIZE - 2; g2dWrapper.finishedDrawingComponent();
g2dWrapper.fillOval(controlPoint.x - pointSize / 2, controlPoint.y - pointSize / 2, pointSize, pointSize); }
}
} // Draw control points of the component in the slot.
} if (controlPointSlot != null) {
} for (Point point : controlPointSlot) {
// Then draw the selected ones. if (point != null) {
for (IDIYComponent<?> component : selectedComponents) { g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
for (int i = 0; i < component.getControlPointCount(); i++) { g2dWrapper.fillOval(point.x - CONTROL_POINT_SIZE / 2, point.y - CONTROL_POINT_SIZE / 2, CONTROL_POINT_SIZE,
if (!groupedComponents.contains(component) CONTROL_POINT_SIZE);
&& (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED || component g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) { g2dWrapper.fillOval(point.x - CONTROL_POINT_SIZE / 2 + 1, point.y - CONTROL_POINT_SIZE / 2 + 1,
CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2);
Point controlPoint = component.getControlPoint(i); }
int pointSize = CONTROL_POINT_SIZE; }
}
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
g2dWrapper.fillOval(controlPoint.x - pointSize / 2, controlPoint.y - pointSize / 2, pointSize, pointSize); // Go back to the original transformation and zoom in to draw the
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR); // selection rectangle and other similar elements.
g2dWrapper.fillOval(controlPoint.x - CONTROL_POINT_SIZE / 2 + 1, controlPoint.y - CONTROL_POINT_SIZE / 2 // g2d.setTransform(initialTx);
+ 1, CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2); // if ((drawOptions.contains(DrawOption.ZOOM)) && (Math.abs(1.0 -
} // zoomLevel) > 1e-4)) {
} // g2d.scale(zoomLevel, zoomLevel);
} // }
}
// At the end draw selection rectangle if needed.
// Draw component slot in a separate composite. if (drawOptions.contains(DrawOption.SELECTION) && (selectionRect != null)) {
if (componentSlot != null) { g2d.setColor(Color.white);
g2dWrapper.startedDrawingComponent(); g2d.draw(selectionRect);
g2dWrapper.setComposite(slotComposite); g2d.setColor(Color.black);
for (IDIYComponent<?> component : componentSlot) { g2d.setStroke(Constants.DASHED_STROKE);
try { g2d.draw(selectionRect);
}
component.draw(g2dWrapper, ComponentState.NORMAL, drawOptions.contains(DrawOption.OUTLINE_MODE), project,
g2dWrapper); // Draw component area for test
if (debugComponentAreas) {
} catch (Exception e) { g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
LOG.error("Error drawing " + component.getName(), e); g2d.setColor(Color.red);
failedComponents.add(component); for (ComponentArea area : componentAreaMap.values()) {
} g2d.draw(area.getOutlineArea());
} }
g2dWrapper.finishedDrawingComponent(); }
}
// Draw continuity area for test
// Draw control points of the component in the slot. if (debugContinuityAreas) {
if (controlPointSlot != null) { g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
for (Point point : controlPointSlot) { g2d.setColor(Color.green);
if (point != null) { for (ComponentArea area : componentAreaMap.values()) {
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker()); for (Area a : area.getContinuityPositiveAreas())
g2dWrapper.fillOval(point.x - CONTROL_POINT_SIZE / 2, point.y - CONTROL_POINT_SIZE / 2, CONTROL_POINT_SIZE, g2d.draw(a);
CONTROL_POINT_SIZE); }
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR); g2d.setColor(Color.blue);
g2dWrapper.fillOval(point.x - CONTROL_POINT_SIZE / 2 + 1, point.y - CONTROL_POINT_SIZE / 2 + 1, for (ComponentArea area : componentAreaMap.values()) {
CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2); for (Area a : area.getContinuityNegativeAreas())
} g2d.draw(a);
} }
} }
// Go back to the original transformation and zoom in to draw the if (continuityArea != null && (ConfigurationManager.getInstance().readBoolean(IPlugInPort.HIGHLIGHT_CONTINUITY_AREA, false)))
// selection rectangle and other similar elements. {
// g2d.setTransform(initialTx); Composite oldComposite = g2d.getComposite();
// if ((drawOptions.contains(DrawOption.ZOOM)) && (Math.abs(1.0 - g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
// zoomLevel) > 1e-4)) { g2d.setColor(Color.green);
// g2d.scale(zoomLevel, zoomLevel); g2d.fill(continuityArea);
// } g2d.setComposite(oldComposite);
}
// At the end draw selection rectangle if needed.
if (drawOptions.contains(DrawOption.SELECTION) && (selectionRect != null)) { return failedComponents;
g2d.setColor(Color.white); }
g2d.draw(selectionRect);
g2d.setColor(Color.black); public double getZoomLevel() {
g2d.setStroke(Constants.DASHED_STROKE); return zoomLevel;
g2d.draw(selectionRect); }
}
public void setZoomLevel(double zoomLevel) {
// Draw component area for test this.zoomLevel = zoomLevel;
if (debugComponentAreas) { fireZoomChanged();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); // ConfigurationManager.getInstance().writeValue(ZOOM_KEY, zoomLevel);
g2d.setColor(Color.red); }
for (Area area : componentAreaMap.values()) {
g2d.draw(area); public void invalidateComponent(IDIYComponent<?> component) {
} componentAreaMap.remove(component);
} lastDrawnStateMap.remove(component);
}
return failedComponents;
} public ComponentArea getComponentArea(IDIYComponent<?> component) {
return componentAreaMap.get(component);
public double getZoomLevel() { }
return zoomLevel;
} public void clearComponentAreaMap() {
componentAreaMap.clear();
public void setZoomLevel(double zoomLevel) { lastDrawnStateMap.clear();
this.zoomLevel = zoomLevel; }
fireZoomChanged();
// ConfigurationManager.getInstance().writeValue(ZOOM_KEY, zoomLevel); public List<IDIYComponent<?>> findComponentsAt(Point point, Project project) {
} List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
for (int i = 0; i < project.getComponents().size(); i++) {
public void invalidateComponent(IDIYComponent<?> component) { ComponentArea area = componentAreaMap.get(project.getComponents().get(i));
componentAreaMap.remove(component); if (area != null && area.getOutlineArea().contains(point)) {
lastDrawnStateMap.remove(component); components.add(0, project.getComponents().get(i));
} }
}
public Area getComponentArea(IDIYComponent<?> component) { return components;
return componentAreaMap.get(component); }
}
public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean useZoom) {
public void clearComponentAreaMap() { double width = project.getWidth().convertToPixels();
componentAreaMap.clear(); double height = project.getHeight().convertToPixels();
lastDrawnStateMap.clear(); if (useZoom) {
} width *= zoomLevel;
height *= zoomLevel;
public List<IDIYComponent<?>> findComponentsAt(Point point, Project project) { } else {
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>(); width /= Constants.PIXEL_SIZE;
for (int i = 0; i < project.getComponents().size(); i++) { height /= Constants.PIXEL_SIZE;
Area area = componentAreaMap.get(project.getComponents().get(i)); }
if (area != null && area.contains(point)) { return new Dimension((int) width, (int) height);
components.add(0, project.getComponents().get(i)); }
}
} public void fireZoomChanged() {
return components; messageDispatcher.dispatchMessage(EventType.ZOOM_CHANGED, zoomLevel);
} messageDispatcher.dispatchMessage(EventType.REPAINT);
}
public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean useZoom) {
double width = project.getWidth().convertToPixels(); public Theme getTheme() {
double height = project.getHeight().convertToPixels(); return theme;
if (useZoom) { }
width *= zoomLevel;
height *= zoomLevel; public void setTheme(Theme theme) {
} else { this.theme = theme;
width /= Constants.PIXEL_SIZE; ConfigurationManager.getInstance().writeValue(IPlugInPort.THEME_KEY, theme);
height /= Constants.PIXEL_SIZE; messageDispatcher.dispatchMessage(EventType.REPAINT);
} }
return new Dimension((int) width, (int) height);
} @SuppressWarnings("unchecked")
public void findContinuityAreaAtPoint(Project project, Point p) {
public void fireZoomChanged() { // Find all individual continuity areas for all components
messageDispatcher.dispatchMessage(EventType.ZOOM_CHANGED, zoomLevel); List<Area> preliminaryAreas = new ArrayList<Area>();
messageDispatcher.dispatchMessage(EventType.REPAINT); List<Boolean> checkBreakout = new ArrayList<Boolean>();
} List<Connection> connections = new ArrayList<Connection>();
for (IDIYComponent<?> c : project.getComponents()) {
public Theme getTheme() { ComponentArea a = getComponentArea(c);
return theme;
} ComponentType type =
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
public void setTheme(Theme theme) { if (type.isContinuity()) {
this.theme = theme; connections.add(new Connection(c.getControlPoint(0), c.getControlPoint(c.getControlPointCount() - 1)));
ConfigurationManager.getInstance().writeValue(IPlugInPort.THEME_KEY, theme); }
messageDispatcher.dispatchMessage(EventType.REPAINT);
} if (a == null || a.getOutlineArea() == null)
} continue;
if (a.getContinuityPositiveAreas() != null)
for (Area a1 : a.getContinuityPositiveAreas()) {
preliminaryAreas.add(a1);
checkBreakout.add(false);
}
if (a.getContinuityNegativeAreas() != null) {
for (Area na : a.getContinuityNegativeAreas())
for (int i = 0; i < preliminaryAreas.size(); i++) {
Area a1 = preliminaryAreas.get(i);
if (a1.intersects(na.getBounds2D())) {
a1.subtract(na);
checkBreakout.set(i, true);
}
}
}
}
// Check if we need to break some areas out in case they are interrupted
List<Area> areas = new ArrayList<Area>();
for (int i = 0; i < preliminaryAreas.size(); i++) {
Area a = preliminaryAreas.get(i);
if (checkBreakout.get(i))
areas.addAll(tryBreakout(a));
else
areas.add(a);
}
crunchAreas(areas, connections);
for (Area a : areas) {
if (a.contains(p)) {
continuityArea = a;
return;
}
}
continuityArea = null;
}
private boolean crunchAreas(List<Area> areas, List<Connection> connections) {
boolean isChanged = false;
List<Area> newAreas = new ArrayList<Area>();
List<Boolean> consumed = new ArrayList<Boolean>();
for (int i = 0; i < areas.size(); i++) {
consumed.add(false);
}
for (int i = 0; i < areas.size(); i++) {
for (int j = i + 1; j < areas.size(); j++) {
if (consumed.get(j))
continue;
Area a1 = areas.get(i);
Area a2 = areas.get(j);
Area intersection = new Area(a1);
intersection.intersect(a2);
// if the two areas intersect, make a union and consume the second area
if (!intersection.isEmpty()) {
a1.add(a2);
consumed.set(j, true);
} else { // maybe there's a connection between them
for (Connection p : connections) {
if ((a1.contains(p.pointA) && a2.contains(p.pointB)) || (a1.contains(p.pointB) && a2.contains(p.pointA))) {
a1.add(a2);
consumed.set(j, true);
break;
}
}
}
}
}
for (int i = 0; i < areas.size(); i++)
if (!consumed.get(i))
newAreas.add(areas.get(i));
else
isChanged = true;
if (isChanged) {
areas.clear();
areas.addAll(newAreas);
crunchAreas(areas, connections);
}
return isChanged;
}
private List<Area> tryBreakout(Area a) {
List<Area> toReturn = new ArrayList<Area>();
Path2D p = null;
PathIterator pathIterator = a.getPathIterator(null);
while (!pathIterator.isDone()) {
double[] coord = new double[6];
int type = pathIterator.currentSegment(coord);
switch (type) {
case PathIterator.SEG_MOVETO:
if (p != null) {
Area partArea = new Area(p);
toReturn.add(partArea);
}
p = new Path2D.Double();
p.moveTo(coord[0], coord[1]);
break;
case PathIterator.SEG_LINETO:
p.lineTo(coord[0], coord[1]);
break;
case PathIterator.SEG_CUBICTO:
p.curveTo(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]);
break;
case PathIterator.SEG_QUADTO:
p.quadTo(coord[0], coord[1], coord[2], coord[3]);
break;
}
pathIterator.next();
}
if (p != null) {
Area partArea = new Area(p);
toReturn.add(partArea);
}
return toReturn;
}
class Connection {
private Point pointA;
private Point pointB;
public Connection(Point pointA, Point pointB) {
super();
this.pointA = pointA;
this.pointB = pointB;
}
public Point getPointA() {
return pointA;
}
public Point getPointB() {
return pointB;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -63,7 +63,7 @@ public class InstantiationManager {
private static final ComponentType clipboardType = new ComponentType("Clipboard contents", private static final ComponentType clipboardType = new ComponentType("Clipboard contents",
"Components from the clipboard", CreationMethod.SINGLE_CLICK, "Multi", "", "", null, null, 0, false, false, null, "Components from the clipboard", CreationMethod.SINGLE_CLICK, "Multi", "", "", null, null, 0, false, false, null,
false, null, KeywordPolicy.NEVER_SHOW, null); false, null, KeywordPolicy.NEVER_SHOW, null, false);
public InstantiationManager() {} public InstantiationManager() {}
@@ -21,63 +21,63 @@
*/ */
package org.diylc.presenter; package org.diylc.presenter;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; 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.AffineTransform;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
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;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.Utils; import org.diylc.appframework.miscutils.Utils;
import org.diylc.appframework.simplemq.MessageDispatcher; import org.diylc.appframework.simplemq.MessageDispatcher;
import org.diylc.appframework.update.Version; import org.diylc.appframework.update.Version;
import org.diylc.appframework.update.VersionNumber; import org.diylc.appframework.update.VersionNumber;
import org.diylc.common.ComponentType; import org.diylc.common.ComponentType;
import org.diylc.common.DrawOption; import org.diylc.common.DrawOption;
import org.diylc.common.EventType; import org.diylc.common.EventType;
import org.diylc.common.IComponentFiler; import org.diylc.common.IComponentFiler;
import org.diylc.common.IComponentTransformer; import org.diylc.common.IComponentTransformer;
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.PropertyWrapper; import org.diylc.common.PropertyWrapper;
import org.diylc.core.ExpansionMode; import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IView; import org.diylc.core.IView;
import org.diylc.core.Project; import org.diylc.core.Project;
import org.diylc.core.Template; import org.diylc.core.Template;
import org.diylc.core.Theme; import org.diylc.core.Theme;
import org.diylc.core.annotations.IAutoCreator; import org.diylc.core.annotations.IAutoCreator;
import org.diylc.core.measures.Size; import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit; import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.Constants; import org.diylc.utils.Constants;
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver; import com.thoughtworks.xstream.io.xml.DomDriver;
/** /**
* The main presenter class, contains core app logic and drawing routines. * The main presenter class, contains core app logic and drawing routines.
@@ -132,7 +132,7 @@ public class Presenter implements IPlugInPort {
private ProjectFileManager projectFileManager; private ProjectFileManager projectFileManager;
private InstantiationManager instantiationManager; private InstantiationManager instantiationManager;
private Rectangle selectionRect; private Rectangle selectionRect;
private final IView view; private final IView view;
@@ -148,7 +148,7 @@ public class Presenter implements IPlugInPort {
private Point previousDragPoint = null; private Point previousDragPoint = null;
private Project preDragProject = null; private Project preDragProject = null;
private int dragAction; private int dragAction;
private Point previousScaledPoint; private Point previousScaledPoint;
public Presenter(IView view) { public Presenter(IView view) {
super(); super();
@@ -212,8 +212,8 @@ public class Presenter implements IPlugInPort {
} }
for (IDIYComponent<?> component : currentProject.getComponents()) { for (IDIYComponent<?> component : currentProject.getComponents()) {
if (!isComponentLocked(component) && isComponentVisible(component)) { if (!isComponentLocked(component) && isComponentVisible(component)) {
Area area = drawingManager.getComponentArea(component); ComponentArea area = drawingManager.getComponentArea(component);
if (area != null && area.contains(scaledPoint)) { if (area != null && area.getOutlineArea() != null && area.getOutlineArea().contains(scaledPoint)) {
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
} }
} }
@@ -599,7 +599,10 @@ public class Presenter implements IPlugInPort {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, currentProject.clone(), "Add " messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, currentProject.clone(), "Add "
+ componentTypeSlot.getName()); + componentTypeSlot.getName());
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
} }
} else if (ConfigurationManager.getInstance().readBoolean(HIGHLIGHT_CONTINUITY_AREA, false)) {
drawingManager.findContinuityAreaAtPoint(currentProject, scaledPoint);
messageDispatcher.dispatchMessage(EventType.REPAINT);
} else { } else {
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(selectedComponents); List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(selectedComponents);
List<IDIYComponent<?>> components = findComponentsAtScaled(scaledPoint); List<IDIYComponent<?>> components = findComponentsAtScaled(scaledPoint);
@@ -867,11 +870,11 @@ public class Presenter implements IPlugInPort {
Area totalArea = new Area(); Area totalArea = new Area();
for (IDIYComponent<?> c : selectedComponents) { for (IDIYComponent<?> c : selectedComponents) {
Area compArea = drawingManager.getComponentArea(c); ComponentArea compArea = drawingManager.getComponentArea(c);
if (compArea != null) if (compArea != null && compArea.getOutlineArea() != null)
totalArea.add(compArea); totalArea.add(compArea.getOutlineArea());
else else
LOG.info("Area is null"); LOG.debug("Area is null");
} }
if (drawingManager.getZoomLevel() != 1 && applyZoom) { if (drawingManager.getZoomLevel() != 1 && applyZoom) {
totalArea totalArea
@@ -1397,8 +1400,8 @@ public class Presenter implements IPlugInPort {
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(); List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>();
for (IDIYComponent<?> component : currentProject.getComponents()) { for (IDIYComponent<?> component : currentProject.getComponents()) {
if (!isComponentLocked(component) && isComponentVisible(component)) { if (!isComponentLocked(component) && isComponentVisible(component)) {
Area area = drawingManager.getComponentArea(component); ComponentArea area = drawingManager.getComponentArea(component);
if ((area != null) && (selectionRect != null) && area.intersects(selectionRect)) { if ((area != null && area.getOutlineArea() != null) && (selectionRect != null) && area.getOutlineArea().intersects(selectionRect)) {
newSelection.addAll(findAllGroupedComponents(component)); newSelection.addAll(findAllGroupedComponents(component));
} }
} }
@@ -1801,16 +1804,16 @@ public class Presenter implements IPlugInPort {
for (IDIYComponent<?> component : getCurrentProject().getComponents()) { for (IDIYComponent<?> component : getCurrentProject().getComponents()) {
// Skip already selected components or ones that cannot be stuck to // Skip already selected components or ones that cannot be stuck to
// other components. // other components.
Area area = drawingManager.getComponentArea(component); ComponentArea area = drawingManager.getComponentArea(component);
if (newSelection.contains(component) || !component.isControlPointSticky(0) || area == null) if (newSelection.contains(component) || !component.isControlPointSticky(0) || area == null || area.getOutlineArea() == null)
continue; continue;
boolean matches = false; boolean matches = false;
for (IDIYComponent<?> selectedComponent : this.selectedComponents) { for (IDIYComponent<?> selectedComponent : this.selectedComponents) {
Area selectedArea = drawingManager.getComponentArea(selectedComponent); ComponentArea selectedArea = drawingManager.getComponentArea(selectedComponent);
if (selectedArea == null) if (selectedArea == null || selectedArea.getOutlineArea() == null)
continue; continue;
Area intersection = new Area(area); Area intersection = new Area(area.getOutlineArea());
intersection.intersect(selectedArea); intersection.intersect(selectedArea.getOutlineArea());
if (!intersection.isEmpty()) { if (!intersection.isEmpty()) {
matches = true; matches = true;
break; break;
Binary file not shown.
@@ -376,8 +376,10 @@ public class TerminalStrip extends AbstractTransparentComponent<String> {
g2d.setColor(finalBorderColor); g2d.setColor(finalBorderColor);
g2d.draw(mainArea); g2d.draw(mainArea);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR); g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR);
g2d.fill(terminalArea); drawingObserver.startTrackingContinuityArea(true);
g2d.fill(terminalArea);
drawingObserver.stopTrackingContinuityArea();
Color finalTerminalBorderColor; Color finalTerminalBorderColor;
if (outlineMode) { if (outlineMode) {
@@ -94,9 +94,11 @@ public class TriPadBoard extends AbstractBoard {
spacesToDraw = (remainingSpace - stripSize) / spacing; spacesToDraw = (remainingSpace - stripSize) / spacing;
} }
g2d.setColor(stripColor); g2d.setColor(stripColor);
drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect(p.x + spacing - stripSize / 2, p.y - stripSize / 2, spacing * (spacesToDraw - 1) + stripSize, g2d.fillRect(p.x + spacing - stripSize / 2, p.y - stripSize / 2, spacing * (spacesToDraw - 1) + stripSize,
stripSize); stripSize);
drawingObserver.stopTrackingContinuityArea();
g2d.setColor(stripColor.darker()); g2d.setColor(stripColor.darker());
g2d.drawRect(p.x + spacing - stripSize / 2, p.y - stripSize / 2, spacing * (spacesToDraw - 1) + stripSize, g2d.drawRect(p.x + spacing - stripSize / 2, p.y - stripSize / 2, spacing * (spacesToDraw - 1) + stripSize,
@@ -130,9 +132,11 @@ public class TriPadBoard extends AbstractBoard {
spacesToDraw = (remainingSpace - stripSize) / spacing; spacesToDraw = (remainingSpace - stripSize) / spacing;
} }
g2d.setColor(stripColor); g2d.setColor(stripColor);
drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect(p.x - stripSize / 2, p.y + spacing - stripSize / 2, stripSize, spacing * (spacesToDraw - 1) g2d.fillRect(p.x - stripSize / 2, p.y + spacing - stripSize / 2, stripSize, spacing * (spacesToDraw - 1)
+ stripSize); + stripSize);
drawingObserver.stopTrackingContinuityArea();
g2d.setColor(stripColor.darker()); g2d.setColor(stripColor.darker());
g2d.drawRect(p.x - stripSize / 2, p.y + spacing - stripSize / 2, stripSize, spacing * (spacesToDraw - 1) g2d.drawRect(p.x - stripSize / 2, p.y + spacing - stripSize / 2, stripSize, spacing * (spacesToDraw - 1)
+ stripSize); + stripSize);
@@ -84,8 +84,10 @@ public class VeroBoard extends AbstractBoard {
while (p.y < secondPoint.y - spacing) { while (p.y < secondPoint.y - spacing) {
p.x = firstPoint.x; p.x = firstPoint.x;
p.y += spacing; p.y += spacing;
g2d.setColor(stripColor); g2d.setColor(stripColor);
g2d.fillRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize); drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize);
drawingObserver.stopTrackingContinuityArea();
g2d.setColor(stripColor.darker()); g2d.setColor(stripColor.darker());
g2d.drawRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize); g2d.drawRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize);
while (p.x < secondPoint.x - spacing - holeSize) { while (p.x < secondPoint.x - spacing - holeSize) {
@@ -100,8 +102,10 @@ public class VeroBoard extends AbstractBoard {
while (p.x < secondPoint.x - spacing) { while (p.x < secondPoint.x - spacing) {
p.x += spacing; p.x += spacing;
p.y = firstPoint.y; p.y = firstPoint.y;
g2d.setColor(stripColor); g2d.setColor(stripColor);
g2d.fillRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y); drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y);
drawingObserver.stopTrackingContinuityArea();
g2d.setColor(stripColor.darker()); g2d.setColor(stripColor.darker());
g2d.drawRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y); g2d.drawRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y);
while (p.y < secondPoint.y - spacing - holeSize) { while (p.y < secondPoint.y - spacing - holeSize) {
@@ -24,13 +24,14 @@ package org.diylc.components.connectivity;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.CubicCurve2D; import java.awt.geom.CubicCurve2D;
import org.diylc.common.SimpleComponentTransformer; import org.diylc.common.SimpleComponentTransformer;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.PCBLayer; import org.diylc.common.PCBLayer;
import org.diylc.components.AbstractCurvedComponent; import org.diylc.components.AbstractCurvedComponent;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.annotations.BomPolicy; import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty; import org.diylc.core.annotations.EditableProperty;
@@ -58,14 +59,16 @@ public class CurvedTrace extends AbstractCurvedComponent<Void> {
} }
@Override @Override
protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState) { protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
float thickness = (float) size.convertToPixels(); float thickness = (float) size.convertToPixels();
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(thickness));
Color curveColor = Color curveColor =
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color; : color;
g2d.setColor(curveColor); g2d.setColor(curveColor);
g2d.draw(curve); drawingObserver.startTrackingContinuityArea(true);
g2d.draw(curve);
drawingObserver.stopTrackingContinuityArea();
} }
@EditableProperty(name = "Width") @EditableProperty(name = "Width")
@@ -24,12 +24,13 @@ package org.diylc.components.connectivity;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.CubicCurve2D; import java.awt.geom.CubicCurve2D;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
import org.diylc.common.SimpleComponentTransformer; import org.diylc.common.SimpleComponentTransformer;
import org.diylc.components.AbstractCurvedComponent; import org.diylc.components.AbstractCurvedComponent;
import org.diylc.core.ComponentState; import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.annotations.BomPolicy; import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty; import org.diylc.core.annotations.EditableProperty;
@@ -38,7 +39,7 @@ import org.diylc.utils.Constants;
@ComponentDescriptor(name = "Hookup Wire", author = "Branislav Stojkovic", category = "Connectivity", @ComponentDescriptor(name = "Hookup Wire", author = "Branislav Stojkovic", category = "Connectivity",
instanceNamePrefix = "W", description = "Flexible wire with two control points", zOrder = IDIYComponent.COMPONENT, instanceNamePrefix = "W", description = "Flexible wire with two control points", zOrder = IDIYComponent.COMPONENT,
flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, flexibleZOrder = true, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
transformer = SimpleComponentTransformer.class) transformer = SimpleComponentTransformer.class, continuity = true)
public class HookupWire extends AbstractCurvedComponent<Void> { public class HookupWire extends AbstractCurvedComponent<Void> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -54,7 +55,7 @@ public class HookupWire extends AbstractCurvedComponent<Void> {
} }
@Override @Override
protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState) { protected void drawCurve(CubicCurve2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
int thickness = int thickness =
(int) (Math.pow(Math.E, -1.12436 - 0.11594 * gauge.getValue()) * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT)); (int) (Math.pow(Math.E, -1.12436 - 0.11594 * gauge.getValue()) * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT));
Color curveColor = Color curveColor =
@@ -40,7 +40,7 @@ import org.diylc.core.measures.Size;
@ComponentDescriptor(name = "Jumper", author = "Branislav Stojkovic", category = "Connectivity", @ComponentDescriptor(name = "Jumper", author = "Branislav Stojkovic", category = "Connectivity",
creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "J", description = "", creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "J", description = "",
zOrder = IDIYComponent.COMPONENT, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, zOrder = IDIYComponent.COMPONENT, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
transformer = SimpleComponentTransformer.class) transformer = SimpleComponentTransformer.class, continuity = true)
public class Jumper extends AbstractLeadedComponent<Void> { public class Jumper extends AbstractLeadedComponent<Void> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -77,16 +77,20 @@ public class TraceCut extends AbstractComponent<Void> {
if (getCutBetweenHoles()) { if (getCutBetweenHoles()) {
int holeSpacing = getClosestOdd(getHoleSpacing().convertToPixels()); int holeSpacing = getClosestOdd(getHoleSpacing().convertToPixels());
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: boardColor); : boardColor);
g2d.fillRect(point.x - holeSpacing / 2 - cutWidth / 2, point.y - size / 2 - 1, cutWidth, size + 2); drawingObserver.startTrackingContinuityArea(false);
g2d.fillRect(point.x - holeSpacing / 2 - cutWidth / 2, point.y - size / 2 - 1, cutWidth, size + 2);
drawingObserver.stopTrackingContinuityArea();
} else { } else {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: boardColor); : boardColor);
g2d.fillRoundRect(point.x - size / 2, point.y - size / 2, size, size, size, size); drawingObserver.startTrackingContinuityArea(false);
g2d.fillRoundRect(point.x - size / 2, point.y - size / 2, size, size, size, size);
drawingObserver.stopTrackingContinuityArea();
g2d.setColor(Constants.CANVAS_COLOR); g2d.setColor(Constants.CANVAS_COLOR);
int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels()); int holeSize = getClosestOdd((int) HOLE_SIZE.convertToPixels());
g2d.fillOval(point.x - holeSize / 2, point.y - holeSize / 2, holeSize, holeSize); g2d.fillOval(point.x - holeSize / 2, point.y - holeSize / 2, holeSize, holeSize);
g2d.setColor(boardColor.darker()); g2d.setColor(boardColor.darker());
g2d.drawOval(point.x - holeSize / 2, point.y - holeSize / 2, holeSize, holeSize); g2d.drawOval(point.x - holeSize / 2, point.y - holeSize / 2, holeSize, holeSize);
} }
+1 -1
View File
@@ -11,5 +11,5 @@
<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;Library&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;DIYLC&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;diylc-core&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;diylc-library&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;default/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;"/> <stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;Library&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;DIYLC&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;diylc-core&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;diylc-library&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;default/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.diylc.DIYLCStarter"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.diylc.DIYLCStarter"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="diylc-swing"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="diylc-swing"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-splash:splash.png -Xms256m -Xmx512m -Dorg.diylc.scriptRun=true -Ddorg.diylc.debugComponentAreas=true"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-splash:splash.png -Xms256m -Xmx512m -Dorg.diylc.scriptRun=true -Ddorg.diylc.debugContinuityAreas=true"/>
</launchConfiguration> </launchConfiguration>
Binary file not shown.
Binary file not shown.
@@ -99,7 +99,10 @@ public class ConfigPlugin implements IPlugIn {
CONFIG_MENU); CONFIG_MENU);
swingUI.injectMenuAction( swingUI.injectMenuAction(
ActionFactory.getInstance() ActionFactory.getInstance()
.createConfigAction(plugInPort, "Sticky Points", IPlugInPort.STICKY_POINTS_KEY, true), CONFIG_MENU); .createConfigAction(plugInPort, "Sticky Points", IPlugInPort.STICKY_POINTS_KEY, true), CONFIG_MENU);
swingUI.injectMenuAction(
ActionFactory.getInstance()
.createConfigAction(plugInPort, "Highlighted Connected Areas", IPlugInPort.HIGHLIGHT_CONTINUITY_AREA, false), CONFIG_MENU);
File themeDir = new File("themes"); File themeDir = new File("themes");
if (themeDir.exists()) { if (themeDir.exists()) {
+4
View File
@@ -1874,6 +1874,10 @@
<releaseDate>2018-12-11 00:00:00.000 CET</releaseDate> <releaseDate>2018-12-11 00:00:00.000 CET</releaseDate>
<name></name> <name></name>
<changes> <changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Highlight connected areas through copper traces, leads, jumpers, etc...</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType> <changeType>NEW_FEATURE</changeType>
<description>Holding "shift" key switches mouse wheel scrolling function from vertical to horizontal</description> <description>Holding "shift" key switches mouse wheel scrolling function from vertical to horizontal</description>