X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.swt%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fswt%2FGraphExplorerViewBase.java;h=72307b32f22ec8371841ed96ef4c469e7d85453a;hp=f748656a5ba10f484a1dd9701f7c4f24b185c7b7;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerViewBase.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerViewBase.java index f748656a5..72307b32f 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerViewBase.java +++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerViewBase.java @@ -1,544 +1,544 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.browsing.ui.swt; - -import java.util.Map; - -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.resource.LocalResourceManager; -import org.eclipse.jface.viewers.ISelectionProvider; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.ui.IMemento; -import org.eclipse.ui.ISelectionListener; -import org.eclipse.ui.IViewSite; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.ViewPart; -import org.simantics.browsing.ui.Column; -import org.simantics.browsing.ui.GraphExplorer; -import org.simantics.browsing.ui.NodeContext; -import org.simantics.browsing.ui.common.ColumnKeys; -import org.simantics.browsing.ui.common.views.IViewArguments; -import org.simantics.browsing.ui.graph.impl.SessionContextInputSource; -import org.simantics.db.Session; -import org.simantics.db.common.request.Queries; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.management.ISessionContext; -import org.simantics.db.management.ISessionContextChangedListener; -import org.simantics.db.management.ISessionContextProvider; -import org.simantics.db.management.SessionContextChangedEvent; -import org.simantics.project.IProject; -import org.simantics.project.ProjectKeys; -import org.simantics.ui.SimanticsUI; -import org.simantics.ui.dnd.BasicDragSource; -import org.simantics.ui.dnd.SessionContainer; -import org.simantics.ui.workbench.IPropertyPage; -import org.simantics.utils.ObjectUtils; -import org.simantics.utils.datastructures.Function; -import org.simantics.utils.datastructures.disposable.DisposeState; -import org.simantics.utils.datastructures.hints.HintListenerAdapter; -import org.simantics.utils.datastructures.hints.HintTracker; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.hints.IHintListener; -import org.simantics.utils.datastructures.hints.IHintObservable; -import org.simantics.utils.datastructures.hints.IHintTracker; -import org.simantics.utils.ui.LayoutUtils; - -/** - * An abstract base Eclipse workbench ViewPart for use in situations where a - * tree-based GraphExplorer graph model browser is needed. - * - *

- * Override to customize behavior: - *

- *

- * - *

- * You can invoke the following methods from within - * {@link #createControls(Composite)} to customize how the view keeps track of - * the active ISessionContext and how the view resolves the input object of the - * GraphExplorer control. - *

- *

- * - * @author Tuukka Lehtonen - * @deprecated in favor of org.simantics.views.swt.ModelledView - */ -public abstract class GraphExplorerViewBase extends ViewPart { - - /** - * The default hint tracker that will be active if - * {@link GraphExplorerViewBase#setSessionContextTracker(IHintTracker) is - * not called. - */ - public class SessionContextProjectTracker extends HintTracker { - public SessionContextProjectTracker() { - IHintListener activeProjectListener = new HintListenerAdapter() { - @Override - public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { - applySessionContext(getSessionContext()); - } - }; - addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener); - } - } - - /** - * The default implementation of a {@link SessionContextInputSource} that - * will be active if - * {@link GraphExplorerViewBase#setInputSource(SessionContextInputSource)} - * is not called. - */ - public class SessionContextProjectSource implements SessionContextInputSource { - /** - * Returns the input object used by this GraphExplorer view. This object - * will be the starting point for all content shown in this explorer tree. - * - * @param sessionContext a valid database session context - * @return the root object of the graph explorer tree or null - * to indicate that there is no input and nothing should be shown. - */ - @Override - public Object get(ISessionContext ctx) { - if (ctx == null) - return GraphExplorer.EMPTY_INPUT; - - String inputId = getViewArguments().get(IViewArguments.INPUT); - if (inputId != null) { - try { - return ctx.getSession().syncRequest(Queries.resource(inputId)); - } catch (DatabaseException e) { - // Ok, the view argument was invalid. Just continue to the next - // method. - } - } - - Object input = GraphExplorer.EMPTY_INPUT; - IProject project2 = ctx.getHint(ProjectKeys.KEY_PROJECT); - if (project2 != null) - input = project2.get(); - return input; - } - - @Override - public IWorkbenchPart getProvider() { - return null; - } - - } - - protected LocalResourceManager resourceManager; - - protected ISelectionListener workbenchSelectionListener; - - protected Composite parent; - - protected GraphExplorer explorer; - - protected IMenuManager menuManager; - - private Map args; - - private ISessionContextProvider contextProvider; - - private ISessionContext sessionContext; - - private Object dragSource; - - protected IMemento memento; - - private IHintTracker sessionContextTracker = new SessionContextProjectTracker(); - - private SessionContextInputSource inputSource = new SessionContextProjectSource(); - - private DisposeState disposeState = DisposeState.Alive; - - protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() { - @Override - public void sessionContextChanged(SessionContextChangedEvent event) { - sessionContext = event.getNewValue(); - sessionContextTracker.track(sessionContext); - } - }; - - protected void setSessionContextTracker(IHintTracker tracker) { - this.sessionContextTracker = tracker; - } - - protected void setInputSource(SessionContextInputSource source) { - this.inputSource = source; - } - - protected SessionContextInputSource getInputSource() { - return inputSource; - } - - protected Map getViewArguments() { - return args; - } - - protected DisposeState getDisposeState() { - return disposeState; - } - - public ISessionContext getSessionContext() { - return sessionContext; - } - - public ISessionContextProvider getSessionContextProvider() { - return contextProvider; - } - - @Override - public void createPartControl(Composite parent) { - this.parent = parent; - this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay())); - - contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow()); - createControls(parent); - attachToSession(); - } - - /** - * Invoked when this viewpart is disposed. Unhooks the view from its - * ISessionContextProvider. Overriding is allowed but super.dispose() must - * be called. - * - * @see org.eclipse.ui.part.WorkbenchPart#dispose() - */ - @Override - public void dispose() { - disposeState = DisposeState.Disposing; - try { - //System.out.println(this + ".GraphExplorerViewBase.dispose()"); - if (contextProvider != null) { - contextProvider.removeContextChangedListener(contextChangeListener); - contextProvider = null; - } - sessionContextTracker.untrack(); - resourceManager.dispose(); - resourceManager = null; - args = null; - explorer = null; - sessionContext = null; - dragSource = null; - parent = null; - super.dispose(); - } finally { - disposeState = DisposeState.Disposed; - } - } - - @Override - public void setFocus() { - if (explorer != null && !explorer.isDisposed()) - explorer.setFocus(); - } - - @Override - public void init(IViewSite site) throws PartInitException { - super.init(site); - this.args = ViewArgumentUtils.parseViewArguments(this); - } - - @Override - public void init(IViewSite site, IMemento memento) throws PartInitException { - super.init(site, memento); - this.args = ViewArgumentUtils.parseViewArguments(this); - this.memento = memento; - } - - @Override - public void saveState(IMemento memento) { - if (this.memento != null) { - memento.putMemento(this.memento); - } -// if (explorer != null) -// explorer.saveState(memento); - } - - protected void setWorkbenchListeners() { - if (workbenchSelectionListener == null) { - - ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class); - - getSite().setSelectionProvider(selectionProvider); - - // Listen to the workbench selection also to propagate it to - // the explorer also. - workbenchSelectionListener = new DefaultExplorerSelectionListener(this, explorer); - getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener); - } - } - - protected void removeWorkbenchListeners() { - // Remember to remove the installed workbench selection listener - if (workbenchSelectionListener != null) { - getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener); - workbenchSelectionListener = null; - - getSite().setSelectionProvider(null); - } - } - - protected final void attachToSession() { - // Track active ISessionContext changes - //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow()); - contextProvider.addContextChangedListener(contextChangeListener); - - // Start tracking the current session context for input changes. - // This will/must cause applySessionContext to get called. - // Doing the applySessionContext initialization this way - // instead of directly calling it will also make sure that - // applySessionContext is only called once when first initialized, - // and not twice like with the direct invocation. - this.sessionContext = contextProvider.getSessionContext(); - sessionContextTracker.track(sessionContext); - } - - // ///////////////////////////////////////////////////////////////////////// - // Override / implement these: - -// /** -// * Returns an ID that is used for persisting a GraphExplorer instance. -// * -// * Used for restoreState(IMemento) and -// * restoreState(IMemento) in OntologyExplorer. Must be unique -// * within a workbench part. -// * -// * @return a unique name for this particular graph explorer view used for -// * saving and restoring the state of this view part -// */ -// public String getExplorerName() { -// return "GraphExplorerViewBase"; -// } - - protected Column[] getColumns() { - return null; - } - - /** - * Override this method to add controls to the view part. This is invoked - * before attaching the view part to a database session. - * - * @param parent - */ - protected void createControls(Composite parent) { - - parent.setLayout(LayoutUtils.createNoBorderGridLayout(1, false)); - - // Initialize explorer control. - explorer = createExplorerControl(parent); - - ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class); - Control control = explorer.getControl(); - - Column[] columns = getColumns(); - if(columns != null) - explorer.setColumns(columns); - - GridDataFactory.fillDefaults().grab(true, true).applyTo(control); - - // Initialize context menu if an initializer is provided. - IContextMenuInitializer cmi = getContextMenuInitializer(); - if (cmi != null) { - menuManager = cmi.createContextMenu(control, selectionProvider, getSite()); - } - - // Initialize DND. - dragSource = createDragSource(explorer); - - // Listeners are only added once per listener, not every time the - // session context changes. - addListeners(explorer, menuManager); - } - - /** - * Override this method and provide a proper context menu initializer if you - * want to have this base class initialize one for you. - * - * @return the initializer to be used by {@link #createControls(Composite)} - */ - protected IContextMenuInitializer getContextMenuInitializer() { - String contextMenuId = getContextMenuId(); - if(contextMenuId != null) { - return new ContextMenuInitializer(contextMenuId); - } else { - return null; - } - } - - /** - * @return the ID of the context menu to initialize for this this graph - * explorer view or null to not initialize a context - * menu - */ - protected String getContextMenuId() { - return null; - } - - protected int getStyle() { - return SWT.MULTI; - } - - /** - * @param parent - * @return - */ - protected GraphExplorer createExplorerControl(Composite parent) { - return GraphExplorerFactory.getInstance() - .selectionDataResolver(new DefaultSelectionDataResolver()) - .create(parent, getStyle()); - } - - /** - * Override to customize drag source initialization. This default - * implementation creates a {@link BasicDragSource}. The drag source is - * initialized when the active database session is set. - * - * @param explorer - * @return the object representing the drag source. If the object implements - * {@link SessionContainer}, its - * {@link SessionContainer#setSession(Session)} will be invoked - * every time the active database session changes. - */ - protected Object createDragSource(GraphExplorer explorer) { - ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class); - Control control = explorer.getControl(); - return new BasicDragSource(selectionProvider, control, null); - } - - protected void setupDragSource(Session session) { - if (dragSource instanceof SessionContainer) { - ((SessionContainer) dragSource).setSession(session); - } - } - - /** - * Override to customize the addition of listeners a newly created - * GraphExplorer. - * - * @param explorer - */ - protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) { - addSelectionInputListeners(explorer, menuManager); - } - - protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) { - // Consider ENTER presses to simulate mouse left button double clicks - explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function() { - @Override - public String[] execute(Object... obj) { - return new String[] { getEditingColumn((NodeContext) obj[0]) }; - } - })); - // Default double click handling - explorer.addListener(new DefaultMouseListener(explorer)); - } - - protected String getEditingColumn(NodeContext context) { - return ColumnKeys.SINGLE; - } - - /** - * Override to customize the initialization of the content provision and - * presentation of a GraphExplorer. This is called every time the input - * database session changes. - * - * @param explorer - * @param context may be null if there is no session - */ - protected void initializeExplorer(final GraphExplorer explorer, ISessionContext context) { - setupDragSource((context != null) ? context.getSession() : null); - } - - // Needed for preventing unnecessary re-initialization of the explorer with the same input. - private Object currentInput; - - protected boolean isImportantInput(Object previousInput, Object input) { - return !ObjectUtils.objectEquals(previousInput, input); - } - - /** - * Invoke this to reinitialize the explorer and reset its input. The input - * will be resolved from the specified ISessionContext based on the - * {@link SessionContextInputSource} that is currently in use. If the input - * is identical to the previous input, nothing will be done. - * - * @param context - */ - protected final boolean applySessionContext(ISessionContext context) { - // If control is not alive anymore, do nothing. -// System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer); - if (disposeState != DisposeState.Alive) - return false; - - this.sessionContext = context; - Object input = inputSource.get(context); - if (!isImportantInput(currentInput, input)) - return false; - -// System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")"); - initializeExplorer(explorer, context); -// System.out.println(this + ": setRoot(" + input + ")"); - explorer.setRoot(input); - - currentInput = input; - - // Start tracking the session context. - // - // If this is not the same session that is currently tracked, it will - // cause IHintListeners of the sessionContextTracker to fire. - // For this we need the above input equality (identity) checking. - // This is here just to make sure that we are tracking the correct - // session context. - sessionContextTracker.track(sessionContext); - - return true; - } - - @SuppressWarnings("rawtypes") - @Override - public Object getAdapter(Class adapter) { - - if (GraphExplorer.class == adapter) - return explorer; - else if(ISessionContextProvider.class == adapter) - return getSessionContextProvider(); - else if(IPropertyPage.class == adapter) - return getPropertyPage(); - - return super.getAdapter(adapter); - - } - - protected IPropertyPage getPropertyPage() { - return null; - } - - - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.browsing.ui.swt; + +import java.util.Map; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.part.ViewPart; +import org.simantics.browsing.ui.Column; +import org.simantics.browsing.ui.GraphExplorer; +import org.simantics.browsing.ui.NodeContext; +import org.simantics.browsing.ui.common.ColumnKeys; +import org.simantics.browsing.ui.common.views.IViewArguments; +import org.simantics.browsing.ui.graph.impl.SessionContextInputSource; +import org.simantics.db.Session; +import org.simantics.db.common.request.Queries; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.management.ISessionContextChangedListener; +import org.simantics.db.management.ISessionContextProvider; +import org.simantics.db.management.SessionContextChangedEvent; +import org.simantics.project.IProject; +import org.simantics.project.ProjectKeys; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.dnd.BasicDragSource; +import org.simantics.ui.dnd.SessionContainer; +import org.simantics.ui.workbench.IPropertyPage; +import org.simantics.utils.ObjectUtils; +import org.simantics.utils.datastructures.Function; +import org.simantics.utils.datastructures.disposable.DisposeState; +import org.simantics.utils.datastructures.hints.HintListenerAdapter; +import org.simantics.utils.datastructures.hints.HintTracker; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintListener; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.datastructures.hints.IHintTracker; +import org.simantics.utils.ui.LayoutUtils; + +/** + * An abstract base Eclipse workbench ViewPart for use in situations where a + * tree-based GraphExplorer graph model browser is needed. + * + *

+ * Override to customize behavior: + *

    + *
  • {@link #createControls(Composite)}
  • + *
  • {@link #createExplorerControl(Composite)}
  • + *
  • {@link #createDragSource(GraphExplorer)}
  • + *
  • {@link #getContextMenuId()}
  • + *
  • {@link #getContextMenuInitializer()}
  • + *
  • {@link #addListeners(GraphExplorer, IMenuManager)}
  • + *
+ *

+ * + *

+ * You can invoke the following methods from within + * {@link #createControls(Composite)} to customize how the view keeps track of + * the active ISessionContext and how the view resolves the input object of the + * GraphExplorer control. + *

    + *
  • {@link #setSessionContextTracker(IHintTracker)}
  • + *
  • {@link #setInputSource(SessionContextInputSource)}
  • + *
+ *

+ * + * @author Tuukka Lehtonen + * @deprecated in favor of org.simantics.views.swt.ModelledView + */ +public abstract class GraphExplorerViewBase extends ViewPart { + + /** + * The default hint tracker that will be active if + * {@link GraphExplorerViewBase#setSessionContextTracker(IHintTracker) is + * not called. + */ + public class SessionContextProjectTracker extends HintTracker { + public SessionContextProjectTracker() { + IHintListener activeProjectListener = new HintListenerAdapter() { + @Override + public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + applySessionContext(getSessionContext()); + } + }; + addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener); + } + } + + /** + * The default implementation of a {@link SessionContextInputSource} that + * will be active if + * {@link GraphExplorerViewBase#setInputSource(SessionContextInputSource)} + * is not called. + */ + public class SessionContextProjectSource implements SessionContextInputSource { + /** + * Returns the input object used by this GraphExplorer view. This object + * will be the starting point for all content shown in this explorer tree. + * + * @param sessionContext a valid database session context + * @return the root object of the graph explorer tree or null + * to indicate that there is no input and nothing should be shown. + */ + @Override + public Object get(ISessionContext ctx) { + if (ctx == null) + return GraphExplorer.EMPTY_INPUT; + + String inputId = getViewArguments().get(IViewArguments.INPUT); + if (inputId != null) { + try { + return ctx.getSession().syncRequest(Queries.resource(inputId)); + } catch (DatabaseException e) { + // Ok, the view argument was invalid. Just continue to the next + // method. + } + } + + Object input = GraphExplorer.EMPTY_INPUT; + IProject project2 = ctx.getHint(ProjectKeys.KEY_PROJECT); + if (project2 != null) + input = project2.get(); + return input; + } + + @Override + public IWorkbenchPart getProvider() { + return null; + } + + } + + protected LocalResourceManager resourceManager; + + protected ISelectionListener workbenchSelectionListener; + + protected Composite parent; + + protected GraphExplorer explorer; + + protected IMenuManager menuManager; + + private Map args; + + private ISessionContextProvider contextProvider; + + private ISessionContext sessionContext; + + private Object dragSource; + + protected IMemento memento; + + private IHintTracker sessionContextTracker = new SessionContextProjectTracker(); + + private SessionContextInputSource inputSource = new SessionContextProjectSource(); + + private DisposeState disposeState = DisposeState.Alive; + + protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() { + @Override + public void sessionContextChanged(SessionContextChangedEvent event) { + sessionContext = event.getNewValue(); + sessionContextTracker.track(sessionContext); + } + }; + + protected void setSessionContextTracker(IHintTracker tracker) { + this.sessionContextTracker = tracker; + } + + protected void setInputSource(SessionContextInputSource source) { + this.inputSource = source; + } + + protected SessionContextInputSource getInputSource() { + return inputSource; + } + + protected Map getViewArguments() { + return args; + } + + protected DisposeState getDisposeState() { + return disposeState; + } + + public ISessionContext getSessionContext() { + return sessionContext; + } + + public ISessionContextProvider getSessionContextProvider() { + return contextProvider; + } + + @Override + public void createPartControl(Composite parent) { + this.parent = parent; + this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay())); + + contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow()); + createControls(parent); + attachToSession(); + } + + /** + * Invoked when this viewpart is disposed. Unhooks the view from its + * ISessionContextProvider. Overriding is allowed but super.dispose() must + * be called. + * + * @see org.eclipse.ui.part.WorkbenchPart#dispose() + */ + @Override + public void dispose() { + disposeState = DisposeState.Disposing; + try { + //System.out.println(this + ".GraphExplorerViewBase.dispose()"); + if (contextProvider != null) { + contextProvider.removeContextChangedListener(contextChangeListener); + contextProvider = null; + } + sessionContextTracker.untrack(); + resourceManager.dispose(); + resourceManager = null; + args = null; + explorer = null; + sessionContext = null; + dragSource = null; + parent = null; + super.dispose(); + } finally { + disposeState = DisposeState.Disposed; + } + } + + @Override + public void setFocus() { + if (explorer != null && !explorer.isDisposed()) + explorer.setFocus(); + } + + @Override + public void init(IViewSite site) throws PartInitException { + super.init(site); + this.args = ViewArgumentUtils.parseViewArguments(this); + } + + @Override + public void init(IViewSite site, IMemento memento) throws PartInitException { + super.init(site, memento); + this.args = ViewArgumentUtils.parseViewArguments(this); + this.memento = memento; + } + + @Override + public void saveState(IMemento memento) { + if (this.memento != null) { + memento.putMemento(this.memento); + } +// if (explorer != null) +// explorer.saveState(memento); + } + + protected void setWorkbenchListeners() { + if (workbenchSelectionListener == null) { + + ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class); + + getSite().setSelectionProvider(selectionProvider); + + // Listen to the workbench selection also to propagate it to + // the explorer also. + workbenchSelectionListener = new DefaultExplorerSelectionListener(this, explorer); + getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener); + } + } + + protected void removeWorkbenchListeners() { + // Remember to remove the installed workbench selection listener + if (workbenchSelectionListener != null) { + getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener); + workbenchSelectionListener = null; + + getSite().setSelectionProvider(null); + } + } + + protected final void attachToSession() { + // Track active ISessionContext changes + //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow()); + contextProvider.addContextChangedListener(contextChangeListener); + + // Start tracking the current session context for input changes. + // This will/must cause applySessionContext to get called. + // Doing the applySessionContext initialization this way + // instead of directly calling it will also make sure that + // applySessionContext is only called once when first initialized, + // and not twice like with the direct invocation. + this.sessionContext = contextProvider.getSessionContext(); + sessionContextTracker.track(sessionContext); + } + + // ///////////////////////////////////////////////////////////////////////// + // Override / implement these: + +// /** +// * Returns an ID that is used for persisting a GraphExplorer instance. +// * +// * Used for restoreState(IMemento) and +// * restoreState(IMemento) in OntologyExplorer. Must be unique +// * within a workbench part. +// * +// * @return a unique name for this particular graph explorer view used for +// * saving and restoring the state of this view part +// */ +// public String getExplorerName() { +// return "GraphExplorerViewBase"; +// } + + protected Column[] getColumns() { + return null; + } + + /** + * Override this method to add controls to the view part. This is invoked + * before attaching the view part to a database session. + * + * @param parent + */ + protected void createControls(Composite parent) { + + parent.setLayout(LayoutUtils.createNoBorderGridLayout(1, false)); + + // Initialize explorer control. + explorer = createExplorerControl(parent); + + ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class); + Control control = explorer.getControl(); + + Column[] columns = getColumns(); + if(columns != null) + explorer.setColumns(columns); + + GridDataFactory.fillDefaults().grab(true, true).applyTo(control); + + // Initialize context menu if an initializer is provided. + IContextMenuInitializer cmi = getContextMenuInitializer(); + if (cmi != null) { + menuManager = cmi.createContextMenu(control, selectionProvider, getSite()); + } + + // Initialize DND. + dragSource = createDragSource(explorer); + + // Listeners are only added once per listener, not every time the + // session context changes. + addListeners(explorer, menuManager); + } + + /** + * Override this method and provide a proper context menu initializer if you + * want to have this base class initialize one for you. + * + * @return the initializer to be used by {@link #createControls(Composite)} + */ + protected IContextMenuInitializer getContextMenuInitializer() { + String contextMenuId = getContextMenuId(); + if(contextMenuId != null) { + return new ContextMenuInitializer(contextMenuId); + } else { + return null; + } + } + + /** + * @return the ID of the context menu to initialize for this this graph + * explorer view or null to not initialize a context + * menu + */ + protected String getContextMenuId() { + return null; + } + + protected int getStyle() { + return SWT.MULTI; + } + + /** + * @param parent + * @return + */ + protected GraphExplorer createExplorerControl(Composite parent) { + return GraphExplorerFactory.getInstance() + .selectionDataResolver(new DefaultSelectionDataResolver()) + .create(parent, getStyle()); + } + + /** + * Override to customize drag source initialization. This default + * implementation creates a {@link BasicDragSource}. The drag source is + * initialized when the active database session is set. + * + * @param explorer + * @return the object representing the drag source. If the object implements + * {@link SessionContainer}, its + * {@link SessionContainer#setSession(Session)} will be invoked + * every time the active database session changes. + */ + protected Object createDragSource(GraphExplorer explorer) { + ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class); + Control control = explorer.getControl(); + return new BasicDragSource(selectionProvider, control, null); + } + + protected void setupDragSource(Session session) { + if (dragSource instanceof SessionContainer) { + ((SessionContainer) dragSource).setSession(session); + } + } + + /** + * Override to customize the addition of listeners a newly created + * GraphExplorer. + * + * @param explorer + */ + protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) { + addSelectionInputListeners(explorer, menuManager); + } + + protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) { + // Consider ENTER presses to simulate mouse left button double clicks + explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function() { + @Override + public String[] execute(Object... obj) { + return new String[] { getEditingColumn((NodeContext) obj[0]) }; + } + })); + // Default double click handling + explorer.addListener(new DefaultMouseListener(explorer)); + } + + protected String getEditingColumn(NodeContext context) { + return ColumnKeys.SINGLE; + } + + /** + * Override to customize the initialization of the content provision and + * presentation of a GraphExplorer. This is called every time the input + * database session changes. + * + * @param explorer + * @param context may be null if there is no session + */ + protected void initializeExplorer(final GraphExplorer explorer, ISessionContext context) { + setupDragSource((context != null) ? context.getSession() : null); + } + + // Needed for preventing unnecessary re-initialization of the explorer with the same input. + private Object currentInput; + + protected boolean isImportantInput(Object previousInput, Object input) { + return !ObjectUtils.objectEquals(previousInput, input); + } + + /** + * Invoke this to reinitialize the explorer and reset its input. The input + * will be resolved from the specified ISessionContext based on the + * {@link SessionContextInputSource} that is currently in use. If the input + * is identical to the previous input, nothing will be done. + * + * @param context + */ + protected final boolean applySessionContext(ISessionContext context) { + // If control is not alive anymore, do nothing. +// System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer); + if (disposeState != DisposeState.Alive) + return false; + + this.sessionContext = context; + Object input = inputSource.get(context); + if (!isImportantInput(currentInput, input)) + return false; + +// System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")"); + initializeExplorer(explorer, context); +// System.out.println(this + ": setRoot(" + input + ")"); + explorer.setRoot(input); + + currentInput = input; + + // Start tracking the session context. + // + // If this is not the same session that is currently tracked, it will + // cause IHintListeners of the sessionContextTracker to fire. + // For this we need the above input equality (identity) checking. + // This is here just to make sure that we are tracking the correct + // session context. + sessionContextTracker.track(sessionContext); + + return true; + } + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + + if (GraphExplorer.class == adapter) + return explorer; + else if(ISessionContextProvider.class == adapter) + return getSessionContextProvider(); + else if(IPropertyPage.class == adapter) + return getPropertyPage(); + + return super.getAdapter(adapter); + + } + + protected IPropertyPage getPropertyPage() { + return null; + } + + + +}