X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FJvOptionPane.java;h=0a7c49ea2a1d758c7daa174d58499bc555cddc8d;hb=1213d49ca3df8f48360da857121805d088c13aab;hp=d8051643a9b4e2276ee3eacb0d4ff5a119f5d4f7;hpb=26cd0e575e86884dee2d8cafab1effa05c3842d3;p=jalview.git diff --git a/src/jalview/gui/JvOptionPane.java b/src/jalview/gui/JvOptionPane.java index d805164..0a7c49e 100644 --- a/src/jalview/gui/JvOptionPane.java +++ b/src/jalview/gui/JvOptionPane.java @@ -32,16 +32,18 @@ import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseMotionAdapter; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.Icon; @@ -50,26 +52,48 @@ import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuBar; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JRootPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.InternalFrameEvent; import javax.swing.event.InternalFrameListener; +import jalview.bin.Console; +import jalview.util.ChannelProperties; +import jalview.util.MessageManager; import jalview.util.Platform; import jalview.util.dialogrunner.DialogRunnerI; -public class JvOptionPane extends JOptionPane implements DialogRunnerI, PropertyChangeListener { +public class JvOptionPane extends JOptionPane + implements DialogRunnerI, PropertyChangeListener +{ private static final long serialVersionUID = -3019167117756785229L; private static Object mockResponse = JvOptionPane.CANCEL_OPTION; private static boolean interactiveMode = true; + public static final Runnable NULLCALLABLE = () -> { + }; + private Component parentComponent; - private Map> callbacks = new HashMap<>(); + private ExecutorService executor = Executors.newCachedThreadPool(); + + private JDialog dialog = null; + + private Map callbacks = new HashMap<>(); + + private int timeout = -1; + + public void setTimeout(int i) + { + timeout = i; + } /* * JalviewJS reports user choice in the dialog as the selected option (text); @@ -77,13 +101,19 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property */ List ourOptions; - public JvOptionPane(final Component parent) { + public JvOptionPane(final Component parent) + { this.parentComponent = Platform.isJS() ? this : parent; + this.setIcon(null); } - public static int showConfirmDialog(Component parentComponent, Object message) throws HeadlessException { + public static int showConfirmDialog(Component parentComponent, + Object message) throws HeadlessException + { // only called by test - return isInteractiveMode() ? JOptionPane.showConfirmDialog(parentComponent, message) : (int) getMockResponse(); + return isInteractiveMode() + ? JOptionPane.showConfirmDialog(parentComponent, message) + : (int) getMockResponse(); } /** @@ -96,12 +126,16 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) - throws HeadlessException { - if (!isInteractiveMode()) { + public static int showConfirmDialog(Component parentComponent, + Object message, String title, int optionType) + throws HeadlessException + { + if (!isInteractiveMode()) + { return (int) getMockResponse(); } - switch (optionType) { + switch (optionType) + { case JvOptionPane.YES_NO_CANCEL_OPTION: // FeatureRenderer amendFeatures ?? TODO ?? // Chimera close @@ -114,7 +148,8 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property // $FALL-THROUGH$ case JvOptionPane.OK_CANCEL_OPTION: // will fall back to simple HTML - return JOptionPane.showConfirmDialog(parentComponent, message, title, optionType); + return JOptionPane.showConfirmDialog(parentComponent, message, title, + optionType); } } @@ -129,12 +164,16 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, - int messageType) throws HeadlessException { + public static int showConfirmDialog(Component parentComponent, + Object message, String title, int optionType, int messageType) + throws HeadlessException + { // JalviewServicesChanged // PromptUserConfig raiseDialog - return isInteractiveMode() ? JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageType) - : (int) getMockResponse(); + return isInteractiveMode() + ? JOptionPane.showConfirmDialog(parentComponent, message, title, + optionType, messageType) + : (int) getMockResponse(); } /** @@ -149,12 +188,15 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, - int messageType, Icon icon) throws HeadlessException { + public static int showConfirmDialog(Component parentComponent, + Object message, String title, int optionType, int messageType, + Icon icon) throws HeadlessException + { // JvOptionPaneTest only return isInteractiveMode() - ? JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageType, icon) - : (int) getMockResponse(); + ? JOptionPane.showConfirmDialog(parentComponent, message, title, + optionType, messageType, icon) + : (int) getMockResponse(); } /** @@ -164,10 +206,14 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param message * @return */ - public static int showInternalConfirmDialog(Component parentComponent, Object message) { + public static int showInternalConfirmDialog(Component parentComponent, + Object message) + { // JvOptionPaneTest only; - return isInteractiveMode() ? JOptionPane.showInternalConfirmDialog(parentComponent, message) - : (int) getMockResponse(); + return isInteractiveMode() + ? JOptionPane.showInternalConfirmDialog(parentComponent, + message) + : (int) getMockResponse(); } /** @@ -179,11 +225,15 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param optionType * @return */ - public static int showInternalConfirmDialog(Component parentComponent, String message, String title, int optionType) { - if (!isInteractiveMode()) { + public static int showInternalConfirmDialog(Component parentComponent, + String message, String title, int optionType) + { + if (!isInteractiveMode()) + { return (int) getMockResponse(); } - switch (optionType) { + switch (optionType) + { case JvOptionPane.YES_NO_CANCEL_OPTION: // ColourMenuHelper.addMenuItmers.offerRemoval TODO case JvOptionPane.YES_NO_OPTION: @@ -196,7 +246,8 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property // Desktop.inputURLMenuItem // WsPreferenses - return JOptionPane.showConfirmDialog(parentComponent, message, title, optionType); + return JOptionPane.showConfirmDialog(parentComponent, message, title, + optionType); } } @@ -209,12 +260,15 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param messageType * @return */ - public static int showInternalConfirmDialog(Component parentComponent, Object message, String title, int optionType, - int messageType) { - if (!isInteractiveMode()) { + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, int optionType, int messageType) + { + if (!isInteractiveMode()) + { return (int) getMockResponse(); } - switch (optionType) { + switch (optionType) + { case JvOptionPane.YES_NO_CANCEL_OPTION: case JvOptionPane.YES_NO_OPTION: // UserQuestionanaireCheck @@ -223,7 +277,8 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property default: case JvOptionPane.OK_CANCEL_OPTION: // will fall back to simple HTML - return JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageType); + return JOptionPane.showConfirmDialog(parentComponent, message, title, + optionType, messageType); } } @@ -238,19 +293,24 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param icon * @return */ - public static int showInternalConfirmDialog(Component parentComponent, Object message, String title, int optionType, - int messageType, Icon icon) { - if (!isInteractiveMode()) { + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, int optionType, int messageType, + Icon icon) + { + if (!isInteractiveMode()) + { return (int) getMockResponse(); } - switch (optionType) { + switch (optionType) + { case JvOptionPane.YES_NO_CANCEL_OPTION: case JvOptionPane.YES_NO_OPTION: //$FALL-THROUGH$ default: case JvOptionPane.OK_CANCEL_OPTION: // Preferences editLink/newLink - return JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageType, icon); + return JOptionPane.showConfirmDialog(parentComponent, message, title, + optionType, messageType, icon); } } @@ -269,9 +329,13 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static int showOptionDialog(Component parentComponent, String message, String title, int optionType, - int messageType, Icon icon, Object[] options, Object initialValue) throws HeadlessException { - if (!isInteractiveMode()) { + public static int showOptionDialog(Component parentComponent, + String message, String title, int optionType, int messageType, + Icon icon, Object[] options, Object initialValue) + throws HeadlessException + { + if (!isInteractiveMode()) + { return (int) getMockResponse(); } // two uses: @@ -288,8 +352,8 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property // // 2) UserDefinedColors warning about saving over a name already defined // - return JOptionPane.showOptionDialog(parentComponent, message, title, optionType, messageType, icon, options, - initialValue); + return JOptionPane.showOptionDialog(parentComponent, message, title, + optionType, messageType, icon, options, initialValue); } /** @@ -298,8 +362,11 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param message * @throws HeadlessException */ - public static void showMessageDialog(Component parentComponent, String message) throws HeadlessException { - if (!isInteractiveMode()) { + public static void showMessageDialog(Component parentComponent, + String message) throws HeadlessException + { + if (!isInteractiveMode()) + { outputMessage(message); return; } @@ -318,16 +385,20 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param messageType * @throws HeadlessException */ - public static void showMessageDialog(Component parentComponent, String message, String title, int messageType) - throws HeadlessException { + public static void showMessageDialog(Component parentComponent, + String message, String title, int messageType) + throws HeadlessException + { // 30 implementations -- all just fine. - if (!isInteractiveMode()) { + if (!isInteractiveMode()) + { outputMessage(message); return; } - JOptionPane.showMessageDialog(parentComponent, getPrefix(messageType) + message, title, messageType); + JOptionPane.showMessageDialog(parentComponent, + getPrefix(messageType) + message, title, messageType); } /** @@ -340,28 +411,35 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param icon * @throws HeadlessException */ - public static void showMessageDialog(Component parentComponent, String message, String title, int messageType, - Icon icon) throws HeadlessException { + public static void showMessageDialog(Component parentComponent, + String message, String title, int messageType, Icon icon) + throws HeadlessException + { // test only - if (!isInteractiveMode()) { + if (!isInteractiveMode()) + { outputMessage(message); return; } - JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon); + JOptionPane.showMessageDialog(parentComponent, message, title, + messageType, icon); } /** * was internal * */ - public static void showInternalMessageDialog(Component parentComponent, Object message) { + public static void showInternalMessageDialog(Component parentComponent, + Object message) + { // WsPreferences only - if (!isInteractiveMode()) { + if (!isInteractiveMode()) + { outputMessage(message); return; } @@ -377,17 +455,20 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param title * @param messageType */ - public static void showInternalMessageDialog(Component parentComponent, String message, String title, - int messageType) { + public static void showInternalMessageDialog(Component parentComponent, + String message, String title, int messageType) + { // 41 references - if (!isInteractiveMode()) { + if (!isInteractiveMode()) + { outputMessage(message); return; } - JOptionPane.showMessageDialog(parentComponent, getPrefix(messageType) + message, title, messageType); + JOptionPane.showMessageDialog(parentComponent, + getPrefix(messageType) + message, title, messageType); } /** @@ -398,17 +479,20 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param messageType * @param icon */ - public static void showInternalMessageDialog(Component parentComponent, Object message, String title, int messageType, - Icon icon) { + public static void showInternalMessageDialog(Component parentComponent, + Object message, String title, int messageType, Icon icon) + { // test only - if (!isInteractiveMode()) { + if (!isInteractiveMode()) + { outputMessage(message); return; } - JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon); + JOptionPane.showMessageDialog(parentComponent, message, title, + messageType, icon); } /** @@ -417,10 +501,13 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static String showInputDialog(Object message) throws HeadlessException { + public static String showInputDialog(Object message) + throws HeadlessException + { // test only - if (!isInteractiveMode()) { + if (!isInteractiveMode()) + { return getMockResponse().toString(); } @@ -434,8 +521,11 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param initialSelectionValue * @return */ - public static String showInputDialog(String message, String initialSelectionValue) { - if (!isInteractiveMode()) { + public static String showInputDialog(String message, + String initialSelectionValue) + { + if (!isInteractiveMode()) + { return getMockResponse().toString(); } @@ -451,8 +541,11 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param initialSelectionValue * @return */ - public static String showInputDialog(Object message, Object initialSelectionValue) { - if (!isInteractiveMode()) { + public static String showInputDialog(Object message, + Object initialSelectionValue) + { + if (!isInteractiveMode()) + { return getMockResponse().toString(); } @@ -469,10 +562,14 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static String showInputDialog(Component parentComponent, String message) throws HeadlessException { + public static String showInputDialog(Component parentComponent, + String message) throws HeadlessException + { // test only - return isInteractiveMode() ? JOptionPane.showInputDialog(parentComponent, message) : getMockResponse().toString(); + return isInteractiveMode() + ? JOptionPane.showInputDialog(parentComponent, message) + : getMockResponse().toString(); } /** @@ -483,12 +580,16 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param initialSelectionValue * @return */ - public static String showInputDialog(Component parentComponent, String message, String initialSelectionValue) { + public static String showInputDialog(Component parentComponent, + String message, String initialSelectionValue) + { // AnnotationPanel - return isInteractiveMode() ? JOptionPane.showInputDialog(parentComponent, message, initialSelectionValue) - : getMockResponse().toString(); + return isInteractiveMode() + ? JOptionPane.showInputDialog(parentComponent, message, + initialSelectionValue) + : getMockResponse().toString(); } /** @@ -499,12 +600,16 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param initialSelectionValue * @return */ - public static String showInputDialog(Component parentComponent, Object message, Object initialSelectionValue) { + public static String showInputDialog(Component parentComponent, + Object message, Object initialSelectionValue) + { // AnnotationPanel - return isInteractiveMode() ? JOptionPane.showInputDialog(parentComponent, message, initialSelectionValue) - : getMockResponse().toString(); + return isInteractiveMode() + ? JOptionPane.showInputDialog(parentComponent, message, + initialSelectionValue) + : getMockResponse().toString(); } /** @@ -516,13 +621,17 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static String showInputDialog(Component parentComponent, String message, String title, int messageType) - throws HeadlessException { + public static String showInputDialog(Component parentComponent, + String message, String title, int messageType) + throws HeadlessException + { // test only - return isInteractiveMode() ? JOptionPane.showInputDialog(parentComponent, message, title, messageType) - : getMockResponse().toString(); + return isInteractiveMode() + ? JOptionPane.showInputDialog(parentComponent, message, title, + messageType) + : getMockResponse().toString(); } /** @@ -538,15 +647,19 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @return * @throws HeadlessException */ - public static Object showInputDialog(Component parentComponent, Object message, String title, int messageType, - Icon icon, Object[] selectionValues, Object initialSelectionValue) throws HeadlessException { + public static Object showInputDialog(Component parentComponent, + Object message, String title, int messageType, Icon icon, + Object[] selectionValues, Object initialSelectionValue) + throws HeadlessException + { // test only return isInteractiveMode() - ? JOptionPane.showInputDialog(parentComponent, message, title, messageType, icon, selectionValues, - initialSelectionValue) - : getMockResponse().toString(); + ? JOptionPane.showInputDialog(parentComponent, message, title, + messageType, icon, selectionValues, + initialSelectionValue) + : getMockResponse().toString(); } /** @@ -556,11 +669,14 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param message * @return */ - public static String showInternalInputDialog(Component parentComponent, String message) { + public static String showInternalInputDialog(Component parentComponent, + String message) + { // test only - return isInteractiveMode() ? JOptionPane.showInternalInputDialog(parentComponent, message) - : getMockResponse().toString(); + return isInteractiveMode() + ? JOptionPane.showInternalInputDialog(parentComponent, message) + : getMockResponse().toString(); } /** @@ -572,14 +688,16 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param messageType * @return */ - public static String showInternalInputDialog(Component parentComponent, String message, String title, - int messageType) { + public static String showInternalInputDialog(Component parentComponent, + String message, String title, int messageType) + { // AlignFrame tabbedPane_mousePressed return isInteractiveMode() - ? JOptionPane.showInternalInputDialog(parentComponent, getPrefix(messageType) + message, title, messageType) - : getMockResponse().toString(); + ? JOptionPane.showInternalInputDialog(parentComponent, + getPrefix(messageType) + message, title, messageType) + : getMockResponse().toString(); } /** @@ -594,47 +712,62 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param initialSelectionValue * @return */ - public static Object showInternalInputDialog(Component parentComponent, String message, String title, int messageType, - Icon icon, Object[] selectionValues, Object initialSelectionValue) { + public static Object showInternalInputDialog(Component parentComponent, + String message, String title, int messageType, Icon icon, + Object[] selectionValues, Object initialSelectionValue) + { // test only - return isInteractiveMode() ? JOptionPane.showInternalInputDialog(parentComponent, message, title, messageType, icon, - selectionValues, initialSelectionValue) : getMockResponse().toString(); + return isInteractiveMode() + ? JOptionPane.showInternalInputDialog(parentComponent, message, + title, messageType, icon, selectionValues, + initialSelectionValue) + : getMockResponse().toString(); } ///////////// end of options /////////////// - private static void outputMessage(Object message) { - System.out.println(">>> JOption Message : " + message.toString()); + private static void outputMessage(Object message) + { + jalview.bin.Console + .outPrintln(">>> JOption Message : " + message.toString()); } - public static Object getMockResponse() { + public static Object getMockResponse() + { return mockResponse; } - public static void setMockResponse(Object mockOption) { + public static void setMockResponse(Object mockOption) + { JvOptionPane.mockResponse = mockOption; } - public static void resetMock() { + public static void resetMock() + { setMockResponse(JvOptionPane.CANCEL_OPTION); setInteractiveMode(true); } - public static boolean isInteractiveMode() { + public static boolean isInteractiveMode() + { return interactiveMode; } - public static void setInteractiveMode(boolean interactive) { + public static void setInteractiveMode(boolean interactive) + { JvOptionPane.interactiveMode = interactive; } - private static String getPrefix(int messageType) { + private static String getPrefix(int messageType) + { String prefix = ""; // JavaScript only - if (Platform.isJS()) { - switch (messageType) { + if (Platform.isJS()) + { + switch (messageType) + { case JvOptionPane.WARNING_MESSAGE: prefix = "WARNING! "; break; @@ -662,28 +795,39 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * @param string2 * @return */ - public static JvOptionPane newOptionDialog() { + public static JvOptionPane newOptionDialog() + { return new JvOptionPane(null); } - public static JvOptionPane newOptionDialog(Component parentComponent) { + public static JvOptionPane newOptionDialog(Component parentComponent) + { return new JvOptionPane(parentComponent); } - public void showDialog(String message, String title, int optionType, int messageType, Icon icon, Object[] options, - Object initialValue) { - showDialog(message, title, optionType, messageType, icon, options, initialValue, true); + public void showDialog(String message, String title, int optionType, + int messageType, Icon icon, Object[] options, Object initialValue) + { + showDialog(message, title, optionType, messageType, icon, options, + initialValue, true); } - public void showDialog(Object message, String title, int optionType, int messageType, Icon icon, Object[] options, - Object initialValue, boolean modal) { - showDialog(message, title, optionType, messageType, icon, options, initialValue, modal, null); + public void showDialog(Object message, String title, int optionType, + int messageType, Icon icon, Object[] options, Object initialValue, + boolean modal) + { + showDialog(message, title, optionType, messageType, icon, options, + initialValue, modal, null); } - public void showDialog(Object message, String title, int optionType, int messageType, Icon icon, Object[] options, - Object initialValue, boolean modal, JButton[] buttons) { - if (!isInteractiveMode()) { + public void showDialog(Object message, String title, int optionType, + int messageType, Icon icon, Object[] options, Object initialValue, + boolean modal, JButton[] buttons) + { + if (!isInteractiveMode()) + { handleResponse(getMockResponse()); + return; } // two uses: // @@ -702,44 +846,94 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property ourOptions = Arrays.asList(options); - if (modal) { + if (modal) + { boolean useButtons = false; Object initialValueButton = null; - NOTNULL: if (buttons != null) { - if (buttons.length != options.length) { - jalview.bin.Console.error("Supplied buttons array not the same length as supplied options array."); + NOTNULL: if (buttons != null) + { + if (buttons.length != options.length) + { + jalview.bin.Console.error( + "Supplied buttons array not the same length as supplied options array."); break NOTNULL; } - int[] buttonActions = { JOptionPane.YES_OPTION, JOptionPane.NO_OPTION, JOptionPane.CANCEL_OPTION }; - for (int i = 0; i < options.length; i++) { + + // run through buttons for initialValue first so can set a final + // timeoutThreadF + Thread timeoutThread = null; + for (int i = 0; i < options.length; i++) + { Object o = options[i]; - jalview.bin.Console.debug("Setting button " + i + " to '" + o.toString() + "'"); JButton jb = buttons[i]; - if (o.equals(initialValue)) + { initialValueButton = jb; + if (timeout > 0 && initialValueButton != null + && initialValueButton instanceof JButton) + { + Runnable timeoutClose = () -> { + try + { + Thread.sleep(timeout); + } catch (InterruptedException e) + { + Console.debug( + "Dialog timeout interrupted. Probably a button pressed."); + } + jb.doClick(); + }; + timeoutThread = new Thread(timeoutClose); + } + } + } + final Thread timeoutThreadF = timeoutThread; + timeoutThreadF.start(); + + int[] buttonActions = { JOptionPane.YES_OPTION, + JOptionPane.NO_OPTION, JOptionPane.CANCEL_OPTION }; + for (int i = 0; i < options.length; i++) + { + Object o = options[i]; + jalview.bin.Console.debug( + "Setting button " + i + " to '" + o.toString() + "'"); + JButton jb = buttons[i]; int buttonAction = buttonActions[i]; - Callable action = callbacks.get(buttonAction); + Runnable action = callbacks.get(buttonAction); jb.setText((String) o); - jb.addActionListener(new ActionListener() { + jb.addActionListener(new ActionListener() + { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(ActionEvent e) + { + if (timeoutThreadF != null) + { + timeoutThreadF.interrupt(); + } Object obj = e.getSource(); - if (obj == null || !(obj instanceof Component)) { - jalview.bin.Console.debug("Could not find Component source of event object " + obj); + if (obj == null || !(obj instanceof Component)) + { + jalview.bin.Console.debug( + "Could not find Component source of event object " + + obj); return; } - Object joptionpaneObject = SwingUtilities.getAncestorOfClass(JOptionPane.class, (Component) obj); - if (joptionpaneObject == null || !(joptionpaneObject instanceof JOptionPane)) { - jalview.bin.Console.debug("Could not find JOptionPane ancestor of event object " + obj); + Object joptionpaneObject = SwingUtilities.getAncestorOfClass( + JOptionPane.class, (Component) obj); + if (joptionpaneObject == null + || !(joptionpaneObject instanceof JOptionPane)) + { + jalview.bin.Console.debug( + "Could not find JOptionPane ancestor of event object " + + obj); return; } JOptionPane joptionpane = (JOptionPane) joptionpaneObject; joptionpane.setValue(buttonAction); if (action != null) - Executors.newSingleThreadExecutor().submit(action); + new Thread(action).start(); joptionpane.transferFocusBackward(); joptionpane.setVisible(false); // put focus and raise parent window if possible, unless cancel or @@ -747,16 +941,21 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property boolean raiseParent = (parentComponent != null); if (buttonAction == JOptionPane.CANCEL_OPTION) raiseParent = false; - if (optionType == JOptionPane.YES_NO_OPTION && buttonAction == JOptionPane.NO_OPTION) + if (optionType == JOptionPane.YES_NO_OPTION + && buttonAction == JOptionPane.NO_OPTION) raiseParent = false; - if (raiseParent) { + if (raiseParent) + { parentComponent.requestFocus(); - if (parentComponent instanceof JInternalFrame) { + if (parentComponent instanceof JInternalFrame) + { JInternalFrame jif = (JInternalFrame) parentComponent; jif.show(); jif.moveToFront(); jif.grabFocus(); - } else if (parentComponent instanceof Window) { + } + else if (parentComponent instanceof Window) + { Window w = (Window) parentComponent; w.toFront(); w.requestFocus(); @@ -770,8 +969,10 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property useButtons = true; } // use a JOptionPane as usual - int response = JOptionPane.showOptionDialog(parentComponent, message, title, optionType, messageType, icon, - useButtons ? buttons : options, useButtons ? initialValueButton : initialValue); + int response = JOptionPane.showOptionDialog(parentComponent, message, + title, optionType, messageType, icon, + useButtons ? buttons : options, + useButtons ? initialValueButton : initialValue); /* * In Java, the response is returned to this thread and handled here; (for @@ -786,7 +987,9 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property { handleResponse(response); } - } else { + } + else + { /* * This is java similar to the swingjs handling, with the callbacks attached to * the button press of the dialog. This means we can use a non-modal JDialog for @@ -794,37 +997,50 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property */ JOptionPane joptionpane = new JOptionPane(); // Make button options - int[] buttonActions = { JvOptionPane.YES_OPTION, JvOptionPane.NO_OPTION, JvOptionPane.CANCEL_OPTION }; + int[] buttonActions = { JvOptionPane.YES_OPTION, + JvOptionPane.NO_OPTION, JvOptionPane.CANCEL_OPTION }; // we need the strings to make the buttons with actionEventListener - if (options == null) { + if (options == null) + { ArrayList options_default = new ArrayList<>(); - options_default.add(UIManager.getString("OptionPane.yesButtonText")); - if (optionType == JvOptionPane.YES_NO_OPTION || optionType == JvOptionPane.YES_NO_CANCEL_OPTION) { - options_default.add(UIManager.getString("OptionPane.noButtonText")); + options_default + .add(UIManager.getString("OptionPane.yesButtonText")); + if (optionType == JvOptionPane.YES_NO_OPTION + || optionType == JvOptionPane.YES_NO_CANCEL_OPTION) + { + options_default + .add(UIManager.getString("OptionPane.noButtonText")); } - if (optionType == JvOptionPane.YES_NO_CANCEL_OPTION) { - options_default.add(UIManager.getString("OptionPane.cancelButtonText")); + if (optionType == JvOptionPane.YES_NO_CANCEL_OPTION) + { + options_default + .add(UIManager.getString("OptionPane.cancelButtonText")); } options = options_default.toArray(); } ArrayList options_btns = new ArrayList<>(); Object initialValue_btn = null; - if (!Platform.isJS()) // JalviewJS already uses callback, don't need to add them here + if (!Platform.isJS()) // JalviewJS already uses callback, don't need to + // add them here { - for (int i = 0; i < options.length && i < 3; i++) { + for (int i = 0; i < options.length && i < 3; i++) + { Object o = options[i]; int buttonAction = buttonActions[i]; - Callable action = callbacks.get(buttonAction); + Runnable action = callbacks.get(buttonAction); JButton jb = new JButton(); jb.setText((String) o); - jb.addActionListener(new ActionListener() { + jb.addActionListener(new ActionListener() + { + @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(ActionEvent e) + { joptionpane.setValue(buttonAction); if (action != null) - Executors.newSingleThreadExecutor().submit(action); + new Thread(action).start(); // joptionpane.transferFocusBackward(); joptionpane.transferFocusBackward(); joptionpane.setVisible(false); @@ -833,16 +1049,21 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property boolean raiseParent = (parentComponent != null); if (buttonAction == JvOptionPane.CANCEL_OPTION) raiseParent = false; - if (optionType == JvOptionPane.YES_NO_OPTION && buttonAction == JvOptionPane.NO_OPTION) + if (optionType == JvOptionPane.YES_NO_OPTION + && buttonAction == JvOptionPane.NO_OPTION) raiseParent = false; - if (raiseParent) { + if (raiseParent) + { parentComponent.requestFocus(); - if (parentComponent instanceof JInternalFrame) { + if (parentComponent instanceof JInternalFrame) + { JInternalFrame jif = (JInternalFrame) parentComponent; jif.show(); jif.moveToFront(); jif.grabFocus(); - } else if (parentComponent instanceof Window) { + } + else if (parentComponent instanceof Window) + { Window w = (Window) parentComponent; w.toFront(); w.requestFocus(); @@ -860,20 +1081,27 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property joptionpane.setMessageType(messageType); joptionpane.setOptionType(optionType); joptionpane.setIcon(icon); - joptionpane.setOptions(Platform.isJS() ? options : options_btns.toArray()); - joptionpane.setInitialValue(Platform.isJS() ? initialValue : initialValue_btn); + joptionpane.setOptions( + Platform.isJS() ? options : options_btns.toArray()); + joptionpane.setInitialValue( + Platform.isJS() ? initialValue : initialValue_btn); JDialog dialog = joptionpane.createDialog(parentComponent, title); - dialog.setIconImage(WindowIcons.logoIcon.getImage()); - dialog.setModalityType(modal ? ModalityType.APPLICATION_MODAL : ModalityType.MODELESS); + dialog.setIconImages(ChannelProperties.getIconList()); + dialog.setModalityType(modal ? ModalityType.APPLICATION_MODAL + : ModalityType.MODELESS); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setVisible(true); + setDialog(dialog); } } - public void showInternalDialog(JPanel mainPanel, String title, int yesNoCancelOption, int questionMessage, Icon icon, - Object[] options, String initresponse) { - if (!isInteractiveMode()) { + public void showInternalDialog(Object mainPanel, String title, + int yesNoCancelOption, int questionMessage, Icon icon, + Object[] options, String initresponse) + { + if (!isInteractiveMode()) + { handleResponse(getMockResponse()); } @@ -886,54 +1114,81 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property this.setMessage(mainPanel); ourOptions = Arrays.asList(options); - int response; - if (parentComponent != this) { - JInternalFrame jif = this.createInternalFrame(parentComponent, title); - jif.setFrameIcon(WindowIcons.logoIcon); - jif.addInternalFrameListener(new InternalFrameListener() { + if (parentComponent != this + && !(parentComponent == null && Desktop.instance == null)) + { + // note the parent goes back to a JRootPane so is probably + // Desktop.getDesktop() + JInternalFrame jif = this.createInternalFrame( + parentComponent != null ? parentComponent : Desktop.instance, + title); + // connect to the alignFrame using a map in Desktop + if (parentComponent instanceof AlignFrame) + { + Desktop.addModal((AlignFrame) parentComponent, jif); + } + jif.setFrameIcon(null); + jif.addInternalFrameListener(new InternalFrameListener() + { @Override - public void internalFrameActivated(InternalFrameEvent arg0) { + public void internalFrameActivated(InternalFrameEvent arg0) + { } @Override - public void internalFrameClosed(InternalFrameEvent arg0) { + public void internalFrameClosed(InternalFrameEvent arg0) + { JvOptionPane.this.internalDialogHandleResponse(); } @Override - public void internalFrameClosing(InternalFrameEvent arg0) { + public void internalFrameClosing(InternalFrameEvent arg0) + { } @Override - public void internalFrameDeactivated(InternalFrameEvent arg0) { + public void internalFrameDeactivated(InternalFrameEvent arg0) + { } @Override - public void internalFrameDeiconified(InternalFrameEvent arg0) { + public void internalFrameDeiconified(InternalFrameEvent arg0) + { } @Override - public void internalFrameIconified(InternalFrameEvent arg0) { + public void internalFrameIconified(InternalFrameEvent arg0) + { } @Override - public void internalFrameOpened(InternalFrameEvent arg0) { + public void internalFrameOpened(InternalFrameEvent arg0) + { } }); jif.setVisible(true); startModal(jif); return; - } else { + } + else + { JDialog dialog = this.createDialog(parentComponent, title); - dialog.setIconImage(WindowIcons.logoIcon.getImage()); + dialog.setIconImages(ChannelProperties.getIconList()); dialog.setVisible(true); // blocking this.internalDialogHandleResponse(); return; } } - private void internalDialogHandleResponse() { - String responseString = (String) this.getValue(); + private void internalDialogHandleResponse() + { + Object value = this.getValue(); + if (value == null + || (value instanceof Integer && (Integer) value == -1)) + { + return; + } + String responseString = value.toString(); int response = ourOptions.indexOf(responseString); if (!Platform.isJS()) @@ -955,17 +1210,45 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * } */ @Override - public JvOptionPane setResponseHandler(Object response, Callable action) { + public JvOptionPane setResponseHandler(Object response, Runnable action) + { + if (action == null) + { + action = NULLCALLABLE; + } callbacks.put(response, action); return this; } + public void setDialog(JDialog d) + { + dialog = d; + } + + public JDialog getDialog() + { + return dialog; + } + /** * showDialogOnTop will create a dialog that (attempts to) come to top of OS * desktop windows */ - public static int showDialogOnTop(String label, String actionString, int JOPTIONPANE_OPTION, - int JOPTIONPANE_MESSAGETYPE) { + public static int showDialogOnTop(String label, String actionString, + int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE) + { + return showDialogOnTop(null, label, actionString, JOPTIONPANE_OPTION, + JOPTIONPANE_MESSAGETYPE); + } + + public static int showDialogOnTop(Component dialogParentComponent, + String label, String actionString, int JOPTIONPANE_OPTION, + int JOPTIONPANE_MESSAGETYPE) + { + if (!isInteractiveMode()) + { + return (int) getMockResponse(); + } // Ensure Jalview window is brought to front (primarily for Quit // confirmation window to be visible) @@ -976,34 +1259,68 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property // A better hack which works is to create a new JFrame parent with // setAlwaysOnTop(true) JFrame dialogParent = new JFrame(); - dialogParent.setIconImage(WindowIcons.logoIcon.getImage()); - dialogParent.setAlwaysOnTop(true); + if (dialogParentComponent == null) + { + dialogParent.setIconImages(ChannelProperties.getIconList()); + dialogParent.setAlwaysOnTop(true); + } - int answer = JOptionPane.showConfirmDialog(dialogParent, label, actionString, JOPTIONPANE_OPTION, - JOPTIONPANE_MESSAGETYPE); + int answer = JOptionPane.showConfirmDialog( + dialogParentComponent == null ? dialogParent + : dialogParentComponent, + label, actionString, JOPTIONPANE_OPTION, + JOPTIONPANE_MESSAGETYPE); - dialogParent.setAlwaysOnTop(false); - dialogParent.dispose(); + if (dialogParentComponent == null) + { + dialogParent.setAlwaysOnTop(false); + dialogParent.dispose(); + } return answer; } - public void showDialogOnTopAsync(String label, String actionString, int JOPTIONPANE_OPTION, - int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options, Object initialValue, boolean modal) { + public void showDialogOnTopAsync(String label, String actionString, + int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE, Icon icon, + Object[] options, Object initialValue, boolean modal) + { JFrame frame = new JFrame(); - frame.setIconImage(WindowIcons.logoIcon.getImage()); - showDialogOnTopAsync(frame, label, actionString, JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options, - initialValue, modal); + frame.setIconImages(ChannelProperties.getIconList()); + showDialogOnTopAsync(frame, label, actionString, JOPTIONPANE_OPTION, + JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal); } - public void showDialogOnTopAsync(JFrame dialogParent, Object label, String actionString, int JOPTIONPANE_OPTION, - int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options, Object initialValue, boolean modal) { - showDialogOnTopAsync(dialogParent, label, actionString, JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options, - initialValue, modal, null); + public void showDialogOnTopAsync(JFrame dialogParent, Object label, + String actionString, int JOPTIONPANE_OPTION, + int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options, + Object initialValue, boolean modal) + { + showDialogOnTopAsync(dialogParent, label, actionString, + JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options, + initialValue, modal, null); } - public void showDialogOnTopAsync(JFrame dialogParent, Object label, String actionString, int JOPTIONPANE_OPTION, - int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options, Object initialValue, boolean modal, JButton[] buttons) { + public void showDialogOnTopAsync(JFrame dialogParent, Object label, + String actionString, int JOPTIONPANE_OPTION, + int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options, + Object initialValue, boolean modal, JButton[] buttons) + { + showDialogOnTopAsync(dialogParent, label, actionString, + JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options, + initialValue, modal, buttons, true); + } + + public void showDialogOnTopAsync(JFrame dialogParent, Object label, + String actionString, int JOPTIONPANE_OPTION, + int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options, + Object initialValue, boolean modal, JButton[] buttons, + boolean dispose) + { + if (!isInteractiveMode()) + { + handleResponse(getMockResponse()); + return; + } // Ensure Jalview window is brought to front (primarily for Quit // confirmation window to be visible) @@ -1016,45 +1333,59 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property dialogParent.setAlwaysOnTop(true); parentComponent = dialogParent; - showDialog(label, actionString, JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal, - buttons); + showDialog(label, actionString, JOPTIONPANE_OPTION, + JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal, + buttons); - dialogParent.setAlwaysOnTop(false); - dialogParent.dispose(); + if (dispose) + { + dialogParent.setAlwaysOnTop(false); + dialogParent.dispose(); + } } /** - * JalviewJS signals option selection by a property change event for the option - * e.g. "OK". This methods responds to that by running the response action that - * corresponds to that option. + * JalviewJS signals option selection by a property change event for the + * option e.g. "OK". This methods responds to that by running the response + * action that corresponds to that option. * * @param evt */ @Override - public void propertyChange(PropertyChangeEvent evt) { + public void propertyChange(PropertyChangeEvent evt) + { Object newValue = evt.getNewValue(); int ourOption = ourOptions.indexOf(newValue); - if (ourOption >= 0) { + if (ourOption >= 0) + { handleResponse(ourOption); - } else { + } + else + { // try our luck.. handleResponse(newValue); } } @Override - public void handleResponse(Object response) { + public void handleResponse(Object response) + { /* * this test is for NaN in Chrome */ - if (response != null && !response.equals(response)) { + if (response != null && !response.equals(response)) + { return; } - Callable action = callbacks.get(response); - if (action != null) { - try { - action.call(); - } catch (Exception e) { + Runnable action = callbacks.get(response); + if (action != null) + { + try + { + new Thread(action).start(); + // action.call(); + } catch (Exception e) + { e.printStackTrace(); } if (parentComponent != null) @@ -1065,61 +1396,90 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property /** * Create a non-modal confirm dialog */ - public JDialog createDialog(Component parentComponent, Object message, String title, int optionType, int messageType, - Icon icon, Object[] options, Object initialValue, boolean modal) { - return createDialog(parentComponent, message, title, optionType, messageType, icon, options, initialValue, modal, - null); + public JDialog createDialog(Component parentComponent, Object message, + String title, int optionType, int messageType, Icon icon, + Object[] options, Object initialValue, boolean modal) + { + return createDialog(parentComponent, message, title, optionType, + messageType, icon, options, initialValue, modal, null); } - public JDialog createDialog(Component parentComponent, Object message, String title, int optionType, int messageType, - Icon icon, Object[] options, Object initialValue, boolean modal, JButton[] buttons) { + public JDialog createDialog(Component parentComponent, Object message, + String title, int optionType, int messageType, Icon icon, + Object[] options, Object initialValue, boolean modal, + JButton[] buttons) + { + if (!isInteractiveMode()) + { + handleResponse(getMockResponse()); + return null; + } JButton[] optionsButtons = null; Object initialValueButton = null; JOptionPane joptionpane = new JOptionPane(); // Make button options - int[] buttonActions = { JOptionPane.YES_OPTION, JOptionPane.NO_OPTION, JOptionPane.CANCEL_OPTION }; + int[] buttonActions = { JOptionPane.YES_OPTION, JOptionPane.NO_OPTION, + JOptionPane.CANCEL_OPTION }; // we need the strings to make the buttons with actionEventListener - if (options == null) { + if (options == null) + { ArrayList options_default = new ArrayList<>(); options_default.add(UIManager.getString("OptionPane.yesButtonText")); - if (optionType == JOptionPane.YES_NO_OPTION || optionType == JOptionPane.YES_NO_CANCEL_OPTION) { + if (optionType == JOptionPane.YES_NO_OPTION + || optionType == JOptionPane.YES_NO_CANCEL_OPTION) + { options_default.add(UIManager.getString("OptionPane.noButtonText")); } - if (optionType == JOptionPane.YES_NO_CANCEL_OPTION) { - options_default.add(UIManager.getString("OptionPane.cancelButtonText")); + if (optionType == JOptionPane.YES_NO_CANCEL_OPTION) + { + options_default + .add(UIManager.getString("OptionPane.cancelButtonText")); } options = options_default.toArray(); } if (!Platform.isJS()) // JalviewJS already uses callback, don't need to // add them here { - if (((optionType == JOptionPane.YES_OPTION || optionType == JOptionPane.NO_OPTION - || optionType == JOptionPane.CANCEL_OPTION || optionType == JOptionPane.OK_OPTION - || optionType == JOptionPane.DEFAULT_OPTION) && options.length < 1) - || ((optionType == JOptionPane.YES_NO_OPTION || optionType == JOptionPane.OK_CANCEL_OPTION) - && options.length < 2) - || (optionType == JOptionPane.YES_NO_CANCEL_OPTION && options.length < 3)) { - jalview.bin.Console.debug("JvOptionPane: not enough options for dialog type"); + if (((optionType == JOptionPane.YES_OPTION + || optionType == JOptionPane.NO_OPTION + || optionType == JOptionPane.CANCEL_OPTION + || optionType == JOptionPane.OK_OPTION + || optionType == JOptionPane.DEFAULT_OPTION) + && options.length < 1) + || ((optionType == JOptionPane.YES_NO_OPTION + || optionType == JOptionPane.OK_CANCEL_OPTION) + && options.length < 2) + || (optionType == JOptionPane.YES_NO_CANCEL_OPTION + && options.length < 3)) + { + jalview.bin.Console + .debug("JvOptionPane: not enough options for dialog type"); } optionsButtons = new JButton[options.length]; - for (int i = 0; i < options.length && i < 3; i++) { + for (int i = 0; i < options.length && i < 3; i++) + { Object o = options[i]; int buttonAction = buttonActions[i]; - Callable action = callbacks.get(buttonAction); + Runnable action = callbacks.get(buttonAction); JButton jb; - if (buttons != null && buttons.length > i && buttons[i] != null) { + if (buttons != null && buttons.length > i && buttons[i] != null) + { jb = buttons[i]; - } else { + } + else + { jb = new JButton(); } jb.setText((String) o); - jb.addActionListener(new ActionListener() { + jb.addActionListener(new ActionListener() + { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(ActionEvent e) + { joptionpane.setValue(buttonAction); if (action != null) - Executors.newSingleThreadExecutor().submit(action); + new Thread(action).start(); // joptionpane.transferFocusBackward(); joptionpane.transferFocusBackward(); joptionpane.setVisible(false); @@ -1128,16 +1488,21 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property boolean raiseParent = (parentComponent != null); if (buttonAction == JOptionPane.CANCEL_OPTION) raiseParent = false; - if (optionType == JOptionPane.YES_NO_OPTION && buttonAction == JOptionPane.NO_OPTION) + if (optionType == JOptionPane.YES_NO_OPTION + && buttonAction == JOptionPane.NO_OPTION) raiseParent = false; - if (raiseParent) { + if (raiseParent) + { parentComponent.requestFocus(); - if (parentComponent instanceof JInternalFrame) { + if (parentComponent instanceof JInternalFrame) + { JInternalFrame jif = (JInternalFrame) parentComponent; jif.show(); jif.moveToFront(); jif.grabFocus(); - } else if (parentComponent instanceof Window) { + } + else if (parentComponent instanceof Window) + { Window w = (Window) parentComponent; w.toFront(); w.requestFocus(); @@ -1156,12 +1521,15 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property joptionpane.setOptionType(optionType); joptionpane.setIcon(icon); joptionpane.setOptions(Platform.isJS() ? options : optionsButtons); - joptionpane.setInitialValue(Platform.isJS() ? initialValue : initialValueButton); + joptionpane.setInitialValue( + Platform.isJS() ? initialValue : initialValueButton); JDialog dialog = joptionpane.createDialog(parentComponent, title); - dialog.setIconImage(WindowIcons.logoIcon.getImage()); - dialog.setModalityType(modal ? ModalityType.APPLICATION_MODAL : ModalityType.MODELESS); + dialog.setIconImages(ChannelProperties.getIconList()); + dialog.setModalityType( + modal ? ModalityType.APPLICATION_MODAL : ModalityType.MODELESS); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setDialog(dialog); return dialog; } @@ -1170,7 +1538,8 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * * returns true if button was found */ - public static boolean clickButton(JFrame frame, int buttonType) { + public static boolean clickButton(JFrame frame, int buttonType) + { return false; } @@ -1181,9 +1550,11 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property * the JInternalFrame and sizes it according to the JInternalFrame's preferred * size. * - * @param f The JInternalFrame to make modal. + * @param f + * The JInternalFrame to make modal. */ - private static void startModal(JInternalFrame f) { + private static void startModal(JInternalFrame f) + { // We need to add an additional glasspane-like component directly // below the frame, which intercepts all mouse events that are not // directed at the frame itself. @@ -1192,19 +1563,39 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property JLayeredPane lp = JLayeredPane.getLayeredPaneAbove(f); lp.setLayer(modalInterceptor, JLayeredPane.MODAL_LAYER.intValue()); modalInterceptor.setBounds(0, 0, lp.getWidth(), lp.getHeight()); - modalInterceptor.addMouseListener(new MouseAdapter() { + modalInterceptor.addMouseListener(new MouseAdapter() + { }); - modalInterceptor.addMouseMotionListener(new MouseMotionAdapter() { + modalInterceptor.addMouseMotionListener(new MouseMotionAdapter() + { }); lp.add(modalInterceptor); f.toFront(); + // disable the main menu bar if in Linux + JMenuBar menubar = null; + if (Platform.isLinux()) + { + JRootPane rootpane = Desktop.getDesktop().getRootPane(); + menubar = rootpane.getJMenuBar(); + } + // We need to explicitly dispatch events when we are blocking the event // dispatch thread. EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue(); - try { - while (!f.isClosed()) { - if (EventQueue.isDispatchThread()) { + try + { + if (menubar != null) + { + // don't allow clicks on main menu on linux due to a hanging bug. + // see JAL-4214. + setMenusEnabled(menubar, false); + } + + while (!f.isClosed()) + { + if (EventQueue.isDispatchThread()) + { // The getNextEventMethod() issues wait() when no // event is available, so we don't need do explicitly wait(). AWTEvent ev = queue.getNextEvent(); @@ -1212,29 +1603,145 @@ public class JvOptionPane extends JOptionPane implements DialogRunnerI, Property // EventQueue.dispatchEvent() directly, because it is // protected, unfortunately. if (ev instanceof ActiveEvent) + { ((ActiveEvent) ev).dispatch(); - else if (ev.getSource() instanceof Component) + } + else if (ev instanceof KeyEvent && ((KeyEvent) ev).isControlDown() + && menubar != null) + { + // temporarily enable menus to send Ctrl+? KeyEvents + setMenusEnabled(menubar, true); ((Component) ev.getSource()).dispatchEvent(ev); + setMenusEnabled(menubar, false); + } else if (ev.getSource() instanceof MenuComponent) + { ((MenuComponent) ev.getSource()).dispatchEvent(ev); + } + else if (ev.getSource() instanceof Component) + { + ((Component) ev.getSource()).dispatchEvent(ev); + } // Other events are ignored as per spec in // EventQueue.dispatchEvent - } else { + } + else + { // Give other threads a chance to become active. Thread.yield(); } } - } catch (InterruptedException ex) { + } catch (InterruptedException ex) + { // If we get interrupted, then leave the modal state. - } finally { + } finally + { + // re-enable the main menu bar + if (menubar != null) + { + setMenusEnabled(menubar, true); + } + // Clean up the modal interceptor. lp.remove(modalInterceptor); + // unpaint the frame + f.setVisible(false); + + // close the frame + try + { + f.setClosed(true); + } catch (PropertyVetoException e) + { + f.doDefaultCloseAction(); + } + // Remove the internal frame from its parent, so it is no longer // lurking around and clogging memory. Container parent = f.getParent(); if (parent != null) + { parent.remove(f); + } + } + } + + public static JvOptionPane frameDialog(Object message, String title, + int messageType, String[] buttonsTextS, String defaultButtonS, + List handlers, boolean modal) + { + JFrame parent = new JFrame(); + JvOptionPane jvop = JvOptionPane.newOptionDialog(); + final String[] buttonsText; + final String defaultButton; + if (buttonsTextS == null) + { + String ok = MessageManager.getString("action.ok"); + buttonsText = new String[] { ok }; + defaultButton = ok; + } + else + { + buttonsText = buttonsTextS; + defaultButton = defaultButtonS; } + JButton[] buttons = new JButton[buttonsText.length]; + for (int i = 0; i < buttonsText.length; i++) + { + buttons[i] = new JButton(); + buttons[i].setText(buttonsText[i]); + Console.debug("DISABLING BUTTON " + buttons[i].getText()); + buttons[i].setEnabled(false); + buttons[i].setVisible(false); + } + + int dialogType = -1; + if (buttonsText.length == 1) + { + dialogType = JOptionPane.OK_OPTION; + } + else if (buttonsText.length == 2) + { + dialogType = JOptionPane.YES_NO_OPTION; + } + else + { + dialogType = JOptionPane.YES_NO_CANCEL_OPTION; + } + jvop.setResponseHandler(JOptionPane.YES_OPTION, + (handlers != null && handlers.size() > 0) ? handlers.get(0) + : NULLCALLABLE); + if (dialogType == JOptionPane.YES_NO_OPTION + || dialogType == JOptionPane.YES_NO_CANCEL_OPTION) + { + jvop.setResponseHandler(JOptionPane.NO_OPTION, + (handlers != null && handlers.size() > 1) ? handlers.get(1) + : NULLCALLABLE); + } + if (dialogType == JOptionPane.YES_NO_CANCEL_OPTION) + { + jvop.setResponseHandler(JOptionPane.CANCEL_OPTION, + (handlers != null && handlers.size() > 2) ? handlers.get(2) + : NULLCALLABLE); + } + + final int dt = dialogType; + new Thread(() -> { + jvop.showDialog(message, title, dt, messageType, null, buttonsText, + defaultButton, modal, buttons); + }).start(); + + return jvop; } + + private static void setMenusEnabled(JMenuBar menubar, boolean b) + { + for (int i = 0; i < menubar.getMenuCount(); i++) + { + JMenu menu = menubar.getMenu(i); + menu.setEnabled(b); + } + } + }