]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/TabbedPropertyPageViewSite.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / TabbedPropertyPageViewSite.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.browsing.ui.swt;
13
14 /*******************************************************************************
15  * Copyright (c) 2000, 2008 IBM Corporation and others.
16  * All rights reserved. This program and the accompanying materials
17  * are made available under the terms of the Eclipse Public License v1.0
18  * which accompanies this distribution, and is available at
19  * http://www.eclipse.org/legal/epl-v10.html
20  *
21  * Contributors:
22  *     IBM Corporation - initial API and implementation
23  *******************************************************************************/
24
25 import java.util.ArrayList;
26
27 import org.eclipse.core.runtime.Assert;
28 import org.eclipse.e4.core.contexts.IEclipseContext;
29 import org.eclipse.jface.action.MenuManager;
30 import org.eclipse.jface.viewers.ILabelDecorator;
31 import org.eclipse.jface.viewers.IPostSelectionProvider;
32 import org.eclipse.jface.viewers.ISelectionChangedListener;
33 import org.eclipse.jface.viewers.ISelectionProvider;
34 import org.eclipse.jface.viewers.SelectionChangedEvent;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.ui.IActionBars;
37 import org.eclipse.ui.IEditorActionBarContributor;
38 import org.eclipse.ui.IKeyBindingService;
39 import org.eclipse.ui.INestableKeyBindingService;
40 import org.eclipse.ui.IViewPart;
41 import org.eclipse.ui.IViewSite;
42 import org.eclipse.ui.IWorkbenchPage;
43 import org.eclipse.ui.IWorkbenchPart;
44 import org.eclipse.ui.IWorkbenchWindow;
45 import org.eclipse.ui.internal.PartSite;
46 import org.eclipse.ui.internal.PopupMenuExtender;
47 import org.eclipse.ui.internal.WorkbenchPlugin;
48 import org.eclipse.ui.internal.services.INestable;
49 import org.eclipse.ui.internal.services.IServiceLocatorCreator;
50 import org.eclipse.ui.internal.services.ServiceLocator;
51 import org.eclipse.ui.part.MultiPageEditorSite;
52 import org.eclipse.ui.services.IDisposable;
53 import org.eclipse.ui.services.IServiceLocator;
54
55 /**
56  * Site for a nested editor within a multi-page editor. Selection is handled by
57  * forwarding the event to the multi-page editor's selection listeners; most
58  * other methods are forwarded to the multi-page editor's site.
59  * <p>
60  * The base implementation of <code>MultiPageEditor.createSite</code> creates
61  * an instance of this class. This class may be instantiated or subclassed.
62  * </p>
63  * 
64  * TODO: copy e4 changes from MultiPageEditorSite to this class as seen fit
65  */
66 @SuppressWarnings({"restriction","deprecation","rawtypes"})
67 public class TabbedPropertyPageViewSite implements IViewSite, INestable {
68
69     /**
70      * The nested editor.
71      */
72     private final IViewPart editor;
73
74     /**
75      * The list of popup menu extenders; <code>null</code> if none registered.
76      */
77     private ArrayList menuExtenders;
78
79     /**
80      * The multi-page editor.
81      */
82     private final TabbedPropertyPage multiPageEditor;
83
84     /**
85      * The post selection changed listener.
86      */
87     private ISelectionChangedListener postSelectionChangedListener = null;
88
89     /**
90      * The selection change listener, initialized lazily; <code>null</code> if
91      * not yet created.
92      */
93     private ISelectionChangedListener selectionChangedListener = null;
94
95     /**
96      * The selection provider; <code>null</code> if none.
97      * 
98      * @see MultiPageEditorSite#setSelectionProvider(ISelectionProvider)
99      */
100     private ISelectionProvider selectionProvider = null;
101
102     /**
103      * The cached copy of the key binding service specific to this multi-page
104      * editor site. This value is <code>null</code> if it is not yet
105      * initialized.
106      */
107     private IKeyBindingService service = null;
108
109     /**
110      * The local service locator for this multi-page editor site. This value is
111      * never <code>null</code>.
112      */
113     private final ServiceLocator serviceLocator;
114
115         private IEclipseContext e4Context;
116
117     /**
118      * Creates a site for the given editor nested within the given multi-page
119      * editor.
120      * 
121      * @param multiPageEditor
122      *            the multi-page editor
123      * @param editor
124      *            the nested editor
125      */
126     public TabbedPropertyPageViewSite(TabbedPropertyPage multiPageEditor,
127             IViewPart editor) {
128         Assert.isNotNull(multiPageEditor);
129         Assert.isNotNull(editor);
130         this.multiPageEditor = multiPageEditor;
131         this.editor = editor;
132
133         final IServiceLocator parentServiceLocator = multiPageEditor.getSite();
134         IServiceLocatorCreator slc = (IServiceLocatorCreator) parentServiceLocator
135         .getService(IServiceLocatorCreator.class);
136         this.serviceLocator = (ServiceLocator) slc.createServiceLocator(
137                 parentServiceLocator, null, new IDisposable() {
138                     @Override
139                     public void dispose() {
140 //                        final Control control = ((PartSite)getMultiPageEditor().getSite()).getPane().getControl();
141 //                        if (control != null && !control.isDisposed()) {
142 //                            ((PartSite)getMultiPageEditor().getSite()).getPane().doHide();
143 //                        }
144                     }
145                 });
146         e4Context = ((PartSite)editor.getViewSite()).getContext().createChild("TabbedPropertyPageViewSite");
147         serviceLocator.setContext(e4Context);
148         initializeDefaultServices();
149     }
150
151     /**
152      * Initialize the slave services for this site.
153      */
154     private void initializeDefaultServices() {
155 //        serviceLocator.registerService(IMultiPageEditorSiteHolder.class,
156 //                new ITabbedPropertyPageSiteHolder() {
157 //                    public TabbedPropertyPageViewSite getSite() {
158 //                        return TabbedPropertyPageViewSite.this;
159 //                    }
160 //                });
161         // Not possible to initialize this service for a view site:
162 //              serviceLocator.registerService(IWorkbenchLocationService.class,
163 //                              new WorkbenchLocationService(IServiceScopes.MPESITE_SCOPE,
164 //                                              getWorkbenchWindow().getWorkbench(),
165 //                                              getWorkbenchWindow(), getMultiPageEditor().getSite(),
166 //                                              this, null, 3));
167     }
168
169     /**
170      * Notifies the multi page editor service that the component within which it
171      * exists has become active.
172      * 
173      * @since 3.2
174      */
175     public final void activate() {
176         e4Context.activate();
177         serviceLocator.activate();
178     }
179
180     /**
181      * Notifies the multi page editor service that the component within which it
182      * exists has been deactived.
183      * 
184      * @since 3.2
185      */
186     public final void deactivate() {
187         serviceLocator.deactivate();
188         e4Context.deactivate();
189     }
190
191     /**
192      * Dispose the contributions.
193      */
194     public void dispose() {
195         if (menuExtenders != null) {
196             for (int i = 0; i < menuExtenders.size(); i++) {
197                 ((PopupMenuExtender) menuExtenders.get(i)).dispose();
198             }
199             menuExtenders = null;
200         }
201
202         // Remove myself from the list of nested key binding services.
203         if (service != null) {
204             IKeyBindingService parentService = getMultiPageEditor().getSite()
205             .getKeyBindingService();
206             if (parentService instanceof INestableKeyBindingService) {
207                 INestableKeyBindingService nestableParent = (INestableKeyBindingService) parentService;
208                 nestableParent.removeKeyBindingService(this);
209             }
210             service = null;
211         }
212
213         if (serviceLocator != null) {
214             serviceLocator.dispose();
215         }
216         e4Context.dispose();
217     }
218
219     /**
220      * The <code>MultiPageEditorSite</code> implementation of this
221      * <code>IEditorSite</code> method returns <code>null</code>, since
222      * nested editors do not have their own action bar contributor.
223      * 
224      * @return <code>null</code>
225      */
226     public IEditorActionBarContributor getActionBarContributor() {
227         return null;
228     }
229
230     /**
231      * The <code>MultiPageEditorSite</code> implementation of this
232      * <code>IEditorSite</code> method forwards to the multi-page editor to
233      * return the action bars.
234      * 
235      * @return The action bars from the parent multi-page editor.
236      */
237     public IActionBars getActionBars() {
238         return ((IViewSite)multiPageEditor.getSite()).getActionBars();
239     }
240
241     /*
242      * (non-Javadoc)
243      * 
244      * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
245      */
246     public Object getAdapter(Class adapter) {
247         return null;
248     }
249
250     /**
251      * The <code>MultiPageEditorSite</code> implementation of this
252      * <code>IWorkbenchPartSite</code> method forwards to the multi-page
253      * editor to return the decorator manager.
254      * 
255      * @return The decorator from the workbench window.
256      * @deprecated use IWorkbench.getDecoratorManager()
257      */
258     @Deprecated
259     public ILabelDecorator getDecoratorManager() {
260         return getWorkbenchWindow().getWorkbench().getDecoratorManager()
261         .getLabelDecorator();
262     }
263
264 //    /**
265 //     * Returns the nested editor.
266 //     *
267 //     * @return the nested editor
268 //     */
269 //    public IEditorPart getEditor() {
270 //        return editor;
271 //    }
272
273     /**
274      * The <code>MultiPageEditorSite</code> implementation of this
275      * <code>IWorkbenchPartSite</code> method returns an empty string since
276      * the nested editor is not created from the registry.
277      * 
278      * @return An empty string.
279      */
280     public String getId() {
281         return ""; //$NON-NLS-1$
282     }
283
284     /*
285      * (non-Javadoc) Method declared on IEditorSite.
286      */
287     public IKeyBindingService getKeyBindingService() {
288         if (service == null) {
289             service = getMultiPageEditor().getSite()
290             .getKeyBindingService();
291             if (service instanceof INestableKeyBindingService) {
292                 INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
293                 service = nestableService.getKeyBindingService(this);
294
295             } else {
296                 /*
297                  * This is an internal reference, and should not be copied by
298                  * client code. If you are thinking of copying this, DON'T DO
299                  * IT.
300                  */
301                 WorkbenchPlugin
302                 .log("MultiPageEditorSite.getKeyBindingService()   Parent key binding service was not an instance of INestableKeyBindingService.  It was an instance of " + service.getClass().getName() + " instead."); //$NON-NLS-1$ //$NON-NLS-2$
303             }
304         }
305         return service;
306     }
307
308     /**
309      * Returns the multi-page editor.
310      * 
311      * @return the multi-page editor
312      */
313     public TabbedPropertyPage getMultiPageEditor() {
314         return multiPageEditor;
315     }
316
317     /**
318      * The <code>MultiPageEditorSite</code> implementation of this
319      * <code>IWorkbenchPartSite</code> method forwards to the multi-page
320      * editor to return the workbench page.
321      * 
322      * @return The workbench page in which this editor site resides.
323      */
324     public IWorkbenchPage getPage() {
325         return getMultiPageEditor().getSite().getPage();
326     }
327
328     /*
329      * (non-Javadoc)
330      * 
331      * @see org.eclipse.ui.IWorkbenchPartSite#getPart()
332      */
333     public IWorkbenchPart getPart() {
334         return editor;
335     }
336
337     /**
338      * The <code>MultiPageEditorSite</code> implementation of this
339      * <code>IWorkbenchPartSite</code> method returns an empty string since
340      * the nested editor is not created from the registry.
341      * 
342      * @return An empty string.
343      */
344     public String getPluginId() {
345         return ""; //$NON-NLS-1$
346     }
347
348     /**
349      * Returns the post selection change listener which listens to the nested
350      * editor's selection changes.
351      * 
352      * @return the post selection change listener.
353      */
354     private ISelectionChangedListener getPostSelectionChangedListener() {
355         if (postSelectionChangedListener == null) {
356             postSelectionChangedListener = new ISelectionChangedListener() {
357                 public void selectionChanged(SelectionChangedEvent event) {
358                     TabbedPropertyPageViewSite.this.handlePostSelectionChanged(event);
359                 }
360             };
361         }
362         return postSelectionChangedListener;
363     }
364
365     /**
366      * The <code>MultiPageEditorSite</code> implementation of this
367      * <code>IWorkbenchPartSite</code> method returns an empty string since
368      * the nested editor is not created from the registry.
369      * 
370      * @return An empty string.
371      */
372     public String getRegisteredName() {
373         return ""; //$NON-NLS-1$
374     }
375
376     /**
377      * Returns the selection changed listener which listens to the nested
378      * editor's selection changes, and calls <code>handleSelectionChanged</code>.
379      * 
380      * @return the selection changed listener
381      */
382     private ISelectionChangedListener getSelectionChangedListener() {
383         if (selectionChangedListener == null) {
384             selectionChangedListener = new ISelectionChangedListener() {
385                 public void selectionChanged(SelectionChangedEvent event) {
386                     TabbedPropertyPageViewSite.this.handleSelectionChanged(event);
387                 }
388             };
389         }
390         return selectionChangedListener;
391     }
392
393     /**
394      * The <code>MultiPageEditorSite</code> implementation of this
395      * <code>IWorkbenchPartSite</code> method returns the selection provider
396      * set by <code>setSelectionProvider</code>.
397      * 
398      * @return The current selection provider.
399      */
400     public ISelectionProvider getSelectionProvider() {
401         return selectionProvider;
402     }
403
404     public final Object getService(final Class key) {
405         return serviceLocator.getService(key);
406     }
407
408     /**
409      * The <code>MultiPageEditorSite</code> implementation of this
410      * <code>IWorkbenchPartSite</code> method forwards to the multi-page
411      * editor to return the shell.
412      * 
413      * @return The shell in which this editor site resides.
414      */
415     public Shell getShell() {
416         return getMultiPageEditor().getSite().getShell();
417     }
418
419     /**
420      * The <code>MultiPageEditorSite</code> implementation of this
421      * <code>IWorkbenchPartSite</code> method forwards to the multi-page
422      * editor to return the workbench window.
423      * 
424      * @return The workbench window in which this editor site resides.
425      */
426     public IWorkbenchWindow getWorkbenchWindow() {
427         return getMultiPageEditor().getSite().getWorkbenchWindow();
428     }
429
430     /**
431      * Handles a post selection changed even from the nexted editor.
432      * <p>
433      * Subclasses may extend or reimplement this method
434      * 
435      * @param event  the event
436      * 
437      * @since 3.2
438      */
439     protected void handlePostSelectionChanged(SelectionChangedEvent event) {
440         ISelectionProvider parentProvider = getMultiPageEditor().getSite()
441         .getSelectionProvider();
442         if (parentProvider instanceof TabbedPageSelectionProvider) {
443             SelectionChangedEvent newEvent = new SelectionChangedEvent(
444                     parentProvider, event.getSelection());
445             TabbedPageSelectionProvider prov = (TabbedPageSelectionProvider) parentProvider;
446             prov.firePostSelectionChanged(newEvent);
447         }
448     }
449
450     /**
451      * Handles a selection changed event from the nested editor. The default
452      * implementation gets the selection provider from the multi-page editor's
453      * site, and calls <code>fireSelectionChanged</code> on it (only if it is
454      * an instance of <code>MultiPageSelectionProvider</code>), passing a new
455      * event object.
456      * <p>
457      * Subclasses may extend or reimplement this method.
458      * </p>
459      * 
460      * @param event
461      *            the event
462      */
463     protected void handleSelectionChanged(SelectionChangedEvent event) {
464         ISelectionProvider parentProvider = getMultiPageEditor().getSite()
465         .getSelectionProvider();
466         if (parentProvider instanceof TabbedPageSelectionProvider) {
467             SelectionChangedEvent newEvent = new SelectionChangedEvent(
468                     parentProvider, event.getSelection());
469             TabbedPageSelectionProvider prov = (TabbedPageSelectionProvider) parentProvider;
470             prov.fireSelectionChanged(newEvent);
471         }
472     }
473
474     public final boolean hasService(final Class key) {
475         return serviceLocator.hasService(key);
476     }
477
478     /**
479      * The <code>MultiPageEditorSite</code> implementation of this
480      * <code>IWorkbenchPartSite</code> method forwards to the multi-page
481      * editor for registration.
482      * 
483      * @param menuManager
484      *            The menu manager
485      * @param selProvider
486      *            The selection provider.
487      */
488     public void registerContextMenu(MenuManager menuManager,
489             ISelectionProvider selProvider) {
490         getMultiPageEditor().getSite().registerContextMenu(menuManager,
491                 selProvider);
492     }
493
494     public final void registerContextMenu(final MenuManager menuManager,
495             final ISelectionProvider selectionProvider,
496             final boolean includeEditorInput) {
497         registerContextMenu(getId(), menuManager, selectionProvider,
498                 includeEditorInput);
499     }
500
501     /**
502      * The <code>MultiPageEditorSite</code> implementation of this
503      * <code>IWorkbenchPartSite</code> method forwards to the multi-page
504      * editor for registration.
505      * 
506      * @param menuID
507      *            The identifier for the menu.
508      * @param menuMgr
509      *            The menu manager
510      * @param selProvider
511      *            The selection provider.
512      */
513     public void registerContextMenu(String menuID, MenuManager menuMgr,
514             ISelectionProvider selProvider) {
515         if (menuExtenders == null) {
516             menuExtenders = new ArrayList(1);
517         }
518         PartSite.registerContextMenu(menuID, menuMgr, selProvider, true,
519                 editor, e4Context, menuExtenders);
520     }
521
522     public final void registerContextMenu(final String menuId,
523             final MenuManager menuManager,
524             final ISelectionProvider selectionProvider,
525             final boolean includeEditorInput) {
526         if (menuExtenders == null) {
527             menuExtenders = new ArrayList(1);
528         }
529         PartSite.registerContextMenu(menuId, menuManager, selectionProvider,
530                 includeEditorInput, editor, e4Context, menuExtenders);
531     }
532
533     /**
534      * The <code>MultiPageEditorSite</code> implementation of this
535      * <code>IWorkbenchPartSite</code> method remembers the selection
536      * provider, and also hooks a listener on it, which calls
537      * <code>handleSelectionChanged</code> when a selection changed event
538      * occurs.
539      * 
540      * @param provider
541      *            The selection provider.
542      * @see MultiPageEditorSite#handleSelectionChanged(SelectionChangedEvent)
543      */
544     public void setSelectionProvider(ISelectionProvider provider) {
545         ISelectionProvider oldSelectionProvider = selectionProvider;
546         selectionProvider = provider;
547         if (oldSelectionProvider != null) {
548             oldSelectionProvider
549             .removeSelectionChangedListener(getSelectionChangedListener());
550             if (oldSelectionProvider instanceof IPostSelectionProvider) {
551                 ((IPostSelectionProvider) oldSelectionProvider)
552                 .removePostSelectionChangedListener(getPostSelectionChangedListener());
553             }
554         }
555         if (selectionProvider != null) {
556             selectionProvider
557             .addSelectionChangedListener(getSelectionChangedListener());
558             if (selectionProvider instanceof IPostSelectionProvider) {
559                 ((IPostSelectionProvider) selectionProvider)
560                 .addPostSelectionChangedListener(getPostSelectionChangedListener());
561             }
562         }
563     }
564
565     @Override
566     public String getSecondaryId() {
567         return ((IViewSite)multiPageEditor.getSite()).getSecondaryId();
568     }
569
570 }