1 package org.simantics.modeling.ui.componentTypeEditor;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
9 import java.util.concurrent.ScheduledFuture;
10 import java.util.concurrent.TimeUnit;
11 import java.util.regex.Matcher;
12 import java.util.regex.Pattern;
14 import org.eclipse.jface.dialogs.IDialogConstants;
15 import org.eclipse.jface.dialogs.IMessageProvider;
16 import org.eclipse.jface.layout.GridDataFactory;
17 import org.eclipse.jface.layout.GridLayoutFactory;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.custom.StyledText;
21 import org.eclipse.swt.custom.TableEditor;
22 import org.eclipse.swt.events.SelectionAdapter;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.graphics.Point;
25 import org.eclipse.swt.graphics.Rectangle;
26 import org.eclipse.swt.widgets.Button;
27 import org.eclipse.swt.widgets.Combo;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.Display;
30 import org.eclipse.swt.widgets.Event;
31 import org.eclipse.swt.widgets.Label;
32 import org.eclipse.swt.widgets.Shell;
33 import org.eclipse.swt.widgets.Table;
34 import org.eclipse.swt.widgets.TableItem;
35 import org.eclipse.swt.widgets.Text;
36 import org.eclipse.ui.forms.widgets.Form;
37 import org.eclipse.ui.forms.widgets.FormToolkit;
38 import org.simantics.Simantics;
39 import org.simantics.databoard.Bindings;
40 import org.simantics.databoard.type.NumberType;
41 import org.simantics.databoard.units.internal.library.UnitLibrary;
42 import org.simantics.databoard.util.Limit;
43 import org.simantics.databoard.util.Range;
44 import org.simantics.databoard.util.RangeException;
45 import org.simantics.db.ReadGraph;
46 import org.simantics.db.RequestProcessor;
47 import org.simantics.db.Resource;
48 import org.simantics.db.Statement;
49 import org.simantics.db.WriteGraph;
50 import org.simantics.db.common.NamedResource;
51 import org.simantics.db.common.request.IndexRoot;
52 import org.simantics.db.common.request.ResourceRead;
53 import org.simantics.db.common.request.WriteRequest;
54 import org.simantics.db.exception.DatabaseException;
55 import org.simantics.db.function.DbConsumer;
56 import org.simantics.db.layer0.QueryIndexUtils;
57 import org.simantics.layer0.Layer0;
58 import org.simantics.modeling.userComponent.ComponentTypeCommands;
59 import org.simantics.scl.runtime.function.Function2;
60 import org.simantics.scl.runtime.function.Function4;
61 import org.simantics.utils.threads.ThreadUtils;
62 import org.simantics.utils.ui.ErrorLogger;
64 public class ComponentTypeViewerData {
66 * Used to validate property names.
68 public static final Pattern PROPERTY_NAME_PATTERN =
69 Pattern.compile("([a-z]|_[0-9a-zA-Z_])[0-9a-zA-Z_]*"); //$NON-NLS-1$
71 public static final String[] PROPERTY_TYPE_SUGGESTIONS = new String[] {
72 "Double", //$NON-NLS-1$
73 "Integer", //$NON-NLS-1$
74 "Float", //$NON-NLS-1$
75 "String", //$NON-NLS-1$
76 "Boolean", //$NON-NLS-1$
78 "[Double]", //$NON-NLS-1$
79 "[Integer]", //$NON-NLS-1$
80 "[Float]", //$NON-NLS-1$
81 "[String]", //$NON-NLS-1$
82 "[Boolean]", //$NON-NLS-1$
83 "[Long]", //$NON-NLS-1$
84 "Vector Double", //$NON-NLS-1$
85 "Vector Integer", //$NON-NLS-1$
86 "Vector Float", //$NON-NLS-1$
87 "Vector String", //$NON-NLS-1$
88 "Vector Boolean", //$NON-NLS-1$
89 "Vector Long" //$NON-NLS-1$
92 public Resource componentType;
93 public FormToolkit tk;
95 public UnitLibrary unitLibrary = UnitLibrary.createDefault();
96 public boolean readOnly;
97 public NamedResource[] connectionPoints;
98 public ComponentTypeViewerPropertyInfo[] properties;
100 public ComponentTypeViewerData(FormToolkit tk, Resource componentType, Form form) {
102 this.componentType = componentType;
106 public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
107 Pattern namePattern) {
108 editName(table, editor, propertyInfo, selectedItem, column, namePattern, null);
111 public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
112 Pattern namePattern, DbConsumer<WriteGraph> extraWriter) {
113 editName(table, editor, propertyInfo, selectedItem, column,
115 (pInfo, name) -> validatePropertyName(pInfo, name, namePattern),
119 public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
120 Function2<ComponentTypeViewerPropertyInfo, String, String> nameFilter, Pattern namePattern, DbConsumer<WriteGraph> extraWriter) {
121 editName(table, editor, propertyInfo, selectedItem, column, nameFilter,
122 (pInfo, name) -> validatePropertyName(pInfo, name, namePattern),
126 public void editName(Table table, TableEditor editor, ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
127 Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator)
129 editName(table, editor, propertyInfo, selectedItem, column, nameValidator, null);
132 public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
133 Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator, DbConsumer<WriteGraph> extraWriter) {
134 editName(table, editor, propertyInfo, selectedItem, column, null, nameValidator, extraWriter);
137 public void editName(
140 final ComponentTypeViewerPropertyInfo propertyInfo,
141 TableItem selectedItem,
143 Function2<ComponentTypeViewerPropertyInfo, String, String> nameFilter,
144 Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator,
145 DbConsumer<WriteGraph> extraWriter) {
146 int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;
147 final Text text = new Text(table, SWT.NONE | extraStyle);
148 org.eclipse.swt.widgets.Listener listener =
149 new org.eclipse.swt.widgets.Listener() {
151 public void handleEvent(Event e) {
152 if (e.type == SWT.Dispose) {
153 form.setMessage(null);
155 } else if (e.type == SWT.Verify) {
156 // Filter input if necessary
157 e.text = nameFilter != null ? nameFilter.apply(propertyInfo, e.text) : e.text;
159 } else if (e.type == SWT.Modify) {
160 // validate current name
161 String error = nameValidator.apply(propertyInfo, text.getText());
163 text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
164 form.setMessage(error, IMessageProvider.ERROR);
166 text.setBackground(null);
167 form.setMessage(null);
170 } else if (e.type == SWT.Traverse) {
171 if (e.detail == SWT.TRAVERSE_ESCAPE) {
176 if (e.detail == SWT.TRAVERSE_ARROW_NEXT || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS || e.detail == SWT.TRAVERSE_MNEMONIC)
180 final String newValue = text.getText();
183 String error = nameValidator.apply(propertyInfo, newValue);
187 if (propertyInfo.immutable)
190 Simantics.getSession().async(new WriteRequest() {
192 public void perform(WriteGraph graph)
193 throws DatabaseException {
194 graph.markUndoPoint();
195 Layer0 L0 = Layer0.getInstance(graph);
196 String prevName = graph.getPossibleRelatedValue2(propertyInfo.resource, L0.HasName);
197 String oldCamelCasedLabel = prevName != null ? ComponentTypeCommands.camelCaseNameToLabel(prevName) : ""; //$NON-NLS-1$
198 String oldLabel = graph.getPossibleRelatedValue(propertyInfo.resource, L0.HasLabel);
199 boolean setLabel = oldLabel == null
200 || oldLabel.isEmpty()
201 || oldCamelCasedLabel.isEmpty()
202 || oldCamelCasedLabel.equals(oldLabel);
204 ComponentTypeCommands.rename(graph, propertyInfo.resource, newValue);
206 ComponentTypeCommands.setLabel(graph, propertyInfo.resource, ComponentTypeCommands.camelCaseNameToLabel(newValue));
208 if (extraWriter != null)
209 extraWriter.accept(graph);
214 if (nameFilter != null)
215 text.addListener(SWT.Verify, listener);
216 text.addListener(SWT.Modify, listener);
217 text.addListener(SWT.Deactivate, listener);
218 text.addListener(SWT.Traverse, listener);
219 text.addListener(SWT.Dispose, listener);
221 text.setText(selectedItem.getText(column));
225 editor.setEditor(text, selectedItem, column);
228 private static class TypeDefinitionMapRequest extends ResourceRead<Map<String,Resource>> {
229 public TypeDefinitionMapRequest(Resource resource) {
234 public Map<String,Resource> perform(ReadGraph graph) throws DatabaseException {
235 Layer0 L0 = Layer0.getInstance(graph);
236 Map<String,Resource> result = new HashMap<>();
237 for(Resource valueType : QueryIndexUtils.searchByType(graph, resource, L0.ValueType)) {
238 Collection<Statement> stms = graph.getAssertedStatements(valueType, L0.HasValueType);
239 if(stms.size() == 1) {
240 String sclValueType = graph.getValue(stms.iterator().next().getObject(), Bindings.STRING);
241 result.put(sclValueType, valueType);
248 public void editType(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column, String range, final boolean convertDefaultValue) {
249 int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;
250 final Combo combo = new Combo(table, SWT.NONE | extraStyle);
251 combo.setText(selectedItem.getText(column));
252 for(String suggestion : PROPERTY_TYPE_SUGGESTIONS)
253 combo.add(suggestion);
254 org.eclipse.swt.widgets.Listener listener =
255 new org.eclipse.swt.widgets.Listener() {
257 public void handleEvent(Event e) {
258 if(e.type == SWT.Traverse) {
259 if (e.detail == SWT.TRAVERSE_ESCAPE) {
264 if (e.detail == SWT.TRAVERSE_ARROW_NEXT
265 || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS
266 || e.detail == SWT.TRAVERSE_MNEMONIC)
269 final String newValue = combo.getText();
270 if (e.type == SWT.Traverse) {
275 if (propertyInfo.immutable)
279 Simantics.getSession().async(new WriteRequest() {
281 public void perform(WriteGraph graph)
282 throws DatabaseException {
283 graph.markUndoPoint();
285 Resource root = graph.syncRequest(new IndexRoot(componentType));
286 Map<String,Resource> typeDefinitionMap = graph.syncRequest(new TypeDefinitionMapRequest(root));
287 Resource possibleGraphType = typeDefinitionMap.get(newValue);
289 ComponentTypeCommands.editType(graph, componentType, propertyInfo.resource, convertDefaultValue, newValue, possibleGraphType);
290 if (range != null) ComponentTypeCommands.setRange(graph, componentType, propertyInfo.resource, range);
296 editor.setEditor(combo, selectedItem, column);
297 combo.addListener(SWT.FocusOut, listener);
298 combo.addListener(SWT.Traverse, listener);
301 public void editUnit(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column) {
302 // Disallow unit editing for non-numeric configuration properties
303 if (propertyInfo.numberType == null && propertyInfo.sectionSpecificData == null)
306 int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;
307 final Combo combo = new Combo(table, SWT.NONE | extraStyle);
308 String initialValue = selectedItem.getText(column);
309 List<String> units = new ArrayList<>( unitLibrary.getUnits() );
310 Collections.sort(units, String.CASE_INSENSITIVE_ORDER);
313 for (String unit : units) {
315 if (unit.equals(initialValue))
319 combo.setText(initialValue);
321 org.eclipse.swt.widgets.Listener listener =
322 new org.eclipse.swt.widgets.Listener() {
324 public void handleEvent(Event e) {
325 if(e.type == SWT.Traverse) {
326 if (e.detail == SWT.TRAVERSE_ESCAPE) {
331 if (e.detail == SWT.TRAVERSE_ARROW_NEXT
332 || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS
333 || e.detail == SWT.TRAVERSE_MNEMONIC)
336 final String newValue = combo.getText();
337 if(e.type == SWT.Traverse) {
342 if (propertyInfo.immutable)
345 Simantics.getSession().async(new WriteRequest() {
347 public void perform(WriteGraph graph)
348 throws DatabaseException {
349 graph.markUndoPoint();
350 ComponentTypeCommands.setUnit(graph, componentType, propertyInfo.resource, newValue);
356 editor.setEditor(combo, selectedItem, column);
357 combo.addListener(SWT.Deactivate, listener);
358 combo.addListener(SWT.Traverse, listener);
361 public void editValue(Table table, TableEditor editor,
362 final ComponentTypeViewerPropertyInfo propertyInfo,
363 TableItem selectedItem, int column,
364 final StringWriter writer,
365 final Function4<RequestProcessor, Resource, Resource, String, String> validator)
367 int extraStyle = writer == null ? SWT.READ_ONLY : 0;
368 final Text text = new Text(table, SWT.NONE | extraStyle);
369 text.setText(selectedItem.getText(column));
370 org.eclipse.swt.widgets.Listener listener =
371 new org.eclipse.swt.widgets.Listener() {
373 public void handleEvent(Event e) {
374 if(e.type == SWT.Traverse) {
375 if (e.detail == SWT.TRAVERSE_ESCAPE) {
380 if (e.detail == SWT.TRAVERSE_ARROW_NEXT
381 || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS
382 || e.detail == SWT.TRAVERSE_MNEMONIC)
385 final String newValue = text.getText();
386 if(e.type == SWT.Traverse) {
391 if (validator != null) {
392 String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue);
397 if (writer != null) {
398 Simantics.getSession().async(new WriteRequest() {
400 public void perform(WriteGraph graph) throws DatabaseException {
401 writer.perform(graph, newValue);
409 editor.setEditor(text, selectedItem, column);
410 text.addListener(SWT.FocusOut, listener);
411 text.addListener(SWT.Traverse, listener);
413 if (validator != null) {
414 org.eclipse.swt.widgets.Listener validationListener = new org.eclipse.swt.widgets.Listener() {
416 private ScheduledFuture<?> future;
419 public void handleEvent(Event e) {
420 final String newValue = text.getText();
421 if (future != null && !future.isCancelled())
423 future = ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> {
424 String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue);
425 if (!text.isDisposed()) {
426 text.getDisplay().asyncExec(() -> {
427 if (!text.isDisposed()) {
429 text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
430 text.setToolTipText(error);
433 text.setBackground(null);
434 text.setToolTipText(null);
440 }, 500, TimeUnit.MILLISECONDS);
443 text.addListener(SWT.Modify, validationListener);
447 private Range parseRange(NumberType numberType, String minStr, String maxStr, boolean lowInclusive, boolean highInclusive) throws RangeException {
449 String rangeStr = (lowInclusive ? "[" : "(") + minStr + ".." + maxStr + (highInclusive ? "]" : ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
450 return Range.valueOf(rangeStr);
451 } catch (IllegalArgumentException e) {
452 // Limits are invalid
453 throw new RangeException(e.getMessage(), e);
457 private static Combo createRangeInclusionCombo(Composite parent, boolean inclusive) {
458 Combo rng = new Combo(parent, SWT.READ_ONLY);
459 rng.add(Messages.ComponentTypeViewerData_Inclusive);
460 rng.add(Messages.ComponentTypeViewerData_Exclusive);
461 rng.select(inclusive ? 0 : 1);
465 protected void editRange(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, Rectangle selectedItemBounds, int column) {
466 // Disallow range editing when the property is not numeric
467 if (propertyInfo.numberType == null)
470 int extraTextStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;
472 // Parse initial range value
474 String rangeStr = selectedItem.getText(column);
476 range = Range.valueOf(rangeStr);
477 } catch (RangeException ex) {
478 range = new Range(Limit.nolimit(), Limit.nolimit());
481 final Shell shell = new Shell(table.getShell(), SWT.ON_TOP);
482 GridLayoutFactory.fillDefaults().applyTo(shell);
484 Composite composite = new Composite(shell, SWT.NONE);
485 GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
486 GridLayoutFactory.swtDefaults().numColumns(3).applyTo(composite);
488 Label low = new Label(composite, SWT.NONE);
489 low.setText(Messages.ComponentTypeViewerData_MinimumValue);
490 final Text lowText = new Text(composite, SWT.BORDER | extraTextStyle);
491 GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(lowText);
492 final Combo lowSelector = createRangeInclusionCombo(composite, !range.getLower().isExclusive());
493 Label high = new Label(composite, SWT.NONE);
494 high.setText(Messages.ComponentTypeViewerData_MaximumValue);
495 final Text highText = new Text(composite, SWT.BORDER | extraTextStyle);
496 GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(highText);
497 final Combo highSelector = createRangeInclusionCombo(composite, !range.getUpper().isExclusive());
499 Composite buttonComposite = new Composite(shell, SWT.NONE);
500 GridDataFactory.fillDefaults().grab(true, false).align(SWT.TRAIL, SWT.FILL).applyTo(buttonComposite);
501 GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(true).applyTo(buttonComposite);
503 Button ok = new Button(buttonComposite, SWT.NONE);
504 ok.setText(IDialogConstants.OK_LABEL);
505 GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(ok);
506 Button cancel = new Button(buttonComposite, SWT.NONE);
507 cancel.setText(IDialogConstants.CANCEL_LABEL);
508 GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(ok);
510 if (range.getLower().getValue() != null)
511 lowText.setText(range.getLower().getValue().toString());
512 if (range.getUpper().getValue() != null)
513 highText.setText(range.getUpper().getValue().toString());
515 shell.addListener(SWT.Deactivate, new org.eclipse.swt.widgets.Listener() {
517 public void handleEvent(Event event) {
522 ok.addSelectionListener(new SelectionAdapter() {
523 public void widgetSelected(SelectionEvent e) {
525 final Range newRange = parseRange(propertyInfo.numberType,
526 lowText.getText().trim(),
527 highText.getText().trim(),
528 lowSelector.getSelectionIndex() == 0 ? true : false,
529 highSelector.getSelectionIndex() == 0 ? true : false);
533 if (propertyInfo.immutable)
536 Simantics.getSession().async(new WriteRequest() {
538 public void perform(WriteGraph graph)
539 throws DatabaseException {
540 graph.markUndoPoint();
541 ComponentTypeCommands.setRange(graph, componentType, propertyInfo.resource, newRange == null ? null : newRange.toString());
544 } catch (RangeException ex) {
545 ErrorLogger.defaultLogError(ex);
549 cancel.addSelectionListener(new SelectionAdapter() {
550 public void widgetSelected(SelectionEvent e) {
556 Point size = shell.getSize();
558 Display display = table.getDisplay();
559 Rectangle clientArea = display.getClientArea();
560 Point bt = table.toDisplay(selectedItemBounds.x, selectedItemBounds.y);
561 Rectangle b = selectedItemBounds;
566 if ((b.x + b.width) > clientArea.width)
567 b.x -= b.x + b.width - clientArea.width;
568 if (b.height > clientArea.height)
569 b.height = clientArea.height;
570 if ((b.y + b.height) > clientArea.height)
571 b.y -= b.y + b.height - clientArea.height;
573 shell.setBounds(selectedItemBounds);
577 public void editMultilineText(Table table, TableEditor editor,
578 final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem,
579 Rectangle selectedItemBounds, int column, final StringWriter writer)
581 final Shell shell = new Shell(table.getShell(), SWT.ON_TOP);
582 GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(shell);
583 final StyledText text = new StyledText(shell, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | (propertyInfo.immutable ? SWT.READ_ONLY : 0));
584 GridDataFactory.fillDefaults().grab(true, true).applyTo(text);
585 text.setText(selectedItem.getText(column));
586 org.eclipse.swt.widgets.Listener listener =
587 new org.eclipse.swt.widgets.Listener() {
589 public void handleEvent(Event e) {
590 final String newValue = text.getText();
592 if (e.type == SWT.Traverse) {
593 if (e.detail == SWT.TRAVERSE_ESCAPE) {
598 if (e.detail == SWT.TRAVERSE_ARROW_NEXT
599 || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS
600 || e.detail == SWT.TRAVERSE_MNEMONIC)
602 if ((e.stateMask & SWT.CTRL) == 0)
609 if (propertyInfo.immutable)
612 if (writer != null) {
613 Simantics.getSession().async(new WriteRequest() {
615 public void perform(WriteGraph graph) throws DatabaseException {
616 writer.perform(graph, newValue);
623 String helpText = propertyInfo.immutable ? Messages.ComponentTypeViewerData_ESCToClose : Messages.ComponentTypeViewerData_CtrlEnterApplyChanges;
624 Label help = tk.createLabel(shell, helpText, SWT.BORDER | SWT.FLAT);
625 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(help);
626 help.setForeground( tk.getColors().createColor( "fg", tk.getColors().getSystemColor(SWT.COLOR_LIST_SELECTION) ) ); //$NON-NLS-1$
628 Display display = table.getDisplay();
629 Rectangle clientArea = display.getClientArea();
630 Point bt = table.toDisplay(selectedItemBounds.x, selectedItemBounds.y);
631 Rectangle b = selectedItemBounds;
635 if ((b.x + b.width) > clientArea.width)
636 b.x -= b.x + b.width - clientArea.width;
637 if (b.height > clientArea.height)
638 b.height = clientArea.height;
639 if ((b.y + b.height) > clientArea.height)
640 b.y -= b.y + b.height - clientArea.height;
642 shell.setBounds(selectedItemBounds);
648 text.addListener(SWT.Traverse, listener);
649 shell.addListener(SWT.Deactivate, listener);
652 private String validatePropertyName(ComponentTypeViewerPropertyInfo propertyInfo, String propertyName, Pattern namePattern) {
653 if (propertyName.equals(propertyInfo.name))
655 for (ComponentTypeViewerPropertyInfo info : properties) {
656 if (propertyName.equals(info.name))
657 return NLS.bind(Messages.ComponentTypeViewerData_PropertyNameInUse, propertyName);
659 for (NamedResource cp : connectionPoints) {
660 if (propertyName.equals(cp.getName()))
661 return NLS.bind(Messages.ComponentTypeViewerData_NameInUse, propertyName );
663 Matcher m = namePattern.matcher(propertyName);
665 return NLS.bind(Messages.ComponentTypeViewerData_ContainsInvalidCharacters, propertyName, namePattern.pattern());