1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
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
113
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
125 {
126 place( aWindow, CENTER );
127 return;
128 }
129 Point parentLocation = (((Dialog)aWindow).getParent()).getLocation();
130
131 Dimension parentSize = (((Dialog)aWindow).getParent()).getSize();
132
133
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
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 {
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
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
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521