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