/***************************************************************************** * Copyright (c) 2009 CEA LIST & LIFL * * * 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: * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.infra.core.sasheditor.editor; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider; import org.eclipse.papyrus.infra.core.sasheditor.internal.IMultiEditorManager; import org.eclipse.papyrus.infra.core.sasheditor.internal.SashWindowsContainer; import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.MultiPageSelectionProvider; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.internal.util.Util; import org.eclipse.ui.part.EditorPart; /** * Base editor that can be subclassed to provide a multi page editor with sash windows. * * @author dumoulin */ public abstract class AbstractMultiPageSashEditor extends EditorPart implements IMultiPageEditorPart, IMultiEditorManager { /** The pageProvider */ private ISashWindowsContentProvider pageProvider; /** The sash windows system :-) */ private SashWindowsContainer sashContainer; /** * Synchronizer in charge of synchronizing tab names with IEditorPart title. */ private SashTabDecorationSynchronizer tabsSynchronizer; /** * get the contentProvider. Create it if necessary. * * @return */ protected ISashWindowsContentProvider getContentProvider() { if(pageProvider == null) { pageProvider = createPageProvider(); } return pageProvider; } /** * Set the contentProvider if not set. If it is already set, this method do not change it. * * @param contentProvider */ protected void setContentProvider(ISashWindowsContentProvider contentProvider) { if(pageProvider == null) { pageProvider = contentProvider; } } /** * Create the provider. * Subclass must implements this method. It should return the provider used by the editor. * */ abstract protected ISashWindowsContentProvider createPageProvider(); /** * Handles a property change notification from a nested editor. The default implementation simply forwards the change to * listeners on this multi-page editor by calling <code>firePropertyChange</code> with the same property id. For example, if * the dirty state of a nested editor changes (property id <code>IEditorPart.PROP_DIRTY</code>), this method handles it * by firing a property change event for <code>IEditorPart.PROP_DIRTY</code> to property listeners on this multi-page * editor. * <p> * Subclasses may extend or reimplement this method. * </p> * * @copiedfrom org.eclipse.ui.part.MultiPageEditorPart.handlePropertyChange(int) * * @param propertyId * the id of the property that changed */ protected void handlePropertyChange(int propertyId) { firePropertyChange(propertyId); } /** * The <code>MultiPageEditorPart</code> implementation of this <code>IEditorPart</code> method sets its site to the given * site, its input to the given input, and the site's selection provider to a <code>MultiPageSelectionProvider</code>. * Subclasses may extend this method. * * @copiedfrom org.eclipse.ui.part.MultiPageEditorPart * @param site * The site for which this part is being created; must not be <code>null</code>. * @param input * The input on which this editor should be created; must not be <code>null</code>. * @throws PartInitException * If the initialization of the part fails -- currently never. */ @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); site.setSelectionProvider(new MultiPageSelectionProvider(this)); } /** * Create the part controls. {@inheritDoc} */ @Override public void createPartControl(Composite parent) { // Create and intialize sash windows sashContainer = new SashWindowsContainer(this); sashContainer.setContentProvider(getContentProvider()); sashContainer.createPartControl(parent); activate(); } /** * Method to activate the editor. * Called immediately after createPartControl() is complete. * To be implemented by subclasses. Default implementation do nothing. */ protected void activate() { tabsSynchronizer = new SashTabDecorationSynchronizer(sashContainer); } /** * Method to deactivate the editor. * Called when dispose() is called. * To be implemented by subclasses. Default implementation do nothing. */ protected void deactivate() { tabsSynchronizer.dispose(); } /** * Dispose the Editor. Also dispose the sashsystem. * * @see org.eclipse.ui.part.WorkbenchPart#dispose() * */ @Override public void dispose() { deactivate(); super.dispose(); } /** * Refresh the sash windows system */ protected void refreshTabs() { if(sashContainer != null) { sashContainer.refreshTabs(); } } /** * If there is an adapter registered against the subclass of MultiPageEditorPart return that. Otherwise, delegate to the * internal editor. * * @copiedfrom org.eclipse.ui.part.MultiPageEditorPart * * @see org.eclipse.ui.part.WorkbenchPart#getAdapter(java.lang.Class) */ @Override public Object getAdapter(Class adapter) { // Get the content provider if requested. if(ISashWindowsContentProvider.class == adapter) { return getContentProvider(); } // Get the content provider if requested. if(ISashWindowsContainer.class == adapter) { return sashContainer; } // Look in hierarchy Object result = super.getAdapter(adapter); // restrict delegating to the UI thread for bug 144851 if(result == null && Display.getCurrent() != null) { IEditorPart innerEditor = getActiveEditor(); // see bug 138823 - prevent some subclasses from causing // an infinite loop if(innerEditor != null && innerEditor != this) { result = Util.getAdapter(innerEditor, adapter); } } return result; } /** * Needed by MultiPageActionBarContributor and MultiPageSelectionProvider. */ public IEditorPart getActiveEditor() { if( sashContainer.isDisposed()) return null; return sashContainer.getActiveEditor(); } /** * Get the {@link ISashWindowsContainer}. * Note the the ISashWindowsContainer can also be acuired with getAdapter(ISashWindowsContainer.class). */ public ISashWindowsContainer getISashWindowsContainer() { return sashContainer; } /** * * {@inheritDoc} */ @Override public void setFocus() { sashContainer.setFocus(); } /** * Overrides isDirty. * * {@inheritDoc} * * TODO Move this method aways. This method is too tightly coupled to the Papyrus GMF UML IEditor. * It doesn't work on other kind of IEditor. It introduce problems in IEditor of other kinds * * @see org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer#isDirty() * @deprecated A SaveAndDirtyService is used instead. */ @Override public boolean isDirty() { // return sashContainer.isDirty(); EditorVisitor visitor = new EditorVisitor(); sashContainer.visit(visitor); for(IEditorPart editorPart : visitor.getPages()) { if(editorPart.isDirty()) { return true; } } return false; } /** * Notify all the editors that the multi editor has been saved.<BR> * Fires the PROP_DIRTY property change. * * TODO Move this method aways. This method is too tightly coupled to the Papyrus GMF UML IEditor. * It doesn't work on other kind of IEditor. It introduce problems in IEditor of other kinds * @deprecated A SaveAndDirtyService is used instead. */ protected void markSaveLocation() { // return sashContainer.isDirty(); EditorVisitor visitor = new EditorVisitor(); sashContainer.visit(visitor); for(IEditorPart editorPart : visitor.getPages()) { editorPart.doSave(new NullProgressMonitor()); } firePropertyChange(PROP_DIRTY); } /** * A visitor allowing to collect the available IEditor. * TODO : Remove * * @author dumoulin * */ protected class EditorVisitor implements IPageVisitor { private List<IEditorPart> pages = new ArrayList<IEditorPart>(); /** * Get collected pages. * * @return */ public List<IEditorPart> getPages() { return pages; } /** * */ public void accept(IComponentPage page) { // Do nothing } /** * */ public void accept(IEditorPage page) { IEditorPart editor = page.getIEditorPart(); pages.add(editor); } } }