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