74abd0c35e47d89bca18b3f53da5862f7aeca63a
[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                 title = NLS.bind(IDEWorkbenchMessages.WorkbenchWindow_shellTitle, lastEditorTitle, title);
521             }
522
523             boolean excludePerspectiveFromTitle = "true".equals(System.getProperty("org.simantics.workbench.application.excludePerspectiveFromTitle", "false").toLowerCase());
524             if (!excludePerspectiveFromTitle) {
525                 IPerspectiveDescriptor persp = currentPage.getPerspective();
526                 String label = ""; //$NON-NLS-1$
527                 if (persp != null) {
528                     label = persp.getLabel();
529                 }
530                 IAdaptable input = currentPage.getInput();
531                 if (input != null && !input.equals(wbAdvisor.getDefaultPageInput())) {
532                     label = currentPage.getLabel();
533                 }
534                 if (label != null && !label.equals("")) { //$NON-NLS-1$
535                     title = NLS.bind(IDEWorkbenchMessages.WorkbenchWindow_shellTitle, label, title);
536                 }
537             }
538         }
539
540         String workspaceLocation = wbAdvisor.getWorkspaceLocation();
541         if (workspaceLocation != null) {
542             title = NLS.bind(IDEWorkbenchMessages.WorkbenchWindow_shellTitle, title, workspaceLocation);
543         }
544
545         // Bug 284447: Prepend workspace name to the title
546         String workspaceName = IDEWorkbenchPlugin.getDefault()
547         .getPreferenceStore().getString(
548                 IDEInternalPreferences.WORKSPACE_NAME);
549         if (workspaceName != null && workspaceName.length() > 0) {
550             title = NLS.bind(IDEWorkbenchMessages.WorkbenchWindow_shellTitle,
551                     workspaceName, title);
552         }
553
554         return title;
555     }
556
557     private void recomputeTitle() {
558         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
559         String oldTitle = configurer.getTitle();
560         String newTitle = computeTitle();
561         if (!newTitle.equals(oldTitle)) {
562             configurer.setTitle(newTitle);
563         }
564     }
565
566     /**
567      * Updates the window title. Format will be:
568      * [pageInput -] [currentPerspective -] [editorInput -] [workspaceLocation -] productName
569      */
570     private void updateTitle(boolean force) {
571         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
572         IWorkbenchWindow window = configurer.getWindow();
573         IEditorPart activeEditor = null;
574         IWorkbenchPage currentPage = window.getActivePage();
575         IPerspectiveDescriptor persp = null;
576         IAdaptable input = null;
577
578         if (currentPage != null) {
579             activeEditor = currentPage.getActiveEditor();
580             persp = currentPage.getPerspective();
581             input = currentPage.getInput();
582         }
583
584         // Nothing to do if the editor hasn't changed or change is not forced.
585         if (!force && activeEditor == lastActiveEditor && currentPage == lastActivePage
586                 && persp == lastPerspective && input == lastInput) {
587             return;
588         }
589
590         if (lastActiveEditor != null) {
591             lastActiveEditor.removePropertyListener(editorPropertyListener );
592         }
593
594         lastActiveEditor = activeEditor;
595         lastActivePage = currentPage;
596         lastPerspective = persp;
597         lastInput = input;
598
599         if (activeEditor != null) {
600             activeEditor.addPropertyListener(editorPropertyListener);
601         }
602
603         recomputeTitle();
604     }
605
606     /* (non-Javadoc)
607      * @see org.eclipse.ui.application.WorkbenchAdvisor#postWindowRestore
608      */
609     @Override
610     public void postWindowRestore()
611     throws WorkbenchException {
612         IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
613         IWorkbenchWindow window = configurer.getWindow();
614
615         int index = getWorkbench().getWorkbenchWindowCount() - 1;
616
617         AboutInfo[] welcomePerspectiveInfos = wbAdvisor.getWelcomePerspectiveInfos();
618         if (index >= 0 && welcomePerspectiveInfos != null
619                 && index < welcomePerspectiveInfos.length) {
620             // find a page that exist in the window
621             IWorkbenchPage page = window.getActivePage();
622             if (page == null) {
623                 IWorkbenchPage[] pages = window.getPages();
624                 if (pages != null && pages.length > 0) {
625                     page = pages[0];
626                 }
627             }
628
629             // if the window does not contain a page, create one
630             String perspectiveId = welcomePerspectiveInfos[index].getWelcomePerspectiveId();
631             if (page == null) {
632                 IAdaptable root = wbAdvisor.getDefaultPageInput();
633                 page = window.openPage(perspectiveId, root);
634             } else {
635                 IPerspectiveRegistry reg = getWorkbench()
636                         .getPerspectiveRegistry();
637                 IPerspectiveDescriptor desc = reg
638                         .findPerspectiveWithId(perspectiveId);
639                 if (desc != null) {
640                     page.setPerspective(desc);
641                 }
642             }
643
644             // set the active page and open the welcome editor
645             window.setActivePage(page);
646             page.openEditor(new WelcomeEditorInput(
647                     welcomePerspectiveInfos[index]), WELCOME_EDITOR_ID, true);
648         }
649     }
650
651     /**
652      * Tries to open the intro, if one exists and otherwise will open the legacy
653      * Welcome pages.
654      * 
655      * @see org.eclipse.ui.application.WorkbenchWindowAdvisor#openIntro()
656      */
657     @Override
658     public void openIntro() {
659         if (editorsAndIntrosOpened ) {
660             return;
661         }
662
663         editorsAndIntrosOpened = true;
664
665         // don't try to open the welcome editors if there is an intro
666         if (wbAdvisor.hasIntro()) {
667             super.openIntro();
668         } else {
669             openWelcomeEditors(getWindowConfigurer().getWindow());
670             // save any preferences changes caused by the above actions
671             IDEWorkbenchPlugin.getDefault().savePluginPreferences();
672         }
673     }
674
675     /*
676      * Open the welcome editor for the primary feature and for any newly
677      * installed features.
678      */
679     private void openWelcomeEditors(IWorkbenchWindow window) {
680         if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(
681                 IDEInternalPreferences.WELCOME_DIALOG)) {
682             // show the welcome page for the product the first time the
683             // workbench opens
684             IProduct product = Platform.getProduct();
685             if (product == null) {
686                 return;
687             }
688
689             AboutInfo productInfo = new AboutInfo(product);
690             URL url = productInfo.getWelcomePageURL();
691             if (url == null) {
692                 return;
693             }
694
695             IDEWorkbenchPlugin.getDefault().getPreferenceStore().setValue(
696                     IDEInternalPreferences.WELCOME_DIALOG, false);
697             openWelcomeEditor(window, new WelcomeEditorInput(productInfo), null);
698         } else {
699             // Show the welcome page for any newly installed features
700             List<AboutInfo> welcomeFeatures = new ArrayList<AboutInfo>();
701             for (Iterator<?> it = wbAdvisor.getNewlyAddedBundleGroups().entrySet()
702                     .iterator(); it.hasNext();) {
703                 Map.Entry<?,?> entry = (Map.Entry<?,?>) it.next();
704                 AboutInfo info = (AboutInfo) entry.getValue();
705
706                 if (info != null && info.getWelcomePageURL() != null) {
707                     welcomeFeatures.add(info);
708                     // activate the feature plug-in so it can run some install
709                     // code
710                     String pi = info.getBrandingBundleId();
711                     if (pi != null) {
712                         // Start the bundle if there is one
713                         Bundle bundle = Platform.getBundle(pi);
714                         if (bundle != null) {
715                             try {
716                                 bundle.start(Bundle.START_TRANSIENT);
717                             } catch (BundleException exception) {
718                                 StatusManager
719                                 .getManager()
720                                 .handle(
721                                         new Status(
722                                                 IStatus.ERROR,
723                                                 Activator.PLUGIN_ID,
724                                                 "Failed to load feature", exception));//$NON-NLS-1$
725                             }
726                         }
727                     }
728                 }
729             }
730
731             int wCount = getWorkbench().getWorkbenchWindowCount();
732             for (int i = 0; i < welcomeFeatures.size(); i++) {
733                 AboutInfo newInfo = (AboutInfo) welcomeFeatures.get(i);
734                 String id = newInfo.getWelcomePerspectiveId();
735                 // Other editors were already opened in postWindowRestore(..)
736                 if (id == null || i >= wCount) {
737                     openWelcomeEditor(window, new WelcomeEditorInput(newInfo),
738                             id);
739                 }
740             }
741         }
742     }
743
744     /**
745      * Open a welcome editor for the given input
746      */
747     private void openWelcomeEditor(IWorkbenchWindow window,
748             WelcomeEditorInput input, String perspectiveId) {
749         if (getWorkbench().getWorkbenchWindowCount() == 0) {
750             // Something is wrong, there should be at least
751             // one workbench window open by now.
752             return;
753         }
754
755         IWorkbenchWindow win = window;
756         if (perspectiveId != null) {
757             try {
758                 win = getWorkbench().openWorkbenchWindow(perspectiveId,
759                         wbAdvisor.getDefaultPageInput());
760                 if (win == null) {
761                     win = window;
762                 }
763             } catch (WorkbenchException e) {
764                 IDEWorkbenchPlugin
765                 .log(
766                         "Error opening window with welcome perspective.", e.getStatus()); //$NON-NLS-1$
767                 return;
768             }
769         }
770
771         if (win == null) {
772             win = getWorkbench().getWorkbenchWindows()[0];
773         }
774
775         IWorkbenchPage page = win.getActivePage();
776         String id = perspectiveId;
777         if (id == null) {
778             id = getWorkbench().getPerspectiveRegistry()
779             .getDefaultPerspective();
780         }
781
782         if (page == null) {
783             try {
784                 page = win.openPage(id, wbAdvisor.getDefaultPageInput());
785             } catch (WorkbenchException e) {
786                 ErrorDialog.openError(win.getShell(),
787                         IDEWorkbenchMessages.Problems_Opening_Page, e
788                         .getMessage(), e.getStatus());
789             }
790         }
791         if (page == null) {
792             return;
793         }
794
795         if (page.getPerspective() == null) {
796             try {
797                 page = getWorkbench().showPerspective(id, win);
798             } catch (WorkbenchException e) {
799                 ErrorDialog
800                 .openError(
801                         win.getShell(),
802                         IDEWorkbenchMessages.Workbench_openEditorErrorDialogTitle,
803                         IDEWorkbenchMessages.Workbench_openEditorErrorDialogMessage,
804                         e.getStatus());
805                 return;
806             }
807         }
808
809         page.setEditorAreaVisible(true);
810
811         // see if we already have an editor
812         IEditorPart editor = page.findEditor(input);
813         if (editor != null) {
814             page.activate(editor);
815             return;
816         }
817
818         try {
819             page.openEditor(input, WELCOME_EDITOR_ID);
820         } catch (PartInitException e) {
821             ErrorDialog
822             .openError(
823                     win.getShell(),
824                     IDEWorkbenchMessages.Workbench_openEditorErrorDialogTitle,
825                     IDEWorkbenchMessages.Workbench_openEditorErrorDialogMessage,
826                     e.getStatus());
827         }
828         return;
829     }
830
831     /* (non-Javadoc)
832      * @see org.eclipse.ui.application.WorkbenchAdvisor#createEmptyWindowContents(org.eclipse.ui.application.IWorkbenchWindowConfigurer, org.eclipse.swt.widgets.Composite)
833      */
834     @Override
835     public Control createEmptyWindowContents(Composite parent) {
836         final IWorkbenchWindow window = getWindowConfigurer().getWindow();
837         Composite composite = new Composite(parent, SWT.NONE);
838         composite.setLayout(new GridLayout(2, false));
839         Display display = composite.getDisplay();
840         Color bgCol = display.getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND);
841         composite.setBackground(bgCol);
842         Label label = new Label(composite, SWT.WRAP);
843         label.setForeground(display.getSystemColor(SWT.COLOR_TITLE_INACTIVE_FOREGROUND));
844         label.setBackground(bgCol);
845         label.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
846         String msg = IDEWorkbenchMessages.IDEWorkbenchAdvisor_noPerspective;
847         label.setText(msg);
848         ToolBarManager toolBarManager = new ToolBarManager();
849         openPerspectiveAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG.create(window);
850         toolBarManager.add(openPerspectiveAction);
851         ToolBar toolBar = toolBarManager.createControl(composite);
852         toolBar.setBackground(bgCol);
853         return composite;
854     }
855
856     @Override
857     public void dispose() {
858         if (propertyChangeListener != null) {
859             IDEWorkbenchPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(propertyChangeListener);
860             propertyChangeListener = null;
861         }
862
863         if (openPerspectiveAction!=null) {
864             openPerspectiveAction.dispose();
865             openPerspectiveAction = null;
866         }
867         super.dispose();
868     }
869
870 }