X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fforms%2FDataboardForm.java;h=b86726c19a5117f2c7bde92fd31f7348661e81c1;hb=HEAD;hp=c73f76eab60ab3e302dfaffdc623e4f6d05a0ba3;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/forms/DataboardForm.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/forms/DataboardForm.java index c73f76eab..b86726c19 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/forms/DataboardForm.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/forms/DataboardForm.java @@ -1,1203 +1,1203 @@ -package org.simantics.databoard.forms; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CTabFolder; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.DirectoryDialog; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.simantics.databoard.Accessors; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.accessor.Accessor; -import org.simantics.databoard.accessor.BooleanAccessor; -import org.simantics.databoard.accessor.RecordAccessor; -import org.simantics.databoard.accessor.StringAccessor; -import org.simantics.databoard.accessor.UnionAccessor; -import org.simantics.databoard.accessor.error.AccessorConstructionException; -import org.simantics.databoard.accessor.error.AccessorException; -import org.simantics.databoard.accessor.error.ReferenceException; -import org.simantics.databoard.accessor.reference.ChildReference; -import org.simantics.databoard.accessor.reference.LabelReference; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.NumberBinding; -import org.simantics.databoard.binding.RecordBinding; -import org.simantics.databoard.binding.StringBinding; -import org.simantics.databoard.binding.UnionBinding; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.binding.mutable.TaggedObject; -import org.simantics.databoard.parser.repository.DataTypeSyntaxError; -import org.simantics.databoard.type.BooleanType; -import org.simantics.databoard.type.Component; -import org.simantics.databoard.type.Datatype; -import org.simantics.databoard.type.NumberType; -import org.simantics.databoard.type.RecordType; -import org.simantics.databoard.type.StringType; -import org.simantics.databoard.type.UnionType; -import org.simantics.databoard.util.Bean; -import org.simantics.databoard.util.StringUtil; -import org.simantics.databoard.util.URIUtil; - -/** - * Databoard form creates SWT user interface from databoard record type. - * - * See DataboardFormExample for example usage. - * - * @author toni.kalajainen@semantum.fi - */ -public class DataboardForm { - - public static final Datatype TEXTBOX; - public static final Datatype PASSWORD; - - public int column1Width = -1; - - private RecordType allfields = new RecordType(); - - /** - * Make file type - * - * @param namesAndExts array of names and extensions - * @param exts - * @return - */ - public static StringType fileSaveDialog(String...namesAndExts) - { - StringType result = new StringType(); - result.metadata.put("style", "filesave"); - - StringBuilder sb1 = new StringBuilder(); - StringBuilder sb2 = new StringBuilder(); - - for (int i=0; i0) sb.append(','); - sb.append(namesAndExts[i]); - } - - result.metadata.put("filetypes", sb1.toString()); - result.metadata.put("fileexts", sb2.toString()); - return result; - } - - /** - * Make file type - * - * @param namesAndExts array of names and extensions - * @param exts - * @return - */ - public static StringType fileOpenDialog(String...namesAndExts) - { - StringType result = new StringType(); - result.metadata.put("style", "fileopen"); - - StringBuilder sb1 = new StringBuilder(); - StringBuilder sb2 = new StringBuilder(); - - for (int i=0; i0) sb.append(','); - sb.append(namesAndExts[i]); - } - - result.metadata.put("filetypes", sb1.toString()); - result.metadata.put("fileexts", sb2.toString()); - return result; - } - - public static StringType directoryDialog() - { - StringType result = new StringType(); - result.metadata.put("style", "directory"); - return result; - } - - public DataboardForm() { - } - - public void setFirstColumnWidth(int width) { - column1Width = width; - } - - - /** - * Validate the fields for valid values. - * StringTypes can be restricted with regular expressions. - * NumberTypes with value ranges. - * - * @param composite - * @return list of problems - */ - public List validate( Composite composite ) { - List result = new ArrayList(); - _validateFields(composite, result); - return result; - } - - public static List toStrings(List problems) { - List result = new ArrayList( problems.size() ); - for (Problem p : problems) result.add(p.error); - return result; - } - - public static class Problem extends Bean { - /** Reference to the field with problem */ - public String fieldReference; - /** The field with problem */ - public transient Control control; - /** The validation error */ - public String error; - } - - protected void _validateFields( Control control, List result ) - { - // Read this control - Object data = control.getData(); - if ( data != null && data instanceof String ) { - String refStr = (String) data; - ChildReference ref = ChildReference.parsePath( refStr); - if ( ref != null ) { - try { - Datatype fieldType = allfields.getChildType( ref ); - - // Read Combo Union - if ( fieldType instanceof UnionType && control instanceof Combo ) { - // Nothing to validate - } else - - // Read Radio Union - if ( fieldType instanceof UnionType && control instanceof Composite ) { - // Nothing to validate - } else - - // Read Boolean - if ( fieldType instanceof BooleanType && control instanceof Button ) { - // Nothing to validate - } else - - // Text + Dialog button - if ( fieldType instanceof RecordType && control instanceof Text ) { - try { - Text text = (Text) control; - RecordBinding fieldBinding = Bindings.getMutableBinding(fieldType); - Object value = parse(fieldBinding, text.getText()); - fieldBinding.assertInstaceIsValid( value ); - } catch (BindingException er) { - Problem problem = new Problem(); - if ( er.getCause()!=null ) { - problem.error = er.getCause().getMessage(); - } else { - problem.error = er.getMessage(); - } - problem.fieldReference = refStr; - problem.control = control; - result.add( problem ); - } - - } else - - // Read Text - if ( fieldType instanceof StringAccessor && control instanceof Text ) { - try { - Text text = (Text) control; - StringBinding binding = Bindings.getBinding(fieldType); - Object value = binding.create(text.getText()); - binding.assertInstaceIsValid( value ); - } catch (BindingException er) { - Problem problem = new Problem(); - if ( er.getCause()!=null ) { - problem.error = er.getCause().getMessage(); - } else { - problem.error = er.getMessage(); - } - problem.fieldReference = refStr; - problem.control = control; - result.add( problem ); - } - } else - - // Read Numbers - if ( fieldType instanceof NumberType && control instanceof Text ) { - try { - Text text = (Text) control; - NumberBinding binding = Bindings.getBinding(fieldType); - Object value = binding.create(text.getText()); - binding.assertInstaceIsValid( value ); - } catch (BindingException er) { - Problem problem = new Problem(); - if ( er.getCause()!=null && er.getCause() instanceof NumberFormatException) { - NumberFormatException nfe = (NumberFormatException) er.getCause(); - problem.error = nfe.getMessage(); - } else { - problem.error = er.getMessage(); - } - problem.fieldReference = refStr; - problem.control = control; - result.add( problem ); - } - } - - } catch (AccessorConstructionException e) { - Problem problem = new Problem(); - problem.error = e.getMessage(); - problem.fieldReference = refStr; - problem.control = control; - result.add( problem ); - } - } - } - - // Recursion - if ( control instanceof Composite ) { - Composite composite = (Composite) control; - for (Control child : composite.getChildren()) - { - _validateFields(child, result); - } - } - - } - - public RecordType type() { - return allfields; - } - - /** - * Find control by reference - * @param control - * @param ref - * @return control or null - */ - public Control getControl( Control control, ChildReference ref ) - { - return getControl( control, ref.toPath() ); - } - - /** - * Find control by reference. - * - * @param composite - * @param ref - * @return control or null - */ - public Control getControl( Control control, String ref ) - { - Object data = control.getData(); - if ( data != null && data instanceof String && data.equals(ref)) return control; - - // Recursion - if ( control instanceof Composite ) { - Composite composite = (Composite) control; - for (Control child : composite.getChildren()) - { - Control result = getControl(child, ref); - if ( result != null ) return result; - } - } - return null; - } - - /** - * Reads values of fields into a record - * - * @param composite the composite that holds the widgets - * @param binding record binding - * @param dst the record where values are read to - * @throws BindingException - * @throws AccessorConstructionException - * @throws AccessorException - */ - public void readFields( Composite composite, RecordBinding binding, Object dst) - throws BindingException, AccessorConstructionException, AccessorException - { - RecordAccessor ra = Accessors.getAccessor(binding, dst); - _readFields(composite, ra); - } - - protected void _readFields( Control control, RecordAccessor ra ) - throws AccessorException, BindingException - { - // Read this control - Object data = control.getData(); - if ( data != null && data instanceof String ) { - ChildReference ref = ChildReference.parsePath( (String) data); - if ( ref != null ) { - try { - Accessor fieldAccessor = ra.getComponent( ref ); - - // Read Combo Union - if ( fieldAccessor instanceof UnionAccessor && control instanceof Combo ) { - UnionAccessor sa = (UnionAccessor) fieldAccessor; - Combo combo = (Combo) control; - String text = combo.getText(); - int tag = sa.type().getComponentIndex2(text); - Datatype tagType = sa.type().components[tag].type; - Binding tagBinding = Bindings.getBinding(tagType); - Object defaultValue = tagBinding.createDefault(); - sa.setComponentValue(tag, tagBinding, defaultValue); - } else - - // Read Radio Union - if ( fieldAccessor instanceof UnionAccessor && control instanceof Composite ) { - Composite radioComposite = (Composite) control; - for (Control c : radioComposite.getChildren()) { - if ( c instanceof Button && ((Button)c).getSelection() ) { - Object data2 = c.getData(); - if (data2==null) continue; - String name = getName( data2.toString() ); - if ( name==null ) continue; - - UnionAccessor sa = (UnionAccessor) fieldAccessor; - int tag = sa.type().getComponentIndex2( name ); - if ( tag>=0 ) { - Datatype tagType = sa.type().components[tag].type; - Binding tagBinding = Bindings.getBinding(tagType); - Object defaultValue = tagBinding.createDefault(); - sa.setComponentValue(tag, tagBinding, defaultValue); - break; - } - } - } - } else - - // Read Boolean - if ( fieldAccessor instanceof BooleanAccessor && control instanceof Button ) { - BooleanAccessor sa = (BooleanAccessor) fieldAccessor; - sa.setValue(((Button)control).getSelection()); - } else - - // Read Text + Dialog Button - if ( fieldAccessor instanceof RecordAccessor && control instanceof Text ) { - RecordAccessor raa = (RecordAccessor) fieldAccessor; - Text text = (Text) control; - RecordBinding fieldBinding = Bindings.getMutableBinding( raa.type() ); - Object value = parse( fieldBinding, text.getText() ); - raa.setValue(fieldBinding, value); - } else - - // Read Text - if ( fieldAccessor instanceof StringAccessor && control instanceof Text ) { - StringAccessor sa = (StringAccessor) fieldAccessor; - sa.setValue(((Text)control).getText()); - } else - - // Read Numbers - if ( fieldAccessor.type() instanceof NumberType && control instanceof Text ) { - NumberBinding binding = Bindings.getBinding( fieldAccessor.type() ); - Object value = binding.create( ((Text)control).getText() ); - fieldAccessor.setValue(binding, value); - } - - } catch (AccessorConstructionException e) { - //e.printStackTrace(); - } - } - } - - // Recursion - if ( control instanceof Composite ) { - Composite composite = (Composite) control; - for (Control child : composite.getChildren()) - { - _readFields(child, ra); - } - } - } - - public void writeFields( Composite composite, RecordBinding binding, Object src) - throws AccessorException, BindingException, AccessorConstructionException - { - RecordAccessor ra = Accessors.getAccessor(binding, src); - _writeFields(composite, ra); - } - - void _writeFields( Control control, RecordAccessor ra ) - throws AccessorException, BindingException, AccessorConstructionException - { - // Read this control - Object data = control.getData(); - if ( data != null && data instanceof String ) { - ChildReference ref = ChildReference.parsePath( (String) data); - if ( ref != null ) { - try { - Accessor fieldAccessor = ra.getComponent( ref ); - - // Read Combo Union - if ( fieldAccessor instanceof UnionAccessor && control instanceof Combo ) { - UnionAccessor sa = (UnionAccessor) fieldAccessor; - Combo combo = (Combo) control; - int tag = sa.getTag(); - combo.setText( sa.type().getComponent(tag).name ); - } else - - // Read Radio Union - if ( fieldAccessor instanceof UnionAccessor && control instanceof Composite) { - Composite radioComposite = (Composite) control; - UnionAccessor sa = (UnionAccessor) fieldAccessor; - int tag = sa.getTag(); - for (int i=0; i0) new Label(parent, 0); - - CTabItem item = new CTabItem(folder, SWT.NONE); - item.setText(childName); - Composite composite = new Composite(folder, 0); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); - composite.setLayout( new GridLayout(3, false) ); - composite.setData(ref); - - if ( childType instanceof RecordType ) { - addRecord( composite, (RecordType)childType, childRef); - } else { - addWidget( composite, childType, childRef ); - } - - item.setControl( composite ); - } - folder.setSelection(0); - - } else - - // Method 1: Dialog = Label + Text + [Button] - if ( dialog ) { - Label label = new Label(parent, 0); - label.setText(fieldName + ":"); - label.setLayoutData( lblLayout ); - - final String title = fieldName; - final Shell shell = parent.getShell(); - final RecordBinding fieldBinding = Bindings.getMutableBinding( fieldType ); - final Object fieldValue = fieldBinding.createDefaultUnchecked(); - final Text text = new Text(parent, SWT.BORDER); - final Button select = new Button(parent, SWT.PUSH); - text.setLayoutData( new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1 ) ); - text.setText( print(fieldBinding, fieldValue) ); - text.setData(ref); - text.addListener(SWT.Verify, new Listener() { - public void handleEvent(Event e) { - try { - String newText = applyEventToString( text.getText(), e ); - Object value = parse(fieldBinding, newText); - fieldBinding.assertInstaceIsValid( value ); - text.setBackground(null); - } catch (BindingException er) { - Color error = new Color(text.getDisplay(), 255, 222, 222); - text.setBackground(error); - error.dispose(); - } - } - }); - - //text.setEditable( false ); - select.setText("Select"); - select.setLayoutData(new GridData(SWT.RIGHT, SWT.BEGINNING, false, false)); - select.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - Object initialValue; - try { - initialValue = parse(fieldBinding, text.getText()); - } catch (BindingException e1) { - initialValue = fieldBinding.createDefaultUnchecked(); - } - DataboardDialog dialog = new DataboardDialog( - shell, - title, - fieldBinding, - initialValue); - - int code = dialog.open(); - if ( code == Window.OK ) { - Object result = dialog.getResult(); - String str = print(fieldBinding, result); - text.setText( str ); - } - } - }); - - } else - - // Method 2: Label + composite - if ( allBooleans(record) ) { - Label label = new Label(parent, 0); - label.setText(fieldName + ":"); - label.setLayoutData( lblLayout ); - - for (int i=0; i0) new Label(parent, 0); - addWidget( parent, childType, childRef ); - } - - } - else - - // Method 3: Groups - { - Group group = new Group(parent, 0); - group.setText(fieldName); - group.setLayout( new GridLayout(3, false) ); - group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); - group.setData(ref); - addRecord(group, record, ref); - } - - } else if (fieldType instanceof UnionType) { - Label label = new Label(parent, 0); - label.setText(fieldName + ":"); - label.setLayoutData( lblLayout ); - addUnion( parent, (UnionType) fieldType, ref ); - } - - } - - protected void addWidget(Composite parent, Datatype fieldType, String ref) { - if (fieldType instanceof StringType) { - addString(parent, (StringType) fieldType, ref); - } else if (fieldType instanceof BooleanType) { - addBoolean(parent, (BooleanType) fieldType, ref); - } else if (fieldType instanceof NumberType) { - addNumber(parent, (NumberType) fieldType, ref); - } else if (fieldType instanceof RecordType) { - RecordType rt = (RecordType) fieldType; - Group group = new Group(parent, 0); - String name = getName(ref); - group.setText(name); - group.setLayout( new GridLayout(3, false) ); - group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); - group.setData(ref); - addRecord(group, rt, ref); - } else if (fieldType instanceof UnionType) { - addUnion( parent, (UnionType) fieldType, ref ); - } - } - - public CTabFolder addTabFolder( Composite parent, RecordType record, String ref ) - { - CTabFolder folder = new CTabFolder(parent, SWT.TOP | SWT.BORDER); - folder.setSimple(false); - folder.setLayout( new GridLayout(3, false) ); - folder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); - - for (int i=0; i0) new Label(parent, 0); - - CTabItem item = new CTabItem(folder, SWT.NONE); - item.setText(childName); - Composite composite = new Composite(folder, 0); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); - composite.setLayout( new GridLayout(3, false) ); - composite.setData(ref); - - if ( childType instanceof RecordType ) { - addRecord( composite, (RecordType)childType, childRef); - } else { - addWidget( composite, childType, childRef ); - } - - item.setControl( composite ); - allfields.addComponent(childName, childType); - } - folder.setSelection(0); - return folder; - - } - - protected void addRecord( Composite parent, RecordType record, String ref ) - { - String options = record.metadata.get("style"); - boolean dialog = options==null?false:options.contains("dialog"); - boolean tabbed = options==null?false:options.contains("tabbed"); - - // Method 0: Tabbed, each field is a tab page - if ( tabbed ) { - addTabFolder( parent, record, ref ); - return; - } - - // Normal Record - GridData lblLayout = new GridData(SWT.LEFT, SWT.BEGINNING, false, false, 1, 1); - if ( getDepth(ref) < 3 ) lblLayout.widthHint = column1Width; - - for (int i=0; i0 ) sb.append(", "); - sb.append(recordBinding.type().getComponent(i).name); - j++; - } catch (BindingException e) { - continue; - } - } - return sb.toString(); - } else - try { - return recordBinding.toString(value, true); - } catch (BindingException e) { - return e.toString(); - } - } - - static Object parse(RecordBinding recordBinding, String txt) throws BindingException { - if ( allBooleans(recordBinding.type() ) ) { - Object result = recordBinding.createDefaultUnchecked(); - String[] tokens = txt.split(", "); - for ( String token : tokens ) { - if ( token.isEmpty() ) continue; - int i = recordBinding.type().getComponentIndex2(token); - if ( i>=0 ) { - try { - recordBinding.setBoolean(result, i, true); - } catch (BindingException e) { - throw e; - } - } else { - throw new BindingException("There is no field \""+token+"\""); - } - } - return result; - } else { - try { - return recordBinding.parseValueDefinition(txt); - } catch (DataTypeSyntaxError e) { - throw new BindingException(e); - } - - } - } - - static { - PASSWORD = new StringType(); - PASSWORD.metadata.put("style", "password"); - - TEXTBOX = new StringType(); - TEXTBOX.metadata.put("style", "multi"); - } - -} +package org.simantics.databoard.forms; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.simantics.databoard.Accessors; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.accessor.Accessor; +import org.simantics.databoard.accessor.BooleanAccessor; +import org.simantics.databoard.accessor.RecordAccessor; +import org.simantics.databoard.accessor.StringAccessor; +import org.simantics.databoard.accessor.UnionAccessor; +import org.simantics.databoard.accessor.error.AccessorConstructionException; +import org.simantics.databoard.accessor.error.AccessorException; +import org.simantics.databoard.accessor.error.ReferenceException; +import org.simantics.databoard.accessor.reference.ChildReference; +import org.simantics.databoard.accessor.reference.LabelReference; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.NumberBinding; +import org.simantics.databoard.binding.RecordBinding; +import org.simantics.databoard.binding.StringBinding; +import org.simantics.databoard.binding.UnionBinding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.mutable.TaggedObject; +import org.simantics.databoard.parser.repository.DataTypeSyntaxError; +import org.simantics.databoard.type.BooleanType; +import org.simantics.databoard.type.Component; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.NumberType; +import org.simantics.databoard.type.RecordType; +import org.simantics.databoard.type.StringType; +import org.simantics.databoard.type.UnionType; +import org.simantics.databoard.util.Bean; +import org.simantics.databoard.util.StringUtil; +import org.simantics.databoard.util.URIUtil; + +/** + * Databoard form creates SWT user interface from databoard record type. + * + * See DataboardFormExample for example usage. + * + * @author toni.kalajainen@semantum.fi + */ +public class DataboardForm { + + public static final Datatype TEXTBOX; + public static final Datatype PASSWORD; + + public int column1Width = -1; + + private RecordType allfields = new RecordType(); + + /** + * Make file type + * + * @param namesAndExts array of names and extensions + * @param exts + * @return + */ + public static StringType fileSaveDialog(String...namesAndExts) + { + StringType result = new StringType(); + result.metadata.put("style", "filesave"); + + StringBuilder sb1 = new StringBuilder(); + StringBuilder sb2 = new StringBuilder(); + + for (int i=0; i0) sb.append(','); + sb.append(namesAndExts[i]); + } + + result.metadata.put("filetypes", sb1.toString()); + result.metadata.put("fileexts", sb2.toString()); + return result; + } + + /** + * Make file type + * + * @param namesAndExts array of names and extensions + * @param exts + * @return + */ + public static StringType fileOpenDialog(String...namesAndExts) + { + StringType result = new StringType(); + result.metadata.put("style", "fileopen"); + + StringBuilder sb1 = new StringBuilder(); + StringBuilder sb2 = new StringBuilder(); + + for (int i=0; i0) sb.append(','); + sb.append(namesAndExts[i]); + } + + result.metadata.put("filetypes", sb1.toString()); + result.metadata.put("fileexts", sb2.toString()); + return result; + } + + public static StringType directoryDialog() + { + StringType result = new StringType(); + result.metadata.put("style", "directory"); + return result; + } + + public DataboardForm() { + } + + public void setFirstColumnWidth(int width) { + column1Width = width; + } + + + /** + * Validate the fields for valid values. + * StringTypes can be restricted with regular expressions. + * NumberTypes with value ranges. + * + * @param composite + * @return list of problems + */ + public List validate( Composite composite ) { + List result = new ArrayList(); + _validateFields(composite, result); + return result; + } + + public static List toStrings(List problems) { + List result = new ArrayList( problems.size() ); + for (Problem p : problems) result.add(p.error); + return result; + } + + public static class Problem extends Bean { + /** Reference to the field with problem */ + public String fieldReference; + /** The field with problem */ + public transient Control control; + /** The validation error */ + public String error; + } + + protected void _validateFields( Control control, List result ) + { + // Read this control + Object data = control.getData(); + if ( data != null && data instanceof String ) { + String refStr = (String) data; + ChildReference ref = ChildReference.parsePath( refStr); + if ( ref != null ) { + try { + Datatype fieldType = allfields.getChildType( ref ); + + // Read Combo Union + if ( fieldType instanceof UnionType && control instanceof Combo ) { + // Nothing to validate + } else + + // Read Radio Union + if ( fieldType instanceof UnionType && control instanceof Composite ) { + // Nothing to validate + } else + + // Read Boolean + if ( fieldType instanceof BooleanType && control instanceof Button ) { + // Nothing to validate + } else + + // Text + Dialog button + if ( fieldType instanceof RecordType && control instanceof Text ) { + try { + Text text = (Text) control; + RecordBinding fieldBinding = Bindings.getMutableBinding(fieldType); + Object value = parse(fieldBinding, text.getText()); + fieldBinding.assertInstaceIsValid( value ); + } catch (BindingException er) { + Problem problem = new Problem(); + if ( er.getCause()!=null ) { + problem.error = er.getCause().getMessage(); + } else { + problem.error = er.getMessage(); + } + problem.fieldReference = refStr; + problem.control = control; + result.add( problem ); + } + + } else + + // Read Text + if ( fieldType instanceof StringAccessor && control instanceof Text ) { + try { + Text text = (Text) control; + StringBinding binding = Bindings.getBinding(fieldType); + Object value = binding.create(text.getText()); + binding.assertInstaceIsValid( value ); + } catch (BindingException er) { + Problem problem = new Problem(); + if ( er.getCause()!=null ) { + problem.error = er.getCause().getMessage(); + } else { + problem.error = er.getMessage(); + } + problem.fieldReference = refStr; + problem.control = control; + result.add( problem ); + } + } else + + // Read Numbers + if ( fieldType instanceof NumberType && control instanceof Text ) { + try { + Text text = (Text) control; + NumberBinding binding = Bindings.getBinding(fieldType); + Object value = binding.create(text.getText()); + binding.assertInstaceIsValid( value ); + } catch (BindingException er) { + Problem problem = new Problem(); + if ( er.getCause()!=null && er.getCause() instanceof NumberFormatException) { + NumberFormatException nfe = (NumberFormatException) er.getCause(); + problem.error = nfe.getMessage(); + } else { + problem.error = er.getMessage(); + } + problem.fieldReference = refStr; + problem.control = control; + result.add( problem ); + } + } + + } catch (AccessorConstructionException e) { + Problem problem = new Problem(); + problem.error = e.getMessage(); + problem.fieldReference = refStr; + problem.control = control; + result.add( problem ); + } + } + } + + // Recursion + if ( control instanceof Composite ) { + Composite composite = (Composite) control; + for (Control child : composite.getChildren()) + { + _validateFields(child, result); + } + } + + } + + public RecordType type() { + return allfields; + } + + /** + * Find control by reference + * @param control + * @param ref + * @return control or null + */ + public Control getControl( Control control, ChildReference ref ) + { + return getControl( control, ref.toPath() ); + } + + /** + * Find control by reference. + * + * @param composite + * @param ref + * @return control or null + */ + public Control getControl( Control control, String ref ) + { + Object data = control.getData(); + if ( data != null && data instanceof String && data.equals(ref)) return control; + + // Recursion + if ( control instanceof Composite ) { + Composite composite = (Composite) control; + for (Control child : composite.getChildren()) + { + Control result = getControl(child, ref); + if ( result != null ) return result; + } + } + return null; + } + + /** + * Reads values of fields into a record + * + * @param composite the composite that holds the widgets + * @param binding record binding + * @param dst the record where values are read to + * @throws BindingException + * @throws AccessorConstructionException + * @throws AccessorException + */ + public void readFields( Composite composite, RecordBinding binding, Object dst) + throws BindingException, AccessorConstructionException, AccessorException + { + RecordAccessor ra = Accessors.getAccessor(binding, dst); + _readFields(composite, ra); + } + + protected void _readFields( Control control, RecordAccessor ra ) + throws AccessorException, BindingException + { + // Read this control + Object data = control.getData(); + if ( data != null && data instanceof String ) { + ChildReference ref = ChildReference.parsePath( (String) data); + if ( ref != null ) { + try { + Accessor fieldAccessor = ra.getComponent( ref ); + + // Read Combo Union + if ( fieldAccessor instanceof UnionAccessor && control instanceof Combo ) { + UnionAccessor sa = (UnionAccessor) fieldAccessor; + Combo combo = (Combo) control; + String text = combo.getText(); + int tag = sa.type().getComponentIndex2(text); + Datatype tagType = sa.type().components[tag].type; + Binding tagBinding = Bindings.getBinding(tagType); + Object defaultValue = tagBinding.createDefault(); + sa.setComponentValue(tag, tagBinding, defaultValue); + } else + + // Read Radio Union + if ( fieldAccessor instanceof UnionAccessor && control instanceof Composite ) { + Composite radioComposite = (Composite) control; + for (Control c : radioComposite.getChildren()) { + if ( c instanceof Button && ((Button)c).getSelection() ) { + Object data2 = c.getData(); + if (data2==null) continue; + String name = getName( data2.toString() ); + if ( name==null ) continue; + + UnionAccessor sa = (UnionAccessor) fieldAccessor; + int tag = sa.type().getComponentIndex2( name ); + if ( tag>=0 ) { + Datatype tagType = sa.type().components[tag].type; + Binding tagBinding = Bindings.getBinding(tagType); + Object defaultValue = tagBinding.createDefault(); + sa.setComponentValue(tag, tagBinding, defaultValue); + break; + } + } + } + } else + + // Read Boolean + if ( fieldAccessor instanceof BooleanAccessor && control instanceof Button ) { + BooleanAccessor sa = (BooleanAccessor) fieldAccessor; + sa.setValue(((Button)control).getSelection()); + } else + + // Read Text + Dialog Button + if ( fieldAccessor instanceof RecordAccessor && control instanceof Text ) { + RecordAccessor raa = (RecordAccessor) fieldAccessor; + Text text = (Text) control; + RecordBinding fieldBinding = Bindings.getMutableBinding( raa.type() ); + Object value = parse( fieldBinding, text.getText() ); + raa.setValue(fieldBinding, value); + } else + + // Read Text + if ( fieldAccessor instanceof StringAccessor && control instanceof Text ) { + StringAccessor sa = (StringAccessor) fieldAccessor; + sa.setValue(((Text)control).getText()); + } else + + // Read Numbers + if ( fieldAccessor.type() instanceof NumberType && control instanceof Text ) { + NumberBinding binding = Bindings.getBinding( fieldAccessor.type() ); + Object value = binding.create( ((Text)control).getText() ); + fieldAccessor.setValue(binding, value); + } + + } catch (AccessorConstructionException e) { + //e.printStackTrace(); + } + } + } + + // Recursion + if ( control instanceof Composite ) { + Composite composite = (Composite) control; + for (Control child : composite.getChildren()) + { + _readFields(child, ra); + } + } + } + + public void writeFields( Composite composite, RecordBinding binding, Object src) + throws AccessorException, BindingException, AccessorConstructionException + { + RecordAccessor ra = Accessors.getAccessor(binding, src); + _writeFields(composite, ra); + } + + void _writeFields( Control control, RecordAccessor ra ) + throws AccessorException, BindingException, AccessorConstructionException + { + // Read this control + Object data = control.getData(); + if ( data != null && data instanceof String ) { + ChildReference ref = ChildReference.parsePath( (String) data); + if ( ref != null ) { + try { + Accessor fieldAccessor = ra.getComponent( ref ); + + // Read Combo Union + if ( fieldAccessor instanceof UnionAccessor && control instanceof Combo ) { + UnionAccessor sa = (UnionAccessor) fieldAccessor; + Combo combo = (Combo) control; + int tag = sa.getTag(); + combo.setText( sa.type().getComponent(tag).name ); + } else + + // Read Radio Union + if ( fieldAccessor instanceof UnionAccessor && control instanceof Composite) { + Composite radioComposite = (Composite) control; + UnionAccessor sa = (UnionAccessor) fieldAccessor; + int tag = sa.getTag(); + for (int i=0; i0) new Label(parent, 0); + + CTabItem item = new CTabItem(folder, SWT.NONE); + item.setText(childName); + Composite composite = new Composite(folder, 0); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); + composite.setLayout( new GridLayout(3, false) ); + composite.setData(ref); + + if ( childType instanceof RecordType ) { + addRecord( composite, (RecordType)childType, childRef); + } else { + addWidget( composite, childType, childRef ); + } + + item.setControl( composite ); + } + folder.setSelection(0); + + } else + + // Method 1: Dialog = Label + Text + [Button] + if ( dialog ) { + Label label = new Label(parent, 0); + label.setText(fieldName + ":"); + label.setLayoutData( lblLayout ); + + final String title = fieldName; + final Shell shell = parent.getShell(); + final RecordBinding fieldBinding = Bindings.getMutableBinding( fieldType ); + final Object fieldValue = fieldBinding.createDefaultUnchecked(); + final Text text = new Text(parent, SWT.BORDER); + final Button select = new Button(parent, SWT.PUSH); + text.setLayoutData( new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1 ) ); + text.setText( print(fieldBinding, fieldValue) ); + text.setData(ref); + text.addListener(SWT.Verify, new Listener() { + public void handleEvent(Event e) { + try { + String newText = applyEventToString( text.getText(), e ); + Object value = parse(fieldBinding, newText); + fieldBinding.assertInstaceIsValid( value ); + text.setBackground(null); + } catch (BindingException er) { + Color error = new Color(text.getDisplay(), 255, 222, 222); + text.setBackground(error); + error.dispose(); + } + } + }); + + //text.setEditable( false ); + select.setText("Select"); + select.setLayoutData(new GridData(SWT.RIGHT, SWT.BEGINNING, false, false)); + select.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + Object initialValue; + try { + initialValue = parse(fieldBinding, text.getText()); + } catch (BindingException e1) { + initialValue = fieldBinding.createDefaultUnchecked(); + } + DataboardDialog dialog = new DataboardDialog( + shell, + title, + fieldBinding, + initialValue); + + int code = dialog.open(); + if ( code == Window.OK ) { + Object result = dialog.getResult(); + String str = print(fieldBinding, result); + text.setText( str ); + } + } + }); + + } else + + // Method 2: Label + composite + if ( allBooleans(record) ) { + Label label = new Label(parent, 0); + label.setText(fieldName + ":"); + label.setLayoutData( lblLayout ); + + for (int i=0; i0) new Label(parent, 0); + addWidget( parent, childType, childRef ); + } + + } + else + + // Method 3: Groups + { + Group group = new Group(parent, 0); + group.setText(fieldName); + group.setLayout( new GridLayout(3, false) ); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); + group.setData(ref); + addRecord(group, record, ref); + } + + } else if (fieldType instanceof UnionType) { + Label label = new Label(parent, 0); + label.setText(fieldName + ":"); + label.setLayoutData( lblLayout ); + addUnion( parent, (UnionType) fieldType, ref ); + } + + } + + protected void addWidget(Composite parent, Datatype fieldType, String ref) { + if (fieldType instanceof StringType) { + addString(parent, (StringType) fieldType, ref); + } else if (fieldType instanceof BooleanType) { + addBoolean(parent, (BooleanType) fieldType, ref); + } else if (fieldType instanceof NumberType) { + addNumber(parent, (NumberType) fieldType, ref); + } else if (fieldType instanceof RecordType) { + RecordType rt = (RecordType) fieldType; + Group group = new Group(parent, 0); + String name = getName(ref); + group.setText(name); + group.setLayout( new GridLayout(3, false) ); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); + group.setData(ref); + addRecord(group, rt, ref); + } else if (fieldType instanceof UnionType) { + addUnion( parent, (UnionType) fieldType, ref ); + } + } + + public CTabFolder addTabFolder( Composite parent, RecordType record, String ref ) + { + CTabFolder folder = new CTabFolder(parent, SWT.TOP | SWT.BORDER); + folder.setSimple(false); + folder.setLayout( new GridLayout(3, false) ); + folder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); + + for (int i=0; i0) new Label(parent, 0); + + CTabItem item = new CTabItem(folder, SWT.NONE); + item.setText(childName); + Composite composite = new Composite(folder, 0); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); + composite.setLayout( new GridLayout(3, false) ); + composite.setData(ref); + + if ( childType instanceof RecordType ) { + addRecord( composite, (RecordType)childType, childRef); + } else { + addWidget( composite, childType, childRef ); + } + + item.setControl( composite ); + allfields.addComponent(childName, childType); + } + folder.setSelection(0); + return folder; + + } + + protected void addRecord( Composite parent, RecordType record, String ref ) + { + String options = record.metadata.get("style"); + boolean dialog = options==null?false:options.contains("dialog"); + boolean tabbed = options==null?false:options.contains("tabbed"); + + // Method 0: Tabbed, each field is a tab page + if ( tabbed ) { + addTabFolder( parent, record, ref ); + return; + } + + // Normal Record + GridData lblLayout = new GridData(SWT.LEFT, SWT.BEGINNING, false, false, 1, 1); + if ( getDepth(ref) < 3 ) lblLayout.widthHint = column1Width; + + for (int i=0; i0 ) sb.append(", "); + sb.append(recordBinding.type().getComponent(i).name); + j++; + } catch (BindingException e) { + continue; + } + } + return sb.toString(); + } else + try { + return recordBinding.toString(value, true); + } catch (BindingException e) { + return e.toString(); + } + } + + static Object parse(RecordBinding recordBinding, String txt) throws BindingException { + if ( allBooleans(recordBinding.type() ) ) { + Object result = recordBinding.createDefaultUnchecked(); + String[] tokens = txt.split(", "); + for ( String token : tokens ) { + if ( token.isEmpty() ) continue; + int i = recordBinding.type().getComponentIndex2(token); + if ( i>=0 ) { + try { + recordBinding.setBoolean(result, i, true); + } catch (BindingException e) { + throw e; + } + } else { + throw new BindingException("There is no field \""+token+"\""); + } + } + return result; + } else { + try { + return recordBinding.parseValueDefinition(txt); + } catch (DataTypeSyntaxError e) { + throw new BindingException(e); + } + + } + } + + static { + PASSWORD = new StringType(); + PASSWORD.metadata.put("style", "password"); + + TEXTBOX = new StringType(); + TEXTBOX.metadata.put("style", "multi"); + } + +}