]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.ui/src/org/simantics/ui/tester/UndoPropertyTester.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / tester / UndoPropertyTester.java
1 /*******************************************************************************\r
2  * Copyright (c) 2011 Association for Decentralized Information Management in\r
3  * 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.tester;\r
13 \r
14 import org.eclipse.core.expressions.PropertyTester;\r
15 import org.eclipse.swt.widgets.Display;\r
16 import org.eclipse.ui.PlatformUI;\r
17 import org.eclipse.ui.contexts.IContextActivation;\r
18 import org.eclipse.ui.contexts.IContextService;\r
19 import org.simantics.DatabaseJob;\r
20 import org.simantics.Simantics;\r
21 import org.simantics.db.Session;\r
22 import org.simantics.db.UndoContext;\r
23 import org.simantics.db.exception.DatabaseException;\r
24 import org.simantics.db.management.ISessionContext;\r
25 import org.simantics.db.service.UndoRedoSupport;\r
26 import org.simantics.ui.SimanticsUI;\r
27 import org.simantics.utils.ui.ErrorLogger;\r
28 import org.simantics.utils.ui.SWTUtils;\r
29 \r
30 /**\r
31  * An eclipse property tester for org.simantics.db database undo/redoability.\r
32  * \r
33  * @author Kalle Kondelin\r
34  */\r
35 public class UndoPropertyTester extends PropertyTester implements UndoRedoSupport.ChangeListener {\r
36 \r
37     private static final String PROP_CAN_REDO = "canRedo";\r
38 \r
39     private static final String PROP_CAN_UNDO = "canUndo";\r
40 \r
41     private static final String SIMANTICS_UNDO_CONTEXT = "org.simantics.ui.undoContext";\r
42 \r
43     public static final boolean DEBUG = false;\r
44 \r
45     public static final String UNDO_ENABLED = "org.simantics.undo.enabled";\r
46     \r
47     UndoRedoSupport undoSupport = null;\r
48     IContextActivation activation = null;\r
49     public UndoPropertyTester() {\r
50         if (DEBUG)\r
51             System.out.println("UndoPropertyTester: " + this);\r
52     }\r
53     @Override\r
54     public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {\r
55         if (DEBUG)\r
56             System.out.println("UndoPropertyTester: receiver=" + receiver);\r
57         \r
58         String undoEnabled = System.getProperty(UNDO_ENABLED);\r
59         if(undoEnabled != null && "false".equals(undoEnabled))\r
60             return false;\r
61         \r
62         if (property.matches(PROP_CAN_UNDO))\r
63             return canUndo();\r
64         else if (property.matches(PROP_CAN_REDO))\r
65             return canRedo();\r
66         else\r
67             return false;\r
68     }\r
69     private boolean canUndo() {\r
70         ISessionContext ctx = Simantics.getSessionContext();\r
71         if (ctx == null) {\r
72             if (DEBUG)\r
73                 System.out.println("UndoPropertyTester: no can do undo.");\r
74             return false;\r
75         }\r
76         try {\r
77             Session s = ctx.peekSession();\r
78             if (null == s) {\r
79                 if (DEBUG)\r
80                     System.out.println("UndoPropertyTester: session is null, no can do undo.");\r
81                 return false;\r
82             }\r
83             if (DatabaseJob.inProgress())\r
84                 return true;\r
85             if (null == undoSupport) {\r
86                 undoSupport = s.getService(UndoRedoSupport.class);\r
87                 undoSupport.subscribe(this);\r
88             }\r
89             UndoContext uc = undoSupport.getUndoContext(s);\r
90             if (uc == null)\r
91                 return false;\r
92             boolean ret = !uc.getAll().isEmpty();\r
93             if (DEBUG)\r
94                 System.out.println("UndoPropertyTester: " + (ret ? "" : "no ")+ "can do undo.");\r
95             return ret;\r
96         } catch (Exception e) {\r
97             ErrorLogger.getDefault().logError("Undo/Redo support failed.", e);\r
98             if (DEBUG)\r
99                 System.out.println("UndoPropertyTester: no can do undo");\r
100             return false;\r
101         }\r
102     }\r
103     private boolean canRedo() {\r
104         ISessionContext ctx = Simantics.getSessionContext();\r
105         if (ctx == null) {\r
106             if (DEBUG)\r
107                 System.out.println("UndoPropertyTester: no can do redo.");\r
108             return false;\r
109         }\r
110         try {\r
111             Session s = ctx.peekSession();\r
112             if (null == s) {\r
113                 if (DEBUG)\r
114                     System.out.println("UndoPropertyTester: session is null, no can do redo.");\r
115                 return false;\r
116             }\r
117             if (DatabaseJob.inProgress())\r
118                 return true;\r
119             if (null == undoSupport) {\r
120                 undoSupport = s.getService(UndoRedoSupport.class);\r
121                 undoSupport.subscribe(this);\r
122             }\r
123             UndoContext uc = undoSupport.getUndoContext(s);\r
124             if (uc == null)\r
125                 return false;\r
126             boolean ret = !uc.getRedoList().isEmpty();\r
127             if (DEBUG)\r
128                 System.out.println("UndoPropertyTester: " + (ret ? "" : "no ")+ "can do redo.");\r
129             return ret;\r
130         } catch (Exception e) {\r
131             ErrorLogger.getDefault().logError("Undo/Redo support failed.", e);\r
132             if (DEBUG)\r
133                 System.out.println("UndoPropertyTester: no can do redo.");\r
134             return false;\r
135         }\r
136     }\r
137     @Override\r
138     public void onChanged() {\r
139         if (DEBUG)\r
140             System.out.println("UndoPropertyTester: on change.");\r
141         Display display = PlatformUI.getWorkbench().getDisplay();\r
142         SWTUtils.asyncExec(display, new Runnable() {\r
143             @Override\r
144             public void run() {\r
145                 handleChange();\r
146             }\r
147         });\r
148     }\r
149     private int oldUndo = 0;\r
150     private int oldRedo = 0;\r
151     private void handleChange() {\r
152         int newUndo = oldUndo;\r
153         int newRedo = oldRedo;\r
154         try {\r
155             ISessionContext ctx = SimanticsUI.getSessionContext();\r
156             if (DEBUG)\r
157                 System.out.println("UndoPropertyTester: handle change, ctx=" + ctx);\r
158             if (ctx == null)\r
159                 return;\r
160             Session session = ctx.peekSession();\r
161             if (DEBUG)\r
162                 System.out.println("UndoPropertyTester: handle change, session=" + session);\r
163             if (session == null)\r
164                 return;\r
165             UndoContext uc = undoSupport.getUndoContext(session);\r
166             if (uc == null)\r
167                 return;\r
168             newUndo = uc.getAll().size();\r
169             newRedo = uc.getRedoList().size();\r
170             if (DEBUG) {\r
171                 System.out.println("on undo change: " + oldUndo + "->" + newUndo);\r
172                 System.out.println("on redo change: " + oldRedo + "->" + newRedo);\r
173             }\r
174             boolean undoOn = oldUndo == 0 && newUndo == 1;\r
175             boolean undoOff = oldUndo > 0 && newUndo == 0;\r
176             boolean redoOn = oldRedo == 0 && newRedo == 1;\r
177             boolean redoOff = oldRedo > 0 && newRedo == 0;\r
178             if (undoOn || undoOff || redoOn || redoOff)\r
179                 toggleContext();\r
180         } catch (DatabaseException e) {\r
181             ErrorLogger.getDefault().logError("Undo/Redo support failed.", e);\r
182         }\r
183         oldUndo = newUndo;\r
184         oldRedo = newRedo;\r
185     }\r
186     private void toggleContext() {\r
187         IContextService contextService = (IContextService)PlatformUI.getWorkbench().getService(IContextService.class);\r
188         if (null != activation) {\r
189             if (DEBUG)\r
190                 System.out.println("UndoPropertyTester: deactivate.");\r
191             try {\r
192                 contextService.deactivateContext(activation);\r
193             } catch (Throwable t) {\r
194                 ErrorLogger.getDefault().logError("Undo/Redo support failed.", t);\r
195             }\r
196             activation = null;\r
197             if (DEBUG)\r
198                 System.out.println("UndoPropertyTester: deactivated.");\r
199         } else {\r
200             if (DEBUG)\r
201                 System.out.println("UndoPropertyTester: activate.");\r
202             try {\r
203                 activation = contextService.activateContext(SIMANTICS_UNDO_CONTEXT);\r
204             } catch (Throwable t) {\r
205                 ErrorLogger.getDefault().logError("Undo/Redo support failed.", t);\r
206                 activation = null;\r
207             }\r
208             if (DEBUG)\r
209                 System.out.println("UndoPropertyTester: activated=" + activation);\r
210         }\r
211     }\r
212 }\r