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