]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.charts/src/org/simantics/charts/editor/AddMilestoneHandler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.charts / src / org / simantics / charts / editor / AddMilestoneHandler.java
diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/editor/AddMilestoneHandler.java b/bundles/org.simantics.charts/src/org/simantics/charts/editor/AddMilestoneHandler.java
new file mode 100644 (file)
index 0000000..d976caf
--- /dev/null
@@ -0,0 +1,337 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.charts.editor;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.core.expressions.IEvaluationContext;\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.dialogs.IDialogSettings;\r
+import org.eclipse.jface.dialogs.IInputValidator;\r
+import org.eclipse.jface.fieldassist.ControlDecoration;\r
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.simantics.Simantics;\r
+import org.simantics.charts.Activator;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.VirtualGraphSupport;\r
+import org.simantics.event.ontology.EventResource;\r
+import org.simantics.event.ontology.EventViewResource;\r
+import org.simantics.event.util.EventWriteData;\r
+import org.simantics.event.view.handler.CorrectMilestoneLabelsAction;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.trend.impl.TrendNode;\r
+import org.simantics.utils.format.TimeFormat;\r
+\r
+/**\r
+ * This handler opens a dialog for new milestone.\r
+ * \r
+ * @author toni.kalajainen\r
+ */\r
+public class AddMilestoneHandler extends AbstractHandler {\r
+\r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+\r
+        TimeSeriesEditor tse = getTSE(event);\r
+        if (tse == null)\r
+            return null;\r
+        TrendNode tn = tse.trendNode;\r
+        if (tn == null)\r
+            return null;\r
+        final Resource experiment = tse.chartData.run;\r
+        if (experiment == null)\r
+            return null;\r
+\r
+        EventData data = new EventData();\r
+        data.initialTime = tn.lastMouseHoverTime;\r
+        AddMilestoneDialog d = new AddMilestoneDialog( tse.getSite().getShell(), data );\r
+        int ok = d.open();\r
+        if (ok != Dialog.OK)\r
+            return null;\r
+\r
+        Session session = Simantics.getSession();\r
+        VirtualGraph vg = session.getService(VirtualGraphSupport.class).getWorkspacePersistent("experiments");\r
+        session.async( new CreateManualEvent(vg, experiment, data) );\r
+\r
+        return null;\r
+    }\r
+\r
+    TimeSeriesEditor getTSE(ExecutionEvent event) {\r
+        Object eac = event.getApplicationContext();\r
+        if (eac == null || (eac instanceof IEvaluationContext == false)) return null;\r
+        IEvaluationContext ec = (IEvaluationContext) eac;\r
+        Object editor = ec.getVariable("activeEditor");\r
+        if (editor == null || (editor instanceof TimeSeriesEditor == false)) return null;\r
+        TimeSeriesEditor tse = (TimeSeriesEditor) editor;\r
+        return tse;\r
+    }\r
+\r
+    static class CreateManualEvent extends WriteRequest {\r
+\r
+        private final Resource experiment;\r
+        private final EventData eventData;\r
+\r
+        public CreateManualEvent(VirtualGraph vg, Resource experiment, EventData eventData) {\r
+            super(vg);\r
+            this.experiment = experiment;\r
+            this.eventData = eventData;\r
+        }\r
+\r
+        @Override\r
+        public void perform(WriteGraph graph) throws DatabaseException {\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+            EventResource EVENT = EventResource.getInstance(graph);\r
+            EventViewResource EVENTVIEW = EventViewResource.getInstance(graph);\r
+            Resource eventlog = graph.getPossibleObject(experiment, EVENT.IsEventProducerOf);\r
+            if (eventlog == null) return;\r
+\r
+            EventWriteData data = new EventWriteData(graph, eventlog, getProvider());\r
+            data.prepareToWrite(graph);\r
+\r
+            Resource event = graph.newResource(); \r
+            graph.claim(event, L0.InstanceOf, EVENT.Event);\r
+            graph.claimLiteral(event, L0.HasName, L0.String, ""+data.targetPos, Bindings.STRING);\r
+            graph.claimLiteral(event, L0.HasLabel, L0.HasLabel_Inverse, L0.String, eventData.description, Bindings.STRING);\r
+            graph.claimLiteral(event, L0.HasDescription, L0.HasDescription_Inverse, L0.String, eventData.description, Bindings.STRING);\r
+            graph.claimLiteral(event, EVENT.HasTimestamp, EVENT.HasTimestamp_Inverse, EVENT.TimeStamp, eventData.parsedTime, Bindings.DOUBLE);\r
+            if (eventData.isMilestone)\r
+                graph.claim(event, EVENT.Milestone, event);\r
+            if (eventData.isBaseline) {\r
+                graph.deny(eventlog, EVENT.EventLog_HasBaselineEvent);\r
+                graph.claim(eventlog, EVENT.EventLog_HasBaselineEvent, event);\r
+            }\r
+            graph.claim(event, EVENT.Event_type, null, EVENTVIEW.ManualEventType);\r
+            graph.claimLiteral(event, EVENT.Event_message, EVENT.Event_message_Inverse, L0.String, eventData.message, Bindings.STRING);\r
+            graph.claimLiteral(event, EVENT.Event_tag, EVENT.Event_tag_Inverse, L0.String, eventData.tag, Bindings.STRING);\r
+            graph.claim(event, EVENT.NoReturn, EVENT.NoReturn, event);\r
+            graph.claim(data.targetSlice, L0.ConsistsOf, L0.PartOf, event);\r
+\r
+            data.written();\r
+            data.commit(graph);\r
+\r
+            graph.syncRequest( new CorrectMilestoneLabelsAction(eventlog, getProvider()) );\r
+        }\r
+    }\r
+\r
+}\r
+\r
+\r
+class AddMilestoneDialog extends Dialog {\r
+\r
+    private static final String DIALOG = "AddMilestoneDialog"; //$NON-NLS-1$\r
+\r
+    IInputValidator timeValidator = new IInputValidator() {\r
+        @Override\r
+        public String isValid(String text) {\r
+            if (text.trim().isEmpty())\r
+                return null;\r
+            return TimeInputValidator.INSTANCE.isValid(text);\r
+        }\r
+    }; \r
+\r
+    Label nameLabel, descLabel, tagLabel, timeLabel, baselineLabel;\r
+    Text nameText, descText, tagText, timeText;\r
+    Button baselineButt;\r
+    ControlDecoration timeDecor;\r
+\r
+    EventData data;\r
+\r
+    private IDialogSettings dialogBoundsSettings;\r
+\r
+    protected AddMilestoneDialog(Shell parentShell, EventData data) {\r
+        super(parentShell);\r
+        this.data = data;\r
+\r
+        IDialogSettings settings = Activator.getDefault().getDialogSettings();\r
+        dialogBoundsSettings = settings.getSection(DIALOG);\r
+        if (dialogBoundsSettings == null)\r
+            dialogBoundsSettings = settings.addNewSection(DIALOG);\r
+    }\r
+\r
+    @Override\r
+    protected IDialogSettings getDialogBoundsSettings() {\r
+        return dialogBoundsSettings;\r
+    }\r
+\r
+    @Override\r
+    protected int getShellStyle() {\r
+        return SWT.RESIZE | SWT.MODELESS | SWT.TITLE | SWT.CLOSE | SWT.BORDER;\r
+    }\r
+\r
+    @Override\r
+    protected void configureShell(Shell newShell) {\r
+        super.configureShell(newShell);\r
+        newShell.setText("Add new milestone");\r
+    }\r
+\r
+    @Override\r
+    protected Point getInitialSize() {\r
+        return super.getInitialSize();\r
+    }\r
+\r
+    @Override\r
+    protected Control createDialogArea(Composite parent) \r
+    {\r
+        Composite composite = (Composite) super.createDialogArea(parent);\r
+        GridLayoutFactory.fillDefaults().margins(8, 8).numColumns(4).applyTo(composite);\r
+\r
+        // In this dialog there are fields for:\r
+        //   Message:\r
+        //   Tag:\r
+        //   Description:\r
+        //   Time:\r
+        //   [x] Baseline\r
+\r
+        GridDataFactory gd1 = GridDataFactory.fillDefaults().span(1, 1);\r
+        GridDataFactory gd2 = GridDataFactory.fillDefaults().minSize(300, SWT.DEFAULT).indent(10, 0).span(3, 1).grab(true, false);\r
+\r
+        nameLabel = new Label(composite, 0);\r
+        nameLabel.setText("Message:");\r
+        gd1.applyTo(nameLabel);\r
+        nameText = new Text(composite, SWT.BORDER);\r
+        nameText.setText("My Milestone");\r
+        gd2.applyTo(nameText);\r
+\r
+        tagLabel = new Label(composite, 0);\r
+        tagLabel.setText("Tag:");\r
+        gd1.applyTo(tagLabel);\r
+        tagText = new Text(composite, SWT.BORDER);\r
+        tagText.setText("");\r
+        gd2.applyTo(tagText);\r
+\r
+        descLabel = new Label(composite, 0);\r
+        descLabel.setText("Description:");\r
+        gd1.applyTo(descLabel);\r
+        descText = new Text(composite, SWT.BORDER);\r
+        gd2.applyTo(descText);\r
+\r
+        timeLabel = new Label(composite, 0);\r
+        timeLabel.setText("Time:");\r
+        gd1.applyTo(timeLabel);\r
+        timeText = new Text(composite, SWT.BORDER);\r
+        TimeFormat tf = new TimeFormat(data.initialTime, 3);\r
+        String time = tf.format( data.initialTime );\r
+        timeText.setText( time );\r
+        gd2.applyTo(timeText);\r
+        timeText.addModifyListener(new ModifyListener() {\r
+            @Override\r
+            public void modifyText(ModifyEvent e) {\r
+                validateInput();\r
+            }\r
+        });\r
+\r
+        baselineLabel = new Label(composite, 0);\r
+        baselineLabel.setText("Is baseline:");\r
+        gd1.applyTo(baselineLabel);\r
+        baselineButt = new Button(composite, SWT.CHECK);\r
+        gd2.applyTo(baselineButt);\r
+\r
+        // Error decorations\r
+        Image image = FieldDecorationRegistry.getDefault()\r
+                .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR)\r
+                .getImage();\r
+\r
+        timeDecor = createDecoration(timeText, SWT.LEFT | SWT.CENTER, image);\r
+\r
+        validateInput();\r
+\r
+        return composite;\r
+    }\r
+\r
+    protected ControlDecoration createDecoration(Control control, int position, Image image) {\r
+        ControlDecoration d = new ControlDecoration(control, position);\r
+        d.setMarginWidth(2);\r
+        d.setImage(image);\r
+        d.hide();\r
+        return d;\r
+    }\r
+\r
+    protected void validateInput() {\r
+        boolean ok = true;\r
+\r
+        // Read data from widgets.\r
+        data.time = timeText.getText();\r
+\r
+        // Validate data.\r
+        Double parsedTime = TimeInputValidator.INSTANCE.parse( data.time );\r
+        if (parsedTime == null) {\r
+            ok = false;\r
+            data.parsedTime = 0.0;\r
+        } else {\r
+            data.parsedTime = parsedTime;\r
+        }\r
+        setDecoration(timeDecor, parsedTime == null ? "Invalid time value" : null);\r
+\r
+        setFinishable(ok);\r
+    }\r
+\r
+    private void setDecoration(ControlDecoration decor, String desc) {\r
+        if (decor == null)\r
+            return;\r
+        if (desc != null) {\r
+            decor.setDescriptionText(desc);\r
+            decor.show();\r
+        } else {\r
+            decor.hide();\r
+        }\r
+    }\r
+\r
+    @Override\r
+    protected void okPressed() {\r
+        data.message = nameText.getText();\r
+        data.tag = tagText.getText();\r
+        data.description = descText.getText();\r
+        data.time = timeText.getText();\r
+        data.isBaseline = baselineButt.getSelection();\r
+        data.isMilestone = true;\r
+        super.okPressed();\r
+    }\r
+\r
+    protected void setFinishable(boolean ok) {\r
+        Button b = getButton(OK);\r
+        if (b != null)\r
+            b.setEnabled(ok);\r
+    }\r
+\r
+}\r
+\r
+class EventData {\r
+    double initialTime;\r
+\r
+    String message;\r
+    String tag;\r
+    String description;\r
+    String time;\r
+    double parsedTime;\r
+    boolean isBaseline;\r
+    boolean isMilestone;\r
+}\r