mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
Add ability to merge disjoint continuity areas
This commit is contained in:
@@ -19,8 +19,8 @@
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.core;
|
||||
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Interface for tracking component drawing process. Components may use it to stop or restart
|
||||
* tracking. Anything drawn while tracking is stopped will not be added to the mouse hot-spot area.
|
||||
@@ -28,14 +28,41 @@ package org.diylc.core;
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IDrawingObserver {
|
||||
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should start tracking the drawing process.
|
||||
*/
|
||||
void stopTracking();
|
||||
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should stop tracking the drawing process.
|
||||
*/
|
||||
void startTracking();
|
||||
|
||||
void stopTrackingContinuityArea();
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should start tracking conductive continuity areas.
|
||||
*
|
||||
* @param positive designates if the area should be additive or subtractive
|
||||
*/
|
||||
void startTrackingContinuityArea(boolean positive);
|
||||
|
||||
boolean isTrackingContinuityArea();
|
||||
/**
|
||||
* Notifies the observer that it should stop tracking conductive continuity areas.
|
||||
*/
|
||||
void stopTrackingContinuityArea();
|
||||
|
||||
/**
|
||||
* Checks if we are tracking continuity ares.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isTrackingContinuityArea();
|
||||
|
||||
/**
|
||||
* Allows us to connect multiple disjoint continuity areas by specifying the same continuity markers.
|
||||
* By default it is set to null and does not connect disjoint areas.
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
void setContinuityMarker(String marker);
|
||||
}
|
||||
|
||||
@@ -22,15 +22,15 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.geom.Area;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ComponentArea {
|
||||
|
||||
private Area outlineArea;
|
||||
private List<Area> continuityPositiveAreas;
|
||||
private List<Area> continuityNegativeAreas;
|
||||
private Collection<Area> continuityPositiveAreas;
|
||||
private Collection<Area> continuityNegativeAreas;
|
||||
|
||||
public ComponentArea(Area outlineArea, List<Area> continuityPositiveAreas, List<Area> continuityNegativeAreas) {
|
||||
public ComponentArea(Area outlineArea, Collection<Area> continuityPositiveAreas, Collection<Area> continuityNegativeAreas) {
|
||||
super();
|
||||
this.outlineArea = outlineArea;
|
||||
this.continuityPositiveAreas = continuityPositiveAreas;
|
||||
@@ -41,11 +41,11 @@ public class ComponentArea {
|
||||
return outlineArea;
|
||||
}
|
||||
|
||||
public List<Area> getContinuityPositiveAreas() {
|
||||
public Collection<Area> getContinuityPositiveAreas() {
|
||||
return continuityPositiveAreas;
|
||||
}
|
||||
|
||||
public List<Area> getContinuityNegativeAreas() {
|
||||
public Collection<Area> getContinuityNegativeAreas() {
|
||||
return continuityNegativeAreas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,13 +532,15 @@ public class DrawingManager {
|
||||
|
||||
if (a == null || a.getOutlineArea() == null)
|
||||
continue;
|
||||
if (a.getContinuityPositiveAreas() != null)
|
||||
for (Area a1 : a.getContinuityPositiveAreas()) {
|
||||
Collection<Area> positiveAreas = a.getContinuityPositiveAreas();
|
||||
if (positiveAreas != null)
|
||||
for (Area a1 : positiveAreas) {
|
||||
preliminaryAreas.add(a1);
|
||||
checkBreakout.add(false);
|
||||
}
|
||||
if (a.getContinuityNegativeAreas() != null) {
|
||||
for (Area na : a.getContinuityNegativeAreas())
|
||||
Collection<Area> negativeAreas = a.getContinuityNegativeAreas();
|
||||
if (negativeAreas != null) {
|
||||
for (Area na : negativeAreas)
|
||||
for (int i = 0; i < preliminaryAreas.size(); i++) {
|
||||
Area a1 = preliminaryAreas.get(i);
|
||||
if (a1.intersects(na.getBounds2D())) {
|
||||
@@ -546,17 +548,17 @@ public class DrawingManager {
|
||||
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);
|
||||
if (checkBreakout.get(i))
|
||||
areas.addAll(tryBreakout(a));
|
||||
else
|
||||
areas.add(a);
|
||||
}
|
||||
|
||||
expandConnections(connections);
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.awt.geom.Area;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.NoninvertibleTransformException;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
@@ -49,10 +50,17 @@ import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.awt.image.renderable.RenderableImage;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.diylc.common.ObjectCache;
|
||||
import org.diylc.common.ZoomableStroke;
|
||||
@@ -70,12 +78,16 @@ import org.diylc.core.IDrawingObserver;
|
||||
class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
|
||||
public static int LINE_SENSITIVITY_MARGIN = 2;
|
||||
public static int CURVE_SENSITIVITY = 6;
|
||||
public static int CURVE_SENSITIVITY = 6;
|
||||
|
||||
private boolean drawingComponent = false;
|
||||
private boolean trackingAllowed = true;
|
||||
private boolean trackingContinuityAllowed = false;
|
||||
private boolean trackingContinuityPositive = true;
|
||||
|
||||
private HashMap<String, Integer> trackingStacks = new HashMap<String, Integer>();
|
||||
|
||||
private int uniqueCounter = 0;
|
||||
|
||||
private Graphics2D canvasGraphics;
|
||||
private Stroke originalStroke;
|
||||
@@ -86,11 +98,12 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
private AffineTransform currentTx;
|
||||
private AffineTransform initialTx;
|
||||
private Area currentArea;
|
||||
private List<Area> continuityPositiveAreas;
|
||||
private List<Area> continuityNegativeAreas;
|
||||
private Map<String, Area> continuityPositiveAreas;
|
||||
private Map<String, Area> continuityNegativeAreas;
|
||||
private String continuityMarker;
|
||||
private Shape lastShape;
|
||||
|
||||
private double zoom;
|
||||
private double zoom;
|
||||
|
||||
/**
|
||||
* Creates a wrapper around specified {@link Graphics2D} object.
|
||||
@@ -102,8 +115,9 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
this.canvasGraphics = canvasGraphics;
|
||||
this.zoom = zoom;
|
||||
currentArea = new Area();
|
||||
continuityPositiveAreas = new ArrayList<Area>();
|
||||
continuityNegativeAreas = new ArrayList<Area>();
|
||||
continuityPositiveAreas = new HashMap<String, Area>();
|
||||
continuityNegativeAreas = new HashMap<String, Area>();
|
||||
continuityMarker = null;
|
||||
currentTx = new AffineTransform();
|
||||
}
|
||||
|
||||
@@ -113,8 +127,10 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
public void startedDrawingComponent() {
|
||||
drawingComponent = true;
|
||||
currentArea = new Area();
|
||||
continuityPositiveAreas = new ArrayList<Area>();
|
||||
continuityNegativeAreas = new ArrayList<Area>();
|
||||
continuityPositiveAreas = new HashMap<String, Area>();
|
||||
continuityNegativeAreas = new HashMap<String, Area>();
|
||||
// trackingStacks.clear();
|
||||
continuityMarker = null;
|
||||
originalStroke = canvasGraphics.getStroke();
|
||||
originalColor = canvasGraphics.getColor();
|
||||
originalTx = canvasGraphics.getTransform();
|
||||
@@ -138,7 +154,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
canvasGraphics.setTransform(originalTx);
|
||||
canvasGraphics.setComposite(originalComposite);
|
||||
canvasGraphics.setFont(originalFont);
|
||||
return new ComponentArea(currentArea, continuityPositiveAreas, continuityNegativeAreas);
|
||||
// Map<String, Integer> sorted = sortByComparator(trackingStacks, false);
|
||||
return new ComponentArea(currentArea, continuityPositiveAreas.values(), continuityNegativeAreas.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,7 +182,12 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
@Override
|
||||
public boolean isTrackingContinuityArea() {
|
||||
return trackingContinuityAllowed;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContinuityMarker(String marker) {
|
||||
continuityMarker = marker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends shape interior to the current component area.
|
||||
@@ -183,17 +205,40 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
area.transform(currentTx);
|
||||
|
||||
if (trackingAllowed)
|
||||
currentArea.add(area);
|
||||
currentArea.add(area);
|
||||
|
||||
Map<String, Area> toAdd;
|
||||
if (trackingContinuityAllowed) {
|
||||
if (trackingContinuityPositive)
|
||||
continuityPositiveAreas.add(area);
|
||||
toAdd = continuityPositiveAreas;
|
||||
else
|
||||
continuityNegativeAreas.add(area);
|
||||
toAdd = continuityNegativeAreas;
|
||||
String marker = continuityMarker == null ? ("internalUnique" + uniqueCounter++) : continuityMarker;
|
||||
if (continuityMarker == null) {
|
||||
toAdd.put(marker, area);
|
||||
// markStack();
|
||||
} else {
|
||||
Area current = toAdd.getOrDefault(marker, null);
|
||||
if (current == null) {
|
||||
toAdd.put(marker, area);
|
||||
// markStack();
|
||||
} else
|
||||
current.add(area);
|
||||
}
|
||||
}
|
||||
lastShape = s;
|
||||
}
|
||||
}
|
||||
|
||||
private void markStack() {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
new Throwable().printStackTrace(pw);
|
||||
String stack = sw.toString();
|
||||
Integer currentCount = trackingStacks.getOrDefault(stack, 0);
|
||||
currentCount++;
|
||||
trackingStacks.put(stack, currentCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends shape outline to the current component area.
|
||||
@@ -202,7 +247,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
*/
|
||||
private void appendShapeOutline(Shape s) {
|
||||
// Do not add shape outline if the same shape has been filled recently.
|
||||
if (!drawingComponent || !trackingAllowed || s.equals(lastShape)) {
|
||||
if (!drawingComponent || (!trackingAllowed && !trackingContinuityAllowed) || s.equals(lastShape)) {
|
||||
return;
|
||||
}
|
||||
Stroke stroke = getStroke();
|
||||
@@ -553,8 +598,15 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolyline(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.drawPolyline(points, points2, points3);
|
||||
public void drawPolyline(int[] pointsX, int[] pointsY, int pointCount) {
|
||||
canvasGraphics.drawPolyline(pointsX, pointsY, pointCount);
|
||||
if (drawingComponent && (trackingAllowed || trackingContinuityAllowed) && pointCount > 1) {
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(pointsX[0], pointsY[0]);
|
||||
for (int i = 1; i < pointCount; i++)
|
||||
path.lineTo(pointsX[i], pointsY[i]);
|
||||
appendShapeOutline(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -667,4 +719,30 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
public void setXORMode(Color c1) {
|
||||
canvasGraphics.setXORMode(c1);
|
||||
}
|
||||
|
||||
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap,
|
||||
final boolean order) {
|
||||
List<Entry<String, Integer>> list =
|
||||
new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
|
||||
|
||||
// Sorting the list based on values
|
||||
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
|
||||
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
|
||||
if (order) {
|
||||
return o1.getValue().compareTo(o2.getValue());
|
||||
} else {
|
||||
return o2.getValue().compareTo(o1.getValue());
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Maintaining insertion order with the help of LinkedList
|
||||
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
|
||||
for (Entry<String, Integer> entry : list) {
|
||||
sortedMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return sortedMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1946,6 +1946,10 @@ public class Presenter implements IPlugInPort {
|
||||
LOG.info(String.format("expandSelection(%s)", expansionMode));
|
||||
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(this.selectedComponents);
|
||||
List<Netlist> netlists = extractNetlists(false);
|
||||
|
||||
if (netlists == null)
|
||||
return;
|
||||
|
||||
List<Set<IDIYComponent<?>>> allGroups = NetlistAnalyzer.extractComponentGroups(netlists);
|
||||
// Find control points of all selected components and all types
|
||||
Set<String> selectedNamePrefixes = new HashSet<String>();
|
||||
|
||||
Binary file not shown.
@@ -324,7 +324,8 @@ public class Breadboard extends AbstractComponent<Void> {
|
||||
@Override
|
||||
public Point getControlPoint(int index) {
|
||||
if (index == 0)
|
||||
return point;
|
||||
return point;
|
||||
// create a synthetic second control point for clipping check and to make sure that we cannot drag the right side of the board off the screen
|
||||
double spacing = SPACING.convertToPixels();
|
||||
int holeCount = getBreadboardSize() == BreadboardSize.Full ? 63 : 30;
|
||||
// adjust the angle
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user