]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.team.ui/src/org/simantics/team/ui/UndoView.java
0e87bf612ff1dd62abd2e6e7d792e9cb7c74e6ab
[simantics/platform.git] / bundles / org.simantics.team.ui / src / org / simantics / team / ui / UndoView.java
1 package org.simantics.team.ui;\r
2 \r
3 import java.lang.ref.WeakReference;\r
4 import java.nio.ByteBuffer;\r
5 import java.nio.CharBuffer;\r
6 import java.nio.charset.CharacterCodingException;\r
7 import java.nio.charset.Charset;\r
8 import java.nio.charset.CharsetDecoder;\r
9 import java.nio.charset.CodingErrorAction;\r
10 import java.util.Collection;\r
11 import java.util.Iterator;\r
12 import java.util.Vector;\r
13 \r
14 import org.eclipse.jface.action.Action;\r
15 import org.eclipse.jface.layout.TreeColumnLayout;\r
16 import org.eclipse.jface.resource.JFaceResources;\r
17 import org.eclipse.jface.resource.LocalResourceManager;\r
18 import org.eclipse.jface.viewers.ColumnWeightData;\r
19 import org.eclipse.jface.viewers.TreeViewer;\r
20 import org.eclipse.jface.viewers.TreeViewerColumn;\r
21 import org.eclipse.swt.SWT;\r
22 import org.eclipse.swt.graphics.Image;\r
23 import org.eclipse.swt.widgets.Composite;\r
24 import org.simantics.db.Operation;\r
25 import org.simantics.db.Session;\r
26 import org.simantics.db.UndoContext;\r
27 import org.simantics.db.common.utils.Logger;\r
28 import org.simantics.db.exception.DatabaseException;\r
29 import org.simantics.db.service.UndoRedoSupport;\r
30 import org.simantics.db.service.UndoRedoSupport.ChangeListener;\r
31 import org.simantics.team.Activator;\r
32 import org.simantics.team.internal.Images;\r
33 import org.simantics.ui.SimanticsUI;\r
34 import org.simantics.utils.ui.dialogs.ShowError;\r
35 \r
36 /**\r
37  * @author Kalle Kondelin\r
38  */\r
39 public class UndoView extends TreeView {\r
40     @Override\r
41     public void createPartControl(Composite parent) {\r
42         this.parent = parent;\r
43         this.treeViewer = new TreeViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION);\r
44         this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), treeViewer.getTree());\r
45         Images.getInstance(JFaceResources.getResources());\r
46         TreeColumnLayout ad = new TreeColumnLayout();\r
47         parent.setLayout(ad);\r
48         treeViewer.getTree().setHeaderVisible(true);\r
49         //treeViewer.getTree().setLinesVisible(true);\r
50         //treeViewer.setUseHashlookup(true);\r
51         //treeViewer.setAutoExpandLevel(3);\r
52 \r
53         TreeViewerColumn idColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);\r
54         TreeViewerColumn dateColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);\r
55         TreeViewerColumn commentColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);\r
56 \r
57         idColumn.setLabelProvider(new IdColumnLabelProvider());\r
58         dateColumn.setLabelProvider(new DateColumnLabelProvider());\r
59         commentColumn.setLabelProvider(new CommentColumnLabelProvider());\r
60 \r
61         idColumn.getColumn().setText("Id");\r
62         idColumn.getColumn().setWidth(20);\r
63         ad.setColumnData(idColumn.getColumn(), new ColumnWeightData(50, 20));\r
64         dateColumn.getColumn().setText("Date");\r
65         dateColumn.getColumn().setWidth(20);\r
66         ad.setColumnData(dateColumn.getColumn(), new ColumnWeightData(50, 40));\r
67         commentColumn.getColumn().setText("Comment");\r
68         commentColumn.getColumn().setWidth(20);\r
69         ad.setColumnData(commentColumn.getColumn(), new ColumnWeightData(50, 50));\r
70 \r
71         final UndoContentProvider contentProvider = new UndoContentProvider(SimanticsUI.getSession());\r
72           treeViewer.setContentProvider(contentProvider);\r
73           treeViewer.setInput(this);\r
74           getViewSite().getActionBars().getToolBarManager().add(new Action("Remove All", Activator.REMOVE_ALL_ICON) {\r
75               @Override\r
76               public void run() {\r
77                   contentProvider.removeAll();\r
78               }\r
79           });\r
80           getViewSite().getActionBars().getToolBarManager().add(new Action("Get Undo History", Activator.REFRESH_ICON) {\r
81               @Override\r
82               public void run() {\r
83                   treeViewer.setContentProvider(contentProvider);\r
84               }\r
85           });\r
86           new ItemDetailToolTip(treeViewer, treeViewer.getTree(), null);\r
87     }\r
88 }\r
89 \r
90 abstract class UndoViewElement extends TreeElement {\r
91     protected Session session;\r
92     UndoViewElement(Session session) {\r
93         this.session = session;\r
94     }\r
95     protected static final Charset UTF8 = Charset.forName("UTF-8");\r
96     protected String toString(byte[] data) {\r
97         if (data == null)\r
98             return "null";\r
99         CharsetDecoder decoder = UTF8.newDecoder();\r
100         ByteBuffer bbuf = ByteBuffer.wrap(data);\r
101         CharBuffer cbuf;\r
102         String s = null;\r
103         try {\r
104             cbuf = decoder.decode(bbuf);\r
105             s = cbuf.toString();\r
106         } catch (CharacterCodingException e) {\r
107             bbuf.rewind();\r
108             try {\r
109                 cbuf = UTF8\r
110                 .newDecoder()\r
111                 .onMalformedInput(CodingErrorAction.REPLACE)\r
112                 .onUnmappableCharacter(CodingErrorAction.REPLACE)\r
113                 .decode(bbuf);\r
114                 s = cbuf.toString();\r
115             } catch (CharacterCodingException e1) {\r
116                 return "String conversion error.";\r
117             }\r
118         }\r
119         return s;\r
120     }\r
121     @Override\r
122     boolean hasChildren() {\r
123             return false;\r
124     }\r
125     @Override\r
126     Object[] getChildren() {\r
127         return new Object[0];\r
128     }\r
129 }\r
130 \r
131 class UndoContextElement extends UndoViewElement {\r
132     protected String name = "Undo";\r
133     protected WeakReference<UndoContext> contextRef;\r
134     UndoContextElement(Session session, UndoContext context) {\r
135         super(session);\r
136         this.contextRef = new WeakReference<UndoContext>(context);\r
137     }\r
138     @Override\r
139     protected Image getIdImage() {\r
140         return Images.getInstance().OTHER_IMAGE;\r
141     }\r
142     @Override\r
143     protected String getIdText() {\r
144         String s = toString();\r
145         return s.substring(0, Math.min(10, s.length()));\r
146     }\r
147     @Override\r
148     boolean hasChildren() {\r
149         UndoContext c = contextRef.get();\r
150         if (null == c)\r
151             return false;\r
152         try {\r
153             return c.getAll().size() > 0;\r
154         } catch (DatabaseException e) {\r
155             Logger.defaultLogError(e);\r
156             return false;\r
157         }\r
158     }\r
159     @Override\r
160     public String toString() {\r
161         UndoContext c = contextRef.get();\r
162         if (null == c)\r
163             return name + "@no context";\r
164         return name + "@" + c;\r
165     }\r
166     @Override\r
167     Object[] getChildren() {\r
168         UndoContext c = contextRef.get();\r
169         if (null == c)\r
170             return new Object[0];\r
171         Collection<Operation> operations;\r
172         try {\r
173             operations = c.getAll();\r
174         } catch (DatabaseException e) {\r
175             Logger.defaultLogError(e);\r
176             return new Object[0];\r
177         }\r
178         if (operations.size() < 1)\r
179             return new Object[0];\r
180         Object[] objects = new Object[operations.size()];\r
181         Iterator<Operation> it = operations.iterator();\r
182         int i = operations.size();\r
183         while (it.hasNext()) {\r
184             Operation op = it.next();\r
185             objects[--i] = new UndoCombinedElement(session, op);\r
186         }\r
187         assert(0==i);\r
188         return objects;\r
189     }\r
190 }\r
191 \r
192 class RedoContextElement extends UndoContextElement {\r
193     RedoContextElement(Session session, UndoContext context) {\r
194         super(session, context);\r
195         this.name = "Redo";\r
196     }\r
197     @Override\r
198     boolean hasChildren() {\r
199         UndoContext c = contextRef.get();\r
200         if (null == c)\r
201             return false;\r
202         try {\r
203             return c.getRedoList().size() > 0;\r
204         } catch (DatabaseException e) {\r
205             Logger.defaultLogError(e);\r
206             return false;\r
207         }\r
208     }\r
209     @Override\r
210     Object[] getChildren() {\r
211         UndoContext c = contextRef.get();\r
212         if (null == c)\r
213             return new Object[0];\r
214         Collection<Operation> operations;\r
215         try {\r
216             operations = c.getRedoList();\r
217         } catch (DatabaseException e) {\r
218             Logger.defaultLogError(e);\r
219             operations = null;\r
220         }\r
221         if (operations.size() < 1)\r
222             return new Object[0];\r
223         Object[] objects = new Object[operations.size()];\r
224         Iterator<Operation> it = operations.iterator();\r
225         int i = operations.size();\r
226         while (it.hasNext()) {\r
227             Operation op = it.next();\r
228             objects[--i] = new UndoCombinedElement(session, op); \r
229         }\r
230         assert(0 == i);\r
231         return objects;\r
232     }\r
233 }\r
234 \r
235 class UndoCombinedElement extends UndoViewElement {\r
236     private final Operation operation;\r
237     private final Vector<ChangeSetElement> elements = new Vector<ChangeSetElement>();\r
238     private String comment = null;\r
239     UndoCombinedElement(Session session, Operation op) {\r
240         super(session);\r
241         operation = op;\r
242     }\r
243     @Override\r
244     protected Image getIdImage() {\r
245         return Images.getInstance().UNDO_IMAGE;\r
246     }\r
247     @Override\r
248     protected String getIdText() {\r
249         return "" + operation.getId();\r
250     }\r
251     @Override\r
252     protected String getDateText() {\r
253         if (elements.size() == 0)\r
254             getChildren();\r
255         if (elements.size() > 0)\r
256             return elements.firstElement().getDateText();\r
257         else\r
258             return null; \r
259     }\r
260     @Override\r
261     protected String getCommentText() {\r
262         if (elements.size() == 0)\r
263             getChildren();\r
264         if (elements.size() > 0)\r
265             return elements.firstElement().getCommentText();\r
266         else\r
267             return null; \r
268     }\r
269     @Override\r
270     boolean hasChildren() {\r
271         return operation.getOperations().size() > 0;\r
272     }\r
273     @Override\r
274     Object[] getChildren() {\r
275         Collection<Operation> ops = operation.getOperations();\r
276         final int SIZE = ops.size(); \r
277         if (SIZE < 1)\r
278             return new Object[0];\r
279         elements.clear();\r
280         Iterator<Operation> it = ops.iterator();\r
281         for (int i=0; i<SIZE; ++i) {\r
282             Operation op = it.next();\r
283             ChangeSetElement e = new ChangeSetElement(session, op.getCSId());\r
284             elements.add(e);\r
285         }\r
286         if (elements.size() == 1)\r
287             return elements.firstElement().getChildren();\r
288         return elements.toArray();\r
289     }\r
290     @Override\r
291     public String toString() {\r
292         getChildren(); // This initializes elements vector.\r
293         for (ChangeSetElement e : elements) {\r
294             comment = e.toString();\r
295             if (null != comment)\r
296                 return comment;\r
297         }\r
298         return "no name";\r
299     }\r
300 }\r
301 \r
302 class UndoContentProvider extends ChangeSetProvider implements ChangeListener {\r
303     private UndoContextElement uce;\r
304     protected UndoRedoSupport undoRedoSupport;\r
305     private boolean subscribed = false;\r
306     UndoContentProvider(Session session) {\r
307         super(session);\r
308         undoRedoSupport = session.getService(UndoRedoSupport.class);\r
309         subscribe();\r
310     }\r
311     @Override\r
312     public Object[] getElements(Object inputElement) {\r
313         return getElements(session);\r
314     }\r
315     @Override\r
316     public void dispose() {\r
317         managementSupport.cancel(this);\r
318         this.subscribed = false;\r
319         super.dispose();\r
320     }\r
321     @Override\r
322     public void onChanged() {\r
323         if (null != viewer)\r
324             refresh();\r
325     }\r
326     protected Object[] getElements(Session session) {\r
327         try {\r
328             UndoRedoSupport undoSupport = session.getService(UndoRedoSupport.class);\r
329             UndoContext undoContext = undoSupport.getUndoContext(session);\r
330             if (null != undoContext) {\r
331                 uce = new UndoContextElement(session, undoContext);\r
332                 return uce.getChildren();\r
333             }\r
334         } catch (Exception e) {\r
335             Logger.defaultLogError(e);\r
336             if (DEBUG)\r
337                 ShowError.showError("Error", e.getMessage(), e);\r
338         }\r
339         return new Object[0];\r
340     }\r
341     protected void subscribe() {\r
342         super.subscribe();\r
343         if (this.subscribed)\r
344             return;\r
345         if (null == undoRedoSupport)\r
346             undoRedoSupport = session.getService(UndoRedoSupport.class);\r
347         undoRedoSupport.subscribe(this);\r
348         this.subscribed = true;\r
349     }\r
350     void removeAll() {\r
351         UndoRedoSupport us = session.getService(UndoRedoSupport.class);\r
352         UndoContext uc = us.getUndoContext(session);\r
353         if (uc != null) {\r
354             uc.clear();\r
355             refresh();\r
356         }\r
357     }\r
358 }\r
359 \r
360 class RedoContentProvider extends UndoContentProvider {\r
361     private RedoContextElement rce;\r
362     RedoContentProvider(Session session) {\r
363         super(session);\r
364     }\r
365     @Override\r
366     protected Object[] getElements(Session session) {\r
367         try {\r
368             UndoRedoSupport undoSupport = session.getService(UndoRedoSupport.class);\r
369             UndoContext undoContext = undoSupport.getUndoContext(session);\r
370             if (null != undoContext) {\r
371                 rce = new RedoContextElement(session, undoContext);\r
372                 return rce.getChildren();\r
373             }\r
374         } catch (Exception e) {\r
375             Logger.defaultLogError(e);\r
376             if (DEBUG)\r
377                 ShowError.showError("Error", e.getMessage(), e);\r
378         }\r
379         return new Object[0];\r
380     }\r
381 }\r