SWT CalendarCombo - bind

lumo

Top Contributor
weiss jemand wie ich das calendarcombo binden kann?

hab das jetzt schon mit SWT.TEXT gemacht, da klappts bestens,
nur beim calendarcombo wirft's mir eine exception
Code:
java.lang.IllegalArgumentException: Widget [org.eclipse.nebula.widgets.calendarcombo.CalendarCombo] is not supported.
	at org.eclipse.jface.internal.databinding.swt.WidgetDelegatingValueProperty.notSupported(WidgetDelegatingValueProperty.java:23)
	at org.eclipse.jface.internal.databinding.swt.WidgetTextWithEventsProperty.doGetDelegate(WidgetTextWithEventsProperty.java:61)
	at org.eclipse.core.databinding.property.value.DelegatingValueProperty.getDelegate(DelegatingValueProperty.java:54)
	at org.eclipse.core.databinding.property.value.DelegatingValueProperty.observe(DelegatingValueProperty.java:80)
	at org.eclipse.jface.internal.databinding.swt.WidgetDelegatingValueProperty.observe(WidgetDelegatingValueProperty.java:35)
	at org.eclipse.jface.databinding.swt.SWTObservables.observeText(SWTObservables.java:255)

ich dachte eigentlich dass die ganzen nebula komponenten swt extenden, und somit hatte ich gedacht dass das auf die selbe art funktioniert... ist aber leider nicht so
und google hat bis jetzt nur geschwiegen (oder ich falsch gesucht - korrigiert mich?)
 
G

Gast2

Gast
Wenn keins ObserableValue gibts schreibst dir selber eins. Hier ist ein Beispiel von CDateTime

Java:
/*******************************************************************************
 * Copyright (c) 2005, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * [url=http://www.eclipse.org/legal/epl-v10.html]Eclipse Public License - Version 1.0[/url]
 *
 * Contributors:
 *     Peter Centgraf - initial API and implementation - bug #177013
 *     Jeremy Dowdall - updating
 *******************************************************************************/
package org.eclipse.nebula.jface.cdatetime;

import java.util.Date;

import org.eclipse.core.databinding.observable.Diffs;
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.nebula.widgets.cdatetime.CDateTime;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;

/**
 * An implementation of the DataBindings IObservableValue interface for the Nebula
 * CDateTime control.
 * 
 * @author pcentgraf
 * @since Mar 8, 2007
 */
public class CDateTimeObservableValue extends AbstractObservableValue {
	
	/**
	 * The Control being observed here.
	 */
	protected final CDateTime dateTime;
	
	/**
	 * Flag to prevent infinite recursion in {@link #doSetValue(Object)}.
	 */
	protected boolean updating = false;
	
	/**
	 * The "old" selection before a selection event is fired.
	 */
	protected Date currentSelection;

	private SelectionListener listener = new SelectionListener() {
		public void widgetDefaultSelected(SelectionEvent e) {
			//Skip
		}
		public void widgetSelected(SelectionEvent e) {
			if (!updating) {
				Date newSelection = CDateTimeObservableValue.this.dateTime.getSelection();
				fireValueChange(Diffs.createValueDiff(currentSelection, newSelection));
				currentSelection = newSelection;
			}
		}
	};
	
	/**
	 * Observe the selection property of the provided CDateTime control.
	 * @param dateTime the control to observe
	 */
	public CDateTimeObservableValue(CDateTime dateTime) {
		this.dateTime = dateTime;
		currentSelection = dateTime.getSelection();
		this.dateTime.addSelectionListener(listener);
	}

	@Override
	public synchronized void dispose() {
		dateTime.removeSelectionListener(listener);
		super.dispose();
	}

	protected Object doGetValue() {
		if(!dateTime.isDisposed()) {
			return dateTime.getSelection();
		}
		return null;
	}
	
	protected void doSetValue(Object value) {
		if(value instanceof Date && !dateTime.isDisposed()) {
			Date oldValue;
			Date newValue;
			try {
				updating = true;
				oldValue = dateTime.getSelection();
				newValue = (Date) value;
				dateTime.setSelection(newValue);
				currentSelection = newValue;
				fireValueChange(Diffs.createValueDiff(oldValue, newValue));
			} finally {
				updating = false;
			}
		}
	}

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

lumo

Top Contributor
danke
hab das jetzt schnell aufs calendarcombo umgeschrieben (zum testen bin ich noch nicht gekommen -> muss jetzt weg)

wenn ichs getestet hab poste ich den code hier :)
 

lumo

Top Contributor
okay, der code sollte passen, allerdings hab ich mit dem converter jetzt ein kleines problem:

Code:
org.eclipse.core.databinding.BindingException: converter does not convert to type class java.util.Date Expected: class java.lang.String, actual: class java.util.Date
	at org.eclipse.core.databinding.UpdateStrategy.checkAssignable(UpdateStrategy.java:97)
	at org.eclipse.core.databinding.UpdateValueStrategy.fillDefaults(UpdateValueStrategy.java:278)
	at org.eclipse.core.databinding.DataBindingContext.bindValue(DataBindingContext.java:161)

er sagt er convertiert nicht nach date, erwartet einen string und wundert sich warum ein date drin ist?! hä?? 'n converter für date wird wohl nach date convertieren und nicht nach string um nen date zurückzugeben?!

und hier noch der observer teil...
Java:
import java.util.Calendar;

import org.eclipse.core.databinding.observable.Diffs;
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.nebula.widgets.calendarcombo.CalendarCombo;
import org.eclipse.nebula.widgets.calendarcombo.ICalendarListener;
 
/**
 * An implementation of the DataBindings IObservableValue interface for the Nebula
 * CalendarCombo control.
 * 
 * @author lumo
 * @since 30.09.2010
 */
public class CalendarComboObservableValue extends AbstractObservableValue {
    
    /**
     * The Control being observed here.
     */
    protected final CalendarCombo cc;
    
    /**
     * Flag to prevent infinite recursion in {@link #doSetValue(Object)}.
     */
    protected boolean updating = false;
    
    /**
     * The "old" selection before a selection event is fired.
     */
    protected Calendar currentDate;
 
    
    private ICalendarListener listener = new ICalendarListener() {
		
		@Override
		public void popupClosed() {
			// SKIP
		}
		
		@Override
		public void dateRangeChanged(Calendar arg0, Calendar arg1) {
			if (!updating) {
            	Calendar newDate = CalendarComboObservableValue.this.cc.getDate();
                fireValueChange(Diffs.createValueDiff(currentDate, newDate));
                currentDate = newDate;
            }
		}
		
		@Override
		public void dateChanged(Calendar arg0) {
			if (!updating) {
            	Calendar newDate = CalendarComboObservableValue.this.cc.getDate();
                fireValueChange(Diffs.createValueDiff(currentDate, newDate));
                currentDate = newDate;
            }
		}
	};
    
    /**
     * Observe the selection property of the provided CalendarCombo control.
     * @param cc the control to observe
     */
    public CalendarComboObservableValue(CalendarCombo cc) {
        this.cc = cc;
        currentDate = cc.getDate();
        this.cc.addCalendarListener(listener);
    }
 
    @Override
    public synchronized void dispose() {
        cc.removeCalendarListener(listener);
        super.dispose();
    }
 
    protected Object doGetValue() {
        if(!cc.isDisposed()) {
            return cc.getDate();
        }
        return null;
    }
    
    protected void doSetValue(Object value) {
        if(value instanceof Calendar && !cc.isDisposed()) {
        	Calendar oldValue;
        	Calendar newValue;
            try {
                updating = true;
                oldValue = cc.getDate();
                newValue = (Calendar) value;
                cc.setDate(newValue);
                currentDate = newValue;
                fireValueChange(Diffs.createValueDiff(oldValue, newValue));
            } finally {
                updating = false;
            }
        }
    }
 
    public Object getValueType() {
        return Calendar.class;
    }
}
 
G

Gast2

Gast
Mach mal ein komplettes Beispiel...
Aber mich wundert schon dass du ein Calendar Objekt setzt und kein Date Objekt?
 

lumo

Top Contributor
ein komplettes beispiel?

die bindingfactory erstellt und managed bindings (selbst implementiert)
bc = bindable component
300 = delay
obj = das objekt das gebunden werden soll
date = die variable im obj die gebunden werden soll,
und dann kommen die converter...

Java:
		BindingFactory.getInstance().bind(bc1, 300, obj, "date",
				new Calendar2String(), new String2Calendar());
Java:
public DataBindingContext bind(final Bindable bindable, Integer delay,
			final Object obj, final String fieldName,
			final IConverter target2modelConverter,
			final IConverter model2targetConverter) {

		if (delay == null || delay < 0) {
			delay = 300;
		}
		UpdateValueStrategy target2modelStrategy = null;
		UpdateValueStrategy model2targetStrategy = null;

		if (target2modelConverter != null & model2targetConverter != null) {
			target2modelStrategy = new UpdateValueStrategy();
			target2modelStrategy.setConverter(target2modelConverter);
			model2targetStrategy = new UpdateValueStrategy();
			model2targetStrategy.setConverter(model2targetConverter);
		}

		IObservableValue observableValue = null;

		// text field should be bind - this will be the most used case
		if (bindable.getControl() instanceof Text) {
			observableValue = SWTObservables.observeDelayedValue(delay,
					SWTObservables.observeText(bindable.getControl(),
							SWT.Modify));
		} else if (bindable.getControl() instanceof CalendarCombo) {
			// add a observer
			observableValue = new CalendarComboObservableValue(
					(CalendarCombo) bindable.getControl());
		} else {
			System.err.println(String.format(
					"This type (%s) is not supported by %s yet.", bindable
							.getControl().getClass().getSimpleName(),
					BindingFactory.class.getSimpleName()));
		}

		final IObservableValue objNameObserveValue = BeansObservables
				.observeValue(obj, fieldName);

		// BIND THE VALUE
		Binding b = null;
		Class<?> clazz = (Class<?>) observableValue.getValueType();

		if (clazz.equals(String.class)) {
			System.out.println("------ String");
			b = bindingContext.bindValue(observableValue, objNameObserveValue,
					target2modelStrategy, model2targetStrategy);
		} else if (clazz.equals(Calendar.class)) {
			System.out.println("------ Calendar");
			b = bindingContext.bindValue(observableValue, objNameObserveValue,
					target2modelStrategy, model2targetStrategy);
		} else {
			System.out
					.println("this class is not supported by the bindingfactory yet: "
							+ observableValue.getValueType().toString());
		}
	return bindingContext;
	}




hier noch die zwei converter die ich implementiert habe
string2calendar & calendar2string
Java:
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;

import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.internal.databinding.conversion.DateConversionSupport;

public class String2Calendar extends DateConversionSupport implements
		IConverter {
	private final DateFormat format = DateFormat
			.getDateInstance(DateFormat.DEFAULT);

	public Object convert(final Object fromObject) {
		if (fromObject == null || fromObject.toString().trim().length() == 0) {
			return null;
		}
		try {
			Calendar c = Calendar.getInstance();
			c.setTime((Date) format.parseObject(fromObject.toString()));
			return c;
		} catch (final ParseException e) {
			System.err.println(String.format(
					"error parsing a date (%s) \n\t%s", String2Calendar.class
							.getSimpleName(), e.getMessage()));
		}
		return null;
	}

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

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

Java:
import java.text.DateFormat;
import java.util.Calendar;

import org.eclipse.core.databinding.conversion.IConverter;

public class Calendar2String implements IConverter {
	private final DateFormat format = DateFormat
			.getDateInstance(DateFormat.DEFAULT);

	public Object convert(final Object fromObject) {
		if (fromObject == null) {
			return null;
		}
		Calendar c = (Calendar) fromObject;
		return format.format(c.getTime());
	}

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

	@Override
	public Object getToType() {
		return String.class;
	}
}
 
Zuletzt bearbeitet:
G

Gast2

Gast
Du sollst ein einfaches "kleines Beispiel" und nicht deine komplette Klassen posten dein Fehler wird in den Converter sein... Schon mal ohne Converter probiert?
 

lumo

Top Contributor
eieieiei, ich brauch den converter in dem fall ja gar nicht...
denn im obj ist der datentyp calendar, und das calendarcombo gibt die daten als calendar zurück...
:oops:

trotzdem versteh ich nicht, warum der converter nicht funktioniert
edit: weil ich versuche string->calendar umzuwandeln und aber schon calendar habe -> der string ist in echt ein calendar - :autsch: - AH JETZT JA!
 
G

Gast2

Gast
okay zu spät ;)... aber so sollte ein bsp aussehen^^...


Java:
package a;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Calendar;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.Diffs;
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.nebula.widgets.calendarcombo.CalendarCombo;
import org.eclipse.nebula.widgets.calendarcombo.ICalendarListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
	public static final String ID = "A.view";

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		final PersonModel model = new PersonModel();
		final CalendarCombo button = new CalendarCombo(parent, SWT.PUSH);

		Button button2 = new Button(parent, SWT.PUSH);
		button2.setText("Model value");
		button2.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				System.out.println(model.getDate());
				
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		DataBindingContext bindingContext = new DataBindingContext();
		bindingContext.bindValue(new CalendarComboObservableValue(button),
				BeanProperties.value(PersonModel.class, "date").observe(model),null,null);
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		
	}
	
	public static class PersonModel {
		private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
				this);
		public void addPropertyChangeListener(String propertyName,
				PropertyChangeListener listener) {
			propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
		}

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

		private Calendar date;

		public void setDate(Calendar date) {
			propertyChangeSupport.firePropertyChange("date", this.date,
					this.date = date);

		}

		public Calendar getDate() {
			return date;
		}

	}
	
	public static class CalendarComboObservableValue extends AbstractObservableValue {
	    
	    /**
	     * The Control being observed here.
	     */
	    protected final CalendarCombo cc;
	    
	    /**
	     * Flag to prevent infinite recursion in {@link #doSetValue(Object)}.
	     */
	    protected boolean updating = false;
	    
	    /**
	     * The "old" selection before a selection event is fired.
	     */
	    protected Calendar currentDate;
	 
	    
	    private ICalendarListener listener = new ICalendarListener() {
	        
	        @Override
	        public void popupClosed() {
	            // SKIP
	        }
	        
	        @Override
	        public void dateRangeChanged(Calendar arg0, Calendar arg1) {
	            if (!updating) {
	                Calendar newDate = CalendarComboObservableValue.this.cc.getDate();
	                fireValueChange(Diffs.createValueDiff(currentDate, newDate));
	                currentDate = newDate;
	            }
	        }
	        
	        @Override
	        public void dateChanged(Calendar arg0) {
	            if (!updating) {
	                Calendar newDate = CalendarComboObservableValue.this.cc.getDate();
	                fireValueChange(Diffs.createValueDiff(currentDate, newDate));
	                currentDate = newDate;
	            }
	        }
	    };
	    
	    /**
	     * Observe the selection property of the provided CalendarCombo control.
	     * @param cc the control to observe
	     */
	    public CalendarComboObservableValue(CalendarCombo cc) {
	        this.cc = cc;
	        currentDate = cc.getDate();
	        this.cc.addCalendarListener(listener);
	    }
	 
	    @Override
	    public synchronized void dispose() {
	        cc.removeCalendarListener(listener);
	        super.dispose();
	    }
	 
	    protected Object doGetValue() {
	        if(!cc.isDisposed()) {
	            return cc.getDate();
	        }
	        return null;
	    }
	    
	    protected void doSetValue(Object value) {
	        if(value instanceof Calendar && !cc.isDisposed()) {
	            Calendar oldValue;
	            Calendar newValue;
	            try {
	                updating = true;
	                oldValue = cc.getDate();
	                newValue = (Calendar) value;
	                cc.setDate(newValue);
	                currentDate = newValue;
	                fireValueChange(Diffs.createValueDiff(oldValue, newValue));
	            } finally {
	                updating = false;
	            }
	        }
	    }
	 
	    public Object getValueType() {
	        return Calendar.class;
	    }
	}
}
 

Oben