]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / componentTypeEditor / ComponentTypeViewerData.java
diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java
new file mode 100644 (file)
index 0000000..6a3e7f1
--- /dev/null
@@ -0,0 +1,564 @@
+package org.simantics.modeling.ui.componentTypeEditor;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.jface.dialogs.IMessageProvider;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.custom.TableEditor;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Combo;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.forms.widgets.Form;\r
+import org.eclipse.ui.forms.widgets.FormToolkit;\r
+import org.simantics.Simantics;\r
+import org.simantics.databoard.type.NumberType;\r
+import org.simantics.databoard.units.internal.library.UnitLibrary;\r
+import org.simantics.databoard.util.Limit;\r
+import org.simantics.databoard.util.Range;\r
+import org.simantics.databoard.util.RangeException;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.userComponent.ComponentTypeCommands;\r
+import org.simantics.scl.runtime.function.Function4;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+\r
+public class ComponentTypeViewerData {\r
+    /**\r
+     * Used to validate property names.\r
+     */\r
+    public static final Pattern PROPERTY_NAME_PATTERN =\r
+            Pattern.compile("([a-z]|_[0-9a-zA-Z_])[0-9a-zA-Z_]*");\r
+\r
+    public static final String[] PROPERTY_TYPE_SUGGESTIONS = new String[] {\r
+        "Double",\r
+        "Integer",\r
+        "Float",\r
+        "String",\r
+        "Boolean",\r
+        "Long",\r
+        "[Double]",\r
+        "[Integer]",\r
+        "[Float]",\r
+        "[String]",\r
+        "[Boolean]",\r
+        "[Long]",\r
+        "Vector Double",\r
+        "Vector Integer",\r
+        "Vector Float",\r
+        "Vector String",\r
+        "Vector Boolean",\r
+        "Vector Long"        \r
+    };\r
+    \r
+    public Resource componentType;\r
+    public FormToolkit tk;\r
+    public Form form;\r
+    public UnitLibrary unitLibrary = UnitLibrary.createDefault();\r
+    public boolean readOnly;\r
+    public NamedResource[] connectionPoints;\r
+    public ComponentTypeViewerPropertyInfo[] properties;\r
+\r
+    public ComponentTypeViewerData(FormToolkit tk, Resource componentType, Form form) {\r
+        this.tk = tk;\r
+        this.componentType = componentType;\r
+        this.form = form;\r
+    }\r
+    \r
+    public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,\r
+            Pattern namePattern) {\r
+        int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;\r
+        final Text text = new Text(table, SWT.NONE | extraStyle);\r
+        org.eclipse.swt.widgets.Listener listener = \r
+                new org.eclipse.swt.widgets.Listener() {\r
+            @Override\r
+            public void handleEvent(Event e) {\r
+                if (e.type == SWT.Dispose) {\r
+                    form.setMessage(null);\r
+                    return;\r
+                }\r
+\r
+                if (e.type == SWT.Modify) {\r
+                    // validate current name\r
+                    String error = validatePropertyName(propertyInfo, text.getText(), namePattern);\r
+                    if (error != null) {\r
+                        text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));\r
+                        form.setMessage(error, IMessageProvider.ERROR);\r
+                    } else {\r
+                        text.setBackground(null);\r
+                        form.setMessage(null);\r
+                    }\r
+                    return;\r
+                }\r
+\r
+                if (e.type == SWT.Traverse) {\r
+                    if (e.detail == SWT.TRAVERSE_ESCAPE) {\r
+                        text.dispose();\r
+                        e.doit = false;\r
+                        return;\r
+                    }\r
+                    if (e.detail == SWT.TRAVERSE_ARROW_NEXT || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS || e.detail == SWT.TRAVERSE_MNEMONIC)\r
+                        return;\r
+                    e.doit = false;\r
+                }\r
+                final String newValue = text.getText();\r
+                text.dispose();\r
+\r
+                String error = validatePropertyName(propertyInfo, newValue, namePattern);\r
+                if (error != null)\r
+                    return;\r
+\r
+                if (propertyInfo.immutable)\r
+                    return;\r
+\r
+                Simantics.getSession().async(new WriteRequest() {\r
+                    @Override\r
+                    public void perform(WriteGraph graph)\r
+                            throws DatabaseException {\r
+                        graph.markUndoPoint();\r
+                        Layer0 L0 = Layer0.getInstance(graph);\r
+                        String prevName = graph.getPossibleRelatedValue2(propertyInfo.resource, L0.HasName);\r
+                        String oldCamelCasedLabel = prevName != null ? ComponentTypeCommands.camelCaseNameToLabel(prevName) : "";\r
+                        String oldLabel = graph.getPossibleRelatedValue(propertyInfo.resource, L0.HasLabel);\r
+                        boolean setLabel = oldLabel == null\r
+                                || oldLabel.isEmpty()\r
+                                || oldCamelCasedLabel.isEmpty()\r
+                                || oldCamelCasedLabel.equals(oldLabel);\r
+\r
+                        ComponentTypeCommands.rename(graph, propertyInfo.resource, newValue);\r
+                        if (setLabel)\r
+                            ComponentTypeCommands.setLabel(graph, propertyInfo.resource, ComponentTypeCommands.camelCaseNameToLabel(newValue));\r
+                    }\r
+                });\r
+            }\r
+        };\r
+        text.addListener(SWT.Modify, listener);\r
+        text.addListener(SWT.Deactivate, listener);\r
+        text.addListener(SWT.Traverse, listener);\r
+        text.addListener(SWT.Dispose, listener);\r
+\r
+        text.setText(selectedItem.getText(column));\r
+        text.selectAll();\r
+        text.setFocus();\r
+\r
+        editor.setEditor(text, selectedItem, column);\r
+    }\r
+\r
+    public void editType(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column, final boolean convertDefaultValue) {\r
+        int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;\r
+        final Combo combo = new Combo(table, SWT.NONE | extraStyle);\r
+        combo.setText(selectedItem.getText(column));\r
+        for(String suggestion : PROPERTY_TYPE_SUGGESTIONS)\r
+            combo.add(suggestion);\r
+        org.eclipse.swt.widgets.Listener listener = \r
+                new org.eclipse.swt.widgets.Listener() {\r
+            @Override\r
+            public void handleEvent(Event e) {\r
+                if(e.type == SWT.Traverse) {\r
+                    if (e.detail == SWT.TRAVERSE_ESCAPE) {\r
+                        combo.dispose();\r
+                        e.doit = false;\r
+                        return;\r
+                    }\r
+                    if (e.detail == SWT.TRAVERSE_ARROW_NEXT\r
+                            || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS\r
+                            || e.detail == SWT.TRAVERSE_MNEMONIC)\r
+                        return;\r
+                }\r
+                final String newValue = combo.getText();\r
+                if (e.type == SWT.Traverse) {\r
+                    e.doit = false;\r
+                }\r
+                combo.dispose();\r
+\r
+                if (propertyInfo.immutable)\r
+                    return;\r
+\r
+                Simantics.getSession().async(new WriteRequest() {\r
+                    @Override\r
+                    public void perform(WriteGraph graph)\r
+                            throws DatabaseException {\r
+                        graph.markUndoPoint();\r
+                        ComponentTypeCommands.editType(graph, componentType, propertyInfo.resource, convertDefaultValue, newValue);\r
+                    }\r
+                });\r
+            }\r
+        };\r
+        combo.setFocus();\r
+        editor.setEditor(combo, selectedItem, column);\r
+        combo.addListener(SWT.FocusOut, listener);\r
+        combo.addListener(SWT.Traverse, listener);\r
+    }\r
+\r
+    protected void editUnit(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column) {\r
+        // Disallow unit editing for non-numeric configuration properties\r
+        if (propertyInfo.numberType == null && propertyInfo.sectionSpecificData == null)\r
+            return;\r
+\r
+        int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;\r
+        final Combo combo = new Combo(table, SWT.NONE | extraStyle);\r
+        String initialValue = selectedItem.getText(column);\r
+        List<String> units = new ArrayList<>( unitLibrary.getUnits() );\r
+        Collections.sort(units, String.CASE_INSENSITIVE_ORDER);\r
+        int i = -1;\r
+        int selected = -1;\r
+        for (String unit : units) {\r
+            combo.add(unit);\r
+            if (unit.equals(initialValue))\r
+                combo.select(i);\r
+        }\r
+        if (selected == -1)\r
+            combo.setText(initialValue);\r
+\r
+        org.eclipse.swt.widgets.Listener listener = \r
+                new org.eclipse.swt.widgets.Listener() {\r
+            @Override\r
+            public void handleEvent(Event e) {\r
+                if(e.type == SWT.Traverse) {\r
+                    if (e.detail == SWT.TRAVERSE_ESCAPE) {\r
+                        combo.dispose();\r
+                        e.doit = false;\r
+                        return;\r
+                    }\r
+                    if (e.detail == SWT.TRAVERSE_ARROW_NEXT\r
+                            || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS\r
+                            || e.detail == SWT.TRAVERSE_MNEMONIC)\r
+                        return;\r
+                }\r
+                final String newValue = combo.getText();\r
+                if(e.type == SWT.Traverse) {\r
+                    e.doit = false;\r
+                }\r
+                combo.dispose();\r
+\r
+                if (propertyInfo.immutable)\r
+                    return;\r
+\r
+                Simantics.getSession().async(new WriteRequest() {\r
+                    @Override\r
+                    public void perform(WriteGraph graph)\r
+                            throws DatabaseException {\r
+                        graph.markUndoPoint();\r
+                        ComponentTypeCommands.setUnit(graph, componentType, propertyInfo.resource, newValue);\r
+                    }\r
+                });\r
+            }\r
+        };\r
+        combo.setFocus();\r
+        editor.setEditor(combo, selectedItem, column);\r
+        combo.addListener(SWT.Deactivate, listener);\r
+        combo.addListener(SWT.Traverse, listener);\r
+    }\r
+\r
+    public void editValue(Table table, TableEditor editor,\r
+            final ComponentTypeViewerPropertyInfo propertyInfo,\r
+            TableItem selectedItem, int column,\r
+            final StringWriter writer,\r
+            final Function4<RequestProcessor, Resource, Resource, String, String> validator)\r
+    {\r
+        int extraStyle = writer == null ? SWT.READ_ONLY : 0;\r
+        final Text text = new Text(table, SWT.NONE | extraStyle);\r
+        text.setText(selectedItem.getText(column));\r
+        org.eclipse.swt.widgets.Listener listener = \r
+                new org.eclipse.swt.widgets.Listener() {\r
+            @Override\r
+            public void handleEvent(Event e) {\r
+                if(e.type == SWT.Traverse) {\r
+                    if (e.detail == SWT.TRAVERSE_ESCAPE) {\r
+                        text.dispose();\r
+                        e.doit = false;\r
+                        return;\r
+                    }\r
+                    if (e.detail == SWT.TRAVERSE_ARROW_NEXT\r
+                            || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS\r
+                            || e.detail == SWT.TRAVERSE_MNEMONIC)\r
+                        return;\r
+                }\r
+                final String newValue = text.getText();\r
+                if(e.type == SWT.Traverse) {\r
+                    e.doit = false;\r
+                }\r
+                text.dispose();\r
+\r
+                if (writer != null) {\r
+                    Simantics.getSession().async(new WriteRequest() {\r
+                        @Override\r
+                        public void perform(WriteGraph graph) throws DatabaseException {\r
+                            writer.perform(graph, newValue);\r
+                        }\r
+                    });\r
+                }\r
+            }\r
+        };\r
+        text.selectAll();\r
+        text.setFocus();\r
+        editor.setEditor(text, selectedItem, column);\r
+        text.addListener(SWT.FocusOut, listener);\r
+        text.addListener(SWT.Traverse, listener);\r
+\r
+        if (validator != null) {\r
+            org.eclipse.swt.widgets.Listener validationListener = new org.eclipse.swt.widgets.Listener() {\r
+                @Override\r
+                public void handleEvent(Event e) {\r
+                    final String newValue = text.getText();\r
+                    String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue);\r
+                    if (error != null) {\r
+                        text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));\r
+                        text.setToolTipText(error);\r
+                        return;\r
+                    } else {\r
+                        text.setBackground(null);\r
+                        text.setToolTipText(null);\r
+                    }\r
+                }\r
+            };\r
+            text.addListener(SWT.Modify, validationListener);\r
+        }\r
+    }\r
+\r
+    private Range parseRange(NumberType numberType, String minStr, String maxStr, boolean lowInclusive, boolean highInclusive) throws RangeException {\r
+        try {\r
+            String rangeStr = (lowInclusive ? "[" : "(")  + minStr + ".." + maxStr + (highInclusive ? "]" : ")");\r
+            return Range.valueOf(rangeStr);\r
+        } catch (IllegalArgumentException e) {\r
+            // Limits are invalid\r
+            throw new RangeException(e.getMessage(), e);\r
+        }\r
+    }\r
+    \r
+    private static Combo createRangeInclusionCombo(Composite parent, boolean inclusive) {\r
+        Combo rng = new Combo(parent, SWT.READ_ONLY);\r
+        rng.add("Inclusive");\r
+        rng.add("Exclusive");\r
+        rng.select(inclusive ? 0 : 1);\r
+        return rng;\r
+    }\r
+    \r
+    protected void editRange(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, Rectangle selectedItemBounds, int column) {\r
+        // Disallow range editing when the property is not numeric\r
+        if (propertyInfo.numberType == null)\r
+            return;\r
+\r
+        int extraTextStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;\r
+\r
+        // Parse initial range value\r
+        Range range = null;\r
+        String rangeStr = selectedItem.getText(column);\r
+        try {\r
+            range = Range.valueOf(rangeStr);\r
+        } catch (RangeException ex) {\r
+            range = new Range(Limit.nolimit(), Limit.nolimit());\r
+        }\r
+\r
+        final Shell shell = new Shell(table.getShell(), SWT.ON_TOP);\r
+        GridLayoutFactory.fillDefaults().applyTo(shell);\r
+\r
+        Composite composite = new Composite(shell, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.swtDefaults().numColumns(3).applyTo(composite);\r
+\r
+        Label low = new Label(composite, SWT.NONE);\r
+        low.setText("Minimum Value:");\r
+        final Text lowText = new Text(composite, SWT.BORDER | extraTextStyle);\r
+        GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(lowText);\r
+        final Combo lowSelector = createRangeInclusionCombo(composite, !range.getLower().isExclusive());\r
+        Label high = new Label(composite, SWT.NONE);\r
+        high.setText("Maximum Value:");\r
+        final Text highText = new Text(composite, SWT.BORDER | extraTextStyle);\r
+        GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(highText);\r
+        final Combo highSelector = createRangeInclusionCombo(composite, !range.getUpper().isExclusive());\r
+\r
+        Composite buttonComposite = new Composite(shell, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, false).align(SWT.TRAIL, SWT.FILL).applyTo(buttonComposite);\r
+        GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(true).applyTo(buttonComposite);\r
+\r
+        Button ok = new Button(buttonComposite, SWT.NONE);\r
+        ok.setText("&OK");\r
+        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(ok);\r
+        Button cancel = new Button(buttonComposite, SWT.NONE);\r
+        cancel.setText("&Cancel");\r
+        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(ok);\r
+\r
+        if (range.getLower().getValue() != null)\r
+            lowText.setText(range.getLower().getValue().toString());\r
+        if (range.getUpper().getValue() != null)\r
+            highText.setText(range.getUpper().getValue().toString());\r
+\r
+        shell.addListener(SWT.Deactivate, new org.eclipse.swt.widgets.Listener() {\r
+            @Override\r
+            public void handleEvent(Event event) {\r
+                shell.dispose();\r
+            }\r
+        });\r
+\r
+        ok.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                try {\r
+                    final Range newRange = parseRange(propertyInfo.numberType,\r
+                            lowText.getText().trim(),\r
+                            highText.getText().trim(),\r
+                            lowSelector.getSelectionIndex() == 0 ? true : false,\r
+                            highSelector.getSelectionIndex() == 0 ? true : false);\r
+\r
+                    shell.dispose();\r
+\r
+                    if (propertyInfo.immutable)\r
+                        return;\r
+\r
+                    Simantics.getSession().async(new WriteRequest() {\r
+                        @Override\r
+                        public void perform(WriteGraph graph)\r
+                                throws DatabaseException {\r
+                            graph.markUndoPoint();\r
+                            ComponentTypeCommands.setRange(graph, componentType, propertyInfo.resource, newRange == null ? null : newRange.toString());\r
+                        }\r
+                    });\r
+                } catch (RangeException ex) {\r
+                    ErrorLogger.defaultLogError(ex);\r
+                }\r
+            }\r
+        });\r
+        cancel.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                shell.dispose();\r
+            }\r
+        });\r
+\r
+        shell.pack();\r
+        Point size = shell.getSize();\r
+\r
+        Display display = table.getDisplay();\r
+        Rectangle clientArea = display.getClientArea();\r
+        Point bt = table.toDisplay(selectedItemBounds.x, selectedItemBounds.y);\r
+        Rectangle b = selectedItemBounds;\r
+        b.x = bt.x;\r
+        b.y = bt.y;\r
+        b.width = size.x;\r
+        b.height = size.y;\r
+        if ((b.x + b.width) > clientArea.width)\r
+            b.x -= b.x + b.width - clientArea.width;\r
+        if (b.height > clientArea.height)\r
+            b.height = clientArea.height;\r
+        if ((b.y + b.height) > clientArea.height)\r
+            b.y -= b.y + b.height - clientArea.height;\r
+\r
+        shell.setBounds(selectedItemBounds);\r
+        shell.open();\r
+    }\r
+\r
+    protected void editMultilineText(Table table, TableEditor editor,\r
+            final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem,\r
+            Rectangle selectedItemBounds, int column, final StringWriter writer)\r
+    {\r
+        final Shell shell = new Shell(table.getShell(), SWT.ON_TOP);\r
+        GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(shell);\r
+        final StyledText text = new StyledText(shell, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | (propertyInfo.immutable ? SWT.READ_ONLY : 0));\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(text);\r
+        text.setText(selectedItem.getText(column));\r
+        org.eclipse.swt.widgets.Listener listener = \r
+                new org.eclipse.swt.widgets.Listener() {\r
+            @Override\r
+            public void handleEvent(Event e) {\r
+                final String newValue = text.getText();\r
+\r
+                if (e.type == SWT.Traverse) {\r
+                    if (e.detail == SWT.TRAVERSE_ESCAPE) {\r
+                        shell.dispose();\r
+                        e.doit = false;\r
+                        return;\r
+                    }\r
+                    if (e.detail == SWT.TRAVERSE_ARROW_NEXT\r
+                            || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS\r
+                            || e.detail == SWT.TRAVERSE_MNEMONIC)\r
+                        return;\r
+                    if ((e.stateMask & SWT.CTRL) == 0)\r
+                        return;\r
+                    e.doit = false;\r
+                }\r
+\r
+                shell.dispose();\r
+\r
+                if (propertyInfo.immutable)\r
+                    return;\r
+\r
+                if (writer != null) {\r
+                    Simantics.getSession().async(new WriteRequest() {\r
+                        @Override\r
+                        public void perform(WriteGraph graph) throws DatabaseException {\r
+                            writer.perform(graph, newValue);\r
+                        }\r
+                    });\r
+                }\r
+            }\r
+        };\r
+\r
+        String helpText = propertyInfo.immutable ? "ESC to close." : "Ctrl+Enter to apply changes, ESC to cancel.";\r
+        Label help = tk.createLabel(shell, helpText, SWT.BORDER | SWT.FLAT);\r
+        GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(help);\r
+        help.setForeground( tk.getColors().createColor( "fg", tk.getColors().getSystemColor(SWT.COLOR_LIST_SELECTION) ) );\r
+\r
+        Display display = table.getDisplay();\r
+        Rectangle clientArea = display.getClientArea();\r
+        Point bt = table.toDisplay(selectedItemBounds.x, selectedItemBounds.y);\r
+        Rectangle b = selectedItemBounds;\r
+        b.x = bt.x;\r
+        b.y = bt.y;\r
+        b.height = 200;\r
+        if ((b.x + b.width) > clientArea.width)\r
+            b.x -= b.x + b.width - clientArea.width;\r
+        if (b.height > clientArea.height)\r
+            b.height = clientArea.height;\r
+        if ((b.y + b.height) > clientArea.height)\r
+            b.y -= b.y + b.height - clientArea.height;\r
+\r
+        shell.setBounds(selectedItemBounds);\r
+        shell.open();\r
+\r
+        text.selectAll();\r
+        text.setFocus();\r
+\r
+        text.addListener(SWT.Traverse, listener);\r
+        shell.addListener(SWT.Deactivate, listener);\r
+    }\r
+\r
+    private String validatePropertyName(ComponentTypeViewerPropertyInfo propertyInfo, String propertyName, Pattern namePattern) {\r
+        if (propertyName.equals(propertyInfo.name))\r
+            return null;\r
+        for (ComponentTypeViewerPropertyInfo info : properties) {\r
+            if (propertyName.equals(info.name))\r
+                return "Property name '" + propertyName + "' is already in use.";\r
+        }\r
+        for (NamedResource cp : connectionPoints) {\r
+            if (propertyName.equals(cp.getName()))\r
+                return "Name '" + propertyName + "' is already used for a terminal.";\r
+        }\r
+        Matcher m = namePattern.matcher(propertyName);\r
+        if (!m.matches())\r
+            return "Property name '" + propertyName + "' contains invalid characters, does not match pattern "\r
+                    + namePattern.pattern() + ".";\r
+        return null;\r
+    }\r
+\r
+}\r