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. * Draw components in outline mode.
*/ */
OUTLINE_MODE; OUTLINE_MODE,
/**
* Include extra space around the layout.
*/
EXTRA_SPACE;
} }
@@ -74,6 +74,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
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 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_STICKY = 0x1;
public static final int DND_TOGGLE_SNAP = 0x40000000; public static final int DND_TOGGLE_SNAP = 0x40000000;
@@ -92,10 +93,11 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
* unit. If <code>useZoom</code> is set to true, the result is scaled by zoom factor. * 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 * @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. * Returns an instance of {@link Cursor} that should be used at the specified location.
@@ -33,7 +33,7 @@ public class CalcUtils {
* @param x * @param x
* @return * @return
*/ */
public static int roundToGrid(int x, Size gridSpacing) { public static int roundToGrid(double x, Size gridSpacing) {
double grid = gridSpacing.convertToPixels(); double grid = gridSpacing.convertToPixels();
return (int) (Math.round(1f * x / grid) * grid); return (int) (Math.round(1f * x / grid) * grid);
} }
@@ -26,10 +26,12 @@ import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.Line2D; import java.awt.geom.Line2D;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
import java.awt.geom.PathIterator; import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@@ -65,6 +67,7 @@ public class DrawingManager {
private static final Logger LOG = Logger.getLogger(DrawingManager.class); private static final Logger LOG = Logger.getLogger(DrawingManager.class);
public static int CONTROL_POINT_SIZE = 7; public static int CONTROL_POINT_SIZE = 7;
public static double EXTRA_SPACE = 0.2;
public static final String ZOOM_KEY = "zoom"; public static final String ZOOM_KEY = "zoom";
@@ -171,7 +174,7 @@ public class DrawingManager {
} }
// AffineTransform initialTx = g2d.getTransform(); // 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.setColor(theme.getBgColor());
g2dWrapper.fillRect(0, 0, d.width, d.height); 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[] { g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {
(float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4)); (float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4));
} else if (gridType == GridType.DOT) { } else if (gridType == GridType.DOT) {
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {1f, g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] {
(float) zoomStep - 1}, 0f)); 1f, (float) zoomStep - 1}, 0f));
} else { } else {
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness)); g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness));
} }
@@ -200,6 +203,21 @@ public class DrawingManager {
} }
} }
// 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) { if (Math.abs(1.0 - zoom) > 1e-4) {
g2dWrapper.scale(zoom, zoom); g2dWrapper.scale(zoom, zoom);
} }
@@ -364,8 +382,8 @@ public class DrawingManager {
} }
} }
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(); Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setColor(Color.green); g2d.setColor(Color.green);
@@ -415,16 +433,26 @@ public class DrawingManager {
return components; return components;
} }
public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean useZoom) { public double getExtraSpace(Project project) {
double width = project.getWidth().convertToPixels(); double width = project.getWidth().convertToPixels();
double height = project.getHeight().convertToPixels(); double height = project.getHeight().convertToPixels();
if (useZoom) { 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; width *= zoomLevel;
height *= zoomLevel; height *= zoomLevel;
} else {
width /= Constants.PIXEL_SIZE;
height /= Constants.PIXEL_SIZE;
}
return new Dimension((int) width, (int) height); return new Dimension((int) width, (int) height);
} }
@@ -481,7 +509,7 @@ public class DrawingManager {
List<Area> areas = new ArrayList<Area>(); List<Area> areas = new ArrayList<Area>();
for (int i = 0; i < preliminaryAreas.size(); i++) { for (int i = 0; i < preliminaryAreas.size(); i++) {
Area a = preliminaryAreas.get(i); Area a = preliminaryAreas.get(i);
// if (checkBreakout.get(i)) // if (checkBreakout.get(i))
areas.addAll(tryBreakout(a)); areas.addAll(tryBreakout(a));
// else // else
// areas.add(a); // areas.add(a);
@@ -250,8 +250,8 @@ public class Presenter implements IPlugInPort {
} }
@Override @Override
public Dimension getCanvasDimensions(boolean useZoom) { public Dimension getCanvasDimensions(boolean useZoom, boolean includeExtraSpace) {
return drawingManager.getCanvasDimensions(currentProject, drawingManager.getZoomLevel(), useZoom); return drawingManager.getCanvasDimensions(currentProject, useZoom ? drawingManager.getZoomLevel() : 1/ Constants.PIXEL_SIZE, includeExtraSpace);
} }
@Override @Override
@@ -1182,8 +1182,10 @@ public class Presenter implements IPlugInPort {
int actualDy = 0; int actualDy = 0;
// For each component, do a simulation of the move to see if any of // For each component, do a simulation of the move to see if any of
// them will overlap or go out of bounds. // 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) { if (controlPointMap.size() == 1) {
Map.Entry<IDIYComponent<?>, Set<Integer>> entry = controlPointMap.entrySet().iterator().next(); Map.Entry<IDIYComponent<?>, Set<Integer>> entry = controlPointMap.entrySet().iterator().next();
@@ -1220,8 +1222,9 @@ public class Presenter implements IPlugInPort {
// actually moved after snapping. // actually moved after snapping.
if (entry.getValue().contains(index)) { if (entry.getValue().contains(index)) {
controlPoints[index].translate(actualDx, actualDy); controlPoints[index].translate(actualDx, actualDy);
if (controlPoints[index].x < 0 || controlPoints[index].y < 0 || controlPoints[index].x > width controlPoints[index].translate((int)extraSpace, (int)extraSpace);
|| controlPoints[index].y > height) { 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. // At least one control point went out of bounds.
return null; return null;
} }
@@ -2424,8 +2427,14 @@ public class Presenter implements IPlugInPort {
* @return * @return
*/ */
private Point scalePoint(Point point) { 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())); (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") @SuppressWarnings("unchecked")
Binary file not shown.
+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.debugContinuityAreas=true -Dorg.diylc.WriteStaticVariants=true"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-splash:splash.png -Xms256m -Xmx512m -Dorg.diylc.scriptRun=true -Ddorg.diylc.debugContinuityAreas=true -Dorg.diylc.WriteStaticVariants=true -Ddorg.diylc.debugComponentAreas=true"/>
</launchConfiguration> </launchConfiguration>
Binary file not shown.
Binary file not shown.
@@ -235,7 +235,7 @@ public class TemplateDialog extends JDialog {
File file = (File) fileList.getSelectedValue(); File file = (File) fileList.getSelectedValue();
if (file != null) { if (file != null) {
presenter.loadProjectFromFile(file.getAbsolutePath()); presenter.loadProjectFromFile(file.getAbsolutePath());
Dimension dim = presenter.getCanvasDimensions(true); Dimension dim = presenter.getCanvasDimensions(true, true);
double xFactor = panelSize.getWidth() / dim.getWidth(); double xFactor = panelSize.getWidth() / dim.getWidth();
double yFactor = panelSize.getHeight() / dim.getHeight(); double yFactor = panelSize.getHeight() / dim.getHeight();
presenter.setZoomLevel(Math.min(xFactor, yFactor)); presenter.setZoomLevel(Math.min(xFactor, yFactor));
@@ -69,6 +69,8 @@ public class CanvasPanel extends JComponent implements Autoscroll {
private static final Logger LOG = Logger.getLogger(CanvasPlugin.class); private static final Logger LOG = Logger.getLogger(CanvasPlugin.class);
public static boolean RENDER_VISIBLE_RECT_ONLY = true;
private IPlugInPort plugInPort; private IPlugInPort plugInPort;
private Image bufferImage; private Image bufferImage;
@@ -209,11 +211,22 @@ public class CanvasPanel extends JComponent implements Autoscroll {
} }
protected void createBufferImage() { protected void createBufferImage() {
int imageWidth;
int imageHeight;
if (RENDER_VISIBLE_RECT_ONLY) {
Rectangle visibleRect = getVisibleRect();
imageWidth = visibleRect.width;
imageHeight = visibleRect.height;
} else {
imageWidth = getWidth();
imageHeight = getHeight();
}
if (useHardwareAcceleration) { if (useHardwareAcceleration) {
bufferImage = screenGraphicsConfiguration.createCompatibleVolatileImage(getWidth(), getHeight()); bufferImage = screenGraphicsConfiguration.createCompatibleVolatileImage(imageWidth, imageHeight);
((VolatileImage) bufferImage).validate(screenGraphicsConfiguration); ((VolatileImage) bufferImage).validate(screenGraphicsConfiguration);
} else { } else {
bufferImage = createImage(getWidth(), getHeight()); bufferImage = createImage(imageWidth, imageHeight);
} }
} }
@@ -226,7 +239,20 @@ public class CanvasPanel extends JComponent implements Autoscroll {
createBufferImage(); createBufferImage();
} }
Graphics2D g2d = (Graphics2D) bufferImage.getGraphics(); Graphics2D g2d = (Graphics2D) bufferImage.getGraphics();
g2d.setClip(getVisibleRect());
Rectangle visibleRect = getVisibleRect();
int x = 0;
int y = 0;
if (RENDER_VISIBLE_RECT_ONLY) {
x = visibleRect.x;
y = visibleRect.y;
g2d.translate(-x, -y);
} else {
g2d.setClip(visibleRect);
}
Set<DrawOption> drawOptions = EnumSet.of(DrawOption.SELECTION, DrawOption.ZOOM, DrawOption.CONTROL_POINTS); Set<DrawOption> drawOptions = EnumSet.of(DrawOption.SELECTION, DrawOption.ZOOM, DrawOption.CONTROL_POINTS);
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.ANTI_ALIASING_KEY, true)) { if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.ANTI_ALIASING_KEY, true)) {
drawOptions.add(DrawOption.ANTIALIASING); drawOptions.add(DrawOption.ANTIALIASING);
@@ -237,7 +263,12 @@ public class CanvasPanel extends JComponent implements Autoscroll {
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.SHOW_GRID_KEY, true)) { if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.SHOW_GRID_KEY, true)) {
drawOptions.add(DrawOption.GRID); drawOptions.add(DrawOption.GRID);
} }
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.EXTRA_SPACE_KEY, true)) {
drawOptions.add(DrawOption.EXTRA_SPACE);
}
plugInPort.draw(g2d, drawOptions, null, null); plugInPort.draw(g2d, drawOptions, null, null);
if (useHardwareAcceleration) { if (useHardwareAcceleration) {
VolatileImage volatileImage = (VolatileImage) bufferImage; VolatileImage volatileImage = (VolatileImage) bufferImage;
do { do {
@@ -250,13 +281,13 @@ public class CanvasPanel extends JComponent implements Autoscroll {
// if (validation == VolatileImage.IMAGE_INCOMPATIBLE) { // if (validation == VolatileImage.IMAGE_INCOMPATIBLE) {
// createBufferImage(); // createBufferImage();
// } // }
g.drawImage(bufferImage, 0, 0, this); g.drawImage(bufferImage, x, y, this);
} catch (NullPointerException e) { } catch (NullPointerException e) {
createBufferImage(); createBufferImage();
} }
} while (volatileImage == null || volatileImage.contentsLost()); } while (volatileImage == null || volatileImage.contentsLost());
} else { } else {
g.drawImage(bufferImage, 0, 0, this); g.drawImage(bufferImage, x, y, this);
// bufferImage.flush(); // bufferImage.flush();
} }
g2d.dispose(); g2d.dispose();
@@ -26,6 +26,8 @@ import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.Transferable; import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
@@ -125,6 +127,27 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
getScrollPane().setRulerVisible(ConfigurationManager.getInstance().readBoolean(IPlugInPort.SHOW_RULERS_KEY, true)); getScrollPane().setRulerVisible(ConfigurationManager.getInstance().readBoolean(IPlugInPort.SHOW_RULERS_KEY, true));
// revalidate canvas on scrolling when we render visible rect only
if (CanvasPanel.RENDER_VISIBLE_RECT_ONLY) {
getScrollPane().getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
getCanvasPanel().invalidateCache();
getCanvasPanel().revalidate();
}
});
getScrollPane().getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
getCanvasPanel().invalidateCache();
getCanvasPanel().revalidate();
}
});
}
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.SHOW_RULERS_KEY, new IConfigListener() { ConfigurationManager.getInstance().addConfigListener(IPlugInPort.SHOW_RULERS_KEY, new IConfigListener() {
@Override @Override
@@ -142,6 +165,20 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
scrollPane.setUseHardwareAcceleration((Boolean) value); scrollPane.setUseHardwareAcceleration((Boolean) value);
} }
}); });
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.EXTRA_SPACE_KEY, new IConfigListener() {
@Override
public void valueChanged(String key, Object value) {
refreshSize();
// Scroll to the center.
Rectangle visibleRect = canvasPanel.getVisibleRect();
visibleRect.setLocation((canvasPanel.getWidth() - visibleRect.width) / 2,
(canvasPanel.getHeight() - visibleRect.height) / 2);
canvasPanel.scrollRectToVisible(visibleRect);
canvasPanel.revalidate();
}
});
} }
public CanvasPanel getCanvasPanel() { public CanvasPanel getCanvasPanel() {
@@ -155,8 +192,8 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (scrollPane.isMouseScrollMode() || e.getButton() == MouseEvent.BUTTON2) if (scrollPane.isMouseScrollMode() || e.getButton() == MouseEvent.BUTTON2)
return; return;
plugInPort.mouseClicked(e.getPoint(), e.getButton(), Utils.isMac() ? e.isMetaDown() : e.isControlDown(), e.isShiftDown(), e.isAltDown(), plugInPort.mouseClicked(e.getPoint(), e.getButton(), Utils.isMac() ? e.isMetaDown() : e.isControlDown(),
e.getClickCount()); e.isShiftDown(), e.isAltDown(), e.getClickCount());
} }
@Override @Override
@@ -174,7 +211,8 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
@Override @Override
public void run() { public void run() {
if (plugInPort.getNewComponentTypeSlot() == null && (e.isPopupTrigger() || (pressedEvent != null && pressedEvent.isPopupTrigger()))) { if (plugInPort.getNewComponentTypeSlot() == null
&& (e.isPopupTrigger() || (pressedEvent != null && pressedEvent.isPopupTrigger()))) {
// Enable actions. // Enable actions.
boolean enabled = !plugInPort.getSelectedComponents().isEmpty(); boolean enabled = !plugInPort.getSelectedComponents().isEmpty();
getCutAction().setEnabled(enabled); getCutAction().setEnabled(enabled);
@@ -214,7 +252,8 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if (plugInPort.keyPressed(e.getKeyCode(), Utils.isMac() ? e.isMetaDown() : e.isControlDown(), e.isShiftDown(), e.isAltDown())) { if (plugInPort.keyPressed(e.getKeyCode(), Utils.isMac() ? e.isMetaDown() : e.isControlDown(),
e.isShiftDown(), e.isAltDown())) {
e.consume(); e.consume();
} }
} }
@@ -227,7 +266,8 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
if (scrollPane.isMouseScrollMode()) if (scrollPane.isMouseScrollMode())
return; return;
canvasPanel.setCursor(plugInPort.getCursorAt(e.getPoint())); canvasPanel.setCursor(plugInPort.getCursorAt(e.getPoint()));
plugInPort.mouseMoved(e.getPoint(), Utils.isMac() ? e.isMetaDown() : e.isControlDown(), e.isShiftDown(), e.isAltDown()); plugInPort.mouseMoved(e.getPoint(), Utils.isMac() ? e.isMetaDown() : e.isControlDown(), e.isShiftDown(),
e.isAltDown());
} }
}); });
} }
@@ -237,11 +277,12 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
private RulerScrollPane getScrollPane() { private RulerScrollPane getScrollPane() {
if (scrollPane == null) { if (scrollPane == null) {
scrollPane = scrollPane =
new RulerScrollPane(getCanvasPanel(), new ProjectDrawingProvider(plugInPort, true, false), new Size(1d, new RulerScrollPane(getCanvasPanel(), new ProjectDrawingProvider(plugInPort, true, false, true), new Size(1d,
SizeUnit.cm).convertToPixels(), new Size(1d, SizeUnit.in).convertToPixels()); SizeUnit.cm).convertToPixels(), new Size(1d, SizeUnit.in).convertToPixels());
boolean metric = ConfigurationManager.getInstance().readBoolean(Presenter.METRIC_KEY, true); boolean metric = ConfigurationManager.getInstance().readBoolean(Presenter.METRIC_KEY, true);
boolean useHardwareAcceleration = ConfigurationManager.getInstance().readBoolean(IPlugInPort.HARDWARE_ACCELERATION, false); boolean useHardwareAcceleration =
ConfigurationManager.getInstance().readBoolean(IPlugInPort.HARDWARE_ACCELERATION, false);
scrollPane.setUseHardwareAcceleration(useHardwareAcceleration); scrollPane.setUseHardwareAcceleration(useHardwareAcceleration);
scrollPane.setMetric(metric); scrollPane.setMetric(metric);
@@ -655,7 +696,9 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
} }
private void refreshSize() { private void refreshSize() {
Dimension d = plugInPort.getCanvasDimensions(true); Dimension d =
plugInPort.getCanvasDimensions(true,
ConfigurationManager.getInstance().readBoolean(IPlugInPort.EXTRA_SPACE_KEY, true));
canvasPanel.setSize(d); canvasPanel.setSize(d);
canvasPanel.setPreferredSize(d); canvasPanel.setPreferredSize(d);
getScrollPane().setZoomLevel(plugInPort.getZoomLevel()); getScrollPane().setZoomLevel(plugInPort.getZoomLevel());
@@ -216,7 +216,7 @@ public class UploadDialog extends ButtonDialog {
} }
private Dimension getThumbnailSize() { private Dimension getThumbnailSize() {
Dimension d = UploadDialog.this.plugInPort.getCanvasDimensions(false); Dimension d = UploadDialog.this.plugInPort.getCanvasDimensions(false, false);
if (d.height > d.width) if (d.height > d.width)
return new Dimension(192 * d.width / d.height, 192); return new Dimension(192 * d.width / d.height, 192);
else else
@@ -304,7 +304,7 @@ public class UploadDialog extends ButtonDialog {
private void paintThumbnail(Graphics g, Rectangle rect) { private void paintThumbnail(Graphics g, Rectangle rect) {
Graphics2D g2d = (Graphics2D) g; Graphics2D g2d = (Graphics2D) g;
Dimension d = UploadDialog.this.plugInPort.getCanvasDimensions(false); Dimension d = UploadDialog.this.plugInPort.getCanvasDimensions(false, false);
g2d.setColor(Color.white); g2d.setColor(Color.white);
g2d.fill(rect); g2d.fill(rect);
@@ -75,6 +75,9 @@ public class ConfigPlugin implements IPlugIn {
swingUI.injectMenuAction( swingUI.injectMenuAction(
ActionFactory.getInstance().createConfigAction(plugInPort, "Export Grid", IPlugInPort.EXPORT_GRID_KEY, false), ActionFactory.getInstance().createConfigAction(plugInPort, "Export Grid", IPlugInPort.EXPORT_GRID_KEY, false),
CONFIG_MENU); CONFIG_MENU);
swingUI.injectMenuAction(
ActionFactory.getInstance().createConfigAction(plugInPort, "Extra Working Area", IPlugInPort.EXTRA_SPACE_KEY, true),
CONFIG_MENU);
swingUI.injectMenuAction( swingUI.injectMenuAction(
ActionFactory.getInstance().createConfigAction(plugInPort, "Hardware Acceleration", IPlugInPort.HARDWARE_ACCELERATION, false), ActionFactory.getInstance().createConfigAction(plugInPort, "Hardware Acceleration", IPlugInPort.HARDWARE_ACCELERATION, false),
CONFIG_MENU); CONFIG_MENU);
@@ -62,7 +62,7 @@ public class FileMenuPlugin implements IPlugIn, IDynamicSubmenuHandler {
@Override @Override
public void connect(IPlugInPort plugInPort) { public void connect(IPlugInPort plugInPort) {
this.plugInPort = plugInPort; this.plugInPort = plugInPort;
this.drawingProvider = new ProjectDrawingProvider(plugInPort, false, true); this.drawingProvider = new ProjectDrawingProvider(plugInPort, false, true, false);
this.traceMaskDrawingProvider = new TraceMaskDrawingProvider(plugInPort); this.traceMaskDrawingProvider = new TraceMaskDrawingProvider(plugInPort);
ActionFactory actionFactory = ActionFactory.getInstance(); ActionFactory actionFactory = ActionFactory.getInstance();
@@ -42,17 +42,19 @@ public class ProjectDrawingProvider implements IDrawingProvider {
private IPlugInPort plugInPort; private IPlugInPort plugInPort;
private boolean useZoom; private boolean useZoom;
private boolean showGridWhenNeeded; private boolean showGridWhenNeeded;
private boolean includeExtraSpace;
public ProjectDrawingProvider(IPlugInPort plugInPort, boolean useZoom, boolean showGridWhenNeeded) { public ProjectDrawingProvider(IPlugInPort plugInPort, boolean useZoom, boolean showGridWhenNeeded, boolean includeExtraSpace) {
super(); super();
this.plugInPort = plugInPort; this.plugInPort = plugInPort;
this.useZoom = useZoom; this.useZoom = useZoom;
this.showGridWhenNeeded = showGridWhenNeeded; this.showGridWhenNeeded = showGridWhenNeeded;
this.includeExtraSpace = includeExtraSpace;
} }
@Override @Override
public Dimension getSize() { public Dimension getSize() {
return plugInPort.getCanvasDimensions(useZoom); return plugInPort.getCanvasDimensions(useZoom, includeExtraSpace);
} }
@Override @Override
@@ -67,6 +69,9 @@ public class ProjectDrawingProvider implements IDrawingProvider {
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.OUTLINE_KEY, false)) { if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.OUTLINE_KEY, false)) {
drawOptions.add(DrawOption.OUTLINE_MODE); drawOptions.add(DrawOption.OUTLINE_MODE);
} }
if (includeExtraSpace) {
drawOptions.add(DrawOption.EXTRA_SPACE);
}
plugInPort.draw((Graphics2D) g, drawOptions, null, zoomFactor); plugInPort.draw((Graphics2D) g, drawOptions, null, zoomFactor);
} }
@@ -127,7 +127,7 @@ public class ProjectPreview extends JPanel implements PropertyChangeListener, IF
super.paint(g); super.paint(g);
Graphics2D g2d = (Graphics2D) g; Graphics2D g2d = (Graphics2D) g;
Dimension d = presenter.getCanvasDimensions(false); Dimension d = presenter.getCanvasDimensions(false, false);
// System.out.println(d); // System.out.println(d);
Rectangle rect = getBounds(); Rectangle rect = getBounds();
// System.out.println(rect); // System.out.println(rect);
@@ -55,7 +55,7 @@ public class TraceMaskDrawingProvider implements IDrawingProvider {
@Override @Override
public Dimension getSize() { public Dimension getSize() {
return plugInPort.getCanvasDimensions(false); return plugInPort.getCanvasDimensions(false, false);
} }
@Override @Override
+8
View File
@@ -2394,6 +2394,14 @@
<releaseDate>2019-02-03 00:00:00.000 CET</releaseDate> <releaseDate>2019-02-03 00:00:00.000 CET</releaseDate>
<name></name> <name></name>
<changes> <changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added extra work space around the layout that can be used to store additional components and helpers, but does not get exported to a file. Configurable from the menu</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Vast improvement of rendering performance, especially with large layouts</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType> <changeType>IMPROVEMENT</changeType>
<description>Create a backup of config file when there is an issue with loading (for example running two DIYLC versions on the same machine) to avoid data loss</description> <description>Create a backup of config file when there is an issue with loading (for example running two DIYLC versions on the same machine) to avoid data loss</description>