View Javadoc

1   /*
2   Wotonomy: OpenStep design patterns for pure Java applications.
3   Copyright (C) 2000 Michael Powers
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, see http://www.gnu.org
17  */
18  
19  package net.wotonomy.ui.swing.util;
20  
21  import java.awt.Component;
22  import java.awt.Container;
23  import java.awt.Dialog;
24  import java.awt.Dimension;
25  import java.awt.Point;
26  import java.awt.Toolkit;
27  import java.awt.Window;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.Collections;
31  import java.util.HashMap;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  
36  /***
37  * A collection of window-related utilities.
38  *
39  * @author michael@mpowers.net
40  * @author $Author: cgruber $
41  * @version $Revision: 904 $
42  * $Date: 2006-02-18 23:19:05 +0000 (Sat, 18 Feb 2006) $
43  *
44  */
45  public class WindowUtilities
46  {
47  
48  /***
49  * Place frame at center (vertically and horizontally) of screen.
50  */
51      public static final int CENTER = 0;
52  
53  /***
54  * Center dialog on frame area of parent, if any.
55  */
56      public static final int CENTER_PARENT = 1;
57  
58  /***
59  * Place lower and to the right of the last window
60  * placed in this manner.  Will wrap to top and left
61  * of screen as necessary.
62  */
63      public static final int CASCADE = 10;
64  
65      // cascade state
66      private static int lastX = 0;
67      private static int lastY = 0;
68      private static int incrementX = 20;
69      private static int incrementY = 20;
70  
71  /***
72  * Place the window in the center of the screen.
73  * Note: don't forget to first set the size of your window.
74  * This is a convenience method and simply calls place() with
75  * the CENTER parameter.
76  * @param aWindow The window to be centered.
77  * @see #place
78  */
79      public static void center( Window aWindow )
80      {
81          place( aWindow, CENTER );
82      }
83  
84  /***
85  * Place lower and to the right of the last window
86  * placed in this manner.  Will wrap to top and left
87  * of screen as necessary.
88  * This is a convenience method and simply calls place() with
89  * the CASCADE parameter.
90  * @param aWindow The window to be cascaded.
91  * @see #place
92  */
93      public static void cascade( Window aWindow )
94      {
95          place( aWindow, CASCADE );
96      }
97  
98  /***
99  * Place the window in the specified location.
100 * Note: don't forget to first set the size of your window.
101 * @param aWindow The window to be placed.
102 * @param location Where on screen to place the frame.
103 */
104     public static void place( Window aWindow, int location)
105     {
106         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
107         Dimension mySize = aWindow.getSize();
108         int x = (aWindow.getLocation()).x;
109         int y = (aWindow.getLocation()).y;
110         float aspectRatio = (float)screenSize.height/(float)screenSize.width;
111 
112         // hack to make windows appear on left monitor if dual monitor
113         // if aspect ratio is less than 0.6, assume dual monitor
114         if (aspectRatio < 0.6)
115         {
116             screenSize.width = screenSize.width/2;
117         }
118 
119         switch (location)
120         {
121           case CENTER_PARENT:
122                   if ( ( ! ( aWindow instanceof Dialog ) )
123                   ||  ( ((Dialog)aWindow).getParent() == null ) )
124 //1.2                  ||  ( ((Dialog)aWindow).getOwner() == null ) )
125                   {
126                     place( aWindow, CENTER );
127                     return;
128                   }
129                   Point parentLocation = (((Dialog)aWindow).getParent()).getLocation();
130 //1.2 (((Dialog)aWindow).getOwner()).getLocation();
131                   Dimension parentSize = (((Dialog)aWindow).getParent()).getSize();
132 
133 //1.2                  Dimension parentSize = (((Dialog)aWindow).getOwner()).getSize();
134 
135                   if (parentSize.width > mySize.width)
136                   {
137                     x = ((parentSize.width - mySize.width)/2) + parentLocation.x;
138                   }
139                   if (parentSize.height > mySize.height)
140                   {
141                     y = ((parentSize.height - mySize.height)/2) + parentLocation.y;
142                   }
143                   break;
144           case CENTER:
145                   if (screenSize.width > mySize.width)
146                   {
147                     x = (screenSize.width - mySize.width)/2;
148                   }
149                   if (screenSize.height > mySize.height)
150                   {
151                     y = (screenSize.height - mySize.height)/2;
152                   }
153                   break;
154           case CASCADE:
155                   x = lastX + incrementX;
156                   if ( x + mySize.width > screenSize.width )
157                   {
158                     x = incrementX;
159                   }
160                   y = lastY + incrementY;
161                   if ( y + mySize.height > screenSize.height )
162                   {
163                     y = incrementY;
164                   }
165                   lastX = x;
166                   lastY = y;
167                   break;
168           default:
169                   // don't move the frame
170                   Point p = aWindow.getLocation();
171                   x = p.x;
172                   y = p.y;
173                   break;
174         }
175         aWindow.setLocation(x,y);
176     }
177 
178 /***
179  * Returns the first parent Window of the specified component.
180  *
181  * @param c the Component whose parent will be found.
182  * @return the Window that contains the component,
183  * or null if the component does not have a valid Frame parent.
184  */
185     public static Window getWindowForComponent(Component c)
186     {
187         for(Component p = c; p != null; p = p.getParent()) {
188             if (p instanceof Window) {
189                 return (Window) p;
190             }
191         }
192         return null;
193     }
194 
195 
196 
197 /***
198 * Prints out a list of all components to System.out.
199 * @param aContainer the Container whose components will be listed.
200 */
201     public static void dumpComponents( Container aContainer )
202     {
203         dumpComponents( aContainer, "" );
204     }
205 
206     protected static void dumpComponents( Container aContainer, String padding )
207     {
208         Component c = null;
209         int count = aContainer.getComponentCount();
210         for ( int i = 0; i < count; i++ )
211         {
212             c = aContainer.getComponent( i );
213             if ( c instanceof javax.swing.JComponent )
214             {
215                 System.out.println( padding + c.getClass() + ": "
216                     + ((javax.swing.JComponent)c).getAccessibleContext().getAccessibleName() );
217             }
218             else
219             {
220                 System.out.println( padding + c.getClass() + ": " + c.getName() );
221             }
222             if ( c instanceof Container )
223             {
224                 dumpComponents( (Container) c, padding + "     " );
225             }
226         }
227     }
228 
229 /***
230 * Gets a list of all children of a specified container, sorted by position.
231 * Components are sorted from top to bottom and then left to right.
232 * @param aContainer The container whose children are to be returned.
233 * @result A List containing the sorted components.
234 */
235     public static List getSortedChildComponents( Container aContainer )
236     {
237         List result = new ArrayList( getAllChildComponents( aContainer ) );
238         Collections.sort( result, new PositionComparator( aContainer ) );
239         return result;
240     }
241 
242     public static void dumpSortedChildComponents( Container aContainer )
243     {
244         Component c = null;
245         Iterator it = getSortedChildComponents( aContainer ).iterator();
246         while ( it.hasNext() )
247         {
248             c = (Component) it.next();
249             System.out.println( c.getLocation() + " : " + c.getClass()  );
250         }
251     }
252 
253     public static void dumpNamedChildComponents( Container aContainer )
254     {
255         Iterator it = getUniqueNameMap( getSortedChildComponents( aContainer ) ).values().iterator();
256         while ( it.hasNext() )
257         {
258             System.out.println( it.next() );
259         }
260     }
261 
262 /***
263 * Generates a unique name for each object in a list and returns
264 * a map that maps the objects to the names.  The name is based
265 * on the class of the object in the object list.
266 * @param anObjectList A List of objects.
267 * @return A Map that maps the objects in the list to the generated names.
268 */
269     public static Map getUniqueNameMap( List anObjectList )
270     {
271         Map namesToObjects = new HashMap(anObjectList.size(), 1F);
272         Map objectsToNames = new HashMap(anObjectList.size(), 1F);
273 
274         Object o = null;
275         String name = null;
276         int lastIndex = 0;
277         Iterator it = anObjectList.iterator();
278         while ( it.hasNext() )
279         {
280             o = it.next();
281             name = o.getClass().getName();
282             lastIndex = name.lastIndexOf( "." );
283             if ( lastIndex != -1 )
284             {
285                 name = name.substring( lastIndex+1 );
286             }
287             name = incrementString( name );
288             while ( namesToObjects.get( name ) != null )
289             {
290                 name = incrementString( name );
291             }
292             namesToObjects.put( name, o );
293             objectsToNames.put( o, name );
294         }
295 
296         return objectsToNames;
297     }
298 
299 /***
300 * Numerically increments a string.  For example, "hello" becomes "hello1"
301 * and "hello1" becomes "hello2" while "hello999" becomes "hello1000".
302 * @param aString a String to be incremented.
303 * @return The incremented String.
304 */
305     public static String incrementString( String aString )
306     {
307         int i = aString.length()-1;
308         while ( ( i >= 0 ) && ( Character.isDigit( aString.charAt( i ) ) ) )
309         {
310             i--;
311         }
312 
313         if ( i == aString.length()-1 )
314         { // no numerics at end of string, increment manually
315             return aString + "1";
316         }
317 
318         String alpha = aString.substring( 0, i+1 );
319         String numeric = aString.substring( i+1 );
320         numeric = Integer.toString( Integer.parseInt( numeric ) + 1 );
321 
322         return alpha + numeric;
323 
324     }
325 
326 /***
327 * Gets all children of the specified container.
328 * @param aContainer the Container to be searched.
329 * @return A Collection containing all of the child components of the container.
330 */
331     public static Collection getAllChildComponents( Container aContainer )
332     {
333         Collection result = new ArrayList();
334         addAllChildComponents( aContainer, result );
335         return result;
336     }
337 
338 /***
339 * Adds all children of the specified container to the specified collection.
340 * @param aContainer the Container to be searched.
341 * @param aCollection the Collection to which the child components will be added.
342 */
343     protected static void addAllChildComponents( Container aContainer, Collection aCollection )
344     {
345         Component c = null;
346         int count = aContainer.getComponentCount();
347         for ( int i = 0; i < count; i++ )
348         {
349             c = aContainer.getComponent( i );
350             aCollection.add( c );
351             if ( c instanceof Container )
352             {
353                 addAllChildComponents( (Container) c, aCollection );
354             }
355         }
356     }
357 
358 /***
359 * Sets each child component's tooltip to show the name generated from
360 * getComponentNameMap(). 
361 * (We're doing this so the tooltip authors can know how to reference
362 * the components.)
363 * @param aContainer the Container whose components will be labeled.
364 */
365     public static void labelComponents( Container aContainer )
366     {
367         Map nameToComponent = getNameToComponentMap( aContainer );
368         Map nameToName = new HashMap(nameToComponent.size(), 1F);
369         Iterator it = nameToComponent.keySet().iterator();
370         String key;
371         while ( it.hasNext() )
372         {
373             key = it.next().toString();
374             nameToName.put( key, key );
375         }
376         labelComponents( aContainer, nameToName );
377     }
378 
379 /***
380 * Sets each child component's tooltip to show a given string retrieved
381 * from a map using the component's generated name as a key.
382 * @param aContainer the Container whose components will be labeled.
383 * @param aNameMap a Map of generated names to string values.
384 */
385     public static void labelComponents( Container aContainer, Map aNameMap )
386     {
387         if ( aNameMap == null ) return;
388 
389         String key;
390         Object o ;
391         Iterator it = aNameMap.keySet().iterator();
392         Map nameToComponent = getNameToComponentMap( aContainer );
393         while ( it.hasNext() )
394         {
395             key = it.next().toString();
396             o = nameToComponent.get( key );
397             if ( o instanceof javax.swing.JComponent )
398             {
399                 ((javax.swing.JComponent)o).setToolTipText( aNameMap.get( key ).toString() );
400             }
401         }
402     }
403 
404 /***
405 * Generates a deterministically unique name for each component in a
406 * container.  The name is based on the name of the class of the component
407 * followed by a number.  Each class of component is numbered based on it's
408 * position in the container, sorted from top to bottom and left to right.
409 * @param aContainer the Container whose components will named.
410 * @return a Map that maps each component to its name.
411 */
412     public static Map getComponentToNameMap( Container aContainer )
413     {
414         return getUniqueNameMap( getSortedChildComponents( aContainer ) );
415     }
416 
417 /***
418 * Maps a deterministically unique name to a component in a
419 * container.  The name is based on the name of the class of the component
420 * followed by a number.  Each class of component is numbered based on it's
421 * position in the container, sorted from top to bottom and left to right.
422 * @param aContainer the Container whose components will named.
423 * @return a Map that maps each component to its name.
424 */
425     public static Map getNameToComponentMap( Container aContainer )
426     {
427         Map componentToName = getComponentToNameMap( aContainer );
428         Map result = new HashMap(componentToName.size(), 1F);
429         Iterator it = componentToName.keySet().iterator();
430         Object key;
431         while ( it.hasNext() )
432         {
433             key = it.next();
434             result.put( componentToName.get( key ), key );
435         }
436         return result;
437     }
438 
439 /***
440 * Sets the tooltips of all components in a container to the
441 * respective names of those components.  (We're using this
442 * so the tooltip authors can know how to reference the components.)
443 * @param aContainer the Container whose components will be labeled.
444 */
445     public static void nameComponents( Container aContainer )
446     {
447         nameComponents( aContainer, "" );
448     }
449 
450     protected static void nameComponents( Container aContainer, String path )
451     {
452         Component c = null;
453         String className = null;
454         int index = 0;
455         int count = aContainer.getComponentCount();
456         for ( int i = 0; i < count; i++ )
457         {
458             c = aContainer.getComponent( i );
459             className = c.getClass().getName();
460             className = className.substring( className.lastIndexOf( '.' ) + 1 );
461             System.out.println( path + className );
462             if ( c instanceof javax.swing.JComponent )
463             {
464                 // ((javax.swing.JComponent)c).setToolTipText( path + className + " (" + c.getName() + ")" );
465                 ((javax.swing.JComponent)c).setToolTipText( c.getName() );
466             }
467             if ( c instanceof Container )
468             {
469                 nameComponents( (Container) c, path + className + "." );
470             }
471         }
472     }
473 
474 /***
475 * Sets the enabled state of a container and all of its components.
476 * @param aContainer the Container whose components will be enabled.
477 * @param isEnabled True if enabled, false id disabled.
478 */
479     public static void enableComponents( Container aContainer, boolean isEnabled )
480     {
481         Component c = null;
482         String className = null;
483         int index = 0;
484         int count = aContainer.getComponentCount();
485         for ( int i = 0; i < count; i++ )
486         {
487             c = aContainer.getComponent( i );
488             if ( c instanceof Container )
489             {
490                 enableComponents( (Container) c, isEnabled );
491             }
492             else
493             {
494                 c.setEnabled( isEnabled );
495             }
496         }
497         aContainer.setEnabled( isEnabled );
498     }
499 
500 }
501 
502 /*
503  * $Log$
504  * Revision 1.2  2006/02/18 23:19:05  cgruber
505  * Update imports and maven dependencies.
506  *
507  * Revision 1.1  2006/02/16 13:22:22  cgruber
508  * Check in all sources in eclipse-friendly maven-enabled packages.
509  *
510  * Revision 1.2  2001/02/17 16:52:05  mpowers
511  * Changes in imports to support building with jdk1.1 collections.
512  *
513  * Revision 1.1.1.1  2000/12/21 15:51:55  mpowers
514  * Contributing wotonomy.
515  *
516  * Revision 1.2  2000/12/20 16:25:46  michael
517  * Added log to all files.
518  *
519  *
520  */
521