package org.simantics.event.view.handler; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.PossibleTypedParent; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.SelectionHints; import org.simantics.event.Activator; import org.simantics.event.ontology.EventResource; import org.simantics.ui.contribution.DynamicMenuContribution; import org.simantics.ui.workbench.action.PerformDefaultAction; import org.simantics.utils.ui.ISelectionUtils; import org.simantics.utils.ui.workbench.WorkbenchUtils; /** * @author Tuukka Lehtonen */ public class MenuActions extends DynamicMenuContribution { /** * The name of the virtual graph the menu actions perform their changes into. */ private static final String VG_EXPERIMENTS = "experiments"; @Override protected Object[] getSelectedObjects() { ISelection sel = getSelection(); List resources = ISelectionUtils.getPossibleKeys(sel, SelectionHints.KEY_MAIN, Resource.class); return resources.toArray(); } List toResources(Object[] array) { Resource[] a = new Resource[array.length]; for (int i = 0; i < array.length; ++i) a[i] = (Resource) array[i]; return Arrays.asList(a); } @Override protected IAction[] getActions(ReadGraph graph, Object[] selection) throws DatabaseException { if (selection.length == 0) return new IAction[0]; List input = toResources(selection); if (input.isEmpty()) return new IAction[0]; boolean logs = false; boolean events = false; EventResource EVENT = EventResource.getInstance(graph); int hiddenCount = 0; int milestoneCount = 0; int hasSourceCount = 0; for (Resource r : input) { logs |= graph.isInstanceOf(r, EVENT.EventLog); events |= graph.isInstanceOf(r, EVENT.Event); if (graph.hasStatement(r, EVENT.Hidden)) ++hiddenCount; if (graph.hasStatement(r, EVENT.Milestone)) ++milestoneCount; if (graph.hasStatement(r, EVENT.Event_source)) ++hasSourceCount; } boolean allHidden = hiddenCount == selection.length; boolean allMilestones= milestoneCount == selection.length; Resource event = null; String eventSourceName = null; if (input.size() == 1) { event = input.get(0); if (hasSourceCount == 1) { eventSourceName = graph.getPossibleRelatedValue(event, EVENT.Event_sourceName, Bindings.STRING); } } List actions = new ArrayList(); if (eventSourceName != null && !eventSourceName.isEmpty()) actions.add(toClipboardAction(eventSourceName, eventSourceName)); if (!allHidden) actions.add(hideAction(input)); if (hiddenCount > 0 || allHidden) actions.add(unhideAction(input)); if (!logs && !allMilestones) actions.add(markMilestoneAction(input)); if (!logs && (milestoneCount > 0 || allMilestones)) { Resource eventLog = graph.syncRequest(new PossibleTypedParent(input.get(0), EVENT.EventLog)); actions.add(unmarkMilestoneAction(eventLog, input)); } if (!logs && events && event != null) { Resource eventLog = graph.syncRequest(new PossibleTypedParent(event, EVENT.EventLog)); if (eventLog != null) { boolean isBaseline = graph.hasStatement(eventLog, EVENT.EventLog_HasBaselineEvent, event); if (isBaseline && allMilestones) actions.add(removeBaseline(Collections.singletonList(eventLog))); else actions.add(setBaseline(eventLog, event)); } } if (logs && !events) { actions.add(removeBaseline(input)); } if (event != null && hasSourceCount == 1) { Resource eventSource = graph.getPossibleObject(event, EVENT.Event_source); if (eventSource != null) actions.add(performDefaultAction(eventSource, null)); } return actions.toArray(new IAction[actions.size()]); } private IAction toClipboardAction(String label, String text) { return new ToClipboardAction(label, text); } private IAction markMilestoneAction(List input) { return tagAction("Mark as Milestone", Activator.MARK_MILESTONE_ICON, EventResource.URIs.Milestone, true, input); } private IAction unmarkMilestoneAction(Resource eventLog, List input) { return new UnmarkMilestone(VG_EXPERIMENTS, eventLog, input); } private IAction unhideAction(List input) { return tagAction("Unhide", Activator.UNHIDE_ICON, EventResource.URIs.Hidden, false, input); } private IAction hideAction(List input) { return tagAction("Hide", Activator.HIDE_ICON, EventResource.URIs.Hidden, true, input); } private IAction tagAction(String label, ImageDescriptor image, String tagURI, boolean tag, List input) { return new TagAction(label, image, VG_EXPERIMENTS, tagURI, tag, input); } private IAction setBaseline(Resource eventLog, Resource event) { return new SetBaseline(VG_EXPERIMENTS, eventLog, event); } private IAction removeBaseline(List logs) { return new DenyAction("Remove Baseline", Activator.REMOVE_BASELINE_ICON, VG_EXPERIMENTS, EventResource.URIs.EventLog_HasBaselineEvent, logs); } private IAction performDefaultAction(Resource input, String sourceName) { String title = "Show Event Source"; if (sourceName != null) title += " (" + sourceName + ")"; return new PerformDefaultAction(title, null, input); } private static class ToClipboardAction extends Action { private String text; public ToClipboardAction(String label, String text) { super(label, Activator.CLIPBOARD_ICON); this.text = text; } @Override public void run() { Clipboard clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay()); clipboard.setContents( new Object[] { text }, new Transfer[] { TextTransfer.getInstance() } ); clipboard.dispose(); // Show a message in the status line if possible IWorkbenchPart part = WorkbenchUtils.getActiveWorkbenchPart(); if (part != null) { IStatusLineManager status = WorkbenchUtils.getStatusLine(part); if (status != null) { status.setErrorMessage(null); status.setMessage("Copied '" + text + "' to clipboard"); } } } } private static class UnmarkMilestone extends TagAction { private final Resource eventLog; private final List events; public UnmarkMilestone(String virtualGraphId, Resource eventLog, List events) { super("Unmark Milestone", Activator.UNMARK_MILESTONE_ICON, virtualGraphId, EventResource.URIs.Milestone, false, events); this.eventLog = eventLog; this.events = events; } @Override public void postTagWrite(WriteGraph graph) throws DatabaseException { EventResource EVENT = EventResource.getInstance(graph); Resource baselineEvent = graph.getPossibleObject(eventLog, EVENT.EventLog_HasBaselineEvent); if (baselineEvent != null) { if (events.contains(baselineEvent)) { graph.deny(eventLog, EVENT.EventLog_HasBaselineEvent); } } } } private static class SetBaseline extends ClaimAction { public SetBaseline(String virtualGraphId, Resource subject, Resource object) { super("Set Baseline", Activator.SET_BASELINE_ICON, virtualGraphId, subject, EventResource.URIs.EventLog_HasBaselineEvent, object); } @Override public void claim(WriteGraph graph) throws DatabaseException { super.claim(graph); EventResource EVENT = EventResource.getInstance(graph); if (!graph.hasStatement(object, EVENT.Milestone)) { graph.claim(object, EVENT.Milestone, object); CorrectMilestoneLabelsAction.correctMilestoneLabels(graph, graph.getProvider(), Collections.singleton(object)); } } } }