History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/DefaultDesktopManager.java (1 of 18352 files). Show all

Unified · Split

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