View Javadoc

1   /*
2    *  jDTAUS Core Utilities
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.core.swing.util;
22  
23  import java.awt.Component;
24  import java.awt.Cursor;
25  import java.awt.KeyEventDispatcher;
26  import java.awt.KeyboardFocusManager;
27  import java.awt.event.KeyEvent;
28  import java.awt.event.MouseAdapter;
29  import java.awt.event.MouseEvent;
30  import java.io.Serializable;
31  import javax.swing.JComponent;
32  import javax.swing.RootPaneContainer;
33  import javax.swing.SwingUtilities;
34  import javax.swing.UIManager;
35  import org.jdtaus.core.container.ContainerFactory;
36  
37  /**
38   * {@code JComponent} for use as a blocking glasspane.
39   * <p>Blocking is controlled by property {@code visible}. If {@code true},
40   * the current look and feel's
41   * {@link javax.swing.LookAndFeel#provideErrorFeedback(Component)
42   * provideErrorFeedback} method is called whenever a mouse clicked
43   * {@code MouseEvent}, or a {@code KeyEvent} of type
44   * {@link KeyEvent#KEY_TYPED KEY_TYPED}, whose source is not {@code null} and
45   * descending from the parent of this component, is received. Also the cursor is
46   * set to the cursor to use when blocking is in effect. If {@code false}, the
47   * cursor is reset to the system's default cursor and no more blocking is
48   * performed. Property {@code visible} defaults to {@code false}.</p>
49   *
50   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
51   * @version $JDTAUS: BlockingGlassPane.java 8743 2012-10-07 03:06:20Z schulte $
52   */
53  public final class BlockingGlassPane extends JComponent
54  {
55      //--Properties--------------------------------------------------------------
56  
57  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
58      // This section is managed by jdtaus-container-mojo.
59  
60      /**
61       * Gets the value of property <code>defaultCursorType</code>.
62       *
63       * @return Default cursor used when blocking is in effect.
64       */
65      private java.lang.Integer getDefaultCursorType()
66      {
67          return (java.lang.Integer) ContainerFactory.getContainer().
68              getProperty( this, "defaultCursorType" );
69  
70      }
71  
72  // </editor-fold>//GEN-END:jdtausProperties
73  
74      //--------------------------------------------------------------Properties--
75      //--JComponent--------------------------------------------------------------
76  
77      /**
78       * Enables or disables blocking.
79       * <p>This method registers a {@code KeyEventDispatcher} with AWT's current
80       * {@code KeyboardFocusManager} blocking the keyboard for any user
81       * interaction and updates the cursor to the cursor to use when blocking is
82       * in effect if {@code visible} is {@code true}. If {@code visible} is
83       * {@code false} the {@code KeyEventDispatcher} is removed and the cursor is
84       * reset to the system's default cursor.</p>
85       *
86       * @param visible {@code true} to enable blocking; {@code false} to disable
87       * blocking.
88       */
89      public void setVisible( final boolean visible )
90      {
91          final Runnable runnable = new Runnable()
92          {
93  
94              public void run()
95              {
96                  if ( visible )
97                  {
98                      BlockingGlassPane.super.setVisible( true );
99                      setCursor( getBlockingCursor() );
100                     KeyboardFocusManager.getCurrentKeyboardFocusManager().
101                         addKeyEventDispatcher( keyDispatcher );
102 
103                 }
104                 else
105                 {
106                     KeyboardFocusManager.getCurrentKeyboardFocusManager().
107                         removeKeyEventDispatcher( keyDispatcher );
108 
109                     setCursor( Cursor.getDefaultCursor() );
110                     BlockingGlassPane.super.setVisible( false );
111                     container.getContentPane().validate();
112                 }
113             }
114         };
115 
116         if ( !SwingUtilities.isEventDispatchThread() )
117         {
118             SwingUtilities.invokeLater( runnable );
119         }
120         else
121         {
122             runnable.run();
123         }
124     }
125 
126     //--------------------------------------------------------------JComponent--
127     //--BlockingGlassPane-------------------------------------------------------
128 
129     /** {@code KeyEventDispatcher} used for blocking. */
130     private final class BlockingDispatcher
131         implements Serializable, KeyEventDispatcher
132     {
133 
134         /** Creates a new {@code BlockingDispatcher} instance. */
135         private BlockingDispatcher()
136         {
137             super();
138         }
139 
140         public boolean dispatchKeyEvent( final KeyEvent e )
141         {
142             final Component source = e.getComponent();
143 
144             if ( source != null &&
145                 SwingUtilities.isDescendingFrom( source, getParent() ) &&
146                 e.getID() == KeyEvent.KEY_TYPED )
147             {
148                 UIManager.getLookAndFeel().provideErrorFeedback( getParent() );
149                 e.consume();
150             }
151 
152             return e.isConsumed();
153         }
154     }
155     /**
156      * Container this component is registered as the glasspane with.
157      * @serial
158      */
159     private final RootPaneContainer container;
160 
161     /**
162      * {@code KeyEventDispatcher} used for blocking keyboard interaction.
163      * @serial
164      */
165     private final KeyEventDispatcher keyDispatcher;
166 
167     /**
168      * Cursor to use when blocking is in effect.
169      * @serial
170      */
171     private Cursor cursor;
172 
173     /**
174      * Creates a new {@code BlockingGlassPane} instance taking the container
175      * this component is registered with.
176      *
177      * @param container the container this component is registered with.
178      *
179      * @throws NullPointerException if {@code container} is {@code null}.
180      */
181     public BlockingGlassPane( final RootPaneContainer container )
182     {
183         super();
184 
185         if ( container == null )
186         {
187             throw new NullPointerException( "container" );
188         }
189 
190         this.container = container;
191         this.keyDispatcher = new BlockingDispatcher();
192         super.setVisible( false );
193         this.setOpaque( false );
194         this.addMouseListener(
195             new MouseAdapter()
196             {
197 
198                 public void mouseClicked( final MouseEvent e )
199                 {
200                     UIManager.getLookAndFeel().
201                         provideErrorFeedback( getParent() );
202 
203                 }
204             } );
205 
206     }
207 
208     /**
209      * Creates a new {@code BlockingGlassPane} instance taking the container
210      * this component is registered with and the cursor to use when blocking is
211      * in effect.
212      *
213      * @param container the container this component is registered with.
214      * @param cursor the cursor to use when blocking is in effect.
215      *
216      * @throws NullPointerException if either {@code container} or
217      * {@code cursor} is {@code null}.
218      */
219     public BlockingGlassPane( final RootPaneContainer container,
220                               final Cursor cursor )
221     {
222         this( container );
223 
224         if ( cursor == null )
225         {
226             throw new NullPointerException( "cursor" );
227         }
228 
229         this.cursor = cursor;
230     }
231 
232     /**
233      * Gets the cursor used when blocking is in effect.
234      * @return the cursor used when blocking is in effect.
235      */
236     private Cursor getBlockingCursor()
237     {
238         if ( this.cursor == null )
239         {
240             this.cursor = Cursor.getPredefinedCursor(
241                 this.getDefaultCursorType().intValue() );
242 
243         }
244 
245         return this.cursor;
246     }
247 
248     //-------------------------------------------------------BlockingGlassPane--
249 }