Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / gnu / java / awt / AWTUtilities.java
blobca7b5511853d2ad62589e863e8cff4f96687278c
1 /* AWTUtilities.java -- Common utility methods for AWT and Swing.
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.java.awt;
40 import java.applet.Applet;
41 import java.awt.Component;
42 import java.awt.Container;
43 import java.awt.Font;
44 import java.awt.FontMetrics;
45 import java.awt.Insets;
46 import java.awt.Point;
47 import java.awt.Rectangle;
48 import java.awt.Toolkit;
49 import java.awt.Window;
50 import java.awt.event.MouseEvent;
51 import java.util.AbstractSequentialList;
52 import java.util.List;
53 import java.util.ListIterator;
54 import java.util.NoSuchElementException;
55 import java.util.WeakHashMap;
56 import java.lang.reflect.InvocationTargetException;
58 /**
59 * This class mirrors the javax.swing.SwingUtilities class. It
60 * provides commonly needed functionalities for AWT classes without
61 * the need to reference classes in the javax.swing package.
63 public class AWTUtilities
66 /**
67 * This List implementation wraps the Component[] returned by
68 * {@link Container#getComponents()} and iterates over the visible Components
69 * in that array. This class is used in {@link #getVisibleChildren}.
71 static class VisibleComponentList extends AbstractSequentialList
73 /**
74 * The ListIterator for this List.
76 class VisibleComponentIterator implements ListIterator
78 /** The current index in the Component[]. */
79 int index;
81 /** The index in the List of visible Components. */
82 int listIndex;
84 /**
85 * Creates a new VisibleComponentIterator that starts at the specified
86 * <code>listIndex</code>. The array of Components is searched from
87 * the beginning to find the matching array index.
89 * @param listIndex the index from where to begin iterating
91 VisibleComponentIterator(int listIndex)
93 this.listIndex = listIndex;
94 int visibleComponentsFound = 0;
95 for (index = 0; visibleComponentsFound != listIndex; index++)
97 if (components[index].isVisible())
98 visibleComponentsFound++;
103 * Returns <code>true</code> if there are more visible components in the
104 * array, <code>false</code> otherwise.
106 * @return <code>true</code> if there are more visible components in the
107 * array, <code>false</code> otherwise
109 public boolean hasNext()
111 boolean hasNext = false;
112 for (int i = index; i < components.length; i++)
114 if (components[i].isVisible())
116 hasNext = true;
117 break;
120 return hasNext;
124 * Returns the next visible <code>Component</code> in the List.
126 * @return the next visible <code>Component</code> in the List
128 * @throws if there is no next element
130 public Object next()
132 Object o = null;
133 for (; index < components.length; index++)
135 if (components[index].isVisible())
137 o = components[index];
138 break;
141 if (o != null)
143 index++;
144 listIndex++;
145 return o;
147 else
148 throw new NoSuchElementException();
152 * Returns <code>true</code> if there are more visible components in the
153 * array in the reverse direction, <code>false</code> otherwise.
155 * @return <code>true</code> if there are more visible components in the
156 * array in the reverse direction, <code>false</code> otherwise
158 public boolean hasPrevious()
160 boolean hasPrevious = false;
161 for (int i = index - 1; i >= 0; i--)
163 if (components[i].isVisible())
165 hasPrevious = true;
166 break;
169 return hasPrevious;
173 * Returns the previous visible <code>Component</code> in the List.
175 * @return the previous visible <code>Component</code> in the List
177 * @throws NoSuchElementException if there is no previous element
179 public Object previous()
181 Object o = null;
182 for (index--; index >= 0; index--)
184 if (components[index].isVisible())
186 o = components[index];
187 break;
190 if (o != null)
192 listIndex--;
193 return o;
195 else
196 throw new NoSuchElementException();
200 * Returns the index of the next element in the List.
202 * @return the index of the next element in the List
204 public int nextIndex()
206 return listIndex + 1;
210 * Returns the index of the previous element in the List.
212 * @return the index of the previous element in the List
214 public int previousIndex()
216 return listIndex - 1;
220 * This operation is not supported because the List is immutable.
222 * @throws UnsupportedOperationException because the List is immutable
224 public void remove()
226 throw new UnsupportedOperationException
227 ("VisibleComponentList is immutable");
231 * This operation is not supported because the List is immutable.
233 * @param o not used here
235 * @throws UnsupportedOperationException because the List is immutable
237 public void set(Object o)
239 throw new UnsupportedOperationException
240 ("VisibleComponentList is immutable");
244 * This operation is not supported because the List is immutable.
246 * @param o not used here
248 * @throws UnsupportedOperationException because the List is immutable
250 public void add(Object o)
252 throw new UnsupportedOperationException
253 ("VisibleComponentList is immutable");
258 * The components over which we iterate. Only the visible components
259 * are returned by this List.
261 Component[] components;
264 * Creates a new instance of VisibleComponentList that wraps the specified
265 * <code>Component[]</code>.
267 * @param c the <code>Component[]</code> to be wrapped.
269 VisibleComponentList(Component[] c)
271 components = c;
275 * Returns a {@link ListIterator} for iterating over this List.
277 * @return a {@link ListIterator} for iterating over this List
279 public ListIterator listIterator(int index)
281 return new VisibleComponentIterator(index);
285 * Returns the number of visible components in the wrapped Component[].
287 * @return the number of visible components
289 public int size()
291 int visibleComponents = 0;
292 for (int i = 0; i < components.length; i++)
293 if (components[i].isVisible())
294 visibleComponents++;
295 return visibleComponents;
300 * The cache for our List instances. We try to hold one instance of
301 * VisibleComponentList for each Component[] that is requested. Note
302 * that we use a WeakHashMap for caching, so that the cache itself
303 * does not keep the array or the List from beeing garbage collected
304 * if no other objects hold references to it.
306 static WeakHashMap visibleChildrenCache = new WeakHashMap();
309 * Returns the visible children of a {@link Container}. This method is
310 * commonly needed in LayoutManagers, because they only have to layout
311 * the visible children of a Container.
313 * @param c the Container from which to extract the visible children
315 * @return the visible children of <code>c</code>
317 public static List getVisibleChildren(Container c)
319 Component[] children = c.getComponents();
320 Object o = visibleChildrenCache.get(children);
321 VisibleComponentList visibleChildren = null;
322 if (o == null)
324 visibleChildren = new VisibleComponentList(children);
325 visibleChildrenCache.put(children, visibleChildren);
327 else
328 visibleChildren = (VisibleComponentList) o;
330 return visibleChildren;
334 * Calculates the portion of the base rectangle which is inside the
335 * insets.
337 * @param base The rectangle to apply the insets to
338 * @param insets The insets to apply to the base rectangle
339 * @param ret A rectangle to use for storing the return value, or
340 * <code>null</code>
342 * @return The calculated area inside the base rectangle and its insets,
343 * either stored in ret or a new Rectangle if ret is <code>null</code>
345 * @see #calculateInnerArea
347 public static Rectangle calculateInsetArea(Rectangle base, Insets insets,
348 Rectangle ret)
350 if (ret == null)
351 ret = new Rectangle();
352 ret.setBounds(base.x + insets.left, base.y + insets.top,
353 base.width - (insets.left + insets.right),
354 base.height - (insets.top + insets.bottom));
355 return ret;
359 * Calculates the bounds of a component in the component's own coordinate
360 * space. The result has the same height and width as the component's
361 * bounds, but its location is set to (0,0).
363 * @param aComponent The component to measure
365 * @return The component's bounds in its local coordinate space
367 public static Rectangle getLocalBounds(Component aComponent)
369 Rectangle bounds = aComponent.getBounds();
370 return new Rectangle(0, 0, bounds.width, bounds.height);
374 * Returns the font metrics object for a given font. The metrics can be
375 * used to calculate crude bounding boxes and positioning information,
376 * for laying out components with textual elements.
378 * @param font The font to get metrics for
380 * @return The font's metrics
382 * @see java.awt.font.GlyphMetrics
384 public static FontMetrics getFontMetrics(Font font)
386 return Toolkit.getDefaultToolkit().getFontMetrics(font);
390 * Returns the least ancestor of <code>comp</code> which has the
391 * specified name.
393 * @param name The name to search for
394 * @param comp The component to search the ancestors of
396 * @return The nearest ancestor of <code>comp</code> with the given
397 * name, or <code>null</code> if no such ancestor exists
399 * @see java.awt.Component#getName
400 * @see #getAncestorOfClass
402 public static Container getAncestorNamed(String name, Component comp)
404 while (comp != null && (comp.getName() != name))
405 comp = comp.getParent();
406 return (Container) comp;
410 * Returns the least ancestor of <code>comp</code> which is an instance
411 * of the specified class.
413 * @param c The class to search for
414 * @param comp The component to search the ancestors of
416 * @return The nearest ancestor of <code>comp</code> which is an instance
417 * of the given class, or <code>null</code> if no such ancestor exists
419 * @see #getAncestorOfClass
420 * @see #windowForComponent
421 * @see
424 public static Container getAncestorOfClass(Class c, Component comp)
426 while (comp != null && (! c.isInstance(comp)))
427 comp = comp.getParent();
428 return (Container) comp;
432 * Equivalent to calling <code>getAncestorOfClass(Window, comp)</code>.
434 * @param comp The component to search for an ancestor window
436 * @return An ancestral window, or <code>null</code> if none exists
438 public static Window windowForComponent(Component comp)
440 return (Window) getAncestorOfClass(Window.class, comp);
444 * Returns the "root" of the component tree containint <code>comp</code>
445 * The root is defined as either the <em>least</em> ancestor of
446 * <code>comp</code> which is a {@link Window}, or the <em>greatest</em>
447 * ancestor of <code>comp</code> which is a {@link Applet} if no {@link
448 * Window} ancestors are found.
450 * @param comp The component to search for a root
452 * @return The root of the component's tree, or <code>null</code>
454 public static Component getRoot(Component comp)
456 Applet app = null;
457 Window win = null;
459 while (comp != null)
461 if (win == null && comp instanceof Window)
462 win = (Window) comp;
463 else if (comp instanceof Applet)
464 app = (Applet) comp;
465 comp = comp.getParent();
468 if (win != null)
469 return win;
470 else
471 return app;
475 * Return true if a descends from b, in other words if b is an
476 * ancestor of a.
478 * @param a The child to search the ancestry of
479 * @param b The potential ancestor to search for
481 * @return true if a is a descendent of b, false otherwise
483 public static boolean isDescendingFrom(Component a, Component b)
485 while (true)
487 if (a == null || b == null)
488 return false;
489 if (a == b)
490 return true;
491 a = a.getParent();
496 * Returns the deepest descendent of parent which is both visible and
497 * contains the point <code>(x,y)</code>. Returns parent when either
498 * parent is not a container, or has no children which contain
499 * <code>(x,y)</code>. Returns <code>null</code> when either
500 * <code>(x,y)</code> is outside the bounds of parent, or parent is
501 * <code>null</code>.
503 * @param parent The component to search the descendents of
504 * @param x Horizontal coordinate to search for
505 * @param y Vertical coordinate to search for
507 * @return A component containing <code>(x,y)</code>, or
508 * <code>null</code>
510 * @see java.awt.Container#findComponentAt
512 public static Component getDeepestComponentAt(Component parent, int x, int y)
514 if (parent == null || (! parent.contains(x, y)))
515 return null;
517 if (! (parent instanceof Container))
518 return parent;
520 Container c = (Container) parent;
521 return c.findComponentAt(x, y);
525 * Converts a point from a component's local coordinate space to "screen"
526 * coordinates (such as the coordinate space mouse events are delivered
527 * in). This operation is equivalent to translating the point by the
528 * location of the component (which is the origin of its coordinate
529 * space).
531 * @param p The point to convert
532 * @param c The component which the point is expressed in terms of
534 * @see convertPointFromScreen
536 public static void convertPointToScreen(Point p, Component c)
538 Point c0 = c.getLocationOnScreen();
539 p.translate(c0.x, c0.y);
543 * Converts a point from "screen" coordinates (such as the coordinate
544 * space mouse events are delivered in) to a component's local coordinate
545 * space. This operation is equivalent to translating the point by the
546 * negation of the component's location (which is the origin of its
547 * coordinate space).
549 * @param p The point to convert
550 * @param c The component which the point should be expressed in terms of
552 public static void convertPointFromScreen(Point p, Component c)
554 Point c0 = c.getLocationOnScreen();
555 p.translate(-c0.x, -c0.y);
559 * Converts a point <code>(x,y)</code> from the coordinate space of one
560 * component to another. This is equivalent to converting the point from
561 * <code>source</code> space to screen space, then back from screen space
562 * to <code>destination</code> space. If exactly one of the two
563 * Components is <code>null</code>, it is taken to refer to the root
564 * ancestor of the other component. If both are <code>null</code>, no
565 * transformation is done.
567 * @param source The component which the point is expressed in terms of
568 * @param x Horizontal coordinate of point to transform
569 * @param y Vertical coordinate of point to transform
570 * @param destination The component which the return value will be
571 * expressed in terms of
573 * @return The point <code>(x,y)</code> converted from the coordinate
574 * space of the
575 * source component to the coordinate space of the destination component
577 * @see #convertPointToScreen
578 * @see #convertPointFromScreen
579 * @see #convertRectangle
580 * @see #getRoot
582 public static Point convertPoint(Component source, int x, int y,
583 Component destination)
585 Point pt = new Point(x, y);
587 if (source == null && destination == null)
588 return pt;
590 if (source == null)
591 source = getRoot(destination);
593 if (destination == null)
594 destination = getRoot(source);
596 if (source.isShowing() && destination.isShowing())
598 convertPointToScreen(pt, source);
599 convertPointFromScreen(pt, destination);
602 return pt;
607 * Converts a rectangle from the coordinate space of one component to
608 * another. This is equivalent to converting the rectangle from
609 * <code>source</code> space to screen space, then back from screen space
610 * to <code>destination</code> space. If exactly one of the two
611 * Components is <code>null</code>, it is taken to refer to the root
612 * ancestor of the other component. If both are <code>null</code>, no
613 * transformation is done.
615 * @param source The component which the rectangle is expressed in terms of
616 * @param rect The rectangle to convert
617 * @param destination The component which the return value will be
618 * expressed in terms of
620 * @return A new rectangle, equal in size to the input rectangle, but
621 * with its position converted from the coordinate space of the source
622 * component to the coordinate space of the destination component
624 * @see #convertPointToScreen
625 * @see #convertPointFromScreen
626 * @see #convertPoint
627 * @see #getRoot
629 public static Rectangle convertRectangle(Component source, Rectangle rect,
630 Component destination)
632 Point pt = convertPoint(source, rect.x, rect.y, destination);
633 return new Rectangle(pt.x, pt.y, rect.width, rect.height);
637 * Convert a mouse event which refrers to one component to another. This
638 * includes changing the mouse event's coordinate space, as well as the
639 * source property of the event. If <code>source</code> is
640 * <code>null</code>, it is taken to refer to <code>destination</code>'s
641 * root component. If <code>destination</code> is <code>null</code>, the
642 * new event will remain expressed in <code>source</code>'s coordinate
643 * system.
645 * @param source The component the mouse event currently refers to
646 * @param sourceEvent The mouse event to convert
647 * @param destination The component the new mouse event should refer to
649 * @return A new mouse event expressed in terms of the destination
650 * component's coordinate space, and with the destination component as
651 * its source
653 * @see #convertPoint
655 public static MouseEvent convertMouseEvent(Component source,
656 MouseEvent sourceEvent,
657 Component destination)
659 Point newpt = convertPoint(source, sourceEvent.getX(), sourceEvent.getY(),
660 destination);
662 return new MouseEvent(destination, sourceEvent.getID(),
663 sourceEvent.getWhen(), sourceEvent.getModifiers(),
664 newpt.x, newpt.y, sourceEvent.getClickCount(),
665 sourceEvent.isPopupTrigger(),
666 sourceEvent.getButton());
670 /**
671 * Calls {@link java.awt.EventQueue.invokeLater} with the
672 * specified {@link Runnable}.
674 public static void invokeLater(Runnable doRun)
676 java.awt.EventQueue.invokeLater(doRun);
679 /**
680 * Calls {@link java.awt.EventQueue.invokeAndWait} with the
681 * specified {@link Runnable}.
683 public static void invokeAndWait(Runnable doRun)
684 throws InterruptedException,
685 InvocationTargetException
687 java.awt.EventQueue.invokeAndWait(doRun);
690 /**
691 * Calls {@link java.awt.EventQueue.isEventDispatchThread}.
693 public static boolean isEventDispatchThread()
695 return java.awt.EventQueue.isDispatchThread();