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