allow extra space around the layout

introduced ability to render just the visible part of the layout for
better performance
This commit is contained in:
Branislav Stojkovic
2019-02-05 12:04:16 +01:00
parent ae3e698d9e
commit 3deb988a06
19 changed files with 198 additions and 65 deletions
@@ -56,5 +56,9 @@ public enum DrawOption {
/**
* Draw components in outline mode.
*/
OUTLINE_MODE;
OUTLINE_MODE,
/**
* Include extra space around the layout.
*/
EXTRA_SPACE;
}
@@ -73,7 +73,8 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
public static final String SHOW_RULERS_KEY = "showRulers";
public static final String SHOW_GRID_KEY = "showGrid";
public static final String HIGHLIGHT_CONTINUITY_AREA = "highlightContinuityArea";
public static final String HARDWARE_ACCELERATION = "hardwareAcceleration";
public static final String HARDWARE_ACCELERATION = "hardwareAcceleration";
public static final String EXTRA_SPACE_KEY = "extraSpace";
public static final int DND_TOGGLE_STICKY = 0x1;
public static final int DND_TOGGLE_SNAP = 0x40000000;
@@ -91,11 +92,12 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
* Each dimension is calculated as the product of the actual size and the number of pixels per
* unit. If <code>useZoom</code> is set to true, the result is scaled by zoom factor.
*
* @param useZoom
* @param useZoom
* @param includeExtraSpace
*
* @return canvas dimensions
*/
Dimension getCanvasDimensions(boolean useZoom);
Dimension getCanvasDimensions(boolean useZoom, boolean includeExtraSpace);
/**
* Returns an instance of {@link Cursor} that should be used at the specified location.
@@ -33,7 +33,7 @@ public class CalcUtils {
* @param x
* @return
*/
public static int roundToGrid(int x, Size gridSpacing) {
public static int roundToGrid(double x, Size gridSpacing) {
double grid = gridSpacing.convertToPixels();
return (int) (Math.round(1f * x / grid) * grid);
}
@@ -26,10 +26,12 @@ import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -65,6 +67,7 @@ public class DrawingManager {
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
public static int CONTROL_POINT_SIZE = 7;
public static double EXTRA_SPACE = 0.2;
public static final String ZOOM_KEY = "zoom";
@@ -141,7 +144,7 @@ public class DrawingManager {
} else {
zoom = 1 / Constants.PIXEL_SIZE;
}
if (externalZoom != null)
zoom *= externalZoom;
@@ -171,7 +174,7 @@ public class DrawingManager {
}
// AffineTransform initialTx = g2d.getTransform();
Dimension d = getCanvasDimensions(project, zoom, true);
Dimension d = getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE));
g2dWrapper.setColor(theme.getBgColor());
g2dWrapper.fillRect(0, 0, d.width, d.height);
@@ -185,8 +188,8 @@ public class DrawingManager {
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {
(float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4));
} else if (gridType == GridType.DOT) {
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {1f,
(float) zoomStep - 1}, 0f));
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {
1f, (float) zoomStep - 1}, 0f));
} else {
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness));
}
@@ -199,11 +202,26 @@ public class DrawingManager {
g2dWrapper.draw(new Line2D.Double(0, j, d.width - 1, j));
}
}
// manage extra space
double extraSpace = 0;
if (drawOptions.contains(DrawOption.EXTRA_SPACE)) {
Dimension dInner = getCanvasDimensions(project, zoom, false);
extraSpace = getExtraSpace(project) * zoom;
float borderThickness = (float) (3f * (zoom > 1 ? 1 : zoom));
g2d.setStroke(ObjectCache.getInstance().fetchStroke(borderThickness, new float[] {borderThickness * 4, borderThickness * 4, }, 0, BasicStroke.CAP_BUTT));
g2dWrapper.setColor(theme.getOutlineColor());
g2d.draw(new Rectangle2D.Double(extraSpace, extraSpace, dInner.getWidth(), dInner.getHeight()));
// translate to the new (0, 0)
g2d.transform(AffineTransform.getTranslateInstance(extraSpace, extraSpace));
}
// apply zoom
if (Math.abs(1.0 - zoom) > 1e-4) {
g2dWrapper.scale(zoom, zoom);
}
// Composite mainComposite = g2d.getComposite();
// Composite alphaComposite =
// AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
@@ -363,9 +381,9 @@ public class DrawingManager {
g2d.draw(a);
}
}
if (continuityArea != null && (ConfigurationManager.getInstance().readBoolean(IPlugInPort.HIGHLIGHT_CONTINUITY_AREA, false)))
{
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);
@@ -399,7 +417,7 @@ public class DrawingManager {
componentAreaMap.clear();
lastDrawnStateMap.clear();
}
public void clearContinuityArea() {
this.continuityArea = null;
}
@@ -415,16 +433,26 @@ public class DrawingManager {
return components;
}
public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean useZoom) {
public double getExtraSpace(Project project) {
double width = project.getWidth().convertToPixels();
double height = project.getHeight().convertToPixels();
if (useZoom) {
width *= zoomLevel;
height *= zoomLevel;
} else {
width /= Constants.PIXEL_SIZE;
height /= Constants.PIXEL_SIZE;
double targetExtraSpace = EXTRA_SPACE * Math.max(width, height);
return CalcUtils.roundToGrid(targetExtraSpace, project.getGridSpacing());
}
public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean includeExtraSpace) {
double width = project.getWidth().convertToPixels();
double height = project.getHeight().convertToPixels();
if (includeExtraSpace) {
double extraSpace = getExtraSpace(project);
width += 2 * extraSpace;
height += 2 * extraSpace;
}
width *= zoomLevel;
height *= zoomLevel;
return new Dimension((int) width, (int) height);
}
@@ -481,8 +509,8 @@ public class DrawingManager {
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));
// if (checkBreakout.get(i))
areas.addAll(tryBreakout(a));
// else
// areas.add(a);
}
@@ -250,8 +250,8 @@ public class Presenter implements IPlugInPort {
}
@Override
public Dimension getCanvasDimensions(boolean useZoom) {
return drawingManager.getCanvasDimensions(currentProject, drawingManager.getZoomLevel(), useZoom);
public Dimension getCanvasDimensions(boolean useZoom, boolean includeExtraSpace) {
return drawingManager.getCanvasDimensions(currentProject, useZoom ? drawingManager.getZoomLevel() : 1/ Constants.PIXEL_SIZE, includeExtraSpace);
}
@Override
@@ -1182,8 +1182,10 @@ public class Presenter implements IPlugInPort {
int actualDy = 0;
// For each component, do a simulation of the move to see if any of
// them will overlap or go out of bounds.
int width = (int) currentProject.getWidth().convertToPixels();
int height = (int) currentProject.getHeight().convertToPixels();
boolean useExtraSpace = ConfigurationManager.getInstance().readBoolean(EXTRA_SPACE_KEY, true);
Dimension d = drawingManager.getCanvasDimensions(currentProject, 1d, useExtraSpace);
double extraSpace = useExtraSpace ? drawingManager.getExtraSpace(currentProject) : 0;
if (controlPointMap.size() == 1) {
Map.Entry<IDIYComponent<?>, Set<Integer>> entry = controlPointMap.entrySet().iterator().next();
@@ -1220,8 +1222,9 @@ public class Presenter implements IPlugInPort {
// actually moved after snapping.
if (entry.getValue().contains(index)) {
controlPoints[index].translate(actualDx, actualDy);
if (controlPoints[index].x < 0 || controlPoints[index].y < 0 || controlPoints[index].x > width
|| controlPoints[index].y > height) {
controlPoints[index].translate((int)extraSpace, (int)extraSpace);
if (controlPoints[index].x < 0 || controlPoints[index].y < 0 || controlPoints[index].x > d.width
|| controlPoints[index].y > d.height) {
// At least one control point went out of bounds.
return null;
}
@@ -2424,8 +2427,14 @@ public class Presenter implements IPlugInPort {
* @return
*/
private Point scalePoint(Point point) {
return point == null ? null : new Point((int) (point.x / drawingManager.getZoomLevel()),
Point p = point == null ? null : new Point((int) (point.x / drawingManager.getZoomLevel()),
(int) (point.y / drawingManager.getZoomLevel()));
if (p != null && ConfigurationManager.getInstance().readBoolean(EXTRA_SPACE_KEY, true)) {
double extraSpace = drawingManager.getExtraSpace(currentProject);
p.translate((int)(-extraSpace), (int)(-extraSpace));
}
return p;
}
@SuppressWarnings("unchecked")