]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.ui/src/org/simantics/ui/workbench/GraphAccessViewPart.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / workbench / GraphAccessViewPart.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 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.ui.workbench;\r
13 \r
14 import org.eclipse.jface.action.IStatusLineManager;\r
15 import org.eclipse.swt.widgets.Composite;\r
16 import org.eclipse.ui.IActionBars;\r
17 import org.eclipse.ui.IMemento;\r
18 import org.eclipse.ui.IViewSite;\r
19 import org.eclipse.ui.PartInitException;\r
20 import org.eclipse.ui.part.ViewPart;\r
21 import org.simantics.db.ReadGraph;\r
22 import org.simantics.db.Session;\r
23 import org.simantics.db.common.request.ReadRequest;\r
24 import org.simantics.db.event.ChangeEvent;\r
25 import org.simantics.db.event.ChangeListener;\r
26 import org.simantics.db.exception.DatabaseException;\r
27 import org.simantics.db.management.ISessionContext;\r
28 import org.simantics.db.service.GraphChangeListenerSupport;\r
29 import org.simantics.ui.SimanticsUI;\r
30 \r
31 /**\r
32  * This class acts as a base class for ViewParts that to access the semantic\r
33  * graph from ProCore via {@link Session} and {@link Graph}.\r
34  * \r
35  * <p>\r
36  * This class contains the vitals for setting up a the editor for ProCore\r
37  * access. It also contains some support for dynamically allocating persistent\r
38  * (via the viewpart memento) ResourceInput instances for the viewpart's\r
39  * use, i.e. with OntologyExplorer controls.\r
40  * </p>\r
41  * \r
42  * <p>\r
43  * To use this class all you need to do is call super.createPartControl in your\r
44  * own createPartControl implementation. This will make sure a {@link Graph}\r
45  * will be available directly after that for initializing the UI and its\r
46  * contents.\r
47  * </p>\r
48  * \r
49  * <pre>\r
50  *       class MyViewPart extends GraphAccessViewPart\r
51  *           public void createPartControl(Composite parent) {\r
52  *               super.createPartControl(parent);\r
53  * \r
54  *               // Initialize UI controls.\r
55  *               // Initialize &quot;controllers&quot; based on the &quot;model&quot; (graph structure).\r
56  *               // Initialize &quot;view&quot; structures from the &quot;controllers&quot;\r
57  *               // Reflect &quot;model&quot; state into &quot;view&quot;\r
58  *               reload();\r
59  *           }\r
60  * \r
61  *           public void reload(Graph g) {\r
62  *               // Reflect the current graph model state in the UI...\r
63  *           }\r
64  *       }\r
65  * </pre>\r
66  * \r
67  * <p>\r
68  * To open a GraphAccessViewPart use\r
69  * <code>WorkbenchUtils.activateView(view id)</code>.\r
70  * </p>\r
71  * \r
72  * TODO: support changing active database session ?\r
73  * \r
74  * @author Tuukka Lehtonen\r
75  */\r
76 public abstract class GraphAccessViewPart extends ViewPart {\r
77 \r
78     private IMemento          memento;\r
79 \r
80     private ChangeListener    graphChangeListener;\r
81 \r
82     protected ISessionContext sessionContext;\r
83 \r
84     protected Session         session;\r
85 \r
86     @SuppressWarnings("unchecked")\r
87         @Override\r
88     public <A> A getAdapter(Class<A> adapter) {\r
89         // NOTE: the Session is instantiated at createPartControl time!\r
90         if (adapter == Session.class)\r
91             return (A) getSession();\r
92         return super.getAdapter(adapter);\r
93     }\r
94 \r
95     // ----------------------------------------------------------------------\r
96     // Getters\r
97 \r
98     public IStatusLineManager getStatusLineManager() {\r
99         IViewSite site = getViewSite();\r
100         IActionBars bars = site.getActionBars();\r
101         IStatusLineManager mgr = bars.getStatusLineManager();\r
102         // if (mgr instanceof SubStatusLineManager)\r
103         // ((SubStatusLineManager)mgr).setVisible(true);\r
104         return mgr;\r
105     }\r
106 \r
107     /**\r
108      * @param message <code>null</code> to remove message\r
109      */\r
110     public void setStatusMessage(String message) {\r
111         getStatusLineManager().setMessage(message);\r
112     }\r
113 \r
114     /**\r
115      * @param message <code>null</code> to remove message\r
116      */\r
117     public void setStatusErrorMessage(String message) {\r
118         getStatusLineManager().setErrorMessage(message);\r
119     }\r
120 \r
121     public IMemento getLastMemento() {\r
122         return memento;\r
123     }\r
124 \r
125     public IMemento consumeLastMemento() {\r
126         IMemento m = memento;\r
127         memento = null;\r
128         return m;\r
129     }\r
130 \r
131     // ----------------------------------------------------------------------\r
132     // Event handlers & initialisation\r
133 \r
134     /**\r
135      * Default implementation of createPartControl. Merely calls\r
136      * {@link #initialize()} to initialize the graph access. To make your\r
137      * ViewPart do anything meaningful, you must override this method. But\r
138      * remember to call super before trying to use the graph.\r
139      * \r
140      * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)\r
141      */\r
142     @Override\r
143     public void createPartControl(Composite parent) {\r
144         initialize();\r
145     }\r
146 \r
147     @Override\r
148     public void dispose() {\r
149         cleanup();\r
150         super.dispose();\r
151     }\r
152 \r
153     @Override\r
154     public void init(IViewSite site) throws PartInitException {\r
155         super.init(site);\r
156     }\r
157 \r
158     @Override\r
159     public void init(IViewSite site, IMemento memento) throws PartInitException {\r
160         super.init(site, memento);\r
161         this.memento = memento;\r
162     }\r
163 \r
164     protected ISessionContext getSessionContext() {\r
165         return sessionContext;\r
166     }\r
167 \r
168     protected Session getSession() {\r
169         return session;\r
170     }\r
171 \r
172     protected void initializeSession() {\r
173         sessionContext = SimanticsUI.getSessionContext();\r
174         if (sessionContext == null)\r
175             throw new IllegalStateException("no active session context");\r
176         session = sessionContext.getSession();\r
177     }\r
178 \r
179     /**\r
180      * Initializes graph data access and view resource ID input structures.\r
181      * \r
182      * <p>\r
183      * This method is automatically called by\r
184      * {@link #createPartControl(Composite)}. Override to perform own\r
185      * graph-related initializations but be absolutely sure to call super the\r
186      * first thing. Clients must not directly call this method.\r
187      * </p>\r
188      */\r
189     protected void initialize() {\r
190         initializeSession();\r
191 \r
192         graphChangeListener = getGraphChangeListener();\r
193         if (graphChangeListener != null) {\r
194             GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class);\r
195             support.addListener(graphChangeListener);\r
196         }\r
197     }\r
198 \r
199     /**\r
200      * Override this and return <code>null</code> to prevent a\r
201      * {@link GraphChangeListener} from being added automatically.\r
202      * \r
203      * @return\r
204      */\r
205     protected ChangeListener getGraphChangeListener() {\r
206         return new ChangeListenerImpl();\r
207     }\r
208 \r
209     /**\r
210      */\r
211     protected void cleanup() {\r
212         if (session != null) {\r
213             Session s = session;\r
214             session = null;\r
215 \r
216             if (graphChangeListener != null) {\r
217                 GraphChangeListenerSupport support = s.getService(GraphChangeListenerSupport.class);\r
218                 support.removeListener(graphChangeListener);\r
219                 graphChangeListener = null;\r
220             }\r
221         }\r
222     }\r
223 \r
224     /**\r
225      * The ProCore update notification listener for all GraphAccessViewPart\r
226      * instances. Calls\r
227      * {@link ResourceInputViewPart#update(GraphChangeEvent)} default\r
228      * implementation of which merely invokes\r
229      * {@link ResourceInputViewPart#reload()} for which overriding is\r
230      * allowed.\r
231      */\r
232     class ChangeListenerImpl implements ChangeListener {\r
233         public void graphChanged(ChangeEvent e) throws DatabaseException {\r
234             // System.out.println(GraphAccessViewPart.this.getClass().getName()\r
235             // + " receives update.");\r
236             update(e);\r
237         }\r
238     }\r
239 \r
240     /**\r
241      * This method is called when an update event is received from the Graph of\r
242      * this {@link ResourceInputViewPart}.\r
243      * \r
244      * This base implementation stupidly calls {@link #reload()} on every\r
245      * committed transaction or undo point change.\r
246      * \r
247      * @param event\r
248      *            the received change event\r
249      */\r
250     protected void update(ChangeEvent event) throws DatabaseException {\r
251         getSession().asyncRequest(new ReadRequest() {\r
252             @Override\r
253             public void run(ReadGraph g) {\r
254                 reload(g);\r
255             }\r
256         });\r
257     }\r
258 \r
259     // ----------------------------------------------------------------------\r
260     // Event utilities\r
261 \r
262     public void updateTitle() {\r
263         // setPartName must not be called with a null name!\r
264         String partName = getTitleText();\r
265         if (partName != null) {\r
266             setPartName(partName);\r
267         }\r
268         // Tooltip may be null, which clears the tooltip.\r
269         setTitleToolTip(getTitleTooltip());\r
270     }\r
271 \r
272     // ----------------------------------------------------------------------\r
273     // (Re-)Implement these if necessary:\r
274 \r
275     /**\r
276      * Returns null by default which makes {@link #updateTitle()} not set the\r
277      * part name programmatically, i.e. the plugin-defined view name will stay.\r
278      * \r
279      * @return\r
280      */\r
281     protected String getTitleText() {\r
282         return null;\r
283     }\r
284 \r
285     /**\r
286      * Return null by default which makes {@link #updateTitle()} clear the\r
287      * tooltip.\r
288      * \r
289      * @return\r
290      */\r
291     protected String getTitleTooltip() {\r
292         return null;\r
293     }\r
294 \r
295     /**\r
296      * Reload the UI because there are changes in the data model that have not\r
297      * been reflected to the UI.\r
298      */\r
299     public abstract void reload(ReadGraph g);\r
300 \r
301 }\r