/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; import org.eclipse.papyrus.infra.core.sasheditor.internal.AbstractPanelPart; import org.eclipse.papyrus.infra.core.sasheditor.internal.IPanelParent; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** * Copy of org.eclipse.ui.part.MultiPageEditorPart. Change if to be suitable has a sash leaf. A multi-page editor is an editor with multiple pages, * each of which may contain an editor or an arbitrary * SWT control. * <p> * This class is intented to separate folder stuff into 2 classes. Subclasses must implement the following methods: * <ul> * <li><code>createPages</code> - to create the required pages by calling one of the <code>addPage</code> methods</li> * <li><code>IEditorPart.doSave</code> - to save contents of editor</li> * <li><code>IEditorPart.doSaveAs</code> - to save contents of editor</li> * <li><code>IEditorPart.isSaveAsAllowed</code> - to enable Save As</li> * <li><code>IEditorPart.gotoMarker</code> - to scroll to a marker</li> * </ul> * </p> * <p> * Multi-page editors have a single action bar contributor, which manages contributions for all the pages. The contributor must be a subclass of * <code>AbstractMultiPageEditorActionBarContributor</code>. Note that since any nested editors are created directly in code by callers of * <code>addPage(IEditorPart,IEditorInput)</code>, nested editors do not have their own contributors. * </p> * * @see org.eclipse.ui.part.MultiPageEditorActionBarContributor */ public abstract class AbstractTabFolderPart extends AbstractPanelPart { /** * Subclasses that override {@link #createPageContainer(Composite)} can use this constant to get a site for the container that can be active while * the current page is deactivated. * * @since 3.4 * @see #activateSite() * @see #deactivateSite(boolean, boolean) * @see #getPageSite(int) */ protected static final int PAGE_CONTAINER_SITE = 65535; // /** // * Private tracing output. // */ // private static final String TRACING_COMPONENT = "MPE"; //$NON-NLS-1$ // /** // * The active service locator. This value may be <code>null</code> if there is no selected page, or if the selected page is a control with no site. // */ // private INestable activeServiceLocator; // // // private IServiceLocator pageContainerSite; /** * Creates an empty multi-page editor with no pages. */ protected AbstractTabFolderPart(IPanelParent parent) { super(parent); } /** * The <code>MultiPageEditor</code> implementation of this <code>IWorkbenchPart</code> method creates the control for the multi-page editor by * calling <code>createContainer</code>, then <code>createPages</code>. Subclasses should implement <code>createPages</code> rather than * overriding this method. * * @param parent * The parent in which the editor should be created; must not be <code>null</code>. */ @Override abstract public void createPartControl(Composite parent); /** * Returns the active nested editor if there is one. * <p> * Subclasses should not override this method * </p> * * @return the active nested editor, or <code>null</code> if none */ // public IEditorPart getActiveEditor() { // int index = getActivePage(); // if (index != -1) { // return getEditor(index); // } // return null; // } /** * Returns the index of the currently active page of this folder, or -1 if there is no active page. * <p> * Subclasses should not override this method * </p> * * @return the index of the active page, or -1 if there is no active page */ protected int getActivePage() { CTabFolder tabFolder = getTabFolder(); if(tabFolder != null && !tabFolder.isDisposed()) { return tabFolder.getSelectionIndex(); } return -1; } /** * Returns the control for the given page index, or <code>null</code> if no control has been set for the page. The page index must be valid. * <p> * Subclasses should not override this method * </p> * * @param pageIndex * the index of the page * @return the control for the specified page, or <code>null</code> if none has been set */ protected Control getControl(int pageIndex) { return getItem(pageIndex).getControl(); } /** * Returns the editor for the given page index. The page index must be valid. * * @param pageIndex * the index of the page * @return the editor for the specified page, or <code>null</code> if the specified page was not created with * <code>addPage(IEditorPart,IEditorInput)</code> */ // abstract protected IEditorPart getEditor(int pageIndex); /** * Returns the service locator for the given page index. This method can be used to create service locators for pages that are just controls. The * page index must be valid. * <p> * This will return the editor site service locator for an editor, and create one for a page that is just a control. * </p> * * @param pageIndex * the index of the page * @return the editor for the specified page, or <code>null</code> if the specified page was not created with * <code>addPage(IEditorPart,IEditorInput)</code> * @since 3.4 */ // protected final IServiceLocator getPageSite(int pageIndex) { // if (pageIndex == PAGE_CONTAINER_SITE) { // return getPageContainerSite(); // } // // /** // * Return the site associated to the editor. // */ // return getEditor(pageIndex).getSite(); // } /** * @return A site that can be used with a header. * @since 3.4 * @see #createPageContainer(Composite) * @see #PAGE_CONTAINER_SITE * @see #getPageSite(int) */ // private IServiceLocator getPageContainerSite() { // if (pageContainerSite == null) { // IServiceLocatorCreator slc = (IServiceLocatorCreator) getSite().getService(IServiceLocatorCreator.class); // pageContainerSite = slc.createServiceLocator(getSite(), null, new IDisposable() { // // public void dispose() { // final Control control = ((PartSite) getSite()).getPane().getControl(); // if (control != null && !control.isDisposed()) { // ((PartSite) getSite()).getPane().doHide(); // } // } // }); // } // return pageContainerSite; // } /** * Returns the tab item for the given page index (page index is 0-based). The page index must be valid. * * @param pageIndex * the index of the page * @return the tab item for the given page index */ private CTabItem getItem(int pageIndex) { return getTabFolder().getItem(pageIndex); } /** * Returns the number of pages in this multi-page editor. * * @return the number of pages */ protected int getPageCount() { CTabFolder folder = getTabFolder(); // May not have been created yet, or may have been disposed. if(folder != null && !folder.isDisposed()) { return folder.getItemCount(); } return 0; } /** * Returns the tab folder containing this multi-page editor's pages. * * @return the tab folder, or <code>null</code> if <code>createPartControl</code> has not been called yet */ protected abstract CTabFolder getTabFolder(); /** * Notifies this multi-page editor that the page with the given id has been activated. This method is called when the user selects a different * tab. * <p> * The <code>MultiPageEditorPart</code> implementation of this method sets focus to the new page, and notifies the action bar contributor (if * there is one). This checks whether the action bar contributor is an instance of <code>MultiPageEditorActionBarContributor</code>, and, if so, * calls <code>setActivePage</code> with the active nested editor. This also fires a selection change event if required. * </p> * <p> * Subclasses may extend this method. * </p> * * @param newPageIndex * the index of the activated page */ protected void pageChange(int newPageIndex) { // System.out.println(this.getClass().getSimpleName() + "pageChange()"); // deactivateSite(false, false); // // IPartService partService = (IPartService) getSite().getService(IPartService.class); // if (partService.getActivePart() == this) { // setFocus(newPageIndex); // } // // IEditorPart activeEditor = getEditor(newPageIndex); // // IEditorActionBarContributor contributor = getEditorSite().getActionBarContributor(); // if (contributor != null && contributor instanceof MultiPageEditorActionBarContributor) { // ((MultiPageEditorActionBarContributor) contributor).setActivePage(activeEditor); // } // // if (activeEditor != null) { // ISelectionProvider selectionProvider = activeEditor.getSite().getSelectionProvider(); // if (selectionProvider != null) { // ISelectionProvider outerProvider = getSite().getSelectionProvider(); // if (outerProvider instanceof MultiPageSelectionProvider) { // SelectionChangedEvent event = new SelectionChangedEvent(selectionProvider, selectionProvider.getSelection()); // // MultiPageSelectionProvider provider = (MultiPageSelectionProvider) outerProvider; // provider.fireSelectionChanged(event); // provider.firePostSelectionChanged(event); // } else { // if (Policy.DEBUG_MPE) { // Tracing.printTrace(TRACING_COMPONENT, "MultiPageEditorPart " + getTitle() //$NON-NLS-1$ // + " did not propogate selection for " //$NON-NLS-1$ // + activeEditor.getTitle()); // } // } // } // } // // activateSite(); } /** * This method can be used by implementors of {@link AbstractTabFolderPart#createPageContainer(Composite)} to deactivate the active inner editor * services while their header has focus. A * deactivateSite() must have a matching call to activateSite() when appropriate. * <p> * An new inner editor will have its site activated on a {@link AbstractTabFolderPart#pageChange(int)}. * </p> * <p> * <b>Note:</b> This API is evolving in 3.4 and this might not be its final form. * </p> * * @param immediate * immediately deactivate the legacy keybinding service * @param containerSiteActive * Leave the page container site active. * @since 3.4 * @see #activateSite() * @see #createPageContainer(Composite) * @see #getPageSite(int) * @see #PAGE_CONTAINER_SITE */ // protected final void deactivateSite(boolean immediate, boolean containerSiteActive) { // // Deactivate the nested services from the last active service locator. // if (activeServiceLocator != null) { // activeServiceLocator.deactivate(); // activeServiceLocator = null; // } // // final int pageIndex = getActivePage(); // final IKeyBindingService service = getSite().getKeyBindingService(); // if (pageIndex < 0 || pageIndex >= getPageCount() || immediate) { // // There is no selected page, so deactivate the active service. // if (service instanceof INestableKeyBindingService) { // final INestableKeyBindingService nestableService = (INestableKeyBindingService) service; // nestableService.activateKeyBindingService(null); // } else { // WorkbenchPlugin // .log("MultiPageEditorPart.deactivateSite() 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$ // } // } // // if (containerSiteActive) { // IServiceLocator containerSite = getPageContainerSite(); // if (containerSite instanceof INestable) { // activeServiceLocator = (INestable) containerSite; // activeServiceLocator.activate(); // } // } // } /** * This method can be used by implementors of {@link #createPageContainer(Composite)} to activate the active inner editor services when their * header loses focus. * <p> * An new inner editor will have its site activated on a {@link #pageChange(int)}. * </p> * <p> * <b>Note:</b> This API is evolving in 3.4 and this might not be its final form. * </p> * * @since 3.4 * @see #deactivateSite(boolean,boolean) * @see #createPageContainer(Composite) * @see #getPageSite(int) */ // protected final void activateSite() { // if (activeServiceLocator != null) { // activeServiceLocator.deactivate(); // activeServiceLocator = null; // } // // final IKeyBindingService service = getSite().getKeyBindingService(); // final int pageIndex = getActivePage(); // final IEditorPart editor = getEditor(pageIndex); // // if (editor != null) { // // active the service for this inner editor // if (service instanceof INestableKeyBindingService) { // final INestableKeyBindingService nestableService = (INestableKeyBindingService) service; // nestableService.activateKeyBindingService(editor.getEditorSite()); // // } else { // WorkbenchPlugin // .log("MultiPageEditorPart.activateSite() 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$ // } // // Activate the services for the new service locator. // final IServiceLocator serviceLocator = editor.getEditorSite(); // if (serviceLocator instanceof INestable) { // activeServiceLocator = (INestable) serviceLocator; // activeServiceLocator.activate(); // } // // } else { // Item item = getItem(pageIndex); // // // There is no selected editor, so deactivate the active service. // if (service instanceof INestableKeyBindingService) { // final INestableKeyBindingService nestableService = (INestableKeyBindingService) service; // nestableService.activateKeyBindingService(null); // } else { // WorkbenchPlugin // .log("MultiPageEditorPart.activateSite() 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$ // } // // if (item.getData() instanceof INestable) { // activeServiceLocator = (INestable) item.getData(); // activeServiceLocator.activate(); // } // } // } // /** // * Disposes the given part and its site. // * // * @param part // * The part to dispose; must not be <code>null</code>. // */ // private void disposePart(final IWorkbenchPart part) { // SafeRunner.run(new ISafeRunnable() { // // public void run() { // IWorkbenchPartSite partSite = part.getSite(); // part.dispose(); // if (partSite instanceof MultiPageEditorSite) { // ((MultiPageEditorSite) partSite).dispose(); // } // } // // public void handleException(Throwable e) { // // Exception has already being logged by Core. Do nothing. // } // }); // } /** * Sets the currently active page for this folder. * * @param pageIndex * the index of the page to be activated; the index must be valid */ public void setActivePage(int pageIndex) { // Assert.isTrue(pageIndex >= 0 && pageIndex < getPageCount()); if(!isValidPageIndex(pageIndex)) return; getTabFolder().setSelection(pageIndex); pageChange(pageIndex); } /** * Return true if the specified index is valid. * The index should be between 0 and pageCount. * If there is no page, return false. * * @param pageIndex * @return */ private boolean isValidPageIndex(int pageIndex) { return pageIndex >= 0 && pageIndex < getPageCount(); } /** * Sets the control for the given page index. The page index must be valid. * * @param pageIndex * the index of the page * @param control * the control for the specified page, or <code>null</code> to clear the control */ protected void setControl(int pageIndex, Control control) { getItem(pageIndex).setControl(control); } /* *************************************** */ /* Added method. */ /* *************************************** */ // /** // * Title of this TilePart ? Needed by a trace message. // */ // protected String getTitle() { // return getClass().toString(); // } // // /** // * // */ // protected IWorkbenchPartSite getSite() { // return getEditorSite(); // } // // /** // * // */ // abstract protected void firePropertyChange(int propertyId); // // /** // * // */ // abstract protected IEditorSite getEditorSite(); }