uqbar-project / arena

MMVC framework
http://arena.uqbar-project.org/
4 stars 2 forks source link

ValueTransformer model view needs an Object type always #38

Closed fdodino closed 7 years ago

fdodino commented 8 years ago

You should use Object as View type

I'm not sure

fdodino commented 8 years ago

Example:

class PasswordOkTransformer implements ValueTransformer<Boolean, Object> {

    override getModelType() {
        typeof(Boolean)
    }

    override getViewType() {
        typeof(Object)
    }

    override modelToView(Boolean valueFromModel) {
        if (valueFromModel) Color.GREEN else Color.ORANGE
    }

    override viewToModel(Object valueFromView) {
        null    
    }

}

Instead of Object, we should use Color. See https://github.com/uqbar-project/eg-login-arena-xtend, in LoginWindow.class

PalumboN commented 8 years ago

If you declare something like:

new TextBox(editorPanel) => [
    value <=> "name"
    (foreground <=> "name").transformer = new NameTransformer()
]

class NameTransformer implements ValueTransformer<String,Color> {
...
}

It fails at runtime:

Exception in thread "main" org.eclipse.core.databinding.BindingException: converter does not convert from type class java.lang.Object Expected: class java.lang.Object, actual: class java.awt.Color
    at org.eclipse.core.databinding.UpdateStrategy.checkAssignable(UpdateStrategy.java:97)
    at org.eclipse.core.databinding.UpdateValueStrategy.fillDefaults(UpdateValueStrategy.java:272)
    at org.eclipse.core.databinding.DataBindingContext.bindValue(DataBindingContext.java:137)
    at org.uqbar.lacar.ui.impl.jface.bindings.JFaceBindingBuilder.createBinding(JFaceBindingBuilder.scala:91)
    at org.uqbar.lacar.ui.impl.jface.bindings.JFaceBindingBuilder.build(JFaceBindingBuilder.scala:84)
    at org.uqbar.lacar.ui.model.bindings.Binding.execute(Binding.java:116)
    at org.uqbar.arena.widgets.Widget.showOn(Widget.java:95)
    at org.uqbar.arena.widgets.Panel.showOn(Panel.java:140)
    at org.uqbar.arena.widgets.Panel.showOn(Panel.java:140)
    at org.uqbar.arena.windows.Window.showOn(Window.java:197)
    at org.uqbar.arena.windows.Window.showOn(Window.java:25)
    at org.uqbar.lacar.ui.impl.jface.builder.windows.JFaceWindowBuilder.createWindowContents(JFaceWindowBuilder.scala:89)
    at org.uqbar.lacar.ui.impl.jface.builder.windows.JFaceWindowBuilder$$anon$1.createContents(JFaceWindowBuilder.scala:146)
    at org.uqbar.lacar.ui.impl.jface.builder.windows.JFaceWindowBuilder$$anon$1.createContents(JFaceWindowBuilder.scala:144)
    at org.eclipse.jface.window.Window.create(Window.java:431)
    at org.uqbar.lacar.ui.impl.jface.builder.windows.JFaceWindowBuilder.open(JFaceWindowBuilder.scala:55)
    at org.uqbar.arena.windows.Window.open(Window.java:145)
    at org.uqbar.arena.Application.run(Application.java:85)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288)
    at org.uqbar.arena.jface.app.JFaceApplicationBuilder.run(JFaceApplicationBuilder.scala:18)
    at org.uqbar.arena.Application.start(Application.java:64)
    at ejercicio1.SaludoApplication.main(SaludoApplication.java:18)

But it works when the transformer returns an Object :+1: :

class NameTransformer implements ValueTransformer<String,Object>{
...
}

I hadn't seen the above comment :P

fdodino commented 7 years ago

FUCK! After spending so many hours, discovered that there were 2 implementations of ControlObservableValue. The Arena one was causing all this problems:

public Object getValueType() {
    return Object.class;
}

So, this fails:

    protected void fillDefaults(IObservableValue source,
            IObservableValue destination) {
        Object sourceType = source.getValueType();
        Object destinationType = destination.getValueType();
        if (provideDefaults && sourceType != null && destinationType != null) {
            if (converter == null) {
                IConverter converter = createConverter(sourceType,
                        destinationType);
                defaultedConverter = (converter != null);
                setConverter(converter);
            }

            if (afterGetValidator == null) {
                afterGetValidator = createValidator(sourceType, destinationType);
            }
        }
        if (converter != null) {
            if (sourceType != null) {
                checkAssignable(converter.getFromType(), sourceType,
                        "converter does not convert from type " + sourceType); //$NON-NLS-1$
            }
            if (destinationType != null) {
                checkAssignable(converter.getToType(), destinationType,
                        "converter does not convert to type " + destinationType); //$NON-NLS-1$
            }
        }
    }

Well, at least I could find the problem.

fdodino commented 7 years ago

Finally got it!

        new TextBox(mainPanel) => [
            value <=> "miles"
            (background <=> "miles").transformer = new MilesTransformer;
            (enabled <=> "miles").transformer = new MilesEnabledTransformer
        ]

and

class MilesTransformer implements ValueTransformer<Double, Color> {

    override getModelType() {
        typeof(Double)
    }

    override getViewType() {
        typeof(Color)
    }

    override modelToView(Double valueFromModel) {
        if (valueFromModel > 100) Color.BLUE else Color.GREEN 
    }

    override viewToModel(Color valueFromView) {
        null
    }

}

Also tested with enabled binding.

All I had to do is change ControlObservableValue

public Object getValueType() {
    return SUPPORTED_ATTRIBUTES.get(attribute);
}

In arena-xtend project it is in conversion example.