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