]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.workbench/src/org/simantics/workbench/internal/SimanticsWorkbenchWindowAdvisor.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / internal / SimanticsWorkbenchWindowAdvisor.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.workbench.internal;
13
14 import java.net.URL;
15 import java.util.ArrayList;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.concurrent.atomic.AtomicBoolean;
20
21 import org.eclipse.core.runtime.IAdaptable;
22 import org.eclipse.core.runtime.IProduct;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.Platform;
25 import org.eclipse.core.runtime.Status;
26 import org.eclipse.jface.action.ToolBarManager;
27 import org.eclipse.jface.dialogs.ErrorDialog;
28 import org.eclipse.jface.dialogs.IDialogConstants;
29 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
30 import org.eclipse.jface.preference.IPreferenceStore;
31 import org.eclipse.jface.resource.JFaceResources;
32 import org.eclipse.jface.util.IPropertyChangeListener;
33 import org.eclipse.jface.util.PropertyChangeEvent;
34 import org.eclipse.osgi.util.NLS;
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.dnd.FileTransfer;
37 import org.eclipse.swt.graphics.Color;
38 import org.eclipse.swt.layout.GridLayout;
39 import org.eclipse.swt.widgets.Composite;
40 import org.eclipse.swt.widgets.Control;
41 import org.eclipse.swt.widgets.Display;
42 import org.eclipse.swt.widgets.Label;
43 import org.eclipse.swt.widgets.Shell;
44 import org.eclipse.swt.widgets.ToolBar;
45 import org.eclipse.ui.IEditorPart;
46 import org.eclipse.ui.IEditorReference;
47 import org.eclipse.ui.IPageListener;
48 import org.eclipse.ui.IPartListener2;
49 import org.eclipse.ui.IPerspectiveDescriptor;
50 import org.eclipse.ui.IPerspectiveRegistry;
51 import org.eclipse.ui.IPropertyListener;
52 import org.eclipse.ui.IWorkbench;
53 import org.eclipse.ui.IWorkbenchPage;
54 import org.eclipse.ui.IWorkbenchPartConstants;
55 import org.eclipse.ui.IWorkbenchPartReference;
56 import org.eclipse.ui.IWorkbenchWindow;
57 import org.eclipse.ui.PartInitException;
58 import org.eclipse.ui.PerspectiveAdapter;
59 import org.eclipse.ui.PlatformUI;
60 import org.eclipse.ui.WorkbenchException;
61 import org.eclipse.ui.actions.ActionFactory;
62 import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
63 import org.eclipse.ui.application.ActionBarAdvisor;
64 import org.eclipse.ui.application.IActionBarConfigurer;
65 import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
66 import org.eclipse.ui.application.WorkbenchWindowAdvisor;
67 import org.eclipse.ui.internal.ide.AboutInfo;
68 import org.eclipse.ui.internal.ide.EditorAreaDropAdapter;
69 import org.eclipse.ui.internal.ide.IDEInternalPreferences;
70 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
71 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
72 import org.eclipse.ui.internal.ide.dialogs.WelcomeEditorInput;
73 import org.eclipse.ui.part.EditorInputTransfer;
74 import org.eclipse.ui.part.MarkerTransfer;
75 import org.eclipse.ui.part.ResourceTransfer;
76 import org.eclipse.ui.statushandlers.StatusManager;
77 import org.osgi.framework.Bundle;
78 import org.osgi.framework.BundleContext;
79 import org.osgi.framework.BundleException;
80 import org.osgi.framework.ServiceReference;
81 import org.simantics.db.management.ISessionContextChangedListener;
82 import org.simantics.db.management.ISessionContextProvider;
83 import org.simantics.db.management.SessionContextChangedEvent;
84 import org.simantics.ui.SimanticsUI;
85 import org.simantics.ui.workbench.WorkbenchShutdownService;
86
87
88 /**
89  * System properties used to configure how this class works:
90  * <ul>
91  * <li><code>org.simantics.workbench.application.showProgressIndicator=true|false (default=true)</code> - Used to initialize IWorkbenchWindowConfigurer.setShowProgressIndicator</li>
92  * <li><code>org.simantics.workbench.application.showFastViewBars=true|false (default=true)</code> - Used to initialize IWorkbenchWindowConfigurer.setShowFastViewBars</li>
93  * <li><code>org.simantics.workbench.application.showPerspectiveBar=true|false (default=true)</code> - Used to initialize IWorkbenchWindowConfigurer.setShowPerspectiveBar</li>
94  * <li><code>org.simantics.workbench.application.excludePerspectiveFromTitle=true|false (default=false)</code> - Used to exclude perspective name in {@link #computeTitle()}</li>
95  * </ul>
96  * 
97  * @author Tuukka Lehtonen
98  */
99 public class SimanticsWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
100
101     private static final String WELCOME_EDITOR_ID = "org.eclipse.ui.internal.ide.dialogs.WelcomeEditor"; //$NON-NLS-1$
102
103     protected SimanticsWorkbenchAdvisor wbAdvisor;
104     protected boolean editorsAndIntrosOpened = false;
105     protected IEditorPart lastActiveEditor = null;
106     protected IPerspectiveDescriptor lastPerspective = null;
107
108     protected IWorkbenchPage lastActivePage;
109     protected String lastEditorTitle = ""; //$NON-NLS-1$
110
111     private final IPropertyListener editorPropertyListener = new IPropertyListener() {
112         @Override
113         public void propertyChanged(Object source, int propId) {
114             if (propId == IWorkbenchPartConstants.PROP_TITLE) {
115                 if (lastActiveEditor != null) {
116                     String newTitle = lastActiveEditor.getTitle();
117                     if (!lastEditorTitle.equals(newTitle)) {
118                         recomputeTitle();
119                     }
120                 }
121             }
122         }
123     };
124
125     private IAdaptable lastInput;
126     private IWorkbenchAction openPerspectiveAction;
127
128     /**
129      * The property change listener.
130      * @since 3.6.1
131      */
132     private IPropertyChangeListener propertyChangeListener;
133
134     /**
135      * Return the style bits for the shortcut bar.
136      * 
137      * @return style bitmask
138      */
139     protected int perspectiveBarStyle() {
140         return SWT.FLAT | SWT.WRAP | SWT.RIGHT | SWT.HORIZONTAL;
141     }
142
143     /**
144      * Crates a new IDE workbench window advisor.
145      * 
146      * @param wbAdvisor the workbench advisor
147      * @param configurer the window configurer
148      */
149     public SimanticsWorkbenchWindowAdvisor(SimanticsWorkbenchAdvisor wbAdvisor, IWorkbenchWindowConfigurer configurer) {
150         super(configurer);
151         this.wbAdvisor = wbAdvisor;
152     }
153
154     /* (non-Javadoc)
155      * @see org.eclipse.ui.application.WorkbenchWindowAdvisor#createActionBarAdvisor(org.eclipse.ui.application.IActionBarConfigurer)
156      */
157     @Override
158     public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
159         return new SimanticsWorkbenchActionBarAdvisor(configurer);
160     }
161
162     /**
163      * Returns the workbench.
164      * 
165      * @return the workbench
166      */
167     private IWorkbench getWorkbench() {
168         return getWindowConfigurer().getWorkbenchConfigurer().getWorkbench();
169     }
170
171     private volatile boolean allWindowShellsClosed = false;
172
173     /*
174      * (non-Javadoc)
175      * 
176      * @see org.eclipse.ui.application.WorkbenchAdvisor#preWindowShellClose
177      */
178     @Override
179     public boolean preWindowShellClose() {
180         if (getWorkbench().getWorkbenchWindowCount() > 1) {
181             return true;
182         }
183
184         // WORKAROUND for a workbench problem which causes Eclipse to invoke this method twice:
185         // Always return false after true has been returned.
186         // Eclipse/SWT or something seems to have a bug of some sort that causes it to receive
187         // See https://www.simantics.org/redmine/issues/3848.
188         if (allWindowShellsClosed)
189             return false;
190
191         // the user has asked to close the last window, while will cause the
192         // workbench to close in due course - prompt the user for confirmation
193         IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
194         .getPreferenceStore();
195         boolean promptOnExit = store
196         .getBoolean(IDEInternalPreferences.EXIT_PROMPT_ON_CLOSE_LAST_WINDOW);
197
198         if (promptOnExit) {
199             String message;
200
201             String productName = null;
202             IProduct product = Platform.getProduct();
203             if (product != null) {
204                 productName = product.getName();
205             }
206             if (productName == null) {
207                 message = IDEWorkbenchMessages.PromptOnExitDialog_message0;
208             } else {
209                 message = NLS.bind(IDEWorkbenchMessages.PromptOnExitDialog_message1, productName);
210             }
211
212             MessageDialogWithToggle dlg = MessageDialogWithToggle
213             .openOkCancelConfirm(getWindowConfigurer().getWindow()
214                     .getShell(), IDEWorkbenchMessages.PromptOnExitDialog_shellTitle,
215                     message, IDEWorkbenchMessages.PromptOnExitDialog_choice,
216                     false, null, null);
217             if (dlg.getReturnCode() != IDialogConstants.OK_ID) {
218                 return false;
219             }
220             if (dlg.getToggleState()) {
221                 store
222                 .setValue(
223                         IDEInternalPreferences.EXIT_PROMPT_ON_CLOSE_LAST_WINDOW,
224                         false);
225                 IDEWorkbenchPlugin.getDefault().savePluginPreferences();
226             }
227         }
228
229         // Make sure that it's OK to close even if there are unsaved changes.
230         AtomicBoolean saveAtExit = new AtomicBoolean(false);
231         if (!ApplicationUtil.allowShutdown(saveAtExit))
232             return false;
233         wbAdvisor.setSaveAtExit(saveAtExit.get());
234
235         BundleContext context = Activator.getDefault().getBundle().getBundleContext();
236         ServiceReference<?> ref = context.getServiceReference(WorkbenchShutdownService.class.getName());
237         WorkbenchShutdownService shutdown = (WorkbenchShutdownService)context.getService(ref);
238         shutdown.doShutdown();
239         context.ungetService(ref);
240
241         allWindowShellsClosed = true;
242
243         return true;
244     }
245
246     /**
247      * Asks the user whether the workbench should really be closed. Only asks if
248      * the preference is enabled.
249      * 
250      * @param parentShell
251      *            the parent shell to use for the confirmation dialog
252      * @return <code>true</code> if OK to exit, <code>false</code> if the user
253      *         canceled
254      * @since 3.6
255      */
256     static boolean promptOnExit(Shell parentShell) {
257         IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
258                 .getPreferenceStore();
259         boolean promptOnExit = store
260                 .getBoolean(IDEInternalPreferences.EXIT_PROMPT_ON_CLOSE_LAST_WINDOW);
261
262         if (promptOnExit) {
263             if (parentShell == null) {
264                 IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
265                 if (workbenchWindow != null) {
266                     parentShell = workbenchWindow.getShell();
267                 }
268             }
269             if (parentShell != null) {
270                 parentShell.setMinimized(false);
271                 parentShell.forceActive();
272             }
273
274             String message;
275
276             String productName = null;
277             IProduct product = Platform.getProduct();
278             if (product != null) {
279                 productName = product.getName();
280             }
281             if (productName == null) {
282                 message = IDEWorkbenchMessages.PromptOnExitDialog_message0;
283             } else {
284                 message = NLS.bind(
285                         IDEWorkbenchMessages.PromptOnExitDialog_message1,
286                         productName);
287             }
288
289             MessageDialogWithToggle dlg = MessageDialogWithToggle
290                     .openOkCancelConfirm(parentShell,
291                             IDEWorkbenchMessages.PromptOnExitDialog_shellTitle,
292                             message,
293                             IDEWorkbenchMessages.PromptOnExitDialog_choice,
294                             false, null, null);
295             if (dlg.getReturnCode() != IDialogConstants.OK_ID) {
296                 return false;
297             }
298             if (dlg.getToggleState()) {
299                 store
300                 .setValue(
301                         IDEInternalPreferences.EXIT_PROMPT_ON_CLOSE_LAST_WINDOW,
302                         false);
303                 IDEWorkbenchPlugin.getDefault().savePluginPreferences();
304             }
305         }
306
307         return true;
308     }
309
310     /* (non-Javadoc)
311      * @see org.eclipse.ui.application.WorkbenchAdvisor#preWindowOpen
312      */
313     @Override
314     public void preWindowOpen() {
315         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
316
317         boolean showProgressIndicator = !"false".equals(System.getProperty("org.simantics.workbench.application.showProgressIndicator", "true").toLowerCase());
318         boolean showPerspectiveBar    = !"false".equals(System.getProperty("org.simantics.workbench.application.showPerspectiveBar", "true").toLowerCase());
319
320         // show the shortcut bar and progress indicator, which are hidden by default
321         configurer.setShowProgressIndicator(showProgressIndicator);
322         configurer.setShowPerspectiveBar(showPerspectiveBar);
323
324         // add the drag and drop support for the editor area
325         configurer.addEditorAreaTransfer(EditorInputTransfer.getInstance());
326         configurer.addEditorAreaTransfer(ResourceTransfer.getInstance());
327         configurer.addEditorAreaTransfer(FileTransfer.getInstance());
328         configurer.addEditorAreaTransfer(MarkerTransfer.getInstance());
329         configurer.configureEditorAreaDropListener(new EditorAreaDropAdapter(
330                 configurer.getWindow()));
331
332         hookTitleUpdateListeners(configurer);
333     }
334
335     /**
336      * Hooks the listeners needed on the window
337      * @param configurer
338      */
339     private void hookTitleUpdateListeners(IWorkbenchWindowConfigurer configurer) {
340         // hook up the listeners to update the window title
341         configurer.getWindow().addPageListener(new IPageListener() {
342             @Override
343             public void pageActivated(IWorkbenchPage page) {
344                 updateTitle(false);
345             }
346
347             @Override
348             public void pageClosed(IWorkbenchPage page) {
349                 updateTitle(false);
350             }
351
352             @Override
353             public void pageOpened(IWorkbenchPage page) {
354                 // do nothing
355             }
356         });
357         configurer.getWindow().addPerspectiveListener(
358                 new PerspectiveAdapter() {
359                     @Override
360                     public void perspectiveActivated(IWorkbenchPage page,
361                             IPerspectiveDescriptor perspective) {
362                         updateTitle(false);
363                     }
364                     @Override
365                     public void perspectiveSavedAs(IWorkbenchPage page,IPerspectiveDescriptor oldPerspective,IPerspectiveDescriptor newPerspective){
366                         updateTitle(false);
367                     }
368                     @Override
369                     public void perspectiveDeactivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
370                         updateTitle(false);
371                     }
372                 });
373         configurer.getWindow().getPartService().addPartListener(
374                 new IPartListener2() {
375                     @Override
376                     public void partActivated(IWorkbenchPartReference ref) {
377                         if (ref instanceof IEditorReference) {
378                             updateTitle(false);
379                         }
380                     }
381
382                     @Override
383                     public void partBroughtToTop(IWorkbenchPartReference ref) {
384                         if (ref instanceof IEditorReference) {
385                             updateTitle(false);
386                         }
387                     }
388
389                     @Override
390                     public void partClosed(IWorkbenchPartReference ref) {
391                         updateTitle(false);
392                     }
393
394                     @Override
395                     public void partDeactivated(IWorkbenchPartReference ref) {
396                         // do nothing
397                     }
398
399                     @Override
400                     public void partOpened(IWorkbenchPartReference ref) {
401                         // do nothing
402                     }
403
404                     @Override
405                     public void partHidden(IWorkbenchPartReference ref) {
406                         if (ref.getPart(false) == lastActiveEditor
407                                 && lastActiveEditor != null) {
408                             updateTitle(true);
409                         }
410                     }
411
412                     @Override
413                     public void partVisible(IWorkbenchPartReference ref) {
414                         if (ref.getPart(false) == lastActiveEditor
415                                 && lastActiveEditor != null) {
416                             updateTitle(false);
417                         }
418                     }
419
420                     @Override
421                     public void partInputChanged(IWorkbenchPartReference ref) {
422                         // do nothing
423                     }
424                 });
425
426         // Update the title when the active UI database session is changed.
427         ISessionContextProvider provider = SimanticsUI.getSessionContextProvider(configurer.getWindow());
428         provider.addContextChangedListener(new ISessionContextChangedListener() {
429             @Override
430             public void sessionContextChanged(SessionContextChangedEvent event) {
431                 IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
432                 IWorkbenchWindow window = configurer.getWindow();
433                 if (window == null)
434                     return;
435                 Shell shell = window.getShell();
436                 if (shell == null || shell.isDisposed())
437                     return;
438                 shell.getDisplay().asyncExec(new Runnable() {
439                     @Override
440                     public void run() {
441                         updateTitle(true);
442                     }
443                 });
444             }
445         });
446
447         // Listen for changes of the workspace name.
448         propertyChangeListener = new IPropertyChangeListener() {
449             public void propertyChange(PropertyChangeEvent event) {
450                 String property = event.getProperty();
451                 if (IDEInternalPreferences.WORKSPACE_NAME.equals(property)
452                         || IDEInternalPreferences.SHOW_LOCATION.equals(property)) {
453                     // Make sure the title is actually updated by
454                     // setting last active page.
455                     lastActivePage = null;
456                     updateTitle(false);
457                 }
458             }
459         };
460         IDEWorkbenchPlugin.getDefault().getPreferenceStore()
461                 .addPropertyChangeListener(propertyChangeListener);
462     }
463
464     protected String computeTitle() {
465         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
466         IWorkbenchPage currentPage = configurer.getWindow().getActivePage();
467         IEditorPart activeEditor = null;
468         if (currentPage != null) {
469             activeEditor = lastActiveEditor;
470         }
471
472         String title = null;
473         IProduct product = Platform.getProduct();
474         if (product != null) {
475             title = product.getName();
476         }
477         if (title == null) {
478             title = ""; //$NON-NLS-1$
479         }
480
481 //        ISessionContext ctx = SimanticsUI.getSessionContext(configurer.getWindow());
482 //        if (ctx != null) {
483 //            ServerAddress addr = ctx.getAddress();
484 //            if (addr != null) {
485 //                title += " - Connected to " + addr.getAddress().getHostName();//InetAddressUtils.toHostString(addr);
486 //            }
487 //            Session session = ctx.getSession();
488 //            if (session != null) {
489 //                SessionUserSupport sessionUser = session.getService(SessionUserSupport.class);
490 //                final Resource user = sessionUser.getUser();
491 //                if (user != null) {
492 //                    String userName;
493 //                    try {
494 //                        userName = session.syncRequest(new Read<String>() {
495 //                            @Override
496 //                            public String perform(ReadGraph graph) throws DatabaseException {
497 //                                try {
498 //                                    return graph.adapt(user, String.class);
499 //                                } catch (AdaptionException e) {
500 //                                    return NameUtils.getSafeName(graph, user);
501 //                                }
502 //                            }
503 //                        });
504 //                    } catch (DatabaseException e) {
505 //                        e.printStackTrace();
506 //                        userName = "ERROR";
507 //                    }
508 //
509 //                    title += " - " + userName;
510 //                }
511 //            }
512 //
513 //        } else {
514 //            //title += " - Disconnected";
515 //        }
516
517         if (currentPage != null) {
518             if (activeEditor != null) {
519                 lastEditorTitle = activeEditor.getTitleToolTip();
520                 //IDEWorkbenchMessages.WorkbenchWindow_shellTitle == "{0} - {1}"
521                 title = NLS.bind("{0} - {1}", lastEditorTitle, title);
522             }
523
524             boolean excludePerspectiveFromTitle = "true".equals(System.getProperty("org.simantics.workbench.application.excludePerspectiveFromTitle", "false").toLowerCase());
525             if (!excludePerspectiveFromTitle) {
526                 IPerspectiveDescriptor persp = currentPage.getPerspective();
527                 String label = ""; //$NON-NLS-1$
528                 if (persp != null) {
529                     label = persp.getLabel();
530                 }
531                 IAdaptable input = currentPage.getInput();
532                 if (input != null && !input.equals(wbAdvisor.getDefaultPageInput())) {
533                     label = currentPage.getLabel();
534                 }
535                 if (label != null && !label.equals("")) { //$NON-NLS-1$
536                         //IDEWorkbenchMessages.WorkbenchWindow_shellTitle == "{0} - {1}"
537                     title = NLS.bind("{0} - {1}", label, title);
538                 }
539             }
540         }
541
542         String workspaceLocation = wbAdvisor.getWorkspaceLocation();
543         if (workspaceLocation != null) {
544             title = NLS.bind("{0} - {1}", title, workspaceLocation);
545         }
546
547         // Bug 284447: Prepend workspace name to the title
548         String workspaceName = IDEWorkbenchPlugin.getDefault()
549         .getPreferenceStore().getString(
550                 IDEInternalPreferences.WORKSPACE_NAME);
551         if (workspaceName != null && workspaceName.length() > 0) {
552                 //IDEWorkbenchMessages.WorkbenchWindow_shellTitle == "{0} - {1}"
553             title = NLS.bind("{0} - {1}", workspaceName, title);
554         }
555
556         return title;
557     }
558
559     private void recomputeTitle() {
560         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
561         String oldTitle = configurer.getTitle();
562         String newTitle = computeTitle();
563         if (!newTitle.equals(oldTitle)) {
564             configurer.setTitle(newTitle);
565         }
566     }
567
568     /**
569      * Updates the window title. Format will be:
570      * [pageInput -] [currentPerspective -] [editorInput -] [workspaceLocation -] productName
571      */
572     private void updateTitle(boolean force) {
573         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
574         IWorkbenchWindow window = configurer.getWindow();
575         IEditorPart activeEditor = null;
576         IWorkbenchPage currentPage = window.getActivePage();
577         IPerspectiveDescriptor persp = null;
578         IAdaptable input = null;
579
580         if (currentPage != null) {
581             activeEditor = currentPage.getActiveEditor();
582             persp = currentPage.getPerspective();
583             input = currentPage.getInput();
584         }
585
586         // Nothing to do if the editor hasn't changed or change is not forced.
587         if (!force && activeEditor == lastActiveEditor && currentPage == lastActivePage
588                 && persp == lastPerspective && input == lastInput) {
589             return;
590         }
591
592         if (lastActiveEditor != null) {
593             lastActiveEditor.removePropertyListener(editorPropertyListener );
594         }
595
596         lastActiveEditor = activeEditor;
597         lastActivePage = currentPage;
598         lastPerspective = persp;
599         lastInput = input;
600
601         if (activeEditor != null) {
602             activeEditor.addPropertyListener(editorPropertyListener);
603         }
604
605         recomputeTitle();
606     }
607
608     /* (non-Javadoc)
609      * @see org.eclipse.ui.application.WorkbenchAdvisor#postWindowRestore
610      */
611     @Override
612     public void postWindowRestore()
613     throws WorkbenchException {
614         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
615         IWorkbenchWindow window = configurer.getWindow();
616
617         int index = getWorkbench().getWorkbenchWindowCount() - 1;
618
619         AboutInfo[] welcomePerspectiveInfos = wbAdvisor.getWelcomePerspectiveInfos();
620         if (index >= 0 && welcomePerspectiveInfos != null
621                 && index < welcomePerspectiveInfos.length) {
622             // find a page that exist in the window
623             IWorkbenchPage page = window.getActivePage();
624             if (page == null) {
625                 IWorkbenchPage[] pages = window.getPages();
626                 if (pages != null && pages.length > 0) {
627                     page = pages[0];
628                 }
629             }
630
631             // if the window does not contain a page, create one
632             String perspectiveId = welcomePerspectiveInfos[index].getWelcomePerspectiveId();
633             if (page == null) {
634                 IAdaptable root = wbAdvisor.getDefaultPageInput();
635                 page = window.openPage(perspectiveId, root);
636             } else {
637                 IPerspectiveRegistry reg = getWorkbench()
638                         .getPerspectiveRegistry();
639                 IPerspectiveDescriptor desc = reg
640                         .findPerspectiveWithId(perspectiveId);
641                 if (desc != null) {
642                     page.setPerspective(desc);
643                 }
644             }
645
646             // set the active page and open the welcome editor
647             window.setActivePage(page);
648             page.openEditor(new WelcomeEditorInput(
649                     welcomePerspectiveInfos[index]), WELCOME_EDITOR_ID, true);
650         }
651     }
652
653     /**
654      * Tries to open the intro, if one exists and otherwise will open the legacy
655      * Welcome pages.
656      * 
657      * @see org.eclipse.ui.application.WorkbenchWindowAdvisor#openIntro()
658      */
659     @Override
660     public void openIntro() {
661         if (editorsAndIntrosOpened ) {
662             return;
663         }
664
665         editorsAndIntrosOpened = true;
666
667         // don't try to open the welcome editors if there is an intro
668         if (wbAdvisor.hasIntro()) {
669             super.openIntro();
670         } else {
671             openWelcomeEditors(getWindowConfigurer().getWindow());
672             // save any preferences changes caused by the above actions
673             IDEWorkbenchPlugin.getDefault().savePluginPreferences();
674         }
675     }
676
677     /*
678      * Open the welcome editor for the primary feature and for any newly
679      * installed features.
680      */
681     private void openWelcomeEditors(IWorkbenchWindow window) {
682         if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(
683                 IDEInternalPreferences.WELCOME_DIALOG)) {
684             // show the welcome page for the product the first time the
685             // workbench opens
686             IProduct product = Platform.getProduct();
687             if (product == null) {
688                 return;
689             }
690
691             AboutInfo productInfo = new AboutInfo(product);
692             URL url = productInfo.getWelcomePageURL();
693             if (url == null) {
694                 return;
695             }
696
697             IDEWorkbenchPlugin.getDefault().getPreferenceStore().setValue(
698                     IDEInternalPreferences.WELCOME_DIALOG, false);
699             openWelcomeEditor(window, new WelcomeEditorInput(productInfo), null);
700         } else {
701             // Show the welcome page for any newly installed features
702             List<AboutInfo> welcomeFeatures = new ArrayList<AboutInfo>();
703             for (Iterator<?> it = wbAdvisor.getNewlyAddedBundleGroups().entrySet()
704                     .iterator(); it.hasNext();) {
705                 Map.Entry<?,?> entry = (Map.Entry<?,?>) it.next();
706                 AboutInfo info = (AboutInfo) entry.getValue();
707
708                 if (info != null && info.getWelcomePageURL() != null) {
709                     welcomeFeatures.add(info);
710                     // activate the feature plug-in so it can run some install
711                     // code
712                     String pi = info.getBrandingBundleId();
713                     if (pi != null) {
714                         // Start the bundle if there is one
715                         Bundle bundle = Platform.getBundle(pi);
716                         if (bundle != null) {
717                             try {
718                                 bundle.start(Bundle.START_TRANSIENT);
719                             } catch (BundleException exception) {
720                                 StatusManager
721                                 .getManager()
722                                 .handle(
723                                         new Status(
724                                                 IStatus.ERROR,
725                                                 Activator.PLUGIN_ID,
726                                                 "Failed to load feature", exception));//$NON-NLS-1$
727                             }
728                         }
729                     }
730                 }
731             }
732
733             int wCount = getWorkbench().getWorkbenchWindowCount();
734             for (int i = 0; i < welcomeFeatures.size(); i++) {
735                 AboutInfo newInfo = (AboutInfo) welcomeFeatures.get(i);
736                 String id = newInfo.getWelcomePerspectiveId();
737                 // Other editors were already opened in postWindowRestore(..)
738                 if (id == null || i >= wCount) {
739                     openWelcomeEditor(window, new WelcomeEditorInput(newInfo),
740                             id);
741                 }
742             }
743         }
744     }
745
746     /**
747      * Open a welcome editor for the given input
748      */
749     private void openWelcomeEditor(IWorkbenchWindow window,
750             WelcomeEditorInput input, String perspectiveId) {
751         if (getWorkbench().getWorkbenchWindowCount() == 0) {
752             // Something is wrong, there should be at least
753             // one workbench window open by now.
754             return;
755         }
756
757         IWorkbenchWindow win = window;
758         if (perspectiveId != null) {
759             try {
760                 win = getWorkbench().openWorkbenchWindow(perspectiveId,
761                         wbAdvisor.getDefaultPageInput());
762                 if (win == null) {
763                     win = window;
764                 }
765             } catch (WorkbenchException e) {
766                 IDEWorkbenchPlugin
767                 .log(
768                         "Error opening window with welcome perspective.", e.getStatus()); //$NON-NLS-1$
769                 return;
770             }
771         }
772
773         if (win == null) {
774             win = getWorkbench().getWorkbenchWindows()[0];
775         }
776
777         IWorkbenchPage page = win.getActivePage();
778         String id = perspectiveId;
779         if (id == null) {
780             id = getWorkbench().getPerspectiveRegistry()
781             .getDefaultPerspective();
782         }
783
784         if (page == null) {
785             try {
786                 page = win.openPage(id, wbAdvisor.getDefaultPageInput());
787             } catch (WorkbenchException e) {
788                 ErrorDialog.openError(win.getShell(),
789                         IDEWorkbenchMessages.Problems_Opening_Page, e
790                         .getMessage(), e.getStatus());
791             }
792         }
793         if (page == null) {
794             return;
795         }
796
797         if (page.getPerspective() == null) {
798             try {
799                 page = getWorkbench().showPerspective(id, win);
800             } catch (WorkbenchException e) {
801                 ErrorDialog
802                 .openError(
803                         win.getShell(),
804                         IDEWorkbenchMessages.Workbench_openEditorErrorDialogTitle,
805                         IDEWorkbenchMessages.Workbench_openEditorErrorDialogMessage,
806                         e.getStatus());
807                 return;
808             }
809         }
810
811         page.setEditorAreaVisible(true);
812
813         // see if we already have an editor
814         IEditorPart editor = page.findEditor(input);
815         if (editor != null) {
816             page.activate(editor);
817             return;
818         }
819
820         try {
821             page.openEditor(input, WELCOME_EDITOR_ID);
822         } catch (PartInitException e) {
823             ErrorDialog
824             .openError(
825                     win.getShell(),
826                     IDEWorkbenchMessages.Workbench_openEditorErrorDialogTitle,
827                     IDEWorkbenchMessages.Workbench_openEditorErrorDialogMessage,
828                     e.getStatus());
829         }
830         return;
831     }
832
833     /* (non-Javadoc)
834      * @see org.eclipse.ui.application.WorkbenchAdvisor#createEmptyWindowContents(org.eclipse.ui.application.IWorkbenchWindowConfigurer, org.eclipse.swt.widgets.Composite)
835      */
836     @Override
837     public Control createEmptyWindowContents(Composite parent) {
838         final IWorkbenchWindow window = getWindowConfigurer().getWindow();
839         Composite composite = new Composite(parent, SWT.NONE);
840         composite.setLayout(new GridLayout(2, false));
841         Display display = composite.getDisplay();
842         Color bgCol = display.getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND);
843         composite.setBackground(bgCol);
844         Label label = new Label(composite, SWT.WRAP);
845         label.setForeground(display.getSystemColor(SWT.COLOR_TITLE_INACTIVE_FOREGROUND));
846         label.setBackground(bgCol);
847         label.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
848         String msg = IDEWorkbenchMessages.IDEWorkbenchAdvisor_noPerspective;
849         label.setText(msg);
850         ToolBarManager toolBarManager = new ToolBarManager();
851         openPerspectiveAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG.create(window);
852         toolBarManager.add(openPerspectiveAction);
853         ToolBar toolBar = toolBarManager.createControl(composite);
854         toolBar.setBackground(bgCol);
855         return composite;
856     }
857
858     @Override
859     public void dispose() {
860         if (propertyChangeListener != null) {
861             IDEWorkbenchPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(propertyChangeListener);
862             propertyChangeListener = null;
863         }
864
865         if (openPerspectiveAction!=null) {
866             openPerspectiveAction.dispose();
867             openPerspectiveAction = null;
868         }
869         super.dispose();
870     }
871
872 }