--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.browsing.ui.swt;\r
+\r
+import java.util.Collections;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DragSource;\r
+import org.eclipse.swt.dnd.DragSourceListener;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.ISelectionListener;\r
+import org.simantics.Simantics;\r
+import org.simantics.browsing.ui.BuiltinKeys;\r
+import org.simantics.browsing.ui.GraphExplorer;\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.common.ColumnKeys;\r
+import org.simantics.browsing.ui.common.node.IDropTargetNode;\r
+import org.simantics.browsing.ui.graph.impl.GraphInputSources;\r
+import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.project.ProjectKeys;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.LocalSelectionDragSourceListener;\r
+import org.simantics.ui.dnd.NoImageDragSourceEffect;\r
+import org.simantics.utils.ObjectUtils;\r
+import org.simantics.utils.datastructures.Function;\r
+import org.simantics.utils.datastructures.disposable.DisposeState;\r
+import org.simantics.utils.datastructures.hints.HintContext;\r
+import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
+import org.simantics.utils.datastructures.hints.HintTracker;\r
+import org.simantics.utils.datastructures.hints.IHintContext;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintListener;\r
+import org.simantics.utils.datastructures.hints.IHintObservable;\r
+import org.simantics.utils.datastructures.hints.IHintTracker;\r
+\r
+public abstract class SimanticsDialog extends Dialog {\r
+\r
+ private final WidgetSupportImpl widgetSupport = new WidgetSupportImpl();\r
+\r
+ protected IHintContext factoryHints = new HintContext();\r
+\r
+ protected LocalResourceManager resourceManager;\r
+\r
+ protected ISelectionListener workbenchSelectionListener;\r
+\r
+ protected Composite parent;\r
+\r
+ private Map<String, String> args;\r
+\r
+// private ISessionContextProvider contextProvider;\r
+\r
+ private ISessionContext sessionContext;\r
+\r
+ protected IMemento memento;\r
+\r
+ //private IHintTracker sessionContextTracker = new SessionContextProjectTracker();\r
+\r
+ private SessionContextInputSource inputSource = GraphInputSources.projectSource();\r
+\r
+ private DisposeState disposeState = DisposeState.Alive;\r
+ \r
+ private final String title;\r
+\r
+// protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {\r
+// @Override\r
+// public void sessionContextChanged(SessionContextChangedEvent event) {\r
+// sessionContext = event.getNewValue();\r
+// sessionContextTracker.track(sessionContext);\r
+// }\r
+// };\r
+\r
+ abstract protected void createControls(Composite body, ISessionContext context, WidgetSupport support);\r
+\r
+ public SimanticsDialog(Shell shell, String title) {\r
+ super(shell);\r
+ this.title = title;\r
+ }\r
+\r
+ @Override\r
+ protected void configureShell(Shell shell) {\r
+ super.configureShell(shell);\r
+ if (title != null) {\r
+ shell.setText(title);\r
+ }\r
+ }\r
+ \r
+ protected Transfer[] getAcceptedDataTypes() {\r
+ return new Transfer[] { LocalObjectTransfer.getTransfer() };\r
+ }\r
+\r
+ protected void handleDrop(Object data, NodeContext target) {\r
+ if (target != null) {\r
+ Object input = target.getConstant(BuiltinKeys.INPUT);\r
+ //System.out.println("DROPPED " + data + " ON " + target);\r
+ if (input instanceof IDropTargetNode)\r
+ ((IDropTargetNode) input).drop(data);\r
+ }\r
+ }\r
+\r
+ protected Object createDragSource(GraphExplorer explorer) {\r
+ ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);\r
+\r
+ DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);\r
+\r
+ Control control = explorer.getControl();\r
+ DragSource source = new DragSource(control, DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);\r
+ source.setTransfer(new Transfer[] {LocalObjectTransfer.getTransfer()});\r
+ source.addDragListener(listener);\r
+ source.setDragSourceEffect(new NoImageDragSourceEffect(control));\r
+\r
+ return listener;\r
+ }\r
+\r
+ /**\r
+ * @return the set of <code>org.eclipse.ui.context</code> contexts to\r
+ * activate for this view site\r
+ */\r
+ protected Set<String> getUiContexts() {\r
+ return Collections.emptySet();\r
+ }\r
+\r
+ /**\r
+ * The default hint tracker that will be active if\r
+ * {@link SimanticsViewBase#setSessionContextTracker(IHintTracker) is\r
+ * not called.\r
+ */\r
+ public class SessionContextProjectTracker extends HintTracker {\r
+ public SessionContextProjectTracker() {\r
+ IHintListener activeProjectListener = new HintListenerAdapter() {\r
+ @Override\r
+ public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
+ applySessionContext(getSessionContext());\r
+ }\r
+ };\r
+ addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);\r
+ }\r
+ }\r
+\r
+// protected void setSessionContextTracker(IHintTracker tracker) {\r
+// this.sessionContextTracker = tracker;\r
+// }\r
+\r
+ protected void setInputSource(SessionContextInputSource source) {\r
+ this.inputSource = source;\r
+ }\r
+\r
+ protected SessionContextInputSource getInputSource() {\r
+ return inputSource;\r
+ }\r
+\r
+ protected Map<String, String> getViewArguments() {\r
+ return args;\r
+ }\r
+\r
+ protected DisposeState getDisposeState() {\r
+ return disposeState;\r
+ }\r
+\r
+ public ISessionContext getSessionContext() {\r
+ return Simantics.getSessionContext();\r
+ }\r
+\r
+// public ISessionContextProvider getSessionContextProvider() {\r
+// return contextProvider;\r
+// }\r
+\r
+ protected final void attachToSession() {\r
+ // Track active ISessionContext changes\r
+ //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());\r
+// contextProvider.addContextChangedListener(contextChangeListener);\r
+\r
+ // Start tracking the current session context for input changes.\r
+ // This will/must cause applySessionContext to get called.\r
+ // Doing the applySessionContext initialization this way\r
+ // instead of directly calling it will also make sure that\r
+ // applySessionContext is only called once when first initialized,\r
+ // and not twice like with the direct invocation.\r
+ this.sessionContext = getSessionContext();\r
+ applySessionContext(this.sessionContext);\r
+// sessionContextTracker.track(sessionContext);\r
+ }\r
+\r
+ // /////////////////////////////////////////////////////////////////////////\r
+ // Override / implement these:\r
+\r
+ /**\r
+ * Override this method and provide a proper context menu initializer if you\r
+ * want to have this base class initialize one for you.\r
+ * \r
+ * @return the initializer to be used by {@link #createControls(Composite)}\r
+ */\r
+ protected IContextMenuInitializer getContextMenuInitializer() {\r
+ String contextMenuId = getContextMenuId();\r
+ if(contextMenuId != null) {\r
+ return new ContextMenuInitializer(contextMenuId);\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ protected String getContextMenuId() {\r
+ return null;\r
+ }\r
+\r
+ protected int getStyle() {\r
+ return SWT.NONE;\r
+ }\r
+ \r
+ /**\r
+ * @param parent\r
+ * @return\r
+ */\r
+ protected GraphExplorer createExplorerControl(Composite parent) {\r
+ return GraphExplorerFactory.getInstance()\r
+ .selectionDataResolver(new DefaultSelectionDataResolver())\r
+ .create(parent, getStyle());\r
+ }\r
+\r
+ /**\r
+ * Override to customize the addition of listeners a newly created\r
+ * GraphExplorer.\r
+ * \r
+ * @param explorer\r
+ */\r
+ protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {\r
+ addSelectionInputListeners(explorer, menuManager);\r
+ }\r
+\r
+ protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {\r
+ // Consider ENTER presses to simulate mouse left button double clicks\r
+ explorer.addListener(new DefaultKeyListener(Simantics.getSessionContextProvider(), explorer, new Function<String[]>() {\r
+ @Override\r
+ public String[] execute(Object... obj) {\r
+ return new String[] { getEditingColumn((NodeContext) obj[0]) };\r
+ }\r
+ }));\r
+ // Default double click handling\r
+ explorer.addListener(new DefaultMouseListener(explorer));\r
+ }\r
+\r
+ protected String getEditingColumn(NodeContext context) {\r
+ return ColumnKeys.SINGLE;\r
+ }\r
+\r
+ // Needed for preventing unnecessary re-initialization of the explorer with the same input.\r
+ private Object currentInput;\r
+\r
+ protected boolean isImportantInput(Object previousInput, Object input) {\r
+ return !ObjectUtils.objectEquals(previousInput, input);\r
+ }\r
+\r
+ /**\r
+ * Invoke this to reinitialize the explorer and reset its input. The input\r
+ * will be resolved from the specified ISessionContext based on the\r
+ * {@link SessionContextInputSource} that is currently in use. If the input\r
+ * is identical to the previous input, nothing will be done.\r
+ * \r
+ * @param context\r
+ */\r
+ protected final boolean applySessionContext(ISessionContext context) {\r
+ \r
+ // If control is not alive anymore, do nothing.\r
+// System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer);\r
+ if (disposeState != DisposeState.Alive)\r
+ return false;\r
+\r
+ this.sessionContext = context;\r
+ Object input = getInputSource().get(context);\r
+// System.out.println("SimanticsView applySessionContext: " + input);\r
+ if (!isImportantInput(currentInput, input))\r
+ return false;\r
+\r
+// System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");\r
+// initializeExplorer(explorer, context);\r
+// System.out.println(this + ": setRoot(" + input + ")");\r
+// explorer.setRoot(input);\r
+\r
+ currentInput = input;\r
+// System.out.println("SimanticsView new input: " + currentInput);\r
+\r
+ widgetSupport.fireInput(context, input);\r
+\r
+ // Start tracking the session context.\r
+ //\r
+ // If this is not the same session that is currently tracked, it will\r
+ // cause IHintListeners of the sessionContextTracker to fire.\r
+ // For this we need the above input equality (identity) checking.\r
+ // This is here just to make sure that we are tracking the correct\r
+ // session context.\r
+ //sessionContextTracker.track(sessionContext);\r
+ applySessionContext(context);\r
+\r
+ return true;\r
+ }\r
+\r
+ protected Control createDialogArea(Composite parent) {\r
+// parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_GREEN));\r
+ this.parent = parent;\r
+ Composite composite = (Composite)super.createDialogArea(parent);\r
+// parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLUE));\r
+ createControls(composite, sessionContext, widgetSupport);\r
+ attachToSession();\r
+ return composite;\r
+ }\r
+ \r
+ @Override\r
+ protected Control createContents(Composite parent) {\r
+// parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_RED));\r
+ return super.createContents(parent);\r
+ }\r
+ \r
+ protected Object getSelection() {\r
+ return null;\r
+ }\r
+ \r
+}\r