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 }