]> gerrit.simantics Code Review - simantics/platform.git/blob
869d5e32aada675fb56981116fd2eb8ac0961c56
[simantics/platform.git] /
1 package org.simantics.modeling.ui.componentTypeEditor;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.List;
6 import java.util.Set;
7
8 import org.eclipse.jface.layout.GridDataFactory;
9 import org.eclipse.jface.layout.GridLayoutFactory;
10 import org.eclipse.jface.layout.TableColumnLayout;
11 import org.eclipse.jface.viewers.ColumnWeightData;
12 import org.eclipse.swt.SWT;
13 import org.eclipse.swt.custom.TableEditor;
14 import org.eclipse.swt.events.MouseAdapter;
15 import org.eclipse.swt.events.MouseEvent;
16 import org.eclipse.swt.events.SelectionAdapter;
17 import org.eclipse.swt.events.SelectionEvent;
18 import org.eclipse.swt.graphics.Color;
19 import org.eclipse.swt.graphics.Rectangle;
20 import org.eclipse.swt.layout.FillLayout;
21 import org.eclipse.swt.widgets.Button;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Table;
25 import org.eclipse.swt.widgets.TableColumn;
26 import org.eclipse.swt.widgets.TableItem;
27 import org.eclipse.ui.forms.widgets.Form;
28 import org.eclipse.ui.forms.widgets.FormToolkit;
29 import org.eclipse.ui.forms.widgets.Section;
30 import org.simantics.Simantics;
31 import org.simantics.db.ReadGraph;
32 import org.simantics.db.RequestProcessor;
33 import org.simantics.db.Resource;
34 import org.simantics.db.WriteGraph;
35 import org.simantics.db.common.request.PossibleIndexRoot;
36 import org.simantics.db.common.request.UniqueRead;
37 import org.simantics.db.common.request.WriteRequest;
38 import org.simantics.db.exception.DatabaseException;
39 import org.simantics.layer0.Layer0;
40 import org.simantics.modeling.userComponent.ComponentTypeCommands;
41 import org.simantics.scl.runtime.function.Function4;
42 import org.simantics.structural.stubs.StructuralResource2;
43
44 public class DerivedPropertiesSection implements ComponentTypeViewerSection {
45     private static final String[] COLUMN_NAMES = {
46             Messages.DerivedPropertiesSection_Name,
47             Messages.DerivedPropertiesSection_Type,
48             Messages.DerivedPropertiesSection_Expression,
49             Messages.DerivedPropertiesSection_Unit,
50             Messages.DerivedPropertiesSection_Label,
51             Messages.DerivedPropertiesSection_Description
52     };
53     private static final int[] COLUMN_LENGTHS =
54             new int[] { 120, 100, 100, 70, 100, 100 };
55     private static final int[] COLUMN_WEIGHTS =
56             new int[] { 0, 0, 100, 0, 0, 0 };
57     private static Function4<RequestProcessor, Resource, Resource, String, String> VALIDATE_MONITOR_EXPRESSION =
58             new Function4<RequestProcessor, Resource, Resource, String, String>() {
59         @Override
60         public String apply(RequestProcessor p0, Resource p1, Resource p2, String p3) {
61             return validateMonitorExpression(p0, p1, p2, p3);
62         }
63     };
64     
65     ComponentTypeViewerData data;
66     Table table;
67     TableColumn[] columns;
68     TableEditor editor;
69     Button newProperty;
70     Button removeProperty;
71     
72     Section section;
73     
74     public DerivedPropertiesSection(ComponentTypeViewerData data) {
75         this.data = data;
76         FormToolkit tk = data.tk;
77         Form form = data.form;
78         section = tk.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED);
79         section.setLayout(new FillLayout());
80         section.setText(Messages.DerivedPropertiesSection_DerivedProperties);
81
82         Composite sectionBody = tk.createComposite(section);
83         GridLayoutFactory.fillDefaults().numColumns(2).applyTo(sectionBody);
84         section.setClient(sectionBody);
85
86         Composite tableComposite = tk.createComposite(sectionBody);
87         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(tableComposite);
88         TableColumnLayout tcl = new TableColumnLayout();
89         tableComposite.setLayout(tcl);
90
91         table = tk.createTable(tableComposite, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
92         table.setLinesVisible(true);
93         table.setHeaderVisible(true);
94
95         columns = new TableColumn[COLUMN_NAMES.length];
96         for(int i=0;i<COLUMN_NAMES.length;++i) {
97             TableColumn column = new TableColumn(table, SWT.NONE);
98             columns[i] = column;
99             tcl.setColumnData(column, new ColumnWeightData(COLUMN_WEIGHTS[i], COLUMN_LENGTHS[i], true));
100             column.setText(COLUMN_NAMES[i]);
101         }
102
103         // Table editor
104         editor = new TableEditor(table);
105         editor.grabHorizontal = true;
106         editor.grabVertical = true;
107         editor.horizontalAlignment = SWT.LEFT;
108         table.addMouseListener(new MouseAdapter() {
109             @Override
110             public void mouseDown(MouseEvent e) {
111                 // Clean up any previous editor control
112                 Control oldEditor = editor.getEditor();
113                 if (oldEditor != null) oldEditor.dispose();
114
115                 if (data.readOnly)
116                     return;
117
118                 // Relative position
119                 Rectangle tableBounds = table.getClientArea();
120                 int rx = e.x - tableBounds.x;
121                 int ry = e.y - tableBounds.y;
122
123                 // Find cell
124                 TableItem selectedItem = null;
125                 int selectedColumn = -1;
126                 Rectangle selectedItemBounds = null;
127                 for(TableItem item : table.getItems()) {
128                     for(int column = 0;column < COLUMN_NAMES.length;++column) {
129                         Rectangle bounds = item.getBounds(column);
130                         if(bounds.contains(rx, ry)) {
131                             selectedItemBounds = bounds;
132                             selectedItem = item;
133                             selectedColumn = column;
134                             break;
135                         }
136                     }
137                 }
138                 if(selectedItem == null) {
139                     return;
140                 }
141
142                 // Table editor
143                 final int column = selectedColumn; 
144                 final ComponentTypeViewerPropertyInfo propertyInfo = (ComponentTypeViewerPropertyInfo)selectedItem.getData();
145                 final Resource resource = propertyInfo.resource;
146                 switch (column) {
147                 case 0:
148                     data.editName(table, editor, propertyInfo, selectedItem, column, ComponentTypeViewerData.PROPERTY_NAME_PATTERN);
149                     break;
150
151                 case 1:
152                     data.editType(table, editor, propertyInfo, selectedItem, column, false);
153                     break;
154
155                 case 2:
156                     data.editValue(table, editor, propertyInfo, selectedItem, column, propertyInfo.immutable ? null : new StringWriter() {
157                         @Override
158                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {
159                             ComponentTypeCommands.setMonitorExpression(graph, data.componentType, resource, newValue);
160                         }
161                     }, VALIDATE_MONITOR_EXPRESSION);
162                     break;
163
164                 case 3:
165                     data.editUnit(table, editor, propertyInfo, selectedItem, column);
166                     break;
167
168                 case 4:
169                     data.editValue(table, editor, propertyInfo, selectedItem, column, propertyInfo.immutable ? null : new StringWriter() {
170                         @Override
171                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {
172                             graph.markUndoPoint();
173                             String value = newValue.isEmpty() ? null : newValue;
174                             ComponentTypeCommands.setLabel(graph, resource, value);
175                         }
176                     }, null);
177                     break;
178
179                 case 5:
180                     data.editMultilineText(table, editor, propertyInfo, selectedItem, selectedItemBounds, column, new StringWriter() {
181                         @Override
182                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {
183                             graph.markUndoPoint();
184                             String value = newValue.isEmpty() ? null : newValue;
185                             ComponentTypeCommands.setDescription(graph, resource, value);
186                         }
187                     });
188                     break;
189                 }
190             }
191
192         });
193
194         // Buttons
195
196         Composite buttons = tk.createComposite(sectionBody);
197         GridDataFactory.fillDefaults().applyTo(buttons);
198         GridLayoutFactory.fillDefaults().applyTo(buttons);
199
200         newProperty = tk.createButton(buttons, Messages.DerivedPropertiesSection_NewProperty, SWT.PUSH);
201         GridDataFactory.fillDefaults().applyTo(newProperty);
202         removeProperty = tk.createButton(buttons, Messages.DerivedPropertiesSection_RemoveProperty, SWT.PUSH);
203         GridDataFactory.fillDefaults().applyTo(removeProperty);
204
205         // Actions
206
207         newProperty.addSelectionListener(new SelectionAdapter() {
208             @Override
209             public void widgetSelected(SelectionEvent e) {
210                 if(editor.getEditor() != null)
211                     editor.getEditor().dispose();
212                 Simantics.getSession().async(new WriteRequest() {
213                     @Override
214                     public void perform(WriteGraph graph)
215                             throws DatabaseException {
216                         ComponentTypeCommands.createMonitorPropertyWithDefaults(graph, data.componentType);
217                     }
218                 });
219             }
220         });
221
222         removeProperty.addSelectionListener(new SelectionAdapter() {
223             @Override
224             public void widgetSelected(SelectionEvent e) {
225                 if(editor.getEditor() != null)
226                     editor.getEditor().dispose();
227                 final List<Resource> propertiesToBeRemoved = 
228                         new ArrayList<>();
229                 for(TableItem item : table.getSelection())
230                     propertiesToBeRemoved.add(((ComponentTypeViewerPropertyInfo)item.getData()).resource);
231                 //System.out.println("remove " + propertiesToBeRemoved.size() + " resources");
232                 if(!propertiesToBeRemoved.isEmpty())
233                     Simantics.getSession().async(new WriteRequest() {
234                         @Override
235                         public void perform(WriteGraph graph)
236                                 throws DatabaseException {
237                             graph.markUndoPoint();
238                             for(Resource property : propertiesToBeRemoved)
239                                 ComponentTypeCommands.removeProperty(graph, data.componentType, property);
240                         }
241                     });
242             }
243         });
244     }
245
246     @Override
247     public void setReadOnly(boolean readOnly) {
248         boolean e = !readOnly;
249         newProperty.setEnabled(e);
250         removeProperty.setEnabled(e);
251     }
252
253     public static String validateMonitorExpression(final RequestProcessor processor, final Resource componentType, final Resource relation, final String expression) {
254
255         if (expression.trim().isEmpty()) {
256             return Messages.DerivedPropertiesSection_ExpressionIsEmpty;
257         }
258
259         if (expression.trim().isEmpty()) {
260             return Messages.DerivedPropertiesSection_ExpressionIsEmpty;
261         }
262         try {
263             return processor.sync(new UniqueRead<String>() {
264
265                 @Override
266                 public String perform(ReadGraph graph) throws DatabaseException {
267
268                     StructuralResource2 STR = StructuralResource2.getInstance(graph);
269
270                     Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(componentType));
271
272                     for(Resource literal : graph.getAssertedObjects(componentType, relation)) {
273
274                         try {
275                             // TODO validation
276                             if(graph.isInstanceOf(componentType, STR.ProceduralComponentType)) {
277                                 //Layer0 L0 = Layer0.getInstance(graph);
278                                 //Resource environment = graph.getPossibleObject(literal, L0.SCLValue_environment); 
279                                 //ContextModule context = graph.sync(new TypeMonitorContextRequest(componentType));
280                                 //String SCLMain = graph.syncRequest(new SCLMainModuleRequest(indexRoot));
281                                 //CompilationContext cc = new CompilationContext(environment, context, SCLMain);
282                                 //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.<CompiledExpression>instance());
283                             } else {
284                                 //CompilationContext cc = new CompileSCLMonitorRequest(literal, componentType, indexRoot).getContext(graph);
285                                 //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.<CompiledExpression>instance());
286                                 //graph.syncRequest(new CompileSCLMonitorRequest(graph, context));
287                             }
288                             
289                         } catch (Exception e) {
290                             String msg = e.getMessage();
291                             int index = msg.indexOf(":"); //$NON-NLS-1$
292                             if(index > 0) msg = msg.substring(index);
293                             return msg;
294                         }
295                         
296                     }
297                     
298                     return null;
299                     
300                 }
301                 
302             });
303         } catch (DatabaseException e) {
304             e.printStackTrace();
305         }
306
307         return null;
308
309     }
310
311     @Override
312     public void update(ComponentTypePropertiesResult result) {
313         if (table.isDisposed())
314             return;
315
316         Set<ComponentTypeViewerPropertyInfo> selected = new HashSet<>();
317         List<TableItem> selectedItems = new ArrayList<TableItem>(selected.size());
318         for (int i : table.getSelectionIndices()) {
319             TableItem item = table.getItem(i);
320             selected.add((ComponentTypeViewerPropertyInfo) item.getData());
321         }
322         
323         int topIndex = table.getTopIndex();
324         table.removeAll();
325         if(editor.getEditor() != null)
326             editor.getEditor().dispose();
327         
328         for(ComponentTypeViewerPropertyInfo info : result.getProperties()) {
329             boolean immutable = result.isImmutable() || info.immutable;
330             Color fg = immutable ? table.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY) : null;
331             if(info.sectionSpecificData != MONITOR)
332                 continue;
333
334             TableItem item = new TableItem(table, SWT.NONE);
335
336             item.setText(0, info.valid != null ? info.name + " (!)" : info.name); //$NON-NLS-1$
337             item.setText(1, info.type);
338             item.setText(2, info.expression);
339             item.setText(3, info.unitString());
340             item.setText(4, info.label);
341             item.setText(5, info.description);
342
343             item.setForeground(fg);
344
345             item.setData(info);
346
347             if (selected.contains(info))
348                 selectedItems.add(item);
349         }
350         
351         table.setTopIndex(topIndex);
352         table.setSelection(selectedItems.toArray(new TableItem[selectedItems.size()]));
353         table.redraw();
354     }
355
356     @Override
357     public Section getSection() {
358         return section;
359     }
360
361     @Override
362     public double getPriority() {
363         return 100.0;
364     }
365
366     private static final Object MONITOR = new Object();
367     
368     @Override
369     public Object getSectionSpecificData(ReadGraph graph,
370             ComponentTypeViewerPropertyInfo info) throws DatabaseException {
371         Layer0 L0 = Layer0.getInstance(graph);
372         StructuralResource2 STR = StructuralResource2.getInstance(graph);
373         Resource range = graph.getPossibleObject(info.resource, L0.HasRange);
374         if(range != null && graph.isInstanceOf(range, STR.MonitorValueType))
375             return MONITOR;
376         else
377             return null;
378     }
379     
380     @Override
381     public double getDataPriority() {
382         return 100.0;
383     }
384
385 }