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 8641 2012-09-27 06:45:17Z 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 class BlockingDispatcher implements Serializable, 131 KeyEventDispatcher 132 { 133 134 public boolean dispatchKeyEvent( final KeyEvent e ) 135 { 136 final Component source = e.getComponent(); 137 138 if ( source != null && 139 SwingUtilities.isDescendingFrom( source, getParent() ) && 140 e.getID() == KeyEvent.KEY_TYPED ) 141 { 142 UIManager.getLookAndFeel().provideErrorFeedback( getParent() ); 143 e.consume(); 144 } 145 146 return e.isConsumed(); 147 } 148 } 149 /** 150 * Container this component is registered as the glasspane with. 151 * @serial 152 */ 153 private final RootPaneContainer container; 154 155 /** 156 * {@code KeyEventDispatcher} used for blocking keyboard interaction. 157 * @serial 158 */ 159 private final KeyEventDispatcher keyDispatcher; 160 161 /** 162 * Cursor to use when blocking is in effect. 163 * @serial 164 */ 165 private Cursor cursor; 166 167 /** 168 * Creates a new {@code BlockingGlassPane} instance taking the container 169 * this component is registered with. 170 * 171 * @param container the container this component is registered with. 172 * 173 * @throws NullPointerException if {@code container} is {@code null}. 174 */ 175 public BlockingGlassPane( final RootPaneContainer container ) 176 { 177 super(); 178 179 if ( container == null ) 180 { 181 throw new NullPointerException( "container" ); 182 } 183 184 this.container = container; 185 this.keyDispatcher = new BlockingDispatcher(); 186 super.setVisible( false ); 187 this.setOpaque( false ); 188 this.addMouseListener( 189 new MouseAdapter() 190 { 191 192 public void mouseClicked( final MouseEvent e ) 193 { 194 UIManager.getLookAndFeel(). 195 provideErrorFeedback( getParent() ); 196 197 } 198 } ); 199 200 } 201 202 /** 203 * Creates a new {@code BlockingGlassPane} instance taking the container 204 * this component is registered with and the cursor to use when blocking is 205 * in effect. 206 * 207 * @param container the container this component is registered with. 208 * @param cursor the cursor to use when blocking is in effect. 209 * 210 * @throws NullPointerException if either {@code container} or 211 * {@code cursor} is {@code null}. 212 */ 213 public BlockingGlassPane( final RootPaneContainer container, 214 final Cursor cursor ) 215 { 216 this( container ); 217 218 if ( cursor == null ) 219 { 220 throw new NullPointerException( "cursor" ); 221 } 222 223 this.cursor = cursor; 224 } 225 226 /** 227 * Gets the cursor used when blocking is in effect. 228 * @return the cursor used when blocking is in effect. 229 */ 230 private Cursor getBlockingCursor() 231 { 232 if ( this.cursor == null ) 233 { 234 this.cursor = Cursor.getPredefinedCursor( 235 this.getDefaultCursorType().intValue() ); 236 237 } 238 239 return this.cursor; 240 } 241 242 //-------------------------------------------------------BlockingGlassPane-- 243 }