]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ConfigurationPropertiesSection.java
Merge commit 'bf75fd9'
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / componentTypeEditor / ConfigurationPropertiesSection.java
1 package org.simantics.modeling.ui.componentTypeEditor;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.Collections;\r
6 import java.util.HashMap;\r
7 import java.util.HashSet;\r
8 import java.util.List;\r
9 import java.util.Map;\r
10 import java.util.Set;\r
11 \r
12 import org.eclipse.jface.dialogs.IDialogSettings;\r
13 import org.eclipse.jface.layout.GridDataFactory;\r
14 import org.eclipse.jface.layout.GridLayoutFactory;\r
15 import org.eclipse.jface.layout.TableColumnLayout;\r
16 import org.eclipse.jface.resource.ImageDescriptor;\r
17 import org.eclipse.jface.viewers.ColumnWeightData;\r
18 import org.eclipse.jface.window.Window;\r
19 import org.eclipse.swt.SWT;\r
20 import org.eclipse.swt.custom.TableEditor;\r
21 import org.eclipse.swt.events.DisposeEvent;\r
22 import org.eclipse.swt.events.DisposeListener;\r
23 import org.eclipse.swt.events.MouseAdapter;\r
24 import org.eclipse.swt.events.MouseEvent;\r
25 import org.eclipse.swt.events.SelectionAdapter;\r
26 import org.eclipse.swt.events.SelectionEvent;\r
27 import org.eclipse.swt.graphics.Color;\r
28 import org.eclipse.swt.graphics.Rectangle;\r
29 import org.eclipse.swt.layout.FillLayout;\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.Shell;\r
34 import org.eclipse.swt.widgets.Table;\r
35 import org.eclipse.swt.widgets.TableColumn;\r
36 import org.eclipse.swt.widgets.TableItem;\r
37 import org.eclipse.ui.PlatformUI;\r
38 import org.eclipse.ui.forms.widgets.Form;\r
39 import org.eclipse.ui.forms.widgets.FormToolkit;\r
40 import org.eclipse.ui.forms.widgets.Section;\r
41 import org.simantics.Simantics;\r
42 import org.simantics.databoard.Bindings;\r
43 import org.simantics.db.ReadGraph;\r
44 import org.simantics.db.Resource;\r
45 import org.simantics.db.WriteGraph;\r
46 import org.simantics.db.common.CommentMetadata;\r
47 import org.simantics.db.common.request.ObjectsWithType;\r
48 import org.simantics.db.common.request.PossibleIndexRoot;\r
49 import org.simantics.db.common.request.UniqueRead;\r
50 import org.simantics.db.common.request.WriteRequest;\r
51 import org.simantics.db.common.utils.NameUtils;\r
52 import org.simantics.db.exception.DatabaseException;\r
53 import org.simantics.db.layer0.adapter.CopyHandler2;\r
54 import org.simantics.db.layer0.adapter.Instances;\r
55 import org.simantics.db.layer0.util.Layer0Utils;\r
56 import org.simantics.db.layer0.variable.Variable;\r
57 import org.simantics.db.layer0.variable.Variables;\r
58 import org.simantics.layer0.Layer0;\r
59 import org.simantics.modeling.ui.Activator;\r
60 import org.simantics.modeling.ui.componentTypeEditor.LiftPropertiesDialog.LiftedProperty;\r
61 import org.simantics.modeling.userComponent.ComponentTypeCommands;\r
62 import org.simantics.selectionview.SelectionViewResources;\r
63 import org.simantics.structural.stubs.StructuralResource2;\r
64 import org.simantics.utils.datastructures.Pair;\r
65 import org.slf4j.Logger;\r
66 import org.slf4j.LoggerFactory;\r
67 \r
68 public class ConfigurationPropertiesSection implements ComponentTypeViewerSection {\r
69 \r
70     private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationPropertiesSection.class);\r
71     \r
72     private static final String[] COLUMN_NAMES = \r
73             new String[] {"Name", "Type", "Default Value", "Unit", "Range", "Label", "Description"};\r
74     private static final int[] COLUMN_LENGTHS =\r
75             new int[] { 120, 100, 100, 50, 100, 100, 100 };\r
76     private static final int[] COLUMN_WEIGHTS =\r
77             new int[] { 0, 0, 0, 0, 0, 50, 100 };\r
78 \r
79     /**\r
80      * Configuration property table column indexes that are to be considered\r
81      * immutable when the property relation is immutable. Note that relation\r
82      * immutability does not make the asserted default value immutable.\r
83      */\r
84     private static final int[] IMMUTABLE_COLUMNS_WITH_IMMUTABLE_RELATION =\r
85         { 0, 1, 3, 4, 5, 6 };\r
86     \r
87     ComponentTypeViewerData data;\r
88     Table table;\r
89     TableColumn[] columns;\r
90     TableEditor editor;\r
91     Button newProperty;\r
92     Button removeProperty;\r
93     Button liftProperties;\r
94 \r
95     boolean hasTypes = false;\r
96     Button setTypes;\r
97     \r
98     Section section;\r
99     \r
100     public ConfigurationPropertiesSection(ComponentTypeViewerData data) {\r
101         this.data = data;\r
102         FormToolkit tk = data.tk;\r
103         Form form = data.form;\r
104         \r
105         section = tk.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED);\r
106         section.setLayout(new FillLayout());\r
107         section.setText("Configuration properties");\r
108 \r
109         Composite sectionBody = tk.createComposite(section);\r
110         GridLayoutFactory.fillDefaults().numColumns(2).applyTo(sectionBody);\r
111         section.setClient(sectionBody);\r
112 \r
113         Composite tableComposite = tk.createComposite(sectionBody);\r
114         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(tableComposite);\r
115         TableColumnLayout tcl = new TableColumnLayout();\r
116         tableComposite.setLayout(tcl);\r
117 \r
118         table = tk.createTable(tableComposite, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);\r
119         table.setLinesVisible(true);\r
120         table.setHeaderVisible(true);\r
121 \r
122         columns = new TableColumn[COLUMN_NAMES.length];\r
123         for(int i=0;i<COLUMN_NAMES.length;++i) {\r
124             TableColumn column = new TableColumn(table, SWT.NONE);\r
125             columns[i] = column;\r
126             tcl.setColumnData(column, new ColumnWeightData(COLUMN_WEIGHTS[i], COLUMN_LENGTHS[i], true));\r
127             column.setText(COLUMN_NAMES[i]);\r
128         }\r
129 \r
130         // Table editor\r
131         editor = new TableEditor(table);\r
132         editor.grabHorizontal = true;\r
133         editor.grabVertical = true;\r
134         editor.horizontalAlignment = SWT.LEFT;\r
135         table.addMouseListener(new MouseAdapter() {\r
136             @Override\r
137             public void mouseDown(MouseEvent e) {\r
138                 // Clean up any previous editor control\r
139                 Control oldEditor = editor.getEditor();\r
140                 if (oldEditor != null) oldEditor.dispose();\r
141 \r
142                 if (data.readOnly)\r
143                     return;\r
144 \r
145                 // Relative position\r
146                 Rectangle tableBounds = table.getClientArea();\r
147                 int rx = e.x - tableBounds.x;\r
148                 int ry = e.y - tableBounds.y;\r
149 \r
150                 // Find cell\r
151                 TableItem selectedItem = null;\r
152                 int selectedColumn = -1;\r
153                 Rectangle selectedItemBounds = null;\r
154                 for(TableItem item : table.getItems()) {\r
155                     for(int column = 0;column < COLUMN_NAMES.length;++column) {\r
156                         Rectangle bounds = item.getBounds(column);\r
157                         if(bounds.contains(rx, ry)) {\r
158                             selectedItemBounds = bounds;\r
159                             selectedItem = item;\r
160                             selectedColumn = column;\r
161                             break;\r
162                         }\r
163                     }\r
164                 }\r
165                 if(selectedItem == null) {\r
166                     return;\r
167                 }\r
168 \r
169                 // Table editor\r
170                 final int column = selectedColumn; \r
171                 final ComponentTypeViewerPropertyInfo propertyInfo = (ComponentTypeViewerPropertyInfo)selectedItem.getData();\r
172                 final Resource resource = propertyInfo.resource;\r
173                 switch (column) {\r
174                 case 0:\r
175                     data.editName(table, editor, propertyInfo, selectedItem, column, ComponentTypeViewerData.PROPERTY_NAME_PATTERN);\r
176                     break;\r
177 \r
178                 case 1:\r
179                     data.editType(table, editor, propertyInfo, selectedItem, column, true);\r
180                     break;\r
181 \r
182                 case 2: {\r
183                     data.editValue(table, editor, propertyInfo, selectedItem, column, data.readOnly ? null : new StringWriter() {\r
184                         @Override\r
185                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {\r
186                             graph.markUndoPoint();\r
187                             ComponentTypeCommands.setDefaultValue(graph, data.componentType, propertyInfo.resource, newValue);\r
188                         }\r
189                     }, null);\r
190                 } break;\r
191 \r
192                 case 3:\r
193                     data.editUnit(table, editor, propertyInfo, selectedItem, column);\r
194                     break;\r
195 \r
196                 case 4:\r
197                     data.editRange(table, editor, propertyInfo, selectedItem, selectedItemBounds, column);\r
198                     break;\r
199 \r
200                 case 5:\r
201                     data.editValue(table, editor, propertyInfo, selectedItem, column, propertyInfo.immutable ? null : new StringWriter() {\r
202                         @Override\r
203                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {\r
204                             graph.markUndoPoint();\r
205                             String value = newValue.isEmpty() ? null : newValue;\r
206                             ComponentTypeCommands.setLabel(graph, resource, value);\r
207                         }\r
208                     }, null);\r
209                     break;\r
210 \r
211                 case 6:\r
212                     data.editMultilineText(table, editor, propertyInfo, selectedItem, selectedItemBounds, column, new StringWriter() {\r
213                         @Override\r
214                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {\r
215                             graph.markUndoPoint();\r
216                             String value = newValue.isEmpty() ? null : newValue;\r
217                             ComponentTypeCommands.setDescription(graph, resource, value);\r
218                         }\r
219                     });\r
220                     break;\r
221                 }\r
222             }\r
223         });\r
224 \r
225         // Buttons\r
226 \r
227         Composite buttons = tk.createComposite(sectionBody);\r
228         GridDataFactory.fillDefaults().applyTo(buttons);\r
229         GridLayoutFactory.fillDefaults().applyTo(buttons);\r
230 \r
231         newProperty = tk.createButton(buttons, "New property", SWT.PUSH);\r
232         GridDataFactory.fillDefaults().applyTo(newProperty);\r
233         removeProperty = tk.createButton(buttons, "Remove property", SWT.PUSH);\r
234         GridDataFactory.fillDefaults().applyTo(removeProperty);\r
235 \r
236         liftProperties = tk.createButton(buttons, "Lift Properties", SWT.PUSH);\r
237         GridDataFactory.fillDefaults().applyTo(liftProperties);\r
238 \r
239         hasTypes = !getTypes().isEmpty();\r
240         \r
241         if(hasTypes) {\r
242             setTypes = tk.createButton(buttons, "Assign Types", SWT.PUSH);\r
243             GridDataFactory.fillDefaults().applyTo(setTypes);\r
244         }\r
245 \r
246         // Actions\r
247 \r
248         table.addSelectionListener(new SelectionAdapter() {\r
249             @Override\r
250             public void widgetSelected(SelectionEvent e) {\r
251                 TableItem[] sel = table.getSelection();\r
252                 for (TableItem item : sel) {\r
253                     ComponentTypeViewerPropertyInfo pi = (ComponentTypeViewerPropertyInfo) item.getData();\r
254                     if (pi.immutable) {\r
255                         removeProperty.setEnabled(false);\r
256                         return;\r
257                     }\r
258                 }\r
259                 removeProperty.setEnabled(true);\r
260             }\r
261         });\r
262 \r
263         newProperty.addSelectionListener(new SelectionAdapter() {\r
264             @Override\r
265             public void widgetSelected(SelectionEvent e) {\r
266                 if(editor.getEditor() != null)\r
267                     editor.getEditor().dispose();\r
268                 Simantics.getSession().async(new WriteRequest() {\r
269                     @Override\r
270                     public void perform(WriteGraph graph)\r
271                             throws DatabaseException {\r
272                         ComponentTypeCommands.createPropertyWithDefaults(graph, data.componentType);\r
273                     }\r
274                 });\r
275             }\r
276         });\r
277 \r
278         removeProperty.addSelectionListener(new SelectionAdapter() {\r
279             @Override\r
280             public void widgetSelected(SelectionEvent e) {\r
281                 if(editor.getEditor() != null)\r
282                     editor.getEditor().dispose();\r
283                 final List<Resource> propertiesToBeRemoved = \r
284                         new ArrayList<>();\r
285                 for(TableItem item : table.getSelection()) {\r
286                     ComponentTypeViewerPropertyInfo info = (ComponentTypeViewerPropertyInfo) item.getData();\r
287                     if (!info.immutable)\r
288                         propertiesToBeRemoved.add(info.resource);\r
289                 }\r
290                 System.out.println("remove " + propertiesToBeRemoved.size() + " resources");\r
291                 if(!propertiesToBeRemoved.isEmpty())\r
292                     Simantics.getSession().async(new WriteRequest() {\r
293                         @Override\r
294                         public void perform(WriteGraph graph)\r
295                                 throws DatabaseException {\r
296                             graph.markUndoPoint();\r
297                             for(Resource property : propertiesToBeRemoved)\r
298                                 ComponentTypeCommands.removeProperty(graph, data.componentType, property);\r
299                         }\r
300                     });\r
301             }\r
302         });\r
303         \r
304         liftProperties.addSelectionListener(new SelectionAdapter() {\r
305             @Override\r
306             public void widgetSelected(SelectionEvent e) {\r
307                 \r
308                 if(editor.getEditor() != null)\r
309                     editor.getEditor().dispose();\r
310 \r
311                 try {\r
312                 \r
313                     Map<LiftedProperty, Pair<String, ImageDescriptor>> map = Simantics.sync(new UniqueRead<Map<LiftedProperty,Pair<String,ImageDescriptor>>>() {\r
314     \r
315                         @Override\r
316                         public Map<LiftedProperty, Pair<String, ImageDescriptor>> perform(ReadGraph graph) throws DatabaseException {\r
317                             \r
318                             Map<LiftedProperty, Pair<String,ImageDescriptor>> map = new HashMap<>(); \r
319                             \r
320                             Layer0 L0 = Layer0.getInstance(graph);\r
321                             StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
322                             SelectionViewResources SEL = SelectionViewResources.getInstance(graph);\r
323     \r
324                             Resource composite = graph.getPossibleObject(data.componentType, STR.IsDefinedBy);\r
325                             if(composite == null) return map;\r
326 \r
327 \r
328                             Set<String> existing = new HashSet<>();\r
329                             for(Resource predicate : graph.getObjects(data.componentType, L0.DomainOf)) {\r
330                                 if(graph.isSubrelationOf(predicate, L0.HasProperty)) {\r
331                                     existing.add(NameUtils.getSafeName(graph, predicate));\r
332                                 }\r
333                             }\r
334                             \r
335                             for(Resource component : graph.syncRequest(new ObjectsWithType(composite, L0.ConsistsOf, STR.Component))) {\r
336     \r
337                                 Resource type = graph.getPossibleType(component, STR.Component);\r
338                                 if(type == null) continue;\r
339                                 \r
340                                 String componentName = NameUtils.getSafeName(graph, component);\r
341     \r
342                                 for(Resource predicate : graph.getPredicates(component)) {\r
343                                     if(graph.isSubrelationOf(predicate, L0.HasProperty)) {\r
344     \r
345                                         // Do not list properties shown under other properties\r
346                                         if(graph.hasStatement(predicate, SEL.IsShownUnder)) continue;\r
347                                         \r
348                                         // Do not list properties that are not visible in selection view\r
349                                         if(!graph.hasStatement(predicate, SEL.HasStandardPropertyInfo)) continue;\r
350                                         \r
351                                         // Some properties are explicitly marked as non-liftable\r
352                                         Boolean canBeLifted = graph.getPossibleRelatedValue(predicate, SEL.canBeLifted, Bindings.BOOLEAN);\r
353                                         if(canBeLifted != null && !canBeLifted) continue;\r
354                                         \r
355                                         String predicateName = NameUtils.getSafeName(graph, predicate);\r
356                                         if(existing.contains(predicateName)) continue;\r
357                                         \r
358                                         String name = componentName + " " + predicateName;\r
359                                         map.put(new LiftedProperty(component, type, predicate), new Pair<String, ImageDescriptor>(name, null));\r
360                                         \r
361                                     }\r
362                                 }\r
363                                 \r
364                             }\r
365                             \r
366                             return map;\r
367                             \r
368                         }\r
369     \r
370                     });\r
371                     \r
372                     Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();\r
373                     LiftPropertiesDialog dialog = new LiftPropertiesDialog(shell, map, "Select properties to lift") {\r
374                         @Override\r
375                         protected IDialogSettings getBaseDialogSettings() {\r
376                             return Activator.getDefault().getDialogSettings();\r
377                         }\r
378                     };\r
379                     if (dialog.open() == Window.OK) {\r
380                         final Collection<LiftedProperty> _result = dialog.getResultT();\r
381                         final boolean mapProperties = dialog.getMapProperties();\r
382                         if (!_result.isEmpty()) {\r
383                             Simantics.getSession().async(new WriteRequest() {\r
384                                 public Resource findAssertion(ReadGraph graph, Resource sourceType, Resource predicate) throws DatabaseException {\r
385                                     Collection<Resource> ass = graph.getAssertedObjects(sourceType, predicate);\r
386                                     if(ass.size() == 1) return ass.iterator().next();\r
387                                     return null;\r
388                                 }\r
389                                 \r
390                                 public void processSubs(ReadGraph graph, Resource predicate, Resource component, Resource componentType, List<LiftedProperty> result, List<Resource> properties, List<Resource> assertions) throws DatabaseException {\r
391                                     SelectionViewResources SEL = SelectionViewResources.getInstance(graph);\r
392                                     for(Resource sub : graph.getObjects(predicate, SEL.UnderOf)) {\r
393                                         Resource ass = findAssertion(graph, componentType, sub);\r
394                                         if(ass == null) continue;\r
395                                         result.add(new LiftedProperty(component, componentType, sub));\r
396                                         properties.add(sub);\r
397                                         assertions.add(ass);\r
398                                         processSubs(graph, sub, component, componentType, result, properties, assertions);\r
399                                     }\r
400                                 }\r
401                                 \r
402                                 @Override\r
403                                 public void perform(WriteGraph graph) throws DatabaseException {\r
404                                     \r
405                                     Layer0 L0 = Layer0.getInstance(graph);\r
406                                     graph.markUndoPoint();\r
407                                     List<Resource> properties = new ArrayList<>();\r
408                                     List<Resource> assertions = new ArrayList<>();\r
409                                     \r
410                                     List<LiftedProperty> result = new ArrayList<>(); \r
411                                     for(LiftedProperty p : _result) {\r
412                                         Resource ass = findAssertion(graph, p.getComponentType(), p.getPredicate());\r
413                                         if(ass == null) continue;\r
414                                         result.add(p);\r
415                                         properties.add(p.getPredicate());\r
416                                         assertions.add(ass);\r
417                                         processSubs(graph, p.getPredicate(), p.getComponent(), p.getComponentType(), result, properties, assertions);\r
418                                     }\r
419                                     \r
420                                     CopyHandler2 ch = Layer0Utils.getPossibleCopyHandler(graph, properties);\r
421                                     Collection<Resource> copies = Layer0Utils.copyTo(graph, data.componentType, null, ch, null);\r
422                                     int index = 0;\r
423                                     for(Resource copy : copies) {\r
424                                         Resource ass = assertions.get(index);\r
425                                         LiftedProperty p = result.get(index);\r
426                                         Collection<Resource> copyAss = Layer0Utils.copyTo(graph, null, ass);\r
427                                         if(copyAss.size() == 1) {\r
428                                             graph.claim(data.componentType, L0.DomainOf, copy);\r
429                                             Layer0Utils.assert_(graph, data.componentType, copy, copyAss.iterator().next());\r
430                                             CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
431                                             graph.addMetadata(cm.add("Lifted property " + NameUtils.getSafeName(graph, copy) + " into "+ NameUtils.getSafeName(graph, data.componentType)));\r
432                                         }\r
433                                         if(mapProperties) {\r
434                                             Variable v = Variables.getVariable(graph, p.getComponent());\r
435                                             Variable property = v.getProperty(graph, p.getPredicate());\r
436                                             Variable displayValue = property.getProperty(graph, Variables.DISPLAY_VALUE);\r
437                                             displayValue.setValue(graph, "=" + NameUtils.getSafeName(graph, p.getPredicate()), Bindings.STRING);\r
438                                         }\r
439                                         index++;\r
440                                     }\r
441                                     \r
442                                 }\r
443                             });\r
444                         }\r
445                     }\r
446 \r
447                 } catch (DatabaseException e1) {\r
448                     \r
449                     LOGGER.error("Lifting properties failed", e1);\r
450                     return;\r
451                     \r
452                 }\r
453                 \r
454             }\r
455         });\r
456 \r
457         if(hasTypes) {\r
458             \r
459             setTypes.addSelectionListener(new SelectionAdapter() {\r
460                 @Override\r
461                 public void widgetSelected(SelectionEvent e) {\r
462                     if(editor.getEditor() != null)\r
463                         editor.getEditor().dispose();\r
464                     final List<Resource> propertiesToSet = \r
465                             new ArrayList<>();\r
466                     for(TableItem item : table.getSelection())\r
467                         propertiesToSet.add(((ComponentTypeViewerPropertyInfo)item.getData()).resource);\r
468                     \r
469                     if(propertiesToSet.size() != 1) return;\r
470 \r
471                     Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();\r
472                     SetTypesDialog page = new SetTypesDialog(shell, getTypes(), "Select user types for property");\r
473                     if (page.open() == Window.OK) {\r
474                         final Object[] result = page.getResult();\r
475                         if (result != null && result.length > 0) {\r
476                             Simantics.getSession().async(new WriteRequest() {\r
477                                 @Override\r
478                                 public void perform(WriteGraph graph)\r
479                                         throws DatabaseException {\r
480                                     for(Object type : result) {\r
481                                         Layer0 L0 = Layer0.getInstance(graph);\r
482                                         graph.claim(propertiesToSet.get(0), L0.InstanceOf, null, (Resource)type);\r
483                                     }\r
484                                 }\r
485                             });\r
486                         }\r
487                     }\r
488                     \r
489                 }\r
490             });\r
491             \r
492         }\r
493 \r
494         table.addDisposeListener(new DisposeListener() {\r
495             @Override\r
496             public void widgetDisposed(DisposeEvent e) {\r
497                 tk.dispose();\r
498             }\r
499         });\r
500     }\r
501 \r
502     public void update(ComponentTypePropertiesResult result) {\r
503         if (table.isDisposed())\r
504             return;\r
505         \r
506         // Save old selection\r
507         Set<ComponentTypeViewerPropertyInfo> selected = new HashSet<>();\r
508         List<TableItem> selectedItems = new ArrayList<>(selected.size());\r
509         for (int i : table.getSelectionIndices()) {\r
510             TableItem item = table.getItem(i);\r
511             selected.add((ComponentTypeViewerPropertyInfo) item.getData());\r
512         }\r
513 \r
514         int topIndex = table.getTopIndex();\r
515 \r
516         table.removeAll();\r
517 \r
518         if(editor.getEditor() != null)\r
519             editor.getEditor().dispose();\r
520 \r
521         for(ComponentTypeViewerPropertyInfo info : result.getProperties()) {\r
522             boolean immutable = result.isImmutable() || info.immutable;\r
523             Color fg = immutable ? table.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY) : null;\r
524             if(info.sectionSpecificData != null)\r
525                 continue;\r
526 \r
527             TableItem item = new TableItem(table, SWT.NONE);\r
528 \r
529             item.setText(0, info.name);\r
530             item.setText(1, info.type);\r
531             item.setText(2, info.defaultValue);\r
532             item.setText(3, unitStr(info));\r
533             item.setText(4, rangeStr(info));\r
534             item.setText(5, info.label);\r
535             item.setText(6, info.description);\r
536 \r
537             for (int columnIndex : IMMUTABLE_COLUMNS_WITH_IMMUTABLE_RELATION)\r
538                 item.setForeground(columnIndex, fg);\r
539 \r
540             item.setData(info);\r
541 \r
542             if (selected.contains(info))\r
543                 selectedItems.add(item);\r
544         }\r
545 \r
546         // Restore old selection\r
547         table.setTopIndex(topIndex);\r
548         table.setSelection(selectedItems.toArray(new TableItem[selectedItems.size()]));\r
549         table.redraw();\r
550     }\r
551     \r
552     private Map<Resource, Pair<String, ImageDescriptor>> getTypes() {\r
553         try {\r
554             return Simantics.getSession().syncRequest(new UniqueRead<Map<Resource, Pair<String, ImageDescriptor>>>() {\r
555                 @Override\r
556                 public Map<Resource, Pair<String, ImageDescriptor>> perform(ReadGraph graph)\r
557                         throws DatabaseException {\r
558                     StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
559                     Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(data.componentType));\r
560                     Instances query = graph.adapt(STR.UserDefinedProperty, Instances.class);\r
561                     Collection<Resource> types = query.find(graph, indexRoot);\r
562                     Map<Resource, Pair<String, ImageDescriptor>> result = new HashMap<>();\r
563                     for(Resource type : types) {\r
564                         String name = NameUtils.getSafeLabel(graph, type);\r
565                         result.put(type, new Pair<String, ImageDescriptor>(name, null));\r
566                     }\r
567                     return result;\r
568                 }\r
569             });\r
570         } catch (DatabaseException e) {\r
571             LOGGER.error("Finding UserDefinedProperties failed.", e);\r
572             return Collections.emptyMap();\r
573         }\r
574     }\r
575 \r
576     private String unitStr(ComponentTypeViewerPropertyInfo info) {\r
577         String unit = info.numberType == null ? null : info.numberType.getUnit();\r
578         if (unit == null)\r
579             unit = info.unit;\r
580         return unit != null ? unit : "";\r
581     }\r
582 \r
583     private String rangeStr(ComponentTypeViewerPropertyInfo info) {\r
584         String range = info.numberType == null ? null : info.numberType.getRangeStr();\r
585         return range != null ? range : "";\r
586     }\r
587     \r
588     @Override\r
589     public void setReadOnly(boolean readOnly) {\r
590         boolean e = !readOnly;\r
591         newProperty.setEnabled(e);\r
592         removeProperty.setEnabled(e);\r
593         liftProperties.setEnabled(e);\r
594     }\r
595     \r
596     @Override\r
597     public Section getSection() {\r
598         return section;\r
599     }\r
600 \r
601     @Override\r
602     public double getPriority() {\r
603         return 0;\r
604     }\r
605 \r
606     @Override\r
607     public Object getSectionSpecificData(ReadGraph graph,\r
608             ComponentTypeViewerPropertyInfo info) throws DatabaseException {\r
609         return null;\r
610     }\r
611 \r
612     @Override\r
613     public double getDataPriority() {\r
614         return 0.0;\r
615     }\r
616 }\r