(Re-)Binding SWT forms with WindowBuilder
A very common case in UI applications are forms which are bound to exchangeable model objects. For example, one might want to bind this address form in such a way that you can set a new
Address
object at any time with the UI reflecting that change:The plain old binding can be created easily using WindowBuilder:
The resulting code might look like this:
public class AddressViewPart extends ViewPart { private DataBindingContext bindingContext; private Address address; private Text textName; @Override public void createPartControl(Composite parent) { parent.setLayout(new GridLayout(3, false)); Label lblName = new Label(parent, SWT.NONE); lblName.setText(Messages.YetAnotherViewPart_lblName_text); textName = new Text(parent, SWT.BORDER); textName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); // ... bindingContext = initDataBindings(); } protected DataBindingContext initDataBindings() { DataBindingContext bindingContext = new DataBindingContext(); // IObservableValue textNameValue = WidgetProperties.text(SWT.Modify).observe(textName); IObservableValue addressNameValue = PojoProperties.value("name").observe(address); bindingContext.bindValue(textNameValue, addressNameValue, null, null); // return bindingContext; } }The tricky part is to bind this in such a way that the model object can be exchanged at any time. There are three possible ways:
1) Dispose bindings
The easiest way is to dispose all bindings and just re-bind whenever a new model object appears:
public class AddressViewPart extends ViewPart { // ... protected void setAddress(Address address) { this.address = address; if (bindingContext != null) bindingContext.dispose(); bindingContext = initDataBindings(); } // ... }Unfortunately, WindowBuilder insists on putting the
initDataBindings
call increatePartControl
. Also, if you are usingControlDecorationSupport
you will stumble upon Bug 341713 - DataBinding ControlDecorationSupport not disposed when DataBindingContext is disposed.2) Binding to a WritableValue
Another way is to use a detail binding to a
WritableValue
which can be changed at any time:public class AddressViewPart extends ViewPart { private WritableValue addressValue = new WritableValue(); protected void setAddress(Address address) { this.addressValue.setValue(address); } protected DataBindingContext initDataBindings() { // ... IObservableValue addressNameValue = PojoProperties.value("name").observeDetail(addressValue); // ... } }Such a Binding can be created in WindowBuilder:
3) Bean binding
Yet another way is to make the ViewPart itself a
Bean
withPropertyChangeSupport
:public class AddressViewPart extends ViewPart { private PropertyChangeSupport changes = new PropertyChangeSupport(this); private Address address; public Address getAddress() { return address; } public void setAddress(Address address) { changes.firePropertyChange("address", this.address, this.address = address); } public void addPropertyChangeListener(PropertyChangeListener l) { changes.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { changes.removePropertyChangeListener(l); } protected DataBindingContext initDataBindings() { //... IObservableValue addressNameValue = BeanProperties.value("address.name").observe(this); //... } }While I like this way conceptionally, in practice it has the problems of Java’s PropertyChangeSupport being cumbersome. Also, JFace Data Binding doesn’t allow to mix Beans and Pojos, so if the Address object in the example is a Pojo, one will get
NoSuchMethodException: Address.addPropertyChangeListener(java.beans.PropertyChangeListener)
. And there seems to be no way to generate such a binding in WindowBuilder.
(Re-)Binding SWT forms with WindowBuilder
via ralfebert.de
Tired Brain, Distractions, and Dehydration
"Man, I'm tired!". That was probably what my brain try to tell me this afternoon. But it was stil 3 pm and I have a list of to-do's waiting on my TiddlyWiki. So I took a little break and fired up the browser to visit my favourite blogs. I even watched an episode of my favourite anime at the break hour, though I know it's a bad idea. All what I get was an even more tired brain plus a pair of heavy eyes. Then I started to think about what was wrong with my brain. After a short walk I realized several things that might cause exhausting to my brain:
1. Bad diet. I woke late this morning and missed the breakfast. Even worse, I had instant noodles for lunch.
2. Dehydration. Long running, extense task swollen me away made me forget to drink water that was even at my desk already.
3. Distractions. Several chores distracted me, some even drove me away far enough, left me wondering "What was that?!". So tomorrow I'll try to revive my pomodoro timers to help me keep focused, though it costs 5 mins on every pmds.
1. Bad diet. I woke late this morning and missed the breakfast. Even worse, I had instant noodles for lunch.
2. Dehydration. Long running, extense task swollen me away made me forget to drink water that was even at my desk already.
3. Distractions. Several chores distracted me, some even drove me away far enough, left me wondering "What was that?!". So tomorrow I'll try to revive my pomodoro timers to help me keep focused, though it costs 5 mins on every pmds.
Reply Header on Thunderbird
Tadi saya mendapat pertanyaan dari salah satu karyawan mengenai Thunderbird yang tidak menyertakan Timestamp pada header reply-nya. Biasanya pada saat reply Thunderbird mengutip isi mail yang kita reply dengan header:
On wrote:
Tapi ternyata ada user yang headernya hanya:
wrote:
Untuk itu, ada yang perlu dirubah di konfigurasi Thunderbirdnya:
1. Menu Edit -> Preferences
2. Tab Advanced, tab General, Klik tombol "Config Editor..."
3. Muncul window About:Config, kemudian di field "Filter" isikan: mailnews.reply_header_type
4. Maka di tabel di bawahnya akan muncul item konfigurasi untuk mailnews.reply_header_type. Agar ada timestampnya, ubah value ini menjadi 2 dengan cara double-click item tadi dan ubah value nya menjadi 2.
5. Tutup window About:Config
6. Test dengan cara me-reply salah satu mail, maka timestamp akan muncul di header reply.
On
Tapi ternyata ada user yang headernya hanya:
Untuk itu, ada yang perlu dirubah di konfigurasi Thunderbirdnya:
1. Menu Edit -> Preferences
2. Tab Advanced, tab General, Klik tombol "Config Editor..."
3. Muncul window About:Config, kemudian di field "Filter" isikan: mailnews.reply_header_type
4. Maka di tabel di bawahnya akan muncul item konfigurasi untuk mailnews.reply_header_type. Agar ada timestampnya, ubah value ini menjadi 2 dengan cara double-click item tadi dan ubah value nya menjadi 2.
5. Tutup window About:Config
6. Test dengan cara me-reply salah satu mail, maka timestamp akan muncul di header reply.