diff options
Diffstat (limited to 'dozentenmodul/src/main/java/org/openslx/dozmod/gui/Gui.java')
-rw-r--r-- | dozentenmodul/src/main/java/org/openslx/dozmod/gui/Gui.java | 224 |
1 files changed, 97 insertions, 127 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/Gui.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/Gui.java index 0d14a3b9..5bce8d9f 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/Gui.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/Gui.java @@ -1,35 +1,38 @@ package org.openslx.dozmod.gui; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; import java.util.concurrent.atomic.AtomicReference; +import javax.management.monitor.Monitor; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + import org.apache.log4j.Logger; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Monitor; -import org.eclipse.swt.widgets.Shell; import org.openslx.dozmod.gui.helper.MessageType; +import org.openslx.util.QuickTimer; public class Gui { private static final Logger LOGGER = Logger.getLogger(Gui.class); - /** - * The one and only display to use throughout the application - */ - public static final Display display = new Display(); - - /** - * All active shells - we don't use display.getShells() as it is slow... - */ - private static final List<Shell> shells = new ArrayList<>(); - - private static volatile int exitCode = 0; + private static Rectangle clientArea(GraphicsDevice gd) { + Insets inset = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration()); + Rectangle bounds = gd.getDefaultConfiguration().getBounds(); + bounds.x += inset.left; + bounds.y += inset.top; + bounds.width -= (inset.top + inset.bottom); + bounds.height -= (inset.left + inset.right); + return bounds; + } /** * Center the given shell on the {@link Monitor} it is displayed on. @@ -37,9 +40,9 @@ public class Gui { * * @param shell Some shell */ - public static void centerShell(Shell shell) { - Monitor activeMonitor = getMonitorFromRectangle(shell.getBounds(), true); - Rectangle bounds = activeMonitor.getClientArea(); + public static void centerShell(JFrame shell) { + GraphicsDevice activeMonitor = getMonitorFromRectangle(shell.getBounds(), true); + Rectangle bounds = clientArea(activeMonitor); Rectangle rect = shell.getBounds(); int x = bounds.x + (bounds.width - rect.width) / 2; int y = bounds.y + (bounds.height - rect.height) / 2; @@ -52,7 +55,7 @@ public class Gui { * @param parent Parent shell, used as reference * @param shellToCenter The shell that should be repositioned */ - public static void centerShellOverShell(Shell parent, Shell shellToCenter) { + public static void centerShellOverShell(JFrame parent, JFrame shellToCenter) { Rectangle bounds = parent.getBounds(); Rectangle rect = shellToCenter.getBounds(); int x = bounds.x + (bounds.width - rect.width) / 2; @@ -65,14 +68,15 @@ public class Gui { } /** - * Make sure the given shell fits the {@link Monitor} it is displayed on. + * Make sure the given shell fits the {@link GraphicsDevice} it is displayed + * on. * * @param shell Some shell */ - public static void limitShellSize(Shell shell) { - Monitor activeMonitor = getMonitorFromRectangle(shell.getBounds(), true); - Rectangle bounds = activeMonitor.getClientArea(); - Rectangle rect = shell.getBounds(); + public static void limitShellSize(JFrame window) { + GraphicsDevice activeMonitor = getMonitorFromRectangle(window.getBounds(), true); + Rectangle bounds = clientArea(activeMonitor); + Rectangle rect = window.getBounds(); boolean changed = false; if (rect.width + 20 > bounds.width) { rect.width = bounds.width - 20; @@ -83,8 +87,8 @@ public class Gui { changed = true; } if (changed) { - shell.setSize(rect.width, rect.height); - rect = shell.getBounds(); + window.setSize(rect.width, rect.height); + rect = window.getBounds(); } changed = false; if (rect.x + rect.width >= bounds.x + bounds.width) { @@ -96,7 +100,7 @@ public class Gui { changed = true; } if (changed) { - shell.setLocation(rect.x, rect.y); + window.setLocation(rect.x, rect.y); } } @@ -108,18 +112,18 @@ public class Gui { * primary monitor if true, <code>null</code> otherwise * @return the {@link Monitor} */ - public static Monitor getMonitorFromPoint(Point point, boolean defaultToPrimary) { + private static GraphicsDevice getMonitorFromPoint(GraphicsDevice[] screens, Point point, + boolean defaultToPrimary) { LOGGER.debug("Finding monitor for point " + point.toString()); - Monitor[] monitors = display.getMonitors(); - for (Monitor monitor : monitors) { - Rectangle bounds = monitor.getBounds(); + for (GraphicsDevice dev : screens) { + Rectangle bounds = dev.getDefaultConfiguration().getBounds(); LOGGER.debug("Checking monitor " + bounds.toString()); if (bounds.contains(point)) - return monitor; + return dev; } if (defaultToPrimary) { LOGGER.debug("Defaulting to primary..."); - return display.getPrimaryMonitor(); + return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); } return null; } @@ -132,10 +136,14 @@ public class Gui { * primary monitor if true, <code>null</code> otherwise * @return the {@link Monitor} */ - public static Monitor getMonitorFromRectangle(Rectangle rect, boolean defaultToPrimary) { + private static GraphicsDevice getMonitorFromRectangle(Rectangle rect, boolean defaultToPrimary) { // Make sure rectangle is in bounds. This is not completely accurate // in case there are multiple monitors that have different resolutions. - Rectangle bounds = display.getBounds(); + GraphicsDevice[] screens = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + Rectangle bounds = new Rectangle(); + for (GraphicsDevice dev : screens) { + bounds.union(dev.getDefaultConfiguration().getBounds()); + } LOGGER.debug("Display bounds are " + bounds.toString() + ", rect is " + rect.toString()); if (rect.x + rect.width >= bounds.x + bounds.width) { rect.width -= (rect.x + rect.width) - (bounds.x + bounds.width); @@ -157,7 +165,7 @@ public class Gui { } LOGGER.debug("After correction: " + rect.toString()); // Now just use the same code as *FromPoint by using the rectangle's center - return getMonitorFromPoint(new Point(rect.x + rect.width / 2, rect.y + rect.height / 2), + return getMonitorFromPoint(screens, new Point(rect.x + rect.width / 2, rect.y + rect.height / 2), defaultToPrimary); } @@ -170,16 +178,28 @@ public class Gui { */ public static <T> T syncExec(final GuiCallable<T> task) { final AtomicReference<T> instance = new AtomicReference<>(); - display.syncExec(new Runnable() { - @Override - public void run() { - try { - instance.set(task.run()); - } catch (Throwable e) { - LOGGER.warn("syncExec failed!", e); + final AtomicReference<Throwable> thrown = new AtomicReference<>(); + if (SwingUtilities.isEventDispatchThread()) { + return task.run(); + } + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + instance.set(task.run()); + } catch (Throwable e) { + thrown.set(e); + } } - } - }); + }); + } catch (InvocationTargetException | InterruptedException e) { + LOGGER.warn("syncExec() failed", e); + return null; + } + if (thrown.get() != null) { + throw new RuntimeException("task passed to syncExec() failed", thrown.get()); + } return instance.get(); } @@ -190,7 +210,7 @@ public class Gui { * @param task Task to run */ public static void asyncExec(final Runnable task) { - display.asyncExec(task); + SwingUtilities.invokeLater(task); } /** @@ -203,93 +223,43 @@ public class Gui { } /** + * Exit application - dispose all shells, so mainloop will terminate. + * + * @param code + */ + public static void exit(int code) { + QuickTimer.cancel(); + Window[] ownerlessWindows = Frame.getOwnerlessWindows(); + for (Window w : ownerlessWindows) { + w.dispose(); + } + System.exit(code); + } + + /** * Generic helper to show a message box to the user, and optionally log the * message to the log file. * - * @param parent parent shell this message box belongs to - * @param message Message to display. Can be multiline. + * @param message Message to display. Can be multi line. * @param messageType Type of message (warning, information) * @param logger Logger instance to log to. Can be null. * @param exception Exception related to this message. Can be null. - * @return true if OK, YES or RETRY was clicked, false for CANCEL or NO + * @return true if OK or YES was clicked, false for CANCEL/NO/(X) */ - public static boolean showMessageBox(Shell parent, String message, MessageType messageType, - Logger logger, Throwable exception) { + public static boolean showMessageBox(String message, MessageType messageType, Logger logger, + Throwable exception) { if (logger != null) logger.log(messageType.logPriority, message, exception); if (exception != null) message += "\n\n" + exception.getClass().getSimpleName() + "\n" + exception.getMessage() + "\n" + " (Siehe Logdatei)"; - MessageBox box = new MessageBox(parent, messageType.style); - box.setMessage(message); - box.setText(messageType.title); - int ret = box.open(); - return ret == SWT.OK || ret == SWT.RETRY || ret == SWT.YES; - } - - /** - * Run the GUI mainloop as long as a window exists. This method does not - * return. - */ - public static void mainloop() { - do { - Iterator<Shell> it = shells.iterator(); - while (it.hasNext()) { - if (it.next().isDisposed()) - it.remove(); - } - if (!display.readAndDispatch()) - display.sleep(); - } while (!shells.isEmpty()); - display.dispose(); - System.exit(exitCode); - } - - /** - * Exit application - dispose all shells, so mainloop will terminate. - * - * @param code - */ - public static void exit(int code) { - exitCode = code; - asyncExec(new Runnable() { - @Override - public void run() { - for (Shell shell : shells) { - shell.dispose(); - } - } - }); - } - - /** - * Wrapper to get a new shell. This adds the shell to the list of shells, - * which we need to determine whether the app should still be running. - * - * @param style the style of the {@link Shell} - * @return a new {@link Shell} that has no other {@link Shell} as its - * parent. - */ - public static Shell newShell(int style) { - Shell shell = new Shell(display, style); - shells.add(shell); - return shell; - } - - /** - * Wrapper to get a new shell that is a child of another shell. This adds - * the shell to the list of shells, which we need to determine whether the - * app should still be running. - * - * @param parent the parent {@link Shell} - * @param style the style of the {@link Shell} - * @return a new {@link Shell} that has no other {@link Shell} as its - * parent. - */ - public static Shell newShell(Shell parent, int style) { - Shell shell = new Shell(parent, style); - shells.add(shell); - return shell; + if (messageType.buttons == -1) { + JOptionPane.showMessageDialog(null, message, messageType.title, messageType.optionPaneId); + return true; + } + int ret = JOptionPane.showConfirmDialog(null, message, messageType.title, messageType.optionPaneId, + messageType.buttons); + return ret == JOptionPane.OK_OPTION || ret == JOptionPane.YES_OPTION; } } |