From 72f96f15e45c70904f4d440611b5315cb87f5aff Mon Sep 17 00:00:00 2001 From: Joacim Breiler Date: Thu, 4 Jul 2024 17:00:58 +0200 Subject: [PATCH] Adjusted how scrolling and zooming works in the designer (#2566) --- .../ugs/nbp/designer/DesignerMain.java | 10 +- .../nbp/designer/entities/EntityGroup.java | 2 +- .../controls/HighlightModelControl.java | 5 +- .../ugs/nbp/designer/gui/Drawing.java | 67 ++++---- .../designer/gui/DrawingOverlayContainer.java | 103 +++++++++++ .../designer/gui/DrawingScrollContainer.java | 160 ++++++++++++++++++ .../ugs/nbp/designer/gui/ToolBox.java | 15 +- .../io/gcode/toolpaths/LaserFillToolPath.java | 2 +- .../platform/DesignerTopComponent.java | 10 +- 9 files changed, 326 insertions(+), 48 deletions(-) create mode 100644 ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingOverlayContainer.java create mode 100644 ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingScrollContainer.java diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/DesignerMain.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/DesignerMain.java index 3069967060..502e838718 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/DesignerMain.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/DesignerMain.java @@ -2,8 +2,9 @@ import com.willwinder.ugs.nbp.designer.actions.UndoManager; import com.willwinder.ugs.nbp.designer.entities.selection.SelectionManager; -import com.willwinder.ugs.nbp.designer.gui.DrawingContainer; import com.willwinder.ugs.nbp.designer.gui.MainMenu; +import com.willwinder.ugs.nbp.designer.gui.DrawingScrollContainer; +import com.willwinder.ugs.nbp.designer.gui.DrawingOverlayContainer; import com.willwinder.ugs.nbp.designer.gui.PopupMenuFactory; import com.willwinder.ugs.nbp.designer.gui.ToolBox; import com.willwinder.ugs.nbp.designer.gui.selectionsettings.SelectionSettingsPanel; @@ -53,13 +54,14 @@ public DesignerMain() { SelectionManager selectionManager = ControllerFactory.getSelectionManager(); CentralLookup.getDefault().add(selectionManager); - DrawingContainer drawingContainer = new DrawingContainer(controller); + DrawingScrollContainer drawingContainer = new DrawingScrollContainer(controller); selectionManager.addSelectionListener(e -> drawingContainer.repaint()); - JSplitPane toolsSplit = createRightPanel(controller); + DrawingOverlayContainer overlayToolContainer = new DrawingOverlayContainer(controller, drawingContainer); + JSplitPane toolsSplit = createRightPanel(controller); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, - drawingContainer, toolsSplit); + overlayToolContainer, toolsSplit); splitPane.setResizeWeight(0.95); getContentPane().add(splitPane, BorderLayout.CENTER); diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/EntityGroup.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/EntityGroup.java index 03f6cee76f..b0305902c5 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/EntityGroup.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/EntityGroup.java @@ -122,7 +122,7 @@ public void addChild(Entity entity, int index) { invalidateBounds(); } - private void invalidateBounds() { + public void invalidateBounds() { cachedBounds = null; } diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/controls/HighlightModelControl.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/controls/HighlightModelControl.java index 65318b1521..fc56926408 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/controls/HighlightModelControl.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/entities/controls/HighlightModelControl.java @@ -21,11 +21,10 @@ public void render(Graphics2D graphics, Drawing drawing) { } // Draw the bounds - double margin = ResizeControl.MARGIN / drawing.getScale(); graphics.setColor(Colors.CONTROL_BORDER); - graphics.setStroke(new BasicStroke(Double.valueOf(0.8 / drawing.getScale()).floatValue())); + graphics.setStroke(new BasicStroke((float) (0.8f / drawing.getScale()))); Rectangle2D bounds = getRelativeShape().getBounds2D(); - bounds.setFrame(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + (margin * 2), bounds.getHeight() + (margin * 2)); + bounds.setFrame(bounds.getX() , bounds.getY() , bounds.getWidth(), bounds.getHeight()); graphics.draw(getSelectionManager().getTransform().createTransformedShape(bounds)); } diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/Drawing.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/Drawing.java index 8c04b76591..684e126d39 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/Drawing.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/Drawing.java @@ -1,5 +1,5 @@ /* - Copyright 2021 Will Winder + Copyright 2021-2024 Will Winder This file is part of Universal Gcode Sender (UGS). @@ -54,6 +54,7 @@ This file is part of Universal Gcode Sender (UGS). import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.io.Serial; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -65,20 +66,20 @@ This file is part of Universal Gcode Sender (UGS). public class Drawing extends JPanel { public static final double MIN_SCALE = 0.05; + @Serial private static final long serialVersionUID = 1298712398723987873L; - private static final int MARGIN = 100; private final transient EntityGroup globalRoot; private final transient EntityGroup entitiesRoot; private final transient EntityGroup controlsRoot; private final transient Set listeners = Sets.newConcurrentHashSet(); private final transient Throttler refreshThrottler; - private double scale; - private AffineTransform transform; - private long lastUpdate; private final transient Rectangle2D currentBounds = new Rectangle(0, 0, 8, 8); + private double scale; + private Point2D.Double position = new Point2D.Double(); + private Dimension oldMinimumSize; public Drawing(Controller controller) { - refreshThrottler = new Throttler(this::refresh, 2000); + refreshThrottler = new Throttler(this::refresh, 1000); globalRoot = new EntityGroup(); globalRoot.addChild(new GridControl(controller)); @@ -219,14 +220,14 @@ public void setScale(double scale) { if (this.scale != newScale) { this.scale = newScale; notifyListeners(DrawingEvent.SCALE_CHANGED); + refresh(); } } @Override public Dimension getMinimumSize() { - int margin = (int) (MARGIN * 2 * scale); - int width = (int) (currentBounds.getWidth() * scale) + margin; - int height = (int) (currentBounds.getHeight() * scale) + margin; + int width = (int) (currentBounds.getWidth() ); + int height = (int) (currentBounds.getHeight()); return new Dimension(width, height); } @@ -235,11 +236,14 @@ public Dimension getPreferredSize() { return getMinimumSize(); } - private void refresh() { + public void refresh() { repaint(); + globalRoot.invalidateBounds(); + updateBounds(); Dimension minimumSize = getMinimumSize(); - firePropertyChange("minimumSize", minimumSize.width, minimumSize.height); - firePropertyChange("preferredSize", minimumSize.width, minimumSize.height); + firePropertyChange("minimumSize", oldMinimumSize, minimumSize); + firePropertyChange("preferredSize", oldMinimumSize, minimumSize); + oldMinimumSize = minimumSize; revalidate(); } @@ -248,17 +252,10 @@ public void addListener(DrawingListener listener) { } public AffineTransform getTransform() { - // Don't update this every time or else it will be hard to move entites outside the canvas - if (System.currentTimeMillis() > lastUpdate + 50) { - - transform = AffineTransform.getScaleInstance(1, -1); - transform.translate(0, -getHeight()); - transform.scale(scale, scale); - transform.translate(MARGIN / 4d, MARGIN / 4d); - transform.translate(-getBounds().getMinX(), -getBounds().getMinY()); - lastUpdate = System.currentTimeMillis(); - } - + AffineTransform transform = AffineTransform.getScaleInstance(1, -1); + transform.translate(0, -getHeight()); + transform.scale(scale, scale); + transform.translate(-position.x, -position.y); return transform; } @@ -277,15 +274,27 @@ public void clear() { entitiesRoot.removeAll(); } - @Override public Rectangle getBounds() { + updateBounds(); + return currentBounds.getBounds(); + } + + private void updateBounds() { Rectangle2D bounds = globalRoot.getBounds(); - double minX = Math.min(currentBounds.getMinX(), bounds.getMinX()); - double minY = Math.min(currentBounds.getMinY(), bounds.getMinY()); - double maxX = Math.max(currentBounds.getMaxX(), bounds.getMaxX()); - double maxY = Math.max(currentBounds.getMaxY(), bounds.getMaxY()); + double minX = (bounds.getMinX()) * scale; + double minY = (bounds.getMinY()) * scale; + double maxX = (bounds.getMaxX()) * scale; + double maxY = (bounds.getMaxY()) * scale; currentBounds.setRect(minX, minY, maxX - minX, maxY - minY); - return currentBounds.getBounds(); + } + + public void setPosition(double x, double y) { + position = new Point2D.Double(x / scale, y / scale); + refresh(); + } + + public Point2D.Double getPosition() { + return new Point2D.Double(position.x * scale, position.y * scale); } } diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingOverlayContainer.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingOverlayContainer.java new file mode 100644 index 0000000000..b566d19137 --- /dev/null +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingOverlayContainer.java @@ -0,0 +1,103 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS 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. + + UGS 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 UGS. If not, see . + */ +package com.willwinder.ugs.nbp.designer.gui; + +import com.willwinder.ugs.nbp.designer.actions.OpenStockSettingsAction; +import com.willwinder.ugs.nbp.designer.actions.OpenToolSettingsAction; +import com.willwinder.ugs.nbp.designer.logic.Controller; + +import javax.swing.Box; +import javax.swing.JComponent; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; + +/** + * A container that will add button overlays + * + * @author Joacim Breiler + */ +public class DrawingOverlayContainer extends JPanel implements ComponentListener { + private final JPanel buttonPanel; + private final JComponent component; + + public DrawingOverlayContainer(Controller controller, JComponent component) { + setLayout(new BorderLayout()); + + this.component = component; + buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonPanel.setOpaque(false); + + ToolButton toolButton = new ToolButton(controller); + toolButton.setMinimumSize(new Dimension(60, 40)); + toolButton.setMaximumSize(new Dimension(100, 40)); + toolButton.addActionListener(new OpenToolSettingsAction(controller)); + buttonPanel.add(toolButton); + + add(Box.createHorizontalStrut(6)); + PanelButton stockButton = new PanelButton("Stock", controller.getSettings().getStockSizeDescription()); + stockButton.setMinimumSize(new Dimension(60, 40)); + stockButton.setMaximumSize(new Dimension(100, 40)); + controller.getSettings().addListener(() -> stockButton.setText(controller.getSettings().getStockSizeDescription())); + stockButton.addActionListener(new OpenStockSettingsAction(controller)); + buttonPanel.add(stockButton); + + JLayeredPane layeredPane = new JLayeredPane(); + + layeredPane.add(component, JLayeredPane.DEFAULT_LAYER, 0); + layeredPane.add(buttonPanel, JLayeredPane.PALETTE_LAYER, 0); + add(layeredPane, BorderLayout.CENTER); + revalidate(); + + // This is a workaround to be able to resize the layered pane + addComponentListener(this); + } + + @Override + public void componentResized(ComponentEvent e) { + // Needed to properly resize the layered pane + SwingUtilities.invokeLater(() -> { + Rectangle bounds = getBounds(); + component.setBounds(0, 0, bounds.width, bounds.height); + buttonPanel.setBounds(0, bounds.height - 80, bounds.width - 30, 80); + revalidate(); + }); + } + + @Override + public void componentMoved(ComponentEvent e) { + // Not used + } + + @Override + public void componentShown(ComponentEvent e) { + // Not used + } + + @Override + public void componentHidden(ComponentEvent e) { + // Not used + } +} diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingScrollContainer.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingScrollContainer.java new file mode 100644 index 0000000000..2898444bba --- /dev/null +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/DrawingScrollContainer.java @@ -0,0 +1,160 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS 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. + + UGS 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 UGS. If not, see . + */ +package com.willwinder.ugs.nbp.designer.gui; + +import com.willwinder.ugs.nbp.designer.logic.Controller; +import com.willwinder.ugs.nbp.lib.lookup.CentralLookup; +import com.willwinder.universalgcodesender.model.BackendAPI; + +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import java.awt.Adjustable; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.KeyboardFocusManager; +import java.awt.event.KeyEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.geom.Rectangle2D; + +/** + * A container that will add scroll bars and handle zooming + * + * @author Joacim Breiler + */ +public class DrawingScrollContainer extends JPanel implements MouseWheelListener { + public static final int MARGIN = 1000; + private final transient Controller controller; + private JScrollBar horizontalScrollBar; + private JScrollBar verticalScrollBar; + + public DrawingScrollContainer(Controller controller) { + super(); + this.controller = controller; + setLayout(new GridBagLayout()); + setDrawing(controller.getDrawing()); + + MouseListener mouseListener = new MouseListener(controller); + controller.getDrawing().addMouseListener(mouseListener); + controller.getDrawing().addMouseMotionListener(mouseListener); + controller.getDrawing().addMouseWheelListener(this); + + KeyboardListener keyboardListener = new KeyboardListener(controller, mouseListener); + KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(e -> { + if (e.getID() == KeyEvent.KEY_PRESSED) { + keyboardListener.keyPressed(e); + } else if (e.getID() == KeyEvent.KEY_RELEASED) { + keyboardListener.keyReleased(e); + } else if (e.getID() == KeyEvent.KEY_TYPED) { + keyboardListener.keyTyped(e); + } + return false; + }); + } + + public void setDrawing(Drawing drawing) { + removeAll(); + createComponents(drawing); + drawing.addPropertyChangeListener("minimumSize", e -> updateScrollBarsSizes()); + resetView(); + } + + public void resetView() { + // Reset the drawing view + controller.getDrawing().refresh(); + updateScrollBarsSizes(); + setScrollbarPercent(horizontalScrollBar, -0.02); + setScrollbarPercent(verticalScrollBar, 0.02); + } + + private void createComponents(Drawing drawing) { + horizontalScrollBar = new JScrollBar(Adjustable.HORIZONTAL); + horizontalScrollBar.setValue((int) drawing.getPosition().x); + horizontalScrollBar.addAdjustmentListener(l -> + updateDrawingPositionFromScrollBars() + ); + + GridBagConstraints drawingConstraints = new GridBagConstraints(); + drawingConstraints.gridx = 0; + drawingConstraints.gridy = 0; + drawingConstraints.weighty = 1; + drawingConstraints.weightx = 1; + drawingConstraints.fill = 1; + add(drawing, drawingConstraints); + + GridBagConstraints hScrollConstraints = new GridBagConstraints(); + hScrollConstraints.gridx = 0; + hScrollConstraints.gridy = 1; + hScrollConstraints.weighty = 0; + hScrollConstraints.weightx = 1; + hScrollConstraints.fill = 1; + add(horizontalScrollBar, hScrollConstraints); + + verticalScrollBar = new JScrollBar(Adjustable.VERTICAL); + verticalScrollBar.setValue((int) drawing.getPosition().y); + verticalScrollBar.addAdjustmentListener(l -> updateDrawingPositionFromScrollBars()); + + GridBagConstraints vScrollConstraints = new GridBagConstraints(); + vScrollConstraints.gridx = 2; + vScrollConstraints.gridy = 0; + vScrollConstraints.weighty = 1; + vScrollConstraints.weightx = 0; + vScrollConstraints.fill = 1; + add(verticalScrollBar, vScrollConstraints); + } + + private void updateScrollBarsSizes() { + Rectangle2D bounds = controller.getDrawing().getBounds(); + int margin = (int) (MARGIN * controller.getDrawing().getScale()); + horizontalScrollBar.setMinimum((int) bounds.getMinX() - margin); + horizontalScrollBar.setMaximum((int) bounds.getMaxX() + margin); + verticalScrollBar.setMinimum((int) bounds.getMinY() - margin); + verticalScrollBar.setMaximum((int) bounds.getMaxY() + margin); + } + + private void updateDrawingPositionFromScrollBars() { + controller.getDrawing().setPosition(horizontalScrollBar.getValue(), -verticalScrollBar.getValue()); + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + BackendAPI backend = CentralLookup.getDefault().lookup(BackendAPI.class); + + double horizontalPercent = getScrollbarPercent(horizontalScrollBar); + double verticalPercent = getScrollbarPercent(verticalScrollBar); + + // Apply the scaling + double scaleFactor = (e.getPreciseWheelRotation() * controller.getDrawing().getScale() * 0.1) * (backend.getSettings().isInvertMouseZoom() ? -1d : 1d); + controller.getDrawing().setScale(controller.getDrawing().getScale() + scaleFactor); + + updateScrollBarsSizes(); + setScrollbarPercent(horizontalScrollBar, horizontalPercent); + setScrollbarPercent(verticalScrollBar, verticalPercent); + } + + private void setScrollbarPercent(JScrollBar scrollBar, double percent) { + double width = ((double) scrollBar.getMaximum() - (double) scrollBar.getMinimum()); + scrollBar.setValue((int) Math.round(width * percent)); + } + + private double getScrollbarPercent(JScrollBar scrollBar) { + double width = ((double) scrollBar.getMaximum() - (double) scrollBar.getMinimum()); + return scrollBar.getValue() == 0 ? 0 : (scrollBar.getValue() / width); + } +} diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/ToolBox.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/ToolBox.java index 8a939d3109..ad473b8ce3 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/ToolBox.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/gui/ToolBox.java @@ -40,6 +40,7 @@ This file is part of Universal Gcode Sender (UGS). public class ToolBox extends ToolBar { private JToggleButton toolDropDownButton = null; + private JToggleButton jogDropDownButton = null; public ToolBox(Controller controller) { setFloatable(false); @@ -147,14 +148,14 @@ public ToolBox(Controller controller) { private JToggleButton createJogDropDownButton() { ActionListener toolMenuListener = e -> { - if (toolDropDownButton == null) { + if (jogDropDownButton == null) { return; } JMenuItem source = (JMenuItem) e.getSource(); - toolDropDownButton.setIcon((Icon) source.getAction().getValue(Action.LARGE_ICON_KEY)); - toolDropDownButton.setSelected(true); - toolDropDownButton.setAction(source.getAction()); + jogDropDownButton.setIcon((Icon) source.getAction().getValue(Action.LARGE_ICON_KEY)); + jogDropDownButton.setSelected(true); + jogDropDownButton.setAction(source.getAction()); }; JogMachineToCenterAction toolDrawRectangleAction = new JogMachineToCenterAction(); @@ -164,9 +165,9 @@ private JToggleButton createJogDropDownButton() { addDropDownAction(popupMenu, new JogMachineToTopRightCornerAction(), toolMenuListener); addDropDownAction(popupMenu, new JogMachineToLowerLeftCornerAction(), toolMenuListener); addDropDownAction(popupMenu, new JogMachineToLowerRightCornerAction(), toolMenuListener); - toolDropDownButton = DropDownButtonFactory.createDropDownToggleButton(ImageUtilities.loadImageIcon(JogMachineToCenterAction.LARGE_ICON_PATH, false), popupMenu); - toolDropDownButton.setAction(toolDrawRectangleAction); - return toolDropDownButton; + jogDropDownButton = DropDownButtonFactory.createDropDownToggleButton(ImageUtilities.loadImageIcon(JogMachineToCenterAction.LARGE_ICON_PATH, false), popupMenu); + jogDropDownButton.setAction(toolDrawRectangleAction); + return jogDropDownButton; } private JToggleButton createToolDropDownButton() { diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/io/gcode/toolpaths/LaserFillToolPath.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/io/gcode/toolpaths/LaserFillToolPath.java index cb8a0b2dce..f20ede69df 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/io/gcode/toolpaths/LaserFillToolPath.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/io/gcode/toolpaths/LaserFillToolPath.java @@ -71,7 +71,7 @@ private static void addLineIntersectionSegments(GcodePath gcodePath, Geometry ge partialPosition = Lists.reverse(partialPosition); } - for (int i = 0; i < partialPosition.size(); i += 2) { + for (int i = 0; i + 1 < partialPosition.size(); i += 2) { gcodePath.addSegment(SegmentType.MOVE, partialPosition.get(i)); gcodePath.addSegment(SegmentType.LINE, partialPosition.get(i + 1)); } diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/DesignerTopComponent.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/DesignerTopComponent.java index 2c48431e53..7e85c0db82 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/DesignerTopComponent.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/DesignerTopComponent.java @@ -21,7 +21,8 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.ugs.nbp.designer.actions.UndoManagerListener; import com.willwinder.ugs.nbp.designer.entities.selection.SelectionEvent; import com.willwinder.ugs.nbp.designer.entities.selection.SelectionListener; -import com.willwinder.ugs.nbp.designer.gui.DrawingContainer; +import com.willwinder.ugs.nbp.designer.gui.DrawingOverlayContainer; +import com.willwinder.ugs.nbp.designer.gui.DrawingScrollContainer; import com.willwinder.ugs.nbp.designer.gui.PopupMenuFactory; import com.willwinder.ugs.nbp.designer.gui.ToolBox; import com.willwinder.ugs.nbp.designer.logic.Controller; @@ -40,8 +41,10 @@ This file is part of Universal Gcode Sender (UGS). import org.openide.text.DataEditorSupport; import org.openide.windows.TopComponent; +import javax.swing.JComponent; import java.awt.BorderLayout; import java.io.File; +import java.io.Serial; import java.util.logging.Level; import java.util.logging.Logger; @@ -56,9 +59,10 @@ This file is part of Universal Gcode Sender (UGS). ) @TopComponent.Registration(mode = Mode.EDITOR_PRIMARY, openAtStartup = false) public class DesignerTopComponent extends TopComponent implements UndoManagerListener, SelectionListener, UGSEventListener { + @Serial private static final long serialVersionUID = 3123334398723987873L; private static final Logger LOGGER = Logger.getLogger(DesignerTopComponent.class.getSimpleName()); - private static DrawingContainer drawingContainer; + private static JComponent drawingContainer; private final transient UndoManagerAdapter undoManagerAdapter; private final transient BackendAPI backend; private final transient Controller controller; @@ -74,7 +78,7 @@ public DesignerTopComponent(UgsDataObject dataObject) { // We need to reuse the drawing container for each loaded file if (drawingContainer == null) { - drawingContainer = new DrawingContainer(controller); + drawingContainer = new DrawingOverlayContainer(controller, new DrawingScrollContainer(controller)); } undoManagerAdapter = new UndoManagerAdapter(controller.getUndoManager());