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