KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > view > dnd > WindowDnDManager


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 package org.netbeans.core.windows.view.dnd;
22
23
24
25 import java.awt.*;
26 import java.awt.datatransfer.*;
27 import java.awt.dnd.*;
28 import java.io.IOException JavaDoc;
29 import java.lang.ref.*;
30 import java.util.*;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33 import javax.swing.*;
34 import org.netbeans.core.windows.*;
35 import org.netbeans.core.windows.view.*;
36 import org.netbeans.core.windows.view.ui.*;
37 import org.openide.util.WeakSet;
38 import org.openide.windows.TopComponent;
39
40
41 /**
42  * Manager for window DnD. Manages notifying all opened
43  * <code>ModeContainer</code>'s to be notified about starting
44  * and finishe window drag operation.
45  *
46  *
47  * @author Peter Zavadsky
48  *
49  * @see TopComponentDragSupport
50  * @see DropTargetGlassPane
51  */

52 public final class WindowDnDManager
53 implements DropTargetGlassPane.Observer, DropTargetGlassPane.Informer {
54
55     
56     private final TopComponentDragSupport topComponentDragSupport = new TopComponentDragSupport(this);
57
58     /** Only instance of drag source used for window system DnD. */
59     private DragSource windowDragSource;
60
61     /** Flag indicating the drag operation is in progress. */
62     private boolean dragging;
63     
64     // XXX #21917. The flag is not correct in jdk dnd framework,
65
// this field is used to workaround the problem. Be aware is
66
// valisd only for DnD of window component.
67
/** Flag keeping info about last drop operation. */
68     private boolean dropSuccess;
69
70     /** Maps root panes to original glass panes. */
71     private final Map<JRootPane,Component> root2glass = new HashMap<JRootPane, Component>();
72     
73     /** Set of floating frame types, i.e. separate windows. */
74     private final Set<Component> floatingFrames = new WeakSet<Component>(4);
75     
76     /** Used to hack the last Drop target to clear its indication. */
77     private Reference<DropTargetGlassPane> lastTargetWRef = new WeakReference<DropTargetGlassPane>(null);
78
79     /** Accesses view. */
80     private final ViewAccessor viewAccessor;
81     
82     // Helpers
83
private TopComponentDroppable startingDroppable;
84     private Point startingPoint;
85     // XXX Normal way it should be possible to retrieve from DnD events.
86
private TopComponent startingTransfer;
87     /** kind of mode into which belonged last dragged TopComponent at that time */
88     private int draggedKind;
89
90     /** drag feedback handler, listen to the mouse pointer motion during the drag */
91     private MotionListener motionListener;
92
93     /** Keeps ref to fake center panel droppable. */
94     private static Reference<CenterPanelDroppable> centerDropWRef =
95             new WeakReference<CenterPanelDroppable>(null);
96
97     /** Keeps ref to fake editor area droppable. */
98     private static Reference<EditorAreaDroppable> editorDropWRef =
99             new WeakReference<EditorAreaDroppable>(null);
100     
101     /** Debugging flag. */
102     private static final boolean DEBUG = Debug.isLoggable(WindowDnDManager.class);
103
104     
105     /** Creates a new instance of <code>WindowsDnDManager</code>. */
106     public WindowDnDManager(ViewAccessor viewAccessor) {
107         this.viewAccessor = viewAccessor;
108         
109         // PENDING Be aware it is added only once.
110
Toolkit.getDefaultToolkit().addAWTEventListener(
111             topComponentDragSupport,
112              AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK
113         );
114     }
115     
116
117     
118     /** Indicates whether the window drag and drop is enabled. */
119     public static boolean isDnDEnabled() {
120         return !Constants.SWITCH_DND_DISABLE;
121     }
122
123     /** Gets the only current instance of <code>DragSource</code> used in
124      * window system DnD. */

125     public synchronized DragSource getWindowDragSource() {
126         if(windowDragSource == null) {
127             windowDragSource = new DragSource();
128             windowDragSource.addDragSourceMotionListener(getMotionListener());
129         }
130         return windowDragSource;
131     }
132
133     /** Accessor for mouse motion listener */
134     public MotionListener getMotionListener () {
135         if (motionListener == null) {
136             motionListener = new MotionListener(this, topComponentDragSupport);
137         };
138         return motionListener;
139     }
140
141     /** Indicates whether the drag is in progress or not. */
142     public boolean isDragging() {
143         return dragging;
144     }
145     
146     /** Sets the <code>dropSuccess</code> flag. */
147     public void setDropSuccess(boolean dropSuccess) {
148         this.dropSuccess = dropSuccess;
149     }
150     
151     /** Indicates whether the last drop operation was successful. */
152     public boolean isDropSuccess() {
153         return dropSuccess;
154     }
155     
156     /**Sets the last drop target compoent over which hovered the mouse.
157      * Hacking purpose only. */

158     public void setLastDropTarget(DropTargetGlassPane target) {
159         if(target != lastTargetWRef.get()) {
160             lastTargetWRef = new WeakReference<DropTargetGlassPane>(target);
161         }
162     }
163     
164     // XXX try out to recover the DnD,
165
// currently impossible no API see #21791, no such API.
166
/** Tries to reset window DnD system in case some DnD problem occured. */
167     public void resetDragSource() {
168         dragFinished();
169     }
170     
171     public TopComponentDroppable getStartingDroppable() {
172         return startingDroppable;
173     }
174     
175     public Point getStartingPoint() {
176         return startingPoint;
177     }
178     
179     public TopComponent getStartingTransfer() {
180         return startingTransfer;
181     }
182
183     /** Called when there is pending drag operation to be started.
184      * Informs all currently opened <code>ModeContainer</code>'s implementing
185      * <code>ModeContainer.DropInidicator</code> interface about
186      * starting drag operation. */

187     public void dragStarting(TopComponentDroppable startingDroppable, Point startingPoint,
188     TopComponent startingTransfer) {
189         if(DEBUG) {
190             debugLog(""); // NOI18N
191
debugLog("dragStarting"); // NOI18N
192
}
193         
194         this.startingDroppable = startingDroppable;
195         this.startingPoint = startingPoint;
196         this.startingTransfer = startingTransfer;
197         ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(startingTransfer);
198         this.draggedKind = mode != null ? mode.getKind() : Constants.MODE_KIND_EDITOR;
199
200         // exclude dragged separate view
201
/*Window rpc = SwingUtilities.getWindowAncestor(startingTransfer);
202         if (rpc != null && !WindowManagerImpl.getInstance().getMainWindow().equals(rpc)) {
203             ZOrderManager.getInstance().setExcludeFromOrder((RootPaneContainer)rpc, true);
204         }*/

205         
206         Map<JRootPane,Component> addedRoots = new HashMap<JRootPane, Component>();
207         Set<Component> addedFrames = new HashSet<Component>();
208
209         for(Component comp: viewAccessor.getModeComponents()) {
210             if(comp instanceof TopComponentDroppable) {
211                 // Find root pane.
212
JRootPane root = null;
213                 if(comp instanceof RootPaneContainer) {
214                     root = ((RootPaneContainer)comp).getRootPane();
215                 } else {
216                     RootPaneContainer rootContainer = (RootPaneContainer)SwingUtilities
217                             .getAncestorOfClass(RootPaneContainer.class, comp);
218                     if(rootContainer != null) {
219                         root = rootContainer.getRootPane();
220                     }
221                 }
222                 
223                 if(root != null) {
224                     Component originalGlass = setDropTargetGlassPane(root, this);
225                     if(originalGlass != null) {
226                         addedRoots.put(root, originalGlass);
227                     }
228                 }
229             }
230         }
231         for(Component w: viewAccessor.getSeparateModeFrames()) {
232             if(w != null) {
233                 addedFrames.add(w);
234             }
235         }
236         
237         if(!addedRoots.isEmpty()) {
238             synchronized(root2glass) {
239                 root2glass.putAll(addedRoots);
240             }
241         }
242         
243         if(!addedFrames.isEmpty()) {
244             synchronized(floatingFrames) {
245                 floatingFrames.addAll(addedFrames);
246             }
247         }
248         
249         dragging = true;
250         dropSuccess = false;
251     }
252
253     
254     /** Sets <code>DropTargetGlassPane<code> for specified JRootPane.
255      * @return original glass pane or null if there was already set drop target
256      * glass pane */

257     private static Component setDropTargetGlassPane(
258     JRootPane rootPane, WindowDnDManager windowDnDManager) {
259         Component glassPane = rootPane.getGlassPane();
260         if(glassPane instanceof DropTargetGlassPane) {
261             // There is already our glass pane.
262
return null;
263         }
264         
265         DropTargetGlassPane dropGlass = new DropTargetGlassPane(windowDnDManager);
266         // Associate with new drop target, and initialize.
267
new DropTarget(
268             dropGlass,
269             DnDConstants.ACTION_COPY_OR_MOVE,
270             dropGlass
271         );
272  
273         rootPane.setGlassPane(dropGlass);
274         // !!! Necessary to initialize it after setGlassPane(..),
275
// i.e. the visibility state.
276
dropGlass.initialize();
277         
278         return glassPane;
279     }
280     
281     /** Called when there finished drag operation.
282      * Informs all turned on <code>TopComponentDroppable</code>'s
283      * about fininshed drag and drop. */

284     public void dragFinished() {
285         if(DEBUG) {
286             debugLog(""); // NOI18N
287
debugLog("dragFinished"); // NOI18N
288
}
289
290         // include dragged separate view back
291
/*Window w = SwingUtilities.getWindowAncestor(startingTransfer);
292         if (w != null && !WindowManagerImpl.getInstance().getMainWindow().equals(w)) {
293             ZOrderManager.getInstance().setExcludeFromOrder((RootPaneContainer)w, false);
294         }*/

295
296         // notify motion handler
297
getMotionListener().dragFinished();
298
299         // PENDING
300
startingDroppable = null;
301         startingPoint = null;
302         startingTransfer = null;
303         
304         // Inform the drag support instance about finishing of the DnD.
305
topComponentDragSupport.dragFinished();
306
307         dragging = false;
308
309         Map<JRootPane, Component> removedRoots;
310         synchronized(root2glass) {
311             removedRoots = new HashMap<JRootPane, Component>(root2glass);
312             root2glass.clear();
313         }
314
315         for(JRootPane root: removedRoots.keySet()) {
316             setOriginalGlassPane(root, removedRoots.get(root));
317         }
318     }
319     
320     /** Sets orgiginal glass pane to specified root pane. */
321     private static void setOriginalGlassPane(
322     JRootPane rootPane, Component originalGlass) {
323         Component glass = rootPane.getGlassPane();
324         
325         if(glass instanceof DropTargetGlassPane) {
326             DropTargetGlassPane dropGlass = (DropTargetGlassPane)glass;
327             
328             // Release the drop target, and unititialize.
329
dropGlass.setDropTarget(null);
330             dropGlass.uninitialize();
331         }
332
333         if(originalGlass != null) {
334             rootPane.setGlassPane(originalGlass);
335         }
336         
337         // #22962. Not selected JInternalFrame needs to have its glass pane
338
// switched on to work properly, ensure it is so.
339
JInternalFrame internalFrame = (JInternalFrame)SwingUtilities.
340             getAncestorOfClass(JInternalFrame.class, originalGlass);
341         if(internalFrame != null && !internalFrame.isSelected()
342         && !originalGlass.isVisible()) {
343             originalGlass.setVisible(true);
344         }
345     }
346     
347     // PENDING Better design of this issue, it needs to be performed
348
// later than dragFinished.
349
/** Maked post drag finished cleaning. Clears references to separated
350      * modes */

351     public void dragFinishedEx() {
352         synchronized(floatingFrames) {
353             floatingFrames.clear();
354         }
355     }
356
357     
358     /** Gets set of floating frames. */
359     public Set<Component> getFloatingFrames() {
360         synchronized(floatingFrames) {
361             return new HashSet<Component>(floatingFrames);
362         }
363     }
364     
365     /** Checks whether the point is inside separated (floating) frame
366      * droppable area. The point is relative to screen. */

367     public boolean isInFloatingFrame(Point location) {
368         for(Component w: getFloatingFrames()) {
369             if(w.getBounds().contains(location)) {
370                 return true;
371             }
372         }
373         
374         return false;
375     }
376
377
378     // XXX
379
public boolean isCopyOperationPossible() {
380         return topComponentDragSupport.isCopyOperationPossible();
381     }
382     
383     public Controller getController() {
384         return viewAccessor.getController();
385     }
386     
387     private static void debugLog(String JavaDoc message) {
388         Debug.log(WindowDnDManager.class, message);
389     }
390
391     // Helpers>>
392
/** Checks whether the point is inside main window droppable area.
393      * The point is relative to screen. */

394     static boolean isInMainWindow(Point location) {
395         return WindowManagerImpl.getInstance().getMainWindow().getBounds().contains(location);
396     }
397     
398     /** Indicates whether there is a droppable in main window, specified
399      * by screen location. */

400     private boolean isInMainWindowDroppable(Point location, int kind, TopComponent transfer) {
401         return findMainWindowDroppable(location, kind, transfer) != null;
402     }
403     
404     /** Checks whetner the point is inside one of floating window,
405      * i.e. separated modes, droppable area. The point is relative to screen. */

406     private static boolean isInFloatingFrameDroppable(Set<Component> floatingFrames, Point location, int kind, TopComponent transfer) {
407         return findFloatingFrameDroppable(floatingFrames, location, kind, transfer) != null;
408     }
409     
410     private static boolean isInFreeArea(Point location) {
411         // prepare array of all our windows
412
Window mainWindow = WindowManagerImpl.getInstance().getMainWindow();
413         Window[] owned = mainWindow.getOwnedWindows();
414         Window[] frames = Frame.getFrames();
415         Window[] windows = new Window[owned.length + frames.length];
416         System.arraycopy(frames, 0, windows, 0, frames.length);
417         System.arraycopy(owned, 0, windows, frames.length, owned.length);
418
419         for(int i = 0; i < windows.length; i++) {
420             //#40782 fix. don't take the invisible frames into account when deciding what is
421
// free space.
422
if(windows[i].isVisible() && windows[i].getBounds().contains(location.x, location.y)) {
423                 return false;
424             }
425         }
426         
427         return true;
428     }
429
430     /** Finds <code>TopComponentDroppable</code> from specified screen location. */
431     private TopComponentDroppable findDroppableFromScreen(
432     Set<Component> floatingFrames, Point location, int kind, TopComponent transfer) {
433
434         TopComponentDroppable droppable = findMainWindowDroppable(location, kind, transfer);
435         if(droppable != null) {
436             return droppable;
437         }
438         
439         droppable = findFloatingFrameDroppable(floatingFrames, location, kind, transfer);
440         if(droppable != null) {
441             return droppable;
442         }
443         
444 // // PENDING center panel area. Maybe editor empty area -> revise later.
445
// if(isAroundCenterPanel(location)) {
446
// return getCenterPanelDroppable();
447
// }
448

449         if(isInFreeArea(location)) {
450             return getFreeAreaDroppable(location);
451         }
452         return null;
453     }
454
455     private CenterSlidingDroppable lastSlideDroppable;
456     
457     /** Gets droppable from main window, specified by screen location.
458      * Helper method. */

459     private TopComponentDroppable findMainWindowDroppable(
460     Point location, int kind, TopComponent transfer) {
461         
462         MainWindow mainWindow = (MainWindow)WindowManagerImpl.getInstance().getMainWindow();
463
464         if (!ZOrderManager.getInstance().isOnTop(mainWindow, location)) {
465             return null;
466         }
467
468         Point p = new Point(location);
469         SwingUtilities.convertPointFromScreen(p, mainWindow.getContentPane());
470         if (lastSlideDroppable != null) {
471             if (lastSlideDroppable.isWithinSlide(p)) {
472                 return lastSlideDroppable;
473             }
474         }
475         TopComponentDroppable droppable = findSlideDroppable(viewAccessor.getSlidingModeComponent(Constants.LEFT));
476         if (droppable != null) {
477             CenterSlidingDroppable drop = new CenterSlidingDroppable(viewAccessor, droppable, Constants.LEFT);
478             if (drop.isWithinSlide(p)) {
479                 lastSlideDroppable = drop;
480                 return drop;
481             }
482         }
483         droppable = findSlideDroppable(viewAccessor.getSlidingModeComponent(Constants.RIGHT));
484         if (droppable != null) {
485             CenterSlidingDroppable drop = new CenterSlidingDroppable(viewAccessor, droppable, Constants.RIGHT);
486             if (drop.isWithinSlide(p)) {
487                 lastSlideDroppable = drop;
488                 return drop;
489             }
490         }
491         droppable = findSlideDroppable(viewAccessor.getSlidingModeComponent(Constants.BOTTOM));
492         if (droppable != null) {
493             CenterSlidingDroppable drop = new CenterSlidingDroppable(viewAccessor, droppable, Constants.BOTTOM);
494             if (drop.isWithinSlide(p)) {
495                 lastSlideDroppable = drop;
496                 return drop;
497             }
498         }
499         lastSlideDroppable = null;
500         if (isNearEditorEdge(location, viewAccessor, kind)) {
501             return getEditorAreaDroppable();
502         }
503         if (isNearEdge(location, viewAccessor)) {
504             return getCenterPanelDroppable();
505         }
506         Point mainP = new Point(location);
507         SwingUtilities.convertPointFromScreen(mainP, mainWindow);
508         return findDroppable(mainWindow, mainP, kind, transfer);
509     }
510     
511     private static TopComponentDroppable findSlideDroppable(Component comp) {
512         TopComponentDroppable droppable = null;
513         if(comp instanceof TopComponentDroppable) {
514             droppable = (TopComponentDroppable)comp;
515         } else {
516             droppable = (TopComponentDroppable)SwingUtilities.getAncestorOfClass(TopComponentDroppable.class, comp);
517         }
518         return droppable;
519     }
520
521     /** Gets droppable from separated (floating) window, specified
522      * by screen location. Helper method. */

523     private static TopComponentDroppable findFloatingFrameDroppable(
524     Set<Component> floatingFrames, Point location, int kind, TopComponent transfer) {
525         for(Component comp: floatingFrames) {
526             Rectangle bounds = comp.getBounds();
527             
528             if(bounds.contains(location) &&
529                ZOrderManager.getInstance().isOnTop((RootPaneContainer)comp, location)) {
530                 TopComponentDroppable droppable = findDroppable(comp,
531                         new Point(location.x - bounds.x, location.y - bounds.y),
532                         kind,
533                         transfer);
534                 if(droppable != null) {
535                     return droppable;
536                 }
537             }
538         }
539         
540         return null;
541     }
542     
543     /** Finds <code>TopComponentDroppable</code> for the location in component.
544      * The location has to be relative to the specified component. Then the
545      * method finds if there is a droppable component in the hierarchy, which
546      * also contains the specified location.
547      * Utilitity method. */

548     private static TopComponentDroppable findDroppable(Component comp,
549                          Point location, int kind, TopComponent transfer) {
550         RootPaneContainer rpc;
551         if(comp instanceof RootPaneContainer) {
552             rpc = (RootPaneContainer)comp;
553         } else {
554             Window w = SwingUtilities.getWindowAncestor(comp);
555             if(w instanceof RootPaneContainer) {
556                 rpc = (RootPaneContainer)w;
557             } else {
558                 return null;
559             }
560         }
561
562         Component contentPane = rpc.getContentPane();
563         location = SwingUtilities.convertPoint(comp, location, contentPane);
564         Component deepest = SwingUtilities.getDeepestComponentAt(
565                 contentPane, location.x, location.y);
566         if(deepest instanceof TopComponentDroppable) {
567             TopComponentDroppable droppable = (TopComponentDroppable)deepest;
568             if(droppable.supportsKind(kind, transfer)) {
569                 return droppable;
570             }
571         }
572         
573         while(deepest != null) {
574             TopComponentDroppable nextDroppable = (TopComponentDroppable)SwingUtilities.getAncestorOfClass(
575                     TopComponentDroppable.class, deepest);
576             if(nextDroppable != null && nextDroppable.supportsKind(kind, transfer)) {
577                 return nextDroppable;
578             }
579             deepest = (Component)nextDroppable;
580         }
581         return null;
582     }
583     
584     /** Indicates whether the cursor is around center panel of main window.
585      * In that case is needed also to provide a drop. */

586     static boolean isAroundCenterPanel(Point location) {
587         Component desktop = ((MainWindow)WindowManagerImpl.getInstance().getMainWindow()).getDesktop();
588         if(desktop == null) {
589             return false;
590         }
591         
592         Point p = new Point(location);
593         SwingUtilities.convertPointFromScreen(p, desktop.getParent());
594         Rectangle centerBounds = desktop.getBounds();
595
596         if(!centerBounds.contains(p)) {
597             centerBounds.grow(Constants.DROP_AREA_SIZE, Constants.DROP_AREA_SIZE);
598             if(centerBounds.contains(p)) {
599                 return true;
600             }
601         }
602         return false;
603     }
604     
605     /** Indicates whether the cursor is around the editor area of the main window.
606      * In that case is needed also to provide a drop. */

607     static boolean isNearEditorEdge(Point location, ViewAccessor viewAccessor, int kind) {
608         Component editor = WindowManagerImpl.getInstance().getEditorAreaComponent();
609         if(editor == null) {
610             return false;
611         }
612         Point p = new Point(location);
613         SwingUtilities.convertPointFromScreen(p, editor.getParent());
614         Rectangle editorBounds = editor.getBounds();
615         editorBounds.y -= 10;
616         editorBounds.height += 10;
617         Rectangle shrinked = editor.getBounds();
618         shrinked.grow(-10,0);
619         shrinked.height -= 10;
620         Component dr = viewAccessor.getSlidingModeComponent(Constants.RIGHT);
621         if (dr != null) {
622             shrinked.width = shrinked.width - dr.getBounds().width;
623         }
624         dr = viewAccessor.getSlidingModeComponent(Constants.BOTTOM);
625         if (dr != null) {
626             shrinked.height = shrinked.height - dr.getBounds().height;
627         }
628         return editorBounds.contains(p) && !shrinked.contains(p) && kind == Constants.MODE_KIND_EDITOR;
629     }
630     
631     
632     /** Indicates whether the cursor is around center panel of main window.
633      * In that case is needed also to provide a drop. */

634     static boolean isNearEdge(Point location, ViewAccessor viewAccessor) {
635         Component desktop = ((MainWindow)WindowManagerImpl.getInstance().getMainWindow()).getDesktop();
636         if(desktop == null) {
637             return false;
638         }
639         Point p = new Point(location);
640         SwingUtilities.convertPointFromScreen(p, desktop);
641         Rectangle centerBounds = desktop.getBounds();
642         centerBounds.y -= 20;
643         centerBounds.height += 20;
644         Rectangle shrinked = desktop.getBounds();
645         shrinked.grow(-10,0);
646         shrinked.height -= 10;
647         Component dr = viewAccessor.getSlidingModeComponent(Constants.LEFT);
648         if (dr != null) {
649             shrinked.x = shrinked.x + dr.getBounds().width;
650             shrinked.width = shrinked.width - dr.getBounds().width;
651         }
652         dr = viewAccessor.getSlidingModeComponent(Constants.RIGHT);
653         if (dr != null) {
654             shrinked.width = shrinked.width - dr.getBounds().width;
655         }
656         dr = viewAccessor.getSlidingModeComponent(Constants.BOTTOM);
657         if (dr != null) {
658             shrinked.height = shrinked.height - dr.getBounds().height;
659         }
660         boolean cont = centerBounds.contains(p) && !shrinked.contains(p);
661         
662         return cont;
663     }
664     
665     /** Creates fake droppable for center panel. */
666     private TopComponentDroppable getCenterPanelDroppable() {
667         CenterPanelDroppable droppable = centerDropWRef.get();
668         
669         if(droppable == null) {
670             droppable = new CenterPanelDroppable();
671             centerDropWRef = new WeakReference<CenterPanelDroppable>(droppable);
672         }
673         
674         return droppable;
675     }
676     
677     private static TopComponentDroppable getFreeAreaDroppable(Point location) {
678         return new FreeAreaDroppable(location);
679     }
680
681     /** Creates fake droppable for editor area. */
682     private TopComponentDroppable getEditorAreaDroppable() {
683         EditorAreaDroppable droppable = editorDropWRef.get();
684         
685         if(droppable == null) {
686             droppable = new EditorAreaDroppable();
687             editorDropWRef = new WeakReference<EditorAreaDroppable>(droppable);
688         }
689         
690         return droppable;
691     }
692     
693     
694     /**
695      * Tries to perform actual drop.
696      * @param location screen location */

697     boolean tryPerformDrop(Controller controller, Set<Component> floatingFrames,
698     Point location, int dropAction, Transferable transferable) {
699         TopComponent[] tcArray = extractTopComponent(
700             dropAction == DnDConstants.ACTION_COPY,
701             transferable
702         );
703         
704         if(tcArray == null || tcArray.length == 0) {
705             return false;
706         }
707         
708         ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(tcArray[0]);
709         int kind = mode != null ? mode.getKind() : Constants.MODE_KIND_EDITOR;
710         
711         TopComponentDroppable droppable
712                 = findDroppableFromScreen(floatingFrames, location, kind, tcArray[0]);
713         if(droppable == null) {
714             return false;
715         }
716         
717         Component dropComponent = droppable.getDropComponent();
718         if(dropComponent != null) {
719             SwingUtilities.convertPointFromScreen(location, dropComponent);
720         }
721         return performDrop(controller, droppable, dropAction, tcArray, location, draggedKind);
722     }
723     
724     /** Extracts <code>TopComponent</code> instance from
725      * <code>Transferable</code> according the <code>dropAction</code>.
726      * Utility method. */

727     static TopComponent[] extractTopComponent(boolean clone,
728     Transferable tr) {
729         DataFlavor df = getDataFlavorForDropAction(clone);
730         
731         if(df == null) {
732             // No data flavor -> unsupported drop action.
733
return null;
734         }
735
736         // Test whether the requested dataflavor is supported by transferable.
737
if(tr.isDataFlavorSupported(df)) {
738             try {
739                 TopComponent tc;
740
741                 if(clone) {
742                     TopComponent.Cloneable ctc = (TopComponent.Cloneable)tr
743                         .getTransferData(df);
744
745                     // "Copy" the top component.
746
tc = ctc.cloneComponent();
747                 } else {
748                     tc = (TopComponent)tr.getTransferData(df);
749                 }
750
751                 return new TopComponent[] {tc};
752             } catch(UnsupportedFlavorException ufe) {
753                 Logger.getLogger(WindowDnDManager.class.getName()).log(Level.WARNING, null, ufe);
754             } catch(IOException JavaDoc ioe) {
755                 Logger.getLogger(WindowDnDManager.class.getName()).log(Level.WARNING, null, ioe);
756             }
757         }
758     
759         df = new DataFlavor(TopComponentDragSupport.MIME_TOP_COMPONENT_ARRAY, null);
760         if(tr.isDataFlavorSupported(df)) {
761             try {
762                 return (TopComponent[])tr.getTransferData(df);
763             } catch(UnsupportedFlavorException ufe) {
764                 Logger.getLogger(WindowDnDManager.class.getName()).log(Level.WARNING, null, ufe);
765             } catch(IOException JavaDoc ioe) {
766                 Logger.getLogger(WindowDnDManager.class.getName()).log(Level.WARNING, null, ioe);
767             }
768         }
769         
770         return null;
771     }
772     
773     /** Gets <code>DataFlavor</code> for specific drop action type.
774      * Helper utility method. */

775     private static DataFlavor getDataFlavorForDropAction(boolean clone) {
776         // Create needed dataflavor.
777
DataFlavor df;
778         if(clone) {
779             df = new DataFlavor(TopComponentDragSupport.MIME_TOP_COMPONENT_CLONEABLE, null);
780         } else {
781             df = new DataFlavor(TopComponentDragSupport.MIME_TOP_COMPONENT, null);
782         }
783         
784         return df;
785     }
786     
787     /**
788      * Performs actual drop operation. Called from DropTargetListener.
789      * @return <code>true</code> if the drop was successful */

790     private static boolean performDrop(Controller controller,
791     TopComponentDroppable droppable, int dropAction, TopComponent[] tcArray, Point location, int draggedKind) {
792         if(DEBUG) {
793             debugLog(""); // NOI18N
794
debugLog("performDrop"); // NOI18N
795
debugLog("droppable=" + droppable); // NOI18N
796
}
797
798         if(tcArray == null || tcArray.length == 0) {
799             return true;
800         }
801         
802         if(!droppable.canDrop(tcArray[0], location)) {
803             return true;
804         }
805         
806         ViewElement viewElement = droppable.getDropViewElement();
807         Object JavaDoc constr = droppable.getConstraintForLocation(location);
808
809         if(viewElement instanceof EditorView) {
810             ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(tcArray[0]);
811             int kind = mode != null ? mode.getKind() : Constants.MODE_KIND_EDITOR;
812             if(kind == Constants.MODE_KIND_EDITOR) {
813                 controller.userDroppedTopComponentsIntoEmptyEditor(tcArray);
814             } else {
815                 if(constr == Constants.TOP
816                 || constr == Constants.LEFT
817                 || constr == Constants.RIGHT
818                 || constr == Constants.BOTTOM) {
819                     controller.userDroppedTopComponentsAroundEditor(tcArray, (String JavaDoc)constr, kind);
820                 } else if(Constants.SWITCH_MODE_ADD_NO_RESTRICT
821                 || WindowManagerImpl.getInstance().isTopComponentAllowedToMoveAnywhere(tcArray[0])) {
822                     controller.userDroppedTopComponentsIntoEmptyEditor(tcArray);
823                 }
824             }
825         } else if(viewElement instanceof ModeView) {
826             ModeView modeView = (ModeView)viewElement;
827             if(constr == Constants.TOP
828             || constr == Constants.LEFT
829             || constr == Constants.RIGHT
830             || constr == Constants.BOTTOM) {
831                 controller.userDroppedTopComponents(modeView, tcArray, (String JavaDoc)constr);
832             } else if(constr instanceof Integer JavaDoc) {
833                 controller.userDroppedTopComponents(modeView, tcArray, ((Integer JavaDoc)constr).intValue());
834             } else {
835                 controller.userDroppedTopComponents(modeView, tcArray);
836             }
837         } else if(viewElement == null) { // XXX around area or free area
838
if(constr == Constants.TOP
839             || constr == Constants.LEFT
840             || constr == Constants.RIGHT
841             || constr == Constants.BOTTOM) { // XXX around area
842
if( droppable instanceof EditorAreaDroppable ) {
843                     controller.userDroppedTopComponentsAroundEditor(tcArray, (String JavaDoc)constr, Constants.MODE_KIND_EDITOR);
844                 } else {
845                     controller.userDroppedTopComponentsAround(tcArray, (String JavaDoc)constr);
846                 }
847             } else if(constr instanceof Rectangle) { // XXX free area
848
Rectangle bounds = (Rectangle)constr;
849                 // #38657 Refine bounds.
850
Component modeComp = SwingUtilities.getAncestorOfClass(ModeComponent.class, tcArray[0]);
851                 if(modeComp != null) {
852                     bounds.setSize(modeComp.getWidth(), modeComp.getHeight());
853                 }
854                 
855                 controller.userDroppedTopComponentsIntoFreeArea(tcArray, bounds, draggedKind);
856             }
857         }
858
859         return true;
860     }
861     // Helpers<<
862

863
864     /** Handles mouse cursors shapes and drag-under feedback during the drag.
865      */

866     private static class MotionListener implements DragSourceMotionListener {
867
868         private final WindowDnDManager windowDnDManager;
869         private final TopComponentDragSupport topComponentDragSupport;
870
871         private Point previousDragLoc;
872
873         /** window used to simulate drag under effect when dropping to free screen area */
874         private Window fakeWindow;
875
876         /** helper; true when size of fake window set and known, false otherwise */
877         private boolean isSizeSet;
878         
879         /** Constrtucts the instance.
880          * Adds the listener to the window dnd <code>DragSource</code>. */

881         private MotionListener(WindowDnDManager windowDnDManager,
882         TopComponentDragSupport topComponentDragSupport) {
883             this.windowDnDManager = windowDnDManager;
884             this.topComponentDragSupport = topComponentDragSupport;
885         }
886         
887
888         /** Implements <code>DragSourceMotionListener</code>. */
889         public void dragMouseMoved(DragSourceDragEvent evt) {
890             if(DEBUG) {
891                 debugLog("dragMouseMoved evt=" + evt); // NOI18N
892
}
893             
894             Point location = evt.getLocation();
895             if(location == null) {
896                 return;
897             }
898
899             // move separate windows along with the mouse
900
/*if (Constants.MODE_STATE_SEPARATED == mode.getState()) {
901                 handleWindowMove(mode, windowDnDManager.startingTransfer, evt);
902             }*/

903
904             boolean isInMainDroppable
905                     = windowDnDManager.isInMainWindowDroppable(location, windowDnDManager.draggedKind, windowDnDManager.startingTransfer);
906             boolean isInFrameDroppable
907                     = isInFloatingFrameDroppable(windowDnDManager.getFloatingFrames(), location, windowDnDManager.draggedKind, windowDnDManager.startingTransfer);
908             boolean isAroundCenterPanel
909                     = isAroundCenterPanel(location);
910             boolean shouldPaintFakeWindow = false;
911
912             if(isInMainDroppable || isInFrameDroppable || isAroundCenterPanel) {
913                 TopComponentDroppable droppable
914                         = windowDnDManager.findDroppableFromScreen(windowDnDManager.getFloatingFrames(), location, windowDnDManager.draggedKind, windowDnDManager.startingTransfer);
915                 //hack - can't get the bounds correctly, sometimes freearedroppable gets here..
916

917                 if (droppable instanceof FreeAreaDroppable) {
918                     if(WindowManagerImpl.getInstance().getEditorAreaState() == Constants.EDITOR_AREA_SEPARATED
919                         && droppable.canDrop(windowDnDManager.startingTransfer, location)) {
920                         topComponentDragSupport.setSuccessCursor(true);
921                     } else {
922                         topComponentDragSupport.setUnsuccessCursor();
923                     }
924                     // for the status bar it's null somehow, workarounding by checking for null.. should go away..
925
} else if (droppable != null) {
926                     
927                     // was probably forgotten to set the lastdrop target, was causing strange repaint side effects when 2 frames overlapped.
928
JComponent cp = (JComponent)droppable.getDropComponent();
929                     Component glass = cp.getRootPane().getGlassPane();
930                     if (glass instanceof DropTargetGlassPane) {
931                         windowDnDManager.setLastDropTarget((DropTargetGlassPane)glass);
932                     }
933                     Point p = new Point(location);
934                     SwingUtilities.convertPointFromScreen(p, droppable.getDropComponent());
935                     if(droppable.canDrop(windowDnDManager.startingTransfer, p)) {
936                         topComponentDragSupport.setSuccessCursor(false);
937                     } else {
938                         topComponentDragSupport.setUnsuccessCursor();
939                     }
940                     dragOverDropTarget(location, droppable);
941                 }
942             } else if(!isInMainWindow(location)
943             && windowDnDManager.isInFloatingFrame(location)) {
944                 // Simulates success drop in free area.
945
topComponentDragSupport.setSuccessCursor(false);
946             } else if(isInFreeArea(location)
947             && getFreeAreaDroppable(location).canDrop(windowDnDManager.startingTransfer, location)) {
948                 topComponentDragSupport.setSuccessCursor(true);
949                 // paint fake window during move over free area
950
shouldPaintFakeWindow = true;
951             } else {
952                 topComponentDragSupport.setUnsuccessCursor();
953             }
954             paintFakeWindow(shouldPaintFakeWindow, evt);
955             
956             if(!isInMainDroppable && !isInFrameDroppable && !isAroundCenterPanel) {
957                 clearExitedDropTarget();
958             }
959         }
960         
961         /** Simulates dropOver event, for glass pane to indicate possible drop
962          * operation. */

963         private /*static*/ void dragOverDropTarget(Point location,
964         TopComponentDroppable droppable) {
965             DropTargetGlassPane lastTarget
966                 = windowDnDManager.lastTargetWRef.get();
967
968             if(lastTarget != null) {
969                 Point p = new Point(location);
970                 SwingUtilities.convertPointFromScreen(p, lastTarget);
971                 lastTarget.dragOver(p, droppable);
972             }
973         }
974
975         /** Hacks drag exit from drop target (glass pane).
976          * Eliminates bug, where remained drop indicator drawed
977          * even for cases the cursor was away from drop target. Missing
978          * drag exit event. */

979         private /*static*/ void clearExitedDropTarget() {
980             DropTargetGlassPane lastTarget
981                 = windowDnDManager.lastTargetWRef.get();
982
983             if(lastTarget != null) {
984                 lastTarget.clearIndications();
985                 windowDnDManager.lastTargetWRef = new WeakReference<DropTargetGlassPane>(null);
986             }
987         }
988         
989         /** Gets main drop target glass pane.*/
990         private static DropTargetGlassPane getMainDropTargetGlassPane() {
991             Component glass = ((JFrame)WindowManagerImpl.getInstance().getMainWindow()).getGlassPane();
992             if(glass instanceof DropTargetGlassPane) {
993                 return (DropTargetGlassPane)glass;
994             } else {
995                 return null;
996             }
997         }
998
999         void dragFinished () {
1000            previousDragLoc = null;
1001            if (fakeWindow != null) {
1002                fakeWindow.dispose();
1003                fakeWindow = null;
1004            }
1005        }
1006
1007        /** Moves the window containing given top component to follow mouse drag.
1008         */

1009        private void handleWindowMove (ModeImpl mode, TopComponent tc, DragSourceDragEvent evt) {
1010            Point dragLoc = evt.getLocation();
1011            // start from real starting point of the drag
1012
Window w = SwingUtilities.getWindowAncestor(tc);
1013            if (previousDragLoc == null) {
1014                previousDragLoc = windowDnDManager.getStartingPoint();
1015                SwingUtilities.convertPointToScreen(previousDragLoc, w);
1016            }
1017            Point newLoc = w.getLocation();
1018            newLoc.translate(dragLoc.x - previousDragLoc.x, dragLoc.y - previousDragLoc.y);
1019            w.setLocation(newLoc);
1020
1021            previousDragLoc = dragLoc;
1022        }
1023
1024        /** Shows or hides fake window as drag under effect
1025         */

1026        private void paintFakeWindow (boolean visible, DragSourceDragEvent evt) {
1027            Point loc = evt.getLocation();
1028            // no window if location is unknown
1029
if (loc == null) {
1030                return;
1031            }
1032            if (fakeWindow == null) {
1033                fakeWindow = createFakeWindow();
1034                isSizeSet = false;
1035            }
1036            fakeWindow.setLocation(loc);
1037            fakeWindow.setVisible(visible);
1038            // calculate space for window with decorations (title, border...)
1039
if (visible && !isSizeSet) {
1040                Dimension size = windowDnDManager.startingTransfer.getSize();
1041                Insets insets = fakeWindow.getInsets();
1042                size.width += insets.left + insets.right;
1043                size.height += insets.top + insets.bottom;
1044                fakeWindow.setSize(size);
1045                isSizeSet = true;
1046            }
1047        }
1048
1049        /** Creates and returns fake window as drag under effect */
1050        private Window createFakeWindow () {
1051            Window result;
1052            if (windowDnDManager.draggedKind == Constants.MODE_KIND_EDITOR) {
1053                result = new JFrame();
1054            } else {
1055                result = new JDialog((JFrame) null);
1056            }
1057            result.setAlwaysOnTop(true);
1058            return result;
1059        }
1060
1061    } // End of class MotionListener.
1062

1063
1064    // XXX
1065
/** Interface for accessing */
1066    public interface ViewAccessor {
1067        public Set<Component> getModeComponents();
1068        public Set<Component> getSeparateModeFrames();
1069        public Controller getController();
1070        public Component getSlidingModeComponent(String JavaDoc side);
1071    } // End of ViewState.
1072

1073    /** Fake helper droppable used when used around */
1074    private class CenterPanelDroppable implements TopComponentDroppable {
1075
1076        /** Implements <code>TopComponentDroppable</code>. */
1077        public java.awt.Shape JavaDoc getIndicationForLocation(Point p) {
1078            Rectangle bounds = getDropComponent().getBounds();
1079            Rectangle res = null;
1080            double ratio = Constants.DROP_AROUND_RATIO;
1081            Object JavaDoc constraint = getConstraintForLocation(p);
1082            if(constraint == JSplitPane.LEFT) {
1083                res = new Rectangle(0, 0, (int)(bounds.width * ratio) - 1, bounds.height - 1);
1084            } else if(constraint == JSplitPane.TOP) {
1085                res = new Rectangle(0, 0, bounds.width - 1, (int)(bounds.height * ratio) - 1);
1086            } else if(constraint == JSplitPane.RIGHT) {
1087                res = new Rectangle(bounds.width - (int)(bounds.width * ratio), 0,
1088                        (int)(bounds.width * ratio) - 1, bounds.height - 1);
1089            } else if(constraint == JSplitPane.BOTTOM) {
1090                res = new Rectangle(0, bounds.height - (int)(bounds.height * ratio), bounds.width - 1,
1091                        (int)(bounds.height * ratio) - 1);
1092            }
1093
1094            return res;
1095        }
1096
1097        /** Implements <code>TopComponentDroppable</code>. */
1098        public Object JavaDoc getConstraintForLocation(Point p) {
1099            Rectangle bounds = getDropComponent().getBounds();
1100            Component leftSlide = viewAccessor.getSlidingModeComponent(Constants.LEFT);
1101            Component rightSlide = viewAccessor.getSlidingModeComponent(Constants.RIGHT);
1102            Component bottomSlide = viewAccessor.getSlidingModeComponent(Constants.BOTTOM);
1103            if(null != leftSlide && p.x < leftSlide.getBounds().width + 10) {
1104                return javax.swing.JSplitPane.LEFT;
1105            } else if(p.y < bounds.y) {
1106                return javax.swing.JSplitPane.TOP;
1107            } else if(null !=rightSlide && null != leftSlide
1108                      && p.x > bounds.width - 10 - rightSlide.getBounds().width - leftSlide.getBounds().width) {
1109                return javax.swing.JSplitPane.RIGHT;
1110            } else if(null != bottomSlide && p.y > bounds.height - 10 - bottomSlide.getBounds().height) {
1111                return javax.swing.JSplitPane.BOTTOM;
1112            }
1113
1114            return null;
1115        }
1116
1117        /** Implements <code>TopComponentDroppable</code>. */
1118        public Component getDropComponent() {
1119            return ((MainWindow)WindowManagerImpl.getInstance().getMainWindow()).getDesktop();
1120        }
1121        
1122        /** Implements <code>TopComponentDroppable</code>. */
1123        public ViewElement getDropViewElement() {
1124            return null;
1125        }
1126        
1127        public boolean canDrop(TopComponent transfer, Point location) {
1128            if(Constants.SWITCH_MODE_ADD_NO_RESTRICT
1129            || WindowManagerImpl.getInstance().isTopComponentAllowedToMoveAnywhere(transfer)) {
1130                return true;
1131            }
1132
1133            ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(transfer);
1134            return mode != null && (mode.getKind() == Constants.MODE_KIND_VIEW || mode.getKind() == Constants.MODE_KIND_SLIDING);
1135        }
1136        
1137        public boolean supportsKind(int kind, TopComponent transfer) {
1138            if(Constants.SWITCH_MODE_ADD_NO_RESTRICT
1139            || WindowManagerImpl.getInstance().isTopComponentAllowedToMoveAnywhere(transfer)) {
1140                return true;
1141            }
1142
1143            return kind == Constants.MODE_KIND_VIEW || kind == Constants.MODE_KIND_SLIDING;
1144        }
1145
1146
1147    } // End of class CenterPanelDroppable.
1148

1149    /** Fake helper droppable used when used around */
1150    private class EditorAreaDroppable implements TopComponentDroppable {
1151
1152        /** Implements <code>TopComponentDroppable</code>. */
1153        public java.awt.Shape JavaDoc getIndicationForLocation(Point p) {
1154            Rectangle bounds = getDropComponent().getBounds();
1155            Rectangle res = null;
1156            double ratio = Constants.DROP_AROUND_RATIO;
1157            Object JavaDoc constraint = getConstraintForLocation(p);
1158            if(constraint == JSplitPane.LEFT) {
1159                res = new Rectangle(0, 0, (int)(bounds.width * ratio) - 1, bounds.height - 1);
1160            } else if(constraint == JSplitPane.TOP) {
1161                res = new Rectangle(0, 0, bounds.width - 1, (int)(bounds.height * ratio) - 1);
1162            } else if(constraint == JSplitPane.RIGHT) {
1163                res = new Rectangle(bounds.width - (int)(bounds.width * ratio), 0,
1164                        (int)(bounds.width * ratio) - 1, bounds.height - 1);
1165            } else if(constraint == JSplitPane.BOTTOM) {
1166                res = new Rectangle(0, bounds.height - (int)(bounds.height * ratio), bounds.width - 1,
1167                        (int)(bounds.height * ratio) - 1);
1168            }
1169
1170            return res;
1171        }
1172
1173        /** Implements <code>TopComponentDroppable</code>. */
1174        public Object JavaDoc getConstraintForLocation(Point p) {
1175            Rectangle bounds = getDropComponent().getBounds();
1176            Component leftSlide = viewAccessor.getSlidingModeComponent(Constants.LEFT);
1177            Component rightSlide = viewAccessor.getSlidingModeComponent(Constants.RIGHT);
1178            Component bottomSlide = viewAccessor.getSlidingModeComponent(Constants.BOTTOM);
1179            if(null != leftSlide && p.x < leftSlide.getBounds().width + 10) {
1180                return javax.swing.JSplitPane.LEFT;
1181            } else if(p.y < bounds.y) {
1182                return javax.swing.JSplitPane.TOP;
1183            } else if(null !=rightSlide && null != leftSlide
1184                      && p.x > bounds.width - 10 - rightSlide.getBounds().width - leftSlide.getBounds().width) {
1185                return javax.swing.JSplitPane.RIGHT;
1186            } else if(null != bottomSlide && p.y > bounds.height - 10 - bottomSlide.getBounds().height) {
1187                return javax.swing.JSplitPane.BOTTOM;
1188            }
1189
1190            return null;
1191        }
1192
1193        /** Implements <code>TopComponentDroppable</code>. */
1194        public Component getDropComponent() {
1195            return WindowManagerImpl.getInstance().getEditorAreaComponent();
1196        }
1197        
1198        /** Implements <code>TopComponentDroppable</code>. */
1199        public ViewElement getDropViewElement() {
1200            return null;
1201        }
1202        
1203        public boolean canDrop(TopComponent transfer, Point location) {
1204            if(Constants.SWITCH_MODE_ADD_NO_RESTRICT
1205            || WindowManagerImpl.getInstance().isTopComponentAllowedToMoveAnywhere(transfer)) {
1206                return true;
1207            }
1208
1209            ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(transfer);
1210            return mode != null && mode.getKind() == Constants.MODE_KIND_EDITOR;
1211        }
1212        
1213        public boolean supportsKind(int kind, TopComponent transfer) {
1214            if(Constants.SWITCH_MODE_ADD_NO_RESTRICT
1215            || WindowManagerImpl.getInstance().isTopComponentAllowedToMoveAnywhere(transfer)) {
1216                return true;
1217            }
1218
1219            return kind == Constants.MODE_KIND_EDITOR;
1220        }
1221
1222
1223    } // End of class EditorAreaDroppable.
1224

1225    
1226    /** Fake helper droppable used when dropping is done into free area. */
1227    private static class FreeAreaDroppable implements TopComponentDroppable {
1228        
1229        private Point location;
1230        
1231        public FreeAreaDroppable(Point location) {
1232            this.location = location;
1233        }
1234        
1235        /** Implements <code>TopComponentDroppable</code>. */
1236        public java.awt.Shape JavaDoc getIndicationForLocation(Point p) {
1237            return null;
1238        }
1239        
1240        /** Implements <code>TopComponentDroppable</code>. */
1241        public Object JavaDoc getConstraintForLocation(Point p) {
1242            return new Rectangle(location.x, location.y,
1243                Constants.DROP_NEW_MODE_SIZE.width, Constants.DROP_NEW_MODE_SIZE.height);
1244        }
1245        
1246        /** Implements <code>TopComponentDroppable</code>. */
1247        public Component getDropComponent() {
1248            return null;
1249        }
1250        
1251        /** Implements <code>TopComponentDroppable</code>. */
1252        public ViewElement getDropViewElement() {
1253            return null;
1254        }
1255        
1256        public boolean canDrop(TopComponent transfer, Point location) {
1257            ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(transfer);
1258            if (mode == null) {
1259                return false;
1260            }
1261            if (Constants.SWITCH_MODE_ADD_NO_RESTRICT ||
1262                WindowManagerImpl.getInstance().isTopComponentAllowedToMoveAnywhere(transfer)) {
1263                return true;
1264            }
1265
1266            // don't accept drop from separated mode with single component in it,
1267
// it makes no sense (because such DnD into free area equals to
1268
// simple window move)
1269
if (mode.getState() == Constants.MODE_STATE_SEPARATED &&
1270                mode.getOpenedTopComponents().size() == 1) {
1271                return false;
1272            }
1273
1274            return true;
1275        }
1276        
1277        public boolean supportsKind(int kind, TopComponent transfer) {
1278            return true;
1279        }
1280
1281    } // End of class FreeAreaDroppable.
1282

1283    /**
1284     * droppable for the sliding bars, both inside and outside of the main window.
1285     *
1286     */

1287    private static class CenterSlidingDroppable implements TopComponentDroppable, EnhancedDragPainter {
1288        
1289        private ViewAccessor accesor;
1290        private TopComponentDroppable original;
1291        private String JavaDoc side;
1292        JPanel pan;
1293        private boolean isShowing;
1294        
1295        public CenterSlidingDroppable(ViewAccessor viewAccesor, TopComponentDroppable slidingBarDelegate,
1296                                      String JavaDoc side) {
1297            original = slidingBarDelegate;
1298            accesor = viewAccesor;
1299            this.side = side;
1300            pan = new JPanel();
1301            isShowing = false;
1302        }
1303        
1304        public boolean canDrop(TopComponent transfer, Point location) {
1305            return original.canDrop(transfer, location);
1306        }
1307
1308        public Object JavaDoc getConstraintForLocation(Point location) {
1309            return original.getConstraintForLocation(location);
1310        }
1311
1312        public Component getDropComponent() {
1313            return original.getDropComponent();
1314        }
1315
1316        public ViewElement getDropViewElement() {
1317            return original.getDropViewElement();
1318        }
1319
1320        public Shape getIndicationForLocation(Point location) {
1321            Shape toReturn = original.getIndicationForLocation(location);
1322            Rectangle dim = original.getDropComponent().getBounds();
1323            if (dim.width < 10 || dim.height < 10) {
1324                Rectangle rect = toReturn.getBounds();
1325                if (Constants.LEFT.equals(side)) {
1326                    toReturn = new Rectangle(0, 0, Math.max(rect.width, Constants.DROP_AREA_SIZE),
1327                                                   Math.max(rect.height, Constants.DROP_AREA_SIZE));
1328                } else if (Constants.RIGHT.equals(side)) {
1329                    toReturn = new Rectangle(- Constants.DROP_AREA_SIZE, 0, Math.max(rect.width, Constants.DROP_AREA_SIZE),
1330                                                                           Math.max(rect.height, Constants.DROP_AREA_SIZE));
1331                } else if (Constants.BOTTOM.equals(side)) {
1332                    toReturn = new Rectangle(0, - Constants.DROP_AREA_SIZE, Math.max(rect.width, Constants.DROP_AREA_SIZE),
1333                                                                           Math.max(rect.height, Constants.DROP_AREA_SIZE));
1334                }
1335            }
1336            return toReturn;
1337        }
1338        
1339        public boolean isWithinSlide(Point location) {
1340            Component root = SwingUtilities.getRootPane(original.getDropComponent());
1341            Point barLoc = SwingUtilities.convertPoint(root, location, original.getDropComponent());
1342            if (original.getDropComponent().contains(barLoc)) {
1343                return true;
1344            }
1345            Dimension dim = original.getDropComponent().getSize();
1346            if (Constants.LEFT.equals(side)) {
1347                int abs = Math.abs(barLoc.x);
1348                if (barLoc.y > - Constants.DROP_AREA_SIZE && barLoc.y < dim.height + Constants.DROP_AREA_SIZE) {
1349                    if (isShowing && abs < Constants.DROP_AREA_SIZE) {
1350                        return true;
1351                    }
1352                    if (!isShowing && barLoc.x <= 0 && barLoc.x > - Constants.DROP_AREA_SIZE) {
1353                        return true;
1354                    }
1355                }
1356            }
1357            else if (Constants.RIGHT.equals(side)) {
1358                if (barLoc.y > - Constants.DROP_AREA_SIZE && barLoc.y < dim.height + Constants.DROP_AREA_SIZE) {
1359                    if (isShowing && ((barLoc.x < 0 && barLoc.x > - Constants.DROP_AREA_SIZE)
1360                                     || barLoc.x > 0 && barLoc.x - dim.width < Constants.DROP_AREA_SIZE)) {
1361                        return true;
1362                    }
1363                    if (!isShowing && barLoc.x >= 0 && barLoc.x < Constants.DROP_AREA_SIZE + dim.width) {
1364                        return true;
1365                    }
1366                }
1367            }
1368            else if (Constants.BOTTOM.equals(side)) {
1369                if (barLoc.x > - Constants.DROP_AREA_SIZE && barLoc.x < dim.width + Constants.DROP_AREA_SIZE) {
1370                    if (isShowing && ((barLoc.y < 0 && barLoc.y > - Constants.DROP_AREA_SIZE)
1371                                     || barLoc.y > 0 && barLoc.y - dim.height < Constants.DROP_AREA_SIZE)) {
1372                        return true;
1373                    }
1374                    if (!isShowing && barLoc.y >= 0 && barLoc.y < Constants.DROP_AREA_SIZE + dim.height) {
1375                        return true;
1376                    }
1377                }
1378            }
1379            return false;
1380            
1381        }
1382
1383        public boolean supportsKind(int kind, TopComponent transfer) {
1384            return original.supportsKind(kind, transfer);
1385        }
1386
1387        public void additionalDragPaint(Graphics2D g) {
1388            Rectangle dim = original.getDropComponent().getBounds();
1389            if (dim.width > 10 && dim.height > 10) {
1390                return;
1391            }
1392            isShowing = true;
1393            Component glassPane = ((JComponent)original.getDropComponent()).getRootPane().getGlassPane();
1394            Point leftTop = SwingUtilities.convertPoint(original.getDropComponent(), 0, 0, glassPane);
1395            Point firstDivider;
1396            Point secondDevider;
1397                    
1398            if (Constants.RIGHT.equals(side)) {
1399                leftTop = new Point(leftTop.x - 24, leftTop.y);
1400                firstDivider = new Point(leftTop);
1401                secondDevider = new Point(leftTop.x, leftTop.y + dim.height);
1402            }
1403            else if (Constants.BOTTOM.equals(side)) {
1404                leftTop = new Point(0, leftTop.y - 24);
1405                firstDivider = new Point(leftTop);
1406                secondDevider = new Point(leftTop.x + glassPane.getBounds().width, leftTop.y);
1407            } else {
1408                firstDivider = new Point(leftTop.x + 25, leftTop.y);
1409                secondDevider = new Point(leftTop.x + 25, leftTop.y + dim.height);
1410            }
1411            Rectangle rect = new Rectangle(leftTop.x, leftTop.y, Math.max(25, dim.width), Math.max(25, dim.height));
1412            if (Constants.BOTTOM.equals(side)) {
1413                // for bottom has special hack to use the whole width
1414
rect.width = glassPane.getBounds().width;
1415            }
1416            
1417            Color col = g.getColor();
1418            g.setColor(pan.getBackground());
1419            g.fill(rect);
1420            g.setColor(pan.getBackground().darker());
1421            g.drawLine(firstDivider.x, firstDivider.y, secondDevider.x, secondDevider.y);
1422            g.setColor(col);
1423        }
1424        
1425    }
1426
1427}
1428
1429
Popular Tags