package edu.harvard.wcfia.yoshikoder.util; import java.awt.AWTEvent; import java.awt.Component; import java.awt.Cursor; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.AWTEventListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import javax.swing.JComponent; import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; /** * This is the glass pane class that intercepts screen interactions during * system busy states. Mildly adjusted by eclipse. * * @author Yexin Chen */ public class GlassPane extends JComponent implements AWTEventListener { private Window theWindow; private Component activeComponent; /** * GlassPane constructor comment. * * @param Container * a */ protected GlassPane(Component activeComponent) { // add adapters that do nothing for keyboard and mouse actions addMouseListener(new MouseAdapter() { }); addKeyListener(new KeyAdapter() { }); setActiveComponent(activeComponent); } /** * Receives all key events in the AWT and processes the ones that originated * from the current window with the glass pane. * * @param event * the AWTEvent that was fired */ public void eventDispatched(AWTEvent event) { Object source = event.getSource(); // discard the event if its source is not from the correct type boolean sourceIsComponent = (event.getSource() instanceof Component); if ((event instanceof KeyEvent) && sourceIsComponent) { // If the event originated from the window w/glass pane, consume the // event if ((SwingUtilities.windowForComponent((Component)source) == theWindow)) { ((KeyEvent)event).consume(); } } } /** * Finds the glass pane that is related to the specified component. * * @param startComponent * the component used to start the search for the glass pane * @param create * a flag whether to create a glass pane if one does not exist * @return GlassPane */ public synchronized static GlassPane mount(Component startComponent, boolean create) { RootPaneContainer aContainer = null; Component aComponent = startComponent; // Climb the component hierarchy until a RootPaneContainer is found or // until the very top while ((aComponent.getParent() != null) && !(aComponent instanceof RootPaneContainer)) { aComponent = aComponent.getParent(); } // Guard against error conditions if climb search wasn't successful if (aComponent instanceof RootPaneContainer) { aContainer = (RootPaneContainer)aComponent; } if (aContainer != null) { // Retrieve an existing GlassPane if old one already exist or create // a new one, otherwise return null if ((aContainer.getGlassPane() != null) && (aContainer.getGlassPane() instanceof GlassPane)) { return (GlassPane)aContainer.getGlassPane(); } else if (create) { GlassPane aGlassPane = new GlassPane(startComponent); aContainer.setGlassPane(aGlassPane); /* System.err.println("GlassPane mounted on " + aContainer.getClass()); */ return aGlassPane; } else { return null; } } else { return null; } } /** * Set the component that ordered-up the glass pane. * * @param aComponent * the UI component that asked for the glass pane */ private void setActiveComponent(Component aComponent) { activeComponent = aComponent; } /** * Sets the glass pane as visible or invisible. The mouse cursor will be set * accordingly. */ public void setVisible(boolean value) { if (value) { // keep track of the visible window associated w/the component // useful during event filtering if (theWindow == null) { theWindow = SwingUtilities.windowForComponent(activeComponent); if (theWindow == null) { if (activeComponent instanceof Window) { theWindow = (Window)activeComponent; } } } // Sets the mouse cursor to hourglass mode getTopLevelAncestor().setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); activeComponent = theWindow.getFocusOwner(); // Start receiving all events and consume them if necessary Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK); this.requestFocus(); // Activate the glass pane capabilities super.setVisible(value); } else { // Stop receiving all events Toolkit.getDefaultToolkit().removeAWTEventListener(this); // Deactivate the glass pane capabilities super.setVisible(value); // Sets the mouse cursor back to the regular pointer if (getTopLevelAncestor() != null) { getTopLevelAncestor().setCursor(null); } } } }