diff --git a/diylc/diylc-core/src/org/diylc/presenter/AreaUtils.java b/diylc/diylc-core/src/org/diylc/presenter/AreaUtils.java
new file mode 100644
index 00000000..4a8674e7
--- /dev/null
+++ b/diylc/diylc-core/src/org/diylc/presenter/AreaUtils.java
@@ -0,0 +1,125 @@
+/*
+
+ 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 .
+
+*/
+package org.diylc.presenter;
+
+import java.awt.geom.Area;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class AreaUtils {
+
+ /**
+ * Merges all areas that either overlap or are joined by connections.
+ *
+ * @param areas
+ * @param connections
+ * @return
+ */
+ public static boolean crunchAreas(List areas, Set connections) {
+ boolean isChanged = false;
+
+ List newAreas = new ArrayList();
+ List consumed = new ArrayList();
+ 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 = null;
+ if (a1.getBounds2D().intersects(a2.getBounds())) {
+ intersection = new Area(a1);
+ intersection.intersect(a2);
+ }
+ // if the two areas intersect, make a union and consume the second area
+ if (intersection != null && !intersection.isEmpty()) {
+ a1.add(a2);
+ consumed.set(j, true);
+ } else { // maybe there's a connection between them
+ for (Connection p : connections) { // use getBounds to optimize the computation, don't get into complex math if not needed
+ if ((a1.getBounds().contains(p.getP1()) && a2.getBounds().contains(p.getP2()) && a1.contains(p.getP1()) && a2.contains(p.getP2())) ||
+ (a1.getBounds().contains(p.getP2()) && a2.getBounds().contains(p.getP1())) && a1.contains(p.getP2()) && a2.contains(p.getP1())) {
+ 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;
+ }
+
+ public static List tryAreaBreakout(Area a) {
+ List toReturn = new ArrayList();
+ 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;
+ }
+}
diff --git a/diylc/diylc-core/src/org/diylc/presenter/CalcUtils.java b/diylc/diylc-core/src/org/diylc/presenter/CalcUtils.java
index 204255e6..c74b9324 100644
--- a/diylc/diylc-core/src/org/diylc/presenter/CalcUtils.java
+++ b/diylc/diylc-core/src/org/diylc/presenter/CalcUtils.java
@@ -22,7 +22,9 @@
package org.diylc.presenter;
import java.awt.Point;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.diylc.core.IDIYComponent;
import org.diylc.core.measures.Size;
@@ -56,5 +58,24 @@ public class CalcUtils {
return;
}
}
+ }
+
+ public static void expandConnections(Set connections) {
+ Set toAdd = new HashSet();
+ for (Connection c1 : connections)
+ for (Connection c2 : connections) {
+ if (c1 == c2)
+ continue;
+ if (c1.getP1().distance(c2.getP1()) < DrawingManager.CONTROL_POINT_SIZE)
+ toAdd.add(new Connection(c1.getP2(), c2.getP2()));
+ if (c1.getP1().distance(c2.getP2()) < DrawingManager.CONTROL_POINT_SIZE)
+ toAdd.add(new Connection(c1.getP2(), c2.getP1()));
+ if (c1.getP2().distance(c2.getP1()) < DrawingManager.CONTROL_POINT_SIZE)
+ toAdd.add(new Connection(c1.getP1(), c2.getP2()));
+ if (c1.getP2().distance(c2.getP2()) < DrawingManager.CONTROL_POINT_SIZE)
+ toAdd.add(new Connection(c1.getP1(), c2.getP1()));
+ }
+ if (connections.addAll(toAdd))
+ expandConnections(connections);
}
}
diff --git a/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java b/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java
index 9a8ff14a..6649fa36 100644
--- a/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java
+++ b/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java
@@ -29,8 +29,6 @@ import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
-import java.awt.geom.Path2D;
-import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
@@ -631,127 +629,15 @@ public class DrawingManager {
for (int i = 0; i < preliminaryAreas.size(); i++) {
Area a = preliminaryAreas.get(i);
if (checkBreakout.get(i))
- areas.addAll(tryBreakout(a));
+ areas.addAll(AreaUtils.tryAreaBreakout(a));
else
areas.add(a);
}
- expandConnections(connections);
+ CalcUtils.expandConnections(connections);
- crunchAreas(areas, connections);
+ AreaUtils.crunchAreas(areas, connections);
return areas;
- }
-
- public void expandConnections(Set connections) {
- Set toAdd = new HashSet();
- for (Connection c1 : connections)
- for (Connection c2 : connections) {
- if (c1 == c2)
- continue;
- if (c1.getP1().distance(c2.getP1()) < CONTROL_POINT_SIZE)
- toAdd.add(new Connection(c1.getP2(), c2.getP2()));
- if (c1.getP1().distance(c2.getP2()) < CONTROL_POINT_SIZE)
- toAdd.add(new Connection(c1.getP2(), c2.getP1()));
- if (c1.getP2().distance(c2.getP1()) < CONTROL_POINT_SIZE)
- toAdd.add(new Connection(c1.getP1(), c2.getP2()));
- if (c1.getP2().distance(c2.getP2()) < CONTROL_POINT_SIZE)
- toAdd.add(new Connection(c1.getP1(), c2.getP1()));
- }
- if (connections.addAll(toAdd))
- expandConnections(connections);
- }
-
- /**
- * Merges all areas that either overlap or are joined by connections.
- *
- * @param areas
- * @param connections
- * @return
- */
- private boolean crunchAreas(List areas, Set connections) {
- boolean isChanged = false;
-
- List newAreas = new ArrayList();
- List consumed = new ArrayList();
- 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 = null;
- if (a1.getBounds2D().intersects(a2.getBounds())) {
- intersection = new Area(a1);
- intersection.intersect(a2);
- }
- // if the two areas intersect, make a union and consume the second area
- if (intersection != null && !intersection.isEmpty()) {
- a1.add(a2);
- consumed.set(j, true);
- } else { // maybe there's a connection between them
- for (Connection p : connections) { // use getBounds to optimize the computation, don't get into complex math if not needed
- if ((a1.getBounds().contains(p.getP1()) && a2.getBounds().contains(p.getP2()) && a1.contains(p.getP1()) && a2.contains(p.getP2())) ||
- (a1.getBounds().contains(p.getP2()) && a2.getBounds().contains(p.getP1())) && a1.contains(p.getP2()) && a2.contains(p.getP1())) {
- 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 tryBreakout(Area a) {
- List toReturn = new ArrayList();
- 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;
- }
+ }
}
diff --git a/diylc/diylc-core/src/org/diylc/presenter/Presenter.java b/diylc/diylc-core/src/org/diylc/presenter/Presenter.java
index eeeb5d6d..d38701bf 100644
--- a/diylc/diylc-core/src/org/diylc/presenter/Presenter.java
+++ b/diylc/diylc-core/src/org/diylc/presenter/Presenter.java
@@ -3141,7 +3141,7 @@ public class Presenter implements IPlugInPort {
}
}
- drawingManager.expandConnections(connections);
+ CalcUtils.expandConnections(connections);
return new ArrayList(connections);
}