KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > instrument > client > InstrumentClientFrame


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14  * implied.
15  *
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19
20 package org.apache.excalibur.instrument.client;
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Dimension JavaDoc;
24 import java.awt.Frame JavaDoc;
25 import java.awt.Toolkit JavaDoc;
26 import java.awt.event.WindowAdapter JavaDoc;
27 import java.awt.event.WindowEvent JavaDoc;
28 import java.io.ByteArrayOutputStream JavaDoc;
29 import java.io.File JavaDoc;
30 import java.io.FileInputStream JavaDoc;
31 import java.io.FileOutputStream JavaDoc;
32 import java.io.InputStream JavaDoc;
33 import java.io.OutputStream JavaDoc;
34 import java.net.MalformedURLException JavaDoc;
35 import java.net.URL JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.HashMap JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Map JavaDoc;
41
42 import javax.swing.ImageIcon JavaDoc;
43 import javax.swing.JDesktopPane JavaDoc;
44 import javax.swing.JFileChooser JavaDoc;
45 import javax.swing.JFrame JavaDoc;
46 import javax.swing.JInternalFrame JavaDoc;
47 import javax.swing.JOptionPane JavaDoc;
48 import javax.swing.JPanel JavaDoc;
49 import javax.swing.JSplitPane JavaDoc;
50 import javax.swing.JTabbedPane JavaDoc;
51 import javax.swing.SwingUtilities JavaDoc;
52 import javax.swing.border.BevelBorder JavaDoc;
53 import javax.swing.filechooser.FileFilter JavaDoc;
54
55 import org.apache.avalon.framework.configuration.Configuration;
56 import org.apache.avalon.framework.configuration.ConfigurationException;
57 import org.apache.avalon.framework.configuration.DefaultConfiguration;
58 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
59 import org.apache.avalon.framework.configuration.DefaultConfigurationSerializer;
60 import org.apache.avalon.framework.container.ContainerUtil;
61 import org.apache.avalon.framework.logger.LogEnabled;
62 import org.apache.avalon.framework.logger.Logger;
63
64 import org.apache.excalibur.instrument.client.http.HTTPInstrumentManagerConnection;
65
66 /**
67  *
68  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
69  * @version CVS $Revision: 1.4 $ $Date: 2004/02/28 11:47:23 $
70  * @since 4.1
71  */

72 class InstrumentClientFrame
73     extends JFrame JavaDoc
74     implements InstrumentManagerConnectionListener, LogEnabled
75 {
76     protected static final String JavaDoc MEDIA_PATH = "org/apache/excalibur/instrument/client/media/";
77     
78     static final String JavaDoc SHUTDOWN_HOOK_NAME = "InstrumentClientShutdownHook";
79     
80     private String JavaDoc m_title;
81     
82     private JTabbedPane JavaDoc m_connectionsPane;
83     private JDesktopPane JavaDoc m_desktopPane;
84     private JSplitPane JavaDoc m_splitPane;
85     private MenuBar m_menuBar;
86     private StatusBar m_statusBar;
87     
88     private boolean m_antialias;
89
90     private File JavaDoc m_desktopFile;
91     private File JavaDoc m_desktopFileDir;
92     
93     private Map JavaDoc m_connections = new HashMap JavaDoc();
94     private InstrumentManagerConnection[] m_connectionArray;
95     
96     /** Shutdown hook */
97     private Thread JavaDoc m_hook;
98     
99     private Logger m_logger;
100     
101     /*---------------------------------------------------------------
102      * Constructors
103      *-------------------------------------------------------------*/

104     /**
105      * Creates a new InstrumentClient frame.
106      *
107      * @param title The title for the frame.
108      */

109     InstrumentClientFrame( String JavaDoc title )
110     {
111         super();
112
113         m_title = title;
114     }
115     
116     public void initialize()
117     {
118         init();
119         
120         ClassLoader JavaDoc cl = this.getClass().getClassLoader();
121         setIconImage( new ImageIcon JavaDoc( cl.getResource( MEDIA_PATH + "client.gif") ).getImage() );
122     }
123     
124     /*---------------------------------------------------------------
125      * InstrumentManagerConnectionListener Methods
126      *-------------------------------------------------------------*/

127     /**
128      * Called when the connection is opened. May be called more than once if
129      * the connection to the InstrumentManager is reopened.
130      *
131      * @param connection Connection which was opened.
132      */

133     public void opened( InstrumentManagerConnection connection )
134     {
135         getLogger().debug( "opened: " + connection.getKey() );
136         updateConnectionTab( connection );
137     }
138     
139     /**
140      * Called when the connection is closed. May be called more than once if
141      * the connection to the InstrumentManager is reopened.
142      *
143      * @param connection Connection which was closed.
144      */

145     public void closed( InstrumentManagerConnection connection )
146     {
147         getLogger().debug( "closed: " + connection.getKey() );
148         updateConnectionTab( connection );
149     }
150     
151     /**
152      * Called when the connection is deleted. All references should be removed.
153      *
154      * @param connection Connection which was deleted.
155      */

156     public void deleted( InstrumentManagerConnection connection )
157     {
158         getLogger().debug( "deleted: " + connection.getKey() );
159         // Remove the tab
160
int tabIndex = m_connectionsPane.indexOfComponent( connection );
161         if ( tabIndex >= 0 )
162         {
163             // Doing this within the shutdown hook causes a deadlock. Java bug?
164
if ( Thread.currentThread() != m_hook )
165             {
166                 m_connectionsPane.remove( connection );
167             }
168         }
169         
170         connection.removeInstrumentManagerConnectionListener( this );
171         Object JavaDoc key = connection.getKey();
172         synchronized ( m_connections )
173         {
174             m_connections.remove( key );
175             m_connectionArray = null;
176         }
177     }
178     
179     /*---------------------------------------------------------------
180      * LogEnabled Methods
181      *-------------------------------------------------------------*/

182     public void enableLogging( Logger logger )
183     {
184         m_logger = logger;
185     }
186     
187     Logger getLogger()
188     {
189         return m_logger;
190     }
191     
192     /*---------------------------------------------------------------
193      * State Methods
194      *-------------------------------------------------------------*/

195     /**
196      * Stores the default state file name and attempts to load it if it exists.
197      * Should onl be called at startup.
198      *
199      * @param defaultStateFile The default statefile which will be loaded on
200      * startup.
201      */

202     void setDefaultStateFile( File JavaDoc defaultStateFile )
203     {
204         // See if the directory containing th defaultStateFile exists. If so set it.
205
File JavaDoc defaultStateFileDir = defaultStateFile.getParentFile();
206         if ( defaultStateFileDir.exists() )
207         {
208             m_desktopFileDir = defaultStateFileDir;
209         }
210         if ( defaultStateFile.exists() )
211         {
212             try
213             {
214                 m_desktopFile = null;
215                 loadStateFromFile( defaultStateFile, true );
216                 m_desktopFile = defaultStateFile;
217             }
218             catch( Exception JavaDoc e )
219             {
220                 String JavaDoc msg = "Unable to load desktop file.";
221                 getLogger().debug( msg, e );
222                 showErrorDialog( msg, e );
223             }
224             updateTitle();
225         }
226     }
227     
228     /**
229      * Loads the Instrument Client state from the specified file.
230      *
231      * @param stateFile File to read the client's state from.
232      * @param showErrorDialog Controls whether an error dialog should be
233      * displayed or not.
234      *
235      * @throws Exception if there are any problems loading the state.
236      */

237     void loadStateFromFile( File JavaDoc stateFile, boolean showErrorDialog ) throws Exception JavaDoc
238     {
239         long now = System.currentTimeMillis();
240         getLogger().debug( "Loading Instrument Client state from: " +
241             stateFile.getAbsolutePath() );
242
243         FileInputStream JavaDoc is = new FileInputStream JavaDoc( stateFile );
244         try
245         {
246             loadStateFromStream( is, showErrorDialog );
247         }
248         finally
249         {
250             is.close();
251         }
252
253         getLogger().debug( "Loading Instrument Client state took " +
254                            ( System.currentTimeMillis() - now ) + "ms." );
255     }
256
257     /**
258      * Loads the Instrument Client state from the specified stream.
259      *
260      * @param is Stream to read the instrument client's state from.
261      * @param showErrorDialog Controls whether an error dialog should be
262      * displayed or not.
263      *
264      * @throws Exception if there are any problems loading the state.
265      */

266     void loadStateFromStream( InputStream JavaDoc is, boolean showErrorDialog ) throws Exception JavaDoc
267     {
268         // Ride on top of the Configuration classes to load the state.
269
DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
270         Configuration stateConfig = builder.build( is );
271
272         loadStateFromConfiguration( stateConfig, showErrorDialog );
273     }
274
275     /**
276      * Loads the Instrument Client state from the specified Configuration.
277      *
278      * @param state Configuration object to load the state from.
279      * @param showErrorDialog Controls whether an error dialog should be
280      * displayed or not.
281      *
282      * @throws ConfigurationException If there were any problems loading the
283      * state.
284      */

285     void loadStateFromConfiguration( Configuration state, boolean showErrorDialog )
286         throws ConfigurationException
287     {
288         // Load the global client state information.
289

290         try
291         {
292             // Load the frame information. It is in a child node.
293
Configuration frameState = state.getChild( "frame" );
294             // Window position
295
setLocation( frameState.getAttributeAsInteger( "x" ),
296                 frameState.getAttributeAsInteger( "y" ) );
297             setSize( frameState.getAttributeAsInteger( "width" ),
298                 frameState.getAttributeAsInteger( "height" ) );
299             // Window state
300
if ( frameState.getAttributeAsBoolean( "iconized", false ) )
301             {
302                 setState( Frame.ICONIFIED );
303             }
304             // Split Pane state
305
m_splitPane.setDividerLocation(
306                 frameState.getAttributeAsInteger( "divider-location" ) );
307             m_splitPane.setLastDividerLocation(
308                 frameState.getAttributeAsInteger( "last-divider-location" ) );
309             // Antialias.
310
m_antialias = frameState.getAttributeAsBoolean( "antialias", false );
311         }
312         catch ( ConfigurationException e )
313         {
314             String JavaDoc msg = "Unable to fully load the frame state.";
315             if ( showErrorDialog )
316             {
317                 getLogger().debug( msg, e );
318                 showErrorDialog( msg, e );
319             }
320             else
321             {
322                 getLogger().warn( msg, e );
323             }
324         }
325         
326         // Show the frame here so that the rest of this works.
327
show();
328         
329         // Store a map of the current connections.
330
Map JavaDoc oldConnections;
331         synchronized( m_connections )
332         {
333             oldConnections = new HashMap JavaDoc( m_connections );
334         }
335             
336         // Load the state of any connections.
337
Configuration[] connConfs = state.getChildren( "connection" );
338         for( int i = 0; i < connConfs.length; i++ )
339         {
340             Configuration connConf = connConfs[ i ];
341             String JavaDoc tURL = connConf.getAttribute( "url" );
342             URL JavaDoc url;
343             try
344             {
345                 url = new URL JavaDoc( tURL );
346             }
347             catch ( MalformedURLException JavaDoc e )
348             {
349                 throw new ConfigurationException( "Invalid url, '" + tURL + "'", e );
350             }
351             
352             InstrumentManagerConnection conn;
353             synchronized ( m_connections )
354             {
355                 conn = (InstrumentManagerConnection)m_connections.get( url );
356                 
357                 if ( conn == null )
358                 {
359                     // Need to create a new connection
360
conn = createConnection( url );
361                 }
362                 
363                 oldConnections.remove( url );
364             }
365             
366             // Load the state into the connection.
367
try
368             {
369                 conn.loadState( connConf );
370             }
371             catch ( ConfigurationException e )
372             {
373                 String JavaDoc msg = "Unable to fully load the state of connection, " + conn.getKey();
374                 if ( showErrorDialog )
375                 {
376                     getLogger().debug( msg, e );
377                     showErrorDialog( msg, e );
378                 }
379                 else
380                 {
381                     getLogger().warn( msg, e );
382                 }
383             }
384         }
385         
386         // Any old connections left need to be deleted.
387
for ( Iterator JavaDoc iter = oldConnections.values().iterator(); iter.hasNext(); )
388         {
389             InstrumentManagerConnection conn = (InstrumentManagerConnection)iter.next();
390             conn.delete();
391         }
392         
393         
394         // Always hide all existing frames as new ones will be created.
395
JInternalFrame JavaDoc frames[] = m_desktopPane.getAllFrames();
396         for ( int i = 0; i < frames.length; i++ )
397         {
398             if ( frames[i] instanceof AbstractInternalFrame )
399             {
400                 ((AbstractInternalFrame)frames[i]).hideFrame();
401             }
402         }
403         
404         // Load the state of any inner frames.
405
Configuration[] frameConfs = state.getChildren( "inner-frame" );
406         for( int i = 0; i < frameConfs.length; i++ )
407         {
408             Configuration frameConf = frameConfs[ i ];
409             String JavaDoc type = frameConf.getAttribute( "type" );
410             
411             if ( type.equals( InstrumentSampleFrame.FRAME_TYPE ) )
412             {
413                 // Figure out which connection the frame will belong to.
414
String JavaDoc tURL = frameConf.getAttribute( "url" );
415                 URL JavaDoc url;
416                 try
417                 {
418                     url = new URL JavaDoc( tURL );
419                 }
420                 catch ( MalformedURLException JavaDoc e )
421                 {
422                     throw new ConfigurationException( "Invalid url, '" + tURL + "'", e );
423                 }
424                 
425                 InstrumentManagerConnection connection = getConnection( url );
426                 if ( connection == null )
427                 {
428                     // Connection not found.
429
String JavaDoc msg = "Sample frame not being loaded becase no connection to " +
430                         url.toExternalForm() + " exists.";
431                     if ( showErrorDialog )
432                     {
433                         getLogger().debug( msg );
434                         showErrorDialog( msg );
435                     }
436                     else
437                     {
438                         getLogger().warn( msg );
439                     }
440                 } else {
441                     // Let the connection load the frame.
442
try
443                     {
444                         connection.loadSampleFrame( frameConf );
445                     }
446                     catch ( ConfigurationException e )
447                     {
448                         String JavaDoc msg =
449                             "Unable to fully load the state of an inner frame for sample: " +
450                             frameConf.getAttribute( "sample", "Sample name missing" );
451                         if ( showErrorDialog )
452                         {
453                             getLogger().debug( msg, e );
454                             showErrorDialog( msg, e );
455                         }
456                         else
457                         {
458                             getLogger().warn( msg, e );
459                         }
460                     }
461                 }
462             }
463             else
464             {
465                 // Ignore unknown types.
466
getLogger().warn( "Not loading inner frame due to unknown type: " + type );
467             }
468         }
469     }
470
471     /**
472      * Saves the Instrument Client's state to the specified file. Any
473      * existing file is backed up before the save takes place and replaced
474      * in the event of an error.
475      *
476      * @param stateFile File to write the Instrument Client's state to.
477      *
478      * @throws Exception if there are any problems saving the state.
479      */

480     void saveStateToFile( File JavaDoc stateFile ) throws Exception JavaDoc
481     {
482         long now = System.currentTimeMillis();
483         getLogger().debug( "Saving Instrument Client state to: " + stateFile.getAbsolutePath() );
484
485         // First save the state to an in memory stream to shorten the
486
// period of time needed to write the data to disk. This makes it
487
// less likely that the files will be left in a corrupted state if
488
// the JVM dies at the wrong time.
489
ByteArrayOutputStream JavaDoc os = new ByteArrayOutputStream JavaDoc();
490         byte[] data;
491         try
492         {
493             saveStateToStream( os );
494             data = os.toByteArray();
495         }
496         finally
497         {
498             os.close();
499         }
500         
501         // If the specified file exists, then rename it before we start writing.
502
// This makes it possible to recover from some errors.
503
File JavaDoc renameFile = null;
504         boolean success = false;
505         if( stateFile.exists() )
506         {
507             renameFile = new File JavaDoc( stateFile.getAbsolutePath() + "." + now + ".backup" );
508             stateFile.renameTo( renameFile );
509         }
510         
511         // Write the data to the new file.
512
FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc( stateFile );
513         try
514         {
515             fos.write( data );
516             success = true;
517         }
518         finally
519         {
520             fos.close();
521             
522             if ( !success )
523             {
524                 // Make sure that part of the file does not exist.
525
stateFile.delete();
526             }
527             
528             // Handle the backup file.
529
if ( renameFile != null )
530             {
531                 if ( success )
532                 {
533                     // No longer need the backup.
534
renameFile.delete();
535                 }
536                 else
537                 {
538                     // Need to replace the backup.
539
renameFile.renameTo( stateFile );
540                 }
541             }
542         }
543         
544         getLogger().debug( "Saving Instrument Client state took " +
545                            ( System.currentTimeMillis() - now ) + "ms." );
546     }
547
548     /**
549      * Saves the Instrument Client's state to the specified output stream.
550      *
551      * @param os Stream to write the Instrument Client's state to.
552      *
553      * @throws Exception if there are any problems saving the state.
554      */

555     void saveStateToStream( OutputStream JavaDoc os ) throws Exception JavaDoc
556     {
557         Configuration stateConfig = saveStateToConfiguration();
558
559         // Ride on top of the Configuration classes to save the state.
560
DefaultConfigurationSerializer serializer = new DefaultConfigurationSerializer();
561         serializer.setIndent( true );
562         serializer.serialize( os, stateConfig );
563     }
564
565     /**
566      * Returns the Instrument Manager's state as a Configuration object.
567      *
568      * @return The Instrument Manager's state as a Configuration object.
569      */

570     Configuration saveStateToConfiguration()
571     {
572         DefaultConfiguration state = new DefaultConfiguration( "instrument-client-state", "-" );
573         
574         // Save the frame information. Use a seperate element to keep it clean.
575
DefaultConfiguration frameState = new DefaultConfiguration( "frame", "-" );
576         // Window position
577
frameState.setAttribute( "x", Integer.toString( getX() ) );
578         frameState.setAttribute( "y", Integer.toString( getY() ) );
579         frameState.setAttribute( "width", Integer.toString( getWidth() ) );
580         frameState.setAttribute( "height", Integer.toString( getHeight() ) );
581         // Window state
582
if ( getState() == Frame.ICONIFIED )
583         {
584             frameState.setAttribute( "iconized", "true" );
585         }
586         // Split Pane state
587
frameState.setAttribute( "divider-location", Integer.toString( m_splitPane.getDividerLocation() ) );
588         frameState.setAttribute( "last-divider-location", Integer.toString( m_splitPane.getLastDividerLocation() ) );
589         // Antialias
590
frameState.setAttribute( "antialias", Boolean.toString( m_antialias ) );
591         // Add frame state
592
state.addChild( frameState );
593         
594         // Save the state of any connections.
595
InstrumentManagerConnection[] connections = getConnections();
596         for ( int i = 0; i < connections.length; i++ )
597         {
598             state.addChild( connections[i].saveState() );
599         }
600         
601         // Save the state of any inner frames.
602
JInternalFrame JavaDoc frames[] = m_desktopPane.getAllFrames();
603         for ( int i = 0; i < frames.length; i++ )
604         {
605             if ( frames[i] instanceof AbstractInternalFrame )
606             {
607                 AbstractInternalFrame internalFrame = (AbstractInternalFrame)frames[i];
608                 state.addChild( internalFrame.getState() );
609             }
610         }
611
612         return state;
613     }
614     
615     /*---------------------------------------------------------------
616      * Methods
617      *-------------------------------------------------------------*/

618     private void init()
619     {
620         updateTitle();
621         
622         // Add a shutdown hook to trap CTRL-C events.
623
m_hook = new Thread JavaDoc( SHUTDOWN_HOOK_NAME )
624         {
625             public void run()
626             {
627                 getLogger().debug( "InstrumentClientFrame.shutdownHook start");
628                 
629                 shutdown();
630                 
631                 getLogger().debug( "InstrumentClientFrame.shutdownHook end");
632             }
633         };
634         Runtime.getRuntime().addShutdownHook( m_hook );
635         
636         // Add a Window listener to trap when the user hits the close box.
637
addWindowListener( new WindowAdapter JavaDoc()
638             {
639                 public void windowClosing( WindowEvent JavaDoc event )
640                 {
641                     fileExit();
642                 }
643             });
644
645         getContentPane().setLayout( new BorderLayout JavaDoc() );
646         
647         // Create a Tabbed Panel of the connections.
648
m_connectionsPane = new JTabbedPane JavaDoc( JTabbedPane.TOP );
649         
650         // Create a DesktopPane and place it in a BevelBorder
651
m_desktopPane = new DesktopPane();
652         JPanel JavaDoc dBorder = new JPanel JavaDoc();
653         dBorder.setBorder( new BevelBorder JavaDoc( BevelBorder.LOWERED ) );
654         dBorder.setLayout( new BorderLayout JavaDoc() );
655         dBorder.add( m_desktopPane, BorderLayout.CENTER );
656
657         // Create a SplitPane at the root.
658
m_splitPane =
659             new JSplitPane JavaDoc( JSplitPane.HORIZONTAL_SPLIT, true, m_connectionsPane, dBorder );
660         m_splitPane.setOneTouchExpandable( true );
661         m_splitPane.setDividerLocation( 250 );
662         
663         getContentPane().add( m_splitPane, BorderLayout.CENTER );
664
665         // Create a Menu Bar
666
m_menuBar = new MenuBar( this );
667         setJMenuBar( m_menuBar );
668         
669         m_statusBar = new StatusBar();
670         getContentPane().add( m_statusBar, BorderLayout.SOUTH );
671
672         Toolkit JavaDoc toolkit = getToolkit();
673         Dimension JavaDoc screenSize = toolkit.getScreenSize();
674         
675         // Set the default size and location of the window. This will be overridden
676
// by whatever is stored in a state file if loaded.
677
int screenWidth = screenSize.width;
678         int screenHeight = screenSize.height;
679         setLocation( screenWidth / 20, screenHeight / 20 );
680         setSize( screenWidth * 9 / 10, screenHeight * 8 / 10 );
681     }
682     
683     boolean isAntialias()
684     {
685         return m_antialias;
686     }
687     void setAntialias( boolean antialias )
688     {
689         m_antialias = antialias;
690     }
691
692     void updateConnectionTab( InstrumentManagerConnection connection )
693     {
694         // Update the tab title.
695
int tabIndex = m_connectionsPane.indexOfComponent( connection );
696         if ( tabIndex >= 0 )
697         {
698             m_connectionsPane.setTitleAt( tabIndex, connection.getTabTitle() );
699             m_connectionsPane.setToolTipTextAt( tabIndex, connection.getTabTooltip() );
700         }
701     }
702     
703     private void updateTitle()
704     {
705         if( m_desktopFile == null )
706         {
707             setTitle( m_title );
708         }
709         else
710         {
711             setTitle( m_title + " - " + m_desktopFile.getAbsolutePath() );
712         }
713     }
714     
715     void setStatusMessage( String JavaDoc message )
716     {
717         m_statusBar.setStatusMessage( message );
718     }
719     
720     JDesktopPane JavaDoc getDesktopPane()
721     {
722         return m_desktopPane;
723     }
724     
725     void closeAllFrames()
726     {
727         JInternalFrame JavaDoc[] frames = m_desktopPane.getAllFrames();
728         for( int i = 0; i < frames.length; i++ )
729         {
730             frames[ i ].setVisible( false );
731             frames[ i ].dispose();
732         }
733     }
734     
735     /**
736      * Tile all open frames
737      */

738     void tileFrames()
739     {
740         JInternalFrame JavaDoc[] openFrames = getOpenFrames();
741         
742         int count = openFrames.length;
743         if ( count == 0)
744         {
745             return;
746         }
747         
748         // Target the frames at the specified maximum aspect ratio. The
749
// additional constraint that the frames will not be allowed to
750
// be less than 70 pixels in height unless their width is less
751
// than 100.
752
float targetRatio = 5.0f;
753         
754         Dimension JavaDoc size = getDesktopPane().getSize();
755         int cols = 1;
756         int rows = count;
757         int frameWidth = size.width / cols;
758         int frameHeight = size.height / rows;
759         float ratio = (float)frameWidth / frameHeight;
760         while ( ( rows > 1 ) && ( ( ratio > targetRatio ) ||
761             ( ( frameHeight < 70 ) && ( frameWidth > 100 ) ) ) )
762         {
763             cols++;
764             rows = (int)Math.ceil( (float)count / cols );
765             frameWidth = size.width / cols;
766             frameHeight = size.height / rows;
767             ratio = (float)frameWidth / frameHeight;
768         }
769         
770         reorganizeFrames( rows, cols, openFrames );
771     }
772     
773     /**
774      * Get a list with all open frames.
775      *
776      * @return Array of all open internal frames
777      */

778     JInternalFrame JavaDoc[] getOpenFrames()
779     {
780         JInternalFrame JavaDoc[] frames = m_desktopPane.getAllFrames();
781         int count = frames.length;
782         
783         // No frames
784
if (count == 0)
785         {
786             // Array is empty, so it is safe to return.
787
return frames;
788         }
789     
790         // add only open frames to the list
791
List JavaDoc openFrames = new ArrayList JavaDoc();
792         for ( int i = 0; i < count; i++ )
793         {
794             JInternalFrame JavaDoc f = frames[i];
795             if( ( f.isClosed() == false ) && ( f.isIcon() == false ) )
796             {
797                 openFrames.add( f );
798             }
799         }
800         
801         // Create a simple array to be returned
802
frames = new JInternalFrame JavaDoc[ openFrames.size() ];
803         openFrames.toArray( frames );
804         
805         return frames;
806     }
807     
808     /**
809      * Reorganizes a list of internal frames to a specific
810      * number of rows and columns.
811      *
812      * @param rows number of rows to use
813      * @param cols number of columns to use
814      * @param frames list with <code>JInternalFrames</code>
815      */

816     void reorganizeFrames( int rows, int cols, JInternalFrame JavaDoc[] frames )
817     {
818         // Determine the size of one windows
819
Dimension JavaDoc desktopsize = m_desktopPane.getSize();
820         int w = desktopsize.width / cols;
821         int h = desktopsize.height / rows;
822         int x = 0;
823         int y = 0;
824         int count = frames.length;
825
826         for ( int i = 0; i < rows; ++i)
827         {
828             for ( int j = 0; j < cols && ( ( i * cols ) + j < count ); ++j )
829             {
830                 JInternalFrame JavaDoc f = frames[ ( i * cols ) + j ];
831                 m_desktopPane.getDesktopManager().resizeFrame( f, x, y, w, h );
832                 x += w;
833             }
834             y += h;
835             x = 0;
836         }
837     }
838     
839     /**
840      * Tiles all internal frames horizontally
841      */

842     void tileFramesH()
843     {
844         JInternalFrame JavaDoc[] openFrames = getOpenFrames();
845         
846         int count = openFrames.length;
847         if ( count == 0 )
848         {
849             return;
850         }
851         reorganizeFrames( count, 1, openFrames );
852     }
853     
854     /**
855      * Tiles all internal frames vertically
856      */

857     void tileFramesV()
858     {
859         JInternalFrame JavaDoc[] openFrames = getOpenFrames();
860         
861         int count=openFrames.length;
862         if ( count == 0)
863         {
864             return;
865         }
866         reorganizeFrames( 1, count, openFrames );
867     }
868     
869     InstrumentManagerConnection[] getConnections()
870     {
871         // Avoid synchronization when possible.
872
InstrumentManagerConnection[] array = m_connectionArray;
873         if ( array == null )
874         {
875             synchronized ( m_connections )
876             {
877                 m_connectionArray = new InstrumentManagerConnection[m_connections.size()];
878                 m_connections.values().toArray( m_connectionArray );
879                 array = m_connectionArray;
880             }
881         }
882         return array;
883     }
884     
885     InstrumentManagerConnection getConnection( URL JavaDoc url )
886     {
887         synchronized ( m_connections )
888         {
889             return (InstrumentManagerConnection)m_connections.get( url );
890         }
891     }
892     
893     void showConnectDialog()
894     {
895         SwingUtilities.invokeLater( new Runnable JavaDoc()
896         {
897             public void run()
898             {
899                 URL JavaDoc defaultURL;
900                 try
901                 {
902                     defaultURL = new URL JavaDoc( "http://localhost:15080" );
903                 }
904                 catch ( MalformedURLException JavaDoc e )
905                 {
906                     // Should never happen.
907
e.printStackTrace();
908                     return;
909                 }
910                 
911                 ConnectDialog dialog = new ConnectDialog( InstrumentClientFrame.this );
912                 dialog.setURL( defaultURL );
913                 dialog.show();
914                 if ( dialog.getAction() == ConnectDialog.BUTTON_OK )
915                 {
916                     synchronized( m_connections )
917                     {
918                         createConnection( dialog.getURL() );
919                     }
920                 }
921             }
922         } );
923     }
924     
925     /**
926      * Creates an registers a new InstrumentManagerConnection. This method
927      * should never be called in the connection already exists. Caller must
928      * ensure that m_connections is synchronized.
929      *
930      * @param url URL of the connecton.
931      *
932      * @return The new InstrumentManagerConnection
933      */

934     private InstrumentManagerConnection createConnection( URL JavaDoc url )
935     {
936         InstrumentManagerConnection conn = new HTTPInstrumentManagerConnection( url );
937         ContainerUtil.enableLogging(
938             conn, getLogger().getChildLogger( url.getHost() + ":" + url.getPort() ) );
939         conn.setFrame( this );
940         conn.init();
941         m_connections.put( conn.getKey(), conn );
942         m_connectionArray = null;
943         
944         conn.addInstrumentManagerConnectionListener( this );
945         
946         m_connectionsPane.add( conn.getTabTitle(), conn );
947         
948         return conn;
949     }
950     
951     private void showErrorDialog( String JavaDoc message )
952     {
953         JOptionPane.showMessageDialog( this,
954                                        "<html><body><font color=\"black\">" + message + "</font>" +
955                                        "</body></html>", m_title + " Error",
956                                        JOptionPane.ERROR_MESSAGE );
957     }
958     
959     private void showErrorDialog( String JavaDoc message, Throwable JavaDoc t )
960     {
961         JOptionPane.showMessageDialog( this,
962                                        "<html><body><font color=\"black\">" + message +
963                                        "</font><br><br><font color=\"black\">Reason: " +
964                                        t.getMessage() + "</font></body></html>",
965                                        m_title + " Error", JOptionPane.ERROR_MESSAGE );
966     }
967
968
969     /**
970      * Shutdown the InstrumentClient.
971      */

972     private void shutdown()
973     {
974         getLogger().debug( "InstrumentClientFrame.shutdown()" );
975         boolean fallThrough = false;
976         if ( m_hook != null )
977         {
978             if ( m_hook == Thread.currentThread() )
979             {
980                 // This is the shutdown hook
981
fallThrough = true;
982             }
983             else
984             {
985                 // Unregister the shutdown hook
986
Runtime.getRuntime().removeShutdownHook( m_hook );
987                 m_hook = null;
988             }
989         }
990         
991         // Delete all of the connections.
992
InstrumentManagerConnection[] connections = getConnections();
993         for ( int i = 0; i < connections.length; i++ )
994         {
995             connections[i].delete();
996         }
997         
998         if ( !fallThrough )
999         {
1000            // Kill the JVM.
1001
System.exit( 1 );
1002        }
1003    }
1004    
1005    /*---------------------------------------------------------------
1006     * Menu Callback Methods
1007     *-------------------------------------------------------------*/

1008    /**
1009     * File->New callback.
1010     */

1011    void fileNew()
1012    {
1013        m_desktopFile = null;
1014        closeAllFrames();
1015        updateTitle();
1016    }
1017    
1018    /**
1019     * File->Open callback.
1020     */

1021    void fileOpen()
1022    {
1023        JFileChooser JavaDoc chooser = new JFileChooser JavaDoc();
1024        
1025        FileFilter JavaDoc filter = new FileFilter JavaDoc()
1026        {
1027            public boolean accept( File JavaDoc f )
1028            {
1029                if( f.isDirectory() )
1030                {
1031                    return true;
1032                }
1033                else
1034                {
1035                    return f.getName().endsWith( ".desktop" );
1036                }
1037            }
1038            
1039            public String JavaDoc getDescription()
1040            {
1041                return "Desktop state files";
1042            }
1043        };
1044        
1045        if ( m_desktopFileDir != null )
1046        {
1047            chooser.setCurrentDirectory( m_desktopFileDir );
1048        }
1049        else
1050        {
1051            chooser.setCurrentDirectory( new File JavaDoc( System.getProperty( "user.dir" ) ) );
1052        }
1053        
1054        chooser.setFileFilter( filter );
1055        
1056        int returnVal = chooser.showOpenDialog( this );
1057        if( returnVal == JFileChooser.APPROVE_OPTION )
1058        {
1059            try
1060            {
1061                m_desktopFile = null;
1062                File JavaDoc file = chooser.getSelectedFile();
1063                m_desktopFileDir = file.getParentFile();
1064                loadStateFromFile( file, true );
1065                m_desktopFile = file;
1066            }
1067            catch( Exception JavaDoc e )
1068            {
1069                String JavaDoc msg = "Unable to load desktop file.";
1070                getLogger().debug( msg, e );
1071                showErrorDialog( msg, e );
1072            }
1073            updateTitle();
1074        }
1075    }
1076    
1077    void fileSave()
1078    {
1079        if( m_desktopFile != null )
1080        {
1081            try
1082            {
1083                saveStateToFile( m_desktopFile );
1084            }
1085            catch( Exception JavaDoc e )
1086            {
1087                String JavaDoc msg = "Unable to save desktop file.";
1088                getLogger().debug( msg, e );
1089                showErrorDialog( msg, e );
1090            }
1091        }
1092        else
1093        {
1094            fileSaveAs();
1095        }
1096    }
1097    
1098    void fileSaveAs()
1099    {
1100        JFileChooser JavaDoc chooser = new JFileChooser JavaDoc();
1101        
1102        FileFilter JavaDoc filter = new FileFilter JavaDoc()
1103        {
1104            public boolean accept( File JavaDoc f )
1105            {
1106                if( f.isDirectory() )
1107                {
1108                    return true;
1109                }
1110                else
1111                {
1112                    return f.getName().endsWith( ".desktop" );
1113                }
1114            }
1115            
1116            public String JavaDoc getDescription()
1117            {
1118                return "Desktop state files";
1119            }
1120        };
1121        
1122        if ( m_desktopFileDir != null )
1123        {
1124            chooser.setCurrentDirectory( m_desktopFileDir );
1125        }
1126        else
1127        {
1128            chooser.setCurrentDirectory( new File JavaDoc( System.getProperty( "user.dir" ) ) );
1129        }
1130        
1131        chooser.setFileFilter( filter );
1132        
1133        int returnVal = chooser.showSaveDialog( this );
1134        if( returnVal == JFileChooser.APPROVE_OPTION )
1135        {
1136            File JavaDoc file = chooser.getSelectedFile();
1137            if( file.getName().indexOf( '.' ) < 0 )
1138            {
1139                // Did not specify an extension. Add one.
1140
file = new File JavaDoc( file.getAbsolutePath() + ".desktop" );
1141            }
1142            
1143            try
1144            {
1145                saveStateToFile( file );
1146                
1147                // If we were able to save the file, then set it as the current
1148
// file.
1149
m_desktopFile = file;
1150                m_desktopFileDir = m_desktopFile.getParentFile();
1151
1152            }
1153            catch( Exception JavaDoc e )
1154            {
1155                String JavaDoc msg = "Unable to save desktop file.";
1156                getLogger().debug( msg, e );
1157                showErrorDialog( msg, e );
1158            }
1159            updateTitle();
1160        }
1161    }
1162    
1163    /**
1164     * File-Exit callback.
1165     */

1166    void fileExit()
1167    {
1168        SwingUtilities.invokeLater( new Runnable JavaDoc()
1169        {
1170            public void run()
1171            {
1172                shutdown();
1173            }
1174        } );
1175    }
1176}
1177
1178
Popular Tags