1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.charts.editor;
14 import org.eclipse.core.commands.AbstractHandler;
15 import org.eclipse.core.commands.ExecutionEvent;
16 import org.eclipse.core.commands.ExecutionException;
17 import org.eclipse.core.expressions.IEvaluationContext;
18 import org.eclipse.jface.dialogs.Dialog;
19 import org.eclipse.jface.dialogs.IDialogSettings;
20 import org.eclipse.jface.dialogs.IInputValidator;
21 import org.eclipse.jface.fieldassist.ControlDecoration;
22 import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
23 import org.eclipse.jface.layout.GridDataFactory;
24 import org.eclipse.jface.layout.GridLayoutFactory;
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.events.ModifyEvent;
27 import org.eclipse.swt.events.ModifyListener;
28 import org.eclipse.swt.graphics.Image;
29 import org.eclipse.swt.graphics.Point;
30 import org.eclipse.swt.widgets.Button;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Control;
33 import org.eclipse.swt.widgets.Label;
34 import org.eclipse.swt.widgets.Shell;
35 import org.eclipse.swt.widgets.Text;
36 import org.simantics.Simantics;
37 import org.simantics.charts.Activator;
38 import org.simantics.databoard.Bindings;
39 import org.simantics.db.Resource;
40 import org.simantics.db.Session;
41 import org.simantics.db.VirtualGraph;
42 import org.simantics.db.WriteGraph;
43 import org.simantics.db.common.request.WriteRequest;
44 import org.simantics.db.exception.DatabaseException;
45 import org.simantics.db.service.VirtualGraphSupport;
46 import org.simantics.event.ontology.EventResource;
47 import org.simantics.event.ontology.EventViewResource;
48 import org.simantics.event.util.EventWriteData;
49 import org.simantics.event.view.handler.CorrectMilestoneLabelsAction;
50 import org.simantics.layer0.Layer0;
51 import org.simantics.trend.impl.TrendNode;
52 import org.simantics.utils.format.TimeFormat;
55 * This handler opens a dialog for new milestone.
57 * @author toni.kalajainen
59 public class AddMilestoneHandler extends AbstractHandler {
62 public Object execute(ExecutionEvent event) throws ExecutionException {
64 TimeSeriesEditor tse = getTSE(event);
67 TrendNode tn = tse.trendNode;
70 final Resource experiment = tse.chartData.run;
71 if (experiment == null)
74 EventData data = new EventData();
75 data.initialTime = tn.lastMouseHoverTime;
76 AddMilestoneDialog d = new AddMilestoneDialog( tse.getSite().getShell(), data );
81 Session session = Simantics.getSession();
82 VirtualGraph vg = session.getService(VirtualGraphSupport.class).getWorkspacePersistent("experiments");
83 session.async( new CreateManualEvent(vg, experiment, data) );
88 TimeSeriesEditor getTSE(ExecutionEvent event) {
89 Object eac = event.getApplicationContext();
90 if (eac == null || (eac instanceof IEvaluationContext == false)) return null;
91 IEvaluationContext ec = (IEvaluationContext) eac;
92 Object editor = ec.getVariable("activeEditor");
93 if (editor == null || (editor instanceof TimeSeriesEditor == false)) return null;
94 TimeSeriesEditor tse = (TimeSeriesEditor) editor;
98 static class CreateManualEvent extends WriteRequest {
100 private final Resource experiment;
101 private final EventData eventData;
103 public CreateManualEvent(VirtualGraph vg, Resource experiment, EventData eventData) {
105 this.experiment = experiment;
106 this.eventData = eventData;
110 public void perform(WriteGraph graph) throws DatabaseException {
111 Layer0 L0 = Layer0.getInstance(graph);
112 EventResource EVENT = EventResource.getInstance(graph);
113 EventViewResource EVENTVIEW = EventViewResource.getInstance(graph);
114 Resource eventlog = graph.getPossibleObject(experiment, EVENT.IsEventProducerOf);
115 if (eventlog == null) return;
117 EventWriteData data = new EventWriteData(graph, eventlog, getProvider());
118 data.prepareToWrite(graph);
120 Resource event = graph.newResource();
121 graph.claim(event, L0.InstanceOf, EVENT.Event);
122 graph.claimLiteral(event, L0.HasName, L0.String, ""+data.targetPos, Bindings.STRING);
123 graph.claimLiteral(event, L0.HasLabel, L0.HasLabel_Inverse, L0.String, eventData.description, Bindings.STRING);
124 graph.claimLiteral(event, L0.HasDescription, L0.HasDescription_Inverse, L0.String, eventData.description, Bindings.STRING);
125 graph.claimLiteral(event, EVENT.HasTimestamp, EVENT.HasTimestamp_Inverse, EVENT.TimeStamp, eventData.parsedTime, Bindings.DOUBLE);
126 if (eventData.isMilestone)
127 graph.claim(event, EVENT.Milestone, event);
128 if (eventData.isBaseline) {
129 graph.deny(eventlog, EVENT.EventLog_HasBaselineEvent);
130 graph.claim(eventlog, EVENT.EventLog_HasBaselineEvent, event);
132 graph.claim(event, EVENT.Event_type, null, EVENTVIEW.ManualEventType);
133 graph.claimLiteral(event, EVENT.Event_message, EVENT.Event_message_Inverse, L0.String, eventData.message, Bindings.STRING);
134 graph.claimLiteral(event, EVENT.Event_tag, EVENT.Event_tag_Inverse, L0.String, eventData.tag, Bindings.STRING);
135 graph.claim(event, EVENT.NoReturn, EVENT.NoReturn, event);
136 graph.claim(data.targetSlice, L0.ConsistsOf, L0.PartOf, event);
141 graph.syncRequest( new CorrectMilestoneLabelsAction(eventlog, getProvider()) );
148 class AddMilestoneDialog extends Dialog {
150 private static final String DIALOG = "AddMilestoneDialog"; //$NON-NLS-1$
152 IInputValidator timeValidator = new IInputValidator() {
154 public String isValid(String text) {
155 if (text.trim().isEmpty())
157 return TimeInputValidator.INSTANCE.isValid(text);
161 Label nameLabel, descLabel, tagLabel, timeLabel, baselineLabel;
162 Text nameText, descText, tagText, timeText;
164 ControlDecoration timeDecor;
168 private IDialogSettings dialogBoundsSettings;
170 protected AddMilestoneDialog(Shell parentShell, EventData data) {
174 IDialogSettings settings = Activator.getDefault().getDialogSettings();
175 dialogBoundsSettings = settings.getSection(DIALOG);
176 if (dialogBoundsSettings == null)
177 dialogBoundsSettings = settings.addNewSection(DIALOG);
181 protected IDialogSettings getDialogBoundsSettings() {
182 return dialogBoundsSettings;
186 protected int getShellStyle() {
187 return SWT.RESIZE | SWT.MODELESS | SWT.TITLE | SWT.CLOSE | SWT.BORDER;
191 protected void configureShell(Shell newShell) {
192 super.configureShell(newShell);
193 newShell.setText("Add new milestone");
197 protected Point getInitialSize() {
198 return super.getInitialSize();
202 protected Control createDialogArea(Composite parent)
204 Composite composite = (Composite) super.createDialogArea(parent);
205 GridLayoutFactory.fillDefaults().margins(8, 8).numColumns(4).applyTo(composite);
207 // In this dialog there are fields for:
214 GridDataFactory gd1 = GridDataFactory.fillDefaults().span(1, 1);
215 GridDataFactory gd2 = GridDataFactory.fillDefaults().minSize(300, SWT.DEFAULT).indent(10, 0).span(3, 1).grab(true, false);
217 nameLabel = new Label(composite, 0);
218 nameLabel.setText("Message:");
219 gd1.applyTo(nameLabel);
220 nameText = new Text(composite, SWT.BORDER);
221 nameText.setText("My Milestone");
222 gd2.applyTo(nameText);
224 tagLabel = new Label(composite, 0);
225 tagLabel.setText("Tag:");
226 gd1.applyTo(tagLabel);
227 tagText = new Text(composite, SWT.BORDER);
229 gd2.applyTo(tagText);
231 descLabel = new Label(composite, 0);
232 descLabel.setText("Description:");
233 gd1.applyTo(descLabel);
234 descText = new Text(composite, SWT.BORDER);
235 gd2.applyTo(descText);
237 timeLabel = new Label(composite, 0);
238 timeLabel.setText("Time:");
239 gd1.applyTo(timeLabel);
240 timeText = new Text(composite, SWT.BORDER);
241 TimeFormat tf = new TimeFormat(data.initialTime, 3);
242 String time = tf.format( data.initialTime );
243 timeText.setText( time );
244 gd2.applyTo(timeText);
245 timeText.addModifyListener(new ModifyListener() {
247 public void modifyText(ModifyEvent e) {
252 baselineLabel = new Label(composite, 0);
253 baselineLabel.setText("Is baseline:");
254 gd1.applyTo(baselineLabel);
255 baselineButt = new Button(composite, SWT.CHECK);
256 gd2.applyTo(baselineButt);
259 Image image = FieldDecorationRegistry.getDefault()
260 .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR)
263 timeDecor = createDecoration(timeText, SWT.LEFT | SWT.CENTER, image);
270 protected ControlDecoration createDecoration(Control control, int position, Image image) {
271 ControlDecoration d = new ControlDecoration(control, position);
278 protected void validateInput() {
281 // Read data from widgets.
282 data.time = timeText.getText();
285 Double parsedTime = TimeInputValidator.INSTANCE.parse( data.time );
286 if (parsedTime == null) {
288 data.parsedTime = 0.0;
290 data.parsedTime = parsedTime;
292 setDecoration(timeDecor, parsedTime == null ? "Invalid time value" : null);
297 private void setDecoration(ControlDecoration decor, String desc) {
301 decor.setDescriptionText(desc);
309 protected void okPressed() {
310 data.message = nameText.getText();
311 data.tag = tagText.getText();
312 data.description = descText.getText();
313 data.time = timeText.getText();
314 data.isBaseline = baselineButt.getSelection();
315 data.isMilestone = true;
319 protected void setFinishable(boolean ok) {
320 Button b = getButton(OK);