Source code: org/eclipse/ui/internal/WorkbenchWindow.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11
12 package org.eclipse.ui.internal;
13
14 import java.lang.reflect.InvocationTargetException;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.eclipse.core.runtime.IAdaptable;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.MultiStatus;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.jface.action.CoolBarManager;
26 import org.eclipse.jface.action.GroupMarker;
27 import org.eclipse.jface.action.IAction;
28 import org.eclipse.jface.action.IContributionItem;
29 import org.eclipse.jface.action.IContributionManager;
30 import org.eclipse.jface.action.IMenuManager;
31 import org.eclipse.jface.action.MenuManager;
32 import org.eclipse.jface.action.Separator;
33 import org.eclipse.jface.action.StatusLineManager;
34 import org.eclipse.jface.action.ToolBarContributionItem;
35 import org.eclipse.jface.action.ToolBarManager;
36 import org.eclipse.jface.operation.IRunnableWithProgress;
37 import org.eclipse.jface.window.ApplicationWindow;
38 import org.eclipse.jface.window.Window;
39 import org.eclipse.swt.SWT;
40 import org.eclipse.swt.custom.BusyIndicator;
41 import org.eclipse.swt.custom.CBanner;
42 import org.eclipse.swt.events.ControlAdapter;
43 import org.eclipse.swt.events.ControlEvent;
44 import org.eclipse.swt.events.ShellAdapter;
45 import org.eclipse.swt.events.ShellEvent;
46 import org.eclipse.swt.graphics.Point;
47 import org.eclipse.swt.graphics.Rectangle;
48 import org.eclipse.swt.widgets.Composite;
49 import org.eclipse.swt.widgets.Control;
50 import org.eclipse.swt.widgets.CoolBar;
51 import org.eclipse.swt.widgets.Event;
52 import org.eclipse.swt.widgets.Label;
53 import org.eclipse.swt.widgets.Layout;
54 import org.eclipse.swt.widgets.Listener;
55 import org.eclipse.swt.widgets.Menu;
56 import org.eclipse.swt.widgets.Shell;
57 import org.eclipse.ui.IEditorPart;
58 import org.eclipse.ui.IElementFactory;
59 import org.eclipse.ui.IMemento;
60 import org.eclipse.ui.IPageListener;
61 import org.eclipse.ui.IPartService;
62 import org.eclipse.ui.IPersistableElement;
63 import org.eclipse.ui.IPerspectiveDescriptor;
64 import org.eclipse.ui.ISelectionService;
65 import org.eclipse.ui.IViewReference;
66 import org.eclipse.ui.IWorkbench;
67 import org.eclipse.ui.IWorkbenchActionConstants;
68 import org.eclipse.ui.IWorkbenchPage;
69 import org.eclipse.ui.IWorkbenchPart;
70 import org.eclipse.ui.IWorkbenchPartReference;
71 import org.eclipse.ui.IWorkbenchPreferenceConstants;
72 import org.eclipse.ui.IWorkbenchWindow;
73 import org.eclipse.ui.PlatformUI;
74 import org.eclipse.ui.WorkbenchException;
75 import org.eclipse.ui.application.IActionBarConfigurer;
76 import org.eclipse.ui.application.WorkbenchAdvisor;
77 import org.eclipse.ui.commands.ActionHandler;
78 import org.eclipse.ui.commands.HandlerSubmission;
79 import org.eclipse.ui.commands.IHandler;
80 import org.eclipse.ui.commands.IWorkbenchCommandSupport;
81 import org.eclipse.ui.commands.Priority;
82 import org.eclipse.ui.contexts.IWorkbenchContextSupport;
83 import org.eclipse.ui.help.WorkbenchHelp;
84 import org.eclipse.ui.internal.dnd.DragUtil;
85 import org.eclipse.ui.internal.intro.IIntroConstants;
86 import org.eclipse.ui.internal.layout.CacheWrapper;
87 import org.eclipse.ui.internal.layout.LayoutUtil;
88 import org.eclipse.ui.internal.layout.TrimLayout;
89 import org.eclipse.ui.internal.layout.TrimLayoutData;
90 import org.eclipse.ui.internal.misc.Assert;
91 import org.eclipse.ui.internal.misc.Policy;
92 import org.eclipse.ui.internal.misc.UIStats;
93 import org.eclipse.ui.internal.progress.ProgressRegion;
94 import org.eclipse.ui.internal.registry.ActionSetRegistry;
95 import org.eclipse.ui.internal.registry.IActionSet;
96 import org.eclipse.ui.internal.registry.IActionSetDescriptor;
97 import org.eclipse.ui.internal.util.PrefUtil;
98
99 /**
100 * A window within the workbench.
101 */
102 public class WorkbenchWindow extends ApplicationWindow implements IWorkbenchWindow {
103
104 private int number;
105 private PageList pageList = new PageList();
106 private PageListenerList pageListeners = new PageListenerList();
107 private PerspectiveListenerListOld perspectiveListeners = new PerspectiveListenerListOld();
108 private WWinPerspectiveService perspectiveService = new WWinPerspectiveService(this);
109 private WWinPartService partService = new WWinPartService(this);
110 private ActionPresentation actionPresentation;
111 private WWinActionBars actionBars;
112
113 private boolean updateDisabled = true;
114 private boolean closing = false;
115 private boolean shellActivated = false;
116
117 private FastViewBar fastViewBar;
118 private PerspectiveSwitcher perspectiveSwitcher;
119
120 private TrimLayout defaultLayout;
121
122 ProgressRegion progressRegion;
123
124 private Label noOpenPerspective;
125 private Rectangle normalBounds;
126 private boolean asMaximizedState = false;
127
128 private CBanner topBar;
129
130 // Previous shell size. Used to prevent the CBanner from triggering redundant layouts
131 private Point lastShellSize = new Point(0,0);
132
133 /**
134 * The composite under which workbench pages create their controls.
135 *
136 * @since 3.0
137 */
138 private Composite pageComposite;
139
140 /**
141 * Bit flags indication which submenus (New, Show Views, ...) this
142 * window contains. Initially none.
143 *
144 * @since 3.0
145 */
146 private int submenus = 0x00;
147
148 /**
149 * Object for configuring this workbench window. Lazily initialized to
150 * an instance unique to this window.
151 *
152 * @since 3.0
153 */
154 private WorkbenchWindowConfigurer windowConfigurer = null;
155
156 // constants for shortcut bar group ids
157 static final String GRP_PAGES = "pages"; //$NON-NLS-1$
158 static final String GRP_PERSPECTIVES = "perspectives"; //$NON-NLS-1$
159 static final String GRP_FAST_VIEWS = "fastViews"; //$NON-NLS-1$
160
161 // static fields for inner classes.
162 static final int VGAP = 0;
163 static final int CLIENT_INSET = 3;
164 static final int BAR_SIZE = 23;
165
166 /**
167 * Constant (bit mask) indicating which the Show View submenu is
168 * probably present somewhere in this window.
169 *
170 * @see #addSubmenu
171 * @since 3.0
172 */
173 public static final int SHOW_VIEW_SUBMENU = 0x01;
174
175 /**
176 * Constant (bit mask) indicating which the Open Perspective submenu is
177 * probably present somewhere in this window.
178 *
179 * @see #addSubmenu
180 * @since 3.0
181 */
182 public static final int OPEN_PERSPECTIVE_SUBMENU = 0x02;
183
184 /**
185 * Constant (bit mask) indicating which the New Wizard submenu is
186 * probably present somewhere in this window.
187 *
188 * @see #addSubmenu
189 * @since 3.0
190 */
191 public static final int NEW_WIZARD_SUBMENU = 0x04;
192
193 /**
194 * Remembers that this window contains the given submenu.
195 *
196 * @param type the type of submenu, one of:
197 * {@link #NEW_WIZARD_SUBMENU NEW_WIZARD_SUBMENU},
198 * {@link #OPEN_PERSPECTIVE_SUBMENU OPEN_PERSPECTIVE_SUBMENU},
199 * {@link #SHOW_VIEW_SUBMENU SHOW_VIEW_SUBMENU}
200 * @see #containsSubmenu
201 * @since 3.0
202 */
203 public void addSubmenu(int type) {
204 submenus |= type;
205 }
206
207 /**
208 * Checks to see if this window contains the given type of submenu.
209 *
210 * @param type the type of submenu, one of:
211 * {@link #NEW_WIZARD_SUBMENU NEW_WIZARD_SUBMENU},
212 * {@link #OPEN_PERSPECTIVE_SUBMENU OPEN_PERSPECTIVE_SUBMENU},
213 * {@link #SHOW_VIEW_SUBMENU SHOW_VIEW_SUBMENU}
214 * @return <code>true</code> if window contains submenu,
215 * <code>false</code> otherwise
216 * @see #addSubmenu
217 * @since 3.0
218 */
219 public boolean containsSubmenu(int type) {
220 return ((submenus & type) != 0);
221 }
222
223 /**
224 * Constant indicating that all the actions bars should be
225 * filled.
226 *
227 * @since 3.0
228 */
229 private static final int FILL_ALL_ACTION_BARS =
230 WorkbenchAdvisor.FILL_MENU_BAR
231 | WorkbenchAdvisor.FILL_COOL_BAR
232 | WorkbenchAdvisor.FILL_STATUS_LINE;
233
234 /**
235 * Creates and initializes a new workbench window.
236 *
237 * @param number the number for the window
238 */
239 public WorkbenchWindow(int number) {
240 super(null);
241 this.number = number;
242
243 // Make sure there is a workbench. This call will throw
244 // an exception if workbench not created yet.
245 PlatformUI.getWorkbench();
246
247 // Add contribution managers that are exposed to other plugins.
248 addMenuBar();
249 addCoolBar(SWT.FLAT);
250 addStatusLine();
251
252 actionPresentation = new ActionPresentation(this);
253
254 // let the application do further configuration
255 getAdvisor().preWindowOpen(getWindowConfigurer());
256
257 // set the shell style
258 setShellStyle(getWindowConfigurer().getShellStyle());
259
260 // Fill the action bars
261 fillActionBars(getWindowConfigurer().getActionBarConfigurer(), FILL_ALL_ACTION_BARS);
262 }
263
264 /**
265 * Return the style bits for the shortcut bar.
266 * @return int
267 */
268 protected int perspectiveBarStyle() {
269 return SWT.FLAT | SWT.WRAP | SWT.RIGHT | SWT.HORIZONTAL;
270 }
271
272 private TrimDropTarget trimDropTarget;
273 private boolean coolBarVisible = true;
274 private boolean perspectiveBarVisible = true;
275 private boolean statusLineVisible = true;
276
277 /**
278 * The handlers for action set actions that were last submitted to the
279 * workbench command support. This is a map of command identifiers to
280 * <code>ActionHandler</code>. This map is never <code>null</code>,
281 * and is never empty as long as at least one action set has been
282 * registered. The items in this map may not all be submitted, as global
283 * actions take priority.
284 */
285 private Map actionSetHandlersByCommandId = new HashMap();
286
287 /**
288 * The handlers for global actions that were last submitted to the workbench
289 * command support. This is a map of command identifiers to
290 * <code>ActionHandler</code>. This map is never <code>null</code>,
291 * and is never empty as long as at least one global action has been
292 * registered.
293 */
294 private Map globalActionHandlersByCommandId = new HashMap();
295
296 /**
297 * The list of handler submissions submitted to the workbench command
298 * support. This list may be empty, but it is never <code>null</code>.
299 */
300 private List handlerSubmissions = new ArrayList();
301
302 void registerActionSets(IActionSet[] actionSets) {
303 // Remove the old handlers, and dispose them.
304 final Iterator oldHandlerItr = actionSetHandlersByCommandId.values()
305 .iterator();
306 while (oldHandlerItr.hasNext()) {
307 ((IHandler) oldHandlerItr.next()).dispose();
308 }
309 actionSetHandlersByCommandId.clear();
310
311 /*
312 * For each action in each action, create a new action handler. If there
313 * are duplicates, then dispose of the earlier handler before clobbering
314 * it. This avoids memory leaks.
315 */
316 for (int i = 0; i < actionSets.length; i++) {
317 if (actionSets[i] instanceof PluginActionSet) {
318 PluginActionSet pluginActionSet = (PluginActionSet) actionSets[i];
319 IAction[] pluginActions = pluginActionSet.getPluginActions();
320
321 for (int j = 0; j < pluginActions.length; j++) {
322 IAction pluginAction = pluginActions[j];
323 String commandId = pluginAction.getActionDefinitionId();
324
325 if (commandId != null) {
326 final Object value = actionSetHandlersByCommandId
327 .get(commandId);
328 if (value instanceof IHandler) {
329 /*
330 * This handler is about to get clobbered, so
331 * dispose it.
332 */
333 ((IHandler) value).dispose();
334 }
335 actionSetHandlersByCommandId.put(commandId,
336 new ActionHandler(pluginAction));
337
338 }
339 }
340 }
341 }
342
343 /* Submit the new amalgamated list of action set handlers and global
344 * handlers.
345 */
346 submitActionSetAndGlobalHandlers();
347 }
348
349 void registerGlobalAction(IAction globalAction) {
350 String commandId = globalAction.getActionDefinitionId();
351
352 if (commandId != null) {
353 final Object value = globalActionHandlersByCommandId.get(commandId);
354 if (value instanceof ActionHandler) {
355 // This handler is about to get clobbered, so dispose it.
356 final ActionHandler handler = (ActionHandler) value;
357 handler.dispose();
358 }
359
360 globalActionHandlersByCommandId.put(commandId, new ActionHandler(
361 globalAction));
362 }
363
364 submitActionSetAndGlobalHandlers();
365 }
366
367 /**
368 * <p>
369 * Submits the action handlers for action set actions and global actions.
370 * Global actions are given priority, so that if a global action and an
371 * action set action both handle the same command, the global action is
372 * given priority.
373 * </p>
374 * <p>
375 * These submissions are submitted as <code>Priority.LEGACY</code>, which
376 * means that they are the lowest priority. This means that if a higher
377 * priority submission handles the same command under the same conditions,
378 * that that submission will become the handler.
379 * </p>
380 */
381 void submitActionSetAndGlobalHandlers() {
382 /* Mash the action sets and global actions together, with global actions
383 * taking priority.
384 */
385 Map handlersByCommandId = new HashMap();
386 handlersByCommandId.putAll(actionSetHandlersByCommandId);
387 handlersByCommandId.putAll(globalActionHandlersByCommandId);
388
389 // Create a low priority submission for each handler.
390 final List newHandlerSubmissions = new ArrayList();
391 final Shell shell = getShell();
392 if (shell != null) {
393
394 for (Iterator iterator = handlersByCommandId.entrySet().iterator(); iterator
395 .hasNext();) {
396 Map.Entry entry = (Map.Entry) iterator.next();
397 String commandId = (String) entry.getKey();
398 IHandler handler = (IHandler) entry.getValue();
399 newHandlerSubmissions.add(new HandlerSubmission(null, shell,
400 null, commandId, handler, Priority.LEGACY));
401 }
402 }
403
404 // Remove the old submissions, and the add the new ones.
405 final IWorkbenchCommandSupport commandSupport = Workbench.getInstance().getCommandSupport();
406 commandSupport.removeHandlerSubmissions(handlerSubmissions);
407 handlerSubmissions = newHandlerSubmissions;
408 commandSupport.addHandlerSubmissions(newHandlerSubmissions);
409 }
410
411 /*
412 * Adds an listener to the part service.
413 */
414 public void addPageListener(IPageListener l) {
415 pageListeners.addPageListener(l);
416 }
417 /*
418 * Adds an listener to the perspective service.
419 *
420 * NOTE: Internally, please use getPerspectiveService instead.
421 */
422 public void addPerspectiveListener(org.eclipse.ui.IPerspectiveListener l) {
423 perspectiveListeners.addPerspectiveListener(l);
424 }
425
426 /**
427 * add a shortcut for the page.
428 */
429 void addPerspectiveShortcut(IPerspectiveDescriptor perspective, WorkbenchPage workbenchPage) {
430 if (perspectiveSwitcher != null)
431 perspectiveSwitcher.addPerspectiveShortcut(perspective, workbenchPage);
432 }
433
434 /**
435 * Configures this window to have a perspecive bar.
436 * Does nothing if it already has one.
437 */
438 protected void addPerspectiveBar(int style) {
439 Assert.isTrue(perspectiveSwitcher == null);
440 perspectiveSwitcher = new PerspectiveSwitcher(this, topBar, style);
441 }
442
443 /**
444 * Close the window.
445 *
446 * Assumes that busy cursor is active.
447 */
448 private boolean busyClose() {
449 // Whether the window was actually closed or not
450 boolean windowClosed = false;
451
452 // Setup internal flags to indicate window is in
453 // progress of closing and no update should be done.
454 closing = true;
455 updateDisabled = true;
456
457 try {
458 // Only do the check if it is OK to close if we are not closing
459 // via the workbench as the workbench will check this itself.
460 Workbench workbench = getWorkbenchImpl();
461 int count = workbench.getWorkbenchWindowCount();
462 //also check for starting - if the first window dies on startup then we'll need to open a default window.
463 if (!workbench.isStarting() && !workbench.isClosing() && count <= 1) {
464 windowClosed = workbench.close();
465 } else {
466 if (okToClose()) {
467 windowClosed = hardClose();
468 }
469 }
470 } finally {
471 if (!windowClosed) {
472 // Reset the internal flags if window was not closed.
473 closing = false;
474 updateDisabled = false;
475 }
476 }
477
478 return windowClosed;
479 }
480 /**
481 * Opens a new page. Assumes that busy cursor is active.
482 * <p>
483 * <b>Note:</b> Since release 2.0, a window is limited to contain at most
484 * one page. If a page exist in the window when this method is used, then
485 * another window is created for the new page. Callers are strongly
486 * recommended to use the <code>IWorkbench.openPerspective</code> APIs to
487 * programmatically show a perspective.
488 * </p>
489 */
490 protected IWorkbenchPage busyOpenPage(String perspID, IAdaptable input)
491 throws WorkbenchException {
492 IWorkbenchPage newPage = null;
493
494 if (pageList.isEmpty()) {
495 newPage = new WorkbenchPage(this, perspID, input);
496 pageList.add(newPage);
497 firePageOpened(newPage);
498 setActivePage(newPage);
499 } else {
500 IWorkbenchWindow window = getWorkbench().openWorkbenchWindow(perspID, input);
501 newPage = window.getActivePage();
502 }
503
504 return newPage;
505 }
506
507 /**
508 * @see Window
509 */
510 public int open() {
511 getAdvisor().postWindowCreate(getWindowConfigurer());
512 getAdvisor().openIntro(getWindowConfigurer());
513 int result = super.open();
514 getWorkbenchImpl().fireWindowOpened(this);
515 getAdvisor().postWindowOpen(getWindowConfigurer());
516 if (perspectiveSwitcher != null)
517 perspectiveSwitcher.updatePerspectiveBar();
518 return result;
519 }
520
521 /* (non-Javadoc)
522 * Method declared on Window.
523 */
524 protected boolean canHandleShellCloseEvent() {
525 if (!super.canHandleShellCloseEvent()) {
526 return false;
527 }
528 // let the advisor veto the user's explicit request to close the window
529 return getAdvisor().preWindowShellClose(getWindowConfigurer());
530 }
531
532 /**
533 * @see IWorkbenchWindow
534 */
535 public boolean close() {
536 final boolean[] ret = new boolean[1];
537 BusyIndicator.showWhile(null, new Runnable() {
538 public void run() {
539 ret[0] = busyClose();
540 }
541 });
542 return ret[0];
543 }
544
545 protected boolean isClosing() {
546 return closing || getWorkbenchImpl().isClosing();
547 }
548 /**
549 * Return whether or not the coolbar layout is locked.
550 */
551 protected boolean isCoolBarLocked() {
552 return getCoolBarManager().getLockLayout();
553 }
554
555 /**
556 * Close all of the pages.
557 */
558 private void closeAllPages() {
559 // Deactivate active page.
560 setActivePage(null);
561
562 // Clone and deref all so that calls to getPages() returns
563 // empty list (if call by pageClosed event handlers)
564 PageList oldList = pageList;
565 pageList = new PageList();
566
567 // Close all.
568 Iterator enum = oldList.iterator();
569 while (enum.hasNext()) {
570 WorkbenchPage page = (WorkbenchPage) enum.next();
571 firePageClosed(page);
572 page.dispose();
573 }
574 if (!closing)
575 showEmptyWindowMessage();
576 }
577 /**
578 * Save and close all of the pages.
579 */
580 public void closeAllPages(boolean save) {
581 if (save) {
582 boolean ret = saveAllPages(true);
583 if (!ret)
584 return;
585 }
586 closeAllPages();
587 }
588 /**
589 * closePerspective method comment.
590 */
591 protected boolean closePage(IWorkbenchPage in, boolean save) {
592 // Validate the input.
593 if (!pageList.contains(in))
594 return false;
595 WorkbenchPage oldPage = (WorkbenchPage) in;
596
597 // Save old perspective.
598 if (save && oldPage.isSaveNeeded()) {
599 if (!oldPage.saveAllEditors(true))
600 return false;
601 }
602
603 // If old page is activate deactivate.
604 boolean oldIsActive = (oldPage == getActiveWorkbenchPage());
605 if (oldIsActive)
606 setActivePage(null);
607
608 // Close old page.
609 pageList.remove(oldPage);
610 firePageClosed(oldPage);
611 oldPage.dispose();
612
613 // Activate new page.
614 if (oldIsActive) {
615 IWorkbenchPage newPage = pageList.getNextActive();
616 if (newPage != null)
617 setActivePage(newPage);
618 }
619 if (!closing && pageList.isEmpty())
620 showEmptyWindowMessage();
621 return true;
622 }
623 private void showEmptyWindowMessage() {
624 Composite parent = getPageComposite();
625 if (noOpenPerspective == null) {
626 noOpenPerspective = new Label(parent, SWT.NONE);
627 noOpenPerspective.setText(WorkbenchMessages.getString("WorkbenchWindow.noPerspective")); //$NON-NLS-1$
628 noOpenPerspective.setBounds(parent.getClientArea());
629 }
630 }
631
632 /* (non-Javadoc)
633 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
634 */
635 protected void configureShell(Shell shell) {
636 super.configureShell(shell);
637
638 String title = getWindowConfigurer().basicGetTitle();
639 if (title != null) {
640 shell.setText(title);
641 }
642
643 WorkbenchHelp.setHelp(shell, IHelpContextIds.WORKBENCH_WINDOW);
644 getWorkbench().getContextSupport().registerShell(shell,
645 IWorkbenchContextSupport.TYPE_WINDOW);
646
647 trackShellActivation(shell);
648 trackShellResize(shell);
649 }
650
651 /* (non-Javadoc)
652 * @see org.eclipse.jface.window.ApplicationWindow#createTrimWidgets(org.eclipse.swt.widgets.Shell)
653 */
654 protected void createTrimWidgets(Shell shell) {
655 // do nothing -- trim widgets are created in createDefaultContents
656 }
657
658 /**
659 * Creates and remembers the client composite, under which workbench
660 * pages create their controls.
661 *
662 * @since 3.0
663 */
664 protected Composite createPageComposite(Composite parent) {
665 pageComposite = new Composite(parent, SWT.NONE);
666 return pageComposite;
667 }
668
669
670 /**
671 * Creates the contents of the workbench window, including
672 * trim controls and the client composite.
673 * This MUST create the client composite via a call to
674 * <code>createClientComposite</code>.
675 *
676 * @since 3.0
677 */
678 protected Control createContents(Composite parent) {
679 // we know from Window.create that the parent is a Shell.
680 getAdvisor().createWindowContents(getWindowConfigurer(), (Shell) parent);
681 // the page composite must be set by createWindowContents
682 Assert.isNotNull(pageComposite, "createWindowContents must call configurer.createPageComposite"); //$NON-NLS-1$
683 return pageComposite;
684 }
685
686 /**
687 * If the perspective bar is drawn on the top right corner of the window,
688 * then this method changes its appearance from curved to square. This
689 * should have its own preference, but for now it piggy-backs on the
690 * SHOW_TRADITIONAL_STYLE_TABS preference.
691 *
692 * @param square
693 * true for a square banner and false otherwise
694 */
695 public void setBannerCurve(boolean square) {
696 if (topBar != null)
697 topBar.setSimple(square);
698 }
699
700 /**
701 * Creates the default contents and layout of the shell.
702 *
703 * @param shell the shell
704 */
705 protected void createDefaultContents(final Shell shell) {
706 defaultLayout = new TrimLayout();
707 defaultLayout.setSpacing(5, 5, 2, 2);
708 shell.setLayout(defaultLayout);
709
710 Menu menuBar = getMenuBarManager().createMenuBar(shell);
711 if (getWindowConfigurer().getShowMenuBar()) {
712 shell.setMenuBar(menuBar);
713 }
714
715 // Create the CBanner widget which parents both the Coolbar
716 // and the perspective switcher, and supports some configurations
717 // on the left right and bottom
718 topBar = new CBanner(shell, SWT.NONE);
719
720 // the banner gets a curve along with the new tab style
721 // TODO create a dedicated preference for this
722 setBannerCurve(PrefUtil.getAPIPreferenceStore().getBoolean(
723 IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS));
724
725 CacheWrapper coolbarCacheWrapper = new CacheWrapper(topBar);
726
727 final Control coolBar = createCoolBarControl(coolbarCacheWrapper.getControl());
728 // need to resize the shell, not just the coolbar's immediate
729 // parent, if the coolbar wants to grow or shrink
730
731 coolBar.addListener(SWT.Resize, new Listener() {
732 public void handleEvent(Event event) {
733 // If the user is dragging the sash then we will need to force
734 // a resize. However, if the coolbar was resized programatically
735 // then everything is already layed out correctly. There is no
736 // direct way to tell the difference between these cases, however
737 // we take advantage of the fact that dragging the sash does not
738 // change the size of the shell, and only force another layout
739 // if the shell size is unchanged.
740 Rectangle clientArea = shell.getClientArea();
741
742 if (lastShellSize.x == clientArea.width && lastShellSize.y == clientArea.height) {
743 LayoutUtil.resize(coolBar);
744 }
745
746 lastShellSize.x = clientArea.width;
747 lastShellSize.y = clientArea.height;
748 }
749 });
750
751 if (getWindowConfigurer().getShowCoolBar()) {
752 topBar.setLeft(coolbarCacheWrapper.getControl());
753 }
754
755 createStatusLine(shell);
756
757 fastViewBar = new FastViewBar(this);
758 fastViewBar.createControl(shell);
759
760 if (getWindowConfigurer().getShowPerspectiveBar()) {
761 addPerspectiveBar(perspectiveBarStyle());
762 perspectiveSwitcher.createControl(shell);
763 }
764
765 createProgressIndicator(shell);
766
767 trimDropTarget = new TrimDropTarget(shell, this);
768 DragUtil.addDragTarget(shell, trimDropTarget);
769
770 // Create the client composite area (where page content goes).
771 createPageComposite(shell);
772
773 setLayoutDataForContents();
774 }
775
776 public void setPerspectiveBarLocation(String location) {
777 if (perspectiveSwitcher != null)
778 perspectiveSwitcher.setPerspectiveBarLocation(location);
779 }
780
781 /**
782 * Returns the shortcut for a page.
783 */
784 /* protected */
785 IContributionItem findPerspectiveShortcut(
786 IPerspectiveDescriptor perspective,
787 WorkbenchPage page) {
788 return perspectiveSwitcher == null ? null : perspectiveSwitcher
789 .findPerspectiveShortcut(perspective, page);
790 }
791 /**
792 * Fires page activated
793 */
794 private void firePageActivated(IWorkbenchPage page) {
795 pageListeners.firePageActivated(page);
796 partService.pageActivated(page);
797 }
798 /**
799 * Fires page closed
800 */
801 private void firePageClosed(IWorkbenchPage page) {
802 pageListeners.firePageClosed(page);
803 partService.pageClosed(page);
804 }
805 /**
806 * Fires page opened
807 */
808 private void firePageOpened(IWorkbenchPage page) {
809 pageListeners.firePageOpened(page);
810 partService.pageOpened(page);
811 }
812 /**
813 * Fires perspective activated
814 */
815 void firePerspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
816 perspectiveListeners.firePerspectiveActivated(page, perspective);
817 perspectiveService.firePerspectiveActivated(page, perspective);
818 }
819 /**
820 * Fires perspective changed
821 */
822 void firePerspectiveChanged(
823 IWorkbenchPage page,
824 IPerspectiveDescriptor perspective,
825 String changeId) {
826 perspectiveListeners.firePerspectiveChanged(page, perspective, changeId);
827 perspectiveService.firePerspectiveChanged(page, perspective, changeId);
828 }
829 /**
830 * Fires perspective changed for an affected part
831 */
832 void firePerspectiveChanged(
833 IWorkbenchPage page,
834 IPerspectiveDescriptor perspective,
835 IWorkbenchPartReference partRef,
836 String changeId) {
837 perspectiveListeners.firePerspectiveChanged(page, perspective, partRef, changeId);
838 }
839 /**
840 * Fires perspective closed
841 */
842 void firePerspectiveClosed(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
843 perspectiveService.firePerspectiveClosed(page, perspective);
844 }
845 /**
846 * Fires perspective opened
847 */
848 void firePerspectiveOpened(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
849 perspectiveService.firePerspectiveOpened(page, perspective);
850 }
851 /**
852 * Returns the action bars for this window.
853 */
854 public WWinActionBars getActionBars() {
855 if (actionBars == null) {
856 actionBars = new WWinActionBars(this);
857 }
858 return actionBars;
859 }
860
861 /**
862 * Returns the active page.
863 *
864 * @return the active page
865 */
866 public IWorkbenchPage getActivePage() {
867 return pageList.getActive();
868 }
869 /**
870 * Returns the active workbench page.
871 *
872 * @return the active workbench page
873 */
874 /* package */
875 WorkbenchPage getActiveWorkbenchPage() {
876 return pageList.getActive();
877 }
878 /**
879 * Returns the page composite, under which the window's pages create
880 * their controls.
881 */
882 protected Composite getPageComposite() {
883 return pageComposite;
884 }
885 /**
886 * Answer the menu manager for this window.
887 */
888 public MenuManager getMenuManager() {
889 return getMenuBarManager();
890 }
891 /**
892 * Returns the number. This corresponds to a page number in a window or a
893 * window number in the workbench.
894 */
895 public int getNumber() {
896 return number;
897 }
898 /**
899 * Returns an array of the pages in the workbench window.
900 *
901 * @return an array of pages
902 */
903 public IWorkbenchPage[] getPages() {
904 return pageList.getPages();
905 }
906 /**
907 * @see IWorkbenchWindow
908 */
909 public IPartService getPartService() {
910 return partService;
911 }
912
913 /**
914 * Returns the layout for the shell.
915 *
916 * @return the layout for the shell
917 */
918 protected Layout getLayout() {
919 return null;
920 }
921
922 /**
923 * @see IWorkbenchWindow
924 */
925 public IPerspectiveService getPerspectiveService() {
926 return perspectiveService;
927 }
928
929 /**
930 * @see IWorkbenchWindow
931 */
932 public ISelectionService getSelectionService() {
933 return partService.getSelectionService();
934 }
935 /**
936 * Returns <code>true</code> when the window's shell
937 * is activated, <code>false</code> when it's shell is
938 * deactivated
939 *
940 * @return boolean <code>true</code> when shell activated,
941 * <code>false</code> when shell deactivated
942 */
943 public boolean getShellActivated() {
944 return shellActivated;
945 }
946
947 /**
948 * Returns the status line manager for this window (if it has one).
949 *
950 * @return the status line manager, or <code>null</code> if
951 * this window does not have a status line
952 * @see #addStatusLine
953 */
954 public StatusLineManager getStatusLineManager() {
955 return super.getStatusLineManager();
956 }
957
958 /**
959 * @see IWorkbenchWindow
960 */
961 public IWorkbench getWorkbench() {
962 return PlatformUI.getWorkbench();
963 }
964 public String getToolbarLabel(String actionSetId) {
965 ActionSetRegistry registry = WorkbenchPlugin.getDefault().getActionSetRegistry();
966 IActionSetDescriptor actionSet = registry.findActionSet(actionSetId);
967 if (actionSet != null) {
968 return actionSet.getLabel();
969 } else {
970 if (IWorkbenchActionConstants.TOOLBAR_FILE.equalsIgnoreCase(actionSetId))
971 return WorkbenchMessages.getString("WorkbenchWindow.FileToolbar"); //$NON-NLS-1$
972 if (IWorkbenchActionConstants.TOOLBAR_NAVIGATE.equalsIgnoreCase(actionSetId))
973 return WorkbenchMessages.getString("WorkbenchWindow.NavigateToolbar"); //$NON-NLS-1$
974 }
975 return null;
976 }
977 /**
978 * Unconditionally close this window. Assumes the proper
979 * flags have been set correctly (e.i. closing and updateDisabled)
980 */
981 private boolean hardClose() {
982 boolean result;
983 try {
984 // Clear the action sets, fix for bug 27416.
985 actionPresentation.clearActionSets();
986
987 // Remove the handler submissions. Bug 64024.
988 final IWorkbench workbench = getWorkbench();
989 final IWorkbenchCommandSupport commandSupport = workbench
990 .getCommandSupport();
991 commandSupport.removeHandlerSubmissions(handlerSubmissions);
992 final Iterator submissionItr = handlerSubmissions.iterator();
993 while (submissionItr.hasNext()) {
994 final HandlerSubmission submission = (HandlerSubmission) submissionItr
995 .next();
996 submission.getHandler().dispose();
997 }
998 handlerSubmissions.clear();
999 actionSetHandlersByCommandId.clear();
1000 globalActionHandlersByCommandId.clear();
1001
1002 // Remove the enabled submissions. Bug 64024.
1003 final IWorkbenchContextSupport contextSupport = workbench
1004 .getContextSupport();
1005 contextSupport.unregisterShell(getShell());
1006
1007 closeAllPages();
1008 // let the application do further deconfiguration
1009 getAdvisor().postWindowClose(getWindowConfigurer());
1010 getWorkbenchImpl().fireWindowClosed(this);
1011
1012 // Null out the progress region. Bug 64024.
1013 progressRegion = null;
1014 } finally {
1015 result = super.close();
1016 }
1017 return result;
1018 }
1019 /**
1020 * @see IWorkbenchWindow
1021 */
1022 public boolean isApplicationMenu(String menuID) {
1023 // delegate this question to the workbench advisor
1024 return getAdvisor().isApplicationMenu(getWindowConfigurer(), menuID);
1025 }
1026
1027 /**
1028 * Return whether or not the given id matches the id of the coolitems that
1029 * the application creates.
1030 */
1031 /* package */
1032 boolean isWorkbenchCoolItemId(String id) {
1033 return windowConfigurer.containsCoolItem(id);
1034 }
1035 /**
1036 * Locks/unlocks the CoolBar for the workbench.
1037 *
1038 * @param lock whether the CoolBar should be locked or unlocked
1039 */
1040 /* package */
1041 void lockCoolBar(boolean lock) {
1042 getCoolBarManager().setLockLayout(lock);
1043 }
1044 /**
1045 * Called when this window is about to be closed.
1046 *
1047 * Subclasses may overide to add code that returns <code>false</code>
1048 * to prevent closing under certain conditions.
1049 */
1050 public boolean okToClose() {
1051 // Save all of the editors.
1052 if (!getWorkbenchImpl().isClosing())
1053 if (!saveAllPages(true))
1054 return false;
1055 return true;
1056 }
1057 /**
1058 * Opens a new page.
1059 * <p>
1060 * <b>Note:</b> Since release 2.0, a window is limited to contain at most
1061 * one page. If a page exist in the window when this method is used, then
1062 * another window is created for the new page. Callers are strongly
1063 * recommended to use the <code>IWorkbench.openPerspective</code> APIs to
1064 * programmatically show a perspective.
1065 * </p>
1066 */
1067 public IWorkbenchPage openPage(final String perspId, final IAdaptable input)
1068 throws WorkbenchException {
1069 Assert.isNotNull(perspId);
1070
1071 // Run op in busy cursor.
1072 final Object[] result = new Object[1];
1073 BusyIndicator.showWhile(null, new Runnable() {
1074 public void run() {
1075 try {
1076 result[0] = busyOpenPage(perspId, input);
1077 } catch (WorkbenchException e) {
1078 result[0] = e;
1079 }
1080 }
1081 });
1082
1083 if (result[0] instanceof IWorkbenchPage)
1084 return (IWorkbenchPage) result[0];
1085 else if (result[0] instanceof WorkbenchException)
1086 throw (WorkbenchException) result[0];
1087 else
1088 throw new WorkbenchException(WorkbenchMessages.getString("WorkbenchWindow.exceptionMessage")); //$NON-NLS-1$
1089 }
1090 /**
1091 * Opens a new page.
1092 * <p>
1093 * <b>Note:</b> Since release 2.0, a window is limited to contain at most
1094 * one page. If a page exist in the window when this method is used, then
1095 * another window is created for the new page. Callers are strongly
1096 * recommended to use the <code>IWorkbench.openPerspective</code> APIs to
1097 * programmatically show a perspective.
1098 * </p>
1099 */
1100 public IWorkbenchPage openPage(IAdaptable input) throws WorkbenchException {
1101 String perspId = getWorkbenchImpl().getPerspectiveRegistry().getDefaultPerspective();
1102 return openPage(perspId, input);
1103 }
1104
1105 /*
1106 * Removes an listener from the part service.
1107 */
1108 public void removePageListener(IPageListener l) {
1109 pageListeners.removePageListener(l);
1110 }
1111 /*
1112 * Removes an listener from the perspective service.
1113 *
1114 * NOTE: Internally, please use getPerspectiveService instead.
1115 */
1116 public void removePerspectiveListener(org.eclipse.ui.IPerspectiveListener l) {
1117 perspectiveListeners.removePerspectiveListener(l);
1118 }
1119 /**
1120 * Remove the shortcut for a page.
1121 */
1122 /* package */
1123 void removePerspectiveShortcut(IPerspectiveDescriptor perspective, WorkbenchPage page) {
1124 if (perspectiveSwitcher != null)
1125 perspectiveSwitcher.removePerspectiveShortcut(perspective, page);
1126 }
1127 private IStatus unableToRestorePage(IMemento pageMem) {
1128 String pageName = pageMem.getString(IWorkbenchConstants.TAG_LABEL);
1129 if (pageName == null)
1130 pageName = ""; //$NON-NLS-1$
1131 return new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, WorkbenchMessages.format("WorkbenchWindow.unableToRestorePerspective", new String[] { pageName }), //$NON-NLS-1$
1132 null);
1133 }
1134 /**
1135 * @see IPersistable.
1136 */
1137 public IStatus restoreState(IMemento memento, IPerspectiveDescriptor activeDescriptor) {
1138 Assert.isNotNull(getShell());
1139
1140 MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.getString("WorkbenchWindow.problemsRestoringWindow"), null); //$NON-NLS-1$
1141
1142 // Read window's bounds and state.
1143 Rectangle displayBounds = getShell().getDisplay().getBounds();
1144 Rectangle shellBounds = new Rectangle(0, 0, 0, 0);
1145
1146 IMemento fastViewMem = memento.getChild(IWorkbenchConstants.TAG_FAST_VIEW_DATA);
1147 if (fastViewMem != null) {
1148 if (fastViewBar != null) {
1149 fastViewBar.restoreState(fastViewMem);
1150 }
1151 }
1152 Integer bigInt = memento.getInteger(IWorkbenchConstants.TAG_X);
1153 shellBounds.x = bigInt == null ? 0 : bigInt.intValue();
1154 bigInt = memento.getInteger(IWorkbenchConstants.TAG_Y);
1155 shellBounds.y = bigInt == null ? 0 : bigInt.intValue();
1156 bigInt = memento.getInteger(IWorkbenchConstants.TAG_WIDTH);
1157 shellBounds.width = bigInt == null ? 0 : bigInt.intValue();
1158 bigInt = memento.getInteger(IWorkbenchConstants.TAG_HEIGHT);
1159 shellBounds.height = bigInt == null ? 0 : bigInt.intValue();
1160 if (!shellBounds.isEmpty()) {
1161 if (!shellBounds.intersects(displayBounds)) {
1162 Rectangle clientArea = getShell().getDisplay().getClientArea();
1163 shellBounds.x = clientArea.x;
1164 shellBounds.y = clientArea.y;
1165 }
1166 getShell().setBounds(shellBounds);
1167 }
1168 if ("true".equals(memento.getString(IWorkbenchConstants.TAG_MAXIMIZED))) { //$NON-NLS-1$
1169 getShell().setMaximized(true);
1170 }
1171 if ("true".equals(memento.getString(IWorkbenchConstants.TAG_MINIMIZED))) { //$NON-NLS-1$
1172 // getShell().setMinimized(true);
1173 }
1174
1175 // restore the width of the perspective bar
1176 if (perspectiveSwitcher != null)
1177 perspectiveSwitcher.restoreState(memento);
1178
1179 // Restore the cool bar order by creating all the tool bar contribution items
1180 // This needs to be done before pages are created to ensure proper canonical creation
1181 // of cool items
1182 if (getCoolBarManager() != null) {
1183 CoolBarManager coolBarMgr = getCoolBarManager();
1184 IMemento coolBarMem = memento.getChild(IWorkbenchConstants.TAG_COOLBAR_LAYOUT);
1185 if (coolBarMem != null) {
1186 // Check if the layout is locked
1187 Integer lockedInt = coolBarMem.getInteger(IWorkbenchConstants.TAG_LOCKED);
1188 if ((lockedInt != null) && (lockedInt.intValue() == 1)) {
1189 coolBarMgr.setLockLayout(true);
1190 }else {
1191 coolBarMgr.setLockLayout(false);
1192 }
1193 // The new layout of the cool bar manager
1194 ArrayList coolBarLayout = new ArrayList();
1195 // Traverse through all the cool item in the memento
1196 IMemento contributionMems[] =
1197 coolBarMem.getChildren(IWorkbenchConstants.TAG_COOLITEM);
1198 for (int i = 0; i < contributionMems.length; i++) {
1199 IMemento contributionMem = contributionMems[i];
1200 String type = contributionMem.getString(IWorkbenchConstants.TAG_ITEM_TYPE);
1201 if (type == null) {
1202 // Do not recognize that type
1203 continue;
1204 }
1205 String id = contributionMem.getString(IWorkbenchConstants.TAG_ID);
1206
1207 // Prevent duplicate items from being read back in.
1208 IContributionItem existingItem = coolBarMgr.find(id);
1209 if ((id != null) && (existingItem != null)) {
1210 if (Policy.DEBUG_TOOLBAR_DISPOSAL) {
1211 System.out.println("Not loading duplicate cool bar item: " + id); //$NON-NLS-1$
1212 }
1213 coolBarLayout.add(existingItem);
1214 continue;
1215 }
1216 IContributionItem newItem = null;
1217 if (type.equals(IWorkbenchConstants.TAG_TYPE_SEPARATOR)) {
1218 if (id != null) {
1219 newItem = new Separator(id);
1220 } else {
1221 newItem = new Separator();
1222 }
1223 } else if (id != null) {
1224 if (type.equals(IWorkbenchConstants.TAG_TYPE_GROUPMARKER)) {
1225 newItem = new GroupMarker(id);
1226
1227 } else if (type.equals(IWorkbenchConstants.TAG_TYPE_TOOLBARCONTRIBUTION)
1228 || type.equals(IWorkbenchConstants.TAG_TYPE_PLACEHOLDER)) {
1229
1230 // Get Width and height
1231 Integer width = contributionMem.getInteger(IWorkbenchConstants.TAG_ITEM_X);
1232 Integer height = contributionMem.getInteger(IWorkbenchConstants.TAG_ITEM_Y);
1233 // Look for the object in the current cool bar manager
1234 IContributionItem oldItem = coolBarMgr.find(id);
1235 // If a tool bar contribution item already exists for this id then use the old object
1236 if (oldItem != null) {
1237 newItem = oldItem;
1238 } else {
1239 newItem =
1240 new ToolBarContributionItem(
1241 new ToolBarManager(coolBarMgr.getStyle()),
1242 id);
1243 if (type.equals(IWorkbenchConstants.TAG_TYPE_PLACEHOLDER)) {
1244 ToolBarContributionItem newToolBarItem = (ToolBarContributionItem) newItem;
1245 if (height != null) {
1246 newToolBarItem.setCurrentHeight(height.intValue());
1247 }
1248 if (width != null) {
1249 newToolBarItem.setCurrentWidth(width.intValue());
1250 }
1251 newItem = new PlaceholderContributionItem(newToolBarItem);
1252 }
1253 // make it invisible by default
1254 newItem.setVisible(false);
1255 // Need to add the item to the cool bar manager so that its canonical order can be preserved
1256 IContributionItem refItem =
1257 findAlphabeticalOrder(
1258 IWorkbenchActionConstants.MB_ADDITIONS,
1259 id,
1260 coolBarMgr);
1261 if (refItem != null) {
1262 coolBarMgr.insertAfter(refItem.getId(), newItem);
1263 }else {
1264 coolBarMgr.add(newItem);
1265 }
1266 }
1267 // Set the current height and width
1268 if ((width != null) && (newItem instanceof ToolBarContributionItem)) {
1269 ((ToolBarContributionItem) newItem).setCurrentWidth(width.intValue());
1270 }
1271 if ((height != null) && (newItem instanceof ToolBarContributionItem)) {
1272 ((ToolBarContributionItem) newItem).setCurrentHeight(height.intValue());
1273 }
1274 }
1275 }
1276 // Add new item into cool bar manager
1277 if (newItem != null) {
1278 coolBarLayout.add(newItem);
1279 newItem.setParent(coolBarMgr);
1280 coolBarMgr.markDirty();
1281 }
1282 }
1283
1284 // We need to check if we have everything we need in the layout.
1285 final ArrayList finalLayout = new ArrayList();
1286 IContributionItem[] existingItems = coolBarMgr.getItems();
1287 for (int i = 0; i < existingItems.length; i++) {
1288 IContributionItem existingItem = existingItems[i];
1289
1290 /* This line shouldn't be necessary, but is here for
1291 * robustness.
1292 */
1293 if (existingItem == null) {
1294 continue;
1295 }
1296
1297 boolean found = false;
1298 Iterator layoutItemItr = coolBarLayout.iterator();
1299 while (layoutItemItr.hasNext()) {
1300 IContributionItem layoutItem = (IContributionItem) layoutItemItr.next();
1301 if ((layoutItem != null) && (layoutItem.equals(existingItem))) {
1302 found = true;
1303 break;
1304 }
1305 }
1306
1307 if (!found) {
1308 if (existingItem != null) {
1309 finalLayout.add(existingItem);
1310 }
1311 }
1312 }
1313
1314 // Set the cool bar layout to the given layout.
1315 finalLayout.addAll(coolBarLayout);
1316 IContributionItem[] itemsToSet = new IContributionItem[finalLayout.size()];
1317 finalLayout.toArray(itemsToSet);
1318 coolBarMgr.setItems(itemsToSet);
1319 } else {
1320 // For older workbenchs
1321 coolBarMem = memento.getChild(IWorkbenchConstants.TAG_TOOLBAR_LAYOUT);
1322 if (coolBarMem != null) {
1323 // Restore an older layout
1324 restoreOldCoolBar(coolBarMem);
1325 }
1326 }
1327 }
1328
1329 // Recreate each page in the window.
1330 IWorkbenchPage newActivePage = null;
1331 IMemento[] pageArray = memento.getChildren(IWorkbenchConstants.TAG_PAGE);
1332 for (int i = 0; i < pageArray.length; i++) {
1333 IMemento pageMem = pageArray[i];
1334 String strFocus = pageMem.getString(IWorkbenchConstants.TAG_FOCUS);
1335 if (strFocus == null || strFocus.length() == 0)
1336 continue;
1337
1338 // Get the input factory.
1339 IAdaptable input = null;
1340 IMemento inputMem = pageMem.getChild(IWorkbenchConstants.TAG_INPUT);
1341 if (inputMem != null) {
1342 String factoryID = inputMem.getString(IWorkbenchConstants.TAG_FACTORY_ID);
1343 if (factoryID == null) {
1344 WorkbenchPlugin.log("Unable to restore page - no input factory ID."); //$NON-NLS-1$
1345 result.add(unableToRestorePage(pageMem));
1346 continue;
1347 }
1348 try {
1349 UIStats.start(UIStats.RESTORE_WORKBENCH, "WorkbenchPageFactory"); //$NON-NLS-1$
1350 IElementFactory factory = PlatformUI.getWorkbench().getElementFactory(factoryID);
1351 if (factory == null) {
1352 WorkbenchPlugin.log("Unable to restore page - cannot instantiate input factory: " + factoryID); //$NON-NLS-1$
1353 result.add(unableToRestorePage(pageMem));
1354 continue;
1355 }
1356
1357 // Get the input element.
1358 input = factory.createElement(inputMem);
1359 if (input == null) {
1360 WorkbenchPlugin.log("Unable to restore page - cannot instantiate input element: " + factoryID); //$NON-NLS-1$
1361 result.add(unableToRestorePage(pageMem));
1362 continue;
1363 }
1364 } finally {
1365 UIStats.end(UIStats.RESTORE_WORKBENCH, "WorkbenchPageFactory"); //$NON-NLS-1$
1366 }
1367 }
1368 // Open the perspective.
1369 WorkbenchPage newPage = null;
1370 try {
1371 newPage = new WorkbenchPage(this, input);
1372 result.add(newPage.restoreState(pageMem, activeDescriptor));
1373 pageList.add(newPage);
1374 firePageOpened(newPage);
1375 } catch (WorkbenchException e) {
1376 WorkbenchPlugin.log("Unable to restore perspective - constructor failed."); //$NON-NLS-1$
1377 result.add(e.getStatus());
1378 continue;
1379 }
1380
1381 if (strFocus != null && strFocus.length() > 0)
1382 newActivePage = newPage;
1383 }
1384
1385 // If there are no pages create a default.
1386 if (pageList.isEmpty()) {
1387 try {
1388 String defPerspID =
1389 getWorkbenchImpl().getPerspectiveRegistry().getDefaultPerspective();
1390 WorkbenchPage newPage =
1391 new WorkbenchPage(this, defPerspID, getAdvisor().getDefaultPageInput());
1392 pageList.add(newPage);
1393 firePageOpened(newPage);
1394 } catch (WorkbenchException e) {
1395 WorkbenchPlugin.log("Unable to create default perspective - constructor failed."); //$NON-NLS-1$
1396 result.add(e.getStatus());
1397 String productName = WorkbenchPlugin.getDefault().getProductName();
1398 if (productName == null) {
1399 productName = ""; //$NON-NLS-1$
1400 }
1401 getShell().setText(productName);
1402 }
1403 }
1404
1405 // Set active page.
1406 if (newActivePage == null)
1407 newActivePage = pageList.getNextActive();
1408
1409 setActivePage(newActivePage);
1410
1411 IMemento introMem = memento.getChild(IWorkbenchConstants.TAG_INTRO);
1412 if (introMem != null) {
1413 getWorkbench().getIntroManager().showIntro(this, Boolean.valueOf(introMem.getString(IWorkbenchConstants.TAG_STANDBY)).booleanValue());
1414 }
1415 return result;
1416 }
1417
1418 /**
1419 * Restores cool item order from an old workbench.
1420 */
1421 private boolean restoreOldCoolBar(IMemento coolbarMem) {
1422 // Make sure the tag exist
1423 if (coolbarMem == null) {
1424 return false;
1425 }
1426 CoolBarManager coolBarMgr = getCoolBarManager();
1427 // Check to see if layout is locked
1428 Integer locked = coolbarMem.getInteger(IWorkbenchConstants.TAG_LOCKED);
1429 boolean state = (locked != null) && (locked.intValue() == 1);
1430 coolBarMgr.setLockLayout(state);
1431
1432 // Get the visual layout
1433 IMemento visibleLayout = coolbarMem.getChild(IWorkbenchConstants.TAG_TOOLBAR_LAYOUT);
1434 ArrayList visibleWrapIndicies = new ArrayList();
1435 ArrayList visibleItems = new ArrayList();
1436 if (visibleLayout != null) {
1437 if (readLayout(visibleLayout,visibleItems,visibleWrapIndicies) == false ) {
1438 return false;
1439 }
1440 }
1441 // Get the remembered layout
1442 IMemento rememberedLayout = coolbarMem.getChild(IWorkbenchConstants.TAG_LAYOUT);
1443 ArrayList rememberedWrapIndicies = new ArrayList();
1444 ArrayList rememberedItems = new ArrayList();
1445 if (rememberedLayout != null) {
1446 if (readLayout(rememberedLayout,rememberedItems,rememberedWrapIndicies) == false ) {
1447 return false;
1448 }
1449 }
1450
1451 // Create the objects
1452 if (visibleItems != null) {
1453 // Merge remembered layout into visible layout
1454 if (rememberedItems != null) {
1455 // Traverse through all the remembered items
1456 int currentIndex = 0;
1457 for (Iterator i = rememberedItems.iterator(); i.hasNext();currentIndex++) {
1458 String id = (String)i.next();
1459 int index = -1;
1460 for(Iterator iter=visibleItems.iterator();iter.hasNext();) {
1461 String visibleId = (String)iter.next();
1462 if (visibleId.equals(id)) {
1463 index = visibleItems.indexOf(visibleId);
1464 break;
1465 }
1466 }
1467 // The item is not in the visible list
1468 if (index == -1) {
1469 int insertAt = Math.max(0,Math.min(currentIndex,visibleItems.size()));
1470 boolean separateLine = false;
1471 // Check whether this item is on a separate line
1472 for(Iterator iter=rememberedWrapIndicies.iterator();iter.hasNext();) {
1473 Integer wrapIndex = (Integer)iter.next();
1474 if (wrapIndex.intValue() <= insertAt) {
1475 insertAt = visibleItems.size();
1476 // Add new wrap index for this Item
1477 visibleWrapIndicies.add(new Integer(insertAt));
1478 separateLine = true;
1479 }
1480 }
1481 // Add item to array list
1482 visibleItems.add(insertAt,id);
1483 // If the item was not on a separate line then adjust the visible wrap indicies
1484 if (!separateLine) {
1485 // Adjust visible wrap indicies
1486 for(int j=0; j < visibleWrapIndicies.size();j++) {
1487 Integer index2 = (Integer)visibleWrapIndicies.get(j);
1488 if (index2.intValue() >= insertAt) {
1489 visibleWrapIndicies.set(j, new Integer(index2.intValue() + 1));
1490 }
1491 }
1492 }
1493 }
1494 }
1495 }
1496 // The new layout of the cool bar manager
1497 ArrayList coolBarLayout = new ArrayList(visibleItems.size());
1498 // Add all visible items to the layout object
1499 for (Iterator i = visibleItems.iterator(); i.hasNext();) {
1500 String id = (String)i.next();
1501 // Look for the object in the current cool bar manager
1502 IContributionItem oldItem = null;
1503 IContributionItem newItem = null;
1504 if (id != null) {
1505 oldItem = coolBarMgr.find(id);
1506 }
1507 // If a tool bar contribution item already exists for this id then use the old object
1508 if (oldItem instanceof ToolBarContributionItem) {
1509 newItem = (ToolBarContributionItem) oldItem;
1510 } else {
1511 newItem =
1512 new ToolBarContributionItem(
1513 new ToolBarManager(coolBarMgr.getStyle()),
1514 id);
1515 // make it invisible by default
1516 newItem.setVisible(false);
1517 // Need to add the item to the cool bar manager so that its canonical order can be preserved
1518 IContributionItem refItem =
1519 findAlphabeticalOrder(
1520 IWorkbenchActionConstants.MB_ADDITIONS,
1521 id,
1522 coolBarMgr);
1523 if (refItem != null) {
1524 coolBarMgr.insertAfter(refItem.getId(), newItem);
1525 }else {
1526 coolBarMgr.add(newItem);
1527 }
1528 }
1529 // Add new item into cool bar manager
1530 if (newItem != null) {
1531 coolBarLayout.add(newItem);
1532 newItem.setParent(coolBarMgr);
1533 coolBarMgr.markDirty();
1534 }
1535 }
1536
1537 // Add separators to the displayed Items data structure
1538 int offset = 0;
1539 for(int i=1; i < visibleWrapIndicies.size(); i++) {
1540 int insertAt = ((Integer)visibleWrapIndicies.get(i)).intValue() + offset;
1541 coolBarLayout.add(insertAt,new Separator(CoolBarManager.USER_SEPARATOR));
1542 offset++;
1543 }
1544
1545 // Add any group markers in their appropriate places
1546 IContributionItem[] items = coolBarMgr.getItems();
1547 for (int i=0; i < items.length; i++) {
1548 IContributionItem item = items[i];
1549 if (item.isGroupMarker()) {
1550 coolBarLayout.add(Math.max(Math.min(i,coolBarLayout.size()), 0),item);
1551 }
1552 }
1553 IContributionItem[] itemsToSet = new IContributionItem[coolBarLayout.size()];
1554 coolBarLayout.toArray(itemsToSet);
1555 coolBarMgr.setItems(itemsToSet);
1556 }
1557 return true;
1558 }
1559
1560 /**
1561 * Helper method used for restoring an old cool bar layout. This method reads the memento
1562 * and populatates the item id's and wrap indicies.
1563 */
1564 private boolean readLayout(IMemento memento, ArrayList itemIds, ArrayList wrapIndicies) {
1565 // Get the Wrap indicies
1566 IMemento [] wraps = memento.getChildren(IWorkbenchConstants.TAG_ITEM_WRAP_INDEX);
1567 if (wraps == null) return false;
1568 for (int i = 0; i < wraps.length; i++) {
1569 IMemento wrapMem = wraps[i];
1570 Integer index = wrapMem.getInteger(IWorkbenchConstants.TAG_INDEX);
1571 if (index == null) return false;
1572 wrapIndicies.add(index);
1573 }
1574 // Get the Item ids
1575 IMemento [] savedItems = memento.getChildren(IWorkbenchConstants.TAG_ITEM);
1576 if (savedItems == null) return false;
1577 for (int i = 0; i < savedItems.length; i++) {
1578 IMemento savedMem = savedItems[i];
1579 String id = savedMem.getString(IWorkbenchConstants.TAG_ID);
1580 if (id == null) return false;
1581 itemIds.add(id);
1582 }
1583 return true;
1584 }
1585
1586 /**
1587 * Returns the contribution item that the given contribution item should be inserted after.
1588 *
1589 * @param startId the location to start looking alphabetically.
1590 * @param itemId the target item id.
1591 * @param mgr the contribution manager.
1592 * @return the contribution item that the given items should be returned after.
1593 */
1594 private IContributionItem findAlphabeticalOrder(
1595 String startId,
1596 String itemId,
1597 IContributionManager mgr) {
1598 IContributionItem[] items = mgr.getItems();
1599 int insertIndex = 0;
1600
1601 // look for starting point
1602 while (insertIndex < items.length) {
1603 IContributionItem item = items[insertIndex];
1604 if (item.getId() != null && item.getId().equals(startId))
1605 break;
1606 ++insertIndex;
1607 }
1608
1609 // Find the index that this item should be inserted in
1610 for (int i = insertIndex + 1; i < items.length; i++) {
1611 IContributionItem item = items[i];
1612 String testId = item.getId();
1613
1614 if (item.isGroupMarker())
1615 break;
1616
1617 if (itemId != null && testId != null) {
1618 if (itemId.compareTo(testId) < 1)
1619 break;
1620 }
1621 insertIndex = i;
1622 }
1623 if ( insertIndex >= items.length) {
1624 return null;
1625 }
1626 return items[insertIndex];
1627 }
1628
1629 /* (non-Javadoc)
1630 * Method declared on IRunnableContext.
1631 */
1632 public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
1633 throws InvocationTargetException, InterruptedException {
1634 IWorkbenchContextSupport contextSupport = getWorkbench().getContextSupport();
1635 final boolean keyFilterEnabled = contextSupport.isKeyFilterEnabled();
1636
1637 Control fastViewBarControl = getFastViewBar() == null ? null : getFastViewBar().getControl();
1638 boolean fastViewBarWasEnabled = fastViewBarControl == null ? false : fastViewBarControl.getEnabled();
1639
1640 Control perspectiveBarControl = getPerspectiveBar() == null ? null : getPerspectiveBar().getControl();
1641 boolean perspectiveBarWasEnabled = perspectiveBarControl == null ? false : perspectiveBarControl.getEnabled();
1642
1643 try {
1644 if (fastViewBarControl != null && !fastViewBarControl.isDisposed())
1645 fastViewBarControl.setEnabled(false);
1646
1647 if (perspectiveBarControl != null && !perspectiveBarControl.isDisposed())
1648 perspectiveBarControl.setEnabled(false);
1649
1650 if (keyFilterEnabled)
1651 contextSupport.setKeyFilterEnabled(false);
1652
1653 super.run(fork, cancelable, runnable);
1654 } finally {
1655 if (fastViewBarControl != null && !fastViewBarControl.isDisposed())
1656 fastViewBarControl.setEnabled(fastViewBarWasEnabled);
1657
1658 if (perspectiveBarControl != null && !perspectiveBarControl.isDisposed())
1659 perspectiveBarControl.setEnabled(perspectiveBarWasEnabled);
1660
1661 if (keyFilterEnabled)
1662 contextSupport.setKeyFilterEnabled(true);
1663 }
1664 }
1665 /**
1666 * Save all of the pages. Returns true if the operation succeeded.
1667 */
1668 private boolean saveAllPages(boolean bConfirm) {
1669 boolean bRet = true;
1670 Iterator enum = pageList.iterator();
1671 while (bRet && enum.hasNext()) {
1672 WorkbenchPage page = (WorkbenchPage) enum.next();
1673 bRet = page.saveAllEditors(bConfirm);
1674 }
1675 return bRet;
1676 }
1677 /**
1678 * @see IPersistable
1679 */
1680 public IStatus saveState(IMemento memento) {
1681
1682 MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.getString("WorkbenchWindow.problemsSavingWindow"), null); //$NON-NLS-1$
1683
1684 // Save the window's state and bounds.
1685 if (getShell().getMaximized() || asMaximizedState) {
1686 memento.putString(IWorkbenchConstants.TAG_MAXIMIZED, "true"); //$NON-NLS-1$
1687 }
1688 if (getShell().getMinimized()) {
1689 memento.putString(IWorkbenchConstants.TAG_MINIMIZED, "true"); //$NON-NLS-1$
1690 }
1691 if (normalBounds == null) {
1692 normalBounds = getShell().getBounds();
1693 }
1694 IMemento fastViewBarMem = memento.createChild(IWorkbenchConstants.TAG_FAST_VIEW_DATA);
1695 if (fastViewBar != null) {
1696 fastViewBar.saveState(fastViewBarMem);
1697 }
1698
1699 memento.putInteger(IWorkbenchConstants.TAG_X, normalBounds.x);
1700 memento.putInteger(IWorkbenchConstants.TAG_Y, normalBounds.y);
1701 memento.putInteger(IWorkbenchConstants.TAG_WIDTH, normalBounds.width);
1702 memento.putInteger(IWorkbenchConstants.TAG_HEIGHT, normalBounds.height);
1703
1704 IWorkbenchPage activePage = getActivePage();
1705 if (activePage != null && activePage.findView(IIntroConstants.INTRO_VIEW_ID) != null) {
1706 IMemento introMem = memento.createChild(IWorkbenchConstants.TAG_INTRO);
1707 introMem.putString(
1708 IWorkbenchConstants.TAG_STANDBY,
1709 Boolean.valueOf(
1710 getWorkbench()
1711 .getIntroManager()
1712 .isIntroStandby(
1713 getWorkbench()
1714 .getIntroManager()
1715 .getIntro())).toString());
1716 }
1717
1718 // save the width of the perspective bar
1719 IMemento persBarMem = memento.createChild(IWorkbenchConstants.TAG_PERSPECTIVE_BAR);
1720 if (perspectiveSwitcher != null) {
1721 perspectiveSwitcher.saveState(persBarMem);
1722 }
1723
1724 /// Save the order of the cool bar contribution items
1725 if (getCoolBarManager() != null) {
1726 getCoolBarManager().refresh();
1727 IMemento coolBarMem = memento.createChild(IWorkbenchConstants.TAG_COOLBAR_LAYOUT);
1728 if (getCoolBarManager().getLockLayout() == true) {
1729 coolBarMem.putInteger(IWorkbenchConstants.TAG_LOCKED,1);
1730 }else {
1731 coolBarMem.putInteger(IWorkbenchConstants.TAG_LOCKED,0);
1732 }
1733 IContributionItem[] items = getCoolBarManager().getItems();
1734 for (int i = 0; i < items.length; i++) {
1735 IMemento coolItemMem = coolBarMem.createChild(IWorkbenchConstants.TAG_COOLITEM);
1736 IContributionItem item = items[i];
1737 // The id of the contribution item
1738 if (item.getId() != null) {
1739 coolItemMem.putString(IWorkbenchConstants.TAG_ID, item.getId());
1740 }
1741 // Write out type and size if applicable
1742 if (item.isSeparator()) {
1743 coolItemMem.putString(
1744 IWorkbenchConstants.TAG_ITEM_TYPE,
1745 IWorkbenchConstants.TAG_TYPE_SEPARATOR);
1746 } else if (item.isGroupMarker() && !item.isSeparator()) {
1747 coolItemMem.putString(
1748 IWorkbenchConstants.TAG_ITEM_TYPE,
1749 IWorkbenchConstants.TAG_TYPE_GROUPMARKER);
1750 } else {
1751 if (item instanceof PlaceholderContributionItem) {
1752 coolItemMem.putString(
1753 IWorkbenchConstants.TAG_ITEM_TYPE,
1754 IWorkbenchConstants.TAG_TYPE_PLACEHOLDER);
1755 } else {
1756 // Store the identifier.
1757 coolItemMem.putString(
1758 IWorkbenchConstants.TAG_ITEM_TYPE,
1759 IWorkbenchConstants.TAG_TYPE_TOOLBARCONTRIBUTION);
1760 }
1761
1762 /* Retrieve a reasonable approximation of the height and
1763 * width, if possible.
1764 */
1765 final int height;
1766 final int width;
1767 if (item instanceof ToolBarContributionItem) {
1768 ToolBarContributionItem toolBarItem = (ToolBarContributionItem) item;
1769 toolBarItem.saveWidgetState();
1770 height = toolBarItem.getCurrentHeight();
1771 width = toolBarItem.getCurrentWidth();
1772 } else if (item instanceof PlaceholderContributionItem) {
1773 PlaceholderContributionItem placeholder = (PlaceholderContributionItem) item;
1774 height = placeholder.getHeight();
1775 width = placeholder.getWidth();
1776 } else {
1777 height = -1;
1778 width = -1;
1779 }
1780
1781 // Store the height and width.
1782 coolItemMem.putInteger(IWorkbenchConstants.TAG_ITEM_X, width);
1783 coolItemMem.putInteger(IWorkbenchConstants.TAG_ITEM_Y, height);
1784 }
1785 }
1786 }
1787
1788
1789 // Save each page.
1790 Iterator enum = pageList.iterator();
1791 while (enum.hasNext()) {
1792 WorkbenchPage page = (WorkbenchPage) enum.next();
1793
1794 // Save perspective.
1795 IMemento pageMem = memento.createChild(IWorkbenchConstants.TAG_PAGE);
1796 pageMem.putString(IWorkbenchConstants.TAG_LABEL, page.getLabel());
1797 result.add(page.saveState(pageMem));
1798
1799 if (page == getActiveWorkbenchPage()) {
1800 pageMem.putString(IWorkbenchConstants.TAG_FOCUS, "true"); //$NON-NLS-1$
1801 }
1802
1803 // Get the input.
1804 IAdaptable input = page.getInput();
1805 if (input != null) {
1806 IPersistableElement persistable =
1807 (IPersistableElement) input.getAdapter(IPersistableElement.class);
1808 if (persistable == null) {
1809 WorkbenchPlugin.log(
1810 "Unable to save page input: " //$NON-NLS-1$
1811 + input
1812 + ", because it does not adapt to IPersistableElement"); //$NON-NLS-1$
1813 }
1814 else {
1815 // Save input.
1816 IMemento inputMem = pageMem.createChild(IWorkbenchConstants.TAG_INPUT);
1817 inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, persistable.getFactoryId());
1818 persistable.saveState(inputMem);
1819 }
1820 }
1821 }
1822 return result;
1823 }
1824 /**
1825 * Select the shortcut for a perspective.
1826 */
1827 /* package */
1828 void selectPerspectiveShortcut(
1829 IPerspectiveDescriptor perspective,
1830 WorkbenchPage page,
1831 boolean selected) {
1832 if (perspectiveSwitcher != null)
1833 perspectiveSwitcher.selectPerspectiveShortcut(perspective, page, selected);
1834 }
1835 /**
1836 * Sets the active page within the window.
1837 *
1838 * @param page identifies the new active page.
1839 */
1840 public void setActivePage(final IWorkbenchPage in) {
1841 if (getActiveWorkbenchPage() == in)
1842 return;
1843
1844 // 1FVGTNR: ITPUI:WINNT - busy cursor for switching perspectives
1845 BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
1846 public void run() {
1847 // Deactivate old persp.
1848 WorkbenchPage currentPage = getActiveWorkbenchPage();
1849 if (currentPage != null) {
1850 currentPage.onDeactivate();
1851 }
1852
1853 // Activate new persp.
1854 if (in == null || pageList.contains(in))
1855 pageList.setActive(in);
1856 WorkbenchPage newPage = pageList.getActive();
1857 if (newPage != null) {
1858 newPage.onActivate();
1859 firePageActivated(newPage);
1860 if (newPage.getPerspective() != null)
1861 firePerspectiveActivated(newPage, newPage.getPerspective());
1862 }
1863
1864 if (isClosing())
1865 return;
1866
1867 updateDisabled = false;
1868
1869 // Update action bars ( implicitly calls updateActionBars() )
1870 updateActionSets();
1871
1872 if (perspectiveSwitcher != null)
1873 perspectiveSwitcher.update(false);
1874
1875 getMenuManager().update(IAction.TEXT);
1876
1877 if (noOpenPerspective != null && in != null) {
1878 noOpenPerspective.dispose();
1879 noOpenPerspective = null;
1880 }
1881 }
1882 });
1883 }
1884
1885 /**
1886 * Returns whether or not children exist for the Window's toolbar control.
1887 * Overridden for coolbar support.
1888 * <p>
1889 * @return boolean true if children exist, false otherwise
1890 */
1891 protected boolean toolBarChildrenExist() {
1892 CoolBar coolBarControl = (CoolBar) getCoolBarControl();
1893 return coolBarControl.getItemCount() > 0;
1894 }
1895 /**
1896 * Hooks a listener to track the activation and
1897 * deactivation of the window's shell. Notifies
1898 * the active part and editor of the change
1899 */
1900 private void trackShellActivation(Shell shell) {
1901 shell.addShellListener(new ShellAdapter() {
1902 public void shellActivated(ShellEvent event) {
1903 shellActivated = true;
1904 getWorkbenchImpl().setActivatedWindow(WorkbenchWindow.this);
1905 WorkbenchPage currentPage = getActiveWorkbenchPage();
1906 if (currentPage != null) {
1907 IWorkbenchPart part = currentPage.getActivePart();
1908 if (part != null) {
1909 PartSite site = (PartSite) part.getSite();
1910 site.getPane().shellActivated();
1911 }
1912 IEditorPart editor = currentPage.getActiveEditor();
1913 if (editor != null) {
1914 PartSite site = (PartSite) editor.getSite();
1915 site.getPane().shellActivated();
1916 }
1917 getWorkbenchImpl().fireWindowActivated(WorkbenchWindow.this);
1918 }
1919 }
1920 public void shellDeactivated(ShellEvent event) {
1921 shellActivated = false;
1922 WorkbenchPage currentPage = getActiveWorkbenchPage();
1923 if (currentPage != null) {
1924 IWorkbenchPart part = currentPage.getActivePart();
1925 if (part != null) {
1926 PartSite site = (PartSite) part.getSite();
1927 site.getPane().shellDeactivated();
1928 }
1929 IEditorPart editor = currentPage.getActiveEditor();
1930 if (editor != null) {
1931 PartSite site = (PartSite) editor.getSite();
1932 site.getPane().shellDeactivated();
1933 }
1934 getWorkbenchImpl().fireWindowDeactivated(WorkbenchWindow.this);
1935 }
1936 }
1937 });
1938 }
1939 /**
1940 * Hooks a listener to track the resize of the window's
1941 * shell. Stores the new bounds if in normal state - that
1942 * is, not in minimized or maximized state)
1943 */
1944 private void trackShellResize(Shell newShell) {
1945 newShell.addControlListener(new ControlAdapter() {
1946 public void controlMoved(ControlEvent e) {
1947 saveBounds();
1948 }
1949
1950 public void controlResized(ControlEvent e) {
1951 saveBounds();
1952 }
1953
1954 private void saveBounds() {
1955 Shell shell = getShell();
1956 if (shell == null)
1957 return;
1958 if (shell.isDisposed())
1959 return;
1960 if (shell.getMinimized())
1961 return;
1962 if (shell.getMaximized()) {
1963 asMaximizedState = true;
1964 return;
1965 }
1966 asMaximizedState = false;
1967 normalBounds = shell.getBounds();
1968 }
1969 });
1970 }
1971
1972 /**
1973 * update the action bars.
1974 */
1975 public void updateActionBars() {
1976 if (updateDisabled)
1977 return;
1978 // updateAll required in order to enable accelerators on pull-down menus
1979 getMenuBarManager().updateAll(false);
1980 getCoolBarManager().update(false);
1981 getStatusLineManager().update(false);
1982 }
1983 /**
1984 * Update the visible action sets. This method is typically called
1985 * from a page when the user changes the visible action sets
1986 * within the prespective.
1987 */
1988 public void updateActionSets() {
1989 if (updateDisabled)
1990 return;
1991
1992 WorkbenchPage currentPage = getActiveWorkbenchPage();
1993 if (currentPage == null)
1994 actionPresentation.clearActionSets();
1995 else {
1996 if (getCoolBarManager() != null) {
1997 getCoolBarManager().refresh();
1998 }
1999 actionPresentation.setActionSets(currentPage.getActionSets());
2000 }
2001 updateActionBars();
2002
2003 // hide the launch menu if it is empty
2004 String path =
2005 IWorkbenchActionConstants.M_WINDOW
2006 + IWorkbenchActionConstants.SEP
2007 + IWorkbenchActionConstants.M_LAUNCH;
2008 IMenuManager manager = getMenuBarManager().findMenuUsingPath(path);
2009 IContributionItem item = getMenuBarManager().findUsingPath(path);
2010
2011 // TODO remove: updateActiveActions();
2012 IActionSet actionSets[] = actionPresentation.getActionSets();
2013 registerActionSets(actionSets);
2014
2015 if (manager == null || item == null)
2016 return;
2017 item.setVisible(manager.getItems().length >= 2);
2018 // there is a separator for the additions group thus >= 2
2019 }
2020 /**
2021 * Updates the shorcut item
2022 */
2023 /* package */
2024 void updatePerspectiveShortcut(
2025 IPerspectiveDescriptor oldDesc,
2026 IPerspectiveDescriptor newDesc,
2027 WorkbenchPage page) {
2028 if (updateDisabled)
2029 return;
2030
2031 if (perspectiveSwitcher != null)
2032 perspectiveSwitcher.updatePerspectiveShortcut(oldDesc, newDesc, page);
2033 }
2034
2035 /**
2036 * Create the progress indicator for the receiver.
2037 * @param shell the parent shell
2038 */
2039 private void createProgressIndicator(Shell shell) {
2040 if (getWindowConfigurer().getShowProgressIndicator()) {
2041 progressRegion = new ProgressRegion();
2042 progressRegion.createContents(shell,this);
2043 }
2044
2045 }
2046 class PageList {
2047 //List of pages in the order they were created;
2048 private List pagesInCreationOrder;
2049 //List of pages where the top is the last activated.
2050 private List pageInActivationOrder;
2051 // The page explicitly activated
2052 private Object active;
2053
2054 public PageList() {
2055 pagesInCreationOrder = new ArrayList(4);
2056 pageInActivationOrder = new ArrayList(4);
2057 }
2058 public boolean add(Object object) {
2059 pagesInCreationOrder.add(object);
2060 pageInActivationOrder.add(0, object);
2061 //It will be moved to top only when activated.
2062 return true;
2063 }
2064 public Iterator iterator() {
2065 return pagesInCreationOrder.iterator();
2066 }
2067 public boolean contains(Object object) {
2068 return pagesInCreationOrder.contains(object);
2069 }
2070 public boolean remove(Object object) {
2071 if (active == object)
2072 active = null;
2073 pageInActivationOrder.remove(object);
2074 return pagesInCreationOrder.remove(object);
2075 }
2076 public boolean isEmpty() {
2077 return pagesInCreationOrder.isEmpty();
2078 }
2079 public IWorkbenchPage[] getPages() {
2080 int nSize = pagesInCreationOrder.size();
2081 IWorkbenchPage[] retArray = new IWorkbenchPage[nSize];
2082 pagesInCreationOrder.toArray(retArray);
2083 return retArray;
2084 }
2085 public void setActive(Object page) {
2086 if (active == page)
2087 return;
2088
2089 active = page;
2090
2091 if (page != null) {
2092 pageInActivationOrder.remove(page);
2093 pageInActivationOrder.add(page);
2094 }
2095 }
2096 public WorkbenchPage getActive() {
2097 return (WorkbenchPage) active;
2098 }
2099 public WorkbenchPage getNextActive() {
2100 if (active == null) {
2101 if (pageInActivationOrder.isEmpty())
2102 return null;
2103 else
2104 return (WorkbenchPage) pageInActivationOrder.get(pageInActivationOrder.size() - 1);
2105 } else {
2106 if (pageInActivationOrder.size() < 2)
2107 return null;
2108 else
2109 return (WorkbenchPage) pageInActivationOrder.get(pageInActivationOrder.size() - 2);
2110 }
2111 }
2112 }
2113
2114 /**
2115 * Returns the unique object that applications use to configure this window.
2116 * <p>
2117 * IMPORTANT This method is declared package-private to prevent regular
2118 * plug-ins from downcasting IWorkbenchWindow to WorkbenchWindow and getting
2119 * hold of the workbench window configurer that would allow them to tamper
2120 * with the workbench window. The workbench window configurer is available
2121 * only to the application.
2122 * </p>
2123 */
2124 /* package - DO NOT CHANGE */
2125 WorkbenchWindowConfigurer getWindowConfigurer() {
2126 if (windowConfigurer == null) {
2127 // lazy initialize
2128 windowConfigurer = new WorkbenchWindowConfigurer(this);
2129 }
2130 return windowConfigurer;
2131 }
2132
2133 /**
2134 * Returns the workbench advisor. Assumes the workbench
2135 * has been created already.
2136 * <p>
2137 * IMPORTANT This method is declared private to prevent regular
2138 * plug-ins from downcasting IWorkbenchWindow to WorkbenchWindow and getting
2139 * hold of the workbench advisor that would allow them to tamper with the
2140 * workbench. The workbench advisor is internal to the application.
2141 * </p>
2142 */
2143 private /* private - DO NOT CHANGE */
2144 WorkbenchAdvisor getAdvisor() {
2145 return getWorkbenchImpl().getAdvisor();
2146 }
2147
2148 /*
2149 * Returns the IWorkbench implementation.
2150 */
2151 private Workbench getWorkbenchImpl() {
2152 return Workbench.getInstance();
2153 }
2154
2155 /**
2156 * Creates a clone copy of the current action bars
2157 * @param configurer location of managers
2158 * @param flags indicate which actions to load and whether its a proxy fill
2159 */
2160 public void fillActionBars(IActionBarConfigurer configurer, int flags) {
2161 Workbench workbench = getWorkbenchImpl();
2162 workbench.largeUpdateStart();
2163 try {
2164
2165 getAdvisor().fillActionBars(this, configurer, flags);
2166
2167 } finally {
2168 workbench.largeUpdateEnd();
2169 }
2170 }
2171
2172
2173 /**
2174 * The <code>WorkbenchWindow</code> implementation of this method has the same
2175 * logic as <code>Window</code>'s implementation, but without the resize check.
2176 * We don't want to skip setting the bounds if the shell has been resized since a
2177 * free resize event occurs on Windows when the menubar is set in configureShell.
2178 */
2179 protected void initializeBounds() {
2180 Point size = getInitialSize();
2181 Point location = getInitialLocation(size);
2182 getShell().setBounds(getConstrainedShellBounds(new Rectangle(location.x, location.y, size.x, size.y)));
2183 }
2184
2185 /**
2186 * The <code>WorkbenchWindow</code> implementation of this method
2187 * delegates to the window configurer.
2188 *
2189 * @since 3.0
2190 */
2191 protected Point getInitialSize() {
2192 return getWindowConfigurer().getInitialSize();
2193 }
2194
2195 /**
2196 * @param visible whether the cool bar should be shown. This is only
2197 * applicable if the window configurer also wishes either the cool bar to be
2198 * visible.
2199 * @since 3.0
2200 */
2201 public void setCoolBarVisible(boolean visible) {
2202 boolean oldValue = coolBarVisible;
2203 coolBarVisible = visible;
2204 if (oldValue != coolBarVisible) {
2205 updateLayoutDataForContents();
2206 }
2207 }
2208
2209 /**
2210 * @return whether the cool bar should be shown. This is only
2211 * applicable if the window configurer also wishes either the cool bar to be
2212 * visible.
2213 * @since 3.0
2214 */
2215 public boolean getCoolBarVisible() {
2216 return coolBarVisible;
2217 }
2218
2219 /**
2220 * @param visible whether the perspective bar should be shown. This is only
2221 * applicable if the window configurer also wishes either the perspective
2222 * bar to be visible.
2223 * @since 3.0
2224 */
2225 public void setPerspectiveBarVisible(boolean visible) {
2226 boolean oldValue = perspectiveBarVisible;
2227 perspectiveBarVisible = visible;
2228 if (oldValue != perspectiveBarVisible) {
2229 updateLayoutDataForContents();
2230 }
2231 }
2232
2233 /**
2234 * @return whether the perspective bar should be shown. This is only
2235 * applicable if the window configurer also wishes either the perspective
2236 * bar to be visible.
2237 * @since 3.0
2238 */
2239 public boolean getPerspectiveBarVisible() {
2240 return perspectiveBarVisible;
2241 }
2242
2243 /**
2244 * @param visible whether the perspective bar should be shown. This is only
2245 * applicable if the window configurer also wishes either the perspective
2246 * bar to be visible.
2247 * @since 3.0
2248 */
2249 public void setStatusLineVisible(boolean visible) {
2250 boolean oldValue = statusLineVisible;
2251 statusLineVisible = visible;
2252 if (oldValue != statusLineVisible) {
2253 updateLayoutDataForContents();
2254 }
2255 }
2256
2257 /**
2258 * @return whether the perspective bar should be shown. This is only
2259 * applicable if the window configurer also wishes either the perspective
2260 * bar to be visible.
2261 * @since 3.0
2262 */
2263 public boolean getStatusLineVisible() {
2264 return statusLineVisible;
2265 }
2266
2267 /**
2268 * Note that this will only have an effect if the default implementation of
2269 * WorkbenchAdvisor.createWindowContents() has been invoked.
2270 *
2271 * called IWorkbench
2272 * @since 3.0
2273 */
2274 private void updateLayoutDataForContents() {
2275 if (defaultLayout == null)
2276 return;
2277
2278 // @issue this is not ideal; coolbar and perspective shortcuts should be
2279 // separately configurable
2280 if ((getCoolBarVisible() && getWindowConfigurer().getShowCoolBar()) || (getPerspectiveBarVisible() && getWindowConfigurer().getShowPerspectiveBar())) {
2281 defaultLayout.addTrim(topBar, SWT.TOP, null);
2282 topBar.setVisible(true);
2283 }
2284 else {
2285 defaultLayout.removeTrim(topBar);
2286 topBar.setVisible(false);
2287 }
2288
2289 if (getStatusLineVisible() && getWindowConfigurer().getShowStatusLine()) {
2290 defaultLayout.addTrim(getStatusLineManager().getControl(), SWT.BOTTOM, null);
2291 getStatusLineManager().getControl().setVisible(true);
2292 }
2293 else {
2294 defaultLayout.removeTrim(getStatusLineManager().getControl());
2295 getStatusLineManager().getControl().setVisible(false);
2296 }
2297
2298 if (getWindowConfigurer().getShowProgressIndicator()) {
2299 if (progressRegion.getControl().getLayoutData() == null) {
2300 TrimLayoutData animationData = new TrimLayoutData(false,
2301 progressRegion.getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
2302 getStatusLineManager().getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
2303
2304 progressRegion.getControl().setLayoutData(animationData);
2305 }
2306 defaultLayout.addTrim(progressRegion.getControl(), SWT.BOTTOM, null);
2307 progressRegion.getControl().setVisible(true);
2308 }
2309 else {
2310 if (progressRegion != null) {
2311 defaultLayout.removeTrim(progressRegion.getControl());
2312 progressRegion.getControl().setVisible(false);
2313 }
2314 }
2315 defaultLayout.setCenterControl(getPageComposite());
2316 }
2317
2318 public boolean getShowFastViewBars() {
2319 return getWindowConfigurer().getShowFastViewBars();
2320 }
2321
2322 /**
2323 * Set the layout data for the contents of the window.
2324 */
2325 private void setLayoutDataForContents() {
2326 updateLayoutDataForContents();
2327
2328 if (getWindowConfigurer().getShowFastViewBars() && fastViewBar != null) {
2329 fastViewBar.addDockingListener(new IChangeListener() {
2330 public void update(boolean changed) {
2331 Control reference = null;
2332 int side = fastViewBar.getSide();
2333
2334 fastViewBar.getControl().setLayoutData(new TrimLayoutData(side != SWT.BOTTOM, SWT.DEFAULT, SWT.DEFAULT));
2335
2336 if (side == SWT.BOTTOM && getWindowConfigurer().getShowStatusLine()) {
2337 reference = getStatusLineManager().getControl();
2338 }
2339
2340 defaultLayout.addTrim(fastViewBar.getControl(), side, reference);
2341 WorkbenchPage page = getActiveWorkbenchPage();
2342
2343 if (page != null) {
2344 Perspective persp = page.getActivePerspective();
2345 IViewReference activeFastView = persp.getActiveFastView();
2346 if (activeFastView != null) {
2347 persp.setActiveFastView(null);
2348 persp.setActiveFastView(activeFastView);
2349 }
2350 }
2351
2352 LayoutUtil.resize(fastViewBar.getControl());
2353 }
2354 });
2355 }
2356 }
2357
2358 /**
2359 * Returns the fast view bar.
2360 */
2361 public FastViewBar getFastViewBar() {
2362 return fastViewBar;
2363 }
2364
2365 /**
2366 * Returns the perspective bar.
2367 */
2368 public PerspectiveBarManager getPerspectiveBar() {
2369 return perspectiveSwitcher == null ? null : perspectiveSwitcher.getPerspectiveBar();
2370 }
2371
2372//for dynamic UI
2373 protected ActionPresentation getActionPresentation() {
2374 return actionPresentation;
2375 }
2376
2377 /* (non-Javadoc)
2378 * @see org.eclipse.jface.window.ApplicationWindow#showTopSeperator()
2379 */
2380 protected boolean showTopSeperator() {
2381 return false;
2382 }
2383
2384
2385 /**
2386 * Delegate to the presentation factory.
2387 *
2388 * @see org.eclipse.jface.window.ApplicationWindow#createStatusLineManager
2389 * @since 3.0
2390 */
2391 protected StatusLineManager createStatusLineManager() {
2392 // @issue ApplicationWindow and WorkbenchWindow should allow full IStatusLineManager
2393 return (StatusLineManager) getWindowConfigurer().getPresentationFactory().createStatusLineManager();
2394 }
2395
2396 /**
2397 * Delegate to the presentation factory.
2398 *
2399 * @see org.eclipse.jface.window.ApplicationWindow#createStatusLine
2400 * @since 3.0
2401 */
2402 protected void createStatusLine(Shell shell) {
2403 getWindowConfigurer().getPresentationFactory().createStatusLineControl(getStatusLineManager(), shell);
2404 }
2405
2406 /**
2407 * Updates the fast view bar, if present.
2408 * TODO: The fast view bar should update itself as necessary.
2409 * All calls to this should be cleaned up.
2410 *
2411 * @since 3.0
2412 */
2413 public void updateFastViewBar() {
2414 if (getFastViewBar() != null) {
2415 getFastViewBar().update(true);
2416 }
2417 }
2418 /**
2419 * @return Returns the progressRegion.
2420 */
2421 public ProgressRegion getProgressRegion() {
2422 return progressRegion;
2423 }
2424
2425 /**
2426 * Add the argument perspective bar control to the argument side of this
2427 * window's trim.
2428 *
2429 * @param control
2430 * the perspective bar's control
2431 * @param side
2432 * one of <code>SWT.LEFT</code>,<code>SWT.BOTTOM</code>,
2433 * or <code>SWT.RIGHT</code> (only LEFT has been tested)
2434 * @since 3.0
2435 */
2436 public void addPerspectiveBarToTrim(Control control, int side) {
2437 Control reference = null;
2438
2439 // the perspective bar should go before the fast view bar they're on the
2440 // same side and before the status line if on the bottom
2441 if (side == fastViewBar.getSide())
2442 reference = fastViewBar.getControl();
2443 else if(side == SWT.BOTTOM && getWindowConfigurer().getShowStatusLine())
2444 reference = getStatusLineManager().getControl();
2445
2446 control.setLayoutData(new TrimLayoutData(false, SWT.DEFAULT, SWT.DEFAULT));
2447 defaultLayout.addTrim(control, side, reference);
2448 }
2449}