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,23 +1,19 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
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; package org.diylc.common;
@@ -53,11 +49,12 @@ public class ComponentType {
private IComponentTransformer transformer; private IComponentTransformer transformer;
private KeywordPolicy keywordPolicy; private KeywordPolicy keywordPolicy;
private String keywordTag; private String keywordTag;
private boolean continuity;
public ComponentType(String name, String description, CreationMethod creationMethod, String category, public ComponentType(String name, String description, CreationMethod creationMethod, String category,
String namePrefix, String author, Icon icon, Class<? extends IDIYComponent<?>> instanceClass, double zOrder, String namePrefix, String author, Icon icon, Class<? extends IDIYComponent<?>> instanceClass, double zOrder,
boolean flexibleZOrder, boolean stretchable, BomPolicy bomPolicy, boolean autoEdit, IComponentTransformer transformer, boolean flexibleZOrder, boolean stretchable, BomPolicy bomPolicy, boolean autoEdit,
KeywordPolicy keywordPolicy, String keywordTag) { IComponentTransformer transformer, KeywordPolicy keywordPolicy, String keywordTag, boolean continuity) {
super(); super();
this.name = name; this.name = name;
this.description = description; this.description = description;
@@ -75,6 +72,7 @@ public class ComponentType {
this.transformer = transformer; this.transformer = transformer;
this.keywordPolicy = keywordPolicy; this.keywordPolicy = keywordPolicy;
this.keywordTag = keywordTag; this.keywordTag = keywordTag;
this.continuity = continuity;
} }
public String getName() { public String getName() {
@@ -141,6 +139,10 @@ public class ComponentType {
return keywordTag; return keywordTag;
} }
public boolean isContinuity() {
return continuity;
}
@Override @Override
public String toString() { public String toString() {
return name; return name;
@@ -71,6 +71,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
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,6 +32,7 @@ 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;
@@ -86,6 +87,10 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
} }
} }
protected boolean IsCopperArea() {
return false;
}
@Override @Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) { IDrawingObserver drawingObserver) {
@@ -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,13 +298,18 @@ 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));
leadColor = getLeadColorForPainting(componentState); leadColor = getLeadColorForPainting(componentState);
@@ -32,4 +32,8 @@ public interface IDrawingObserver {
void stopTracking(); void stopTracking();
void startTracking(); void startTracking();
void stopTrackingContinuityArea();
void startTrackingContinuityArea(boolean positive);
} }
@@ -118,4 +118,11 @@ public @interface ComponentDescriptor {
*/ */
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;
}
}
@@ -98,6 +98,7 @@ public class ComponentProcessor {
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();
@@ -114,6 +115,7 @@ public class ComponentProcessor {
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 = "";
@@ -129,6 +131,7 @@ public class ComponentProcessor {
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,23 +1,19 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
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; package org.diylc.presenter;
@@ -31,6 +27,8 @@ import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@@ -41,6 +39,7 @@ import java.util.Set;
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.simplemq.MessageDispatcher; import org.diylc.appframework.simplemq.MessageDispatcher;
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.GridType; import org.diylc.common.GridType;
@@ -69,6 +68,7 @@ public class DrawingManager {
public static final String ZOOM_KEY = "zoom"; public static final String ZOOM_KEY = "zoom";
public static String DEBUG_COMPONENT_AREAS = "org.diylc.debugComponentAreas"; public static String DEBUG_COMPONENT_AREAS = "org.diylc.debugComponentAreas";
public static String DEBUG_CONTINUITY_AREAS = "org.diylc.debugContinuityAreas";
public static Color CONTROL_POINT_COLOR = Color.blue; public static Color CONTROL_POINT_COLOR = Color.blue;
public static Color SELECTED_CONTROL_POINT_COLOR = Color.green; public static Color SELECTED_CONTROL_POINT_COLOR = Color.green;
@@ -77,11 +77,13 @@ public class DrawingManager {
Constants.DEFAULT_THEME); Constants.DEFAULT_THEME);
// Keeps Area object of each drawn component. // Keeps Area object of each drawn component.
private Map<IDIYComponent<?>, Area> componentAreaMap; private Map<IDIYComponent<?>, ComponentArea> componentAreaMap;
// Maps components to the last state they are drawn in. Also, used to // Maps components to the last state they are drawn in. Also, used to
// determine which components are invalidated when they are not in the map. // determine which components are invalidated when they are not in the map.
private Map<IDIYComponent<?>, ComponentState> lastDrawnStateMap; private Map<IDIYComponent<?>, ComponentState> lastDrawnStateMap;
private Area continuityArea;
private Composite slotComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); private Composite slotComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
private Composite lockedComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); private Composite lockedComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
private List<IDIYComponent<?>> failedComponents = new ArrayList<IDIYComponent<?>>(); private List<IDIYComponent<?>> failedComponents = new ArrayList<IDIYComponent<?>>();
@@ -92,14 +94,18 @@ public class DrawingManager {
private MessageDispatcher<EventType> messageDispatcher; private MessageDispatcher<EventType> messageDispatcher;
private boolean debugComponentAreas; private boolean debugComponentAreas;
private boolean debugContinuityAreas;
public DrawingManager(MessageDispatcher<EventType> messageDispatcher) { public DrawingManager(MessageDispatcher<EventType> messageDispatcher) {
super(); super();
this.messageDispatcher = messageDispatcher; this.messageDispatcher = messageDispatcher;
componentAreaMap = new HashMap<IDIYComponent<?>, Area>(); componentAreaMap = new HashMap<IDIYComponent<?>, ComponentArea>();
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>(); lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS); String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS);
debugComponentAreas = debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true"); debugComponentAreas = debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true");
String debugContinuityAreasStr = System.getProperty(DEBUG_CONTINUITY_AREAS);
debugContinuityAreas = debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true");
} }
/** /**
@@ -230,8 +236,8 @@ public class DrawingManager {
LOG.error("Error drawing " + component.getName(), e); LOG.error("Error drawing " + component.getName(), e);
failedComponents.add(component); failedComponents.add(component);
} }
Area area = g2dWrapper.finishedDrawingComponent(); ComponentArea area = g2dWrapper.finishedDrawingComponent();
if (trackArea && area != null && !area.isEmpty()) { if (trackArea && area != null && !area.getOutlineArea().isEmpty()) {
componentAreaMap.put(component, area); componentAreaMap.put(component, area);
lastDrawnStateMap.put(component, state); lastDrawnStateMap.put(component, state);
} }
@@ -330,11 +336,35 @@ public class DrawingManager {
if (debugComponentAreas) { if (debugComponentAreas) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.setColor(Color.red); g2d.setColor(Color.red);
for (Area area : componentAreaMap.values()) { for (ComponentArea area : componentAreaMap.values()) {
g2d.draw(area); g2d.draw(area.getOutlineArea());
} }
} }
// Draw continuity area for test
if (debugContinuityAreas) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.setColor(Color.green);
for (ComponentArea area : componentAreaMap.values()) {
for (Area a : area.getContinuityPositiveAreas())
g2d.draw(a);
}
g2d.setColor(Color.blue);
for (ComponentArea area : componentAreaMap.values()) {
for (Area a : area.getContinuityNegativeAreas())
g2d.draw(a);
}
}
if (continuityArea != null && (ConfigurationManager.getInstance().readBoolean(IPlugInPort.HIGHLIGHT_CONTINUITY_AREA, false)))
{
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setColor(Color.green);
g2d.fill(continuityArea);
g2d.setComposite(oldComposite);
}
return failedComponents; return failedComponents;
} }
@@ -353,7 +383,7 @@ public class DrawingManager {
lastDrawnStateMap.remove(component); lastDrawnStateMap.remove(component);
} }
public Area getComponentArea(IDIYComponent<?> component) { public ComponentArea getComponentArea(IDIYComponent<?> component) {
return componentAreaMap.get(component); return componentAreaMap.get(component);
} }
@@ -365,8 +395,8 @@ public class DrawingManager {
public List<IDIYComponent<?>> findComponentsAt(Point point, Project project) { public List<IDIYComponent<?>> findComponentsAt(Point point, Project project) {
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>(); List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
for (int i = 0; i < project.getComponents().size(); i++) { for (int i = 0; i < project.getComponents().size(); i++) {
Area area = componentAreaMap.get(project.getComponents().get(i)); ComponentArea area = componentAreaMap.get(project.getComponents().get(i));
if (area != null && area.contains(point)) { if (area != null && area.getOutlineArea().contains(point)) {
components.add(0, project.getComponents().get(i)); components.add(0, project.getComponents().get(i));
} }
} }
@@ -400,4 +430,162 @@ public class DrawingManager {
ConfigurationManager.getInstance().writeValue(IPlugInPort.THEME_KEY, theme); ConfigurationManager.getInstance().writeValue(IPlugInPort.THEME_KEY, theme);
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} }
@SuppressWarnings("unchecked")
public void findContinuityAreaAtPoint(Project project, Point p) {
// Find all individual continuity areas for all components
List<Area> preliminaryAreas = new ArrayList<Area>();
List<Boolean> checkBreakout = new ArrayList<Boolean>();
List<Connection> connections = new ArrayList<Connection>();
for (IDIYComponent<?> c : project.getComponents()) {
ComponentArea a = getComponentArea(c);
ComponentType type =
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
if (type.isContinuity()) {
connections.add(new Connection(c.getControlPoint(0), c.getControlPoint(c.getControlPointCount() - 1)));
}
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;
}
}
} }
@@ -1,23 +1,19 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
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; package org.diylc.presenter;
@@ -57,6 +53,8 @@ import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage; import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage; import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.diylc.common.ObjectCache; import org.diylc.common.ObjectCache;
@@ -78,6 +76,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
private boolean drawingComponent = false; private boolean drawingComponent = false;
private boolean trackingAllowed = true; private boolean trackingAllowed = true;
private boolean trackingContinuityAllowed = false;
private boolean trackingContinuityPositive = true;
private Graphics2D canvasGraphics; private Graphics2D canvasGraphics;
private Stroke originalStroke; private Stroke originalStroke;
@@ -88,6 +88,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
private AffineTransform currentTx; private AffineTransform currentTx;
private AffineTransform initialTx; private AffineTransform initialTx;
private Area currentArea; private Area currentArea;
private List<Area> currentContinuityPositiveAreas;
private List<Area> currentContinuityNegativeAreas;
private Shape lastShape; private Shape lastShape;
private double zoom; private double zoom;
@@ -102,6 +104,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
this.canvasGraphics = canvasGraphics; this.canvasGraphics = canvasGraphics;
this.zoom = zoom; this.zoom = zoom;
currentArea = new Area(); currentArea = new Area();
currentContinuityPositiveAreas = new ArrayList<Area>();
currentContinuityNegativeAreas = new ArrayList<Area>();
currentTx = new AffineTransform(); currentTx = new AffineTransform();
} }
@@ -111,6 +115,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
public void startedDrawingComponent() { public void startedDrawingComponent() {
drawingComponent = true; drawingComponent = true;
currentArea = new Area(); currentArea = new Area();
currentContinuityPositiveAreas = new ArrayList<Area>();
currentContinuityNegativeAreas = new ArrayList<Area>();
originalStroke = canvasGraphics.getStroke(); originalStroke = canvasGraphics.getStroke();
originalColor = canvasGraphics.getColor(); originalColor = canvasGraphics.getColor();
originalTx = canvasGraphics.getTransform(); originalTx = canvasGraphics.getTransform();
@@ -127,14 +133,14 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
* *
* @return * @return
*/ */
public Area finishedDrawingComponent() { public ComponentArea finishedDrawingComponent() {
drawingComponent = false; drawingComponent = false;
canvasGraphics.setStroke(originalStroke); canvasGraphics.setStroke(originalStroke);
canvasGraphics.setColor(originalColor); canvasGraphics.setColor(originalColor);
canvasGraphics.setTransform(originalTx); canvasGraphics.setTransform(originalTx);
canvasGraphics.setComposite(originalComposite); canvasGraphics.setComposite(originalComposite);
canvasGraphics.setFont(originalFont); canvasGraphics.setFont(originalFont);
return currentArea; return new ComponentArea(currentArea, currentContinuityPositiveAreas, currentContinuityNegativeAreas);
} }
@Override @Override
@@ -147,13 +153,25 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
this.trackingAllowed = false; this.trackingAllowed = false;
} }
@Override
public void startTrackingContinuityArea(boolean positive) {
this.trackingContinuityAllowed = true;
this.trackingContinuityPositive = positive;
}
@Override
public void stopTrackingContinuityArea() {
this.trackingContinuityAllowed = false;
}
/** /**
* Appends shape interior to the current component area. * Appends shape interior to the current component area.
* *
* @param s * @param s
*/ */
private void appendShape(Shape s) { private void appendShape(Shape s) {
if (!drawingComponent || !trackingAllowed) { if (!drawingComponent || (!trackingAllowed && !trackingContinuityAllowed)) {
return; return;
} }
Rectangle2D bounds = s.getBounds2D(); Rectangle2D bounds = s.getBounds2D();
@@ -161,7 +179,16 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
if (bounds.getWidth() > 1 && bounds.getHeight() > 1) { if (bounds.getWidth() > 1 && bounds.getHeight() > 1) {
Area area = new Area(s); Area area = new Area(s);
area.transform(currentTx); area.transform(currentTx);
if (trackingAllowed)
currentArea.add(area); currentArea.add(area);
if (trackingContinuityAllowed) {
if (trackingContinuityPositive)
currentContinuityPositiveAreas.add(area);
else
currentContinuityNegativeAreas.add(area);
}
lastShape = s; lastShape = s;
} }
} }
@@ -580,7 +607,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void drawLine(int x1, int y1, int x2, int y2) { public void drawLine(int x1, int y1, int x2, int y2) {
canvasGraphics.drawLine(x1, y1, x2, y2); canvasGraphics.drawLine(x1, y1, x2, y2);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShapeOutline(new Line2D.Double(x1, y1, x2, y2)); appendShapeOutline(new Line2D.Double(x1, y1, x2, y2));
} }
} }
@@ -588,7 +615,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void drawOval(int x, int y, int width, int height) { public void drawOval(int x, int y, int width, int height) {
canvasGraphics.drawOval(x, y, width, height); canvasGraphics.drawOval(x, y, width, height);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShapeOutline(new Ellipse2D.Double(x, y, width, height)); appendShapeOutline(new Ellipse2D.Double(x, y, width, height));
} }
} }
@@ -596,7 +623,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void drawPolygon(int[] points, int[] points2, int points3) { public void drawPolygon(int[] points, int[] points2, int points3) {
canvasGraphics.drawPolygon(points, points2, points3); canvasGraphics.drawPolygon(points, points2, points3);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShapeOutline(new Polygon(points, points2, points3)); appendShapeOutline(new Polygon(points, points2, points3));
} }
} }
@@ -609,7 +636,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
canvasGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight); canvasGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShapeOutline(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight)); appendShapeOutline(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
} }
} }
@@ -617,7 +644,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
canvasGraphics.fillArc(x, y, width, height, startAngle, arcAngle); canvasGraphics.fillArc(x, y, width, height, startAngle, arcAngle);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShape(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.PIE)); appendShape(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.PIE));
} }
} }
@@ -625,7 +652,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void fillOval(int x, int y, int width, int height) { public void fillOval(int x, int y, int width, int height) {
canvasGraphics.fillOval(x, y, width, height); canvasGraphics.fillOval(x, y, width, height);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShape(new Ellipse2D.Double(x, y, width, height)); appendShape(new Ellipse2D.Double(x, y, width, height));
} }
} }
@@ -633,7 +660,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void fillPolygon(int[] points, int[] points2, int points3) { public void fillPolygon(int[] points, int[] points2, int points3) {
canvasGraphics.fillPolygon(points, points2, points3); canvasGraphics.fillPolygon(points, points2, points3);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShape(new Polygon(points, points2, points3)); appendShape(new Polygon(points, points2, points3));
} }
} }
@@ -641,7 +668,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void drawRect(int x, int y, int width, int height) { public void drawRect(int x, int y, int width, int height) {
canvasGraphics.drawRect(x, y, width, height); canvasGraphics.drawRect(x, y, width, height);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShapeOutline(new Rectangle(x, y, width, height)); appendShapeOutline(new Rectangle(x, y, width, height));
} }
} }
@@ -649,7 +676,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void fillRect(int x, int y, int width, int height) { public void fillRect(int x, int y, int width, int height) {
canvasGraphics.fillRect(x, y, width, height); canvasGraphics.fillRect(x, y, width, height);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShape(new Rectangle(x, y, width, height)); appendShape(new Rectangle(x, y, width, height));
} }
} }
@@ -657,7 +684,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override @Override
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
canvasGraphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight); canvasGraphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
if (drawingComponent && trackingAllowed) { if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShape(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight)); appendShape(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
} }
} }
@@ -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() {}
@@ -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);
} }
} }
@@ -600,6 +600,9 @@ public class Presenter implements IPlugInPort {
+ 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.
@@ -377,7 +377,9 @@ public class TerminalStrip extends AbstractTransparentComponent<String> {
g2d.draw(mainArea); g2d.draw(mainArea);
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR); g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : TERMINAL_COLOR);
drawingObserver.startTrackingContinuityArea(true);
g2d.fill(terminalArea); g2d.fill(terminalArea);
drawingObserver.stopTrackingContinuityArea();
Color finalTerminalBorderColor; Color finalTerminalBorderColor;
if (outlineMode) { if (outlineMode) {
@@ -95,8 +95,10 @@ public class TriPadBoard extends AbstractBoard {
} }
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,
@@ -131,8 +133,10 @@ public class TriPadBoard extends AbstractBoard {
} }
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);
@@ -85,7 +85,9 @@ public class VeroBoard extends AbstractBoard {
p.x = firstPoint.x; p.x = firstPoint.x;
p.y += spacing; p.y += spacing;
g2d.setColor(stripColor); g2d.setColor(stripColor);
drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize); 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) {
@@ -101,7 +103,9 @@ public class VeroBoard extends AbstractBoard {
p.x += spacing; p.x += spacing;
p.y = firstPoint.y; p.y = firstPoint.y;
g2d.setColor(stripColor); g2d.setColor(stripColor);
drawingObserver.startTrackingContinuityArea(true);
g2d.fillRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y); 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) {
@@ -31,6 +31,7 @@ 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);
drawingObserver.startTrackingContinuityArea(true);
g2d.draw(curve); g2d.draw(curve);
drawingObserver.stopTrackingContinuityArea();
} }
@EditableProperty(name = "Width") @EditableProperty(name = "Width")
@@ -30,6 +30,7 @@ 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;
@@ -78,11 +78,15 @@ public class TraceCut extends AbstractComponent<Void> {
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);
drawingObserver.startTrackingContinuityArea(false);
g2d.fillRect(point.x - holeSpacing / 2 - cutWidth / 2, point.y - size / 2 - 1, cutWidth, size + 2); 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);
drawingObserver.startTrackingContinuityArea(false);
g2d.fillRoundRect(point.x - size / 2, point.y - size / 2, size, size, size, size); 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());
+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.
@@ -100,6 +100,9 @@ public class ConfigPlugin implements IPlugIn {
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>