OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [SwingUtilities.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* SwingUtilities.java --
2
   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
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.
10
 
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.
15
 
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.
20
 
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.
25
 
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. */
37
 
38
 
39
package javax.swing;
40
 
41
import java.applet.Applet;
42
import java.awt.Component;
43
import java.awt.ComponentOrientation;
44
import java.awt.Container;
45
import java.awt.FontMetrics;
46
import java.awt.Frame;
47
import java.awt.Graphics;
48
import java.awt.Insets;
49
import java.awt.KeyboardFocusManager;
50
import java.awt.Point;
51
import java.awt.Rectangle;
52
import java.awt.Shape;
53
import java.awt.Window;
54
import java.awt.event.ActionEvent;
55
import java.awt.event.InputEvent;
56
import java.awt.event.KeyEvent;
57
import java.awt.event.MouseEvent;
58
import java.lang.reflect.InvocationTargetException;
59
 
60
import javax.accessibility.Accessible;
61
import javax.accessibility.AccessibleStateSet;
62
import javax.swing.plaf.ActionMapUIResource;
63
import javax.swing.plaf.InputMapUIResource;
64
 
65
/**
66
 * A number of static utility functions which are
67
 * useful when drawing swing components, dispatching events, or calculating
68
 * regions which need painting.
69
 *
70
 * @author Graydon Hoare (graydon@redhat.com)
71
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
72
 */
73
public class SwingUtilities
74
  implements SwingConstants
75
{
76
  /**
77
   * This frame should be used as parent for JWindow or JDialog
78
   * that doesn't an owner
79
   */
80
  private static OwnerFrame ownerFrame;
81
 
82
  private SwingUtilities()
83
  {
84
    // Do nothing.
85
  }
86
 
87
  /**
88
   * Calculates the portion of the base rectangle which is inside the
89
   * insets.
90
   *
91
   * @param base The rectangle to apply the insets to
92
   * @param insets The insets to apply to the base rectangle
93
   * @param ret A rectangle to use for storing the return value, or
94
   * <code>null</code>
95
   *
96
   * @return The calculated area inside the base rectangle and its insets,
97
   * either stored in ret or a new Rectangle if ret is <code>null</code>
98
   *
99
   * @see #calculateInnerArea
100
   */
101
  public static Rectangle calculateInsetArea(Rectangle base, Insets insets,
102
                                             Rectangle ret)
103
  {
104
    if (ret == null)
105
      ret = new Rectangle();
106
    ret.setBounds(base.x + insets.left, base.y + insets.top,
107
                  base.width - (insets.left + insets.right),
108
                  base.height - (insets.top + insets.bottom));
109
    return ret;
110
  }
111
 
112
  /**
113
   * Calculates the portion of the component's bounds which is inside the
114
   * component's border insets. This area is usually the area a component
115
   * should confine its painting to. The coordinates are returned in terms
116
   * of the <em>component's</em> coordinate system, where (0,0) is the
117
   * upper left corner of the component's bounds.
118
   *
119
   * @param c The component to measure the bounds of
120
   * @param r A Rectangle to store the return value in, or
121
   * <code>null</code>
122
   *
123
   * @return The calculated area inside the component and its border
124
   * insets
125
   *
126
   * @see #calculateInsetArea
127
   */
128
  public static Rectangle calculateInnerArea(JComponent c, Rectangle r)
129
  {
130
    Rectangle b = getLocalBounds(c);
131
    return calculateInsetArea(b, c.getInsets(), r);
132
  }
133
 
134
  /**
135
   * Returns the focus owner or <code>null</code> if <code>comp</code> is not
136
   * the focus owner or a parent of it.
137
   *
138
   * @param comp the focus owner or a parent of it
139
   *
140
   * @return the focus owner, or <code>null</code>
141
   *
142
   * @deprecated 1.4 Replaced by
143
   * <code>KeyboardFocusManager.getFocusOwner()</code>.
144
   */
145
  public static Component findFocusOwner(Component comp)
146
  {
147
    // Get real focus owner.
148
    Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager()
149
                                               .getFocusOwner();
150
 
151
    // Check if comp is the focus owner or a parent of it.
152
    Component tmp = focusOwner;
153
 
154
    while (tmp != null)
155
      {
156
        if (tmp == comp)
157
          return focusOwner;
158
 
159
        tmp = tmp.getParent();
160
      }
161
 
162
    return null;
163
  }
164
 
165
  /**
166
   * Returns the <code>Accessible</code> child of the specified component
167
   * which appears at the supplied <code>Point</code>.  If there is no
168
   * child located at that particular pair of co-ordinates, null is returned
169
   * instead.
170
   *
171
   * @param c the component whose children may be found at the specified
172
   *          point.
173
   * @param p the point at which to look for the existence of children
174
   *          of the specified component.
175
   * @return the <code>Accessible</code> child at the point, <code>p</code>,
176
   *         or null if there is no child at this point.
177
   * @see javax.accessibility.AccessibleComponent#getAccessibleAt
178
   */
179
  public static Accessible getAccessibleAt(Component c, Point p)
180
  {
181
    return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p);
182
  }
183
 
184
  /**
185
   * <p>
186
   * Returns the <code>Accessible</code> child of the specified component
187
   * that has the supplied index within the parent component.  The indexing
188
   * of the children is zero-based, making the first child have an index of
189
   * 0.
190
   * </p>
191
   * <p>
192
   * Caution is advised when using this method, as its operation relies
193
   * on the behaviour of varying implementations of an abstract method.
194
   * For greater surety, direct use of the AWT component implementation
195
   * of this method is advised.
196
   * </p>
197
   *
198
   * @param c the component whose child should be returned.
199
   * @param i the index of the child within the parent component.
200
   * @return the <code>Accessible</code> child at index <code>i</code>
201
   *         in the component, <code>c</code>.
202
   * @see javax.accessibility.AccessibleContext#getAccessibleChild
203
   * @see java.awt.Component.AccessibleAWTComponent#getAccessibleChild
204
   */
205
  public static Accessible getAccessibleChild(Component c, int i)
206
  {
207
    return c.getAccessibleContext().getAccessibleChild(i);
208
  }
209
 
210
  /**
211
   * <p>
212
   * Returns the number of <code>Accessible</code> children within
213
   * the supplied component.
214
   * </p>
215
   * <p>
216
   * Caution is advised when using this method, as its operation relies
217
   * on the behaviour of varying implementations of an abstract method.
218
   * For greater surety, direct use of the AWT component implementation
219
   * of this method is advised.
220
   * </p>
221
   *
222
   * @param c the component whose children should be counted.
223
   * @return the number of children belonging to the component,
224
   *         <code>c</code>.
225
   * @see javax.accessibility.AccessibleContext#getAccessibleChildrenCount
226
   * @see java.awt.Component.AccessibleAWTComponent#getAccessibleChildrenCount
227
   */
228
  public static int getAccessibleChildrenCount(Component c)
229
  {
230
    return c.getAccessibleContext().getAccessibleChildrenCount();
231
  }
232
 
233
  /**
234
   * <p>
235
   * Returns the zero-based index of the specified component
236
   * within its parent.  If the component doesn't have a parent,
237
   * -1 is returned.
238
   * </p>
239
   * <p>
240
   * Caution is advised when using this method, as its operation relies
241
   * on the behaviour of varying implementations of an abstract method.
242
   * For greater surety, direct use of the AWT component implementation
243
   * of this method is advised.
244
   * </p>
245
   *
246
   * @param c the component whose parental index should be found.
247
   * @return the index of the component within its parent, or -1
248
   *         if the component doesn't have a parent.
249
   * @see javax.accessibility.AccessibleContext#getAccessibleIndexInParent
250
   * @see java.awt.Component.AccessibleAWTComponent#getAccessibleIndexInParent
251
   */
252
  public static int getAccessibleIndexInParent(Component c)
253
  {
254
    return c.getAccessibleContext().getAccessibleIndexInParent();
255
  }
256
 
257
  /**
258
   * <p>
259
   * Returns a set of <code>AccessibleState</code>s, which represent
260
   * the state of the supplied component.
261
   * </p>
262
   * <p>
263
   * Caution is advised when using this method, as its operation relies
264
   * on the behaviour of varying implementations of an abstract method.
265
   * For greater surety, direct use of the AWT component implementation
266
   * of this method is advised.
267
   * </p>
268
   *
269
   * @param c the component whose accessible state should be retrieved.
270
   * @return a set of <code>AccessibleState</code> objects, which represent
271
   *         the state of the supplied component.
272
   * @see javax.accessibility.AccessibleContext#getAccessibleStateSet
273
   * @see java.awt.Component.AccessibleAWTComponent#getAccessibleStateSet
274
   */
275
  public static AccessibleStateSet getAccessibleStateSet(Component c)
276
  {
277
    return c.getAccessibleContext().getAccessibleStateSet();
278
  }
279
 
280
  /**
281
   * Calculates the bounds of a component in the component's own coordinate
282
   * space. The result has the same height and width as the component's
283
   * bounds, but its location is set to (0,0).
284
   *
285
   * @param aComponent The component to measure
286
   *
287
   * @return The component's bounds in its local coordinate space
288
   */
289
  public static Rectangle getLocalBounds(Component aComponent)
290
  {
291
    Rectangle bounds = aComponent.getBounds();
292
    return new Rectangle(0, 0, bounds.width, bounds.height);
293
  }
294
 
295
  /**
296
   * If <code>comp</code> is a RootPaneContainer, return its JRootPane.
297
   * Otherwise call <code>getAncestorOfClass(JRootPane.class, a)</code>.
298
   *
299
   * @param comp The component to get the JRootPane of
300
   *
301
   * @return a suitable JRootPane for <code>comp</code>, or <code>null</code>
302
   *
303
   * @see javax.swing.RootPaneContainer#getRootPane
304
   * @see #getAncestorOfClass
305
   */
306
  public static JRootPane getRootPane(Component comp)
307
  {
308
    if (comp instanceof RootPaneContainer)
309
      return ((RootPaneContainer)comp).getRootPane();
310
    else
311
      return (JRootPane) getAncestorOfClass(JRootPane.class, comp);
312
  }
313
 
314
  /**
315
   * Returns the least ancestor of <code>comp</code> which has the
316
   * specified name.
317
   *
318
   * @param name The name to search for
319
   * @param comp The component to search the ancestors of
320
   *
321
   * @return The nearest ancestor of <code>comp</code> with the given
322
   * name, or <code>null</code> if no such ancestor exists
323
   *
324
   * @see java.awt.Component#getName
325
   * @see #getAncestorOfClass
326
   */
327
  public static Container getAncestorNamed(String name, Component comp)
328
  {
329
    while (comp != null && (comp.getName() != name))
330
      comp = comp.getParent();
331
    return (Container) comp;
332
  }
333
 
334
  /**
335
   * Returns the least ancestor of <code>comp</code> which is an instance
336
   * of the specified class.
337
   *
338
   * @param c The class to search for
339
   * @param comp The component to search the ancestors of
340
   *
341
   * @return The nearest ancestor of <code>comp</code> which is an instance
342
   * of the given class, or <code>null</code> if no such ancestor exists
343
   *
344
   * @see #getAncestorOfClass
345
   * @see #windowForComponent
346
   */
347
  public static Container getAncestorOfClass(Class c, Component comp)
348
  {
349
    while (comp != null && (! c.isInstance(comp)))
350
      comp = comp.getParent();
351
    return (Container) comp;
352
  }
353
 
354
  /**
355
   * Returns the first ancestor of <code>comp</code> that is a {@link Window}
356
   * or <code>null</code> if <code>comp</code> is not contained in a
357
   * {@link Window}.
358
   *
359
   * This is equivalent to calling
360
   * <code>getAncestorOfClass(Window, comp)</code> or
361
   * <code>windowForComponent(comp)</code>.
362
   *
363
   * @param comp the component for which we are searching the ancestor Window
364
   *
365
   * @return the first ancestor Window of <code>comp</code> or
366
   *     <code>null</code> if <code>comp</code> is not contained in a Window
367
   */
368
  public static Window getWindowAncestor(Component comp)
369
  {
370
    return (Window) getAncestorOfClass(Window.class, comp);
371
  }
372
 
373
  /**
374
   * Equivalent to calling <code>getAncestorOfClass(Window, comp)</code>.
375
   *
376
   * @param comp The component to search for an ancestor window
377
   *
378
   * @return An ancestral window, or <code>null</code> if none exists
379
   */
380
  public static Window windowForComponent(Component comp)
381
  {
382
    return (Window) getAncestorOfClass(Window.class, comp);
383
  }
384
 
385
  /**
386
   * Returns the "root" of the component tree containint <code>comp</code>
387
   * The root is defined as either the <em>least</em> ancestor of
388
   * <code>comp</code> which is a {@link Window}, or the <em>greatest</em>
389
   * ancestor of <code>comp</code> which is a {@link Applet} if no {@link
390
   * Window} ancestors are found.
391
   *
392
   * @param comp The component to search for a root
393
   *
394
   * @return The root of the component's tree, or <code>null</code>
395
   */
396
  public static Component getRoot(Component comp)
397
  {
398
    Applet app = null;
399
    Window win = null;
400
 
401
    while (comp != null)
402
      {
403
        if (win == null && comp instanceof Window)
404
          win = (Window) comp;
405
        else if (comp instanceof Applet)
406
          app = (Applet) comp;
407
        comp = comp.getParent();
408
      }
409
 
410
    if (win != null)
411
      return win;
412
    else
413
      return app;
414
  }
415
 
416
  /**
417
   * Return true if a descends from b, in other words if b is an
418
   * ancestor of a.
419
   *
420
   * @param a The child to search the ancestry of
421
   * @param b The potential ancestor to search for
422
   *
423
   * @return true if a is a descendent of b, false otherwise
424
   */
425
  public static boolean isDescendingFrom(Component a, Component b)
426
  {
427
    while (true)
428
      {
429
        if (a == null || b == null)
430
          return false;
431
        if (a == b)
432
          return true;
433
        a = a.getParent();
434
      }
435
  }
436
 
437
  /**
438
   * Returns the deepest descendent of parent which is both visible and
439
   * contains the point <code>(x,y)</code>. Returns parent when either
440
   * parent is not a container, or has no children which contain
441
   * <code>(x,y)</code>. Returns <code>null</code> when either
442
   * <code>(x,y)</code> is outside the bounds of parent, or parent is
443
   * <code>null</code>.
444
   *
445
   * @param parent The component to search the descendents of
446
   * @param x Horizontal coordinate to search for
447
   * @param y Vertical coordinate to search for
448
   *
449
   * @return A component containing <code>(x,y)</code>, or
450
   * <code>null</code>
451
   *
452
   * @see java.awt.Container#findComponentAt(int, int)
453
   */
454
  public static Component getDeepestComponentAt(Component parent, int x, int y)
455
  {
456
    if (parent == null || (! parent.contains(x, y)))
457
      return null;
458
 
459
    if (! (parent instanceof Container))
460
      return parent;
461
 
462
    Container c = (Container) parent;
463
    return c.findComponentAt(x, y);
464
  }
465
 
466
  /**
467
   * Converts a point from a component's local coordinate space to "screen"
468
   * coordinates (such as the coordinate space mouse events are delivered
469
   * in). This operation is equivalent to translating the point by the
470
   * location of the component (which is the origin of its coordinate
471
   * space).
472
   *
473
   * @param p The point to convert
474
   * @param c The component which the point is expressed in terms of
475
   *
476
   * @see #convertPointFromScreen
477
   */
478
  public static void convertPointToScreen(Point p, Component c)
479
  {
480
    Point c0 = c.getLocationOnScreen();
481
    p.translate(c0.x, c0.y);
482
  }
483
 
484
  /**
485
   * Converts a point from "screen" coordinates (such as the coordinate
486
   * space mouse events are delivered in) to a component's local coordinate
487
   * space. This operation is equivalent to translating the point by the
488
   * negation of the component's location (which is the origin of its
489
   * coordinate space).
490
   *
491
   * @param p The point to convert
492
   * @param c The component which the point should be expressed in terms of
493
   */
494
  public static void convertPointFromScreen(Point p, Component c)
495
  {
496
    Point c0 = c.getLocationOnScreen();
497
    p.translate(-c0.x, -c0.y);
498
  }
499
 
500
  /**
501
   * Converts a point <code>(x,y)</code> from the coordinate space of one
502
   * component to another. This is equivalent to converting the point from
503
   * <code>source</code> space to screen space, then back from screen space
504
   * to <code>destination</code> space. If exactly one of the two
505
   * Components is <code>null</code>, it is taken to refer to the root
506
   * ancestor of the other component. If both are <code>null</code>, no
507
   * transformation is done.
508
   *
509
   * @param source The component which the point is expressed in terms of
510
   * @param x Horizontal coordinate of point to transform
511
   * @param y Vertical coordinate of point to transform
512
   * @param destination The component which the return value will be
513
   * expressed in terms of
514
   *
515
   * @return The point <code>(x,y)</code> converted from the coordinate space of the
516
   * source component to the coordinate space of the destination component
517
   *
518
   * @see #convertPointToScreen
519
   * @see #convertPointFromScreen
520
   * @see #convertRectangle
521
   * @see #getRoot
522
   */
523
  public static Point convertPoint(Component source, int x, int y,
524
                                   Component destination)
525
  {
526
    Point pt = new Point(x, y);
527
 
528
    if (source == null && destination == null)
529
      return pt;
530
 
531
    if (source == null)
532
      source = getRoot(destination);
533
 
534
    if (destination == null)
535
      destination = getRoot(source);
536
 
537
    if (source.isShowing() && destination.isShowing())
538
      {
539
        convertPointToScreen(pt, source);
540
        convertPointFromScreen(pt, destination);
541
      }
542
 
543
    return pt;
544
  }
545
 
546
  public static Point convertPoint(Component source, Point aPoint, Component destination)
547
  {
548
    return convertPoint(source, aPoint.x, aPoint.y, destination);
549
  }
550
 
551
  /**
552
   * Converts a rectangle from the coordinate space of one component to
553
   * another. This is equivalent to converting the rectangle from
554
   * <code>source</code> space to screen space, then back from screen space
555
   * to <code>destination</code> space. If exactly one of the two
556
   * Components is <code>null</code>, it is taken to refer to the root
557
   * ancestor of the other component. If both are <code>null</code>, no
558
   * transformation is done.
559
   *
560
   * @param source The component which the rectangle is expressed in terms of
561
   * @param rect The rectangle to convert
562
   * @param destination The component which the return value will be
563
   * expressed in terms of
564
   *
565
   * @return A new rectangle, equal in size to the input rectangle, but
566
   * with its position converted from the coordinate space of the source
567
   * component to the coordinate space of the destination component
568
   *
569
   * @see #convertPointToScreen
570
   * @see #convertPointFromScreen
571
   * @see #convertPoint(Component, int, int, Component)
572
   * @see #getRoot
573
   */
574
  public static Rectangle convertRectangle(Component source,
575
                                           Rectangle rect,
576
                                           Component destination)
577
  {
578
    Point pt = convertPoint(source, rect.x, rect.y, destination);
579
    return new Rectangle(pt.x, pt.y, rect.width, rect.height);
580
  }
581
 
582
  /**
583
   * Convert a mouse event which refrers to one component to another.  This
584
   * includes changing the mouse event's coordinate space, as well as the
585
   * source property of the event. If <code>source</code> is
586
   * <code>null</code>, it is taken to refer to <code>destination</code>'s
587
   * root component. If <code>destination</code> is <code>null</code>, the
588
   * new event will remain expressed in <code>source</code>'s coordinate
589
   * system.
590
   *
591
   * @param source The component the mouse event currently refers to
592
   * @param sourceEvent The mouse event to convert
593
   * @param destination The component the new mouse event should refer to
594
   *
595
   * @return A new mouse event expressed in terms of the destination
596
   * component's coordinate space, and with the destination component as
597
   * its source
598
   *
599
   * @see #convertPoint(Component, int, int, Component)
600
   */
601
  public static MouseEvent convertMouseEvent(Component source,
602
                                             MouseEvent sourceEvent,
603
                                             Component destination)
604
  {
605
    Point newpt = convertPoint(source, sourceEvent.getX(), sourceEvent.getY(),
606
                               destination);
607
 
608
    return new MouseEvent(destination, sourceEvent.getID(),
609
                          sourceEvent.getWhen(), sourceEvent.getModifiersEx(),
610
                          newpt.x, newpt.y, sourceEvent.getClickCount(),
611
                          sourceEvent.isPopupTrigger(), sourceEvent.getButton());
612
  }
613
 
614
  /**
615
   * Recursively walk the component tree under <code>comp</code> calling
616
   * <code>updateUI</code> on each {@link JComponent} found. This causes
617
   * the entire tree to re-initialize its UI delegates.
618
   *
619
   * @param comp The component to walk the children of, calling <code>updateUI</code>
620
   */
621
  public static void updateComponentTreeUI(Component comp)
622
  {
623
    if (comp == null)
624
      return;
625
 
626
    if (comp instanceof Container)
627
      {
628
        Component[] children = ((Container)comp).getComponents();
629
        for (int i = 0; i < children.length; ++i)
630
          updateComponentTreeUI(children[i]);
631
      }
632
 
633
    if (comp instanceof JComponent)
634
      ((JComponent)comp).updateUI();
635
  }
636
 
637
 
638
  /**
639
   * <p>Layout a "compound label" consisting of a text string and an icon
640
   * which is to be placed near the rendered text. Once the text and icon
641
   * are laid out, the text rectangle and icon rectangle parameters are
642
   * altered to store the calculated positions.</p>
643
   *
644
   * <p>The size of the text is calculated from the provided font metrics
645
   * object.  This object should be the metrics of the font you intend to
646
   * paint the label with.</p>
647
   *
648
   * <p>The position values control where the text is placed relative to
649
   * the icon. The horizontal position value should be one of the constants
650
   * <code>LEADING</code>, <code>TRAILING</code>, <code>LEFT</code>,
651
   * <code>RIGHT</code> or <code>CENTER</code>. The vertical position value
652
   * should be one fo the constants <code>TOP</code>, <code>BOTTOM</code>
653
   * or <code>CENTER</code>.</p>
654
   *
655
   * <p>The text-icon gap value controls the number of pixels between the
656
   * icon and the text.</p>
657
   *
658
   * <p>The alignment values control where the text and icon are placed, as
659
   * a combined unit, within the view rectangle. The horizontal alignment
660
   * value should be one of the constants <code>LEADING</code>,
661
   * <code>TRAILING</code>, <code>LEFT</code>, <code>RIGHT</code> or
662
   * <code>CENTER</code>. The vertical alignment valus should be one of the
663
   * constants <code>TOP</code>, <code>BOTTOM</code> or
664
   * <code>CENTER</code>.</p>
665
   *
666
   * <p>If the <code>LEADING</code> or <code>TRAILING</code> constants are
667
   * given for horizontal alignment or horizontal text position, they are
668
   * interpreted relative to the provided component's orientation property,
669
   * a constant in the {@link java.awt.ComponentOrientation} class. For
670
   * example, if the component's orientation is <code>LEFT_TO_RIGHT</code>,
671
   * then the <code>LEADING</code> value is a synonym for <code>LEFT</code>
672
   * and the <code>TRAILING</code> value is a synonym for
673
   * <code>RIGHT</code></p>
674
   *
675
   * <p>If the text and icon are equal to or larger than the view
676
   * rectangle, the horizontal and vertical alignment values have no
677
   * affect.</p>
678
   *
679
   * @param c A component used for its orientation value
680
   * @param fm The font metrics used to measure the text
681
   * @param text The text to place in the compound label
682
   * @param icon The icon to place next to the text
683
   * @param verticalAlignment The vertical alignment of the label relative
684
   * to its component
685
   * @param horizontalAlignment The horizontal alignment of the label
686
   * relative to its component
687
   * @param verticalTextPosition The vertical position of the label's text
688
   * relative to its icon
689
   * @param horizontalTextPosition The horizontal position of the label's
690
   * text relative to its icon
691
   * @param viewR The view rectangle, specifying the area which layout is
692
   * constrained to
693
   * @param iconR A rectangle which is modified to hold the laid-out
694
   * position of the icon
695
   * @param textR A rectangle which is modified to hold the laid-out
696
   * position of the text
697
   * @param textIconGap The distance between text and icon
698
   *
699
   * @return The string of characters, possibly truncated with an elipsis,
700
   * which is laid out in this label
701
   */
702
 
703
  public static String layoutCompoundLabel(JComponent c,
704
                                           FontMetrics fm,
705
                                           String text,
706
                                           Icon icon,
707
                                           int verticalAlignment,
708
                                           int horizontalAlignment,
709
                                           int verticalTextPosition,
710
                                           int horizontalTextPosition,
711
                                           Rectangle viewR,
712
                                           Rectangle iconR,
713
                                           Rectangle textR,
714
                                           int textIconGap)
715
  {
716
 
717
    // Fix up the orientation-based horizontal positions.
718
 
719
    if (horizontalTextPosition == LEADING)
720
      {
721
        if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
722
          horizontalTextPosition = RIGHT;
723
        else
724
          horizontalTextPosition = LEFT;
725
      }
726
    else if (horizontalTextPosition == TRAILING)
727
      {
728
        if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
729
          horizontalTextPosition = LEFT;
730
        else
731
          horizontalTextPosition = RIGHT;
732
      }
733
 
734
    // Fix up the orientation-based alignments.
735
 
736
    if (horizontalAlignment == LEADING)
737
      {
738
        if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
739
          horizontalAlignment = RIGHT;
740
        else
741
          horizontalAlignment = LEFT;
742
      }
743
    else if (horizontalAlignment == TRAILING)
744
      {
745
        if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
746
          horizontalAlignment = LEFT;
747
        else
748
          horizontalAlignment = RIGHT;
749
      }
750
 
751
    return layoutCompoundLabel(fm, text, icon,
752
                               verticalAlignment,
753
                               horizontalAlignment,
754
                               verticalTextPosition,
755
                               horizontalTextPosition,
756
                               viewR, iconR, textR, textIconGap);
757
  }
758
 
759
  /**
760
   * <p>Layout a "compound label" consisting of a text string and an icon
761
   * which is to be placed near the rendered text. Once the text and icon
762
   * are laid out, the text rectangle and icon rectangle parameters are
763
   * altered to store the calculated positions.</p>
764
   *
765
   * <p>The size of the text is calculated from the provided font metrics
766
   * object.  This object should be the metrics of the font you intend to
767
   * paint the label with.</p>
768
   *
769
   * <p>The position values control where the text is placed relative to
770
   * the icon. The horizontal position value should be one of the constants
771
   * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>. The
772
   * vertical position value should be one fo the constants
773
   * <code>TOP</code>, <code>BOTTOM</code> or <code>CENTER</code>.</p>
774
   *
775
   * <p>The text-icon gap value controls the number of pixels between the
776
   * icon and the text.</p>
777
   *
778
   * <p>The alignment values control where the text and icon are placed, as
779
   * a combined unit, within the view rectangle. The horizontal alignment
780
   * value should be one of the constants <code>LEFT</code>, <code>RIGHT</code> or
781
   * <code>CENTER</code>. The vertical alignment valus should be one of the
782
   * constants <code>TOP</code>, <code>BOTTOM</code> or
783
   * <code>CENTER</code>.</p>
784
   *
785
   * <p>If the text and icon are equal to or larger than the view
786
   * rectangle, the horizontal and vertical alignment values have no
787
   * affect.</p>
788
   *
789
   * <p>Note that this method does <em>not</em> know how to deal with
790
   * horizontal alignments or positions given as <code>LEADING</code> or
791
   * <code>TRAILING</code> values. Use the other overloaded variant of this
792
   * method if you wish to use such values.
793
   *
794
   * @param fm The font metrics used to measure the text
795
   * @param text The text to place in the compound label
796
   * @param icon The icon to place next to the text
797
   * @param verticalAlignment The vertical alignment of the label relative
798
   * to its component
799
   * @param horizontalAlignment The horizontal alignment of the label
800
   * relative to its component
801
   * @param verticalTextPosition The vertical position of the label's text
802
   * relative to its icon
803
   * @param horizontalTextPosition The horizontal position of the label's
804
   * text relative to its icon
805
   * @param viewR The view rectangle, specifying the area which layout is
806
   * constrained to
807
   * @param iconR A rectangle which is modified to hold the laid-out
808
   * position of the icon
809
   * @param textR A rectangle which is modified to hold the laid-out
810
   * position of the text
811
   * @param textIconGap The distance between text and icon
812
   *
813
   * @return The string of characters, possibly truncated with an elipsis,
814
   * which is laid out in this label
815
   */
816
 
817
  public static String layoutCompoundLabel(FontMetrics fm,
818
                                           String text,
819
                                           Icon icon,
820
                                           int verticalAlignment,
821
                                           int horizontalAlignment,
822
                                           int verticalTextPosition,
823
                                           int horizontalTextPosition,
824
                                           Rectangle viewR,
825
                                           Rectangle iconR,
826
                                           Rectangle textR,
827
                                           int textIconGap)
828
  {
829
 
830
    // Work out basic height and width.
831
 
832
    if (icon == null)
833
      {
834
        textIconGap = 0;
835
        iconR.width = 0;
836
        iconR.height = 0;
837
      }
838
    else
839
      {
840
        iconR.width = icon.getIconWidth();
841
        iconR.height = icon.getIconHeight();
842
      }
843
    if (text == null || text.equals(""))
844
      {
845
        textIconGap = 0;
846
        textR.width = 0;
847
        textR.height = 0;
848
      }
849
    else
850
      {
851
        int fromIndex = 0;
852
        textR.width = fm.stringWidth(text);
853
        textR.height = fm.getHeight();
854
        while (text.indexOf('\n', fromIndex) != -1)
855
          {
856
            textR.height += fm.getHeight();
857
            fromIndex = text.indexOf('\n', fromIndex) + 1;
858
          }
859
      }
860
 
861
    // Work out the position of text and icon, assuming the top-left coord
862
    // starts at (0,0). We will fix that up momentarily, after these
863
    // "position" decisions are made and we look at alignment.
864
 
865
    switch (horizontalTextPosition)
866
      {
867
      case LEFT:
868
        textR.x = 0;
869
        iconR.x = textR.width + textIconGap;
870
        break;
871
      case RIGHT:
872
        iconR.x = 0;
873
        textR.x = iconR.width + textIconGap;
874
        break;
875
      case CENTER:
876
        int centerLine = Math.max(textR.width, iconR.width) / 2;
877
        textR.x = centerLine - textR.width/2;
878
        iconR.x = centerLine - iconR.width/2;
879
        break;
880
      }
881
 
882
    switch (verticalTextPosition)
883
      {
884
      case TOP:
885
        textR.y = 0;
886
        iconR.y = (horizontalTextPosition == CENTER
887
                   ? textR.height + textIconGap : 0);
888
        break;
889
      case BOTTOM:
890
        iconR.y = 0;
891
        textR.y = (horizontalTextPosition == CENTER
892
                   ? iconR.height + textIconGap
893
                   : Math.max(iconR.height - textR.height, 0));
894
        break;
895
      case CENTER:
896
        int centerLine = Math.max(textR.height, iconR.height) / 2;
897
        textR.y = centerLine - textR.height/2;
898
        iconR.y = centerLine - iconR.height/2;
899
        break;
900
      }
901
    // The two rectangles are laid out correctly now, but only assuming
902
    // that their upper left corner is at (0,0). If we have any alignment other
903
    // than TOP and LEFT, we need to adjust them.
904
 
905
    Rectangle u = textR.union(iconR);
906
    int horizontalAdjustment = viewR.x;
907
    int verticalAdjustment = viewR.y;
908
    switch (verticalAlignment)
909
      {
910
      case TOP:
911
        break;
912
      case BOTTOM:
913
        verticalAdjustment += (viewR.height - u.height);
914
        break;
915
      case CENTER:
916
        verticalAdjustment += ((viewR.height/2) - (u.height/2));
917
        break;
918
      }
919
    switch (horizontalAlignment)
920
      {
921
      case LEFT:
922
        break;
923
      case RIGHT:
924
        horizontalAdjustment += (viewR.width - u.width);
925
        break;
926
      case CENTER:
927
        horizontalAdjustment += ((viewR.width/2) - (u.width/2));
928
        break;
929
      }
930
 
931
    iconR.x += horizontalAdjustment;
932
    iconR.y += verticalAdjustment;
933
 
934
    textR.x += horizontalAdjustment;
935
    textR.y += verticalAdjustment;
936
 
937
    return text;
938
  }
939
 
940
  /**
941
   * Calls {@link java.awt.EventQueue#invokeLater} with the
942
   * specified {@link Runnable}.
943
   */
944
  public static void invokeLater(Runnable doRun)
945
  {
946
    java.awt.EventQueue.invokeLater(doRun);
947
  }
948
 
949
  /**
950
   * Calls {@link java.awt.EventQueue#invokeAndWait} with the
951
   * specified {@link Runnable}.
952
   */
953
  public static void invokeAndWait(Runnable doRun)
954
    throws InterruptedException,
955
    InvocationTargetException
956
  {
957
    java.awt.EventQueue.invokeAndWait(doRun);
958
  }
959
 
960
  /**
961
   * Calls {@link java.awt.EventQueue#isDispatchThread()}.
962
   *
963
   * @return <code>true</code> if the current thread is the current AWT event
964
   * dispatch thread.
965
   */
966
  public static boolean isEventDispatchThread()
967
  {
968
    return java.awt.EventQueue.isDispatchThread();
969
  }
970
 
971
  /**
972
   * This method paints the given component at the given position and size.
973
   * The component will be reparented to the container given.
974
   *
975
   * @param g The Graphics object to draw with.
976
   * @param c The Component to draw
977
   * @param p The Container to reparent to.
978
   * @param x The x coordinate to draw at.
979
   * @param y The y coordinate to draw at.
980
   * @param w The width of the drawing area.
981
   * @param h The height of the drawing area.
982
   */
983
  public static void paintComponent(Graphics g, Component c, Container p,
984
                                    int x, int y, int w, int h)
985
  {
986
    Container parent = c.getParent();
987
    if (parent != null)
988
      parent.remove(c);
989
    if (p != null)
990
      p.add(c);
991
 
992
    Shape savedClip = g.getClip();
993
 
994
    g.setClip(x, y, w, h);
995
    g.translate(x, y);
996
 
997
    c.paint(g);
998
 
999
    g.translate(-x, -y);
1000
    g.setClip(savedClip);
1001
  }
1002
 
1003
  /**
1004
   * This method paints the given component in the given rectangle.
1005
   * The component will be reparented to the container given.
1006
   *
1007
   * @param g The Graphics object to draw with.
1008
   * @param c The Component to draw
1009
   * @param p The Container to reparent to.
1010
   * @param r The rectangle that describes the drawing area.
1011
   */
1012
  public static void paintComponent(Graphics g, Component c,
1013
                                    Container p, Rectangle r)
1014
  {
1015
    paintComponent(g, c, p, r.x, r.y, r.width, r.height);
1016
  }
1017
 
1018
  /**
1019
   * This method returns the common Frame owner used in JDialogs or
1020
   * JWindow when no owner is provided.
1021
   *
1022
   * @return The common Frame
1023
   */
1024
  static Frame getOwnerFrame()
1025
  {
1026
    if (ownerFrame == null)
1027
      ownerFrame = new OwnerFrame();
1028
    return ownerFrame;
1029
  }
1030
 
1031
  /**
1032
   * Checks if left mouse button was clicked.
1033
   *
1034
   * @param event the event to check
1035
   *
1036
   * @return true if left mouse was clicked, false otherwise.
1037
   */
1038
  public static boolean isLeftMouseButton(MouseEvent event)
1039
  {
1040
    return ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK)
1041
             == InputEvent.BUTTON1_DOWN_MASK);
1042
  }
1043
 
1044
  /**
1045
   * Checks if middle mouse button was clicked.
1046
   *
1047
   * @param event the event to check
1048
   *
1049
   * @return true if middle mouse was clicked, false otherwise.
1050
   */
1051
  public static boolean isMiddleMouseButton(MouseEvent event)
1052
  {
1053
    return ((event.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK)
1054
             == InputEvent.BUTTON2_DOWN_MASK);
1055
  }
1056
 
1057
  /**
1058
   * Checks if right mouse button was clicked.
1059
   *
1060
   * @param event the event to check
1061
   *
1062
   * @return true if right mouse was clicked, false otherwise.
1063
   */
1064
  public static boolean isRightMouseButton(MouseEvent event)
1065
  {
1066
    return ((event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK)
1067
             == InputEvent.BUTTON3_DOWN_MASK);
1068
  }
1069
 
1070
  /**
1071
   * This frame should be used when constructing a Window/JDialog without
1072
   * a parent. In this case, we are forced to use this frame as a window's
1073
   * parent, because we simply cannot pass null instead of parent to Window
1074
   * constructor, since doing it will result in NullPointerException.
1075
   */
1076
  private static class OwnerFrame extends Frame
1077
  {
1078
    public void setVisible(boolean b)
1079
    {
1080
      // Do nothing here. 
1081
    }
1082
 
1083
    public boolean isShowing()
1084
    {
1085
      return true;
1086
    }
1087
  }
1088
 
1089
  public static boolean notifyAction(Action action,
1090
                                     KeyStroke ks,
1091
                                     KeyEvent event,
1092
                                     Object sender,
1093
                                     int modifiers)
1094
  {
1095
    if (action != null && action.isEnabled())
1096
      {
1097
        String name = (String) action.getValue(Action.ACTION_COMMAND_KEY);
1098
        if (name == null
1099
            && event.getKeyChar() != KeyEvent.CHAR_UNDEFINED)
1100
          name = new String(new char[] {event.getKeyChar()});
1101
        action.actionPerformed(new ActionEvent(sender,
1102
                                               ActionEvent.ACTION_PERFORMED,
1103
                                               name, modifiers));
1104
        return true;
1105
      }
1106
    return false;
1107
  }
1108
 
1109
  /**
1110
   * <p>Change the shared, UI-managed {@link ActionMap} for a given
1111
   * component. ActionMaps are arranged in a hierarchy, in order to
1112
   * encourage sharing of common actions between components. The hierarchy
1113
   * unfortunately places UI-managed ActionMaps at the <em>end</em> of the
1114
   * parent-pointer chain, as illustrated:</p>
1115
   *
1116
   * <pre>
1117
   *  [{@link javax.swing.JComponent#getActionMap()}]
1118
   *          --&gt; [{@link javax.swing.ActionMap}]
1119
   *     parent --&gt; [{@link javax.swing.text.JTextComponent.KeymapActionMap}]
1120
   *       parent --&gt; [{@link javax.swing.plaf.ActionMapUIResource}]
1121
   * </pre>
1122
   *
1123
   * <p>Our goal with this method is to replace the first ActionMap along
1124
   * this chain which is an instance of {@link ActionMapUIResource}, since
1125
   * these are the ActionMaps which are supposed to be shared between
1126
   * components.</p>
1127
   *
1128
   * <p>If the provided ActionMap is <code>null</code>, we interpret the
1129
   * call as a request to remove the UI-managed ActionMap from the
1130
   * component's ActionMap parent chain.</p>
1131
   */
1132
  public static void replaceUIActionMap(JComponent component,
1133
                                        ActionMap uiActionMap)
1134
  {
1135
    ActionMap child = component.getActionMap();
1136
    if (child == null)
1137
      component.setActionMap(uiActionMap);
1138
    else
1139
      {
1140
        ActionMap parent = child.getParent();
1141
        while (parent != null && !(parent instanceof ActionMapUIResource))
1142
          {
1143
            child = parent;
1144
            parent = child.getParent();
1145
          }
1146
        child.setParent(uiActionMap);
1147
      }
1148
  }
1149
 
1150
  /**
1151
   * <p>Change the shared, UI-managed {@link InputMap} for a given
1152
   * component. InputMaps are arranged in a hierarchy, in order to
1153
   * encourage sharing of common input mappings between components. The
1154
   * hierarchy unfortunately places UI-managed InputMaps at the
1155
   * <em>end</em> of the parent-pointer chain, as illustrated:</p>
1156
   *
1157
   * <pre>
1158
   *  [{@link javax.swing.JComponent#getInputMap()}]
1159
   *          --&gt; [{@link javax.swing.InputMap}]
1160
   *     parent --&gt; [{@link javax.swing.text.JTextComponent.KeymapWrapper}]
1161
   *       parent --&gt; [{@link javax.swing.plaf.InputMapUIResource}]
1162
   * </pre>
1163
   *
1164
   * <p>Our goal with this method is to replace the first InputMap along
1165
   * this chain which is an instance of {@link InputMapUIResource}, since
1166
   * these are the InputMaps which are supposed to be shared between
1167
   * components.</p>
1168
   *
1169
   * <p>If the provided InputMap is <code>null</code>, we interpret the
1170
   * call as a request to remove the UI-managed InputMap from the
1171
   * component's InputMap parent chain.</p>
1172
   */
1173
  public static void replaceUIInputMap(JComponent component,
1174
                                       int condition,
1175
                                       InputMap uiInputMap)
1176
  {
1177
    InputMap child = component.getInputMap(condition);
1178
    if (child == null)
1179
      component.setInputMap(condition, uiInputMap);
1180
    else
1181
      {
1182
        InputMap parent = child.getParent();
1183
        while (parent != null && !(parent instanceof InputMapUIResource))
1184
          {
1185
            child = parent;
1186
            parent = parent.getParent();
1187
          }
1188
        child.setParent(uiInputMap);
1189
      }
1190
  }
1191
 
1192
  /**
1193
   * Subtracts a rectangle from another and return the area as an array
1194
   * of rectangles.
1195
   * Returns the areas of rectA which are not covered by rectB.
1196
   * If the rectangles do not overlap, or if either parameter is
1197
   * <code>null</code>, a zero-size array is returned.
1198
   * @param rectA The first rectangle
1199
   * @param rectB The rectangle to subtract from the first
1200
   * @return An array of rectangles representing the area in rectA
1201
   * not overlapped by rectB
1202
   */
1203
  public static Rectangle[] computeDifference(Rectangle rectA, Rectangle rectB)
1204
  {
1205
    if (rectA == null || rectB == null)
1206
      return new Rectangle[0];
1207
 
1208
    Rectangle[] r = new Rectangle[4];
1209
    int x1 = rectA.x;
1210
    int y1 = rectA.y;
1211
    int w1 = rectA.width;
1212
    int h1 = rectA.height;
1213
    int x2 = rectB.x;
1214
    int y2 = rectB.y;
1215
    int w2 = rectB.width;
1216
    int h2 = rectB.height;
1217
 
1218
    // (outer box = rectA)
1219
    // ------------- 
1220
    // |_____0_____|
1221
    // |  |rectB|  |
1222
    // |_1|_____|_2|
1223
    // |     3     |
1224
    // -------------
1225
    int H0 = (y2 > y1) ? y2 - y1 : 0; // height of box 0
1226
    int H3 = (y2 + h2 < y1 + h1) ? y1 + h1 - y2 - h2 : 0; // height box 3
1227
    int W1 = (x2 > x1) ? x2 - x1 : 0; // width box 1
1228
    int W2 = (x1 + w1 > x2 + w2) ? x1 + w1 - x2 - w2 : 0; // w. box 2
1229
    int H12 = (H0 + H3 < h1) ? h1 - H0 - H3 : 0; // height box 1 & 2
1230
 
1231
    if (H0 > 0)
1232
      r[0] = new Rectangle(x1, y1, w1, H0);
1233
    else
1234
      r[0] = null;
1235
 
1236
    if (W1 > 0 && H12 > 0)
1237
      r[1] = new Rectangle(x1, y1 + H0, W1, H12);
1238
    else
1239
      r[1] = null;
1240
 
1241
    if (W2 > 0 && H12 > 0)
1242
      r[2] = new Rectangle(x2 + w2, y1 + H0, W2, H12);
1243
    else
1244
      r[2] = null;
1245
 
1246
    if (H3 > 0)
1247
      r[3] = new Rectangle(x1, y1 + H0 + H12, w1, H3);
1248
    else
1249
      r[3] = null;
1250
 
1251
    // sort out null objects
1252
    int n = 0;
1253
    for (int i = 0; i < 4; i++)
1254
      if (r[i] != null)
1255
        n++;
1256
    Rectangle[] out = new Rectangle[n];
1257
    for (int i = 3; i >= 0; i--)
1258
      if (r[i] != null)
1259
        out[--n] = r[i];
1260
 
1261
    return out;
1262
  }
1263
 
1264
  /**
1265
   * Calculates the intersection of two rectangles.
1266
   *
1267
   * @param x upper-left x coodinate of first rectangle
1268
   * @param y upper-left y coodinate of first rectangle
1269
   * @param w width of first rectangle
1270
   * @param h height of first rectangle
1271
   * @param rect a Rectangle object of the second rectangle
1272
   * @throws NullPointerException if rect is null.
1273
   *
1274
   * @return a rectangle corresponding to the intersection of the
1275
   * two rectangles. A zero rectangle is returned if the rectangles
1276
   * do not overlap.
1277
   */
1278
  public static Rectangle computeIntersection(int x, int y, int w, int h,
1279
                                              Rectangle rect)
1280
  {
1281
    int x2 = (int) rect.getX();
1282
    int y2 = (int) rect.getY();
1283
    int w2 = (int) rect.getWidth();
1284
    int h2 = (int) rect.getHeight();
1285
 
1286
    int dx = (x > x2) ? x : x2;
1287
    int dy = (y > y2) ? y : y2;
1288
    int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
1289
    int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);
1290
 
1291
    if (dw >= 0 && dh >= 0)
1292
      return new Rectangle(dx, dy, dw, dh);
1293
 
1294
    return new Rectangle(0, 0, 0, 0);
1295
  }
1296
 
1297
  /**
1298
   * Calculates the width of a given string.
1299
   *
1300
   * @param fm the <code>FontMetrics</code> object to use
1301
   * @param str the string
1302
   *
1303
   * @return the width of the the string.
1304
   */
1305
  public static int computeStringWidth(FontMetrics fm, String str)
1306
  {
1307
    return fm.stringWidth(str);
1308
  }
1309
 
1310
  /**
1311
   * Calculates the union of two rectangles.
1312
   *
1313
   * @param x upper-left x coodinate of first rectangle
1314
   * @param y upper-left y coodinate of first rectangle
1315
   * @param w width of first rectangle
1316
   * @param h height of first rectangle
1317
   * @param rect a Rectangle object of the second rectangle
1318
   * @throws NullPointerException if rect is null.
1319
   *
1320
   * @return a rectangle corresponding to the union of the
1321
   * two rectangles. A rectangle encompassing both is returned if the
1322
   * rectangles do not overlap.
1323
   */
1324
  public static Rectangle computeUnion(int x, int y, int w, int h,
1325
                                       Rectangle rect)
1326
  {
1327
    int x2 = (int) rect.getX();
1328
    int y2 = (int) rect.getY();
1329
    int w2 = (int) rect.getWidth();
1330
    int h2 = (int) rect.getHeight();
1331
 
1332
    int dx = (x < x2) ? x : x2;
1333
    int dy = (y < y2) ? y : y2;
1334
    int dw = (x + w > x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
1335
    int dh = (y + h > y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);
1336
 
1337
    if (dw >= 0 && dh >= 0)
1338
      return new Rectangle(dx, dy, dw, dh);
1339
 
1340
    return new Rectangle(0, 0, 0, 0);
1341
  }
1342
 
1343
  /**
1344
   * Tests if a rectangle contains another.
1345
   * @param a first rectangle
1346
   * @param b second rectangle
1347
   * @return true if a contains b, false otherwise
1348
   * @throws NullPointerException
1349
   */
1350
  public static boolean isRectangleContainingRectangle(Rectangle a, Rectangle b)
1351
  {
1352
    // Note: zero-size rects inclusive, differs from Rectangle.contains()
1353
    return b.width >= 0 && b.height >= 0 && b.width >= 0 && b.height >= 0
1354
           && b.x >= a.x && b.x + b.width <= a.x + a.width && b.y >= a.y
1355
           && b.y + b.height <= a.y + a.height;
1356
  }
1357
 
1358
  /**
1359
   * Returns the InputMap that is provided by the ComponentUI of
1360
   * <code>component</code> for the specified condition.
1361
   *
1362
   * @param component the component for which the InputMap is returned
1363
   * @param cond the condition that specifies which of the three input
1364
   *     maps should be returned, may be
1365
   *     {@link JComponent#WHEN_IN_FOCUSED_WINDOW},
1366
   *     {@link JComponent#WHEN_FOCUSED} or
1367
   *     {@link JComponent#WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}
1368
   *
1369
   * @return The input map.
1370
   */
1371
  public static InputMap getUIInputMap(JComponent component, int cond)
1372
  {
1373
    if (UIManager.getUI(component) != null)
1374
      // we assume here that the UI class sets the parent of the component's
1375
      // InputMap, which is the correct behaviour. If it's not, then
1376
      // this can be considered a bug
1377
      return component.getInputMap(cond).getParent();
1378
    else
1379
      return null;
1380
  }
1381
 
1382
  /**
1383
   * Returns the ActionMap that is provided by the ComponentUI of
1384
   * <code>component</code>.
1385
   *
1386
   * @param component the component for which the ActionMap is returned
1387
   */
1388
  public static ActionMap getUIActionMap(JComponent component)
1389
  {
1390
    if (UIManager.getUI(component) != null)
1391
      // we assume here that the UI class sets the parent of the component's
1392
      // ActionMap, which is the correct behaviour. If it's not, then
1393
      // this can be considered a bug
1394
      return component.getActionMap().getParent();
1395
    else
1396
      return null;
1397
  }
1398
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.