Clover coverage report - gsbase - 2.0.1
Coverage timestamp: Sat Jan 1 2005 12:30:02 EST
file stats: LOC: 249   Methods: 10
NCLOC: 118   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DelayedComponentLoaderPanel.java 0% 0% 0% 0%
coverage
 1    /*
 2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
 3    *
 4    * Redistribution and use in source and binary forms, with or without
 5    * modification, are permitted provided that the following conditions are met:
 6    *
 7    * 1. Redistributions of source code must retain the above copyright notice,
 8    * this list of conditions and the following disclaimer.
 9    * 2. Redistributions in binary form must reproduce the above copyright notice,
 10    * this list of conditions and the following disclaimer in the documentation
 11    * and/or other materials provided with the distribution.
 12    * 3. The end-user documentation included with the redistribution, if any, must
 13    * include the following acknowledgment:
 14    *
 15    * "This product includes software developed by Gargoyle Software Inc.
 16    * (http://www.GargoyleSoftware.com/)."
 17    *
 18    * Alternately, this acknowledgment may appear in the software itself, if
 19    * and wherever such third-party acknowledgments normally appear.
 20    * 4. The name "Gargoyle Software" must not be used to endorse or promote
 21    * products derived from this software without prior written permission.
 22    * For written permission, please contact info@GargoyleSoftware.com.
 23    * 5. Products derived from this software may not be called "GSBase", nor may
 24    * "GSBase" appear in their name, without prior written permission of
 25    * Gargoyle Software Inc.
 26    *
 27    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 28    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 29    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
 30    * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 31    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 32    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 33    * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 34    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 35    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 36    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 37    */
 38    package com.gargoylesoftware.base.gui;
 39   
 40    import com.gargoylesoftware.base.util.DetailedIllegalArgumentException;
 41    import com.gargoylesoftware.base.util.DetailedNullPointerException;
 42    import java.awt.BorderLayout;
 43    import java.awt.Component;
 44    import java.util.Collections;
 45    import java.util.HashSet;
 46    import java.util.Set;
 47    import javax.swing.JComponent;
 48    import javax.swing.JLabel;
 49    import javax.swing.SwingUtilities;
 50    import javax.swing.UIManager;
 51    import javax.swing.JScrollPane;
 52   
 53    /**
 54    * A panel that supports delayed loading of its contents. This is useful when
 55    * the component that will fill this panel will take a long time to load. A "please
 56    * wait" message will be displayed while the component is being loaded. When loading
 57    * is complete, the new component will be made a child of this panel so that it can
 58    * become visible.<p>
 59    *
 60    * The following sample will create a delayed loader with a default "please wait" message.
 61    * <pre>
 62    * final DelayedComponentLoaderPanel panel = new DelayedComponentLoaderPanel();
 63    * panel.setComponentLoader( new DefaultComponentLoader(MyExpensiveComponent.class) );
 64    * </pre>
 65    *
 66    * This sample has a custom message.
 67    * <pre>
 68    * final JLabel label = new JLabel("My custom wait message");
 69    * final DelayedComponentLoaderPanel panel = new DelayedComponentLoaderPanel(label);
 70    * panel.setComponentLoader( new DefaultComponentLoader(MyExpensiveComponent.class) );
 71    * </pre>
 72    *
 73    * @version $Revision: 1.7 $
 74    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
 75    */
 76    public class DelayedComponentLoaderPanel extends JComponent {
 77    private static final long serialVersionUID = 1;
 78    private static final int LOADER_STARTED = 1;
 79    private static final int LOADER_FINISHED = 2;
 80   
 81    private Set listeners_;
 82    private Component waitingComponent_;
 83   
 84    /**
 85    * Create a new panel that will display a simple "please wait" message
 86    * when it is loading.
 87    */
 88  0 public DelayedComponentLoaderPanel() {
 89  0 this( new JLabel("Loading ... Please wait.") );
 90  0 JLabel label = (JLabel)waitingComponent_;
 91  0 label.setIcon( UIManager.getIcon("OptionPane.informationIcon") );
 92  0 label.setHorizontalAlignment( JLabel.CENTER );
 93  0 label.setOpaque(true);
 94    }
 95   
 96    /**
 97    * Create a new panel that will display the specified waitingComponent
 98    * while it is loading.
 99    *
 100    * @param waitingComponent The component to display while loading is in progress.
 101    */
 102  0 public DelayedComponentLoaderPanel( final Component waitingComponent ) {
 103  0 assertNotNull("waitingComponent", waitingComponent);
 104   
 105  0 setLayout( new BorderLayout() );
 106  0 waitingComponent_ = waitingComponent;
 107  0 add( BorderLayout.CENTER, waitingComponent_ );
 108    }
 109   
 110    /**
 111    * Set the new component loader. The waiting component will be displayed
 112    * immediately and component loading will start on a background thread.
 113    * If the new loader is null then no loading will take place and the waiting
 114    * component will be displayed indefinitely
 115    *
 116    * @param loader The new component loader.
 117    */
 118  0 public void setComponentLoader( final ComponentLoader loader ) {
 119    // Display the waiting component
 120  0 replaceComponent( waitingComponent_ );
 121   
 122  0 if( loader != null ) {
 123  0 fireComponentLoadingEvent(LOADER_STARTED, loader, null);
 124  0 new Thread() {
 125  0 public void run() {
 126  0 try {
 127  0 sleep(500);
 128    }
 129    catch( final InterruptedException e ) {
 130    // Ignore this
 131    }
 132   
 133  0 Component loadedComponent;
 134   
 135  0 try {
 136  0 loadedComponent = loader.loadComponent();
 137    }
 138    catch( final Throwable t ) {
 139  0 loadedComponent = new JScrollPane(new ThrowablePanel(t));
 140  0 t.printStackTrace();
 141    }
 142   
 143  0 final Component finalLoadedComponent = loadedComponent;
 144  0 SwingUtilities.invokeLater( new Runnable() {
 145  0 public void run() {
 146  0 replaceComponent( finalLoadedComponent );
 147  0 fireComponentLoadingEvent(LOADER_FINISHED, loader,
 148    finalLoadedComponent );
 149    }
 150    } );
 151    }
 152    }.start();
 153    }
 154    }
 155   
 156    /**
 157    * Replace the current child with the specified component
 158    * @param component The new component.
 159    */
 160  0 private void replaceComponent( final Component component ) {
 161  0 removeAll();
 162  0 add( BorderLayout.CENTER, component );
 163  0 revalidate();
 164    }
 165   
 166    /**
 167    * Add the specified listener.
 168    *
 169    * @param listener The new listener
 170    */
 171  0 public void addDelayedComponentLoaderListener( final DelayedComponentLoaderListener listener ) {
 172   
 173  0 assertNotNull("listener", listener);
 174   
 175    // Perform delayed loading of the listeners collection
 176  0 if( listeners_ == null ) {
 177  0 synchronized(this) {
 178  0 if( listeners_ == null ) {
 179  0 listeners_ = Collections.synchronizedSet(new HashSet());
 180    }
 181    }
 182    }
 183  0 listeners_.add(listener);
 184    }
 185   
 186    /**
 187    * Remove the specified listener.
 188    * @param listener the listener to remove.
 189    */
 190  0 public void removeDelayedComponentLoaderListener(final DelayedComponentLoaderListener listener ) {
 191   
 192  0 assertNotNull("listener", listener);
 193   
 194  0 if( listeners_ != null ) {
 195  0 listeners_.remove(listener);
 196    }
 197    }
 198   
 199    /**
 200    * Fire the component loading event.
 201    * @param action The action id
 202    * @param loader The loader
 203    * @param loadedComponent The component that was just loaded.
 204    */
 205  0 private void fireComponentLoadingEvent(
 206    final int action,
 207    final ComponentLoader loader,
 208    final Component loadedComponent ) {
 209   
 210  0 if( listeners_ != null && listeners_.isEmpty() == false ) {
 211  0 DelayedComponentLoaderListener listenerArray[];
 212  0 synchronized(listeners_) {
 213  0 listenerArray = new DelayedComponentLoaderListener[listeners_.size()];
 214  0 listeners_.toArray(listenerArray);
 215    }
 216   
 217  0 final DelayedComponentLoaderEvent event
 218    = new DelayedComponentLoaderEvent(this, loader, loadedComponent);
 219   
 220  0 int i;
 221  0 for( i=0; i<listenerArray.length; i++ ) {
 222  0 switch( action ) {
 223  0 case LOADER_STARTED:
 224  0 listenerArray[i].componentLoadingStarted(event);
 225  0 break;
 226   
 227  0 case LOADER_FINISHED:
 228  0 listenerArray[i].componentLoadingFinished(event);
 229  0 break;
 230   
 231  0 default:
 232  0 throw new DetailedIllegalArgumentException("action", new Integer(action), "Unexpected value");
 233    }
 234    }
 235    }
 236    }
 237   
 238   
 239    /**
 240    * Throw an exception if the specified object is null
 241    * @param fieldName The name of the paremeter we are checking
 242    * @param object The value of the parameter we are checking
 243    */
 244  0 protected final void assertNotNull( final String fieldName, final Object object ) {
 245  0 if( object == null ) {
 246  0 throw new DetailedNullPointerException(fieldName);
 247    }
 248    }
 249    }