Package DisplayProject

Source Code of DisplayProject.GlassPaneWithEvents

package DisplayProject;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import sun.awt.dnd.SunDropTargetEvent;
import Framework.LogMgr;

/**
* This glass pane component will stop all mouse events, except for a double click.
*
* If the first mouse click it receives is a double click, then it will pass that
* event on, as it means a single click has just occurred before it (the glass pane)
* was displayed.  If it receives any other click events before a double click
* event, then it will not pass on the double click.  Also, once it has received
* a double click event, it will not pass on any other double click events.
*
* This logic will be reset when the glass pane gets set to invisible/visible.
*
* This GlassPaneWithEvents component will be installed on the window when
* {@link UIutils#getGlassPane(Component)} is called.
*
* @author Craig Mitchell
* @since 31/03/2008
*/
@SuppressWarnings("serial")
public class GlassPaneWithEvents extends JComponent implements MouseListener {
    /**
     * A flag to indicate whether the glass pane is to be coloured
     * to aid with the debugging effort. -DLogFlags="(trc:ui:2:255)"
     */
    protected static boolean colouredGlassForDebug = LogMgr.getInstance().test(LogMgr.TYPE_DEBUG, LogMgr.SERVICE_UI, 2, 255);

    /**
     * Store the content pane we are blocking
     */
    private Container contentPane;
   
    /**
     * This works out if a double click event will be allowed to be passed through
     */
    private boolean doubleClickAllowed;

    /**
     * This is the current event we're processing. If no event is currently being processed then this will be
     * null, however, this field can only be read by the EDT which will be waiting when not processing an event
     * this should never be read as null.
     */
  private static AWTEvent currentEvent = null;
 
  static {
    // DK:30/10/2008:intercept KeyEvents to consume all key actions once the GlassPane is visible.
    //Allow one KeyRelese event once KeyPressed event was registered before the GlassPane become visible.
    //KeyRelese event need to be allowed to complete Alt+Key actions as well as DefaultButton actions.
    //In other case the action will be ignored due GlassPane is become visible in between Key Pressed and Released events.
    // TF:20/11/2009:Forced this action to be done on the EDT
    UIutils.invokeOnGuiThread(new Runnable() {
      public void run() {
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueue() {
          private Object lastPressedComponent = null;

          @Override
          protected void dispatchEvent(AWTEvent event) {
            if (event instanceof KeyEvent && event.getSource() != null) {
              Component glassPane = null;
              if (event.getSource() instanceof JFrame) {
                glassPane = ((JFrame) event.getSource()).getRootPane().getGlassPane();
              } else if (event.getSource() instanceof JComponent) {
                JFrame frame = UIutils.getWindowForComponent((JComponent)event.getSource());
                if (frame != null) {
                  glassPane = frame.getRootPane().getGlassPane();
                }
              }
              if (glassPane != null) {
                if (glassPane.isVisible()) {
                  if (event.getID() == KeyEvent.KEY_RELEASED
                      && lastPressedComponent == event.getSource()) {
                    //allow last pressed component to process release action
                    lastPressedComponent = null;
                  } else {
                    ((KeyEvent) event).consume();
                  }
                } else {
                  if (event.getID() == KeyEvent.KEY_PRESSED) {
                    //remember last pressed component
                    lastPressedComponent  = event.getSource();
                  }
                }
              }
            }
            currentEvent = event;
            try {
              super.dispatchEvent(event);
              //Bart Gauquie 2010/03/04: click mouse button and release mousebutton on a CompoundGraphic which is within a CompoundGraphic does not generate:
              //java.awt.event.MouseEvent[MOUSE_PRESSED,(902,222),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on A3_MainHIC
              //java.awt.event.MouseEvent[MOUSE_RELEASED,(902,222),button=1,modifiers=Button1,clickCount=1] on A3_MainHIC
              //
              //but
              //
              //java.awt.event.MouseEvent[MOUSE_PRESSED,(920,224),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on A3_MainHIC
              //java.awt.event.InvocationEvent[INVOCATION_DEFAULT,runnable=sun.awt.dnd.SunDragSourceContextPeer$1@d8dcac,notifier=null,catchExceptions=false,when=1267698736927] on sun.awt.windows.WToolkit@330fb9
              //sun.awt.dnd.SunDropTargetEvent[MOUSE_ENTERED,(920,224),button=0,clickCount=0] on A3_MainHIC
              //sun.awt.PeerEvent[INVOCATION_DEFAULT,runnable=sun.awt.windows.WDropTargetContextPeer$1@1ffb136,notifier=null,catchExceptions=false,when=1267698736990] on A3_MainHIC
              //sun.awt.PeerEvent[INVOCATION_DEFAULT,runnable=sun.awt.dnd.SunDragSourceContextPeer$EventDispatcher@1b23800,notifier=null,catchExceptions=false,when=1267698736990] on be.brail.displayproject.controls.TextGraphic[,1,1,34x10,alignmentX=0.0,alignmentY=0.0,border=,flags=58720256,maximumSize=,minimumSize=java.awt.Dimension[width=34,height=10],preferredSize=java.awt.Dimension[width=34,height=10],defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=EE47897,verticalAlignment=CENTER,verticalTextPosition=CENTER]
              //sun.awt.dnd.SunDropTargetEvent[MOUSE_DROPPED,(920,224)] on A3_MainHIC
              //
              // so we create a new MouseReleased event with the same coordinates and dispatch that event also ...
              if (event instanceof SunDropTargetEvent) {
                SunDropTargetEvent sunDropTargetEvent = (SunDropTargetEvent) event;
                if (sunDropTargetEvent.getID() == SunDropTargetEvent.MOUSE_DROPPED) {
                  MouseEvent mouseReleasedEvent = new MouseEvent((Component) event.getSource(), MouseEvent.MOUSE_RELEASED, sunDropTargetEvent.getWhen(),
                      MouseEvent.BUTTON1_MASK, sunDropTargetEvent.getX(), sunDropTargetEvent.getY(), 1, false, MouseEvent.BUTTON1);
                  super.dispatchEvent(mouseReleasedEvent);
                }
              }
            }
            finally {
              currentEvent = null;
            }
          }
        });     
      }
    });
  }

  /**
   * Return the current event. This method will return null unless the calling thread is the event dispatching
   * thread, and the event dispatching thread is processing an event. (If the former condition is true, the
   * latter condition is almost certain)
   * @return
   */
  public static AWTEvent getCurrentEvent() {
    if (SwingUtilities.isEventDispatchThread()) {
      return currentEvent;
    }
    else {
      return null;
    }
  }
 
  /**
   * Main constructor.
   *
   * @param pContentPane The content pane that is directly below this glass pane.
   */
  public GlassPaneWithEvents(Container pContentPane) {
    this.addMouseListener(this);
    this.contentPane = pContentPane;
    this.doubleClickAllowed = true;
  }

  /**
   * Take the mouse event and repost it on the appropriate widget.
   *
   * @param pEvent
   * @param repaint
   */
  private void redispatchMouseEvent(MouseEvent pEvent) {
    // Get the mouse click point relative to the content pane
    Point containerPoint = SwingUtilities.convertPoint(this, pEvent.getPoint(), this.contentPane);

    // Find the component that is under this point
    Component component = SwingUtilities.getDeepestComponentAt(
        this.contentPane,
        containerPoint.x,
        containerPoint.y);

    // Return if nothing was found
    if (component == null) {
      return;
    }

    // Convert point relative to the target component
    Point componentPoint = SwingUtilities.convertPoint(
        this,
        pEvent.getPoint(),
        component);

    // Redispatch the event
    component.dispatchEvent(new MouseEvent(component,
        pEvent.getID(),
        pEvent.getWhen(),
        pEvent.getModifiers(),
        componentPoint.x,
        componentPoint.y,
        pEvent.getClickCount(),
        pEvent.isPopupTrigger()));
  }

  /**
   * MouseClicked is the only event we care to redispatch.
   *
   * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
   */
  public void mouseClicked(MouseEvent e) {
    // If we are a double click event, and we are allowed to happen.  Redispatch the event.
    if (e.getClickCount() == 2 && this.doubleClickAllowed) {
      this.redispatchMouseEvent(e);
    }
    // Any thing other then a double click, and even after we have done a double click, we disable all further double click events.
    this.doubleClickAllowed = false;
  }

  // Ignored events ...
  public void mouseEntered(MouseEvent e) {}
  public void mouseExited(MouseEvent e) {}
  // DK:02/03/2009: redispatch mouse Pressed and Released events either.
  //because some of listeners are listening for mouse press/release events to process double click events
  //If glass pane has been shown in between of two clicks then mouse press/release/click events with the second click
  //will come to glass pane. That is why we need to redispatch them.
  public void mousePressed(MouseEvent e) {
    if (e.getClickCount() == 2 && this.doubleClickAllowed) {
      redispatchMouseEvent(e);
    }
  }
  public void mouseReleased(MouseEvent e) {
    if (e.getClickCount() == 2 && this.doubleClickAllowed) {
      redispatchMouseEvent(e);
    }
  }

  /**
   * Reset our doubleClickAllowed flag.
   *
   * @see javax.swing.JComponent#setVisible(boolean)
   */
  @Override
  public void setVisible(boolean flag) {
    super.setVisible(flag);

    // We we are set to displayed, then allow double click events
    this.doubleClickAllowed = true;
  }
 
  @Override
  public void paint(Graphics g) {
    if (colouredGlassForDebug) {
      g.setColor(Color.cyan);
      g.fillRect(0, 0, g.getClipBounds().width, g.getClipBounds().height);
      g.setColor(Color.black);
      int x = Math.max(g.getClipBounds().width, 1) / 2 - 20;
      int y = Math.max(g.getClipBounds().height, 1) / 2 - 7;
      g.drawString("LOCKED", x, y);
    }
  }
}
TOP

Related Classes of DisplayProject.GlassPaneWithEvents

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.