Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 116862 - [DataBinding] Problem with converter from double to String
Summary: [DataBinding] Problem with converter from double to String
Status: RESOLVED WORKSFORME
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Boris Bokowski CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-11-17 08:25 EST by Boris Bokowski CLA
Modified: 2006-06-13 15:51 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Boris Bokowski CLA 2005-11-17 08:25:09 EST
Konstantin Scheglov reported the following problem (originally in bug 104570):

I think I found problem with this version: eclipse-SDK-I20051116-1332-win32.zip 
When I try to bind "double" property to Text it throws exception:

org.eclipse.jface.databinding.BindingException: Converter does not apply to
model type. Expected: double, actual: class java.lang.String
	at org.eclipse.jface.databinding.internal.ValueBinding.<init>(ValueBinding.java:61)
	at
org.eclipse.jface.databinding.internal.DataBindingContext.bind(DataBindingContext.java:399)
	at
org.eclipse.jface.databinding.internal.DataBindingContext.bind(DataBindingContext.java:454)
	at
org.eclipse.jface.databinding.internal.DataBindingContext.bind(DataBindingContext.java:511)
	at ru.nlmk.Test.createContents(Test.java:87)
	at ru.nlmk.Test.open(Test.java:45)
	at ru.nlmk.Test.main(Test.java:34)

  I am not sure, but problem can be in ValueBinding, because when I change this:

		if (!converter.getModelType().equals(model.getValueType())) {
			throw new BindingException(
					"Converter does not apply to model type. Expected: " + model.getValueType()
+ ", actual: " + converter.getModelType()); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (!converter.getTargetType().equals(target.getValueType())) {
			throw new BindingException(
					"Converter does not apply to target type. Expected: " +
target.getValueType() + ", actual: " + converter.getTargetType()); //$NON-NLS-1$
//$NON-NLS-2$
		}

to this:

		if (!converter.getTargetType().equals(model.getValueType())) {
			throw new BindingException(
					"Converter does not apply to model type. Expected: " + model.getValueType()
+ ", actual: " + converter.getTargetType()); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (!converter.getModelType().equals(target.getValueType())) {
			throw new BindingException(
					"Converter does not apply to target type. Expected: " +
target.getValueType() + ", actual: " + converter.getModelType()); //$NON-NLS-1$
//$NON-NLS-2$
		}

  it works.

  See also source code for bean and GUI below.

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class User {
	private String m_firstName;

	private String m_lastName;

	private double m_age;

	private PropertyChangeSupport m_propertyListeners = new PropertyChangeSupport(
			this);

	public String getFirstName() {
		return m_firstName;
	}

	public void setFirstName(String firstName) {
		m_firstName = firstName;
	}

	public String getLastName() {
		return m_lastName;
	}

	public void setLastName(String lastName) {
		String oldLastName = m_lastName;
		m_lastName = lastName;
		m_propertyListeners.firePropertyChange("lastName", oldLastName,
				m_lastName);
	}

	public double getAge() {
		return m_age;
	}

	public void setAge(double age) {
		Double oldAge = new Double(m_age);
		m_age = age;
		m_propertyListeners
				.firePropertyChange("age", oldAge, new Double(m_age));
	}

	@Override
	public String toString() {
		return "(" + m_firstName + ", " + m_lastName + ", " + m_age + ")";
	}

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

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


import org.eclipse.jface.databinding.DataBinding;
import org.eclipse.jface.databinding.IDataBindingContext;
import org.eclipse.jface.databinding.PropertyDescription;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Test {

	private Text m_txtAge;

	private Text m_txtLast;

	private Text m_txtFirst;

	protected Shell shell;

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Test window = new Test();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setLayout(new GridLayout());
		shell.setSize(439, 312);
		shell.setText("SWT Application");

		final User user = new User();
		user.setFirstName("Konstantin");
		user.setLastName("Scheglov");
		user.setAge(12);
		System.out.println("before: " + user);

		m_txtFirst = new Text(shell, SWT.BORDER);
		m_txtFirst.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
				true, false));

		m_txtLast = new Text(shell, SWT.BORDER);
		m_txtLast.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
				true, false));

		m_txtAge = new Text(shell, SWT.BORDER);
		m_txtAge.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
				true, false));

		IDataBindingContext bindingContext = DataBinding.createContext(shell);
		try {
			bindingContext.bind(m_txtFirst, new PropertyDescription(user,
					"firstName"), null);
			bindingContext.bind(m_txtLast, new PropertyDescription(user,
					"lastName"), null);
			bindingContext.bind(m_txtAge, new PropertyDescription(user, "age"),
					null);
		} catch (Throwable e) {
			e.printStackTrace();
		}

		final Button showButton = new Button(shell, SWT.NONE);
		showButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				System.out.println("current: " + user);
			}
		});
		showButton.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
				true, false));
		showButton.setText("Show!");

		final Button changeButton = new Button(shell, SWT.NONE);
		changeButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				user.setLastName("" + System.currentTimeMillis());
				user.setAge(18);
			}
		});
		changeButton.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
				false, false));
		changeButton.setText("Change!");
	}

}
Comment 1 Gili Mendel CLA 2005-11-18 08:11:03 EST
The converters use the target/model designation given that they work both way.

The IBindSupportFactory, and IDataBindingContext use the from/to designation for
validators given that they work one way.

It will make it less confusing if it is consistent - as the construction or the
defaulting to one, an 2 arg. lookup.
Comment 2 Boris Bokowski CLA 2006-06-13 15:51:50 EDT
This should be fixed now that we have only one-way converters, and support for converting to and from primitive types. Please reopen if I am wrong.