HexFlex
HexFlex

Reputation: 271

Use DataBinding on Combo

I try to use DataBinding on SWT Widgets.

I´m wondering if there is a way to connect a Combo Box to an underlying String in the model. So I have a String in the Model and a Combo on my View?

As the standard way is not working:

//View
DataBindingContext ctx = new DataBindingContext();
IObservableValue target1 = WidgetProperties.singleSelectionIndex().observe(combo);
IObservableValue model1 = BeanProperties.value(OutputVariable.class, "type").observe(outputVariable);
ctx.bindValue(target1, model1);

//Model
public void setType(String type) {
    //TYPES is a constant with the possible Combo values
    if (contains(TYPES, type)) {
        String oldType = this.type;
        this.type = type;
        firePropertyChange("type", oldType, this.type);
    }else {
        throw new IllegalArgumentException();
    }
}

I tried to use the fireIndexedPropertyChangeMethod which didn't worked either.

Is there a way to connect those two together? Maybe I have to use another WidgetProperties or BeanProperties method?

As a workaround I could maybe use a new Property in the model, which defines the combo selection index, connect this to the Combo and transfer changes of this index to the type Property and vice versa. But that seems not as a great solution to me.

Edit: The Solution with a selectionIndex Property is working. But a cleaner method would still be nice as now a type Property change in the model has to reset the selectionIndex too and vice versa.

Upvotes: 0

Views: 432

Answers (1)

HexFlex
HexFlex

Reputation: 271

I have a clean solution now, which is to use a Converter.

//View
    IObservableValue comboObservable = WidgetProperties.singleSelectionIndex().observe(combo);
    IObservableValue viewTypeObservable = BeanProperties.value(DebugModel.class, "type").observe(debugModel);

    IConverter viewTypeToIntConverter = createViewTypeToIntConverter();
    UpdateValueStrategy toTargetStrategy = new UpdateValueStrategy();
    toTargetStrategy.setConverter(viewTypeToIntConverter);

    IConverter intToViewTypeConverter = createIntToViewTypeConverter();
    UpdateValueStrategy toModelStrategy = new UpdateValueStrategy();
    toModelStrategy.setConverter(intToViewTypeConverter);

    DataBindingContext context = new DataBindingContext();
    context.bindValue(comboObservable, viewTypeObservable, toModelStrategy, toTargetStrategy);

//Converter
private IConverter createIntToViewTypeConverter() {
    return new IConverter() {

        @Override
        public Object convert(Object value) {
            if(value instanceof Integer) {
                for(ViewType type : ViewType.values()) {
                    if(type.toString().equals(ViewType.getStringAtIndex((int)value))) {
                        return type;
                    }
                }
            }
            throw new IllegalArgumentException("We need an Integer to convert it but got an " + value.getClass());
        }

        @Override
        public Object getFromType() {
            return Integer.class;
        }

        @Override
        public Object getToType() {
            return ViewType.class;
        }

    };
}

private IConverter createViewTypeToIntConverter() {
    return new IConverter() {

        @Override
        public Object convert(Object value) {
            if(value instanceof ViewType) {
                String[] viewTypes = ViewType.getStringValues();
                for(int i=0;i<viewTypes.length;i++) {
                    if(viewTypes[i].equals(((ViewType)value).toString())) {
                        return i;
                    }
                } 
            }
            throw new IllegalArgumentException("We need a View Type to be converted but got a " + value.getClass());
        }

        @Override
        public Object getFromType() {
            return ViewType.class;
        }

        @Override
        public Object getToType() {
            return Integer.class;
        }

    };
}

//Model
public class DebugModel extends ModelObject {
    private ViewType type;
    public ViewType getType() {
         return type;
    }

    public void setType(ViewType type) {
        firePropertyChange("type", this.type, this.type = type);
    }
}

//Just to complete the example, be sure the Model class extends a ModelObject class like this
public class ModelObject {
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
        this);

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.removePropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propertyName,
        PropertyChangeListener listener) {
        changeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void removePropertyChangeListener(String propertyName,
        PropertyChangeListener listener) {
        changeSupport.removePropertyChangeListener(propertyName, listener);
    }

    protected void firePropertyChange(String propertyName, Object oldValue,
        Object newValue) {
        changeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    protected void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
        changeSupport.fireIndexedPropertyChange(propertyName, index, oldValue, newValue);
    }
}

Of course you can outsource the Converters to custom classes, I used it this way just to show a quick solution here.

Upvotes: 1

Related Questions