FileDocCategorySizeDatePackage
FixedGlassPane.javaAPI DocExample4602Fri Jan 17 07:33:24 GMT 2003None

FixedGlassPane.java

// FixedGlassPane.java
// Based in part on code from the Java Tutorial for glass panes (java.sun.com).
// This version handles both mouse events and focus events.  The focus is
// held on the panel so that key events are also effectively ignored.  (But
// a KeyListener could still be attached by the program activating this pane.)
//

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;

public class FixedGlassPane extends JPanel 
    implements MouseListener, MouseMotionListener, FocusListener 
{
  // helpers for redispatch logic
  Toolkit toolkit;
  JMenuBar menuBar;
  Container contentPane;
  boolean inDrag = false;

  // trigger for redispatching (allows external control)
  boolean needToRedispatch = false;

  public FixedGlassPane(JMenuBar mb, Container cp) {
    toolkit = Toolkit.getDefaultToolkit();
    menuBar = mb;
    contentPane = cp;
    addMouseListener(this);
    addMouseMotionListener(this);
    addFocusListener(this);
  }

  public void setVisible(boolean v) {
    // Make sure we grab the focus so that key events don't go astray.
    if (v) requestFocus();
    super.setVisible(v);
  }

  // Once we have focus, keep it if we're visible
  public void focusLost(FocusEvent fe) { if (isVisible()) requestFocus(); }
  public void focusGained(FocusEvent fe) { }

  // We only need to redispatch if we're not visible, but having full control
  // over this might prove handy.
  public void setNeedToRedispatch(boolean need) {
    needToRedispatch = need;
  }

  /* (Based on code from the Java Tutorial)
   * We must forward at least the mouse drags that started
   * with mouse presses over the check box.  Otherwise,
   * when the user presses the check box then drags off,
   * the check box isn't disarmed -- it keeps its dark
   * gray background or whatever its L&F uses to indicate
   * that the button is currently being pressed.
   */
  public void mouseDragged(MouseEvent e) {
    if (needToRedispatch) redispatchMouseEvent(e);
  }

  public void mouseMoved(MouseEvent e) {
    if (needToRedispatch) redispatchMouseEvent(e);
  }

  public void mouseClicked(MouseEvent e) {
    if (needToRedispatch) redispatchMouseEvent(e);
  }

  public void mouseEntered(MouseEvent e) {
    if (needToRedispatch) redispatchMouseEvent(e);
  }

  public void mouseExited(MouseEvent e) {
    if (needToRedispatch) redispatchMouseEvent(e);
  }

  public void mousePressed(MouseEvent e) {
    if (needToRedispatch) redispatchMouseEvent(e);
  }

  public void mouseReleased(MouseEvent e) {
    if (needToRedispatch) {
      redispatchMouseEvent(e);
      inDrag = false;
    }
  }

  private void redispatchMouseEvent(MouseEvent e) {
    boolean inButton = false;
    boolean inMenuBar = false;
    Point glassPanePoint = e.getPoint();
    Component component = null;
    Container container = contentPane;
    Point containerPoint = SwingUtilities.convertPoint(this, glassPanePoint, 
                                      contentPane);
    int eventID = e.getID();

    if (containerPoint.y < 0) {
      inMenuBar = true;
      container = menuBar;
      containerPoint = SwingUtilities.convertPoint(this, glassPanePoint,
                                      menuBar);
      testForDrag(eventID);
    } 

    //XXX: If the event is from a component in a popped-up menu,
    //XXX: then the container should probably be the menu's
    //XXX: JPopupMenu, and containerPoint should be adjusted
    //XXX: accordingly.
    component = SwingUtilities.getDeepestComponentAt(container,
                                        containerPoint.x,
                                        containerPoint.y);

    if (component == null) {
      return;
    }
    else {
      inButton = true;
      testForDrag(eventID);
    }

    if (inMenuBar || inButton || inDrag) {
      Point componentPoint = SwingUtilities.convertPoint(this, glassPanePoint, 
                                                         component);
      component.dispatchEvent(new MouseEvent(component,
                                             eventID,
                                             e.getWhen(),
                                             e.getModifiers(),
                                             componentPoint.x,
                                             componentPoint.y,
                                             e.getClickCount(),
                                             e.isPopupTrigger()));
    }
  }

  private void testForDrag(int eventID) {
    if (eventID == MouseEvent.MOUSE_PRESSED) {
      inDrag = true;
    }
  }
}