Skip to content

Commit

Permalink
Mappable shortcuts in the designer (#2118)
Browse files Browse the repository at this point in the history
* Made it possible to assign shortcuts to actions in the designer
* Fixed selection problem in the entities list and added popup menu.
  • Loading branch information
breiler authored Jan 11, 2023
1 parent 83c7e58 commit fd049ae
Show file tree
Hide file tree
Showing 48 changed files with 687 additions and 291 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.model.Position;
import com.willwinder.universalgcodesender.model.UGSEvent;
import com.willwinder.universalgcodesender.model.events.ControllerStateEvent;
import com.willwinder.universalgcodesender.model.events.FileState;
import com.willwinder.universalgcodesender.model.events.FileStateEvent;
import com.willwinder.universalgcodesender.uielements.helpers.LoaderDialogHelper;
import com.willwinder.universalgcodesender.utils.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
package com.willwinder.ugs.nbp.designer;

import com.willwinder.ugs.nbp.designer.actions.SimpleUndoManager;
import com.willwinder.ugs.nbp.designer.actions.UndoManager;
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionManager;
import com.willwinder.ugs.nbp.designer.gui.*;
import com.willwinder.ugs.nbp.designer.gui.DrawingContainer;
import com.willwinder.ugs.nbp.designer.gui.MainMenu;
import com.willwinder.ugs.nbp.designer.gui.PopupMenuFactory;
import com.willwinder.ugs.nbp.designer.gui.SelectionSettingsPanel;
import com.willwinder.ugs.nbp.designer.gui.ToolBox;
import com.willwinder.ugs.nbp.designer.gui.tree.EntitiesTree;
import com.willwinder.ugs.nbp.designer.gui.tree.EntityTreeModel;
import com.willwinder.ugs.nbp.designer.io.svg.SvgReader;
import com.willwinder.ugs.nbp.designer.logic.Controller;
import com.willwinder.ugs.nbp.designer.logic.ControllerFactory;
import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;

import javax.swing.*;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Dimension;

/**
* A test implementation of the gcode designer tool that works in stand alone mode
Expand All @@ -21,27 +30,29 @@
public class DesignerMain extends JFrame {

private static final long serialVersionUID = 0;
public static final String PROPERTY_IS_STANDALONE = "ugs.designer.standalone";
public static final String PROPERTY_USE_SCREEN_MENU = "apple.laf.useScreenMenuBar";

/**
* Constructs a new graphical user interface for the program and shows it.
*/
public DesignerMain() {
System.setProperty("apple.laf.useScreenMenuBar", "true");

System.setProperty(PROPERTY_USE_SCREEN_MENU, "true");
System.setProperty(PROPERTY_IS_STANDALONE, "true");

setTitle("UGS Designer");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(1024, 768));

UndoManager undoManager = new SimpleUndoManager();
Controller controller = ControllerFactory.getController();
CentralLookup.getDefault().add(controller);

UndoManager undoManager = ControllerFactory.getUndoManager();
CentralLookup.getDefault().add(undoManager);

SelectionManager selectionManager = new SelectionManager();
SelectionManager selectionManager = ControllerFactory.getSelectionManager();
CentralLookup.getDefault().add(selectionManager);

Controller controller = new Controller(selectionManager, undoManager);
CentralLookup.getDefault().add(controller);

DrawingContainer drawingContainer = new DrawingContainer(controller);
selectionManager.addSelectionListener(e -> drawingContainer.repaint());

Expand All @@ -64,13 +75,13 @@ public DesignerMain() {
setVisible(true);

loadExample(controller);
controller.getDrawing().setComponentPopupMenu(new PopupMenuFactory().createPopupMenu(controller));
controller.getDrawing().setComponentPopupMenu(PopupMenuFactory.createPopupMenu());
controller.getDrawing().repaint();
}

private JSplitPane createRightPanel(Controller controller) {
EntityTreeModel entityTreeModel = new EntityTreeModel(controller);
JSplitPane toolsSplit = new JSplitPane( JSplitPane.VERTICAL_SPLIT, new JScrollPane(new EntitiesTree(controller, entityTreeModel)), new SelectionSettingsPanel(controller));
JSplitPane toolsSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(new EntitiesTree(controller, entityTreeModel)), new SelectionSettingsPanel(controller));
toolsSplit.setResizeWeight(0.9);
return toolsSplit;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ This file is part of Universal Gcode Sender (UGS).
import java.awt.geom.Point2D;
import java.text.ParseException;

import static com.willwinder.ugs.nbp.designer.DesignerMain.PROPERTY_IS_STANDALONE;

/**
* @author Joacim Breiler
*/
Expand Down Expand Up @@ -113,4 +115,14 @@ public static double roundToDecimals(double value, int decimals) {
}
return Math.round(value * power) / power;
}

/**
* Returns if the application is stand alone. This is a work around for
* the netbeans platform that uses DataObjects to open files.
*
* @return true if we are running in our own main
*/
public static boolean isStandalone() {
return Boolean.parseBoolean(System.getProperty(PROPERTY_IS_STANDALONE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright 2023 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 <http://www.gnu.org/licenses/>.
*/
package com.willwinder.ugs.nbp.designer.actions;

import com.willwinder.ugs.nbp.designer.Utils;
import com.willwinder.ugs.nbp.designer.platform.UgsDataObject;
import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;
import com.willwinder.universalgcodesender.listeners.UGSEventListener;
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.model.UGSEvent;
import com.willwinder.universalgcodesender.model.events.ControllerStateEvent;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.Utilities;

import javax.swing.AbstractAction;

/**
* An abstract action class for design actions. This will listen if a connected machine is idle or
* that a file has been loaded
*
* @author Joacim Breiler
*/
public abstract class AbstractDesignAction extends AbstractAction implements LookupListener, UGSEventListener {
private final transient BackendAPI backendAPI;
private final transient Lookup context;

protected AbstractDesignAction() {
this(Utilities.actionsGlobalContext());
}

protected AbstractDesignAction(Lookup context) {
super();
this.context = context;
backendAPI = CentralLookup.getDefault().lookup(BackendAPI.class);
backendAPI.addUGSEventListener(this);

Lookup.Result<UgsDataObject> lookupResult = context.lookupResult(UgsDataObject.class);
lookupResult.addLookupListener(this);
}

@Override
public void resultChanged(LookupEvent ev) {
boolean isIdleOrDisconnected = (backendAPI.isConnected() && backendAPI.isIdle()) || !backendAPI.isConnected();
boolean isFileLoaded = Utils.isStandalone() || (!context.lookupAll(UgsDataObject.class).isEmpty());
setEnabled(isIdleOrDisconnected && isFileLoaded);
}

@Override
public void UGSEvent(UGSEvent event) {
if (event instanceof ControllerStateEvent) {
resultChanged(null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.entities.Entity;
import com.willwinder.ugs.nbp.designer.logic.Controller;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -33,7 +32,7 @@ This file is part of Universal Gcode Sender (UGS).
*
* @author Joacim Breiler
*/
public class AddAction extends AbstractAction implements DrawAction, UndoableAction {
public class AddAction extends AbstractDesignAction implements DrawAction, UndoableAction {

private final transient Controller controller;
private final transient List<Entity> entities;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionManager;
import com.willwinder.ugs.nbp.designer.io.gcode.toolpaths.ToolPathUtils;
import com.willwinder.ugs.nbp.designer.logic.Controller;
import com.willwinder.ugs.nbp.designer.logic.ControllerFactory;
import com.willwinder.ugs.nbp.lib.services.LocalizingService;
import org.locationtech.jts.awt.ShapeWriter;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.openide.awt.ActionID;
import org.openide.awt.ActionRegistration;
import org.openide.util.ImageUtilities;

import javax.swing.*;
import java.awt.*;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.geom.Area;
import java.util.ArrayList;
Expand All @@ -47,19 +50,26 @@ This file is part of Universal Gcode Sender (UGS).
*
* @author Joacim Breiler
*/
public class BreakApartAction extends AbstractAction implements SelectionListener {
private static final String SMALL_ICON_PATH = "img/break.svg";
@ActionID(
category = LocalizingService.CATEGORY_DESIGNER,
id = "BreakApartAction")
@ActionRegistration(
iconBase = BreakApartAction.SMALL_ICON_PATH,
displayName = "Break apart",
lazy = false)
public class BreakApartAction extends AbstractDesignAction implements SelectionListener {
public static final String SMALL_ICON_PATH = "img/break.svg";
private static final String LARGE_ICON_PATH = "img/break24.svg";
private final transient Controller controller;

public BreakApartAction(Controller controller) {
public BreakApartAction() {
putValue("menuText", "Break apart");
putValue(NAME, "Break apart");
putValue("iconBase", SMALL_ICON_PATH);
putValue(SMALL_ICON, ImageUtilities.loadImageIcon(SMALL_ICON_PATH, false));
putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(LARGE_ICON_PATH, false));

this.controller = controller;
this.controller = ControllerFactory.getController();
SelectionManager selectionManager = controller.getSelectionManager();
selectionManager.addSelectionListener(this);
onSelectionEvent(new SelectionEvent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionListener;
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionManager;
import com.willwinder.ugs.nbp.designer.logic.Controller;
import com.willwinder.ugs.nbp.designer.logic.ControllerFactory;
import com.willwinder.ugs.nbp.lib.services.LocalizingService;
import org.openide.awt.ActionID;
import org.openide.awt.ActionRegistration;
import org.openide.util.ImageUtilities;

import javax.swing.*;
Expand All @@ -30,21 +34,28 @@ This file is part of Universal Gcode Sender (UGS).
/**
* @author Joacim Breiler
*/
@ActionID(
category = LocalizingService.CATEGORY_DESIGNER,
id = "ClearSelectionAction")
@ActionRegistration(
iconBase = ClearSelectionAction.SMALL_ICON_PATH,
displayName = "Clear selection",
lazy = false)
public class ClearSelectionAction extends AbstractAction implements SelectionListener {

public static final String SMALL_ICON_PATH = "img/clear-selection.svg";
public static final String LARGE_ICON_PATH = "img/clear-selection24.svg";

private final transient SelectionManager selectionManager;

public ClearSelectionAction(Controller controller) {
public ClearSelectionAction() {
putValue("iconBase", SMALL_ICON_PATH);
putValue(SMALL_ICON, ImageUtilities.loadImageIcon(SMALL_ICON_PATH, false));
putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(LARGE_ICON_PATH, false));
putValue("menuText", "Clear selection");
putValue(NAME, "Clear selection");

selectionManager = controller.getSelectionManager();
selectionManager = ControllerFactory.getSelectionManager();
selectionManager.addSelectionListener(this);
setEnabled(!selectionManager.getSelection().isEmpty());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionManager;
import com.willwinder.ugs.nbp.designer.io.ugsd.UgsDesignWriter;
import com.willwinder.ugs.nbp.designer.logic.Controller;
import com.willwinder.ugs.nbp.designer.logic.ControllerFactory;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
Expand All @@ -24,15 +25,15 @@
path = "Shortcuts",
name = "D-C")
})
public class CopyAction extends AbstractAction implements SelectionListener {
public class CopyAction extends AbstractDesignAction implements SelectionListener {

private final transient Controller controller;

public CopyAction(Controller controller) {
public CopyAction() {
putValue("menuText", "Copy");
putValue(NAME, "Copy");

this.controller = controller;
this.controller = ControllerFactory.getController();

SelectionManager selectionManager = controller.getSelectionManager();
selectionManager.addSelectionListener(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionEvent;
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionListener;
import com.willwinder.ugs.nbp.designer.entities.selection.SelectionManager;
import com.willwinder.ugs.nbp.designer.logic.ControllerFactory;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
Expand All @@ -48,7 +49,7 @@ This file is part of Universal Gcode Sender (UGS).
path = "Shortcuts",
name = "BACK_SPACE")
})
public class DeleteAction extends AbstractAction implements SelectionListener {
public class DeleteAction extends AbstractDesignAction implements SelectionListener {

private static final String SMALL_ICON_PATH = "img/delete.svg";
private static final String LARGE_ICON_PATH = "img/delete24.svg";
Expand All @@ -58,14 +59,14 @@ public class DeleteAction extends AbstractAction implements SelectionListener {
* Creates an DeleteAction that removes all shapes in the given Selection
* from the given Drawing.
*/
public DeleteAction(Controller controller) {
public DeleteAction() {
putValue("iconBase", SMALL_ICON_PATH);
putValue(SMALL_ICON, ImageUtilities.loadImageIcon(SMALL_ICON_PATH, false));
putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(LARGE_ICON_PATH, false));
putValue("menuText", "Delete");
putValue(NAME, "Delete");

this.controller = controller;
this.controller = ControllerFactory.getController();

SelectionManager selectionManager = controller.getSelectionManager();
selectionManager.addSelectionListener(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.utils.SwingHelpers;
import org.openide.util.ImageUtilities;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.Optional;

/**
* @author Joacim Breiler
*/
public class ExportGcodeAction extends AbstractAction {
public class ExportGcodeAction extends AbstractDesignAction {
public static final String SMALL_ICON_PATH = "img/export.svg";
public static final String LARGE_ICON_PATH = "img/export24.svg";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.logic.Controller;
import org.openide.util.ImageUtilities;

import javax.swing.AbstractAction;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
Expand All @@ -32,7 +31,7 @@ This file is part of Universal Gcode Sender (UGS).
/**
* @author Joacim Breiler
*/
public class ExportPngAction extends AbstractAction {
public class ExportPngAction extends AbstractDesignAction {

private static final String SMALL_ICON_PATH = "img/export.svg";
private static final String LARGE_ICON_PATH = "img/export24.svg";
Expand Down
Loading

0 comments on commit fd049ae

Please sign in to comment.