54 public class SwingUtilities implements SwingConstants 55 { 56 // These states are system-wide, rather than AppContext wide. 57 private static boolean canAccessEventQueue = false; 58 private static boolean eventQueueTested = false; 59 60 /** 61 * Indicates if we should change the drop target when a 62 * {@code TransferHandler} is set. 63 */ 64 private static boolean suppressDropSupport; 65 66 /** 67 * Indiciates if we've checked the system property for suppressing 68 * drop support. 69 */ 70 private static boolean checkedSuppressDropSupport; 71 72 73 /** 74 * Returns true if <code>setTransferHandler</code> should change the 75 * <code>DropTarget</code>. 76 */ 77 private static boolean getSuppressDropTarget() { 78 if (!checkedSuppressDropSupport) { 79 suppressDropSupport = Boolean.valueOf( 80 AccessController.doPrivileged( 81 new GetPropertyAction("suppressSwingDropSupport"))); 82 checkedSuppressDropSupport = true; 83 } 84 return suppressDropSupport; 85 } 86 87 /** 88 * Installs a {@code DropTarget} on the component as necessary for a 89 * {@code TransferHandler} change. 90 */ 91 static void installSwingDropTargetAsNecessary(Component c, 92 TransferHandler t) { 93 94 if (!getSuppressDropTarget()) { 95 DropTarget dropHandler = c.getDropTarget(); 113 */ 114 public static final boolean isRectangleContainingRectangle(Rectangle a,Rectangle b) { 115 return b.x >= a.x && (b.x + b.width) <= (a.x + a.width) && 116 b.y >= a.y && (b.y + b.height) <= (a.y + a.height); 117 } 118 119 /** 120 * Return the rectangle (0,0,bounds.width,bounds.height) for the component {@code aComponent} 121 * 122 * @param aComponent a component 123 * @return the local bounds for the component {@code aComponent} 124 */ 125 public static Rectangle getLocalBounds(Component aComponent) { 126 Rectangle b = new Rectangle(aComponent.getBounds()); 127 b.x = b.y = 0; 128 return b; 129 } 130 131 132 /** 133 * Returns the first <code>Window </code> ancestor of <code>c</code>, or 134 * {@code null} if <code>c</code> is not contained inside a <code>Window</code>. 135 * 136 * @param c <code>Component</code> to get <code>Window</code> ancestor 137 * of. 138 * @return the first <code>Window </code> ancestor of <code>c</code>, or 139 * {@code null} if <code>c</code> is not contained inside a 140 * <code>Window</code>. 141 * @since 1.3 142 */ 143 public static Window getWindowAncestor(Component c) { 144 for(Container p = c.getParent(); p != null; p = p.getParent()) { 145 if (p instanceof Window) { 146 return (Window)p; 147 } 148 } 149 return null; 150 } 151 152 /** 153 * Converts the location <code>x</code> <code>y</code> to the 154 * parents coordinate system, returning the location. 155 */ 156 static Point convertScreenLocationToParent(Container parent,int x, int y) { 157 for (Container p = parent; p != null; p = p.getParent()) { 158 if (p instanceof Window) { 159 Point point = new Point(x, y); 160 161 SwingUtilities.convertPointFromScreen(point, parent); 162 return point; 163 } 164 } 165 throw new Error("convertScreenLocationToParent: no window ancestor"); 166 } 167 168 /** 169 * Convert a <code>aPoint</code> in <code>source</code> coordinate system to 170 * <code>destination</code> coordinate system. 171 * If <code>source</code> is {@code null}, <code>aPoint</code> is assumed to be in <code>destination</code>'s 172 * root component coordinate system. 173 * If <code>destination</code> is {@code null}, <code>aPoint</code> will be converted to <code>source</code>'s 174 * root component coordinate system. 175 * If both <code>source</code> and <code>destination</code> are {@code null}, return <code>aPoint</code> 176 * without any conversion. 177 * 178 * @param source the source component 179 * @param aPoint the point 180 * @param destination the destination component 181 * 182 * @return the converted coordinate 183 */ 184 public static Point convertPoint(Component source,Point aPoint,Component destination) { 185 Point p; 186 187 if(source == null && destination == null) 188 return aPoint; 189 if(source == null) { 190 source = getWindowAncestor(destination); 191 if(source == null) 192 throw new Error("Source component not connected to component tree hierarchy"); 193 } 194 p = new Point(aPoint); 195 convertPointToScreen(p,source); 196 if(destination == null) { 197 destination = getWindowAncestor(source); 198 if(destination == null) 199 throw new Error("Destination component not connected to component tree hierarchy"); 200 } 201 convertPointFromScreen(p,destination); 202 return p; 203 } 204 205 /** 206 * Convert the point <code>(x,y)</code> in <code>source</code> coordinate system to 207 * <code>destination</code> coordinate system. 208 * If <code>source</code> is {@code null}, <code>(x,y)</code> is assumed to be in <code>destination</code>'s 209 * root component coordinate system. 210 * If <code>destination</code> is {@code null}, <code>(x,y)</code> will be converted to <code>source</code>'s 211 * root component coordinate system. 212 * If both <code>source</code> and <code>destination</code> are {@code null}, return <code>(x,y)</code> 213 * without any conversion. 214 * 215 * @param source the source component 216 * @param x the x-coordinate of the point 217 * @param y the y-coordinate of the point 218 * @param destination the destination component 219 * 220 * @return the converted coordinate 221 */ 222 public static Point convertPoint(Component source,int x, int y,Component destination) { 223 Point point = new Point(x,y); 224 return convertPoint(source,point,destination); 225 } 226 227 /** 228 * Convert the rectangle <code>aRectangle</code> in <code>source</code> coordinate system to 229 * <code>destination</code> coordinate system. 230 * If <code>source</code> is {@code null}, <code>aRectangle</code> is assumed to be in <code>destination</code>'s 231 * root component coordinate system. 232 * If <code>destination</code> is {@code null}, <code>aRectangle</code> will be converted to <code>source</code>'s 233 * root component coordinate system. 234 * If both <code>source</code> and <code>destination</code> are {@code null}, return <code>aRectangle</code> 235 * without any conversion. 236 * 237 * @param source the source component 238 * @param aRectangle a rectangle 239 * @param destination the destination component 240 * 241 * @return the converted rectangle 242 */ 243 public static Rectangle convertRectangle(Component source,Rectangle aRectangle,Component destination) { 244 Point point = new Point(aRectangle.x,aRectangle.y); 245 point = convertPoint(source,point,destination); 246 return new Rectangle(point.x,point.y,aRectangle.width,aRectangle.height); 247 } 248 249 /** 250 * Convenience method for searching above <code>comp</code> in the 251 * component hierarchy and returns the first object of class <code>c</code> it 252 * finds. Can return {@code null}, if a class <code>c</code> cannot be found. 253 * 254 * @param c the class of a component 255 * @param comp the component 256 * 257 * @return the ancestor of the {@code comp}, 258 * or {@code null} if {@code c} cannot be found. 259 */ 260 public static Container getAncestorOfClass(Class<?> c, Component comp) 261 { 262 if(comp == null || c == null) 263 return null; 264 265 Container parent = comp.getParent(); 266 while(parent != null && !(c.isInstance(parent))) 267 parent = parent.getParent(); 268 return parent; 269 } 270 271 /** 272 * Convenience method for searching above <code>comp</code> in the 273 * component hierarchy and returns the first object of <code>name</code> it 274 * finds. Can return {@code null}, if <code>name</code> cannot be found. 275 * 276 * @param name the name of a component 277 * @param comp the component 278 * 279 * @return the ancestor of the {@code comp}, 280 * or {@code null} if {@code name} cannot be found. 281 */ 282 public static Container getAncestorNamed(String name, Component comp) { 283 if(comp == null || name == null) 284 return null; 285 286 Container parent = comp.getParent(); 287 while(parent != null && !(name.equals(parent.getName()))) 288 parent = parent.getParent(); 289 return parent; 290 } 291 292 /** 293 * Returns the deepest visible descendent Component of <code>parent</code> 294 * that contains the location <code>x</code>, <code>y</code>. 295 * If <code>parent</code> does not contain the specified location, 296 * then <code>null</code> is returned. If <code>parent</code> is not a 297 * container, or none of <code>parent</code>'s visible descendents 298 * contain the specified location, <code>parent</code> is returned. 299 * 300 * @param parent the root component to begin the search 301 * @param x the x target location 302 * @param y the y target location 303 * 304 * @return the deepest component 305 */ 306 public static Component getDeepestComponentAt(Component parent, int x, int y) { 307 if (!parent.contains(x, y)) { 308 return null; 309 } 310 if (parent instanceof Container) { 311 Component components[] = ((Container)parent).getComponents(); 312 for (Component comp : components) { 313 if (comp != null && comp.isVisible()) { 314 Point loc = comp.getLocation(); 315 if (comp instanceof Container) { 316 comp = getDeepestComponentAt(comp, x - loc.x, y - loc.y); 317 } else { 318 comp = comp.getComponentAt(x - loc.x, y - loc.y); 319 } 320 if (comp != null && comp.isVisible()) { 321 return comp; 322 } 323 } 324 } 325 } 326 return parent; 327 } 328 329 330 /** 331 * Returns a MouseEvent similar to <code>sourceEvent</code> except that its x 332 * and y members have been converted to <code>destination</code>'s coordinate 333 * system. If <code>source</code> is {@code null}, <code>sourceEvent</code> x and y members 334 * are assumed to be into <code>destination</code>'s root component coordinate system. 335 * If <code>destination</code> is <code>null</code>, the 336 * returned MouseEvent will be in <code>source</code>'s coordinate system. 337 * <code>sourceEvent</code> will not be changed. A new event is returned. 338 * the <code>source</code> field of the returned event will be set 339 * to <code>destination</code> if destination is non-{@code null} 340 * use the translateMouseEvent() method to translate a mouse event from 341 * one component to another without changing the source. 342 * 343 * @param source the source component 344 * @param sourceEvent the source mouse event 345 * @param destination the destination component 346 * 347 * @return the new mouse event 348 */ 349 public static MouseEvent convertMouseEvent(Component source, 350 MouseEvent sourceEvent, 351 Component destination) { 352 Point p = convertPoint(source,new Point(sourceEvent.getX(), 353 sourceEvent.getY()), 354 destination); 355 Component newSource; 356 357 if(destination != null) 358 newSource = destination; 359 else 471 y = pp.y; 472 } catch (IllegalComponentStateException icse) { 473 x = c.getX(); 474 y = c.getY(); 475 } 476 } else { 477 x = c.getX(); 478 y = c.getY(); 479 } 480 481 p.x -= x; 482 p.y -= y; 483 484 if(c instanceof java.awt.Window || c instanceof java.applet.Applet) 485 break; 486 c = c.getParent(); 487 } while(c != null); 488 } 489 490 /** 491 * Returns the first <code>Window </code> ancestor of <code>c</code>, or 492 * {@code null} if <code>c</code> is not contained inside a <code>Window</code>. 493 * <p> 494 * Note: This method provides the same functionality as 495 * <code>getWindowAncestor</code>. 496 * 497 * @param c <code>Component</code> to get <code>Window</code> ancestor 498 * of. 499 * @return the first <code>Window </code> ancestor of <code>c</code>, or 500 * {@code null} if <code>c</code> is not contained inside a 501 * <code>Window</code>. 502 */ 503 public static Window windowForComponent(Component c) { 504 return getWindowAncestor(c); 505 } 506 507 /** 508 * Return {@code true} if a component {@code a} descends from a component {@code b} 509 * 510 * @param a the first component 511 * @param b the second component 512 * @return {@code true} if a component {@code a} descends from a component {@code b} 513 */ 514 public static boolean isDescendingFrom(Component a,Component b) { 515 if(a == b) 516 return true; 517 for(Container p = a.getParent();p!=null;p=p.getParent()) 518 if(p == b) 519 return true; 520 return false; 521 } 522 523 524 /** 525 * Convenience to calculate the intersection of two rectangles 526 * without allocating a new rectangle. 527 * If the two rectangles don't intersect, 528 * then the returned rectangle begins at (0,0) 529 * and has zero width and height. 530 * 531 * @param x the X coordinate of the first rectangle's top-left point 532 * @param y the Y coordinate of the first rectangle's top-left point 533 * @param width the width of the first rectangle 534 * @param height the height of the first rectangle 535 * @param dest the second rectangle 536 * 537 * @return <code>dest</code>, modified to specify the intersection 538 */ 539 public static Rectangle computeIntersection(int x,int y,int width,int height,Rectangle dest) { 540 int x1 = (x > dest.x) ? x : dest.x; 541 int x2 = ((x+width) < (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width); 542 int y1 = (y > dest.y) ? y : dest.y; 543 int y2 = ((y + height) < (dest.y + dest.height) ? (y+height) : (dest.y + dest.height)); 544 545 dest.x = x1; 546 dest.y = y1; 547 dest.width = x2 - x1; 548 dest.height = y2 - y1; 549 550 // If rectangles don't intersect, return zero'd intersection. 551 if (dest.width < 0 || dest.height < 0) { 552 dest.x = dest.y = dest.width = dest.height = 0; 553 } 554 555 return dest; 556 } 557 558 /** 559 * Convenience method that calculates the union of two rectangles 560 * without allocating a new rectangle. 561 * 562 * @param x the x-coordinate of the first rectangle 563 * @param y the y-coordinate of the first rectangle 564 * @param width the width of the first rectangle 565 * @param height the height of the first rectangle 566 * @param dest the coordinates of the second rectangle; the union 567 * of the two rectangles is returned in this rectangle 568 * @return the <code>dest</code> <code>Rectangle</code> 569 */ 570 public static Rectangle computeUnion(int x,int y,int width,int height,Rectangle dest) { 571 int x1 = (x < dest.x) ? x : dest.x; 572 int x2 = ((x+width) > (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width); 573 int y1 = (y < dest.y) ? y : dest.y; 574 int y2 = ((y+height) > (dest.y + dest.height)) ? (y+height) : (dest.y + dest.height); 575 576 dest.x = x1; 577 dest.y = y1; 578 dest.width = (x2 - x1); 579 dest.height= (y2 - y1); 580 return dest; 581 } 582 583 /** 584 * Convenience returning an array of rect representing the regions within 585 * <code>rectA</code> that do not overlap with <code>rectB</code>. If the 586 * two Rects do not overlap, returns an empty array 587 * 588 * @param rectA the first rectangle 589 * @param rectB the second rectangle 590 * 591 * @return an array of rectangles representing the regions within {@code rectA} 592 * that do not overlap with {@code rectB}. 593 */ 594 public static Rectangle[] computeDifference(Rectangle rectA,Rectangle rectB) { 595 if (rectB == null || !rectA.intersects(rectB) || isRectangleContainingRectangle(rectB,rectA)) { 596 return new Rectangle[0]; 597 } 598 599 Rectangle t = new Rectangle(); 600 Rectangle a=null,b=null,c=null,d=null; 601 Rectangle result[]; 602 int rectCount = 0; 603 604 /* rectA contains rectB */ 605 if (isRectangleContainingRectangle(rectA,rectB)) { 1198 1199 iconR.x += dx; 1200 iconR.y += dy; 1201 1202 if (lsb < 0) { 1203 // lsb is negative. Shift the x location so that the text is 1204 // visually drawn at the right location. 1205 textR.x -= lsb; 1206 1207 textR.width += lsb; 1208 } 1209 if (rsb > 0) { 1210 textR.width -= rsb; 1211 } 1212 1213 return text; 1214 } 1215 1216 1217 /** 1218 * Paints a component to the specified <code>Graphics</code>. 1219 * This method is primarily useful to render 1220 * <code>Component</code>s that don't exist as part of the visible 1221 * containment hierarchy, but are used for rendering. For 1222 * example, if you are doing your own rendering and want to render 1223 * some text (or even HTML), you could make use of 1224 * <code>JLabel</code>'s text rendering support and have it paint 1225 * directly by way of this method, without adding the label to the 1226 * visible containment hierarchy. 1227 * <p> 1228 * This method makes use of <code>CellRendererPane</code> to handle 1229 * the actual painting, and is only recommended if you use one 1230 * component for rendering. If you make use of multiple components 1231 * to handle the rendering, as <code>JTable</code> does, use 1232 * <code>CellRendererPane</code> directly. Otherwise, as described 1233 * below, you could end up with a <code>CellRendererPane</code> 1234 * per <code>Component</code>. 1235 * <p> 1236 * If <code>c</code>'s parent is not a <code>CellRendererPane</code>, 1237 * a new <code>CellRendererPane</code> is created, <code>c</code> is 1238 * added to it, and the <code>CellRendererPane</code> is added to 1239 * <code>p</code>. If <code>c</code>'s parent is a 1240 * <code>CellRendererPane</code> and the <code>CellRendererPane</code>s 1241 * parent is not <code>p</code>, it is added to <code>p</code>. 1242 * <p> 1243 * The component should either descend from <code>JComponent</code> 1244 * or be another kind of lightweight component. 1245 * A lightweight component is one whose "lightweight" property 1246 * (returned by the <code>Component</code> 1247 * <code>isLightweight</code> method) 1248 * is true. If the Component is not lightweight, bad things map happen: 1249 * crashes, exceptions, painting problems... 1250 * 1251 * @param g the <code>Graphics</code> object to draw on 1252 * @param c the <code>Component</code> to draw 1253 * @param p the intermediate <code>Container</code> 1254 * @param x an int specifying the left side of the area draw in, in pixels, 1255 * measured from the left edge of the graphics context 1256 * @param y an int specifying the top of the area to draw in, in pixels 1257 * measured down from the top edge of the graphics context 1258 * @param w an int specifying the width of the area draw in, in pixels 1259 * @param h an int specifying the height of the area draw in, in pixels 1260 * 1261 * @see CellRendererPane 1262 * @see java.awt.Component#isLightweight 1263 */ 1264 public static void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) { 1265 getCellRendererPane(c, p).paintComponent(g, c, p, x, y, w, h,false); 1266 } 1267 1268 /** 1269 * Paints a component to the specified <code>Graphics</code>. This 1270 * is a cover method for 1271 * {@link #paintComponent(Graphics,Component,Container,int,int,int,int)}. 1272 * Refer to it for more information. 1273 * 1274 * @param g the <code>Graphics</code> object to draw on 1275 * @param c the <code>Component</code> to draw 1276 * @param p the intermediate <code>Container</code> 1277 * @param r the <code>Rectangle</code> to draw in 1278 * 1279 * @see #paintComponent(Graphics,Component,Container,int,int,int,int) 1280 * @see CellRendererPane 1281 */ 1282 public static void paintComponent(Graphics g, Component c, Container p, Rectangle r) { 1283 paintComponent(g, c, p, r.x, r.y, r.width, r.height); 1284 } 1285 1286 1287 /* 1288 * Ensures that cell renderer <code>c</code> has a 1289 * <code>ComponentShell</code> parent and that 1290 * the shell's parent is p. 1291 */ 1292 private static CellRendererPane getCellRendererPane(Component c, Container p) { 1293 Container shell = c.getParent(); 1294 if (shell instanceof CellRendererPane) { 1295 if (shell.getParent() != p) { 1296 p.add(shell); 1297 } 1298 } else { 1299 shell = new CellRendererPane(); 1300 shell.add(c); 1301 p.add(shell); 1302 } 1303 return (CellRendererPane)shell; 1304 } 1305 1306 /** 1307 * A simple minded look and feel change: ask each node in the tree 1308 * to <code>updateUI()</code> -- that is, to initialize its UI property 1309 * with the current look and feel. 1310 * 1311 * @param c the component 1312 */ 1313 public static void updateComponentTreeUI(Component c) { 1314 updateComponentTreeUI0(c); 1315 c.invalidate(); 1316 c.validate(); 1317 c.repaint(); 1318 } 1319 1320 private static void updateComponentTreeUI0(Component c) { 1321 if (c instanceof JComponent) { 1322 JComponent jc = (JComponent) c; 1323 jc.updateUI(); 1324 JPopupMenu jpm =jc.getComponentPopupMenu(); 1325 if(jpm != null) { 1326 updateComponentTreeUI(jpm); 1327 } 1328 } 1329 Component[] children = null; 1330 if (c instanceof JMenu) { 1331 children = ((JMenu)c).getMenuComponents(); 1332 } 1333 else if (c instanceof Container) { 1334 children = ((Container)c).getComponents(); 1335 } 1336 if (children != null) { 1337 for (Component child : children) { 1338 updateComponentTreeUI0(child); 1339 } 1340 } 1341 } 1342 1343 1344 /** 1345 * Causes <i>doRun.run()</i> to be executed asynchronously on the 1346 * AWT event dispatching thread. This will happen after all 1347 * pending AWT events have been processed. This method should 1348 * be used when an application thread needs to update the GUI. 1349 * In the following example the <code>invokeLater</code> call queues 1350 * the <code>Runnable</code> object <code>doHelloWorld</code> 1351 * on the event dispatching thread and 1352 * then prints a message. 1353 * <pre> 1354 * Runnable doHelloWorld = new Runnable() { 1355 * public void run() { 1356 * System.out.println("Hello World on " + Thread.currentThread()); 1357 * } 1358 * }; 1359 * 1360 * SwingUtilities.invokeLater(doHelloWorld); 1361 * System.out.println("This might well be displayed before the other message."); 1362 * </pre> 1363 * If invokeLater is called from the event dispatching thread -- 1364 * for example, from a JButton's ActionListener -- the <i>doRun.run()</i> will 1365 * still be deferred until all pending events have been processed. 1366 * Note that if the <i>doRun.run()</i> throws an uncaught exception 1367 * the event dispatching thread will unwind (not the current thread). 1368 * <p> 1369 * Additional documentation and examples for this method can be 1370 * found in 1371 * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency in Swing</a>. 1372 * <p> 1373 * As of 1.3 this method is just a cover for <code>java.awt.EventQueue.invokeLater()</code>. 1374 * <p> 1375 * Unlike the rest of Swing, this method can be invoked from any thread. 1376 * 1377 * @param doRun the instance of {@code Runnable} 1378 * @see #invokeAndWait 1379 */ 1380 public static void invokeLater(Runnable doRun) { 1381 EventQueue.invokeLater(doRun); 1382 } 1383 1384 1385 /** 1386 * Causes <code>doRun.run()</code> to be executed synchronously on the 1387 * AWT event dispatching thread. This call blocks until 1388 * all pending AWT events have been processed and (then) 1389 * <code>doRun.run()</code> returns. This method should 1390 * be used when an application thread needs to update the GUI. 1391 * It shouldn't be called from the event dispatching thread. 1392 * Here's an example that creates a new application thread 1393 * that uses <code>invokeAndWait</code> to print a string from the event 1394 * dispatching thread and then, when that's finished, print 1395 * a string from the application thread. 1396 * <pre> 1397 * final Runnable doHelloWorld = new Runnable() { 1398 * public void run() { 1399 * System.out.println("Hello World on " + Thread.currentThread()); 1400 * } 1401 * }; 1402 * 1403 * Thread appThread = new Thread() { 1404 * public void run() { 1405 * try { 1406 * SwingUtilities.invokeAndWait(doHelloWorld); 1407 * } 1408 * catch (Exception e) { 1409 * e.printStackTrace(); 1410 * } 1411 * System.out.println("Finished on " + Thread.currentThread()); 1412 * } 1413 * }; 1414 * appThread.start(); 1415 * </pre> 1416 * Note that if the <code>Runnable.run</code> method throws an 1417 * uncaught exception 1418 * (on the event dispatching thread) it's caught and rethrown, as 1419 * an <code>InvocationTargetException</code>, on the caller's thread. 1420 * <p> 1421 * Additional documentation and examples for this method can be 1422 * found in 1423 * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency in Swing</a>. 1424 * <p> 1425 * As of 1.3 this method is just a cover for 1426 * <code>java.awt.EventQueue.invokeAndWait()</code>. 1427 * 1428 * @param doRun the instance of {@code Runnable} 1429 * @exception InterruptedException if we're interrupted while waiting for 1430 * the event dispatching thread to finish executing 1431 * <code>doRun.run()</code> 1432 * @exception InvocationTargetException if an exception is thrown 1433 * while running <code>doRun</code> 1434 * 1435 * @see #invokeLater 1436 */ 1437 public static void invokeAndWait(final Runnable doRun) 1438 throws InterruptedException, InvocationTargetException 1439 { 1440 EventQueue.invokeAndWait(doRun); 1441 } 1442 1443 /** 1444 * Returns true if the current thread is an AWT event dispatching thread. 1445 * <p> 1446 * As of 1.3 this method is just a cover for 1447 * <code>java.awt.EventQueue.isDispatchThread()</code>. 1448 * 1449 * @return true if the current thread is an AWT event dispatching thread 1450 */ 1451 public static boolean isEventDispatchThread() 1452 { 1453 return EventQueue.isDispatchThread(); 1454 } 1455 1456 1457 /* 1458 * --- Accessibility Support --- 1459 * 1460 */ 1461 1462 /** 1463 * Get the index of this object in its accessible parent.<p> 1464 * 1465 * Note: as of the Java 2 platform v1.3, it is recommended that developers call 1466 * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead 1467 * of using this method. 1468 * 1469 * @param c the component 1470 * @return -1 of this object does not have an accessible parent. 1471 * Otherwise, the index of the child in its accessible parent. 1472 */ 1473 public static int getAccessibleIndexInParent(Component c) { 1474 return c.getAccessibleContext().getAccessibleIndexInParent(); 1475 } 1476 1477 /** 1478 * Returns the <code>Accessible</code> child contained at the 1479 * local coordinate <code>Point</code>, if one exists. 1480 * Otherwise returns <code>null</code>. 1481 * 1482 * @param c the component 1483 * @param p the local coordinate 1484 * @return the <code>Accessible</code> at the specified location, 1485 * if it exists; otherwise <code>null</code> 1486 */ 1487 public static Accessible getAccessibleAt(Component c, Point p) { 1488 if (c instanceof Container) { 1489 return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p); 1490 } else if (c instanceof Accessible) { 1491 Accessible a = (Accessible) c; 1492 if (a != null) { 1493 AccessibleContext ac = a.getAccessibleContext(); 1494 if (ac != null) { 1495 AccessibleComponent acmp; 1496 Point location; 1497 int nchildren = ac.getAccessibleChildrenCount(); 1498 for (int i=0; i < nchildren; i++) { 1499 a = ac.getAccessibleChild(i); 1500 if ((a != null)) { 1501 ac = a.getAccessibleContext(); 1502 if (ac != null) { 1503 acmp = ac.getAccessibleComponent(); 1504 if ((acmp != null) && (acmp.isShowing())) { 1505 location = acmp.getLocation(); 1550 public static int getAccessibleChildrenCount(Component c) { 1551 return c.getAccessibleContext().getAccessibleChildrenCount(); 1552 } 1553 1554 /** 1555 * Return the nth Accessible child of the object. <p> 1556 * 1557 * Note: as of the Java 2 platform v1.3, it is recommended that developers call 1558 * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead 1559 * of using this method. 1560 * 1561 * @param c the component 1562 * @param i zero-based index of child 1563 * @return the nth Accessible child of the object 1564 */ 1565 public static Accessible getAccessibleChild(Component c, int i) { 1566 return c.getAccessibleContext().getAccessibleChild(i); 1567 } 1568 1569 /** 1570 * Return the child <code>Component</code> of the specified 1571 * <code>Component</code> that is the focus owner, if any. 1572 * 1573 * @param c the root of the <code>Component</code> hierarchy to 1574 * search for the focus owner 1575 * @return the focus owner, or <code>null</code> if there is no focus 1576 * owner, or if the focus owner is not <code>comp</code>, or a 1577 * descendant of <code>comp</code> 1578 * 1579 * @see java.awt.KeyboardFocusManager#getFocusOwner 1580 * @deprecated As of 1.4, replaced by 1581 * <code>KeyboardFocusManager.getFocusOwner()</code>. 1582 */ 1583 @Deprecated 1584 public static Component findFocusOwner(Component c) { 1585 Component focusOwner = KeyboardFocusManager. 1586 getCurrentKeyboardFocusManager().getFocusOwner(); 1587 1588 // verify focusOwner is a descendant of c 1589 for (Component temp = focusOwner; temp != null; 1590 temp = (temp instanceof Window) ? null : temp.getParent()) 1591 { 1592 if (temp == c) { 1593 return focusOwner; 1594 } 1595 } 1596 1597 return null; 1598 } 1599 1600 /** 1601 * If c is a JRootPane descendant return its JRootPane ancestor. 1631 } 1632 if (p instanceof Applet) { 1633 applet = p; 1634 } 1635 } 1636 return applet; 1637 } 1638 1639 static JComponent getPaintingOrigin(JComponent c) { 1640 Container p = c; 1641 while ((p = p.getParent()) instanceof JComponent) { 1642 JComponent jp = (JComponent) p; 1643 if (jp.isPaintingOrigin()) { 1644 return jp; 1645 } 1646 } 1647 return null; 1648 } 1649 1650 /** 1651 * Process the key bindings for the <code>Component</code> associated with 1652 * <code>event</code>. This method is only useful if 1653 * <code>event.getComponent()</code> does not descend from 1654 * <code>JComponent</code>, or your are not invoking 1655 * <code>super.processKeyEvent</code> from within your 1656 * <code>JComponent</code> subclass. <code>JComponent</code> 1657 * automatically processes bindings from within its 1658 * <code>processKeyEvent</code> method, hence you rarely need 1659 * to directly invoke this method. 1660 * 1661 * @param event KeyEvent used to identify which bindings to process, as 1662 * well as which Component has focus. 1663 * @return true if a binding has found and processed 1664 * @since 1.4 1665 */ 1666 public static boolean processKeyBindings(KeyEvent event) { 1667 if (event != null) { 1668 if (event.isConsumed()) { 1669 return false; 1670 } 1671 1672 Component component = event.getComponent(); 1673 boolean pressed = (event.getID() == KeyEvent.KEY_PRESSED); 1674 1675 if (!isValidKeyEventForKeyBindings(event)) { 1676 return false; 1677 } 1678 // Find the first JComponent in the ancestor hierarchy, and 1679 // invoke processKeyBindings on it 1680 while (component != null) { 1681 if (component instanceof JComponent) { 1682 return ((JComponent)component).processKeyBindings( 1683 event, pressed); 1684 } 1685 if ((component instanceof Applet) || 1686 (component instanceof Window)) { 1687 // No JComponents, if Window or Applet parent, process 1688 // WHEN_IN_FOCUSED_WINDOW bindings. 1689 return JComponent.processKeyBindingsForAllComponents( 1690 event, (Container)component, pressed); 1691 } 1692 component = component.getParent(); 1693 } 1694 } 1695 return false; 1696 } 1697 1698 /** 1699 * Returns true if the <code>e</code> is a valid KeyEvent to use in 1700 * processing the key bindings associated with JComponents. 1701 */ 1702 static boolean isValidKeyEventForKeyBindings(KeyEvent e) { 1703 return true; 1704 } 1705 1706 /** 1707 * Invokes <code>actionPerformed</code> on <code>action</code> if 1708 * <code>action</code> is enabled (and non-{@code null}). The command for the 1709 * ActionEvent is determined by: 1710 * <ol> 1711 * <li>If the action was registered via 1712 * <code>registerKeyboardAction</code>, then the command string 1713 * passed in ({@code null} will be used if {@code null} was passed in). 1714 * <li>Action value with name Action.ACTION_COMMAND_KEY, unless {@code null}. 1715 * <li>String value of the KeyEvent, unless <code>getKeyChar</code> 1716 * returns KeyEvent.CHAR_UNDEFINED.. 1717 * </ol> 1718 * This will return true if <code>action</code> is non-{@code null} and 1719 * actionPerformed is invoked on it. 1720 * 1721 * @param action an action 1722 * @param ks a key stroke 1723 * @param event a key event 1724 * @param sender a sender 1725 * @param modifiers action modifiers 1726 * @return {@code true} if {@code action} is non-{@code null} and 1727 * actionPerformed is invoked on it. 1728 * 1729 * @since 1.3 1730 */ 1731 public static boolean notifyAction(Action action, KeyStroke ks, 1732 KeyEvent event, Object sender, 1733 int modifiers) { 1734 if (action == null) { 1735 return false; 1736 } 1737 if (action instanceof UIAction) { 1738 if (!((UIAction)action).isEnabled(sender)) { 1761 1762 if (commandO != null) { 1763 command = commandO.toString(); 1764 } 1765 else if (!stayNull && event.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { 1766 command = String.valueOf(event.getKeyChar()); 1767 } 1768 else { 1769 // Do null for undefined chars, or if registerKeyboardAction 1770 // was called with a null. 1771 command = null; 1772 } 1773 action.actionPerformed(new ActionEvent(sender, 1774 ActionEvent.ACTION_PERFORMED, command, event.getWhen(), 1775 modifiers)); 1776 return true; 1777 } 1778 1779 1780 /** 1781 * Convenience method to change the UI InputMap for <code>component</code> 1782 * to <code>uiInputMap</code>. If <code>uiInputMap</code> is {@code null}, 1783 * this removes any previously installed UI InputMap. 1784 * 1785 * @param component a component 1786 * @param type a type 1787 * @param uiInputMap an {@code InputMap} 1788 * @since 1.3 1789 */ 1790 public static void replaceUIInputMap(JComponent component, int type, 1791 InputMap uiInputMap) { 1792 InputMap map = component.getInputMap(type, (uiInputMap != null)); 1793 1794 while (map != null) { 1795 InputMap parent = map.getParent(); 1796 if (parent == null || (parent instanceof UIResource)) { 1797 map.setParent(uiInputMap); 1798 return; 1799 } 1800 map = parent; 1801 } 1802 } 1803 1804 1805 /** 1806 * Convenience method to change the UI ActionMap for <code>component</code> 1807 * to <code>uiActionMap</code>. If <code>uiActionMap</code> is {@code null}, 1808 * this removes any previously installed UI ActionMap. 1809 * 1810 * @param component a component 1811 * @param uiActionMap an {@code ActionMap} 1812 * @since 1.3 1813 */ 1814 public static void replaceUIActionMap(JComponent component, 1815 ActionMap uiActionMap) { 1816 ActionMap map = component.getActionMap((uiActionMap != null)); 1817 1818 while (map != null) { 1819 ActionMap parent = map.getParent(); 1820 if (parent == null || (parent instanceof UIResource)) { 1821 map.setParent(uiActionMap); 1822 return; 1823 } 1824 map = parent; 1825 } 1826 } 1827 1828 1829 /** 1830 * Returns the InputMap provided by the UI for condition 1831 * <code>condition</code> in component <code>component</code>. 1832 * <p>This will return {@code null} if the UI has not installed an InputMap 1833 * of the specified type. 1834 * 1835 * @param component a component 1836 * @param condition a condition 1837 * @return the {@code ActionMap} provided by the UI for {@code condition} 1838 * in the component, or {@code null} if the UI has not installed 1839 * an InputMap of the specified type. 1840 * @since 1.3 1841 */ 1842 public static InputMap getUIInputMap(JComponent component, int condition) { 1843 InputMap map = component.getInputMap(condition, false); 1844 while (map != null) { 1845 InputMap parent = map.getParent(); 1846 if (parent instanceof UIResource) { 1847 return parent; 1848 } 1849 map = parent; 1850 } 1851 return null; 1852 } 1853 1854 /** 1855 * Returns the ActionMap provided by the UI 1856 * in component <code>component</code>. 1857 * <p>This will return {@code null} if the UI has not installed an ActionMap. 1858 * 1859 * @param component a component 1860 * @return the {@code ActionMap} provided by the UI in the component, 1861 * or {@code null} if the UI has not installed an ActionMap. 1862 * @since 1.3 1863 */ 1864 public static ActionMap getUIActionMap(JComponent component) { 1865 ActionMap map = component.getActionMap(false); 1866 while (map != null) { 1867 ActionMap parent = map.getParent(); 1868 if (parent instanceof UIResource) { 1869 return parent; 1870 } 1871 map = parent; 1872 } 1873 return null; 1874 } 1875 1876 1996 1997 static Class<?> loadSystemClass(String className) throws ClassNotFoundException { 1998 ReflectUtil.checkPackageAccess(className); 1999 return Class.forName(className, true, Thread.currentThread(). 2000 getContextClassLoader()); 2001 } 2002 2003 2004 /* 2005 * Convenience function for determining ComponentOrientation. Helps us 2006 * avoid having Munge directives throughout the code. 2007 */ 2008 static boolean isLeftToRight( Component c ) { 2009 return c.getComponentOrientation().isLeftToRight(); 2010 } 2011 private SwingUtilities() { 2012 throw new Error("SwingUtilities is just a container for static methods"); 2013 } 2014 2015 /** 2016 * Returns true if the Icon <code>icon</code> is an instance of 2017 * ImageIcon, and the image it contains is the same as <code>image</code>. 2018 */ 2019 static boolean doesIconReferenceImage(Icon icon, Image image) { 2020 Image iconImage = (icon != null && (icon instanceof ImageIcon)) ? 2021 ((ImageIcon)icon).getImage() : null; 2022 return (iconImage == image); 2023 } 2024 2025 /** 2026 * Returns index of the first occurrence of <code>mnemonic</code> 2027 * within string <code>text</code>. Matching algorithm is not 2028 * case-sensitive. 2029 * 2030 * @param text The text to search through, may be {@code null} 2031 * @param mnemonic The mnemonic to find the character for. 2032 * @return index into the string if exists, otherwise -1 2033 */ 2034 static int findDisplayedMnemonicIndex(String text, int mnemonic) { 2035 if (text == null || mnemonic == '\0') { 2036 return -1; 2037 } 2038 2039 char uc = Character.toUpperCase((char)mnemonic); 2040 char lc = Character.toLowerCase((char)mnemonic); 2041 2042 int uci = text.indexOf(uc); 2043 int lci = text.indexOf(lc); 2044 2045 if (uci == -1) { 2046 return lci; 2047 } else if(lci == -1) { 2048 return uci; 2049 } else { 2050 return (lci < uci) ? lci : uci; 2051 } 2052 } 2053 2054 /** 2055 * Stores the position and size of 2056 * the inner painting area of the specified component 2057 * in <code>r</code> and returns <code>r</code>. 2058 * The position and size specify the bounds of the component, 2059 * adjusted so as not to include the border area (the insets). 2060 * This method is useful for classes 2061 * that implement painting code. 2062 * 2063 * @param c the JComponent in question; if {@code null}, this method returns {@code null} 2064 * @param r the Rectangle instance to be modified; 2065 * may be {@code null} 2066 * @return {@code null} if the Component is {@code null}; 2067 * otherwise, returns the passed-in rectangle (if non-{@code null}) 2068 * or a new rectangle specifying position and size information 2069 * 2070 * @since 1.4 2071 */ 2072 public static Rectangle calculateInnerArea(JComponent c, Rectangle r) { 2073 if (c == null) { 2074 return null; 2075 } 2076 Rectangle rect = r; 2077 Insets insets = c.getInsets(); | 54 public class SwingUtilities implements SwingConstants 55 { 56 // These states are system-wide, rather than AppContext wide. 57 private static boolean canAccessEventQueue = false; 58 private static boolean eventQueueTested = false; 59 60 /** 61 * Indicates if we should change the drop target when a 62 * {@code TransferHandler} is set. 63 */ 64 private static boolean suppressDropSupport; 65 66 /** 67 * Indiciates if we've checked the system property for suppressing 68 * drop support. 69 */ 70 private static boolean checkedSuppressDropSupport; 71 72 73 /** 74 * Returns true if {@code setTransferHandler} should change the 75 * {@code DropTarget}. 76 */ 77 private static boolean getSuppressDropTarget() { 78 if (!checkedSuppressDropSupport) { 79 suppressDropSupport = Boolean.valueOf( 80 AccessController.doPrivileged( 81 new GetPropertyAction("suppressSwingDropSupport"))); 82 checkedSuppressDropSupport = true; 83 } 84 return suppressDropSupport; 85 } 86 87 /** 88 * Installs a {@code DropTarget} on the component as necessary for a 89 * {@code TransferHandler} change. 90 */ 91 static void installSwingDropTargetAsNecessary(Component c, 92 TransferHandler t) { 93 94 if (!getSuppressDropTarget()) { 95 DropTarget dropHandler = c.getDropTarget(); 113 */ 114 public static final boolean isRectangleContainingRectangle(Rectangle a,Rectangle b) { 115 return b.x >= a.x && (b.x + b.width) <= (a.x + a.width) && 116 b.y >= a.y && (b.y + b.height) <= (a.y + a.height); 117 } 118 119 /** 120 * Return the rectangle (0,0,bounds.width,bounds.height) for the component {@code aComponent} 121 * 122 * @param aComponent a component 123 * @return the local bounds for the component {@code aComponent} 124 */ 125 public static Rectangle getLocalBounds(Component aComponent) { 126 Rectangle b = new Rectangle(aComponent.getBounds()); 127 b.x = b.y = 0; 128 return b; 129 } 130 131 132 /** 133 * Returns the first {@code Window} ancestor of {@code c}, or 134 * {@code null} if {@code c} is not contained inside a {@code Window}. 135 * 136 * @param c {@code Component} to get {@code Window} ancestor 137 * of. 138 * @return the first {@code Window} ancestor of {@code c}, or 139 * {@code null} if {@code c} is not contained inside a 140 * {@code Window}. 141 * @since 1.3 142 */ 143 public static Window getWindowAncestor(Component c) { 144 for(Container p = c.getParent(); p != null; p = p.getParent()) { 145 if (p instanceof Window) { 146 return (Window)p; 147 } 148 } 149 return null; 150 } 151 152 /** 153 * Converts the location {@code x y} to the 154 * parents coordinate system, returning the location. 155 */ 156 static Point convertScreenLocationToParent(Container parent,int x, int y) { 157 for (Container p = parent; p != null; p = p.getParent()) { 158 if (p instanceof Window) { 159 Point point = new Point(x, y); 160 161 SwingUtilities.convertPointFromScreen(point, parent); 162 return point; 163 } 164 } 165 throw new Error("convertScreenLocationToParent: no window ancestor"); 166 } 167 168 /** 169 * Convert a {@code aPoint} in {@code source} coordinate system to 170 * {@code destination} coordinate system. 171 * If {@code source} is {@code null}, {@code aPoint} is assumed to be in {@code destination}'s 172 * root component coordinate system. 173 * If {@code destination} is {@code null}, {@code aPoint} will be converted to {@code source}'s 174 * root component coordinate system. 175 * If both {@code source} and {@code destination} are {@code null}, return {@code aPoint} 176 * without any conversion. 177 * 178 * @param source the source component 179 * @param aPoint the point 180 * @param destination the destination component 181 * 182 * @return the converted coordinate 183 */ 184 public static Point convertPoint(Component source,Point aPoint,Component destination) { 185 Point p; 186 187 if(source == null && destination == null) 188 return aPoint; 189 if(source == null) { 190 source = getWindowAncestor(destination); 191 if(source == null) 192 throw new Error("Source component not connected to component tree hierarchy"); 193 } 194 p = new Point(aPoint); 195 convertPointToScreen(p,source); 196 if(destination == null) { 197 destination = getWindowAncestor(source); 198 if(destination == null) 199 throw new Error("Destination component not connected to component tree hierarchy"); 200 } 201 convertPointFromScreen(p,destination); 202 return p; 203 } 204 205 /** 206 * Convert the point {@code (x,y)} in {@code source} coordinate system to 207 * {@code destination} coordinate system. 208 * If {@code source} is {@code null}, {@code (x,y)} is assumed to be in {@code destination}'s 209 * root component coordinate system. 210 * If {@code destination} is {@code null}, {@code (x,y)} will be converted to {@code source}'s 211 * root component coordinate system. 212 * If both {@code source} and {@code destination} are {@code null}, return {@code (x,y)} 213 * without any conversion. 214 * 215 * @param source the source component 216 * @param x the x-coordinate of the point 217 * @param y the y-coordinate of the point 218 * @param destination the destination component 219 * 220 * @return the converted coordinate 221 */ 222 public static Point convertPoint(Component source,int x, int y,Component destination) { 223 Point point = new Point(x,y); 224 return convertPoint(source,point,destination); 225 } 226 227 /** 228 * Convert the rectangle {@code aRectangle} in {@code source} coordinate system to 229 * {@code destination} coordinate system. 230 * If {@code source} is {@code null}, {@code aRectangle} is assumed to be in {@code destination}'s 231 * root component coordinate system. 232 * If {@code destination} is {@code null}, {@code aRectangle} will be converted to {@code source}'s 233 * root component coordinate system. 234 * If both {@code source} and {@code destination} are {@code null}, return {@code aRectangle} 235 * without any conversion. 236 * 237 * @param source the source component 238 * @param aRectangle a rectangle 239 * @param destination the destination component 240 * 241 * @return the converted rectangle 242 */ 243 public static Rectangle convertRectangle(Component source,Rectangle aRectangle,Component destination) { 244 Point point = new Point(aRectangle.x,aRectangle.y); 245 point = convertPoint(source,point,destination); 246 return new Rectangle(point.x,point.y,aRectangle.width,aRectangle.height); 247 } 248 249 /** 250 * Convenience method for searching above {@code comp} in the 251 * component hierarchy and returns the first object of class {@code c} it 252 * finds. Can return {@code null}, if a class {@code c} cannot be found. 253 * 254 * @param c the class of a component 255 * @param comp the component 256 * 257 * @return the ancestor of the {@code comp}, 258 * or {@code null} if {@code c} cannot be found. 259 */ 260 public static Container getAncestorOfClass(Class<?> c, Component comp) 261 { 262 if(comp == null || c == null) 263 return null; 264 265 Container parent = comp.getParent(); 266 while(parent != null && !(c.isInstance(parent))) 267 parent = parent.getParent(); 268 return parent; 269 } 270 271 /** 272 * Convenience method for searching above {@code comp} in the 273 * component hierarchy and returns the first object of {@code name} it 274 * finds. Can return {@code null}, if {@code name} cannot be found. 275 * 276 * @param name the name of a component 277 * @param comp the component 278 * 279 * @return the ancestor of the {@code comp}, 280 * or {@code null} if {@code name} cannot be found. 281 */ 282 public static Container getAncestorNamed(String name, Component comp) { 283 if(comp == null || name == null) 284 return null; 285 286 Container parent = comp.getParent(); 287 while(parent != null && !(name.equals(parent.getName()))) 288 parent = parent.getParent(); 289 return parent; 290 } 291 292 /** 293 * Returns the deepest visible descendent Component of {@code parent} 294 * that contains the location {@code x}, {@code y}. 295 * If {@code parent} does not contain the specified location, 296 * then {@code null} is returned. If {@code parent} is not a 297 * container, or none of {@code parent}'s visible descendents 298 * contain the specified location, {@code parent} is returned. 299 * 300 * @param parent the root component to begin the search 301 * @param x the x target location 302 * @param y the y target location 303 * 304 * @return the deepest component 305 */ 306 public static Component getDeepestComponentAt(Component parent, int x, int y) { 307 if (!parent.contains(x, y)) { 308 return null; 309 } 310 if (parent instanceof Container) { 311 Component components[] = ((Container)parent).getComponents(); 312 for (Component comp : components) { 313 if (comp != null && comp.isVisible()) { 314 Point loc = comp.getLocation(); 315 if (comp instanceof Container) { 316 comp = getDeepestComponentAt(comp, x - loc.x, y - loc.y); 317 } else { 318 comp = comp.getComponentAt(x - loc.x, y - loc.y); 319 } 320 if (comp != null && comp.isVisible()) { 321 return comp; 322 } 323 } 324 } 325 } 326 return parent; 327 } 328 329 330 /** 331 * Returns a MouseEvent similar to {@code sourceEvent} except that its x 332 * and y members have been converted to {@code destination}'s coordinate 333 * system. If {@code source} is {@code null}, {@code sourceEvent} x and y members 334 * are assumed to be into {@code destination}'s root component coordinate system. 335 * If {@code destination} is {@code null}, the 336 * returned MouseEvent will be in {@code source}'s coordinate system. 337 * {@code sourceEvent} will not be changed. A new event is returned. 338 * the {@code source} field of the returned event will be set 339 * to {@code destination} if destination is non-{@code null} 340 * use the translateMouseEvent() method to translate a mouse event from 341 * one component to another without changing the source. 342 * 343 * @param source the source component 344 * @param sourceEvent the source mouse event 345 * @param destination the destination component 346 * 347 * @return the new mouse event 348 */ 349 public static MouseEvent convertMouseEvent(Component source, 350 MouseEvent sourceEvent, 351 Component destination) { 352 Point p = convertPoint(source,new Point(sourceEvent.getX(), 353 sourceEvent.getY()), 354 destination); 355 Component newSource; 356 357 if(destination != null) 358 newSource = destination; 359 else 471 y = pp.y; 472 } catch (IllegalComponentStateException icse) { 473 x = c.getX(); 474 y = c.getY(); 475 } 476 } else { 477 x = c.getX(); 478 y = c.getY(); 479 } 480 481 p.x -= x; 482 p.y -= y; 483 484 if(c instanceof java.awt.Window || c instanceof java.applet.Applet) 485 break; 486 c = c.getParent(); 487 } while(c != null); 488 } 489 490 /** 491 * Returns the first {@code Window} ancestor of {@code c}, or 492 * {@code null} if {@code c} is not contained inside a {@code Window}. 493 * <p> 494 * Note: This method provides the same functionality as 495 * {@code getWindowAncestor}. 496 * 497 * @param c {@code Component} to get {@code Window} ancestor 498 * of. 499 * @return the first {@code Window} ancestor of {@code c}, or 500 * {@code null} if {@code c} is not contained inside a 501 * {@code Window}. 502 */ 503 public static Window windowForComponent(Component c) { 504 return getWindowAncestor(c); 505 } 506 507 /** 508 * Return {@code true} if a component {@code a} descends from a component {@code b} 509 * 510 * @param a the first component 511 * @param b the second component 512 * @return {@code true} if a component {@code a} descends from a component {@code b} 513 */ 514 public static boolean isDescendingFrom(Component a,Component b) { 515 if(a == b) 516 return true; 517 for(Container p = a.getParent();p!=null;p=p.getParent()) 518 if(p == b) 519 return true; 520 return false; 521 } 522 523 524 /** 525 * Convenience to calculate the intersection of two rectangles 526 * without allocating a new rectangle. 527 * If the two rectangles don't intersect, 528 * then the returned rectangle begins at (0,0) 529 * and has zero width and height. 530 * 531 * @param x the X coordinate of the first rectangle's top-left point 532 * @param y the Y coordinate of the first rectangle's top-left point 533 * @param width the width of the first rectangle 534 * @param height the height of the first rectangle 535 * @param dest the second rectangle 536 * 537 * @return {@code dest}, modified to specify the intersection 538 */ 539 public static Rectangle computeIntersection(int x,int y,int width,int height,Rectangle dest) { 540 int x1 = (x > dest.x) ? x : dest.x; 541 int x2 = ((x+width) < (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width); 542 int y1 = (y > dest.y) ? y : dest.y; 543 int y2 = ((y + height) < (dest.y + dest.height) ? (y+height) : (dest.y + dest.height)); 544 545 dest.x = x1; 546 dest.y = y1; 547 dest.width = x2 - x1; 548 dest.height = y2 - y1; 549 550 // If rectangles don't intersect, return zero'd intersection. 551 if (dest.width < 0 || dest.height < 0) { 552 dest.x = dest.y = dest.width = dest.height = 0; 553 } 554 555 return dest; 556 } 557 558 /** 559 * Convenience method that calculates the union of two rectangles 560 * without allocating a new rectangle. 561 * 562 * @param x the x-coordinate of the first rectangle 563 * @param y the y-coordinate of the first rectangle 564 * @param width the width of the first rectangle 565 * @param height the height of the first rectangle 566 * @param dest the coordinates of the second rectangle; the union 567 * of the two rectangles is returned in this rectangle 568 * @return the {@code dest Rectangle} 569 */ 570 public static Rectangle computeUnion(int x,int y,int width,int height,Rectangle dest) { 571 int x1 = (x < dest.x) ? x : dest.x; 572 int x2 = ((x+width) > (dest.x + dest.width)) ? (x+width) : (dest.x + dest.width); 573 int y1 = (y < dest.y) ? y : dest.y; 574 int y2 = ((y+height) > (dest.y + dest.height)) ? (y+height) : (dest.y + dest.height); 575 576 dest.x = x1; 577 dest.y = y1; 578 dest.width = (x2 - x1); 579 dest.height= (y2 - y1); 580 return dest; 581 } 582 583 /** 584 * Convenience returning an array of rect representing the regions within 585 * {@code rectA} that do not overlap with {@code rectB}. If the 586 * two Rects do not overlap, returns an empty array 587 * 588 * @param rectA the first rectangle 589 * @param rectB the second rectangle 590 * 591 * @return an array of rectangles representing the regions within {@code rectA} 592 * that do not overlap with {@code rectB}. 593 */ 594 public static Rectangle[] computeDifference(Rectangle rectA,Rectangle rectB) { 595 if (rectB == null || !rectA.intersects(rectB) || isRectangleContainingRectangle(rectB,rectA)) { 596 return new Rectangle[0]; 597 } 598 599 Rectangle t = new Rectangle(); 600 Rectangle a=null,b=null,c=null,d=null; 601 Rectangle result[]; 602 int rectCount = 0; 603 604 /* rectA contains rectB */ 605 if (isRectangleContainingRectangle(rectA,rectB)) { 1198 1199 iconR.x += dx; 1200 iconR.y += dy; 1201 1202 if (lsb < 0) { 1203 // lsb is negative. Shift the x location so that the text is 1204 // visually drawn at the right location. 1205 textR.x -= lsb; 1206 1207 textR.width += lsb; 1208 } 1209 if (rsb > 0) { 1210 textR.width -= rsb; 1211 } 1212 1213 return text; 1214 } 1215 1216 1217 /** 1218 * Paints a component to the specified {@code Graphics}. 1219 * This method is primarily useful to render 1220 * {@code Component}s that don't exist as part of the visible 1221 * containment hierarchy, but are used for rendering. For 1222 * example, if you are doing your own rendering and want to render 1223 * some text (or even HTML), you could make use of 1224 * {@code JLabel}'s text rendering support and have it paint 1225 * directly by way of this method, without adding the label to the 1226 * visible containment hierarchy. 1227 * <p> 1228 * This method makes use of {@code CellRendererPane} to handle 1229 * the actual painting, and is only recommended if you use one 1230 * component for rendering. If you make use of multiple components 1231 * to handle the rendering, as {@code JTable} does, use 1232 * {@code CellRendererPane} directly. Otherwise, as described 1233 * below, you could end up with a {@code CellRendererPane} 1234 * per {@code Component}. 1235 * <p> 1236 * If {@code c}'s parent is not a {@code CellRendererPane}, 1237 * a new {@code CellRendererPane} is created, {@code c} is 1238 * added to it, and the {@code CellRendererPane} is added to 1239 * {@code p}. If {@code c}'s parent is a 1240 * {@code CellRendererPane} and the {@code CellRendererPane}s 1241 * parent is not {@code p}, it is added to {@code p}. 1242 * <p> 1243 * The component should either descend from {@code JComponent} 1244 * or be another kind of lightweight component. 1245 * A lightweight component is one whose "lightweight" property 1246 * (returned by the {@code Component} 1247 * {@code isLightweight} method) 1248 * is true. If the Component is not lightweight, bad things map happen: 1249 * crashes, exceptions, painting problems... 1250 * 1251 * @param g the {@code Graphics} object to draw on 1252 * @param c the {@code Component} to draw 1253 * @param p the intermediate {@code Container} 1254 * @param x an int specifying the left side of the area draw in, in pixels, 1255 * measured from the left edge of the graphics context 1256 * @param y an int specifying the top of the area to draw in, in pixels 1257 * measured down from the top edge of the graphics context 1258 * @param w an int specifying the width of the area draw in, in pixels 1259 * @param h an int specifying the height of the area draw in, in pixels 1260 * 1261 * @see CellRendererPane 1262 * @see java.awt.Component#isLightweight 1263 */ 1264 public static void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) { 1265 getCellRendererPane(c, p).paintComponent(g, c, p, x, y, w, h,false); 1266 } 1267 1268 /** 1269 * Paints a component to the specified {@code Graphics}. This 1270 * is a cover method for 1271 * {@link #paintComponent(Graphics,Component,Container,int,int,int,int)}. 1272 * Refer to it for more information. 1273 * 1274 * @param g the {@code Graphics} object to draw on 1275 * @param c the {@code Component} to draw 1276 * @param p the intermediate {@code Container} 1277 * @param r the {@code Rectangle} to draw in 1278 * 1279 * @see #paintComponent(Graphics,Component,Container,int,int,int,int) 1280 * @see CellRendererPane 1281 */ 1282 public static void paintComponent(Graphics g, Component c, Container p, Rectangle r) { 1283 paintComponent(g, c, p, r.x, r.y, r.width, r.height); 1284 } 1285 1286 1287 /* 1288 * Ensures that cell renderer {@code c} has a 1289 * {@code ComponentShell} parent and that 1290 * the shell's parent is p. 1291 */ 1292 private static CellRendererPane getCellRendererPane(Component c, Container p) { 1293 Container shell = c.getParent(); 1294 if (shell instanceof CellRendererPane) { 1295 if (shell.getParent() != p) { 1296 p.add(shell); 1297 } 1298 } else { 1299 shell = new CellRendererPane(); 1300 shell.add(c); 1301 p.add(shell); 1302 } 1303 return (CellRendererPane)shell; 1304 } 1305 1306 /** 1307 * A simple minded look and feel change: ask each node in the tree 1308 * to {@code updateUI()} -- that is, to initialize its UI property 1309 * with the current look and feel. 1310 * 1311 * @param c the component 1312 */ 1313 public static void updateComponentTreeUI(Component c) { 1314 updateComponentTreeUI0(c); 1315 c.invalidate(); 1316 c.validate(); 1317 c.repaint(); 1318 } 1319 1320 private static void updateComponentTreeUI0(Component c) { 1321 if (c instanceof JComponent) { 1322 JComponent jc = (JComponent) c; 1323 jc.updateUI(); 1324 JPopupMenu jpm =jc.getComponentPopupMenu(); 1325 if(jpm != null) { 1326 updateComponentTreeUI(jpm); 1327 } 1328 } 1329 Component[] children = null; 1330 if (c instanceof JMenu) { 1331 children = ((JMenu)c).getMenuComponents(); 1332 } 1333 else if (c instanceof Container) { 1334 children = ((Container)c).getComponents(); 1335 } 1336 if (children != null) { 1337 for (Component child : children) { 1338 updateComponentTreeUI0(child); 1339 } 1340 } 1341 } 1342 1343 1344 /** 1345 * Causes <i>doRun.run()</i> to be executed asynchronously on the 1346 * AWT event dispatching thread. This will happen after all 1347 * pending AWT events have been processed. This method should 1348 * be used when an application thread needs to update the GUI. 1349 * In the following example the {@code invokeLater} call queues 1350 * the {@code Runnable} object {@code doHelloWorld} 1351 * on the event dispatching thread and 1352 * then prints a message. 1353 * <pre> 1354 * Runnable doHelloWorld = new Runnable() { 1355 * public void run() { 1356 * System.out.println("Hello World on " + Thread.currentThread()); 1357 * } 1358 * }; 1359 * 1360 * SwingUtilities.invokeLater(doHelloWorld); 1361 * System.out.println("This might well be displayed before the other message."); 1362 * </pre> 1363 * If invokeLater is called from the event dispatching thread -- 1364 * for example, from a JButton's ActionListener -- the <i>doRun.run()</i> will 1365 * still be deferred until all pending events have been processed. 1366 * Note that if the <i>doRun.run()</i> throws an uncaught exception 1367 * the event dispatching thread will unwind (not the current thread). 1368 * <p> 1369 * Additional documentation and examples for this method can be 1370 * found in 1371 * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency in Swing</a>. 1372 * <p> 1373 * As of 1.3 this method is just a cover for {@code java.awt.EventQueue.invokeLater()}. 1374 * <p> 1375 * Unlike the rest of Swing, this method can be invoked from any thread. 1376 * 1377 * @param doRun the instance of {@code Runnable} 1378 * @see #invokeAndWait 1379 */ 1380 public static void invokeLater(Runnable doRun) { 1381 EventQueue.invokeLater(doRun); 1382 } 1383 1384 1385 /** 1386 * Causes {@code doRun.run()} to be executed synchronously on the 1387 * AWT event dispatching thread. This call blocks until 1388 * all pending AWT events have been processed and (then) 1389 * {@code doRun.run()} returns. This method should 1390 * be used when an application thread needs to update the GUI. 1391 * It shouldn't be called from the event dispatching thread. 1392 * Here's an example that creates a new application thread 1393 * that uses {@code invokeAndWait} to print a string from the event 1394 * dispatching thread and then, when that's finished, print 1395 * a string from the application thread. 1396 * <pre> 1397 * final Runnable doHelloWorld = new Runnable() { 1398 * public void run() { 1399 * System.out.println("Hello World on " + Thread.currentThread()); 1400 * } 1401 * }; 1402 * 1403 * Thread appThread = new Thread() { 1404 * public void run() { 1405 * try { 1406 * SwingUtilities.invokeAndWait(doHelloWorld); 1407 * } 1408 * catch (Exception e) { 1409 * e.printStackTrace(); 1410 * } 1411 * System.out.println("Finished on " + Thread.currentThread()); 1412 * } 1413 * }; 1414 * appThread.start(); 1415 * </pre> 1416 * Note that if the {@code Runnable.run} method throws an 1417 * uncaught exception 1418 * (on the event dispatching thread) it's caught and rethrown, as 1419 * an {@code InvocationTargetException}, on the caller's thread. 1420 * <p> 1421 * Additional documentation and examples for this method can be 1422 * found in 1423 * <A HREF="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html">Concurrency in Swing</a>. 1424 * <p> 1425 * As of 1.3 this method is just a cover for 1426 * {@code java.awt.EventQueue.invokeAndWait()}. 1427 * 1428 * @param doRun the instance of {@code Runnable} 1429 * @exception InterruptedException if we're interrupted while waiting for 1430 * the event dispatching thread to finish executing 1431 * {@code doRun.run()} 1432 * @exception InvocationTargetException if an exception is thrown 1433 * while running {@code doRun} 1434 * 1435 * @see #invokeLater 1436 */ 1437 public static void invokeAndWait(final Runnable doRun) 1438 throws InterruptedException, InvocationTargetException 1439 { 1440 EventQueue.invokeAndWait(doRun); 1441 } 1442 1443 /** 1444 * Returns true if the current thread is an AWT event dispatching thread. 1445 * <p> 1446 * As of 1.3 this method is just a cover for 1447 * {@code java.awt.EventQueue.isDispatchThread()}. 1448 * 1449 * @return true if the current thread is an AWT event dispatching thread 1450 */ 1451 public static boolean isEventDispatchThread() 1452 { 1453 return EventQueue.isDispatchThread(); 1454 } 1455 1456 1457 /* 1458 * --- Accessibility Support --- 1459 * 1460 */ 1461 1462 /** 1463 * Get the index of this object in its accessible parent.<p> 1464 * 1465 * Note: as of the Java 2 platform v1.3, it is recommended that developers call 1466 * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead 1467 * of using this method. 1468 * 1469 * @param c the component 1470 * @return -1 of this object does not have an accessible parent. 1471 * Otherwise, the index of the child in its accessible parent. 1472 */ 1473 public static int getAccessibleIndexInParent(Component c) { 1474 return c.getAccessibleContext().getAccessibleIndexInParent(); 1475 } 1476 1477 /** 1478 * Returns the {@code Accessible} child contained at the 1479 * local coordinate {@code Point}, if one exists. 1480 * Otherwise returns {@code null}. 1481 * 1482 * @param c the component 1483 * @param p the local coordinate 1484 * @return the {@code Accessible} at the specified location, 1485 * if it exists; otherwise {@code null} 1486 */ 1487 public static Accessible getAccessibleAt(Component c, Point p) { 1488 if (c instanceof Container) { 1489 return c.getAccessibleContext().getAccessibleComponent().getAccessibleAt(p); 1490 } else if (c instanceof Accessible) { 1491 Accessible a = (Accessible) c; 1492 if (a != null) { 1493 AccessibleContext ac = a.getAccessibleContext(); 1494 if (ac != null) { 1495 AccessibleComponent acmp; 1496 Point location; 1497 int nchildren = ac.getAccessibleChildrenCount(); 1498 for (int i=0; i < nchildren; i++) { 1499 a = ac.getAccessibleChild(i); 1500 if ((a != null)) { 1501 ac = a.getAccessibleContext(); 1502 if (ac != null) { 1503 acmp = ac.getAccessibleComponent(); 1504 if ((acmp != null) && (acmp.isShowing())) { 1505 location = acmp.getLocation(); 1550 public static int getAccessibleChildrenCount(Component c) { 1551 return c.getAccessibleContext().getAccessibleChildrenCount(); 1552 } 1553 1554 /** 1555 * Return the nth Accessible child of the object. <p> 1556 * 1557 * Note: as of the Java 2 platform v1.3, it is recommended that developers call 1558 * Component.AccessibleAWTComponent.getAccessibleIndexInParent() instead 1559 * of using this method. 1560 * 1561 * @param c the component 1562 * @param i zero-based index of child 1563 * @return the nth Accessible child of the object 1564 */ 1565 public static Accessible getAccessibleChild(Component c, int i) { 1566 return c.getAccessibleContext().getAccessibleChild(i); 1567 } 1568 1569 /** 1570 * Return the child {@code Component} of the specified 1571 * {@code Component} that is the focus owner, if any. 1572 * 1573 * @param c the root of the {@code Component} hierarchy to 1574 * search for the focus owner 1575 * @return the focus owner, or {@code null} if there is no focus 1576 * owner, or if the focus owner is not {@code comp}, or a 1577 * descendant of {@code comp} 1578 * 1579 * @see java.awt.KeyboardFocusManager#getFocusOwner 1580 * @deprecated As of 1.4, replaced by 1581 * {@code KeyboardFocusManager.getFocusOwner()}. 1582 */ 1583 @Deprecated 1584 public static Component findFocusOwner(Component c) { 1585 Component focusOwner = KeyboardFocusManager. 1586 getCurrentKeyboardFocusManager().getFocusOwner(); 1587 1588 // verify focusOwner is a descendant of c 1589 for (Component temp = focusOwner; temp != null; 1590 temp = (temp instanceof Window) ? null : temp.getParent()) 1591 { 1592 if (temp == c) { 1593 return focusOwner; 1594 } 1595 } 1596 1597 return null; 1598 } 1599 1600 /** 1601 * If c is a JRootPane descendant return its JRootPane ancestor. 1631 } 1632 if (p instanceof Applet) { 1633 applet = p; 1634 } 1635 } 1636 return applet; 1637 } 1638 1639 static JComponent getPaintingOrigin(JComponent c) { 1640 Container p = c; 1641 while ((p = p.getParent()) instanceof JComponent) { 1642 JComponent jp = (JComponent) p; 1643 if (jp.isPaintingOrigin()) { 1644 return jp; 1645 } 1646 } 1647 return null; 1648 } 1649 1650 /** 1651 * Process the key bindings for the {@code Component} associated with 1652 * {@code event}. This method is only useful if 1653 * {@code event.getComponent()} does not descend from 1654 * {@code JComponent}, or your are not invoking 1655 * {@code super.processKeyEvent} from within your 1656 * {@code JComponent} subclass. {@code JComponent} 1657 * automatically processes bindings from within its 1658 * {@code processKeyEvent} method, hence you rarely need 1659 * to directly invoke this method. 1660 * 1661 * @param event KeyEvent used to identify which bindings to process, as 1662 * well as which Component has focus. 1663 * @return true if a binding has found and processed 1664 * @since 1.4 1665 */ 1666 public static boolean processKeyBindings(KeyEvent event) { 1667 if (event != null) { 1668 if (event.isConsumed()) { 1669 return false; 1670 } 1671 1672 Component component = event.getComponent(); 1673 boolean pressed = (event.getID() == KeyEvent.KEY_PRESSED); 1674 1675 if (!isValidKeyEventForKeyBindings(event)) { 1676 return false; 1677 } 1678 // Find the first JComponent in the ancestor hierarchy, and 1679 // invoke processKeyBindings on it 1680 while (component != null) { 1681 if (component instanceof JComponent) { 1682 return ((JComponent)component).processKeyBindings( 1683 event, pressed); 1684 } 1685 if ((component instanceof Applet) || 1686 (component instanceof Window)) { 1687 // No JComponents, if Window or Applet parent, process 1688 // WHEN_IN_FOCUSED_WINDOW bindings. 1689 return JComponent.processKeyBindingsForAllComponents( 1690 event, (Container)component, pressed); 1691 } 1692 component = component.getParent(); 1693 } 1694 } 1695 return false; 1696 } 1697 1698 /** 1699 * Returns true if the {@code e} is a valid KeyEvent to use in 1700 * processing the key bindings associated with JComponents. 1701 */ 1702 static boolean isValidKeyEventForKeyBindings(KeyEvent e) { 1703 return true; 1704 } 1705 1706 /** 1707 * Invokes {@code actionPerformed} on {@code action} if 1708 * {@code action} is enabled (and non-{@code null}). The command for the 1709 * ActionEvent is determined by: 1710 * <ol> 1711 * <li>If the action was registered via 1712 * {@code registerKeyboardAction}, then the command string 1713 * passed in ({@code null} will be used if {@code null} was passed in). 1714 * <li>Action value with name Action.ACTION_COMMAND_KEY, unless {@code null}. 1715 * <li>String value of the KeyEvent, unless {@code getKeyChar} 1716 * returns KeyEvent.CHAR_UNDEFINED.. 1717 * </ol> 1718 * This will return true if {@code action} is non-{@code null} and 1719 * actionPerformed is invoked on it. 1720 * 1721 * @param action an action 1722 * @param ks a key stroke 1723 * @param event a key event 1724 * @param sender a sender 1725 * @param modifiers action modifiers 1726 * @return {@code true} if {@code action} is non-{@code null} and 1727 * actionPerformed is invoked on it. 1728 * 1729 * @since 1.3 1730 */ 1731 public static boolean notifyAction(Action action, KeyStroke ks, 1732 KeyEvent event, Object sender, 1733 int modifiers) { 1734 if (action == null) { 1735 return false; 1736 } 1737 if (action instanceof UIAction) { 1738 if (!((UIAction)action).isEnabled(sender)) { 1761 1762 if (commandO != null) { 1763 command = commandO.toString(); 1764 } 1765 else if (!stayNull && event.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { 1766 command = String.valueOf(event.getKeyChar()); 1767 } 1768 else { 1769 // Do null for undefined chars, or if registerKeyboardAction 1770 // was called with a null. 1771 command = null; 1772 } 1773 action.actionPerformed(new ActionEvent(sender, 1774 ActionEvent.ACTION_PERFORMED, command, event.getWhen(), 1775 modifiers)); 1776 return true; 1777 } 1778 1779 1780 /** 1781 * Convenience method to change the UI InputMap for {@code component} 1782 * to {@code uiInputMap}. If {@code uiInputMap} is {@code null}, 1783 * this removes any previously installed UI InputMap. 1784 * 1785 * @param component a component 1786 * @param type a type 1787 * @param uiInputMap an {@code InputMap} 1788 * @since 1.3 1789 */ 1790 public static void replaceUIInputMap(JComponent component, int type, 1791 InputMap uiInputMap) { 1792 InputMap map = component.getInputMap(type, (uiInputMap != null)); 1793 1794 while (map != null) { 1795 InputMap parent = map.getParent(); 1796 if (parent == null || (parent instanceof UIResource)) { 1797 map.setParent(uiInputMap); 1798 return; 1799 } 1800 map = parent; 1801 } 1802 } 1803 1804 1805 /** 1806 * Convenience method to change the UI ActionMap for {@code component} 1807 * to {@code uiActionMap}. If {@code uiActionMap} is {@code null}, 1808 * this removes any previously installed UI ActionMap. 1809 * 1810 * @param component a component 1811 * @param uiActionMap an {@code ActionMap} 1812 * @since 1.3 1813 */ 1814 public static void replaceUIActionMap(JComponent component, 1815 ActionMap uiActionMap) { 1816 ActionMap map = component.getActionMap((uiActionMap != null)); 1817 1818 while (map != null) { 1819 ActionMap parent = map.getParent(); 1820 if (parent == null || (parent instanceof UIResource)) { 1821 map.setParent(uiActionMap); 1822 return; 1823 } 1824 map = parent; 1825 } 1826 } 1827 1828 1829 /** 1830 * Returns the InputMap provided by the UI for condition 1831 * {@code condition} in component {@code component}. 1832 * <p>This will return {@code null} if the UI has not installed an InputMap 1833 * of the specified type. 1834 * 1835 * @param component a component 1836 * @param condition a condition 1837 * @return the {@code ActionMap} provided by the UI for {@code condition} 1838 * in the component, or {@code null} if the UI has not installed 1839 * an InputMap of the specified type. 1840 * @since 1.3 1841 */ 1842 public static InputMap getUIInputMap(JComponent component, int condition) { 1843 InputMap map = component.getInputMap(condition, false); 1844 while (map != null) { 1845 InputMap parent = map.getParent(); 1846 if (parent instanceof UIResource) { 1847 return parent; 1848 } 1849 map = parent; 1850 } 1851 return null; 1852 } 1853 1854 /** 1855 * Returns the ActionMap provided by the UI 1856 * in component {@code component}. 1857 * <p>This will return {@code null} if the UI has not installed an ActionMap. 1858 * 1859 * @param component a component 1860 * @return the {@code ActionMap} provided by the UI in the component, 1861 * or {@code null} if the UI has not installed an ActionMap. 1862 * @since 1.3 1863 */ 1864 public static ActionMap getUIActionMap(JComponent component) { 1865 ActionMap map = component.getActionMap(false); 1866 while (map != null) { 1867 ActionMap parent = map.getParent(); 1868 if (parent instanceof UIResource) { 1869 return parent; 1870 } 1871 map = parent; 1872 } 1873 return null; 1874 } 1875 1876 1996 1997 static Class<?> loadSystemClass(String className) throws ClassNotFoundException { 1998 ReflectUtil.checkPackageAccess(className); 1999 return Class.forName(className, true, Thread.currentThread(). 2000 getContextClassLoader()); 2001 } 2002 2003 2004 /* 2005 * Convenience function for determining ComponentOrientation. Helps us 2006 * avoid having Munge directives throughout the code. 2007 */ 2008 static boolean isLeftToRight( Component c ) { 2009 return c.getComponentOrientation().isLeftToRight(); 2010 } 2011 private SwingUtilities() { 2012 throw new Error("SwingUtilities is just a container for static methods"); 2013 } 2014 2015 /** 2016 * Returns true if the Icon {@code icon} is an instance of 2017 * ImageIcon, and the image it contains is the same as {@code image}. 2018 */ 2019 static boolean doesIconReferenceImage(Icon icon, Image image) { 2020 Image iconImage = (icon != null && (icon instanceof ImageIcon)) ? 2021 ((ImageIcon)icon).getImage() : null; 2022 return (iconImage == image); 2023 } 2024 2025 /** 2026 * Returns index of the first occurrence of {@code mnemonic} 2027 * within string {@code text}. Matching algorithm is not 2028 * case-sensitive. 2029 * 2030 * @param text The text to search through, may be {@code null} 2031 * @param mnemonic The mnemonic to find the character for. 2032 * @return index into the string if exists, otherwise -1 2033 */ 2034 static int findDisplayedMnemonicIndex(String text, int mnemonic) { 2035 if (text == null || mnemonic == '\0') { 2036 return -1; 2037 } 2038 2039 char uc = Character.toUpperCase((char)mnemonic); 2040 char lc = Character.toLowerCase((char)mnemonic); 2041 2042 int uci = text.indexOf(uc); 2043 int lci = text.indexOf(lc); 2044 2045 if (uci == -1) { 2046 return lci; 2047 } else if(lci == -1) { 2048 return uci; 2049 } else { 2050 return (lci < uci) ? lci : uci; 2051 } 2052 } 2053 2054 /** 2055 * Stores the position and size of 2056 * the inner painting area of the specified component 2057 * in {@code r} and returns {@code r}. 2058 * The position and size specify the bounds of the component, 2059 * adjusted so as not to include the border area (the insets). 2060 * This method is useful for classes 2061 * that implement painting code. 2062 * 2063 * @param c the JComponent in question; if {@code null}, this method returns {@code null} 2064 * @param r the Rectangle instance to be modified; 2065 * may be {@code null} 2066 * @return {@code null} if the Component is {@code null}; 2067 * otherwise, returns the passed-in rectangle (if non-{@code null}) 2068 * or a new rectangle specifying position and size information 2069 * 2070 * @since 1.4 2071 */ 2072 public static Rectangle calculateInnerArea(JComponent c, Rectangle r) { 2073 if (c == null) { 2074 return null; 2075 } 2076 Rectangle rect = r; 2077 Insets insets = c.getInsets(); |