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