+
@@ -3017,8 +3020,10 @@
Options
if (text === "Inactive" || text === "Error") {
$("#launch").show();
+ $("#menu").hide();
} else {
$("#launch").hide();
+ $("#menu").show();
}
}
diff --git a/src/qz/common/Constants.java b/src/qz/common/Constants.java
index 3dcf9f889..af3b04227 100644
--- a/src/qz/common/Constants.java
+++ b/src/qz/common/Constants.java
@@ -93,6 +93,10 @@ public class Constants {
public static final Color TRUSTED_COLOR_LITE = Color.BLUE;
public static final Color WARNING_COLOR_DARK = Color.decode("#EB6261");
public static final Color TRUSTED_COLOR_DARK = Color.decode("#589DF6");
+ public static final Color RUNNING_COLOR = Color.decode("#00AD47");
+ public static final Color PENDING_COLOR = Color.decode("#B2B247");
+ public static final Color STOPPED_COLOR = Color.decode("#AE4745");
+
public static Color WARNING_COLOR = WARNING_COLOR_LITE;
public static Color TRUSTED_COLOR = TRUSTED_COLOR_LITE;
diff --git a/src/qz/common/TrayManager.java b/src/qz/common/TrayManager.java
index b620b48f0..313868a8a 100644
--- a/src/qz/common/TrayManager.java
+++ b/src/qz/common/TrayManager.java
@@ -26,12 +26,11 @@
import qz.utils.*;
import qz.ws.PrintSocketServer;
import qz.ws.SingleInstanceChecker;
+import qz.ws.SocketMethod;
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
+import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -62,6 +61,7 @@ public class TrayManager {
private AboutDialog aboutDialog;
private LogDialog logDialog;
private SiteManagerDialog sitesDialog;
+ private ControlDialog controlDialog;
private ArrayList componentList;
private IconCache.Icon shownIcon;
@@ -254,6 +254,10 @@ private void addMenuItems() {
sitesDialog = new SiteManagerDialog(sitesItem, iconCache, prefs);
componentList.add(sitesDialog);
+ JMenuItem controlMenuItem = new JMenuItem("Control Menu...", iconCache.getIcon(SAVED_ICON));
+ controlMenuItem.setMnemonic(KeyEvent.VK_C);
+ controlMenuItem.addActionListener(controlMenuListener);
+
JMenuItem diagnosticMenu = new JMenu("Diagnostic");
JMenuItem browseApp = new JMenuItem("Browse App folder...", iconCache.getIcon(FOLDER_ICON));
@@ -328,6 +332,7 @@ private void addMenuItems() {
advancedMenu.add(new JSeparator());
}
advancedMenu.add(sitesItem);
+ advancedMenu.add(controlMenuItem);
advancedMenu.add(desktopItem);
advancedMenu.add(new JSeparator());
advancedMenu.add(anonymousItem);
@@ -369,26 +374,87 @@ private void addMenuItems() {
popup.add(separator);
popup.add(exitItem);
+ controlDialog = new ControlDialog(iconCache);
+ componentList.add(controlDialog);
+
+ // Status/control section
+ controlDialog.add(reloadItem, ControlDialog.Category.STATUS);
+ controlDialog.add(exitItem, "Shut down", ControlDialog.Category.STATUS);
+
+ // General section
+ controlDialog.add(aboutItem, ControlDialog.Category.GENERAL);
+ controlDialog.add(sitesItem, ControlDialog.Category.GENERAL);
+ controlDialog.add(logItem, ControlDialog.Category.GENERAL);
+
+ // Advanced section
+ controlDialog.add(startupItem, ControlDialog.Category.ADVANCED);
+ controlDialog.add(notificationsItem, ControlDialog.Category.ADVANCED);
+ controlDialog.add(monocleItem, ControlDialog.Category.ADVANCED);
+ controlDialog.add(anonymousItem, ControlDialog.Category.ADVANCED);
+ controlDialog.add(new JSeparator(), ControlDialog.Category.ADVANCED);
+ controlDialog.add(desktopItem, ControlDialog.Category.ADVANCED);
+
+ // Diagnostic section
+ controlDialog.add(zipLogs, ControlDialog.Category.DIAGNOSTIC);
+ controlDialog.add(new JSeparator(), ControlDialog.Category.DIAGNOSTIC);
+ controlDialog.add(browseApp, ControlDialog.Category.DIAGNOSTIC);
+ controlDialog.add(browseUser, ControlDialog.Category.DIAGNOSTIC);
+ controlDialog.add(browseShared, ControlDialog.Category.DIAGNOSTIC);
+
if (tray != null) {
tray.setJPopupMenu(popup);
+ } // FIXME REMOVE THIS COMMENT // else {
+ // Display and minimize
+ controlDialog.setPersistent(true);
+ controlDialog.setVisible(true);
+ controlDialog.setState(Frame.ICONIFIED);
+ // FIXME REMOVE THIS COMMENT // controlMenuDialog.setState(Frame.ICONIFIED);
+ // FIXME REMOVE THIS COMMENT // }
+
+
+ }
+
+ private static boolean getCheckBoxState(ActionEvent e) {
+ Object o = e.getSource();
+ if(o instanceof JCheckBox) {
+ return ((JCheckBox)o).isSelected();
+ } else if(o instanceof JCheckBoxMenuItem) {
+ return ((JCheckBoxMenuItem)o).getState();
+ } else if(o instanceof CheckboxMenuItem) {
+ return ((CheckboxMenuItem)o).getState();
}
+ throw new UnsupportedOperationException("Cannot get checkbox state of " + o.getClass().getSimpleName());
}
+ private static void setCheckBoxState(ActionEvent e, boolean state) {
+ Object o = e.getSource();
+ if(o instanceof JCheckBox) {
+ ((JCheckBox)o).setSelected(state);
+ return;
+ } else if(o instanceof JCheckBoxMenuItem) {
+ ((JCheckBoxMenuItem)o).setState(state);
+ return;
+ } else if(o instanceof CheckboxMenuItem) {
+ ((CheckboxMenuItem)o).setState(state);
+ return;
+ }
+ throw new UnsupportedOperationException("Cannot get checkbox state of " + o.getClass().getSimpleName());
+ }
private final ActionListener notificationsListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- prefs.setProperty(Constants.PREFS_NOTIFICATIONS, ((JCheckBoxMenuItem)e.getSource()).getState());
+ prefs.setProperty(Constants.PREFS_NOTIFICATIONS, getCheckBoxState(e));
}
};
private final ActionListener monocleListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- JCheckBoxMenuItem j = (JCheckBoxMenuItem)e.getSource();
- prefs.setProperty(Constants.PREFS_MONOCLE, j.getState());
+ boolean state = getCheckBoxState(e);
+ prefs.setProperty(Constants.PREFS_MONOCLE, state);
displayWarningMessage(String.format("A restart of %s is required to ensure this feature is %sabled.",
- Constants.ABOUT_TITLE, j.getState()? "en":"dis"));
+ Constants.ABOUT_TITLE, state? "en":"dis"));
}
};
@@ -405,10 +471,7 @@ public void actionPerformed(ActionEvent e) {
};
private final ActionListener anonymousListener = e -> {
- boolean checkBoxState = true;
- if (e.getSource() instanceof JCheckBoxMenuItem) {
- checkBoxState = ((JCheckBoxMenuItem)e.getSource()).getState();
- }
+ boolean checkBoxState = getCheckBoxState(e);
log.debug("Block unsigned: {}", checkBoxState);
@@ -429,17 +492,18 @@ public void actionPerformed(ActionEvent e) {
private ActionListener startupListener() {
return e -> {
- JCheckBoxMenuItem source = (JCheckBoxMenuItem)e.getSource();
- if (!source.getState() && !confirmDialog.prompt("Remove " + name + " from startup?")) {
- source.setState(true);
+ if (!getCheckBoxState(e) && !confirmDialog.prompt("Remove " + name + " from startup?")) {
+ setCheckBoxState(e,true);
return;
}
- if (FileUtilities.setAutostart(source.getState())) {
- displayInfoMessage("Successfully " + (source.getState() ? "enabled" : "disabled") + " autostart");
+
+ boolean state = getCheckBoxState(e);
+ if (FileUtilities.setAutostart(state)) {
+ displayInfoMessage("Successfully " + (state ? "enabled" : "disabled") + " autostart");
} else {
- displayErrorMessage("Error " + (source.getState() ? "enabling" : "disabling") + " autostart");
+ displayErrorMessage("Error " + (state ? "enabling" : "disabling") + " autostart");
}
- source.setState(FileUtilities.isAutostart());
+ setCheckBoxState(e, FileUtilities.isAutostart());
};
}
@@ -475,6 +539,11 @@ public void actionPerformed(ActionEvent e) {
}
};
+
+ private final ActionListener controlMenuListener = e -> {
+ controlDialog.setVisible(true);
+ };
+
public void exit(int returnCode) {
prefs.save();
System.exit(returnCode);
@@ -602,6 +671,7 @@ private void setIcon(final IconCache.Icon i) {
public void refreshIcon(final Runnable whenDone) {
SwingUtilities.invokeLater(() -> {
tray.setIcon(shownIcon);
+ controlDialog.setRunningIndicator(shownIcon);
if(whenDone != null) {
whenDone.run();
}
@@ -630,6 +700,31 @@ private void displayMessage(final String caption, final String text, final TrayI
}
}
+ public void displayComponent(SocketMethod method, Point location) {
+ SwingUtilities.invokeLater(() -> {
+ switch(method) {
+ case GUI_SHOW_ABOUT:
+ SystemUtilities.centerWindow(aboutDialog, location);
+ aboutDialog.setVisible(true);
+ break;
+ case GUI_SHOW_LOG:
+ SystemUtilities.centerWindow(logDialog, location);
+ logDialog.setVisible(true);
+ break;
+ case GUI_SHOW_SITES:
+ SystemUtilities.centerWindow(sitesDialog, location);
+ sitesDialog.setVisible(true);
+ break;
+ case GUI_SHOW_MENU:
+ SystemUtilities.centerWindow(controlDialog, location);
+ controlDialog.setVisible(true);
+ break;
+ default:
+ throw new UnsupportedOperationException("Call \"" + method.getCallName() + "\" is not yet supported");
+ }
+ });
+ }
+
public void singleInstanceCheck(java.util.List insecurePorts, Integer insecurePortIndex) {
for(int port : insecurePorts) {
if (port != insecurePorts.get(insecurePortIndex)) {
diff --git a/src/qz/ui/BasicDialog.java b/src/qz/ui/BasicDialog.java
index 40829d070..07576a0bf 100644
--- a/src/qz/ui/BasicDialog.java
+++ b/src/qz/ui/BasicDialog.java
@@ -17,7 +17,7 @@
/**
* Created by Tres on 2/23/2015.
*/
-public class BasicDialog extends JDialog implements Themeable {
+public class BasicDialog extends JFrame implements Themeable {
private JPanel mainPanel;
private JComponent headerComponent;
private JComponent contentComponent;
@@ -30,13 +30,13 @@ public class BasicDialog extends JDialog implements Themeable {
private int stockButtonCount = 0;
public BasicDialog(JMenuItem caller, IconCache iconCache) {
- super((Frame)null, caller.getText().replaceAll("\\.+", ""), true);
+ super(caller.getText().replaceAll("\\.+", ""));
this.iconCache = iconCache;
initBasicComponents();
}
- public BasicDialog(Frame owner, String title, IconCache iconCache) {
- super(owner, title, true);
+ public BasicDialog(String title, IconCache iconCache) {
+ super(title);
this.iconCache = iconCache;
initBasicComponents();
}
diff --git a/src/qz/ui/ControlDialog.java b/src/qz/ui/ControlDialog.java
new file mode 100644
index 000000000..359c5a9c9
--- /dev/null
+++ b/src/qz/ui/ControlDialog.java
@@ -0,0 +1,232 @@
+package qz.ui;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import qz.common.Constants;
+import qz.ui.component.IconCache;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.Arrays;
+
+/**
+ * Created by Tres on 11/16/2022
+ * A container for all the System Tray menu items
+ */
+public class ControlDialog extends BasicDialog implements Themeable {
+ private static final Logger log = LogManager.getLogger(ControlDialog.class);
+
+ public enum Category {
+ STATUS,
+ GENERAL,
+ ADVANCED,
+ DIAGNOSTIC
+ }
+
+ private boolean persistent = false;
+
+ private JPanel statusPanel;
+ private JPanel statusLeftPanel;
+ private JPanel statusRightPanel;
+ private JPanel generalPanel;
+ private JPanel advancedPanel;
+ private JPanel diagnosticPanel;
+
+ private JLabel runningIndicator;
+ private JLabel runningLabel;
+
+ public ControlDialog(IconCache iconCache) {
+ super(Constants.ABOUT_TITLE, iconCache);
+ initComponents();
+ }
+
+ public void add(Component component, Category category) {
+ add(component, null, category);
+ }
+
+ public void add(Component component, String text, Category category) {
+ JComponent toAdd = null;
+ if(component instanceof JCheckBoxMenuItem) {
+ JCheckBoxMenuItem checkBoxMenuItem = (JCheckBoxMenuItem)component;
+ JCheckBox checkBox = new JCheckBox(text == null ? checkBoxMenuItem.getText() : text, checkBoxMenuItem.getIcon(), checkBoxMenuItem.getState());
+ Arrays.stream(checkBoxMenuItem.getActionListeners()).forEach(checkBox::addActionListener);
+
+ // Keep original in sync
+ checkBox.addChangeListener(e -> {
+ checkBoxMenuItem.setState(checkBox.isSelected());
+ });
+
+ // Add change listener on the original too
+ checkBoxMenuItem.addChangeListener(e -> checkBox.setSelected(checkBoxMenuItem.getState()));
+
+ toAdd = checkBox;
+ } else if(component instanceof JMenuItem) {
+ JMenuItem menuItem = (JMenuItem)component;
+ JButton button = new JButton(text == null ? menuItem.getText() : text, menuItem.getIcon());
+ Arrays.stream(menuItem.getActionListeners()).forEach(button::addActionListener);
+ toAdd = button;
+ } else if(component instanceof JSeparator){
+ toAdd = (JSeparator)component;
+ } else if (component instanceof JComponent){
+ toAdd = (JComponent)component;
+ } else {
+ log.warn("Cannot add {}, not yet supported.", component.getClass().getSimpleName());
+ }
+ if(toAdd != null) {
+ switch(category) {
+ case STATUS:
+ statusRightPanel.add(toAdd);
+ break;
+ case ADVANCED:
+ advancedPanel.add(toAdd);
+ break;
+ case DIAGNOSTIC:
+ diagnosticPanel.add(toAdd);
+ break;
+ case GENERAL:
+ default:
+ generalPanel.add(toAdd);
+ }
+ }
+ pack();
+ }
+
+ private void initComponents() {
+
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.setBorder(createPaddedLineBorder(5, SwingConstants.SOUTH));
+
+ statusLeftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ statusRightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+
+ statusPanel = new JPanel(new GridLayout(1, 3));
+
+ // Running indicator
+ runningIndicator = new JLabel("•");
+ runningIndicator.setFont(new Font("", Font.BOLD, 24));
+ runningIndicator.setForeground(Constants.STOPPED_COLOR);
+ runningIndicator.setBorder(new EmptyBorder(0, 2, 2, 2));
+ runningLabel = new JLabel("Stopped");
+ runningLabel.setBorder(new EmptyBorder(0, 0, 0, 4));
+ statusLeftPanel.add(runningIndicator);
+ statusLeftPanel.add(runningLabel);
+ statusPanel.add(statusLeftPanel);
+
+ // Version label
+ JLabel versionLabel = new JLabel(Constants.ABOUT_TITLE + " " + Constants.VERSION);
+ versionLabel.setFont(runningLabel.getFont());
+ statusPanel.add(versionLabel);
+
+ // Additional controls added with .add()
+ statusPanel.add(statusRightPanel);
+
+ Font headingFont = new JLabel().getFont().deriveFont(16f).deriveFont(Font.BOLD);
+
+ generalPanel = new JPanel();
+ generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
+ generalPanel.setBorder(createPaddedLineBorder(5, SwingConstants.EAST));
+ JLabel generalLabel = new JLabel("General");
+ generalLabel.setFont(headingFont);
+ generalPanel.add(generalLabel);
+
+ advancedPanel = new JPanel();
+ advancedPanel.setLayout(new BoxLayout(advancedPanel, BoxLayout.Y_AXIS));
+ advancedPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
+ JLabel advancedLabel = new JLabel("Advanced");
+ advancedLabel.setFont(headingFont);
+ advancedPanel.add(advancedLabel);
+
+ diagnosticPanel = new JPanel();
+ diagnosticPanel.setLayout(new BoxLayout(diagnosticPanel, BoxLayout.Y_AXIS));
+ diagnosticPanel.setBorder(createPaddedLineBorder(5, SwingConstants.WEST));
+ JLabel diagnosticLabel = new JLabel("Diagnostic");
+ diagnosticLabel.setFont(headingFont);
+ diagnosticPanel.add(diagnosticLabel);
+
+ setHeader(statusPanel);
+ statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
+ mainPanel.add(generalPanel, BorderLayout.LINE_START);
+ mainPanel.add(advancedPanel, BorderLayout.CENTER);
+ mainPanel.add(diagnosticPanel, BorderLayout.LINE_END);
+ setContent(mainPanel, false);
+
+ if(persistent) {
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ setExtendedState(JFrame.ICONIFIED);
+ }
+ });
+ }
+
+ setResizable(false);
+ pack();
+
+ setLocationRelativeTo(null); // center on main display
+ }
+
+ private static Border createPaddedLineBorder(int padding, int position) {
+ Color borderColor = new JSeparator().getForeground();
+ Border margins = new EmptyBorder(padding, padding, padding, padding);
+ Border border;
+
+ switch(position) {
+ case SwingConstants.NORTH:
+ border = new MatteBorder(1, 0, 0, 0, borderColor);
+ break;
+ case SwingConstants.WEST:
+ border = new MatteBorder(0, 1, 0, 0, borderColor);
+ break;
+ case SwingConstants.SOUTH:
+ border = new MatteBorder(0, 0, 1, 0, borderColor);
+ break;
+ default:
+ case SwingConstants.EAST:
+ border = new MatteBorder(0, 0, 0, 1, borderColor);
+ }
+ return new CompoundBorder(border, margins);
+ }
+
+ @Override
+ public void setVisible(boolean b) {
+ // Prevent closing if persistent mode is enabled
+ if(!b && persistent) {
+ setExtendedState(JFrame.ICONIFIED);
+ } else {
+ super.setVisible(b);
+ }
+ }
+
+ @Override
+ public void refresh() {
+ ThemeUtilities.refreshAll(this);
+ }
+
+ public void setRunningIndicator(IconCache.Icon icon) {
+ switch(icon) {
+ case WARNING_ICON:
+ runningIndicator.setForeground(Constants.PENDING_COLOR);
+ runningLabel.setText("Pending");
+ break;
+ case DANGER_ICON:
+ runningIndicator.setForeground(Constants.STOPPED_COLOR);
+ runningLabel.setText("Stopped");
+ break;
+ case DEFAULT_ICON:
+ default:
+ runningIndicator.setForeground(Constants.RUNNING_COLOR);
+ runningLabel.setText("Running");
+ }
+ }
+
+ /**
+ * Sets persistent mode, window can't be closed unless shutdown
+ */
+ public void setPersistent(boolean persistent) {
+ this.persistent = persistent;
+ }
+}
+
diff --git a/src/qz/ui/GatewayDialog.java b/src/qz/ui/GatewayDialog.java
index e9aa3cdb0..1e1ebd94f 100644
--- a/src/qz/ui/GatewayDialog.java
+++ b/src/qz/ui/GatewayDialog.java
@@ -220,7 +220,7 @@ public boolean prompt(String description, RequestState request, Point position)
setDescription(description);
setRequest(request);
refreshComponents();
- SystemUtilities.centerDialog(this, position);
+ SystemUtilities.centerWindow(this, position);
setVisible(true);
return isApproved();
diff --git a/src/qz/ui/tray/AWTMenuWrapper.java b/src/qz/ui/tray/AWTMenuWrapper.java
index 99304e9f2..c103c6325 100644
--- a/src/qz/ui/tray/AWTMenuWrapper.java
+++ b/src/qz/ui/tray/AWTMenuWrapper.java
@@ -75,7 +75,10 @@ private void wrapItemListeners(final JMenuItem item) {
private void wrapState(JMenuItem item) {
if (this.item instanceof CheckboxMenuItem && item instanceof JCheckBoxMenuItem) {
+ // Match initial state
((CheckboxMenuItem)this.item).setState(((JCheckBoxMenuItem)item).getState());
+ // Monitor future state
+ item.addChangeListener(e -> ((CheckboxMenuItem)AWTMenuWrapper.this.item).setState(((JCheckBoxMenuItem)item).getState()));
}
}
diff --git a/src/qz/ui/tray/TrayType.java b/src/qz/ui/tray/TrayType.java
index 3167e9c33..80aa0fa30 100644
--- a/src/qz/ui/tray/TrayType.java
+++ b/src/qz/ui/tray/TrayType.java
@@ -2,7 +2,6 @@
import org.jdesktop.swinghelper.tray.JXTrayIcon;
import qz.ui.component.IconCache;
-
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
diff --git a/src/qz/utils/MacUtilities.java b/src/qz/utils/MacUtilities.java
index 26822b7f5..20be2e007 100644
--- a/src/qz/utils/MacUtilities.java
+++ b/src/qz/utils/MacUtilities.java
@@ -38,7 +38,7 @@
*/
public class MacUtilities {
private static final Logger log = LogManager.getLogger(MacUtilities.class);
- private static Dialog aboutDialog;
+ private static Window aboutDialog;
private static TrayManager trayManager;
private static String bundleId;
private static Boolean jdkSupportsTemplateIcon;
@@ -56,7 +56,7 @@ public static void showExitPrompt() {
/**
* Adds a listener to register the Apple "About" dialog to call {@code setVisible()} on the specified Dialog
*/
- public static void registerAboutDialog(Dialog aboutDialog) {
+ public static void registerAboutDialog(Window aboutDialog) {
MacUtilities.aboutDialog = aboutDialog;
try {
diff --git a/src/qz/utils/SystemUtilities.java b/src/qz/utils/SystemUtilities.java
index ea6442662..969fce7ed 100644
--- a/src/qz/utils/SystemUtilities.java
+++ b/src/qz/utils/SystemUtilities.java
@@ -517,11 +517,11 @@ public static boolean setSystemLookAndFeel() {
* @param position The center point of a screen as calculated from a web browser at 96-dpi
* @return true if the operation is successful
*/
- public static void centerDialog(Dialog dialog, Point position) {
+ public static void centerWindow(Window window, Point position) {
// Assume 0,0 are bad coordinates
if (position == null || (position.getX() == 0 && position.getY() == 0)) {
log.debug("Invalid dialog position provided: {}, we'll center on first monitor instead", position);
- dialog.setLocationRelativeTo(null);
+ window.setLocationRelativeTo(null);
return;
}
@@ -529,22 +529,22 @@ public static void centerDialog(Dialog dialog, Point position) {
double dpiScale = getWindowScaleFactor();
if (dpiScale == 0) {
log.debug("Invalid window scale value: {}, we'll center on the primary monitor instead", dpiScale);
- dialog.setLocationRelativeTo(null);
+ window.setLocationRelativeTo(null);
return;
}
- Rectangle rect = new Rectangle((int)(position.x * dpiScale), (int)(position.y * dpiScale), dialog.getWidth(), dialog.getHeight());
- rect.translate(-dialog.getWidth() / 2, -dialog.getHeight() / 2);
+ Rectangle rect = new Rectangle((int)(position.x * dpiScale), (int)(position.y * dpiScale), window.getWidth(), window.getHeight());
+ rect.translate(-window.getWidth() / 2, -window.getHeight() / 2);
Point p = new Point((int)rect.getCenterX(), (int)rect.getCenterY());
log.debug("Calculated dialog centered at: {}", p);
if (!isWindowLocationValid(rect)) {
log.debug("Dialog position provided is out of bounds: {}, we'll center on the primary monitor instead", p);
- dialog.setLocationRelativeTo(null);
+ window.setLocationRelativeTo(null);
return;
}
- dialog.setLocation(rect.getLocation());
+ window.setLocation(rect.getLocation());
}
/**
diff --git a/src/qz/ws/PrintSocketClient.java b/src/qz/ws/PrintSocketClient.java
index 4133f5cb5..edc59653c 100644
--- a/src/qz/ws/PrintSocketClient.java
+++ b/src/qz/ws/PrintSocketClient.java
@@ -633,6 +633,16 @@ private void processMessage(Session session, JSONObject json, SocketConnection c
case GET_VERSION:
sendResult(session, UID, Constants.VERSION);
break;
+ case GUI_SHOW_MENU:
+ case GUI_SHOW_SITES:
+ case GUI_SHOW_ABOUT:
+ case GUI_SHOW_LOG:
+ if(trayManager != null) {
+ trayManager.displayComponent(call, findDialogPosition(session, json.optJSONObject("position")));
+ } else {
+ log.warn("Cannot call \"{}\" when trayManager is null", call.getCallName());
+ }
+ break;
case WEBSOCKET_STOP:
log.info("Another instance of {} is asking this to close", Constants.ABOUT_TITLE);
String challenge = json.optString("challenge", "");
diff --git a/src/qz/ws/SocketMethod.java b/src/qz/ws/SocketMethod.java
index 0caf37998..ba50ca0a2 100644
--- a/src/qz/ws/SocketMethod.java
+++ b/src/qz/ws/SocketMethod.java
@@ -1,5 +1,7 @@
package qz.ws;
+import qz.common.Constants;
+
public enum SocketMethod {
PRINTERS_GET_DEFAULT("printers.getDefault", true, "access connected printers"),
PRINTERS_FIND("printers.find", true, "access connected printers"),
@@ -55,6 +57,11 @@ public enum SocketMethod {
NETWORKING_DEVICE_LEGACY("websocket.getNetworkInfo", true),
GET_VERSION("getVersion", false),
+ GUI_SHOW_MENU("gui.showMenu", true, "show " + Constants.ABOUT_TITLE + " menu"),
+ GUI_SHOW_SITES("gui.showSites", true, "show " + Constants.ABOUT_TITLE + " Site Manager"),
+ GUI_SHOW_ABOUT("gui.showAbout", true, "show " + Constants.ABOUT_TITLE + " About Dialog"),
+ GUI_SHOW_LOG("gui.showLog", true, "show " + Constants.ABOUT_TITLE + " Log Dialog"),
+
WEBSOCKET_STOP("websocket.stop", false),
INVALID("", false);