+ 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.
+ JPanel modalInterceptor = new JPanel();
+ modalInterceptor.setOpaque(false);
+ 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.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
+ {
+ 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();
+ // This mimics EventQueue.dispatchEvent(). We can't use
+ // EventQueue.dispatchEvent() directly, because it is
+ // protected, unfortunately.
+ if (ev instanceof ActiveEvent)
+ {
+ ((ActiveEvent) ev).dispatch();
+ }
+ 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
+ {
+ // Give other threads a chance to become active.
+ Thread.yield();
+ }
+ }
+ } catch (InterruptedException ex)
+ {
+ // If we get interrupted, then leave the modal state.
+ } 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<Runnable> handlers, boolean modal)