1 /* 2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package javax.swing; 28 29 import com.sun.awt.AWTUtilities; 30 import sun.awt.AWTAccessor; 31 import sun.awt.SunToolkit; 32 33 import java.awt.*; 34 import java.beans.PropertyVetoException; 35 36 /** This is an implementation of the <code>DesktopManager</code>. 37 * It currently implements the basic behaviors for managing 38 * <code>JInternalFrame</code>s in an arbitrary parent. 39 * <code>JInternalFrame</code>s that are not children of a 40 * <code>JDesktop</code> will use this component 41 * to handle their desktop-like actions. 42 * <p>This class provides a policy for the various JInternalFrame methods, 43 * it is not meant to be called directly rather the various JInternalFrame 44 * methods will call into the DesktopManager.</p> 45 * @see JDesktopPane 46 * @see JInternalFrame 47 * @author David Kloba 48 * @author Steve Wilson 49 */ 50 public class DefaultDesktopManager implements DesktopManager, java.io.Serializable { 51 final static String HAS_BEEN_ICONIFIED_PROPERTY = "wasIconOnce"; 52 53 final static int DEFAULT_DRAG_MODE = 0; 54 final static int OUTLINE_DRAG_MODE = 1; 55 final static int FASTER_DRAG_MODE = 2; 56 57 int dragMode = DEFAULT_DRAG_MODE; 58 59 private transient Rectangle currentBounds = null; 60 private transient Graphics desktopGraphics = null; 61 private transient Rectangle desktopBounds = null; 62 private transient Rectangle[] floatingItems = {}; 63 64 /** 65 * Set to true when the user actually drags a frame vs clicks on it 66 * to start the drag operation. This is only used when dragging with 67 * FASTER_DRAG_MODE. 68 */ 69 private transient boolean didDrag; 70 71 /** Normally this method will not be called. If it is, it 72 * try to determine the appropriate parent from the desktopIcon of the frame. 73 * Will remove the desktopIcon from its parent if it successfully adds the frame. 74 */ 75 public void openFrame(JInternalFrame f) { 76 if(f.getDesktopIcon().getParent() != null) { 77 f.getDesktopIcon().getParent().add(f); 78 removeIconFor(f); 79 } 80 } 81 82 /** 83 * Removes the frame, and, if necessary, the 84 * <code>desktopIcon</code>, from its parent. 85 * @param f the <code>JInternalFrame</code> to be removed 86 */ 87 public void closeFrame(JInternalFrame f) { 88 JDesktopPane d = f.getDesktopPane(); 89 if (d == null) { 90 return; 91 } 92 boolean findNext = f.isSelected(); 93 Container c = f.getParent(); 94 JInternalFrame nextFrame = null; 95 if (findNext) { 96 nextFrame = d.getNextFrame(f); 97 try { f.setSelected(false); } catch (PropertyVetoException e2) { } 98 } 99 if(c != null) { 100 c.remove(f); // Removes the focus. 101 c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); 102 } 103 removeIconFor(f); 104 if(f.getNormalBounds() != null) 105 f.setNormalBounds(null); 106 if(wasIcon(f)) 107 setWasIcon(f, null); 108 if (nextFrame != null) { 109 try { nextFrame.setSelected(true); } 110 catch (PropertyVetoException e2) { } 111 } else if (findNext && d.getComponentCount() == 0) { 112 // It was selected and was the last component on the desktop. 113 d.requestFocus(); 114 } 115 } 116 117 /** 118 * Resizes the frame to fill its parents bounds. 119 * @param f the frame to be resized 120 */ 121 public void maximizeFrame(JInternalFrame f) { 122 if (f.isIcon()) { 123 try { 124 // In turn calls deiconifyFrame in the desktop manager. 125 // That method will handle the maximization of the frame. 126 f.setIcon(false); 127 } catch (PropertyVetoException e2) { 128 } 129 } else { 130 f.setNormalBounds(f.getBounds()); 131 Rectangle desktopBounds = f.getParent().getBounds(); 132 setBoundsForFrame(f, 0, 0, 133 desktopBounds.width, desktopBounds.height); 134 } 135 136 // Set the maximized frame as selected. 137 try { 138 f.setSelected(true); 139 } catch (PropertyVetoException e2) { 140 } 141 } 142 143 /** 144 * Restores the frame back to its size and position prior 145 * to a <code>maximizeFrame</code> call. 146 * @param f the <code>JInternalFrame</code> to be restored 147 */ 148 public void minimizeFrame(JInternalFrame f) { 149 // If the frame was an icon restore it back to an icon. 150 if (f.isIcon()) { 151 iconifyFrame(f); 152 return; 153 } 154 155 if ((f.getNormalBounds()) != null) { 156 Rectangle r = f.getNormalBounds(); 157 f.setNormalBounds(null); 158 try { f.setSelected(true); } catch (PropertyVetoException e2) { } 159 setBoundsForFrame(f, r.x, r.y, r.width, r.height); 160 } 161 } 162 163 /** 164 * Removes the frame from its parent and adds its 165 * <code>desktopIcon</code> to the parent. 166 * @param f the <code>JInternalFrame</code> to be iconified 167 */ 168 public void iconifyFrame(JInternalFrame f) { 169 JInternalFrame.JDesktopIcon desktopIcon; 170 Container c = f.getParent(); 171 JDesktopPane d = f.getDesktopPane(); 172 boolean findNext = f.isSelected(); 173 desktopIcon = f.getDesktopIcon(); 174 if(!wasIcon(f)) { 175 Rectangle r = getBoundsForIconOf(f); 176 desktopIcon.setBounds(r.x, r.y, r.width, r.height); 177 setWasIcon(f, Boolean.TRUE); 178 } 179 180 if (c == null || d == null) { 181 return; 182 } 183 184 if (c instanceof JLayeredPane) { 185 JLayeredPane lp = (JLayeredPane)c; 186 int layer = lp.getLayer(f); 187 lp.putLayer(desktopIcon, layer); 188 } 189 190 // If we are maximized we already have the normal bounds recorded 191 // don't try to re-record them, otherwise we incorrectly set the 192 // normal bounds to maximized state. 193 if (!f.isMaximum()) { 194 f.setNormalBounds(f.getBounds()); 195 } 196 d.setComponentOrderCheckingEnabled(false); 197 c.remove(f); 198 c.add(desktopIcon); 199 d.setComponentOrderCheckingEnabled(true); 200 c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); 201 if (findNext) { 202 if (d.selectFrame(true) == null) { 203 // The icon is the last frame. 204 f.restoreSubcomponentFocus(); 205 } 206 } 207 } 208 209 /** 210 * Removes the desktopIcon from its parent and adds its frame 211 * to the parent. 212 * @param f the <code>JInternalFrame</code> to be de-iconified 213 */ 214 public void deiconifyFrame(JInternalFrame f) { 215 JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon(); 216 Container c = desktopIcon.getParent(); 217 JDesktopPane d = f.getDesktopPane(); 218 if (c != null && d != null) { 219 c.add(f); 220 // If the frame is to be restored to a maximized state make 221 // sure it still fills the whole desktop. 222 if (f.isMaximum()) { 223 Rectangle desktopBounds = c.getBounds(); 224 if (f.getWidth() != desktopBounds.width || 225 f.getHeight() != desktopBounds.height) { 226 setBoundsForFrame(f, 0, 0, 227 desktopBounds.width, desktopBounds.height); 228 } 229 } 230 removeIconFor(f); 231 if (f.isSelected()) { 232 f.moveToFront(); 233 f.restoreSubcomponentFocus(); 234 } 235 else { 236 try { 237 f.setSelected(true); 238 } catch (PropertyVetoException e2) {} 239 240 } 241 } 242 } 243 244 /** This will activate <b>f</b> moving it to the front. It will 245 * set the current active frame's (if any) 246 * <code>IS_SELECTED_PROPERTY</code> to <code>false</code>. 247 * There can be only one active frame across all Layers. 248 * @param f the <code>JInternalFrame</code> to be activated 249 */ 250 public void activateFrame(JInternalFrame f) { 251 Container p = f.getParent(); 252 Component[] c; 253 JDesktopPane d = f.getDesktopPane(); 254 JInternalFrame currentlyActiveFrame = 255 (d == null) ? null : d.getSelectedFrame(); 256 // fix for bug: 4162443 257 if(p == null) { 258 // If the frame is not in parent, its icon maybe, check it 259 p = f.getDesktopIcon().getParent(); 260 if(p == null) 261 return; 262 } 263 // we only need to keep track of the currentActive InternalFrame, if any 264 if (currentlyActiveFrame == null){ 265 if (d != null) { d.setSelectedFrame(f);} 266 } else if (currentlyActiveFrame != f) { 267 // if not the same frame as the current active 268 // we deactivate the current 269 if (currentlyActiveFrame.isSelected()) { 270 try { 271 currentlyActiveFrame.setSelected(false); 272 } 273 catch(PropertyVetoException e2) {} 274 } 275 if (d != null) { d.setSelectedFrame(f);} 276 } 277 f.moveToFront(); 278 } 279 280 // implements javax.swing.DesktopManager 281 public void deactivateFrame(JInternalFrame f) { 282 JDesktopPane d = f.getDesktopPane(); 283 JInternalFrame currentlyActiveFrame = 284 (d == null) ? null : d.getSelectedFrame(); 285 if (currentlyActiveFrame == f) 286 d.setSelectedFrame(null); 287 } 288 289 // implements javax.swing.DesktopManager 290 public void beginDraggingFrame(JComponent f) { 291 setupDragMode(f); 292 293 if (dragMode == FASTER_DRAG_MODE) { 294 Component desktop = f.getParent(); 295 floatingItems = findFloatingItems(f); 296 currentBounds = f.getBounds(); 297 if (desktop instanceof JComponent) { 298 desktopBounds = ((JComponent)desktop).getVisibleRect(); 299 } 300 else { 301 desktopBounds = desktop.getBounds(); 302 desktopBounds.x = desktopBounds.y = 0; 303 } 304 desktopGraphics = JComponent.safelyGetGraphics(desktop); 305 ((JInternalFrame)f).isDragging = true; 306 didDrag = false; 307 } 308 309 } 310 311 private void setupDragMode(JComponent f) { 312 JDesktopPane p = getDesktopPane(f); 313 Container parent = f.getParent(); 314 dragMode = DEFAULT_DRAG_MODE; 315 if (p != null) { 316 String mode = (String)p.getClientProperty("JDesktopPane.dragMode"); 317 Window window = SwingUtilities.getWindowAncestor(f); 318 if (window != null && !AWTUtilities.isWindowOpaque(window)) { 319 dragMode = DEFAULT_DRAG_MODE; 320 } else if (mode != null && mode.equals("outline")) { 321 dragMode = OUTLINE_DRAG_MODE; 322 } else if (mode != null && mode.equals("faster") 323 && f instanceof JInternalFrame 324 && ((JInternalFrame)f).isOpaque() && 325 (parent == null || parent.isOpaque())) { 326 dragMode = FASTER_DRAG_MODE; 327 } else { 328 if (p.getDragMode() == JDesktopPane.OUTLINE_DRAG_MODE ) { 329 dragMode = OUTLINE_DRAG_MODE; 330 } else if ( p.getDragMode() == JDesktopPane.LIVE_DRAG_MODE 331 && f instanceof JInternalFrame 332 && ((JInternalFrame)f).isOpaque()) { 333 dragMode = FASTER_DRAG_MODE; 334 } else { 335 dragMode = DEFAULT_DRAG_MODE; 336 } 337 } 338 } 339 } 340 341 private transient Point currentLoc = null; 342 343 /** 344 * Moves the visible location of the frame being dragged 345 * to the location specified. The means by which this occurs can vary depending 346 * on the dragging algorithm being used. The actual logical location of the frame 347 * might not change until <code>endDraggingFrame</code> is called. 348 */ 349 public void dragFrame(JComponent f, int newX, int newY) { 350 351 if (dragMode == OUTLINE_DRAG_MODE) { 352 JDesktopPane desktopPane = getDesktopPane(f); 353 if (desktopPane != null){ 354 Graphics g = JComponent.safelyGetGraphics(desktopPane); 355 356 g.setXORMode(Color.white); 357 if (currentLoc != null) { 358 g.drawRect(currentLoc.x, currentLoc.y, 359 f.getWidth()-1, f.getHeight()-1); 360 } 361 g.drawRect( newX, newY, f.getWidth()-1, f.getHeight()-1); 362 currentLoc = new Point (newX, newY); 363 g.dispose(); 364 } 365 } else if (dragMode == FASTER_DRAG_MODE) { 366 dragFrameFaster(f, newX, newY); 367 } else { 368 setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight()); 369 } 370 } 371 372 // implements javax.swing.DesktopManager 373 public void endDraggingFrame(JComponent f) { 374 if ( dragMode == OUTLINE_DRAG_MODE && currentLoc != null) { 375 setBoundsForFrame(f, currentLoc.x, currentLoc.y, f.getWidth(), f.getHeight() ); 376 currentLoc = null; 377 } else if (dragMode == FASTER_DRAG_MODE) { 378 currentBounds = null; 379 if (desktopGraphics != null) { 380 desktopGraphics.dispose(); 381 desktopGraphics = null; 382 } 383 desktopBounds = null; 384 ((JInternalFrame)f).isDragging = false; 385 } 386 } 387 388 // implements javax.swing.DesktopManager 389 public void beginResizingFrame(JComponent f, int direction) { 390 setupDragMode(f); 391 } 392 393 /** 394 * Calls <code>setBoundsForFrame</code> with the new values. 395 * @param f the component to be resized 396 * @param newX the new x-coordinate 397 * @param newY the new y-coordinate 398 * @param newWidth the new width 399 * @param newHeight the new height 400 */ 401 public void resizeFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) { 402 403 if ( dragMode == DEFAULT_DRAG_MODE || dragMode == FASTER_DRAG_MODE ) { 404 setBoundsForFrame(f, newX, newY, newWidth, newHeight); 405 } else { 406 JDesktopPane desktopPane = getDesktopPane(f); 407 if (desktopPane != null){ 408 Graphics g = JComponent.safelyGetGraphics(desktopPane); 409 410 g.setXORMode(Color.white); 411 if (currentBounds != null) { 412 g.drawRect( currentBounds.x, currentBounds.y, currentBounds.width-1, currentBounds.height-1); 413 } 414 g.drawRect( newX, newY, newWidth-1, newHeight-1); 415 currentBounds = new Rectangle (newX, newY, newWidth, newHeight); 416 g.setPaintMode(); 417 g.dispose(); 418 } 419 } 420 421 } 422 423 // implements javax.swing.DesktopManager 424 public void endResizingFrame(JComponent f) { 425 if ( dragMode == OUTLINE_DRAG_MODE && currentBounds != null) { 426 setBoundsForFrame(f, currentBounds.x, currentBounds.y, currentBounds.width, currentBounds.height ); 427 currentBounds = null; 428 } 429 } 430 431 432 /** This moves the <code>JComponent</code> and repaints the damaged areas. */ 433 public void setBoundsForFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) { 434 boolean didResize = (f.getWidth() != newWidth || f.getHeight() != newHeight); 435 f.setBounds(newX, newY, newWidth, newHeight); 436 if(didResize) { 437 f.validate(); 438 } 439 } 440 441 /** Convenience method to remove the desktopIcon of <b>f</b> is necessary. */ 442 protected void removeIconFor(JInternalFrame f) { 443 JInternalFrame.JDesktopIcon di = f.getDesktopIcon(); 444 Container c = di.getParent(); 445 if(c != null) { 446 c.remove(di); 447 c.repaint(di.getX(), di.getY(), di.getWidth(), di.getHeight()); 448 } 449 } 450 451 /** The iconifyFrame() code calls this to determine the proper bounds 452 * for the desktopIcon. 453 */ 454 455 protected Rectangle getBoundsForIconOf(JInternalFrame f) { 456 // 457 // Get the icon for this internal frame and its preferred size 458 // 459 460 JInternalFrame.JDesktopIcon icon = f.getDesktopIcon(); 461 Dimension prefSize = icon.getPreferredSize(); 462 // 463 // Get the parent bounds and child components. 464 // 465 466 Container c = f.getParent(); 467 if (c == null) { 468 c = f.getDesktopIcon().getParent(); 469 } 470 471 if (c == null) { 472 /* the frame has not yet been added to the parent; how about (0,0) ?*/ 473 return new Rectangle(0, 0, prefSize.width, prefSize.height); 474 } 475 476 Rectangle parentBounds = c.getBounds(); 477 Component [] components = c.getComponents(); 478 479 480 // 481 // Iterate through valid default icon locations and return the 482 // first one that does not intersect any other icons. 483 // 484 485 Rectangle availableRectangle = null; 486 JInternalFrame.JDesktopIcon currentIcon = null; 487 488 int x = 0; 489 int y = parentBounds.height - prefSize.height; 490 int w = prefSize.width; 491 int h = prefSize.height; 492 493 boolean found = false; 494 495 while (!found) { 496 497 availableRectangle = new Rectangle(x,y,w,h); 498 499 found = true; 500 501 for ( int i=0; i<components.length; i++ ) { 502 503 // 504 // Get the icon for this component 505 // 506 507 if ( components[i] instanceof JInternalFrame ) { 508 currentIcon = ((JInternalFrame)components[i]).getDesktopIcon(); 509 } 510 else if ( components[i] instanceof JInternalFrame.JDesktopIcon ){ 511 currentIcon = (JInternalFrame.JDesktopIcon)components[i]; 512 } else 513 /* found a child that's neither an internal frame nor 514 an icon. I don't believe this should happen, but at 515 present it does and causes a null pointer exception. 516 Even when that gets fixed, this code protects against 517 the npe. hania */ 518 continue; 519 520 // 521 // If this icon intersects the current location, get next location. 522 // 523 524 if ( !currentIcon.equals(icon) ) { 525 if ( availableRectangle.intersects(currentIcon.getBounds()) ) { 526 found = false; 527 break; 528 } 529 } 530 } 531 532 if (currentIcon == null) 533 /* didn't find any useful children above. This probably shouldn't 534 happen, but this check protects against an npe if it ever does 535 (and it's happening now) */ 536 return availableRectangle; 537 538 x += currentIcon.getBounds().width; 539 540 if ( x + w > parentBounds.width ) { 541 x = 0; 542 y -= h; 543 } 544 } 545 546 return(availableRectangle); 547 } 548 549 /** 550 * Stores the bounds of the component just before a maximize call. 551 * @param f the component about to be resized 552 * @param r the normal bounds to be saved away 553 */ 554 protected void setPreviousBounds(JInternalFrame f, Rectangle r) { 555 f.setNormalBounds(r); 556 } 557 558 /** 559 * Gets the normal bounds of the component prior to the component 560 * being maximized. 561 * @param f the <code>JInternalFrame</code> of interest 562 * @return the normal bounds of the component 563 */ 564 protected Rectangle getPreviousBounds(JInternalFrame f) { 565 return f.getNormalBounds(); 566 } 567 568 /** 569 * Sets that the component has been iconized and the bounds of the 570 * <code>desktopIcon</code> are valid. 571 */ 572 protected void setWasIcon(JInternalFrame f, Boolean value) { 573 if (value != null) { 574 f.putClientProperty(HAS_BEEN_ICONIFIED_PROPERTY, value); 575 } 576 } 577 578 /** 579 * Returns <code>true</code> if the component has been iconized 580 * and the bounds of the <code>desktopIcon</code> are valid, 581 * otherwise returns <code>false</code>. 582 * 583 * @param f the <code>JInternalFrame</code> of interest 584 * @return <code>true</code> if the component has been iconized; 585 * otherwise returns <code>false</code> 586 */ 587 protected boolean wasIcon(JInternalFrame f) { 588 return (f.getClientProperty(HAS_BEEN_ICONIFIED_PROPERTY) == Boolean.TRUE); 589 } 590 591 592 JDesktopPane getDesktopPane( JComponent frame ) { 593 JDesktopPane pane = null; 594 Component c = frame.getParent(); 595 596 // Find the JDesktopPane 597 while ( pane == null ) { 598 if ( c instanceof JDesktopPane ) { 599 pane = (JDesktopPane)c; 600 } 601 else if ( c == null ) { 602 break; 603 } 604 else { 605 c = c.getParent(); 606 } 607 } 608 609 return pane; 610 } 611 612 613 // =========== stuff for faster frame dragging =================== 614 615 private void dragFrameFaster(JComponent f, int newX, int newY) { 616 617 Rectangle previousBounds = new Rectangle(currentBounds.x, 618 currentBounds.y, 619 currentBounds.width, 620 currentBounds.height); 621 622 // move the frame 623 currentBounds.x = newX; 624 currentBounds.y = newY; 625 626 if (didDrag) { 627 // Only initiate cleanup if we have actually done a drag. 628 emergencyCleanup(f); 629 } 630 else { 631 didDrag = true; 632 // We reset the danger field as until now we haven't actually 633 // moved the internal frame so we don't need to initiate repaint. 634 ((JInternalFrame)f).danger = false; 635 } 636 637 boolean floaterCollision = isFloaterCollision(previousBounds, currentBounds); 638 639 JComponent parent = (JComponent)f.getParent(); 640 Rectangle visBounds = previousBounds.intersection(desktopBounds); 641 642 RepaintManager currentManager = RepaintManager.currentManager(f); 643 644 currentManager.beginPaint(); 645 try { 646 if(!floaterCollision) { 647 currentManager.copyArea(parent, desktopGraphics, visBounds.x, 648 visBounds.y, 649 visBounds.width, 650 visBounds.height, 651 newX - previousBounds.x, 652 newY - previousBounds.y, 653 true); 654 } 655 656 f.setBounds(currentBounds); 657 658 if(floaterCollision) { 659 // since we couldn't blit we just redraw as fast as possible 660 // the isDragging mucking is to avoid activating emergency 661 // cleanup 662 ((JInternalFrame)f).isDragging = false; 663 parent.paintImmediately(currentBounds); 664 ((JInternalFrame)f).isDragging = true; 665 } 666 667 // fake out the repaint manager. We'll take care of everything 668 669 currentManager.markCompletelyClean(parent); 670 currentManager.markCompletelyClean(f); 671 672 // compute the minimal newly exposed area 673 // if the rects intersect then we use computeDifference. Otherwise 674 // we'll repaint the entire previous bounds 675 Rectangle[] dirtyRects = null; 676 if ( previousBounds.intersects(currentBounds) ) { 677 dirtyRects = SwingUtilities.computeDifference(previousBounds, 678 currentBounds); 679 } else { 680 dirtyRects = new Rectangle[1]; 681 dirtyRects[0] = previousBounds; 682 }; 683 684 // Fix the damage 685 for (int i = 0; i < dirtyRects.length; i++) { 686 parent.paintImmediately(dirtyRects[i]); 687 } 688 689 // new areas of blit were exposed 690 if ( !(visBounds.equals(previousBounds)) ) { 691 dirtyRects = SwingUtilities.computeDifference(previousBounds, 692 desktopBounds); 693 for (int i = 0; i < dirtyRects.length; i++) { 694 dirtyRects[i].x += newX - previousBounds.x; 695 dirtyRects[i].y += newY - previousBounds.y; 696 ((JInternalFrame)f).isDragging = false; 697 698 parent.paintImmediately(dirtyRects[i]); 699 ((JInternalFrame)f).isDragging = true; 700 } 701 702 } 703 } finally { 704 currentManager.endPaint(); 705 } 706 707 // update window if it's non-opaque 708 Window topLevel = SwingUtilities.getWindowAncestor(f); 709 Toolkit tk = Toolkit.getDefaultToolkit(); 710 if (!topLevel.isOpaque() && 711 (tk instanceof SunToolkit) && 712 ((SunToolkit)tk).needUpdateWindow()) 713 { 714 AWTAccessor.getWindowAccessor().updateWindow(topLevel); 715 } 716 } 717 718 private boolean isFloaterCollision(Rectangle moveFrom, Rectangle moveTo) { 719 if (floatingItems.length == 0) { 720 // System.out.println("no floaters"); 721 return false; 722 } 723 724 for (int i = 0; i < floatingItems.length; i++) { 725 boolean intersectsFrom = moveFrom.intersects(floatingItems[i]); 726 if (intersectsFrom) { 727 return true; 728 } 729 boolean intersectsTo = moveTo.intersects(floatingItems[i]); 730 if (intersectsTo) { 731 return true; 732 } 733 } 734 735 return false; 736 } 737 738 private Rectangle[] findFloatingItems(JComponent f) { 739 Container desktop = f.getParent(); 740 Component[] children = desktop.getComponents(); 741 int i = 0; 742 for (i = 0; i < children.length; i++) { 743 if (children[i] == f) { 744 break; 745 } 746 } 747 // System.out.println(i); 748 Rectangle[] floaters = new Rectangle[i]; 749 for (i = 0; i < floaters.length; i++) { 750 floaters[i] = children[i].getBounds(); 751 } 752 753 return floaters; 754 } 755 756 /** 757 * This method is here to clean up problems associated 758 * with a race condition which can occur when the full contents 759 * of a copyArea's source argument is not available onscreen. 760 * This uses brute force to clean up in case of possible damage 761 */ 762 private void emergencyCleanup(final JComponent f) { 763 764 if ( ((JInternalFrame)f).danger ) { 765 766 SwingUtilities.invokeLater( new Runnable(){ 767 public void run(){ 768 769 ((JInternalFrame)f).isDragging = false; 770 f.paintImmediately(0,0, 771 f.getWidth(), 772 f.getHeight()); 773 774 //finalFrame.repaint(); 775 ((JInternalFrame)f).isDragging = true; 776 // System.out.println("repair complete"); 777 }}); 778 779 ((JInternalFrame)f).danger = false; 780 } 781 782 } 783 784 785 }