1 /*
2 * Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 }