/****************************************************************************** * Copyright (c) 2016 Oracle and Liferay * 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: * Konstantin Komissarchik - initial implementation and ongoing maintenance * Ling Hao - [329114] rewrite context help binding feature * Shenxue Zhou - [365019] SapphireDiagramEditor does not work on non-workspace files * Gregory Amerson - [372816] Provide adapt mechanism for SapphirePart * Gregory Amerson - [346172] Support zoom, print and save as image actions in the diagram editor * Gregory Amerson - [444202] Lazy loading of editor pages ******************************************************************************/ package org.eclipse.sapphire.ui; import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gd; import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.glayout; import java.lang.reflect.Constructor; import java.net.URI; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.help.IContext; import org.eclipse.sapphire.Element; import org.eclipse.sapphire.Event; import org.eclipse.sapphire.Listener; import org.eclipse.sapphire.LocalizableText; import org.eclipse.sapphire.LoggingService; import org.eclipse.sapphire.PropertyDef; import org.eclipse.sapphire.Sapphire; import org.eclipse.sapphire.Text; import org.eclipse.sapphire.modeling.CorruptedResourceExceptionInterceptor; import org.eclipse.sapphire.modeling.ResourceStoreException; import org.eclipse.sapphire.modeling.Status; import org.eclipse.sapphire.services.Service; import org.eclipse.sapphire.ui.def.DefinitionLoader; import org.eclipse.sapphire.ui.def.DefinitionLoader.Reference; import org.eclipse.sapphire.ui.def.EditorPageDef; import org.eclipse.sapphire.ui.def.PartDef; import org.eclipse.sapphire.ui.diagram.def.DiagramEditorPageDef; import org.eclipse.sapphire.ui.forms.FormEditorPageDef; import org.eclipse.sapphire.ui.forms.MasterDetailsEditorPageDef; import org.eclipse.sapphire.ui.forms.PropertiesViewContributionPart; import org.eclipse.sapphire.ui.forms.swt.EditorPagePresentation; import org.eclipse.sapphire.ui.forms.swt.FormEditorPage; import org.eclipse.sapphire.ui.forms.swt.MasterDetailsEditorPage; import org.eclipse.sapphire.ui.forms.swt.SapphireEditorFormPage; import org.eclipse.sapphire.ui.forms.swt.SwtResourceCache; import org.eclipse.sapphire.ui.forms.swt.internal.SapphirePropertySheetPage; import org.eclipse.sapphire.ui.forms.swt.internal.text.SapphireFormText; import org.eclipse.sapphire.ui.internal.PartServiceContext; import org.eclipse.sapphire.ui.internal.SapphireActionManager; import org.eclipse.sapphire.ui.internal.SapphireEditorContentOutline; import org.eclipse.sapphire.util.ListFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IURIEditorInput; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.forms.editor.FormEditor; import org.eclipse.ui.forms.editor.IFormPage; import org.eclipse.ui.internal.EditorActionBars; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.part.MultiPageEditorActionBarContributor; import org.eclipse.ui.part.MultiPageEditorPart; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> * @author <a href="mailto:ling.hao@oracle.com">Ling Hao</a> * @author <a href="mailto:shenxue.zhou@oracle.com">Shenxue Zhou</a> * @author <a href="mailto:gregory.amerson@liferay.com">Gregory Amerson</a> */ public abstract class SapphireEditor extends FormEditor implements ISapphirePart { @Text( "Associated resources are not accessible" ) private static LocalizableText resourceNotAccessible; @Text( "Editor {0} failed to instantiate its model" ) private static LocalizableText failedToCreateModel; @Text( "Error" ) private static LocalizableText errorPageTitle; @Text( "Failed to find a definition '{0}'" ) private static LocalizableText failedToFindDefinition; static { LocalizableText.init( SapphireEditor.class ); } private static class SapphireEditorActionBarContributor extends MultiPageEditorActionBarContributor { private MultiPageEditorPart multiPageEditor = null; public void setActiveEditor(IEditorPart targetEditor) { if (targetEditor instanceof MultiPageEditorPart) { this.multiPageEditor = (MultiPageEditorPart) targetEditor; } super.setActiveEditor(targetEditor); } @Override public void setActivePage(IEditorPart activeEditor) { ISapphireEditorActionContributor actionContributor = null; ITextEditor textEditor = null; if (this.multiPageEditor != null) { if (activeEditor instanceof ISapphireEditorActionContributor) { actionContributor = (ISapphireEditorActionContributor)activeEditor; } else if (activeEditor instanceof ITextEditor) { textEditor = (ITextEditor)activeEditor; } else if (activeEditor == null) { Object obj = this.multiPageEditor.getSelectedPage(); if (obj instanceof ISapphireEditorActionContributor) { actionContributor = (ISapphireEditorActionContributor)obj; } } } IActionBars actionBars = getActionBars(); if (actionBars != null && (actionContributor != null || textEditor != null)) { /** The global actions to be connected with editor actions */ if (actionContributor != null) { actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), actionContributor.getAction(ActionFactory.DELETE.getId())); actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), actionContributor.getAction(ActionFactory.SELECT_ALL.getId())); actionBars.setGlobalActionHandler(ActionFactory.PRINT.getId(), actionContributor.getAction(ActionFactory.PRINT.getId())); } else if (textEditor != null) { actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), textEditor.getAction(ActionFactory.DELETE.getId())); actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), textEditor.getAction(ActionFactory.SELECT_ALL.getId())); actionBars.setGlobalActionHandler(ActionFactory.PRINT.getId(), textEditor.getAction(ActionFactory.PRINT.getId())); } actionBars.updateActionBars(); } } } private static final String PREFS_LAST_ACTIVE_PAGE = "LastActivePage"; //$NON-NLS-1$ private static final String PREFS_GLOBAL = "Global"; //$NON-NLS-1$ private static final String PREFS_INSTANCE_BY_URI = "InstanceByUri"; //$NON-NLS-1$ private static final String PREFS_INSTANCE_BY_EDITOR_INPUT_TYPE = "InstanceByEditorInputType"; //$NON-NLS-1$ private final String pluginId; private Element model; private IResourceChangeListener fileChangeListener; private SwtResourceCache imageCache; private SapphireEditorContentOutline outline; private SapphireActionManager actionsManager; private SapphirePropertySheetPage propertiesViewPage; private Listener propertiesViewContributionChangeListener; private PartServiceContext serviceContext; private boolean ignorePageChange; public SapphireEditor() { this.pluginId = FrameworkUtil.getBundle( getClass() ).getSymbolicName(); this.imageCache = new SwtResourceCache(); this.outline = null; this.actionsManager = new SapphireActionManager( this, getActionContexts() ); } @Override public Composite getContainer() { return super.getContainer(); } public PartDef definition() { return null; } public final Element getModelElement() { if( this.model == null ) { this.model = createModel(); adaptModel( this.model ); } return this.model; } public final Element getLocalModelElement() { return getModelElement(); } protected abstract Element createModel(); protected void adaptModel( final Element model ) { final CorruptedResourceExceptionInterceptor interceptor = new CorruptedResourceExceptionInterceptorImpl( getEditorSite().getShell() ); this.model.resource().setCorruptedResourceExceptionInterceptor( interceptor ); } public final Preferences getGlobalPreferences( final boolean createIfNecessary ) throws BackingStoreException { final Preferences prefs = getPreferencesRoot( createIfNecessary ); if( prefs != null && ( prefs.nodeExists( PREFS_GLOBAL ) || createIfNecessary ) ) { return prefs.node( PREFS_GLOBAL ); } return null; } public final Preferences getInstancePreferences( final boolean createIfNecessary ) throws BackingStoreException { final IEditorInput editorInput = getEditorInput(); final String level1; final String level2; if( editorInput instanceof IURIEditorInput ) { level1 = PREFS_INSTANCE_BY_URI; final URI uri = ( (IURIEditorInput) editorInput ).getURI(); if( uri != null ) { level2 = ( (IURIEditorInput) editorInput ).getURI().toString(); } else { level2 = "$#%**invalid**%#$"; } } else { level1 = PREFS_INSTANCE_BY_EDITOR_INPUT_TYPE; level2 = editorInput.getClass().getName(); } Preferences prefs = getPreferencesRoot( createIfNecessary ); if( prefs != null && ( prefs.nodeExists( level1 ) || createIfNecessary ) ) { prefs = prefs.node( level1 ); if( prefs.nodeExists( level2 ) || createIfNecessary ) { return prefs.node( level2 ); } } return null; } private final Preferences getPreferencesRoot( final boolean createIfNecessary ) throws BackingStoreException { /* * Replace "new InstanceScope()" with "InstanceScope.INSTANCE" once Sapphire no longer needs to * support Eclipse 3.6.x releases. */ @SuppressWarnings( "deprecation" ) final IScopeContext scope = new InstanceScope(); final Preferences prefs = scope.getNode( this.pluginId ); final String editorId = getClass().getName(); if( prefs.nodeExists( editorId ) || createIfNecessary ) { return prefs.node( editorId ); } return null; } private final int getLastActivePage() { int lastActivePage = 0; try { final Preferences prefs = getInstancePreferences( false ); if( prefs != null ) { lastActivePage = prefs.getInt( PREFS_LAST_ACTIVE_PAGE, lastActivePage ); } } catch( BackingStoreException e ) { Sapphire.service( LoggingService.class ).log( e ); } return lastActivePage; } private final void setLastActivePage( final int index ) { try { final Preferences prefs = getInstancePreferences( true ); if( prefs != null ) { prefs.putInt( PREFS_LAST_ACTIVE_PAGE, index ); prefs.flush(); } } catch( BackingStoreException e ) { Sapphire.service( LoggingService.class ).log( e ); } } public IFile getFile() { final IEditorInput editorInput = getEditorInput(); if( editorInput instanceof FileEditorInput ) { return ( (FileEditorInput) editorInput ).getFile(); } else { return null; } } public final IProject getProject() { final IFile ifile = getFile(); return ( ifile == null ? null : ifile.getProject() ); } public final void init( final IEditorSite site, final IEditorInput input ) throws PartInitException { super.init( site, input ); doSetInput( input ); } protected final void setInput( final IEditorInput input ) { doSetInput( input ); super.setInput( input ); } @Override protected final void setInputWithNotify( final IEditorInput input ) { doSetInput( input ); super.setInputWithNotify( input ); } private void doSetInput( final IEditorInput input ) { setPartName( input.getName() ); } public int addEditorPage(IEditorPart page) throws PartInitException { return addPage(page, getEditorInput()); } public void addEditorPage(int index, IEditorPart page) throws PartInitException { addPage(index, page, getEditorInput()); } @Override public int addPage( final IEditorPart page, final IEditorInput input ) throws PartInitException { int index = super.addPage(page, input); setPageText( index, page.getTitle() ); return index; } @Override public void addPage( final int index, final IEditorPart page, final IEditorInput input) throws PartInitException { super.addPage(index, page, input); setPageText( index, page.getTitle() ); } /** * Adds a page that will be loaded from its definition when the user first opens it. When this method * is used, the editor will load the page definition by calling {@link #getDefinition(String)}. By default, * the definitions are loaded from an sdef file with the same name as the editor class. If the default * behavior is inadequate, either {@link #getDefinitionLoader()} or {@link #getDefinition(String)} should be * overridden. * * @since 8.1 * @param index the position of the page in the editor's page list * @param pageName the localizable name of the page * @param pageDefinitionId the id of the page definition * @throws IllegalArgumentException if index is less than -1 or more than current page count * @throws IllegalArgumentException if pageName is null */ protected final void addDeferredPage( final int index, final String pageName, final String pageDefinitionId ) { if( index < -1 ) { throw new IllegalArgumentException(); } if( pageName == null ) { throw new IllegalArgumentException(); } final DeferredPage page = new DeferredPage( getContainer(), pageDefinitionId ); if( index == -1 ) { addPage( page ); setPageText( this.pages.size() - 1, pageName ); } else { addPage( index, page ); setPageText( index, pageName ); } } /** * Adds a page that will be loaded from its definition when the user first opens it. When this method * is used, the editor will load the page definition by calling {@link #getDefinition(String)}. By default, * the definitions are loaded from an sdef file with the same name as the editor class. If the default * behavior is inadequate, either {@link #getDefinitionLoader()} or {@link #getDefinition(String)} should be * overridden. * * @since 8.1 * @param pageName the localizable name of the page * @param pageDefinitionId the id of the page definition * @throws IllegalArgumentException if pageName is null */ protected final void addDeferredPage( final String pageName, final String pageDefinitionId ) { addDeferredPage( -1, pageName, pageDefinitionId ); } /** * Called when the editor should create its pages. The default implementation calls {@link #createSourcePages()}, * {@link #createFormPages()} and {@link #createDiagramPages()} methods, in that order. * * @since 8.1 * @throws PartInitException if a page could not be created */ protected void createEditorPages() throws PartInitException { createSourcePages(); createFormPages(); createDiagramPages(); } protected void createSourcePages() throws PartInitException { } protected void createFormPages() throws PartInitException { } protected void createDiagramPages() throws PartInitException { } @Override protected final void addPages() { // Insert an action bar contributor if none is specified in the editor if (getEditorSite().getActionBarContributor() == null) { IActionBars actionBars = getEditorSite().getActionBars(); EditorActionBars editorActionBars = (EditorActionBars)actionBars; SapphireEditorActionBarContributor actionBarContributor = new SapphireEditorActionBarContributor(); actionBarContributor.init(actionBars, this.getSite().getPage()); editorActionBars.setEditorContributor(actionBarContributor); } String error = null; final IFile file = getFile(); if( file != null && ! file.isAccessible() ) { error = resourceNotAccessible.text(); } if( error == null ) { try { createEditorPages(); } catch( PartInitException e ) { Sapphire.service( LoggingService.class ).log( e ); } createFileChangeListener(); setActivePage( getLastActivePage() ); } else { final Composite page = new Composite( getContainer(), SWT.NONE ); page.setLayout( glayout( 1 ) ); page.setBackground( getSite().getShell().getDisplay().getSystemColor( SWT.COLOR_WHITE ) ); final SapphireFormText message = new SapphireFormText( page, SWT.NONE ); message.setLayoutData( gd() ); message.setBackground( getSite().getShell().getDisplay().getSystemColor( SWT.COLOR_WHITE ) ); message.setText( error, false, false ); addPage( page ); setPageText( 0, errorPageTitle.text() ); } } /** * Returns the definition loader to be used with this editor. The default implementation calls * <code>DefinitionLoader.sdef( getClass() )</code> and returns the result. This will load the definition * from an sdef file with the same name as the editor class. * * @since 8.1 */ protected DefinitionLoader getDefinitionLoader() { return DefinitionLoader.sdef( getClass() ); } /** * Returns the page definition corresponding to the specified id. The default implementation relies on * the {@link #getDefinitionLoader()} method. * * @since 8.1 * @param pageDefinitionId the page definition id or null to load the first page definition that's found */ protected Reference<EditorPageDef> getDefinition( final String pageDefinitionId ) { return getDefinitionLoader().page( pageDefinitionId ); } /** * Creates an editor page based on the page definition. * * @since 8.1 * @param pageDefinitionId the page definition id * @return the created page * @throws IllegalArgumentException if the definition is not found */ protected IEditorPart createPage( final String pageDefinitionId ) { IEditorPart page = null; final Reference<EditorPageDef> definition = getDefinition( pageDefinitionId ); if( definition != null ) { page = createPage( definition ); } else { throw new IllegalArgumentException( failedToFindDefinition.format( pageDefinitionId ) ); } return page; } /** * Creates an editor page based on the page definition. * * @since 8.1 * @param definition the page definition * @return the created page */ protected IEditorPart createPage( final Reference<EditorPageDef> definition ) { IEditorPart page = null; final EditorPageDef def = definition.resolve(); if( def instanceof MasterDetailsEditorPageDef ) { page = new MasterDetailsEditorPage( this, getModelElement(), definition ); } else if( def instanceof FormEditorPageDef ) { page = new FormEditorPage( this, getModelElement(), definition ); } else if( def instanceof DiagramEditorPageDef ) { final Bundle bundle = Platform.getBundle( "org.eclipse.sapphire.ui.swt.gef" ); if( bundle != null ) { try { final Class<?> cl = bundle.loadClass( "org.eclipse.sapphire.ui.swt.gef.SapphireDiagramEditor" ); final Constructor<?> constructor = cl.getConstructors()[ 0 ]; page = (IEditorPart) constructor.newInstance( this, getModelElement(), definition ); } catch( final Exception e ) { Sapphire.service( LoggingService.class ).log( e ); } } } else { throw new IllegalStateException(); } return page; } public final Object getPage() { final int pageIndex = getActivePage(); if( pageIndex == -1 ) { return null; } else { return this.pages.get( pageIndex ); } } public final void showPage( final Object page ) { final int index = this.pages.indexOf( page ); setActivePage( index ); } public final void showPage( final SapphireEditorPagePart editorPagePart ) { for( int i = 0, n = getPageCount(); i < n; i++ ) { final Object page = this.pages.get( i ); if( page instanceof EditorPagePresentation && ( (EditorPagePresentation) page ).getPart() == editorPagePart ) { setActivePage( i ); return; } } } @Override protected void pageChange( final int pageIndex ) { if( this.ignorePageChange ) { return; } final Object newPage = this.pages.get( pageIndex ); if( newPage instanceof DeferredPage ) { BusyIndicator.showWhile ( getContainer().getDisplay(), new Runnable() { @Override public void run() { final IEditorPart page = createPage( ( (DeferredPage) newPage ).getDefinitionId() ); if( page != null ) { try { if( page instanceof IFormPage ) { addPage( pageIndex, (IFormPage) page ); } else { addPage( pageIndex, page, getEditorInput() ); } for( int i = 0; i < SapphireEditor.this.pages.size(); i++ ) { final Object p = SapphireEditor.this.pages.get( i ); if( p == newPage ) { SapphireEditor.this.ignorePageChange = true; removePage( i ); SapphireEditor.this.ignorePageChange = false; break; } } setActivePage( pageIndex ); } catch( final PartInitException e ) { Sapphire.service( LoggingService.class ).log( e ); } } } } ); } super.pageChange( pageIndex ); setLastActivePage( pageIndex ); if( this.outline != null && ! this.outline.isDisposed() ) { this.outline.refresh(); } refreshPropertiesViewContribution(); final Object page = this.pages.get( pageIndex ); if( page instanceof SapphireEditorFormPage ) { ( (SapphireEditorFormPage) page ).setFocus(); } } public void doSave( final IProgressMonitor monitor ) { if( this.model != null ) { try { this.model.resource().save(); } catch( ResourceStoreException e ) { Sapphire.service( LoggingService.class ).log( e ); } } final Iterator<?> pages = this.pages.iterator(); while( pages.hasNext() ) { final Object page = pages.next(); if( page instanceof IEditorPart ) { ( (IEditorPart) page ).doSave( new NullProgressMonitor() );; } } } public void doSaveAs() { throw new UnsupportedOperationException(); } public boolean isSaveAsAllowed() { return false; } protected final void createFileChangeListener() { this.fileChangeListener = new IResourceChangeListener() { public void resourceChanged( final IResourceChangeEvent event ) { handleFileChangedEvent( event ); } }; ResourcesPlugin.getWorkspace().addResourceChangeListener( this.fileChangeListener, IResourceChangeEvent.POST_CHANGE ); } protected final void handleFileChangedEvent( final IResourceChangeEvent event ) { final IResourceDelta delta = event.getDelta(); if( delta != null && getFile() != null ) { final IResourceDelta localDelta = delta.findMember( getFile().getFullPath() ); if( localDelta != null ) { PlatformUI.getWorkbench().getDisplay().asyncExec ( new Runnable() { public void run() { if( localDelta.getKind() == IResourceDelta.REMOVED ) { getSite().getPage().closeEditor( SapphireEditor.this, false ); } } } ); } } } @Override public void dispose() { super.dispose(); if( this.fileChangeListener != null ) { ResourcesPlugin.getWorkspace().removeResourceChangeListener( this.fileChangeListener ); this.fileChangeListener = null; } this.imageCache.dispose(); this.imageCache = null; this.actionsManager.dispose(); this.actionsManager = null; if( this.model != null ) { this.model.dispose(); this.model = null; } if( this.serviceContext != null ) { this.serviceContext.dispose(); this.serviceContext = null; } this.outline = null; this.propertiesViewPage = null; this.propertiesViewContributionChangeListener = null; } @Override public final void close() { dispose(); } @Override @SuppressWarnings( "rawtypes" ) public Object getAdapter( final Class type ) { if( type == IContentOutlinePage.class ) { if( this.outline == null || this.outline.isDisposed() ) { this.outline = new SapphireEditorContentOutline( this ); } return this.outline; } else if( type == IPropertySheetPage.class ) { if( this.propertiesViewPage == null ) { this.propertiesViewPage = new SapphirePropertySheetPage(); this.propertiesViewContributionChangeListener = new Listener() { @Override public void handle( final Event event ) { if( event instanceof SapphireEditorPagePart.PropertiesViewContributionChangedEvent ) { final SapphireEditorPagePart.PropertiesViewContributionChangedEvent evt = (SapphireEditorPagePart.PropertiesViewContributionChangedEvent) event; SapphireEditor.this.propertiesViewPage.setPart( evt.contribution() ); } } }; refreshPropertiesViewContribution(); } return this.propertiesViewPage; } return super.getAdapter( type ); } public final List<SapphireEditorPagePart> getEditorPageParts() { final ListFactory<SapphireEditorPagePart> parts = ListFactory.start(); for( Object page : this.pages ) { if( page instanceof EditorPagePresentation ) { parts.add( ( (EditorPagePresentation) page ).getPart() ); } } return parts.result(); } public final SapphireEditorPagePart getEditorPagePart( final String name ) { for( Object page : this.pages ) { if( page instanceof EditorPagePresentation && ( (EditorPagePresentation) page ).getPart().definition().getPageName().content().equalsIgnoreCase( name ) ) { return ( (EditorPagePresentation) page ).getPart(); } } return null; } private void refreshPropertiesViewContribution() { if( this.propertiesViewPage != null ) { for( SapphireEditorPagePart editorPagePart : getEditorPageParts() ) { editorPagePart.detach( this.propertiesViewContributionChangeListener ); } PropertiesViewContributionPart contribution = null; final Object page = getPage(); if( page instanceof EditorPagePresentation ) { final SapphireEditorPagePart editorPagePart = ( (EditorPagePresentation) page ).getPart(); editorPagePart.attach( this.propertiesViewContributionChangeListener ); contribution = editorPagePart.getPropertiesViewContribution(); } this.propertiesViewPage.setPart( contribution ); } } public final IContentOutlinePage getContentOutlineForActivePage() { final int activePageIndex = getActivePage(); final Object page = this.pages.get( activePageIndex ); return getContentOutline( page ); } public IContentOutlinePage getContentOutline( final Object page ) { if( page instanceof MasterDetailsEditorPage ) { final MasterDetailsEditorPage mdpage = (MasterDetailsEditorPage) page; return mdpage.getContentOutlinePage(); } else if (page instanceof IEditorPart) { if (((IEditorPart)page).getAdapter( IContentOutlinePage.class ) != null) { return (IContentOutlinePage)((IEditorPart)page).getAdapter( IContentOutlinePage.class ); } } return null; } // ********************* // ISapphirePart Methods // ********************* public ISapphirePart parent() { return null; } @SuppressWarnings( "unchecked" ) public <T> T nearest( final Class<T> partType ) { if( partType.isAssignableFrom( getClass() ) ) { return (T) this; } else { return null; } } public Set<String> getActionContexts() { return Collections.emptySet(); } public final String getMainActionContext() { return this.actionsManager.getMainActionContext(); } public final SapphireActionGroup getActions() { return this.actionsManager.getActions(); } public final SapphireActionGroup getActions( final String context ) { return this.actionsManager.getActions( context ); } public final SapphireAction getAction( final String id ) { return this.actionsManager.getAction( id ); } public Status validation() { throw new UnsupportedOperationException(); } public IContext getDocumentationContext() { return null; } public SwtResourceCache getSwtResourceCache() { return this.imageCache; } public void collectAllReferencedProperties( final Set<PropertyDef> collection ) { throw new UnsupportedOperationException(); } public <A> A adapt( final Class<A> adapterType ) { A result = null; if( adapterType == IEditorPart.class ) { result = adapterType.cast( getActiveEditor() ); } if( result == null && adapterType == IEditorSite.class ) { result = adapterType.cast( getEditorSite() ); } if( result == null ) { result = adapterType.cast( getAdapter( adapterType ) ); } if( result == null && parent() != null ) { result = parent().adapt( adapterType ); } return result; } public final <S extends Service> S service( final Class<S> serviceType ) { final List<S> services = services( serviceType ); return ( services.isEmpty() ? null : services.get( 0 ) ); } public final <S extends Service> List<S> services( final Class<S> serviceType ) { if( this.serviceContext == null ) { this.serviceContext = new PartServiceContext( this ); } return this.serviceContext.services( serviceType ); } private static final class DeferredPage extends Composite { private final String definitionId; public DeferredPage( final Composite parent, final String definitionId ) { super( parent, SWT.NONE ); this.definitionId = definitionId; } public String getDefinitionId() { return this.definitionId; } } }