KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 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  * Chris Grindstaff <chris@gstaff.org> - Fix for bug 158016
11  *******************************************************************************/

12 package org.eclipse.ui.internal;
13
14 import java.util.Arrays JavaDoc;
15 import java.util.StringTokenizer JavaDoc;
16
17 import org.eclipse.core.runtime.Assert;
18 import org.eclipse.jface.action.IContributionItem;
19 import org.eclipse.jface.preference.IPreferenceStore;
20 import org.eclipse.jface.util.IPropertyChangeListener;
21 import org.eclipse.jface.util.PropertyChangeEvent;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.custom.CBanner;
24 import org.eclipse.swt.events.ControlAdapter;
25 import org.eclipse.swt.events.ControlEvent;
26 import org.eclipse.swt.events.DisposeEvent;
27 import org.eclipse.swt.events.DisposeListener;
28 import org.eclipse.swt.events.SelectionAdapter;
29 import org.eclipse.swt.events.SelectionEvent;
30 import org.eclipse.swt.events.SelectionListener;
31 import org.eclipse.swt.graphics.Cursor;
32 import org.eclipse.swt.graphics.Point;
33 import org.eclipse.swt.graphics.Rectangle;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.Control;
37 import org.eclipse.swt.widgets.CoolBar;
38 import org.eclipse.swt.widgets.CoolItem;
39 import org.eclipse.swt.widgets.Event;
40 import org.eclipse.swt.widgets.Label;
41 import org.eclipse.swt.widgets.Listener;
42 import org.eclipse.swt.widgets.Menu;
43 import org.eclipse.swt.widgets.MenuItem;
44 import org.eclipse.swt.widgets.ToolBar;
45 import org.eclipse.swt.widgets.ToolItem;
46 import org.eclipse.ui.IMemento;
47 import org.eclipse.ui.IPageListener;
48 import org.eclipse.ui.IPerspectiveDescriptor;
49 import org.eclipse.ui.IWorkbenchPage;
50 import org.eclipse.ui.IWorkbenchPreferenceConstants;
51 import org.eclipse.ui.IWorkbenchWindow;
52 import org.eclipse.ui.PerspectiveAdapter;
53 import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
54 import org.eclipse.ui.internal.dnd.AbstractDropTarget;
55 import org.eclipse.ui.internal.dnd.DragUtil;
56 import org.eclipse.ui.internal.dnd.IDragOverListener;
57 import org.eclipse.ui.internal.dnd.IDropTarget;
58 import org.eclipse.ui.internal.layout.CacheWrapper;
59 import org.eclipse.ui.internal.layout.CellLayout;
60 import org.eclipse.ui.internal.layout.ITrimManager;
61 import org.eclipse.ui.internal.layout.IWindowTrim;
62 import org.eclipse.ui.internal.layout.LayoutUtil;
63 import org.eclipse.ui.internal.layout.Row;
64 import org.eclipse.ui.internal.util.PrefUtil;
65 import org.eclipse.ui.presentations.PresentationUtil;
66
67 /**
68  * A utility class to manage the perspective switcher. At some point, it might be nice to
69  * move all this into PerspectiveViewBar.
70  *
71  * @since 3.0
72  */

73 public class PerspectiveSwitcher implements IWindowTrim {
74
75     /**
76      * The minimal width for the switcher (i.e. for the open button and chevron).
77      */

78     private static final int MIN_WIDTH = 45;
79     
80     /**
81      * The average width for each perspective button.
82      */

83     private static final int ITEM_WIDTH = 80;
84     
85     /**
86      * The minimum default width.
87      */

88     private static final int MIN_DEFAULT_WIDTH = 160;
89     
90     private IWorkbenchWindow window;
91
92     private CBanner topBar;
93
94     private int style;
95
96     private Composite parent;
97
98     private Composite trimControl;
99
100     private Label trimSeparator;
101
102     private GridData trimLayoutData;
103
104     private boolean trimVisible = false;
105
106     private int trimOldLength = 0;
107
108     private PerspectiveBarManager perspectiveBar;
109
110     private CoolBar perspectiveCoolBar;
111
112     private CacheWrapper perspectiveCoolBarWrapper;
113
114     private CoolItem coolItem;
115
116     private CacheWrapper toolbarWrapper;
117
118     // The menus are cached, so the radio buttons should not be disposed until
119
// the switcher is disposed.
120
private Menu popupMenu;
121
122     private Menu genericMenu;
123
124     private static final int INITIAL = -1;
125
126     private static final int TOP_RIGHT = 1;
127
128     private static final int TOP_LEFT = 2;
129
130     private static final int LEFT = 3;
131
132     private int currentLocation = INITIAL;
133
134     private IPreferenceStore apiPreferenceStore = PrefUtil
135             .getAPIPreferenceStore();
136
137     private IPropertyChangeListener propertyChangeListener;
138
139     private Listener popupListener = new Listener() {
140         public void handleEvent(Event event) {
141             if (event.type == SWT.MenuDetect) {
142                 showPerspectiveBarPopup(new Point(event.x, event.y));
143             }
144         }
145     };
146
147     class ChangeListener extends PerspectiveAdapter implements IPageListener {
148         public void perspectiveOpened(IWorkbenchPage page,
149                 IPerspectiveDescriptor perspective) {
150             if (findPerspectiveShortcut(perspective, page) == null) {
151                 addPerspectiveShortcut(perspective, page);
152             }
153         }
154         public void perspectiveClosed(IWorkbenchPage page,
155                 IPerspectiveDescriptor perspective) {
156             // Don't remove the shortcut if the workbench is
157
// closing. This causes a spurious 'layout' on the
158
// shell during close, leading to possible life-cycle issues
159
if (page != null && !page.getWorkbenchWindow().getWorkbench().isClosing()) {
160                 removePerspectiveShortcut(perspective, page);
161             }
162         }
163         public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
164             selectPerspectiveShortcut(perspective, page, true);
165         }
166         public void perspectiveDeactivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
167             selectPerspectiveShortcut(perspective, page, false);
168         }
169         public void perspectiveSavedAs(IWorkbenchPage page,
170                 IPerspectiveDescriptor oldPerspective,
171                 IPerspectiveDescriptor newPerspective) {
172             updatePerspectiveShortcut(oldPerspective, newPerspective, page);
173         }
174         public void pageActivated(IWorkbenchPage page) {
175         }
176
177         public void pageClosed(IWorkbenchPage page) {
178         }
179
180         public void pageOpened(IWorkbenchPage page) {
181         }
182     }
183     
184     private ChangeListener changeListener = new ChangeListener();
185     
186     private Listener dragListener;
187
188     private IDragOverListener dragTarget;
189
190     private DisposeListener toolBarListener;
191
192     private IReorderListener reorderListener;
193
194     /**
195      * Creates an instance of the perspective switcher.
196      * @param window it's window
197      * @param topBar the CBanner to place this widget in
198      * @param style the widget style to use
199      */

200     public PerspectiveSwitcher(IWorkbenchWindow window, CBanner topBar, int style) {
201         this.window = window;
202         this.topBar = topBar;
203         this.style = style;
204         setPropertyChangeListener();
205         // this listener will only be run when the Shell is being disposed
206
// and each WorkbenchWindow has its own PerspectiveSwitcher
207
toolBarListener = new DisposeListener() {
208             public void widgetDisposed(DisposeEvent e) {
209                 dispose();
210             }
211         };
212         window.addPerspectiveListener(changeListener);
213         window.addPageListener(changeListener);
214     }
215
216     private static int convertLocation(String JavaDoc preference) {
217         if (IWorkbenchPreferenceConstants.TOP_RIGHT.equals(preference)) {
218             return TOP_RIGHT;
219         }
220         if (IWorkbenchPreferenceConstants.TOP_LEFT.equals(preference)) {
221             return TOP_LEFT;
222         }
223         if (IWorkbenchPreferenceConstants.LEFT.equals(preference)) {
224             return LEFT;
225         }
226
227         return TOP_RIGHT;
228     }
229
230     /**
231      * Create the contents of the receiver
232      * @param parent
233      */

234     public void createControl(Composite parent) {
235         Assert.isTrue(this.parent == null);
236         this.parent = parent;
237         // set the initial location read from the preference
238
setPerspectiveBarLocation(PrefUtil.getAPIPreferenceStore().getString(
239                 IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR));
240     }
241
242     private void addPerspectiveShortcut(IPerspectiveDescriptor perspective,
243             IWorkbenchPage workbenchPage) {
244         if (perspectiveBar == null) {
245             return;
246         }
247
248         PerspectiveBarContributionItem item = new PerspectiveBarContributionItem(
249                 perspective, workbenchPage);
250         perspectiveBar.addItem(item);
251         setCoolItemSize(coolItem);
252         // This is need to update the vertical size of the tool bar on GTK+ when
253
// using large fonts.
254
if (perspectiveBar != null) {
255             perspectiveBar.update(true);
256         }
257     }
258
259     /**
260      * Find a contribution item that matches the perspective provided.
261      *
262      * @param perspective
263      * @param page
264      * @return the <code>IContributionItem</code> or null if no matches were found
265      */

266     public IContributionItem findPerspectiveShortcut(
267             IPerspectiveDescriptor perspective, IWorkbenchPage page) {
268         if (perspectiveBar == null) {
269             return null;
270         }
271
272         IContributionItem[] items = perspectiveBar.getItems();
273         int length = items.length;
274         for (int i = 0; i < length; i++) {
275             IContributionItem item = items[i];
276             if (item instanceof PerspectiveBarContributionItem
277                     && ((PerspectiveBarContributionItem) item).handles(
278                             perspective, page)) {
279                 return item;
280             }
281         }
282         return null;
283     }
284
285     private void removePerspectiveShortcut(IPerspectiveDescriptor perspective,
286             IWorkbenchPage page) {
287         if (perspectiveBar == null) {
288             return;
289         }
290
291         IContributionItem item = findPerspectiveShortcut(perspective, page);
292         if (item != null) {
293             if (item instanceof PerspectiveBarContributionItem) {
294                 perspectiveBar
295                         .removeItem((PerspectiveBarContributionItem) item);
296             }
297             item.dispose();
298             perspectiveBar.update(false);
299             setCoolItemSize(coolItem);
300         }
301     }
302
303     /**
304      * Locate the perspective bar according to the provided location
305      * @param preference the location to put the perspective bar at
306      */

307     public void setPerspectiveBarLocation(String JavaDoc preference) {
308         // return if the control has not been created. createControl(...) will
309
// handle updating the state in that case
310
if (parent == null) {
311             return;
312         }
313         int newLocation = convertLocation(preference);
314         if (newLocation == currentLocation) {
315             return;
316         }
317         createControlForLocation(newLocation);
318         currentLocation = newLocation;
319         showPerspectiveBar();
320         if (newLocation == TOP_LEFT || newLocation == TOP_RIGHT) {
321             updatePerspectiveBar();
322             updateBarParent();
323         }
324     }
325
326     /**
327      * Make the perspective bar visible in its current location. This method
328      * should not be used unless the control has been successfully created.
329      */

330     private void showPerspectiveBar() {
331         switch (currentLocation) {
332         case TOP_LEFT:
333             topBar.setRight(null);
334             topBar.setBottom(perspectiveCoolBarWrapper.getControl());
335             break;
336         case TOP_RIGHT:
337             topBar.setBottom(null);
338             topBar.setRight(perspectiveCoolBarWrapper.getControl());
339             topBar.setRightWidth(getDefaultWidth());
340             break;
341         case LEFT:
342             topBar.setBottom(null);
343             topBar.setRight(null);
344             LayoutUtil.resize(topBar);
345             getTrimManager().addTrim(SWT.LEFT, this);
346             break;
347         default:
348             return;
349         }
350
351         LayoutUtil.resize(perspectiveBar.getControl());
352     }
353
354     /**
355      * Returns the default width for the switcher.
356      */

357     private int getDefaultWidth() {
358         String JavaDoc extras = PrefUtil.getAPIPreferenceStore().getString(
359                 IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS);
360         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(extras, ", "); //$NON-NLS-1$
361
int numExtras = tok.countTokens();
362         int numPersps = Math.max(numExtras, 1); // assume initial perspective is also listed in extras
363
return Math.max(MIN_DEFAULT_WIDTH, MIN_WIDTH + (numPersps*ITEM_WIDTH));
364     }
365
366     /**
367      * Get the trim manager from the default workbench window. If the current
368      * workbench window is -not- the <code>WorkbenchWindow</code> then return null.
369      *
370      * @return The trim manager for the current workbench window
371      */

372     private ITrimManager getTrimManager() {
373         if (window instanceof WorkbenchWindow)
374             return ((WorkbenchWindow)window).getTrimManager();
375         
376         return null; // not using the default workbench window
377
}
378
379     /**
380      * Update the receiver
381      * @param force
382      */

383     public void update(boolean force) {
384         if (perspectiveBar == null) {
385             return;
386         }
387
388         perspectiveBar.update(force);
389
390         if (currentLocation == LEFT) {
391             ToolItem[] items = perspectiveBar.getControl().getItems();
392             boolean shouldExpand = items.length > 0;
393             if (shouldExpand != trimVisible) {
394                 perspectiveBar.getControl().setVisible(true);
395                 trimVisible = shouldExpand;
396             }
397
398             if (items.length != trimOldLength) {
399                 LayoutUtil.resize(trimControl);
400                 trimOldLength = items.length;
401             }
402         }
403     }
404
405     private void selectPerspectiveShortcut(IPerspectiveDescriptor perspective,
406             IWorkbenchPage page, boolean selected) {
407         IContributionItem item = findPerspectiveShortcut(perspective, page);
408         if (item != null && (item instanceof PerspectiveBarContributionItem)) {
409             if (selected) {
410                 // check if not visible and ensure visible
411
PerspectiveBarContributionItem contribItem = (PerspectiveBarContributionItem) item;
412                 perspectiveBar.select(contribItem);
413             }
414             // select or de-select
415
((PerspectiveBarContributionItem) item).setSelection(selected);
416         }
417     }
418
419     private void updatePerspectiveShortcut(IPerspectiveDescriptor oldDesc,
420             IPerspectiveDescriptor newDesc, IWorkbenchPage page) {
421         IContributionItem item = findPerspectiveShortcut(oldDesc, page);
422         if (item != null && (item instanceof PerspectiveBarContributionItem)) {
423             ((PerspectiveBarContributionItem) item).update(newDesc);
424         }
425     }
426
427     /**
428      * Answer the perspective bar manager
429      * @return the manager
430      */

431     public PerspectiveBarManager getPerspectiveBar() {
432         return perspectiveBar;
433     }
434
435     /**
436      * Dispose resources being held by the receiver
437      */

438     public void dispose() {
439         window.removePerspectiveListener(changeListener);
440         window.removePageListener(changeListener);
441         if (propertyChangeListener != null) {
442             apiPreferenceStore
443                     .removePropertyChangeListener(propertyChangeListener);
444             propertyChangeListener = null;
445         }
446         unhookDragSupport();
447         disposeChildControls();
448         toolBarListener = null;
449     }
450
451     private void disposeChildControls() {
452
453         if (trimControl != null) {
454             trimControl.dispose();
455             trimControl = null;
456         }
457
458         if (trimSeparator != null) {
459             trimSeparator.dispose();
460             trimSeparator = null;
461         }
462
463         if (perspectiveCoolBar != null) {
464             perspectiveCoolBar.dispose();
465             perspectiveCoolBar = null;
466         }
467
468         if (toolbarWrapper != null) {
469             toolbarWrapper.dispose();
470             toolbarWrapper = null;
471         }
472
473         if (perspectiveBar != null) {
474             perspectiveBar.dispose();
475             perspectiveBar = null;
476         }
477
478         perspectiveCoolBarWrapper = null;
479     }
480
481     /**
482      * Ensures the control has been set for the argument location. If the
483      * control already exists and can be used the argument location, nothing
484      * happens. Updates the location attribute.
485      *
486      * @param newLocation
487      */

488     private void createControlForLocation(int newLocation) {
489         // if there is a control, then perhaps it can be reused
490
if (perspectiveBar != null && perspectiveBar.getControl() != null
491                 && !perspectiveBar.getControl().isDisposed()) {
492             if (newLocation == LEFT && currentLocation == LEFT) {
493                 return;
494             }
495             if ((newLocation == TOP_LEFT || newLocation == TOP_RIGHT)
496                     && (currentLocation == TOP_LEFT || currentLocation == TOP_RIGHT)) {
497                 return;
498             }
499         }
500
501         if (perspectiveBar != null) {
502             perspectiveBar.getControl().removeDisposeListener(toolBarListener);
503             unhookDragSupport();
504         }
505         // otherwise dispose the current controls and make new ones
506

507         // First, make sure that the existing verion is removed from the trim layout
508
getTrimManager().removeTrim(this);
509
510         disposeChildControls();
511         if (newLocation == LEFT) {
512             createControlForLeft();
513         } else {
514             createControlForTop();
515         }
516         hookDragSupport();
517
518         perspectiveBar.getControl().addDisposeListener(toolBarListener);
519     }
520
521     /**
522      * Remove any drag and drop support and associated listeners hooked for the
523      * perspective switcher.
524      */

525     private void unhookDragSupport() {
526         ToolBar bar = perspectiveBar.getControl();
527
528         if (bar == null || bar.isDisposed() || dragListener == null) {
529             return;
530         }
531         PresentationUtil.removeDragListener(bar, dragListener);
532         DragUtil.removeDragTarget(perspectiveBar.getControl(), dragTarget);
533         dragListener = null;
534         dragTarget = null;
535     }
536
537     /**
538      * Attach drag and drop support and associated listeners hooked for
539      * the perspective switcher.
540      */

541      private void hookDragSupport() {
542         dragListener = new Listener() {
543             /* (non-Javadoc)
544              * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
545              */

546             public void handleEvent(Event event) {
547                 ToolBar toolbar = perspectiveBar.getControl();
548                 ToolItem item = toolbar.getItem(new Point(event.x, event.y));
549                 
550                 if (item != null) {
551                     //ignore the first item, which remains in position Zero
552
if (item.getData() instanceof PerspectiveBarNewContributionItem) {
553                         return;
554                     }
555                     
556                     Rectangle bounds = item.getBounds();
557                     Rectangle parentBounds = toolbar.getBounds();
558                     bounds.x += parentBounds.x;
559                     bounds.y += parentBounds.y;
560                     startDragging(item.getData(), toolbar.getDisplay().map(toolbar, null, bounds));
561                 } else {
562                     //startDragging(toolbar, toolbar.getDisplay().map(toolbar, null, toolbar.getBounds()));
563
}
564             }
565             
566             private void startDragging(Object JavaDoc widget, Rectangle bounds) {
567                 if(!DragUtil.performDrag(widget, bounds, new Point(bounds.x, bounds.y), true)) {
568                        //currently do nothing on a failed drag
569
}
570             }
571         };
572
573         dragTarget = new IDragOverListener() {
574             protected PerspectiveDropTarget perspectiveDropTarget;
575
576             class PerspectiveDropTarget extends AbstractDropTarget {
577
578                 private PerspectiveBarContributionItem perspective;
579
580                 private Point location;
581
582                 /**
583                  * @param location
584                  * @param draggedObject
585                  */

586                 public PerspectiveDropTarget(Object JavaDoc draggedObject,
587                         Point location) {
588                     update(draggedObject, location);
589                 }
590
591                 /**
592                  *
593                  * @param draggedObject
594                  * @param location
595                  */

596                 private void update(Object JavaDoc draggedObject, Point location) {
597                     this.location = location;
598                     this.perspective = (PerspectiveBarContributionItem) draggedObject;
599                 }
600
601                 /*
602                  * (non-Javadoc)
603                  *
604                  * @see org.eclipse.ui.internal.dnd.IDropTarget#drop()
605                  */

606                 public void drop() {
607                     ToolBar toolBar = perspectiveBar.getControl();
608                     ToolItem item = toolBar.getItem(toolBar.getDisplay().map(
609                             null, toolBar, location));
610                     if (toolBar.getItem(0) == item) {
611                         return;
612                     }
613                     ToolItem[] items = toolBar.getItems();
614                     ToolItem droppedItem = null;
615                     int dropIndex = -1;
616                     for (int i = 0; i < items.length; i++) {
617                         if (item == items[i]) {
618                             dropIndex = i;
619                         }
620                         if (items[i].getData() == perspective) {
621                             droppedItem = items[i];
622                         }
623                     }
624                     if (dropIndex != -1 && droppedItem != null && (droppedItem != item)) {
625                         PerspectiveBarContributionItem barItem = (PerspectiveBarContributionItem) droppedItem.getData();
626                         // policy is to insert at the beginning so mirror the value when indicating a
627
// new position for the perspective
628
if (reorderListener != null) {
629                             reorderListener.reorder(barItem.getPerspective(), Math.abs(dropIndex - (items.length - 1)));
630                         }
631
632                         perspectiveBar.relocate(barItem, dropIndex);
633                     }
634                 }
635
636                 /*
637                  * (non-Javadoc)
638                  *
639                  * @see org.eclipse.ui.internal.dnd.IDropTarget#getCursor()
640                  */

641                 public Cursor getCursor() {
642                     return DragCursors.getCursor(DragCursors.CENTER);
643                 }
644
645                 boolean sameShell() {
646                     return perspective.getToolItem().getParent().getShell().equals(perspectiveBar.getControl().getShell());
647                 }
648                 
649                 public Rectangle getSnapRectangle() {
650                     ToolBar toolBar = perspectiveBar.getControl();
651                     ToolItem item = toolBar.getItem(toolBar.getDisplay().map(
652                             null, toolBar, location));
653                     Rectangle bounds;
654                     if (item != null && item != toolBar.getItem(0)) {
655                         bounds = item.getBounds();
656                     } else {
657                         // it should not be possible to start a drag with item 0
658
return null;
659                     }
660                     return toolBar.getDisplay().map(toolBar, null, bounds);
661                 }
662             }
663
664             public IDropTarget drag(Control currentControl,
665                     Object JavaDoc draggedObject, Point position,
666                     Rectangle dragRectangle) {
667                 if (draggedObject instanceof PerspectiveBarContributionItem) {
668                     if (perspectiveDropTarget == null) {
669                         perspectiveDropTarget = new PerspectiveDropTarget(
670                                 draggedObject, position);
671                     } else {
672                         perspectiveDropTarget.update(draggedObject, position);
673                     }
674                     // do not support drag to perspective bars between shells.
675
if (!perspectiveDropTarget.sameShell()) {
676                         return null;
677                     }
678                     
679                     return perspectiveDropTarget;
680                 }// else if (draggedObject instanceof IPerspectiveBar) {
681
// return new PerspectiveBarDropTarget();
682
//}
683

684                 return null;
685             }
686
687         };
688
689         PresentationUtil.addDragListener(perspectiveBar.getControl(),
690                 dragListener);
691         DragUtil.addDragTarget(perspectiveBar.getControl(), dragTarget);
692     }
693
694     private void setPropertyChangeListener() {
695         propertyChangeListener = new IPropertyChangeListener() {
696
697             public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
698                 if (IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR
699                         .equals(propertyChangeEvent.getProperty())) {
700                     if (perspectiveBar == null) {
701                         return;
702                     }
703                     updatePerspectiveBar();
704                     updateBarParent();
705                 }
706             }
707         };
708         apiPreferenceStore.addPropertyChangeListener(propertyChangeListener);
709     }
710
711     private void createControlForLeft() {
712         trimControl = new Composite(parent, SWT.NONE);
713
714         trimControl.setLayout(new CellLayout(1).setMargins(0, 0).setSpacing(3,
715                 3).setDefaultRow(Row.fixed()).setDefaultColumn(Row.growing()));
716
717         perspectiveBar = createBarManager(SWT.VERTICAL);
718
719         perspectiveBar.createControl(trimControl);
720         perspectiveBar.getControl().addListener(SWT.MenuDetect, popupListener);
721
722 // trimSeparator = new Label(trimControl, SWT.SEPARATOR | SWT.HORIZONTAL);
723
// GridData sepData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
724
// | GridData.HORIZONTAL_ALIGN_CENTER);
725
// sepData.widthHint = SEPARATOR_LENGTH;
726
// trimSeparator.setLayoutData(sepData);
727
// trimSeparator.setVisible(false);
728

729         trimLayoutData = new GridData(GridData.FILL_BOTH);
730         trimVisible = false;
731         perspectiveBar.getControl().setLayoutData(trimLayoutData);
732     }
733
734     private void createControlForTop() {
735         perspectiveBar = createBarManager(SWT.HORIZONTAL);
736
737         perspectiveCoolBarWrapper = new CacheWrapper(topBar);
738         perspectiveCoolBar = new CoolBar(
739                 perspectiveCoolBarWrapper.getControl(), SWT.FLAT);
740         coolItem = new CoolItem(perspectiveCoolBar, SWT.DROP_DOWN);
741         toolbarWrapper = new CacheWrapper(perspectiveCoolBar);
742         perspectiveBar.createControl(toolbarWrapper.getControl());
743         coolItem.setControl(toolbarWrapper.getControl());
744         perspectiveCoolBar.setLocked(true);
745         perspectiveBar.setParent(perspectiveCoolBar);
746         perspectiveBar.update(true);
747
748         // adjust the toolbar size to display as many items as possible
749
perspectiveCoolBar.addControlListener(new ControlAdapter() {
750             public void controlResized(ControlEvent e) {
751                 setCoolItemSize(coolItem);
752             }
753         });
754
755         coolItem.addSelectionListener(new SelectionAdapter() {
756             public void widgetSelected(SelectionEvent e) {
757                 if (e.detail == SWT.ARROW) {
758                     if (perspectiveBar != null) {
759                         perspectiveBar.handleChevron(e);
760                     }
761                 }
762             }
763         });
764         coolItem.setMinimumSize(0, 0);
765         perspectiveBar.getControl().addListener(SWT.MenuDetect, popupListener);
766     }
767
768     /**
769      * @param coolItem
770      */

771     private void setCoolItemSize(final CoolItem coolItem) {
772         // there is no coolItem when the bar is on the left
773
if (currentLocation == LEFT) {
774             return;
775         }
776
777         ToolBar toolbar = perspectiveBar.getControl();
778         if (toolbar == null) {
779             return;
780         }
781
782         int rowHeight = 0;
783         ToolItem[] toolItems = toolbar.getItems();
784         for (int i = 0; i < toolItems.length; i++) {
785             rowHeight = Math.max(rowHeight, toolItems[i].getBounds().height);
786         }
787
788         Rectangle area = perspectiveCoolBar.getClientArea();
789         int rows = rowHeight <= 0 ? 1 : (int) Math.max(1, Math
790                 .floor(area.height / rowHeight));
791         if (rows == 1 || (toolbar.getStyle() & SWT.WRAP) == 0
792                 || currentLocation == TOP_LEFT) {
793             Point p = toolbar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
794             coolItem.setSize(coolItem.computeSize(p.x, p.y));
795             return;
796         }
797         Point offset = coolItem.computeSize(0, 0);
798         Point wrappedSize = toolbar.computeSize(area.width - offset.x,
799                 SWT.DEFAULT);
800         int h = rows * rowHeight;
801         int w = wrappedSize.y <= h ? wrappedSize.x : wrappedSize.x + 1;
802         coolItem.setSize(coolItem.computeSize(w, h));
803     }
804
805     private void showPerspectiveBarPopup(Point pt) {
806         if (perspectiveBar == null) {
807             return;
808         }
809
810         // Get the tool item under the mouse.
811
ToolBar toolBar = perspectiveBar.getControl();
812         ToolItem toolItem = toolBar.getItem(toolBar.toControl(pt));
813         
814         // Get the action for the tool item.
815
Object JavaDoc data = null;
816         if (toolItem != null){
817             data = toolItem.getData();
818         }
819         if (toolItem == null
820                 || !(data instanceof PerspectiveBarContributionItem)) {
821             if (genericMenu == null) {
822                 Menu menu = new Menu(toolBar);
823                 addDockOnSubMenu(menu);
824                 addShowTextItem(menu);
825                 genericMenu = menu;
826             }
827
828             // set the state of the menu items to match the preferences
829
genericMenu
830                     .getItem(1)
831                     .setSelection(
832                             PrefUtil
833                                     .getAPIPreferenceStore()
834                                     .getBoolean(
835                                             IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR));
836             updateLocationItems(genericMenu.getItem(0).getMenu(),
837                     currentLocation);
838
839             // Show popup menu.
840
genericMenu.setLocation(pt.x, pt.y);
841             genericMenu.setVisible(true);
842             return;
843         }
844
845         if (data == null || !(data instanceof PerspectiveBarContributionItem)) {
846             return;
847         }
848
849         PerspectiveBarContributionItem pbci = (PerspectiveBarContributionItem) data;
850         IPerspectiveDescriptor selectedPerspective = pbci.getPerspective();
851
852         // The perspective bar menu is created lazily here.
853
// Its data is set (each time) to the tool item, which refers to the SetPagePerspectiveAction
854
// which in turn refers to the page and perspective.
855
// It is important not to refer to the action, the page or the perspective directly
856
// since otherwise the menu hangs on to them after they are closed.
857
// By hanging onto the tool item instead, these references are cleared when the
858
// corresponding page or perspective is closed.
859
// See bug 11282 for more details on why it is done this way.
860
if (popupMenu != null) {
861             popupMenu.dispose();
862             popupMenu = null;
863         }
864         popupMenu = createPopup(toolBar, selectedPerspective);
865         popupMenu.setData(toolItem);
866         
867         // Show popup menu.
868
popupMenu.setLocation(pt.x, pt.y);
869         popupMenu.setVisible(true);
870     }
871
872     /**
873      * @param persp the perspective
874      * @return <code>true</code> if the perspective is active in the active page
875      */

876     private boolean perspectiveIsActive(IPerspectiveDescriptor persp) {
877         IWorkbenchPage page = window.getActivePage();
878         return page != null && persp.equals(page.getPerspective());
879     }
880
881     /**
882      * @param persp the perspective
883      * @return <code>true</code> if the perspective is open in the active page
884      */

885     private boolean perspectiveIsOpen(IPerspectiveDescriptor persp) {
886         IWorkbenchPage page = window.getActivePage();
887         return page != null && Arrays.asList(page.getOpenPerspectives()).contains(persp);
888     }
889
890     private Menu createPopup(ToolBar toolBar, IPerspectiveDescriptor persp){
891         Menu menu = new Menu(toolBar);
892         if (perspectiveIsActive(persp)) {
893             addCustomizeItem(menu);
894             addSaveAsItem(menu);
895             addResetItem(menu);
896         }
897         if (perspectiveIsOpen(persp)) {
898             addCloseItem(menu);
899         }
900
901         new MenuItem(menu, SWT.SEPARATOR);
902         addDockOnSubMenu(menu);
903         addShowTextItem(menu);
904         return menu;
905     }
906
907     private void addCloseItem(Menu menu) {
908         MenuItem menuItem = new MenuItem(menu, SWT.NONE);
909         menuItem.setText(WorkbenchMessages.WorkbenchWindow_close);
910         window.getWorkbench().getHelpSystem().setHelp(menuItem,
911                 IWorkbenchHelpContextIds.CLOSE_PAGE_ACTION);
912         menuItem.addSelectionListener(new SelectionAdapter() {
913             public void widgetSelected(SelectionEvent e) {
914                 ToolItem perspectiveToolItem = (ToolItem) popupMenu
915                         .getData();
916                 if (perspectiveToolItem != null
917                         && !perspectiveToolItem.isDisposed()) {
918                     PerspectiveBarContributionItem item = (PerspectiveBarContributionItem) perspectiveToolItem
919                             .getData();
920                     item.getPage().closePerspective(item.getPerspective(),
921                             true, true);
922                 }
923             }
924         });
925     }
926
927     /**
928      * @param direction one of <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>
929      */

930     private PerspectiveBarManager createBarManager(int direction) {
931         PerspectiveBarManager barManager = new PerspectiveBarManager(style
932                 | direction);
933         barManager.add(new PerspectiveBarNewContributionItem(window));
934
935         // add an item for all open perspectives
936
IWorkbenchPage page = window.getActivePage();
937         if (page != null) {
938             // these are returned with the most recently opened one first
939
IPerspectiveDescriptor[] perspectives = page
940                     .getOpenPerspectives();
941             for (int i = 0; i < perspectives.length; i++) {
942                 barManager.insert(1, new PerspectiveBarContributionItem(
943                         perspectives[i], page));
944             }
945         }
946
947         return barManager;
948     }
949
950
951     private void updateLocationItems(Menu parent, int newLocation) {
952         MenuItem left;
953         MenuItem topLeft;
954         MenuItem topRight;
955
956         topRight = parent.getItem(0);
957         topLeft = parent.getItem(1);
958         left = parent.getItem(2);
959
960         if (newLocation == LEFT) {
961             left.setSelection(true);
962             topRight.setSelection(false);
963             topLeft.setSelection(false);
964         } else if (newLocation == TOP_LEFT) {
965             topLeft.setSelection(true);
966             left.setSelection(false);
967             topRight.setSelection(false);
968         } else {
969             topRight.setSelection(true);
970             left.setSelection(false);
971             topLeft.setSelection(false);
972         }
973     }
974
975     private void addDockOnSubMenu(Menu menu) {
976         MenuItem item = new MenuItem(menu, SWT.CASCADE);
977         item.setText(WorkbenchMessages.PerspectiveSwitcher_dockOn);
978
979         final Menu subMenu = new Menu(item);
980
981         final MenuItem menuItemTopRight = new MenuItem(subMenu, SWT.RADIO);
982         menuItemTopRight.setText(WorkbenchMessages.PerspectiveSwitcher_topRight);
983         
984         window.getWorkbench().getHelpSystem().setHelp(menuItemTopRight,
985                 IWorkbenchHelpContextIds.DOCK_ON_PERSPECTIVE_ACTION);
986
987         final MenuItem menuItemTopLeft = new MenuItem(subMenu, SWT.RADIO);
988         menuItemTopLeft.setText(WorkbenchMessages.PerspectiveSwitcher_topLeft);
989         
990         window.getWorkbench().getHelpSystem().setHelp(menuItemTopLeft,
991                 IWorkbenchHelpContextIds.DOCK_ON_PERSPECTIVE_ACTION);
992
993         final MenuItem menuItemLeft = new MenuItem(subMenu, SWT.RADIO);
994         menuItemLeft.setText(WorkbenchMessages.PerspectiveSwitcher_left);
995         
996         window.getWorkbench().getHelpSystem().setHelp(menuItemLeft,
997                 IWorkbenchHelpContextIds.DOCK_ON_PERSPECTIVE_ACTION);
998
999         SelectionListener listener = new SelectionAdapter() {
1000            public void widgetSelected(SelectionEvent e) {
1001                MenuItem item = (MenuItem) e.widget;
1002                String JavaDoc pref = null;
1003                if (item.equals(menuItemLeft)) {
1004                    updateLocationItems(subMenu, LEFT);
1005                    pref = IWorkbenchPreferenceConstants.LEFT;
1006                } else if (item.equals(menuItemTopLeft)) {
1007                    updateLocationItems(subMenu, TOP_LEFT);
1008                    pref = IWorkbenchPreferenceConstants.TOP_LEFT;
1009                } else {
1010                    updateLocationItems(subMenu, TOP_RIGHT);
1011                    pref = IWorkbenchPreferenceConstants.TOP_RIGHT;
1012                }
1013                IPreferenceStore apiStore = PrefUtil.getAPIPreferenceStore();
1014                if (!pref
1015                        .equals(apiStore
1016                                .getDefaultString(IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR))) {
1017                    PrefUtil.getInternalPreferenceStore().setValue(
1018                            IPreferenceConstants.OVERRIDE_PRESENTATION, true);
1019                }
1020                apiStore.setValue(
1021                        IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR,
1022                        pref);
1023            }
1024        };
1025
1026        menuItemTopRight.addSelectionListener(listener);
1027        menuItemTopLeft.addSelectionListener(listener);
1028        menuItemLeft.addSelectionListener(listener);
1029        item.setMenu(subMenu);
1030        updateLocationItems(subMenu, currentLocation);
1031    }
1032
1033    private void addShowTextItem(Menu menu) {
1034        final MenuItem showtextMenuItem = new MenuItem(menu, SWT.CHECK);
1035        showtextMenuItem.setText(WorkbenchMessages.PerspectiveBar_showText);
1036        window.getWorkbench().getHelpSystem().setHelp(showtextMenuItem,
1037                IWorkbenchHelpContextIds.SHOW_TEXT_PERSPECTIVE_ACTION);
1038
1039        showtextMenuItem.addSelectionListener(new SelectionAdapter() {
1040            public void widgetSelected(SelectionEvent e) {
1041                if (perspectiveBar == null) {
1042                    return;
1043                }
1044
1045                boolean preference = showtextMenuItem.getSelection();
1046                if (preference != PrefUtil
1047                        .getAPIPreferenceStore()
1048                        .getDefaultBoolean(
1049                                IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR)) {
1050                    PrefUtil.getInternalPreferenceStore().setValue(
1051                            IPreferenceConstants.OVERRIDE_PRESENTATION, true);
1052                }
1053                PrefUtil
1054                        .getAPIPreferenceStore()
1055                        .setValue(
1056                                IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR,
1057                                preference);
1058            }
1059        });
1060        showtextMenuItem.setSelection(
1061                PrefUtil
1062                        .getAPIPreferenceStore()
1063                        .getBoolean(
1064                                IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR));
1065    }
1066
1067    private void addCustomizeItem(Menu menu) {
1068        final MenuItem customizeMenuItem = new MenuItem(menu, SWT.Activate);
1069        customizeMenuItem.setText(WorkbenchMessages.PerspectiveBar_customize);
1070        window.getWorkbench().getHelpSystem().setHelp(customizeMenuItem,
1071                IWorkbenchHelpContextIds.EDIT_ACTION_SETS_ACTION);
1072        customizeMenuItem.addSelectionListener(new SelectionAdapter() {
1073            public void widgetSelected(SelectionEvent e) {
1074                if (perspectiveBar == null) {
1075                    return;
1076                }
1077                EditActionSetsAction editAction=new EditActionSetsAction(window);
1078                editAction.setEnabled(true);
1079                editAction.run();
1080            }
1081        });
1082    }
1083    
1084    private void addSaveAsItem(Menu menu) {
1085        final MenuItem saveasMenuItem = new MenuItem(menu, SWT.Activate);
1086        saveasMenuItem.setText(WorkbenchMessages.PerspectiveBar_saveAs);
1087        window.getWorkbench().getHelpSystem().setHelp(saveasMenuItem,
1088                IWorkbenchHelpContextIds.SAVE_PERSPECTIVE_ACTION);
1089        saveasMenuItem.addSelectionListener(new SelectionAdapter() {
1090            public void widgetSelected(SelectionEvent e) {
1091                if (perspectiveBar == null) {
1092                    return;
1093                }
1094                SavePerspectiveAction saveAction=new SavePerspectiveAction(window);
1095                saveAction.setEnabled(true);
1096                saveAction.run();
1097            }
1098        });
1099    }
1100    
1101    private void addResetItem(Menu menu) {
1102        final MenuItem resetMenuItem = new MenuItem(menu, SWT.Activate);
1103        resetMenuItem.setText(WorkbenchMessages.PerspectiveBar_reset);
1104        window.getWorkbench().getHelpSystem().setHelp(resetMenuItem,
1105                IWorkbenchHelpContextIds.RESET_PERSPECTIVE_ACTION);
1106        resetMenuItem.addSelectionListener(new SelectionAdapter() {
1107            public void widgetSelected(SelectionEvent e) {
1108                if (perspectiveBar == null) {
1109                    return;
1110                }
1111                ResetPerspectiveAction resetAction=new ResetPerspectiveAction(window);
1112                resetAction.setEnabled(true);
1113                resetAction.run();
1114             }
1115        });
1116    }
1117    
1118    /**
1119     * Method to save the width of the perspective bar in the
1120     * @param persBarMem
1121     */

1122    public void saveState(IMemento persBarMem) {
1123        // save the width of the perspective bar
1124
IMemento childMem = persBarMem
1125                .createChild(IWorkbenchConstants.TAG_ITEM_SIZE);
1126
1127        int x;
1128        if (currentLocation == TOP_RIGHT && topBar != null) {
1129            x = topBar.getRightWidth();
1130        } else {
1131            x = getDefaultWidth();
1132        }
1133
1134        childMem.putString(IWorkbenchConstants.TAG_X, Integer.toString(x));
1135    }
1136
1137    /**
1138     * Method to restore the width of the perspective bar
1139     * @param memento
1140     */

1141    public void restoreState(IMemento memento) {
1142        if (memento == null) {
1143            return;
1144        }
1145        // restore the width of the perspective bar
1146
IMemento attributes = memento
1147                .getChild(IWorkbenchConstants.TAG_PERSPECTIVE_BAR);
1148        IMemento size = null;
1149        if (attributes != null) {
1150            size = attributes.getChild(IWorkbenchConstants.TAG_ITEM_SIZE);
1151        }
1152        if (size != null && currentLocation == TOP_RIGHT && topBar != null) {
1153            final Integer JavaDoc x = size.getInteger(IWorkbenchConstants.TAG_X);
1154            StartupThreading.runWithoutExceptions(new StartupRunnable() {
1155
1156                public void runWithException() {
1157                    if (x != null) {
1158                        topBar.setRightWidth(x.intValue());
1159                    } else {
1160                        topBar.setRightWidth(getDefaultWidth());
1161                    }
1162                }});
1163        }
1164    }
1165
1166    /**
1167     * Method to rebuild and update the toolbar when necessary
1168     */

1169    void updatePerspectiveBar() {
1170        // Update each item as the text may have to be shortened.
1171
IContributionItem[] items = perspectiveBar.getItems();
1172        for (int i = 0; i < items.length; i++) {
1173            items[i].update();
1174        }
1175        // make sure the selected item is visible
1176
perspectiveBar.arrangeToolbar();
1177        setCoolItemSize(coolItem);
1178        perspectiveBar.getControl().redraw();
1179    }
1180
1181    /**
1182     * Updates the height of the CBanner if the perspective bar
1183     * is docked on the top right
1184     */

1185    public void updateBarParent() {
1186        if (perspectiveBar == null || perspectiveBar.getControl() == null) {
1187            return;
1188        }
1189
1190        // TOP_LEFT and LEFT need only relayout in this case, however TOP_RIGHT
1191
// will need to set the minimum height of the CBanner as it might have changed.
1192
if (currentLocation == TOP_RIGHT && topBar != null) {
1193            // This gets the height of the tallest tool item.
1194
int maxRowHeight = 0;
1195            ToolItem[] toolItems = perspectiveBar.getControl().getItems();
1196            for (int i = 0; i < toolItems.length; i++) {
1197                maxRowHeight = Math.max(maxRowHeight,
1198                        toolItems[i].getBounds().height);
1199            }
1200            // This sets the CBanner's minimum height to support large fonts
1201
// TODO: Actually calculate the correct 'min' size for the right side
1202
topBar.setRightMinimumSize(new Point(MIN_WIDTH, maxRowHeight));
1203        }
1204
1205        LayoutUtil.resize(perspectiveBar.getControl());
1206    }
1207
1208    /**
1209     * Add a listener for reordering of perspectives (usually done through drag
1210     * and drop).
1211     *
1212     * @param listener
1213     */

1214    public void addReorderListener(IReorderListener listener) {
1215        reorderListener = listener;
1216    }
1217
1218    /* (non-Javadoc)
1219     * @see org.eclipse.ui.internal.IWindowTrim#dock(int)
1220     */

1221    public void dock(int dropSide) {
1222    }
1223
1224    /* (non-Javadoc)
1225     * @see org.eclipse.ui.internal.IWindowTrim#getControl()
1226     */

1227    public Control getControl() {
1228        return trimControl;
1229    }
1230
1231    /* (non-Javadoc)
1232     * @see org.eclipse.ui.internal.IWindowTrim#getId()
1233     */

1234    public String JavaDoc getId() {
1235        return "org.eclipse.ui.internal.PerspectiveSwitcher"; //$NON-NLS-1$
1236
}
1237
1238    /* (non-Javadoc)
1239     * @see org.eclipse.ui.internal.IWindowTrim#getDisplayName()
1240     */

1241    public String JavaDoc getDisplayName() {
1242        return WorkbenchMessages.TrimCommon_PerspectiveSwitcher_TrimName;
1243    }
1244
1245    /* (non-Javadoc)
1246     * @see org.eclipse.ui.internal.IWindowTrim#getValidSides()
1247     */

1248    public int getValidSides() {
1249        return SWT.NONE;
1250    }
1251
1252    /* (non-Javadoc)
1253     * @see org.eclipse.ui.internal.IWindowTrim#isCloseable()
1254     */

1255    public boolean isCloseable() {
1256        return false;
1257    }
1258
1259    /* (non-Javadoc)
1260     * @see org.eclipse.ui.internal.IWindowTrim#handleClose()
1261     */

1262    public void handleClose() {
1263        // nothing to do...
1264
}
1265
1266    /* (non-Javadoc)
1267     * @see org.eclipse.ui.IWindowTrim#getWidthHint()
1268     */

1269    public int getWidthHint() {
1270        return SWT.DEFAULT;
1271    }
1272
1273    /* (non-Javadoc)
1274     * @see org.eclipse.ui.IWindowTrim#getHeightHint()
1275     */

1276    public int getHeightHint() {
1277        return SWT.DEFAULT;
1278    }
1279
1280    /* (non-Javadoc)
1281     * @see org.eclipse.ui.IWindowTrim#isResizeable()
1282     */

1283    public boolean isResizeable() {
1284        return false;
1285    }
1286}
1287
Popular Tags