KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > DetachedWindow


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.internal;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Vector JavaDoc;
19
20 import org.eclipse.jface.util.Geometry;
21 import org.eclipse.jface.window.Window;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.events.ShellAdapter;
24 import org.eclipse.swt.events.ShellEvent;
25 import org.eclipse.swt.events.ShellListener;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.graphics.Rectangle;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.Control;
30 import org.eclipse.swt.widgets.Event;
31 import org.eclipse.swt.widgets.Listener;
32 import org.eclipse.swt.widgets.Shell;
33 import org.eclipse.ui.IMemento;
34 import org.eclipse.ui.IPropertyListener;
35 import org.eclipse.ui.IWorkbenchPage;
36 import org.eclipse.ui.IWorkbenchPartConstants;
37 import org.eclipse.ui.IWorkbenchPartReference;
38 import org.eclipse.ui.contexts.IContextService;
39 import org.eclipse.ui.internal.dnd.DragUtil;
40 import org.eclipse.ui.internal.dnd.IDragOverListener;
41 import org.eclipse.ui.internal.dnd.IDropTarget;
42 import org.eclipse.ui.internal.presentations.PresentationFactoryUtil;
43 import org.eclipse.ui.internal.presentations.util.AbstractTabFolder;
44 import org.eclipse.ui.internal.presentations.util.AbstractTabItem;
45 import org.eclipse.ui.internal.presentations.util.TabbedStackPresentation;
46 import org.eclipse.ui.presentations.StackDropResult;
47
48
49 /**
50  * TODO: Drag from detached to fast view bar back to detached causes NPE
51  *
52  * @since 3.1
53  */

54 public class DetachedWindow implements IDragOverListener {
55
56     private PartStack folder;
57
58     private WorkbenchPage page;
59     
60     private Rectangle bounds = new Rectangle(0,0,0,0);
61
62     private Shell windowShell;
63     
64     private boolean hideViewsOnClose = true;
65     
66     private ShellListener shellListener = new ShellAdapter() {
67         public void shellClosed(ShellEvent e) {
68             handleClose();
69         }
70     };
71     
72     private Listener resizeListener = new Listener() {
73         public void handleEvent(Event event) {
74             Shell shell = (Shell) event.widget;
75             folder.setBounds(shell.getClientArea());
76         }
77     };
78
79     private IPropertyListener propertyListener = new IPropertyListener() {
80         public void propertyChanged(Object JavaDoc source, int propId) {
81             if (propId == PartStack.PROP_SELECTION) {
82                 activePartChanged(getPartReference(folder.getSelection()));
83             }
84         }
85     };
86
87     private IWorkbenchPartReference activePart;
88
89     private IPropertyListener partPropertyListener = new IPropertyListener() {
90         public void propertyChanged(Object JavaDoc source, int propId) {
91             if (propId == IWorkbenchPartConstants.PROP_TITLE) {
92                 updateTitle();
93             }
94         }
95     };
96     
97     /**
98      * Create a new FloatingWindow.
99      */

100     public DetachedWindow(WorkbenchPage workbenchPage) {
101         this.page = workbenchPage;
102         
103         folder = new ViewStack(page, false, PresentationFactoryUtil.ROLE_VIEW, null);
104         folder.addListener(propertyListener);
105     }
106
107     protected void activePartChanged(IWorkbenchPartReference partReference) {
108         if (activePart == partReference) {
109             return;
110         }
111          
112         if (activePart != null) {
113             activePart.removePropertyListener(partPropertyListener);
114         }
115         activePart = partReference;
116         if (partReference != null) {
117             partReference.addPropertyListener(partPropertyListener);
118         }
119         updateTitle();
120     }
121
122     private void updateTitle() {
123         if (activePart != null) {
124             // Uncomment to set the shell title to match the title of the active part
125
// String text = activePart.getTitle();
126
//
127
// if (!text.equals(s.getText())) {
128
// s.setText(text);
129
// }
130
}
131     }
132
133     private static IWorkbenchPartReference getPartReference(PartPane pane) {
134         
135         if (pane == null) {
136             return null;
137         }
138         
139         return pane.getPartReference();
140     }
141
142     public Shell getShell() {
143         return windowShell;
144     }
145     
146     public void create() {
147         windowShell = ((WorkbenchWindow)page.getWorkbenchWindow()).getDetachedWindowPool().allocateShell(shellListener);
148         windowShell.setData(this);
149         windowShell.setText(""); //$NON-NLS-1$
150
DragUtil.addDragTarget(windowShell, this);
151         hideViewsOnClose = true;
152         if (bounds.isEmpty()) {
153             Point center = Geometry.centerPoint(page.getWorkbenchWindow().getShell().getBounds());
154             Point size = new Point(300, 200);
155             Point upperLeft = Geometry.subtract(center, Geometry.divide(size, 2));
156             
157             bounds = Geometry.createRectangle(upperLeft, size);
158         }
159         getShell().setBounds(bounds);
160
161         configureShell(windowShell);
162         
163         createContents(windowShell);
164         windowShell.layout(true);
165         folder.setBounds(windowShell.getClientArea());
166     }
167     
168     
169     /**
170      * Adds a visual part to this window.
171      * Supports reparenting.
172      */

173     public void add(ViewPane part) {
174
175         Shell shell = getShell();
176         if (shell != null) {
177             part.reparent(shell);
178         }
179         folder.add(part);
180         
181         // Ensure that the shell's minimum size is capable of showing the initial first tab
182
// We can only do this for 'Tabbed' stacked presentations...
183
if (folder.getPresentation() instanceof TabbedStackPresentation) {
184             TabbedStackPresentation stack = (TabbedStackPresentation) folder.getPresentation();
185             
186             AbstractTabFolder tabFolder = stack.getTabFolder();
187             if (tabFolder.getItemCount() == 1) {
188                 // Get the space that we need to show the tab
189
AbstractTabItem firstItem = tabFolder.getItem(0);
190                 Rectangle tabRect = firstItem.getBounds();
191                 
192                 // Take the current shell 'trim' into account
193
int shellHeight = windowShell.getBounds().height - windowShell.getClientArea().height;
194                 int shellWidth = windowShell.getBounds().width - windowShell.getClientArea().width;
195                 
196                 windowShell.setMinimumSize(tabRect.width + shellWidth, tabRect.height + shellHeight);
197             }
198         }
199     }
200
201     public boolean belongsToWorkbenchPage(IWorkbenchPage workbenchPage) {
202         return (this.page == workbenchPage);
203     }
204
205     public boolean close() {
206         hideViewsOnClose = false;
207         Shell shell = getShell();
208         if (shell != null) {
209             shell.close();
210         }
211         return true;
212     }
213     
214     /**
215      * Closes this window and disposes its shell.
216      */

217     private boolean handleClose() {
218         
219         if (hideViewsOnClose) {
220             List JavaDoc views = new ArrayList JavaDoc();
221             collectViewPanes(views, getChildren());
222             Iterator JavaDoc itr = views.iterator();
223             while (itr.hasNext()) {
224                 ViewPane child = (ViewPane) itr.next();
225
226                 // Only close if closable...
227
if (child.isCloseable()) {
228                     page.hideView(child.getViewReference());
229                 } else {
230                     page.attachView(child.getViewReference());
231                 }
232             }
233         }
234
235         if (folder != null) {
236             folder.dispose();
237         }
238         
239         if (windowShell != null) {
240             windowShell.removeListener(SWT.Resize, resizeListener);
241             DragUtil.removeDragTarget(windowShell, this);
242             bounds = windowShell.getBounds();
243
244             // Unregister this detached view as a window (for key bindings).
245
final IContextService contextService = (IContextService) getWorkbenchPage().getWorkbenchWindow().getWorkbench().getService(IContextService.class);
246             contextService.unregisterShell(windowShell);
247
248             windowShell.setData(null);
249             windowShell = null;
250         }
251
252         return true;
253     }
254
255     /* (non-Javadoc)
256      * @see org.eclipse.ui.internal.dnd.IDragOverListener#drag(org.eclipse.swt.widgets.Control, java.lang.Object, org.eclipse.swt.graphics.Point, org.eclipse.swt.graphics.Rectangle)
257      */

258     public IDropTarget drag(Control currentControl, Object JavaDoc draggedObject,
259             Point position, Rectangle dragRectangle) {
260
261         if (!(draggedObject instanceof PartPane)) {
262             return null;
263         }
264
265         final PartPane sourcePart = (PartPane) draggedObject;
266
267         if (sourcePart.getWorkbenchWindow() != page.getWorkbenchWindow()) {
268             return null;
269         }
270     
271         // Only handle the event if the source part is acceptable to the particular PartStack
272
IDropTarget target = null;
273         if (folder.allowsDrop(sourcePart)) {
274             target = folder.getDropTarget(draggedObject, position);
275             
276             if (target == null) {
277                 Rectangle displayBounds = DragUtil.getDisplayBounds(folder.getControl());
278                 if (displayBounds.contains(position)) {
279                     target = folder.createDropTarget(sourcePart, new StackDropResult(displayBounds, null));
280                 } else {
281                     return null;
282                 }
283             }
284         }
285         
286         return target;
287     }
288     
289     /**
290      * Answer a list of the view panes.
291      */

292     private void collectViewPanes(List JavaDoc result, LayoutPart[] parts) {
293         for (int i = 0, length = parts.length; i < length; i++) {
294             LayoutPart part = parts[i];
295             if (part instanceof ViewPane) {
296                 result.add(part);
297             }
298         }
299     }
300
301     /**
302      * This method will be called to initialize the given Shell's layout
303      */

304     protected void configureShell(Shell shell) {
305         updateTitle();
306         shell.addListener(SWT.Resize, resizeListener);
307
308         // Register this detached view as a window (for key bindings).
309
final IContextService contextService = (IContextService) getWorkbenchPage()
310                 .getWorkbenchWindow().getWorkbench().getService(IContextService.class);
311         contextService.registerShell(shell,
312                 IContextService.TYPE_WINDOW);
313
314         page.getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp(shell,
315                 IWorkbenchHelpContextIds.DETACHED_WINDOW);
316     }
317
318     /**
319      * Override this method to create the widget tree that is used as the window's contents.
320      */

321     protected Control createContents(Composite parent) {
322         // Create the tab folder.
323
folder.createControl(parent);
324
325         // Reparent each view in the tab folder.
326
Vector JavaDoc detachedChildren = new Vector JavaDoc();
327         collectViewPanes(detachedChildren, getChildren());
328         Enumeration JavaDoc itr = detachedChildren.elements();
329         while (itr.hasMoreElements()) {
330             LayoutPart part = (LayoutPart) itr.nextElement();
331             part.reparent(parent);
332         }
333
334         // Return tab folder control.
335
return folder.getControl();
336     }
337
338     public LayoutPart[] getChildren() {
339         return folder.getChildren();
340     }
341
342     public WorkbenchPage getWorkbenchPage() {
343         return this.page;
344     }
345
346     /**
347      * @see IPersistablePart
348      */

349     public void restoreState(IMemento memento) {
350         // Read the bounds.
351
Integer JavaDoc bigInt;
352         bigInt = memento.getInteger(IWorkbenchConstants.TAG_X);
353         int x = bigInt.intValue();
354         bigInt = memento.getInteger(IWorkbenchConstants.TAG_Y);
355         int y = bigInt.intValue();
356         bigInt = memento.getInteger(IWorkbenchConstants.TAG_WIDTH);
357         int width = bigInt.intValue();
358         bigInt = memento.getInteger(IWorkbenchConstants.TAG_HEIGHT);
359         int height = bigInt.intValue();
360         bigInt = memento.getInteger(IWorkbenchConstants.TAG_FLOAT);
361
362         // Set the bounds.
363
bounds = new Rectangle(x, y, width, height);
364         if (getShell() != null) {
365             getShell().setBounds(bounds);
366         }
367         
368         // Create the folder.
369
IMemento childMem = memento.getChild(IWorkbenchConstants.TAG_FOLDER);
370         if (childMem != null) {
371             folder.restoreState(childMem);
372         }
373     }
374
375     /**
376      * @see IPersistablePart
377      */

378     public void saveState(IMemento memento) {
379         if (getShell() != null) {
380             bounds = getShell().getBounds();
381         }
382
383         // Save the bounds.
384
memento.putInteger(IWorkbenchConstants.TAG_X, bounds.x);
385         memento.putInteger(IWorkbenchConstants.TAG_Y, bounds.y);
386         memento.putInteger(IWorkbenchConstants.TAG_WIDTH, bounds.width);
387         memento.putInteger(IWorkbenchConstants.TAG_HEIGHT, bounds.height);
388
389         // Save the views.
390
IMemento childMem = memento.createChild(IWorkbenchConstants.TAG_FOLDER);
391         folder.saveState(childMem);
392     }
393     
394     /* (non-Javadoc)
395      * @see org.eclipse.ui.internal.IWorkbenchDragDropPart#getControl()
396      */

397     public Control getControl() {
398         return folder.getControl();
399     }
400     
401     /**
402      * Opens the detached window.
403      */

404     public int open() {
405          
406         if (getShell() == null) {
407             create();
408         }
409
410         Rectangle bounds = getShell().getBounds();
411         getShell().setVisible(true);
412          
413         if (!bounds.equals(getShell().getBounds())) {
414             getShell().setBounds(bounds);
415         }
416          
417         return Window.OK;
418     }
419     
420 }
421
Popular Tags