]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/SimanticsDialog.java
Merge remote-tracking branch 'origin/svn' commit 'ccc1271c9d6657fb9dcf4cf3cb115fa0c8c...
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / SimanticsDialog.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2012 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.browsing.ui.swt;\r
13 \r
14 import java.util.Collections;\r
15 import java.util.Map;\r
16 import java.util.Set;\r
17 \r
18 import org.eclipse.jface.action.IMenuManager;\r
19 import org.eclipse.jface.dialogs.Dialog;\r
20 import org.eclipse.jface.resource.LocalResourceManager;\r
21 import org.eclipse.jface.viewers.ISelectionProvider;\r
22 import org.eclipse.swt.SWT;\r
23 import org.eclipse.swt.dnd.DND;\r
24 import org.eclipse.swt.dnd.DragSource;\r
25 import org.eclipse.swt.dnd.DragSourceListener;\r
26 import org.eclipse.swt.dnd.Transfer;\r
27 import org.eclipse.swt.widgets.Composite;\r
28 import org.eclipse.swt.widgets.Control;\r
29 import org.eclipse.swt.widgets.Shell;\r
30 import org.eclipse.ui.IMemento;\r
31 import org.eclipse.ui.ISelectionListener;\r
32 import org.simantics.Simantics;\r
33 import org.simantics.browsing.ui.BuiltinKeys;\r
34 import org.simantics.browsing.ui.GraphExplorer;\r
35 import org.simantics.browsing.ui.NodeContext;\r
36 import org.simantics.browsing.ui.common.ColumnKeys;\r
37 import org.simantics.browsing.ui.common.node.IDropTargetNode;\r
38 import org.simantics.browsing.ui.graph.impl.GraphInputSources;\r
39 import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;\r
40 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
41 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
42 import org.simantics.db.management.ISessionContext;\r
43 import org.simantics.project.ProjectKeys;\r
44 import org.simantics.ui.dnd.LocalObjectTransfer;\r
45 import org.simantics.ui.dnd.LocalSelectionDragSourceListener;\r
46 import org.simantics.ui.dnd.NoImageDragSourceEffect;\r
47 import org.simantics.utils.ObjectUtils;\r
48 import org.simantics.utils.datastructures.Function;\r
49 import org.simantics.utils.datastructures.disposable.DisposeState;\r
50 import org.simantics.utils.datastructures.hints.HintContext;\r
51 import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
52 import org.simantics.utils.datastructures.hints.HintTracker;\r
53 import org.simantics.utils.datastructures.hints.IHintContext;\r
54 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
55 import org.simantics.utils.datastructures.hints.IHintListener;\r
56 import org.simantics.utils.datastructures.hints.IHintObservable;\r
57 import org.simantics.utils.datastructures.hints.IHintTracker;\r
58 \r
59 public abstract class SimanticsDialog extends Dialog {\r
60 \r
61     private final WidgetSupportImpl          widgetSupport = new WidgetSupportImpl();\r
62 \r
63     protected IHintContext                   factoryHints = new HintContext();\r
64 \r
65     protected LocalResourceManager           resourceManager;\r
66 \r
67     protected ISelectionListener             workbenchSelectionListener;\r
68 \r
69     protected Composite                      parent;\r
70 \r
71     private Map<String, String>              args;\r
72 \r
73 //    private ISessionContextProvider          contextProvider;\r
74 \r
75     private ISessionContext                  sessionContext;\r
76 \r
77     protected IMemento                       memento;\r
78 \r
79     //private IHintTracker                     sessionContextTracker = new SessionContextProjectTracker();\r
80 \r
81     private SessionContextInputSource        inputSource           = GraphInputSources.projectSource();\r
82 \r
83     private DisposeState                     disposeState          = DisposeState.Alive;\r
84     \r
85     private final String title;\r
86 \r
87 //    protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {\r
88 //        @Override\r
89 //        public void sessionContextChanged(SessionContextChangedEvent event) {\r
90 //            sessionContext = event.getNewValue();\r
91 //            sessionContextTracker.track(sessionContext);\r
92 //        }\r
93 //    };\r
94 \r
95     abstract protected void createControls(Composite body, ISessionContext context, WidgetSupport support);\r
96 \r
97     public SimanticsDialog(Shell shell, String title) {\r
98         super(shell);\r
99         this.title = title;\r
100     }\r
101 \r
102     @Override\r
103     protected void configureShell(Shell shell) {\r
104         super.configureShell(shell);\r
105         if (title != null) {\r
106                         shell.setText(title);\r
107                 }\r
108     }\r
109     \r
110     protected Transfer[] getAcceptedDataTypes() {\r
111         return new Transfer[] {  LocalObjectTransfer.getTransfer() };\r
112     }\r
113 \r
114     protected void handleDrop(Object data, NodeContext target) {\r
115         if (target != null) {\r
116             Object input = target.getConstant(BuiltinKeys.INPUT);\r
117             //System.out.println("DROPPED " + data + " ON " + target);\r
118             if (input instanceof IDropTargetNode)\r
119                 ((IDropTargetNode) input).drop(data);\r
120         }\r
121     }\r
122 \r
123     protected Object createDragSource(GraphExplorer explorer) {\r
124         ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);\r
125 \r
126         DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);\r
127 \r
128         Control control = explorer.getControl();\r
129         DragSource source = new DragSource(control, DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);\r
130         source.setTransfer(new Transfer[] {LocalObjectTransfer.getTransfer()});\r
131         source.addDragListener(listener);\r
132         source.setDragSourceEffect(new NoImageDragSourceEffect(control));\r
133 \r
134         return listener;\r
135     }\r
136 \r
137     /**\r
138      * @return the set of <code>org.eclipse.ui.context</code> contexts to\r
139      *         activate for this view site\r
140      */\r
141     protected Set<String> getUiContexts() {\r
142         return Collections.emptySet();\r
143     }\r
144 \r
145     /**\r
146      * The default hint tracker that will be active if\r
147      * {@link SimanticsViewBase#setSessionContextTracker(IHintTracker) is\r
148      * not called.\r
149      */\r
150     public class SessionContextProjectTracker extends HintTracker {\r
151         public SessionContextProjectTracker() {\r
152             IHintListener activeProjectListener = new HintListenerAdapter() {\r
153                 @Override\r
154                 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
155                     applySessionContext(getSessionContext());\r
156                 }\r
157             };\r
158             addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);\r
159         }\r
160     }\r
161 \r
162 //    protected void setSessionContextTracker(IHintTracker tracker) {\r
163 //        this.sessionContextTracker = tracker;\r
164 //    }\r
165 \r
166     protected void setInputSource(SessionContextInputSource source) {\r
167         this.inputSource = source;\r
168     }\r
169 \r
170     protected SessionContextInputSource getInputSource() {\r
171         return inputSource;\r
172     }\r
173 \r
174     protected Map<String, String> getViewArguments() {\r
175         return args;\r
176     }\r
177 \r
178     protected DisposeState getDisposeState() {\r
179         return disposeState;\r
180     }\r
181 \r
182     public ISessionContext getSessionContext() {\r
183         return Simantics.getSessionContext();\r
184     }\r
185 \r
186 //    public ISessionContextProvider getSessionContextProvider() {\r
187 //        return contextProvider;\r
188 //    }\r
189 \r
190     protected final void attachToSession() {\r
191         // Track active ISessionContext changes\r
192         //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());\r
193 //        contextProvider.addContextChangedListener(contextChangeListener);\r
194 \r
195         // Start tracking the current session context for input changes.\r
196         // This will/must cause applySessionContext to get called.\r
197         // Doing the applySessionContext initialization this way\r
198         // instead of directly calling it will also make sure that\r
199         // applySessionContext is only called once when first initialized,\r
200         // and not twice like with the direct invocation.\r
201         this.sessionContext = getSessionContext();\r
202         applySessionContext(this.sessionContext);\r
203 //        sessionContextTracker.track(sessionContext);\r
204     }\r
205 \r
206     // /////////////////////////////////////////////////////////////////////////\r
207     // Override / implement these:\r
208 \r
209     /**\r
210      * Override this method and provide a proper context menu initializer if you\r
211      * want to have this base class initialize one for you.\r
212      * \r
213      * @return the initializer to be used by {@link #createControls(Composite)}\r
214      */\r
215     protected IContextMenuInitializer getContextMenuInitializer() {\r
216         String contextMenuId = getContextMenuId();\r
217         if(contextMenuId != null) {\r
218             return new ContextMenuInitializer(contextMenuId);\r
219         } else {\r
220             return null;\r
221         }\r
222     }\r
223 \r
224     protected String getContextMenuId() {\r
225         return null;\r
226     }\r
227 \r
228     protected int getStyle() {\r
229         return SWT.NONE;\r
230     }\r
231     \r
232     /**\r
233      * @param parent\r
234      * @return\r
235      */\r
236     protected GraphExplorer createExplorerControl(Composite parent) {\r
237         return GraphExplorerFactory.getInstance()\r
238         .selectionDataResolver(new DefaultSelectionDataResolver())\r
239         .create(parent, getStyle());\r
240     }\r
241 \r
242     /**\r
243      * Override to customize the addition of listeners a newly created\r
244      * GraphExplorer.\r
245      * \r
246      * @param explorer\r
247      */\r
248     protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {\r
249         addSelectionInputListeners(explorer, menuManager);\r
250     }\r
251 \r
252     protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {\r
253         // Consider ENTER presses to simulate mouse left button double clicks\r
254         explorer.addListener(new DefaultKeyListener(Simantics.getSessionContextProvider(), explorer, new Function<String[]>() {\r
255             @Override\r
256             public String[] execute(Object... obj) {\r
257                 return new String[] { getEditingColumn((NodeContext) obj[0]) };\r
258             }\r
259         }));\r
260         // Default double click handling\r
261         explorer.addListener(new DefaultMouseListener(explorer));\r
262     }\r
263 \r
264     protected String getEditingColumn(NodeContext context) {\r
265         return ColumnKeys.SINGLE;\r
266     }\r
267 \r
268     // Needed for preventing unnecessary re-initialization of the explorer with the same input.\r
269     private Object currentInput;\r
270 \r
271     protected boolean isImportantInput(Object previousInput, Object input) {\r
272         return !ObjectUtils.objectEquals(previousInput, input);\r
273     }\r
274 \r
275     /**\r
276      * Invoke this to reinitialize the explorer and reset its input. The input\r
277      * will be resolved from the specified ISessionContext based on the\r
278      * {@link SessionContextInputSource} that is currently in use. If the input\r
279      * is identical to the previous input, nothing will be done.\r
280      * \r
281      * @param context\r
282      */\r
283     protected final boolean applySessionContext(ISessionContext context) {\r
284         \r
285         // If control is not alive anymore, do nothing.\r
286 //        System.out.println(this + ": applySessionContext(" + context + "), explorer="  + explorer);\r
287         if (disposeState != DisposeState.Alive)\r
288             return false;\r
289 \r
290         this.sessionContext = context;\r
291         Object input = getInputSource().get(context);\r
292 //        System.out.println("SimanticsView applySessionContext: " + input);\r
293         if (!isImportantInput(currentInput, input))\r
294             return false;\r
295 \r
296 //        System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");\r
297 //        initializeExplorer(explorer, context);\r
298 //        System.out.println(this + ": setRoot(" + input + ")");\r
299 //        explorer.setRoot(input);\r
300 \r
301         currentInput = input;\r
302 //        System.out.println("SimanticsView new input: " + currentInput);\r
303 \r
304         widgetSupport.fireInput(context, input);\r
305 \r
306         // Start tracking the session context.\r
307         //\r
308         // If this is not the same session that is currently tracked, it will\r
309         // cause IHintListeners of the sessionContextTracker to fire.\r
310         // For this we need the above input equality (identity) checking.\r
311         // This is here just to make sure that we are tracking the correct\r
312         // session context.\r
313         //sessionContextTracker.track(sessionContext);\r
314         applySessionContext(context);\r
315 \r
316         return true;\r
317     }\r
318 \r
319         protected Control createDialogArea(Composite parent) {\r
320 //              parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_GREEN));\r
321             this.parent = parent;\r
322                 Composite composite = (Composite)super.createDialogArea(parent);\r
323 //              parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLUE));\r
324                 createControls(composite, sessionContext, widgetSupport);\r
325                 attachToSession();\r
326                 return composite;\r
327         }\r
328         \r
329         @Override\r
330         protected Control createContents(Composite parent) {\r
331 //              parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_RED));\r
332                 return super.createContents(parent);\r
333         }\r
334     \r
335         protected Object getSelection() {\r
336                 return null;\r
337         }\r
338         \r
339 }\r