Merge commit 'bd5bc6e45f700e755b61bd112631796631330ecb'
[simantics/platform.git] / bundles / org.simantics.event / src / org / simantics / event / view / handler / MenuActions.java
1 package org.simantics.event.view.handler;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Arrays;\r
5 import java.util.Collections;\r
6 import java.util.List;\r
7 \r
8 import org.eclipse.jface.action.Action;\r
9 import org.eclipse.jface.action.IAction;\r
10 import org.eclipse.jface.action.IStatusLineManager;\r
11 import org.eclipse.jface.resource.ImageDescriptor;\r
12 import org.eclipse.jface.viewers.ISelection;\r
13 import org.eclipse.swt.dnd.Clipboard;\r
14 import org.eclipse.swt.dnd.TextTransfer;\r
15 import org.eclipse.swt.dnd.Transfer;\r
16 import org.eclipse.ui.IWorkbenchPart;\r
17 import org.eclipse.ui.PlatformUI;\r
18 import org.simantics.databoard.Bindings;\r
19 import org.simantics.db.ReadGraph;\r
20 import org.simantics.db.Resource;\r
21 import org.simantics.db.WriteGraph;\r
22 import org.simantics.db.common.request.PossibleTypedParent;\r
23 import org.simantics.db.exception.DatabaseException;\r
24 import org.simantics.db.layer0.SelectionHints;\r
25 import org.simantics.event.Activator;\r
26 import org.simantics.event.ontology.EventResource;\r
27 import org.simantics.event.util.EventUtils;\r
28 import org.simantics.ui.contribution.DynamicMenuContribution;\r
29 import org.simantics.ui.workbench.action.PerformDefaultAction;\r
30 import org.simantics.utils.ui.ISelectionUtils;\r
31 import org.simantics.utils.ui.workbench.WorkbenchUtils;\r
32 \r
33 /**\r
34  * @author Tuukka Lehtonen\r
35  */\r
36 public class MenuActions extends DynamicMenuContribution {\r
37 \r
38     /**\r
39      * The name of the virtual graph the menu actions perform their changes into.\r
40      */\r
41     private static final String VG_EXPERIMENTS = "experiments";\r
42 \r
43     @Override\r
44     protected Object[] getSelectedObjects() {\r
45         ISelection sel = getSelection();\r
46         List<Resource> resources = ISelectionUtils.getPossibleKeys(sel, SelectionHints.KEY_MAIN, Resource.class);\r
47         return resources.toArray();\r
48     }\r
49 \r
50     List<Resource> toResources(Object[] array) {\r
51         Resource[] a = new Resource[array.length];\r
52         for (int i = 0; i < array.length; ++i)\r
53             a[i] = (Resource) array[i];\r
54         return Arrays.asList(a);\r
55     }\r
56 \r
57     @Override\r
58     protected IAction[] getActions(ReadGraph graph, Object[] selection) throws DatabaseException {\r
59         if (selection.length == 0)\r
60             return new IAction[0];\r
61 \r
62         List<Resource> input = toResources(selection);\r
63         if (input.isEmpty())\r
64             return new IAction[0];\r
65 \r
66         boolean logs = false;\r
67         boolean events = false;\r
68 \r
69         EventResource EVENT = EventResource.getInstance(graph);\r
70         int hiddenCount = 0; \r
71         int milestoneCount = 0; \r
72         int hasSourceCount = 0;\r
73         for (Resource r : input) {\r
74             logs |= graph.isInstanceOf(r, EVENT.EventLog);\r
75             events |= graph.isInstanceOf(r, EVENT.Event);\r
76             if (graph.hasStatement(r, EVENT.Hidden))\r
77                 ++hiddenCount;\r
78             if (graph.hasStatement(r, EVENT.Milestone))\r
79                 ++milestoneCount;\r
80             if (graph.hasStatement(r, EVENT.Event_source))\r
81                 ++hasSourceCount;\r
82         }\r
83         boolean allHidden = hiddenCount == selection.length;\r
84         boolean allMilestones= milestoneCount == selection.length;\r
85 \r
86         Resource event = null;\r
87         String eventSourceName = null;\r
88         if (input.size() == 1) {\r
89             event = input.get(0);\r
90             if (hasSourceCount == 1) {\r
91                 eventSourceName = graph.getPossibleRelatedValue(event, EVENT.Event_sourceName, Bindings.STRING);\r
92             }\r
93         }\r
94 \r
95         List<IAction> actions = new ArrayList<IAction>();\r
96 \r
97         if (eventSourceName != null && !eventSourceName.isEmpty())\r
98             actions.add(toClipboardAction(eventSourceName, eventSourceName));\r
99         if (!allHidden)\r
100             actions.add(hideAction(input));\r
101         if (hiddenCount > 0 || allHidden)\r
102             actions.add(unhideAction(input));\r
103 \r
104         if (!logs && !allMilestones)\r
105             actions.add(markMilestoneAction(input));\r
106         if (!logs && (milestoneCount > 0 || allMilestones)) {\r
107             Resource eventLog = graph.syncRequest(new PossibleTypedParent(input.get(0), EVENT.EventLog));\r
108             actions.add(unmarkMilestoneAction(eventLog, input));\r
109         }\r
110 \r
111         if (!logs && events && event != null) {\r
112             Resource eventLog = graph.syncRequest(new PossibleTypedParent(event, EVENT.EventLog));\r
113             if (eventLog != null) {\r
114                 boolean isBaseline = graph.hasStatement(eventLog, EVENT.EventLog_HasBaselineEvent, event);\r
115                 if (isBaseline && allMilestones)\r
116                     actions.add(removeBaseline(Collections.singletonList(eventLog)));\r
117                 else\r
118                     actions.add(setBaseline(eventLog, event));\r
119             }\r
120         }\r
121         if (logs && !events) {\r
122             actions.add(removeBaseline(input));\r
123         }\r
124 \r
125         if (event != null && hasSourceCount == 1) {\r
126             Resource eventSource = graph.getPossibleObject(event, EVENT.Event_source);\r
127             if (eventSource != null)\r
128                 actions.add(performDefaultAction(eventSource, null));\r
129         }\r
130 \r
131         return actions.toArray(new IAction[actions.size()]);\r
132     }\r
133 \r
134     private IAction toClipboardAction(String label, String text) {\r
135         return new ToClipboardAction(label, text);\r
136     }\r
137 \r
138     private IAction markMilestoneAction(List<Resource> input) {\r
139         return tagAction("Mark as Milestone", Activator.MARK_MILESTONE_ICON, EventResource.URIs.Milestone, true, input);\r
140     }\r
141 \r
142     private IAction unmarkMilestoneAction(Resource eventLog, List<Resource> input) {\r
143         return new UnmarkMilestone(VG_EXPERIMENTS, eventLog, input);\r
144     }\r
145 \r
146     private IAction unhideAction(List<Resource> input) {\r
147         return tagAction("Unhide", Activator.UNHIDE_ICON, EventResource.URIs.Hidden, false, input);\r
148     }\r
149 \r
150     private IAction hideAction(List<Resource> input) {\r
151         return contentChangingTagAction("Hide", Activator.HIDE_ICON, EventResource.URIs.Hidden, true, input);\r
152     }\r
153 \r
154     private IAction tagAction(String label, ImageDescriptor image, String tagURI, boolean tag, List<Resource> input) {\r
155         return new TagAction(label, image, VG_EXPERIMENTS, tagURI, tag, input);\r
156     }\r
157 \r
158     private IAction contentChangingTagAction(String label, ImageDescriptor image, String tagURI, boolean tag, List<Resource> input) {\r
159         return new ContentChangingTagAction(label, image, VG_EXPERIMENTS, tagURI, tag, input);\r
160     }\r
161 \r
162     private IAction setBaseline(Resource eventLog, Resource event) {\r
163         return new SetBaseline(VG_EXPERIMENTS, eventLog, event);\r
164     }\r
165 \r
166     private IAction removeBaseline(List<Resource> logs) {\r
167         return new DenyAction("Remove Baseline", Activator.REMOVE_BASELINE_ICON, VG_EXPERIMENTS, EventResource.URIs.EventLog_HasBaselineEvent, logs);\r
168     }\r
169 \r
170     private IAction performDefaultAction(Resource input, String sourceName) {\r
171         String title = "Show Event Source";\r
172         if (sourceName != null)\r
173             title += " (" + sourceName + ")";\r
174         return new PerformDefaultAction(title, null, input);\r
175     }\r
176 \r
177     private static class ContentChangingTagAction extends TagAction {\r
178         public ContentChangingTagAction(String label, ImageDescriptor image, String virtualGraphId, String tagURI, boolean tag, List<Resource> input) {\r
179             super(label, image, virtualGraphId, tagURI, tag, input);\r
180         }\r
181 \r
182         @Override\r
183         public void postTagWrite(WriteGraph graph) throws DatabaseException {\r
184             EventUtils.bumpModificationCounter(graph, resources);\r
185         }\r
186     }\r
187 \r
188     private static class ToClipboardAction extends Action {\r
189         private String text;\r
190 \r
191         public ToClipboardAction(String label, String text) {\r
192             super(label, Activator.CLIPBOARD_ICON);\r
193             this.text = text;\r
194         }\r
195 \r
196         @Override\r
197         public void run() {\r
198             Clipboard clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay());\r
199             clipboard.setContents(\r
200                     new Object[] { text },\r
201                     new Transfer[] { TextTransfer.getInstance() }\r
202                     );\r
203             clipboard.dispose();\r
204 \r
205             // Show a message in the status line if possible\r
206             IWorkbenchPart part = WorkbenchUtils.getActiveWorkbenchPart();\r
207             if (part != null) {\r
208                 IStatusLineManager status = WorkbenchUtils.getStatusLine(part);\r
209                 if (status != null) {\r
210                     status.setErrorMessage(null);\r
211                     status.setMessage("Copied '" + text + "' to clipboard");\r
212                 }\r
213             }\r
214         }\r
215     }\r
216 \r
217     private static class UnmarkMilestone extends TagAction {\r
218         private final Resource eventLog;\r
219         private final List<Resource> events;\r
220         public UnmarkMilestone(String virtualGraphId, Resource eventLog, List<Resource> events) {\r
221             super("Unmark Milestone", Activator.UNMARK_MILESTONE_ICON, virtualGraphId, EventResource.URIs.Milestone, false, events);\r
222             this.eventLog = eventLog;\r
223             this.events = events;\r
224         }\r
225         @Override\r
226         public void postTagWrite(WriteGraph graph) throws DatabaseException {\r
227             EventResource EVENT = EventResource.getInstance(graph);\r
228             Resource baselineEvent = graph.getPossibleObject(eventLog, EVENT.EventLog_HasBaselineEvent);\r
229             if (baselineEvent != null) {\r
230                 if (events.contains(baselineEvent)) {\r
231                     graph.deny(eventLog, EVENT.EventLog_HasBaselineEvent);\r
232                 }\r
233             }\r
234         }\r
235     }\r
236 \r
237     private static class SetBaseline extends ClaimAction {\r
238         public SetBaseline(String virtualGraphId, Resource subject, Resource object) {\r
239             super("Set Baseline", Activator.SET_BASELINE_ICON, virtualGraphId, subject, EventResource.URIs.EventLog_HasBaselineEvent, object);\r
240         }\r
241         @Override\r
242         public void claim(WriteGraph graph) throws DatabaseException {\r
243             super.claim(graph);\r
244             EventResource EVENT = EventResource.getInstance(graph);\r
245             if (!graph.hasStatement(object, EVENT.Milestone)) {\r
246                 graph.claim(object, EVENT.Milestone, object);\r
247                 CorrectMilestoneLabelsAction.correctMilestoneLabels(graph, graph.getProvider(), Collections.singleton(object));\r
248             }\r
249         }\r
250     }\r
251 }