1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.browsing.ui.swt;
15 /*******************************************************************************
16 * Copyright (c) 2000, 2008 IBM Corporation and others.
17 * All rights reserved. This program and the accompanying materials
18 * are made available under the terms of the Eclipse Public License v1.0
19 * which accompanies this distribution, and is available at
20 * http://www.eclipse.org/legal/epl-v10.html
23 * IBM Corporation - initial API and implementation
24 *******************************************************************************/
26 import java.util.ArrayList;
27 import java.util.List;
29 import org.eclipse.core.commands.util.Tracing;
30 import org.eclipse.core.runtime.Adapters;
31 import org.eclipse.core.runtime.Assert;
32 import org.eclipse.core.runtime.ISafeRunnable;
33 import org.eclipse.core.runtime.SafeRunner;
34 import org.eclipse.jface.resource.ImageDescriptor;
35 import org.eclipse.jface.viewers.ISelectionProvider;
36 import org.eclipse.jface.viewers.SelectionChangedEvent;
37 import org.eclipse.swt.SWT;
38 import org.eclipse.swt.custom.CTabFolder;
39 import org.eclipse.swt.custom.CTabItem;
40 import org.eclipse.swt.events.SelectionAdapter;
41 import org.eclipse.swt.events.SelectionEvent;
42 import org.eclipse.swt.graphics.Image;
43 import org.eclipse.swt.layout.FillLayout;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Control;
46 import org.eclipse.swt.widgets.Display;
47 import org.eclipse.swt.widgets.Item;
48 import org.eclipse.ui.IEditorInput;
49 import org.eclipse.ui.IEditorPart;
50 import org.eclipse.ui.IKeyBindingService;
51 import org.eclipse.ui.IMemento;
52 import org.eclipse.ui.INestableKeyBindingService;
53 import org.eclipse.ui.IPartService;
54 import org.eclipse.ui.IViewPart;
55 import org.eclipse.ui.IViewSite;
56 import org.eclipse.ui.IWorkbenchPart;
57 import org.eclipse.ui.IWorkbenchPartSite;
58 import org.eclipse.ui.PartInitException;
59 import org.eclipse.ui.internal.WorkbenchPlugin;
60 import org.eclipse.ui.internal.misc.Policy;
61 import org.eclipse.ui.internal.services.INestable;
62 import org.eclipse.ui.internal.services.IServiceLocatorCreator;
63 import org.eclipse.ui.internal.util.Util;
64 import org.eclipse.ui.part.MultiPageEditorPart;
65 import org.eclipse.ui.part.MultiPageEditorSite;
66 import org.eclipse.ui.part.MultiPageSelectionProvider;
67 import org.eclipse.ui.part.PageSwitcher;
68 import org.eclipse.ui.part.ViewPart;
69 import org.eclipse.ui.services.IDisposable;
70 import org.eclipse.ui.services.IServiceLocator;
73 * A multi-page editor is an editor with multiple pages, each of which may
74 * contain an editor or an arbitrary SWT control.
76 * Subclasses must implement the following methods:
78 * <li><code>createPages</code> - to create the required pages by calling one
79 * of the <code>addPage</code> methods</li>
80 * <li><code>IEditorPart.doSave</code> - to save contents of editor</li>
81 * <li><code>IEditorPart.doSaveAs</code> - to save contents of editor</li>
82 * <li><code>IEditorPart.isSaveAsAllowed</code> - to enable Save As</li>
83 * <li><code>IEditorPart.gotoMarker</code> - to scroll to a marker</li>
87 * Multi-page editors have a single action bar contributor, which manages
88 * contributions for all the pages. The contributor must be a subclass of
89 * <code>AbstractMultiPageEditorActionBarContributor</code>. Note that since
90 * any nested editors are created directly in code by callers of
91 * <code>addPage(IEditorPart,IEditorInput)</code>, nested editors do not have
92 * their own contributors.
95 * @see org.eclipse.ui.part.MultiPageEditorActionBarContributor
97 * NOTE: this class was originally copied from MultiPageEditorPart and adapter to work as a ViewPart.
99 @SuppressWarnings({"restriction","deprecation","unchecked","rawtypes"})
100 public abstract class TabbedPropertyPage extends ViewPart {
103 * Subclasses that override {@link #createPageContainer(Composite)} can use
104 * this constant to get a site for the container that can be active while
105 * the current page is deactivated.
108 * @see #activateSite()
109 * @see #deactivateSite(boolean, boolean)
110 * @see #getPageSite(int)
112 protected static final int PAGE_CONTAINER_SITE = 65535;
115 * Private tracing output.
117 private static final String TRACING_COMPONENT = "MPE"; //$NON-NLS-1$
120 * The active service locator. This value may be <code>null</code> if
121 * there is no selected page, or if the selected page is a control with
124 private INestable activeServiceLocator;
127 * The container widget.
129 private CTabFolder container;
130 private Composite pageContainer;
133 * List of nested editors. Element type: IEditorPart. Need to hang onto them
134 * here, in addition to using get/setData on the items, because dispose()
135 * needs to access them, but widgetry has already been disposed at that
138 private final ArrayList nestedEditors = new ArrayList(3);
140 private final List pageSites = new ArrayList(3);
142 private IServiceLocator pageContainerSite;
145 * Creates and adds a new page containing the given control to this
146 * multi-page editor. The control may be <code>null</code>, allowing it
147 * to be created and set later using <code>setControl</code>.
150 * the control, or <code>null</code>
151 * @return the index of the new page
153 * @see MultiPageEditorPart#setControl(int, Control)
155 public int addPage(Control control) {
156 int index = getPageCount();
157 addPage(index, control);
162 * @param control the control to add as a page
163 * @param text the page title text
164 * @param image the page title image
167 public int addPage(Control control, String text, Image image) {
168 int result = addPage(control);
169 setPageText(result, text);
170 setPageImage(result, image);
175 * Creates and adds a new page containing the given control to this
176 * multi-page editor. The page is added at the given index. The control may
177 * be <code>null</code>, allowing it to be created and set later using
178 * <code>setControl</code>.
181 * the index at which to add the page (0-based)
183 * the control, or <code>null</code>
185 * @see MultiPageEditorPart#setControl(int, Control)
187 public void addPage(int index, Control control) {
188 createItem(index, control);
192 * Creates an empty container. Creates a CTabFolder with no style bits set,
193 * and hooks a selection listener which calls <code>pageChange()</code>
194 * whenever the selected tab changes.
197 * The composite in which the container tab folder should be
198 * created; must not be <code>null</code>.
199 * @return a new container
201 private CTabFolder createContainer(Composite parent) {
202 // use SWT.FLAT style so that an extra 1 pixel border is not reserved
204 parent.setLayout(new FillLayout());
205 final CTabFolder newContainer = new CTabFolder(parent, getContainerStyle());
206 newContainer.addSelectionListener(new SelectionAdapter() {
208 public void widgetSelected(SelectionEvent e) {
209 int newPageIndex = newContainer.indexOf((CTabItem) e.item);
210 pageChange(newPageIndex);
217 * Override this to customize the style given to the container
218 * {@link CTabFolder} instance created by
219 * {@link #createContainer(Composite)}. Default value is {@value SWT#BOTTOM}
220 * | {@value SWT#FLAT}.
222 * @return swt style mask for {@link CTabFolder}
224 protected int getContainerStyle() {
225 return SWT.BOTTOM | SWT.FLAT;
229 * Creates a tab item at the given index and places the given control in the
230 * new item. The item is a CTabItem with no style bits set.
233 * the index at which to add the control
235 * is the control to be placed in an item
238 private CTabItem createItem(int index, Control control) {
239 CTabItem item = new CTabItem(getTabFolder(), SWT.NONE, index);
240 item.setControl(control);
245 * Creates the pages of this multi-page editor.
247 * Subclasses must implement this method.
250 protected abstract void createPages();
253 * The <code>MultiPageEditor</code> implementation of this
254 * <code>IWorkbenchPart</code> method creates the control for the
255 * multi-page editor by calling <code>createContainer</code>, then
256 * <code>createPages</code>. Subclasses should implement
257 * <code>createPages</code> rather than overriding this method.
260 * The parent in which the editor should be created; must not be
264 public final void createPartControl(Composite parent) {
265 this.pageContainer = createPageContainer(parent);
266 this.container = createContainer(pageContainer);
268 // set the active page (page 0 by default), unless it has already been
270 if (getActivePage() == -1) {
272 IViewSite site = getViewSite();
274 final IServiceLocator serviceLocator = site;
275 if (serviceLocator instanceof INestable) {
276 activeServiceLocator = (INestable) serviceLocator;
277 activeServiceLocator.activate();
281 initializePageSwitching();
285 * Initialize the MultiPageEditorPart to use the page switching command.
286 * Clients can override this method with an empty body if they wish to
291 protected void initializePageSwitching() {
292 new PageSwitcher(getSite().getPart()) {
294 public Object[] getPages() {
295 int pageCount = getPageCount();
296 Object[] result = new Object[pageCount];
297 for (int i = 0; i < pageCount; i++) {
298 result[i] = new Integer(i);
304 public String getName(Object page) {
305 return getPageText(((Integer) page).intValue());
309 public ImageDescriptor getImageDescriptor(Object page) {
310 Image image = getPageImage(((Integer) page).intValue());
314 return ImageDescriptor.createFromImage(image);
318 public void activatePage(Object page) {
319 setActivePage(((Integer) page).intValue());
323 public int getCurrentPageIndex() {
324 return getActivePage();
330 * Creates the parent control for the container returned by
331 * {@link #getContainer() }.
334 * Subclasses may extend and must call super implementation first.
338 * the parent for all of the editors contents.
339 * @return the parent for this editor's container. Must not be
344 protected Composite createPageContainer(Composite parent) {
348 public Composite getPageContainer() {
349 return pageContainer;
353 * Creates the site for the given nested editor. The
354 * <code>MultiPageEditorPart</code> implementation of this method creates
355 * an instance of <code>MultiPageEditorSite</code>. Subclasses may
356 * reimplement to create more specialized sites.
360 * @return the editor site
362 protected IViewSite createSite(IViewPart editor) {
363 return new TabbedPropertyPageViewSite(this, editor);
367 * The <code>MultiPageEditorPart</code> implementation of this
368 * <code>IWorkbenchPart</code> method disposes all nested editors.
369 * Subclasses may extend.
372 public void dispose() {
373 for (int i = 0; i < nestedEditors.size(); ++i) {
374 IEditorPart editor = (IEditorPart) nestedEditors.get(i);
377 nestedEditors.clear();
378 if (pageContainerSite instanceof IDisposable) {
379 ((IDisposable) pageContainerSite).dispose();
380 pageContainerSite = null;
382 for (int i = 0; i < pageSites.size(); i++) {
383 IServiceLocator sl = (IServiceLocator) pageSites.get(i);
384 if (sl instanceof IDisposable) {
385 ((IDisposable) sl).dispose();
392 * Returns the active nested editor if there is one.
394 * Subclasses should not override this method
397 * @return the active nested editor, or <code>null</code> if none
399 protected IEditorPart getActiveEditor() {
400 int index = getActivePage();
402 return getEditor(index);
408 * Returns the index of the currently active page, or -1 if there is no
411 * Subclasses should not override this method
414 * @return the index of the active page, or -1 if there is no active page
416 protected int getActivePage() {
417 CTabFolder tabFolder = getTabFolder();
418 if (tabFolder != null && !tabFolder.isDisposed()) {
419 return tabFolder.getSelectionIndex();
425 * Returns the composite control containing this multi-page editor's pages.
426 * This should be used as the parent when creating controls for the
427 * individual pages. That is, when calling <code>addPage(Control)</code>,
428 * the passed control should be a child of this container.
430 * Warning: Clients should not assume that the container is any particular
431 * subclass of Composite. The actual class used may change in order to
432 * improve the look and feel of multi-page editors. Any code making
433 * assumptions on the particular subclass would thus be broken.
436 * Subclasses should not override this method
439 * @return the composite, or <code>null</code> if
440 * <code>createPartControl</code> has not been called yet
442 protected Composite getContainer() {
447 * Returns the control for the given page index, or <code>null</code> if
448 * no control has been set for the page. The page index must be valid.
450 * Subclasses should not override this method
454 * the index of the page
455 * @return the control for the specified page, or <code>null</code> if
458 protected Control getControl(int pageIndex) {
459 return getItem(pageIndex).getControl();
463 * Returns the editor for the given page index. The page index must be
467 * the index of the page
468 * @return the editor for the specified page, or <code>null</code> if the
469 * specified page was not created with
470 * <code>addPage(IEditorPart,IEditorInput)</code>
472 protected IEditorPart getEditor(int pageIndex) {
473 Item item = getItem(pageIndex);
475 Object data = item.getData();
476 if (data instanceof IEditorPart) {
477 return (IEditorPart) data;
484 * Returns the service locator for the given page index. This method can be
485 * used to create service locators for pages that are just controls. The
486 * page index must be valid.
488 * This will return the editor site service locator for an editor, and
489 * create one for a page that is just a control.
493 * the index of the page
494 * @return the editor for the specified page, or <code>null</code> if the
495 * specified page was not created with
496 * <code>addPage(IEditorPart,IEditorInput)</code>
499 protected final IServiceLocator getPageSite(int pageIndex) {
500 if (pageIndex == PAGE_CONTAINER_SITE) {
501 return getPageContainerSite();
504 Item item = getItem(pageIndex);
506 Object data = item.getData();
507 if (data instanceof IEditorPart) {
508 return ((IEditorPart) data).getSite();
509 } else if (data instanceof IServiceLocator) {
510 return (IServiceLocator) data;
511 } else if (data == null) {
512 IServiceLocatorCreator slc = (IServiceLocatorCreator) getSite()
513 .getService(IServiceLocatorCreator.class);
514 IServiceLocator sl = slc.createServiceLocator(getSite(), null, new IDisposable() {
516 public void dispose() {
517 // TODO Auto-generated method stub
529 * @return A site that can be used with a header.
531 * @see #createPageContainer(Composite)
532 * @see #PAGE_CONTAINER_SITE
533 * @see #getPageSite(int)
535 private IServiceLocator getPageContainerSite() {
536 if (pageContainerSite == null) {
537 IServiceLocatorCreator slc = (IServiceLocatorCreator) getSite()
538 .getService(IServiceLocatorCreator.class);
539 pageContainerSite = slc.createServiceLocator(getSite(), null, new IDisposable() {
541 public void dispose() {
542 // TODO Auto-generated method stub
546 return pageContainerSite;
550 * Returns the tab item for the given page index (page index is 0-based).
551 * The page index must be valid.
554 * the index of the page
555 * @return the tab item for the given page index
557 private CTabItem getItem(int pageIndex) {
558 return getTabFolder().getItem(pageIndex);
562 * Returns the number of pages in this multi-page editor.
564 * @return the number of pages
566 protected int getPageCount() {
567 CTabFolder folder = getTabFolder();
568 // May not have been created yet, or may have been disposed.
569 if (folder != null && !folder.isDisposed()) {
570 return folder.getItemCount();
576 * Returns the image for the page with the given index, or <code>null</code>
577 * if no image has been set for the page. The page index must be valid.
580 * the index of the page
581 * @return the image, or <code>null</code> if none
583 protected Image getPageImage(int pageIndex) {
584 return getItem(pageIndex).getImage();
588 * Returns the text label for the page with the given index. Returns the
589 * empty string if no text label has been set for the page. The page index
593 * the index of the page
594 * @return the text label for the page
596 protected String getPageText(int pageIndex) {
597 return getItem(pageIndex).getText();
601 * Returns the tab folder containing this multi-page editor's pages.
603 * @return the tab folder, or <code>null</code> if
604 * <code>createPartControl</code> has not been called yet
606 protected CTabFolder getTabFolder() {
611 * Handles a property change notification from a nested editor. The default
612 * implementation simply forwards the change to listeners on this multi-page
613 * editor by calling <code>firePropertyChange</code> with the same
614 * property id. For example, if the dirty state of a nested editor changes
615 * (property id <code>IEditorPart.PROP_DIRTY</code>), this method handles
616 * it by firing a property change event for
617 * <code>IEditorPart.PROP_DIRTY</code> to property listeners on this
620 * Subclasses may extend or reimplement this method.
624 * the id of the property that changed
626 protected void handlePropertyChange(int propertyId) {
627 firePropertyChange(propertyId);
631 * The <code>MultiPageEditorPart</code> implementation of this
632 * <code>IEditorPart</code> method sets its site to the given site, its
633 * input to the given input, and the site's selection provider to a
634 * <code>MultiPageSelectionProvider</code>. Subclasses may extend this
638 * The site for which this part is being created; must not be
641 * The input on which this editor should be created; must not be
643 * @throws PartInitException
644 * If the initialization of the part fails -- currently never.
647 public void init(IViewSite site, IMemento memento)
648 throws PartInitException {
650 site.setSelectionProvider(new TabbedPageSelectionProvider(this));
654 * Notifies this multi-page editor that the page with the given id has been
655 * activated. This method is called when the user selects a different tab.
657 * The <code>MultiPageEditorPart</code> implementation of this method sets
658 * focus to the new page, and notifies the action bar contributor (if there
659 * is one). This checks whether the action bar contributor is an instance of
660 * <code>MultiPageEditorActionBarContributor</code>, and, if so, calls
661 * <code>setActivePage</code> with the active nested editor. This also
662 * fires a selection change event if required.
665 * Subclasses may extend this method.
668 * @param newPageIndex
669 * the index of the activated page
671 protected void pageChange(int newPageIndex) {
672 deactivateSite(false, false);
674 IPartService partService = (IPartService) getSite().getService(
676 if (partService != null && partService.getActivePart() == this) {
677 setFocus(newPageIndex);
680 IEditorPart activeEditor = getEditor(newPageIndex);
682 // IEditorActionBarContributor contributor = getViewSite()
683 // .getActionBarContributor();
684 // if (contributor != null
685 // && contributor instanceof MultiPageEditorActionBarContributor) {
686 // ((MultiPageEditorActionBarContributor) contributor)
687 // .setActivePage(activeEditor);
690 if (activeEditor != null) {
691 ISelectionProvider selectionProvider = activeEditor.getSite()
692 .getSelectionProvider();
693 if (selectionProvider != null) {
694 ISelectionProvider outerProvider = getSite()
695 .getSelectionProvider();
696 if (outerProvider instanceof MultiPageSelectionProvider) {
697 SelectionChangedEvent event = new SelectionChangedEvent(
698 selectionProvider, selectionProvider.getSelection());
700 MultiPageSelectionProvider provider = (MultiPageSelectionProvider) outerProvider;
701 provider.fireSelectionChanged(event);
702 provider.firePostSelectionChanged(event);
704 if (Policy.DEBUG_MPE) {
705 Tracing.printTrace(TRACING_COMPONENT,
706 "MultiPageEditorPart " + getTitle() //$NON-NLS-1$
707 + " did not propogate selection for " //$NON-NLS-1$
708 + activeEditor.getTitle());
718 * This method can be used by implementors of
719 * {@link MultiPageEditorPart#createPageContainer(Composite)} to deactivate
720 * the active inner editor services while their header has focus. A
721 * deactivateSite() must have a matching call to activateSite() when
724 * An new inner editor will have its site activated on a
725 * {@link MultiPageEditorPart#pageChange(int)}.
728 * <b>Note:</b> This API is evolving in 3.4 and this might not be its final
733 * immediately deactivate the legacy keybinding service
734 * @param containerSiteActive
735 * Leave the page container site active.
737 * @see #activateSite()
738 * @see #createPageContainer(Composite)
739 * @see #getPageSite(int)
740 * @see #PAGE_CONTAINER_SITE
742 protected final void deactivateSite(boolean immediate,
743 boolean containerSiteActive) {
744 // Deactivate the nested services from the last active service locator.
745 if (activeServiceLocator != null) {
746 activeServiceLocator.deactivate();
747 activeServiceLocator = null;
750 final int pageIndex = getActivePage();
751 final IKeyBindingService service = getSite().getKeyBindingService();
752 if (pageIndex < 0 || pageIndex >= getPageCount() || immediate) {
753 // There is no selected page, so deactivate the active service.
754 if (service instanceof INestableKeyBindingService) {
755 final INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
756 nestableService.activateKeyBindingService(null);
759 .log("MultiPageEditorPart.setFocus() 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$
763 if (containerSiteActive) {
764 IServiceLocator containerSite = getPageContainerSite();
765 if (containerSite instanceof INestable) {
766 activeServiceLocator = (INestable) containerSite;
767 activeServiceLocator.activate();
773 * This method can be used by implementors of
774 * {@link #createPageContainer(Composite)} to activate the active inner
775 * editor services when their header loses focus.
777 * An new inner editor will have its site activated on a
778 * {@link #pageChange(int)}.
781 * <b>Note:</b> This API is evolving in 3.4 and this might not be its final
786 * @see #deactivateSite(boolean,boolean)
787 * @see #createPageContainer(Composite)
788 * @see #getPageSite(int)
790 protected final void activateSite() {
791 if (activeServiceLocator != null) {
792 activeServiceLocator.deactivate();
793 activeServiceLocator = null;
796 final IKeyBindingService service = getSite().getKeyBindingService();
797 final int pageIndex = getActivePage();
798 final IEditorPart editor = getEditor(pageIndex);
800 if (editor != null) {
801 // active the service for this inner editor
802 if (service instanceof INestableKeyBindingService) {
803 final INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
804 nestableService.activateKeyBindingService(editor
809 .log("MultiPageEditorPart.setFocus() 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$
811 // Activate the services for the new service locator.
812 final IServiceLocator serviceLocator = editor.getEditorSite();
813 if (serviceLocator instanceof INestable) {
814 activeServiceLocator = (INestable) serviceLocator;
815 activeServiceLocator.activate();
819 Item item = getItem(pageIndex);
821 // There is no selected editor, so deactivate the active service.
822 if (service instanceof INestableKeyBindingService) {
823 final INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
824 nestableService.activateKeyBindingService(null);
827 .log("MultiPageEditorPart.setFocus() 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$
830 if (item.getData() instanceof INestable) {
831 activeServiceLocator = (INestable) item.getData();
832 activeServiceLocator.activate();
838 * Disposes the given part and its site.
841 * The part to dispose; must not be <code>null</code>.
843 private void disposePart(final IWorkbenchPart part) {
844 SafeRunner.run(new ISafeRunnable() {
846 IWorkbenchPartSite partSite = part.getSite();
848 if (partSite instanceof MultiPageEditorSite) {
849 ((MultiPageEditorSite) partSite).dispose();
853 public void handleException(Throwable e) {
854 // Exception has already being logged by Core. Do nothing.
860 * Removes the page with the given index from this multi-page editor. The
861 * controls for the page are disposed of; if the page has an editor, it is
862 * disposed of too. The page index must be valid.
865 * the index of the page
866 * @see MultiPageEditorPart#addPage(Control)
867 * @see MultiPageEditorPart#addPage(IEditorPart, IEditorInput)
869 public void removePage(int pageIndex) {
870 Assert.isTrue(pageIndex >= 0 && pageIndex < getPageCount());
871 // get editor (if any) before disposing item
872 IEditorPart editor = getEditor(pageIndex);
874 // get control for the item if it's not an editor
875 CTabItem item = getItem(pageIndex);
876 IServiceLocator pageLocator = null;
877 if (item.getData() instanceof IServiceLocator) {
878 pageLocator = (IServiceLocator) item.getData();
880 Control pageControl = item.getControl();
882 // dispose item before disposing editor, in case there's an exception
883 // in editor's dispose
886 if (pageControl != null) {
887 pageControl.dispose();
890 // dispose editor (if any)
891 if (editor != null) {
892 nestedEditors.remove(editor);
895 if (pageLocator != null) {
896 pageSites.remove(pageLocator);
897 if (pageLocator instanceof IDisposable) {
898 ((IDisposable) pageLocator).dispose();
904 * Sets the currently active page.
907 * the index of the page to be activated; the index must be valid
909 protected void setActivePage(int pageIndex) {
910 Assert.isTrue(pageIndex >= 0 && pageIndex < getPageCount());
911 getTabFolder().setSelection(pageIndex);
912 pageChange(pageIndex);
916 * Sets the control for the given page index. The page index must be valid.
919 * the index of the page
921 * the control for the specified page, or <code>null</code> to
924 protected void setControl(int pageIndex, Control control) {
925 getItem(pageIndex).setControl(control);
929 * The <code>MultiPageEditor</code> implementation of this
930 * <code>IWorkbenchPart</code> method sets focus on the active nested
931 * editor, if there is one.
933 * Subclasses may extend or reimplement.
937 public void setFocus() {
938 setFocus(getActivePage());
942 * Sets focus to the control for the given page. If the page has an editor,
943 * this calls its <code>setFocus()</code> method. Otherwise, this calls
944 * <code>setFocus</code> on the control for the page.
947 * the index of the page
949 private void setFocus(int pageIndex) {
950 final IEditorPart editor = getEditor(pageIndex);
951 if (editor != null) {
955 // Give the page's control focus.
956 final Control control = getControl(pageIndex);
957 if (control != null) {
964 * Sets the image for the page with the given index, or <code>null</code>
965 * to clear the image for the page. The page index must be valid.
968 * the index of the page
970 * the image, or <code>null</code>
972 protected void setPageImage(int pageIndex, Image image) {
973 getItem(pageIndex).setImage(image);
977 * Sets the text label for the page with the given index. The page index
978 * must be valid. The text label must not be null.
981 * the index of the page
985 protected void setPageText(int pageIndex, String text) {
986 getItem(pageIndex).setText(text);
990 * If there is an adapter registered against the subclass of
991 * MultiPageEditorPart return that. Otherwise, delegate to the internal
994 * @see org.eclipse.ui.part.WorkbenchPart#getAdapter(java.lang.Class)
997 public Object getAdapter(Class adapter) {
998 Object result = super.getAdapter(adapter);
999 // restrict delegating to the UI thread for bug 144851
1000 if (result == null && Display.getCurrent()!=null) {
1001 IEditorPart innerEditor = getActiveEditor();
1002 // see bug 138823 - prevent some subclasses from causing
1004 if (innerEditor != null && innerEditor != this) {
1005 result = Adapters.adapt(innerEditor, adapter);
1012 // * Find the editors contained in this multi-page editor
1013 // * whose editor input match the provided input.
1014 // * @param input the editor input
1015 // * @return the editors contained in this multi-page editor
1016 // * whose editor input match the provided input
1019 // public final IEditorPart[] findEditors(IEditorInput input) {
1020 // List result = new ArrayList();
1021 // int count = getPageCount();
1022 // for (int i = 0; i < count; i++) {
1023 // IEditorPart editor = getEditor(i);
1024 // if (editor != null
1025 // && editor.getEditorInput() != null
1026 // && editor.getEditorInput().equals(input)) {
1027 // result.add(editor);
1030 // return (IEditorPart[]) result.toArray(new IEditorPart[result.size()]);
1034 // * Set the active page of this multi-page editor to the
1035 // * page that contains the given editor part. This method has
1036 // * no effect of the given editor part is not contained in this
1037 // * multi-page editor.
1038 // * @param editorPart the editor part
1041 // public final void setActiveEditor(IEditorPart editorPart) {
1042 // int count = getPageCount();
1043 // for (int i = 0; i < count; i++) {
1044 // IEditorPart editor = getEditor(i);
1045 // if (editor == editorPart) {
1046 // setActivePage(i);
1052 // private IViewPart part;
1054 // public IViewSite getSite() {
1055 // return part.getViewSite();
1058 // public IViewPart getPart() {
1064 public IViewSite getViewSite() {
1065 if(part instanceof IViewPart) return ((IViewPart) part).getViewSite();
1070 public IWorkbenchPartSite getSite() {
1071 return part.getSite();
1074 IWorkbenchPart part;
1076 public TabbedPropertyPage(IWorkbenchPart part) {
1078 // Given part may be null
1079 // assert(part != null);
1080 // setSite(part.getSite());