[JBoss Tools] - Manage SWTBot bits used by builds and developers
by Max Andersen
Max Andersen [http://community.jboss.org/people/max.andersen%40jboss.com] modified the document:
"Manage SWTBot bits used by builds and developers"
To view the document, visit: http://community.jboss.org/docs/DOC-16087
--------------------------------------------------------------
JBT/JBDS builds and JBT/JBDS SWTBot tests developers have to use the same version of SWTBot to ensure consistency.
Current version of SWTBot release used is specified in the target platform definition files (*.target) stored in SVN repository here: http://anonsvn.jboss.org/repos/jbosstools/trunk/build/target-platform/ http://anonsvn.jboss.org/repos/jbosstools/trunk/build/target-platform/.
There are two files available. *Multiple.target* contains all the source URLs from whichc the target is built. *Unified.target* contains the same IUs (installable units) but swaps out the URLs for our own JBoss mirror, located here: http://download.jboss.org/jbosstools/updates/target-platform/latest/ http://download.jboss.org/jbosstools/updates/target-platform/latest/
Open the .target file in your favourite Text or XML Editor, and search (CTRL-F or /) for "swtbot" to find the relevant IUs and their versions. ".feature.group" means "this feature and all its contained plugins".
h5. Updating JBoss Tools Hudson Builds To The Latest SWTBot Release
When SWTBot needs to be updated, verify your tests will still work with the latest release:
1. Compile complete SWTBot test suite in your workspace (using M2Eclipse) or via commandline (using Tycho) to verify updated SWTBot release does not break your tests.* If there are compilation errors, fix them or report them in JIRA. Test locally before committing changes to the tests back to SVN
2. Update SWTBot target file to specify proper SWTBot release version and commit it to SVN. 1. The easiest way to do this is to do a Maven build in the target-platform directory and generate the target platform repo locally. * cd ~/trunk/build/target-platform; mvn3 clean install -P get.*local.target*
2. This will fetch all the contents from the target platform, and update the .target files to use the versions found in the repo you generate locally. You can also update the .target files by hand, if you prefer, but the automated approach is easier and less error-prone.
3. As a result of running a build of the target platform locally, you can now *OPTIONALLY* use that repo instead of the remote one when running your builds. To activate this *local.target* repo, do this:* cd ~/trunk/build/parent; mvn3 clean install -P *local.target*
* cd ~/trunk/build; mvn3 clean install -P*+componentToBuild+*,*local.target*
(where +*componentToBuild*+ may be as, archives, esb, ... or as-bootstrap, archives-bootstrap, esb-bootstrap, ...)
While a build will run automatically in response to your committed changes, you can also kick one manually to save time:
* http://hudson.qa.jboss.com/hudson/job/jbosstools-3.2.0.Beta2.target-platf... http://hudson.qa.jboss.com/hudson/job/jbosstools-3.2.0.Beta2.target-platf... (currently require VPN)
h5. Updating JBoss Developer Studio ("Uberbuilder") Hudson Builds To The Latest SWTBot Release
1. Create a collection of new zips of the for the updated releases.
2. Create new md5sums.
3. Publish them somewhere that Hudson can see them
4. Update the properties file that JBDS uses to access them:
* http://svn.jboss.org/repos/devstudio/trunk/releng/org.jboss.ide.eclipse.r... http://svn.jboss.org/repos/devstudio/trunk/releng/org.jboss.ide.eclipse.r...
h5. Communication Strategy, or, Letting People Know About Changes
It's important to let others know that you've updated the SWTBot baseline against which everyone's tests will be run. Send an email to the mailing list here:
* jbosstools-dev < mailto:jbosstools-dev@lists.jboss.org jbosstools-dev(a)lists.jboss.org>
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-16087]
Create a new document in JBoss Tools at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
14 years, 11 months
[JBoss Tools] - How we use jface databinding in Deltacloud Tools
by Andre Dietisheim
Andre Dietisheim [http://community.jboss.org/people/adietish] modified the document:
"How we use jface databinding in Deltacloud Tools"
To view the document, visit: http://community.jboss.org/docs/DOC-15964
--------------------------------------------------------------
h1. Less code
If you use jface databinding to code your swt views in Eclipse you'll get spared from writing listeners and updating code by hand. JFace databinding offers very nice abstractions and automatisms that offer funcitonalities for the vast majority of the tasks where you have to listen for user input and update the view accordingly.
h1. *Premise*
If you implement a complex and highly dynamic UI in Eclipse you'll have to code many many many listener that wait for user actions. Those listeners mostly do nothing spectacular but update widgets and models in reaction to the user inputs. You end up with a lot of repetitive boilerplate code. UI frameworks in the non-java land (ex. http://qt.nokia.com/products/ Trolltechs QT) already have approaches that are far more elegant and slick than what we knew for Swing and SWT.
By luck Eclipse has progressed in this area (since 2005!) and offers neat abstractions that help a lot in this area and lead to far more concise and a less verbose implementations: Jface Databinding!
h1. Usecase
We had to implement a wizard page that allows a user to create a connection to a deltacloud server. The user has to supply a name, an url and the credentials for it.
http://community.jboss.org/servlet/JiveServlet/showImage/10530/cloud-conn... http://community.jboss.org/servlet/JiveServlet/downloadImage/10530/cloud-...
Sounds pretty simple at first sight. Looking closer at it you'll discover few buttons that shall be disabled if you enter inacurrate values. Furthermore we need to inform the user in a intuitive way and mark them by error decorations. The wizard page shall also show a global error message that reflects what's wrong in what the user entered.
http://community.jboss.org/servlet/JiveServlet/showImage/10531/invalid-ur... http://community.jboss.org/servlet/JiveServlet/downloadImage/10531/invali...
h1.
h1. Where's the source?
You may have a look at the implementation we discuss here at http://anonsvn.jboss.org/repos/jbosstools/trunk/deltacloud/plugins/org.jb... CloudConnectionPage.java
h1. *A first step: only use unique names*
Our GUI holds multiple connections to various deltacloud servers. The wizard allows you to edit existing connections or create new ones. The may of course not use names that are already picked for other connections.
http://community.jboss.org/servlet/JiveServlet/showImage/10533/duplicate-... http://community.jboss.org/servlet/JiveServlet/downloadImage/10533/duplic...
To be intuitive the wizard shall decorate the field that's invalid. The wizard shall also show you the full error text in the title area and disable the finish button if the user supplies invalid values.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-26-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-26...
h1. *How to decorate the name text field*
Let us take a first step and implement the code that will decorate our text field if we enter an name that's already used.
Jface databinding is a framework that is built upon the principle of model-view-controller (*MVC*). It connects a view to a model and transfers the values the user enters in the view to the model. It of course also operates the other way round and updates the view if new values are set to the model.
If a invalid value is detected while transfering it, an error is generated. If a user supplies a duplicate name to our connection, we'll be able show the error that occurs while transfering this name to the model.
h2. Let us create a model
As explained above, databinding operates on a model. We therefore need a model to store our values. We'll use a bean for that sake and provide notification capabilities with PropertyChangeSupport. PropertyChangeSupport, an implementation of the observer pattern, that's shipped with the jdk, allows jface databinding to observe value changes in our model. It will get notified as soon as we set new names to the model.
public class CloudConnectionModel extends ObservablePojo {
public static final String PROPERTY_NAME = "name";
private String name;
public CloudConnectionModel(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
getPropertyChangeSupport().
firePropertyChange(PROPERTY_NAME, this.name, this.name = name);
}
}
h2. Databinding, transfer the user input to our model!
We now have a model that holds our name. We now have to listen for user input on the text widget and set the model accordingly. We of course don't want to do that manually, we want databinding to provide this functionality.
h2. A bit of theory: what the hell are observables?
JFace databinding does not operate on the level of SWT listeners. It offers its own observer pattern. The main benefit here is that both ends of a *MVC* dont differ any longer, there are no SWT listeners to listen to changes in widgets nor PropertyChangeSupprt listeners to act upon changes in a model. Jface databinding observers *Observables*. Any participant to the jface databinding framework must implement the Observable interface. It of course provides adapters that adapt the various observer implementations that exist in the wild.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-26-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-26...
h2. Databdining, adapt those beasts!
We need an *Observable* for our model since our model uses PropertyChangeSupport to notify observers. Jface databinding offers a factory that adapts the PropertyChangeSupport we used. To tell databindirng to observe changes in the name property we do the following:
IObservableValue beanPropertyObservable =
BeanProperties.value(CloudConnectionModel.class, "name").observe(connectionModel)
We also need to provide an observable for the text widget, that allows the user to enter the name of the connection. We tell the appropriate observable factory it to listen to text modifications on the text widget:
h2. Now connect both ends
Now that we have observables on both ends (model and widget), we can tell databinding to connect both ends of our *MVC* and transfer the values between them. Databinding does that if we instruct the *DataBindingContext* to create a bind them:
DataBindingContext dbc = new DataBindingContext();
dbc.bindValue(
WidgetProperties.text(SWT.Modify).observe(nameText),
BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME)
.observe(connectionModel));
h2. But hey, inputs are not always valid
We now told databinding to transfer the name the user enters in our text widget to our model and to update the widget if we set a new name to the model. What we still miss is the ability to constrain user inputs.
http://community.jboss.org/servlet/JiveServlet/showImage/10542/convert-va... http://community.jboss.org/servlet/JiveServlet/downloadImage/10542/conver...
Jface databinding offers the ability to convert and validate values while it transfers values from one end to the other. In other words we can tell it to validate the name before it sets the user input to the model.Databinding uses *IValidator* instances for that sake:
private class CloudNameValidator implements IValidator {
The binding we created now has to be told to use our CloudNameValidator. We do that in a custom *UpdateValueStrategy*. As we saw above, databinding transfers values both ways: from the view to the model and the other way round. Databinding therefore offers strategies for both transfers. We only want to validate names that get transfered from the text widget, where the user may enter new names, to the model. We dont need validation where new names set in the model get propagated to the text widget. We therefore only set a single UpateValueStrategy and stick to the default (that does not validate) for the other strategy by indicating *null*.
>
> dbc.bindValue(
> WidgetProperties.text(SWT.Modify).observe(nameText),
> BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel),
> *new UpdateValueStrategy().setBeforeSetValidator(new CloudNameValidator()),*
> null
> );
>
>
h1. Disable finish button
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-26-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-26...
In non-technical pure logical terms there's a single trigger to all these markers: You entered a bad value to a field.
The wizard reacts by decorating the text field that holds a the duplicate name, it displays the error in the header and it disabled the Finish button.
Jface databinding offers a context that holds a global validity state for a form. If a form gets invalid, the golbal state gets invalid, too. A jface wizards is built upon several pages. Such a page is a form that may be globally valid or invalid.
> DataBindingContext dbc = new DataBindingContext();
To enable/disable the Finish button you now need to connect the wizard page to the DataBindingContext. Jface databinding will then enable/disable the Finish (or the Next Page button for instance) automatically for you. To bind the validity of the databinding context to the page validity, you only need 1 line of code:
> WizardPageSupport.create(this, dbc);
Jface databinding will now enable the finish button (or the next-page button) for you as soon as the form aka the databinding context is valid.
h2. WORK IN PROGRESS
h1. Conclusion
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-15964]
Create a new document in JBoss Tools at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
14 years, 11 months
[JBoss Tools] - How we use jface databinding in Deltacloud Tools
by Andre Dietisheim
Andre Dietisheim [http://community.jboss.org/people/adietish] modified the document:
"How we use jface databinding in Deltacloud Tools"
To view the document, visit: http://community.jboss.org/docs/DOC-15964
--------------------------------------------------------------
h1. Less code
If you use jface databinding to code your swt views in Eclipse you'll get spared from writing listeners and updating code by hand. JFace databinding offers very nice abstractions and automatisms that offer funcitonalities for the vast majority of the tasks where you have to listen for user input and update the view accordingly.
h1. *Premise*
If you implement a complex and highly dynamic UI in Eclipse you'll have to code many many many listener that wait for user actions. Those listeners mostly do nothing spectacular but update widgets and models in reaction to the user inputs. You end up with a lot of repetitive boilerplate code. UI frameworks in the non-java land (ex. http://qt.nokia.com/products/ Trolltechs QT) already have approaches that are far more elegant and slick than what we knew for Swing and SWT.
By luck Eclipse has progressed in this area (since 2005!) and offers neat abstractions that help a lot in this area and lead to far more concise and a less verbose implementations: Jface Databinding!
h1. Usecase
We had to implement a wizard page that allows a user to create a connection to a deltacloud server. The user has to supply a name, an url and the credentials for it.
http://community.jboss.org/servlet/JiveServlet/showImage/10530/cloud-conn... http://community.jboss.org/servlet/JiveServlet/downloadImage/10530/cloud-...
Sounds pretty simple at first sight. Looking closer at it you'll discover few buttons that shall be disabled if you enter inacurrate values. Furthermore we need to inform the user in a intuitive way and mark them by error decorations. The wizard page shall also show a global error message that reflects what's wrong in what the user entered.
http://community.jboss.org/servlet/JiveServlet/showImage/10531/invalid-ur... http://community.jboss.org/servlet/JiveServlet/downloadImage/10531/invali...
h1.
h1. Where's the source?
You may have a look at the implementation we discuss here at http://anonsvn.jboss.org/repos/jbosstools/trunk/deltacloud/plugins/org.jb... CloudConnectionPage.java
h1. *A first step: only use unique names*
Our GUI holds multiple connections to various deltacloud servers. The wizard allows you to edit existing connections or create new ones. The may of course not use names that are already picked for other connections.
http://community.jboss.org/servlet/JiveServlet/showImage/10533/duplicate-... http://community.jboss.org/servlet/JiveServlet/downloadImage/10533/duplic...
To be intuitive the wizard shall decorate the field that's invalid. The wizard shall also show you the full error text in the title area and disable the finish button if the user supplies invalid values.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-25-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-25...
h1. *How to decorate the name text field*
Let us take a first step and implement the code that will decorate our text field if we enter an name that's already used.
Jface databinding is a framework that is built upon the principle of model-view-controller (*MVC*). It connects a view to a model and transfers the values the user enters in the view to the model. It of course also operates the other way round and updates the view if new values are set to the model.
If a invalid value is detected while transfering it, an error is generated. If a user supplies a duplicate name to our connection, we'll be able show the error that occurs while transfering this name to the model.
h2. Let us create a model
As explained above, databinding operates on a model. We therefore need a model to store our values. We'll use a bean for that sake and provide notification capabilities with PropertyChangeSupport. PropertyChangeSupport, an implementation of the observer pattern, that's shipped with the jdk, allows jface databinding to observe value changes in our model. It will get notified as soon as we set new names to the model.
public class CloudConnectionModel extends ObservablePojo {
public static final String PROPERTY_NAME = "name";
private String name;
public CloudConnectionModel(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
getPropertyChangeSupport().
firePropertyChange(PROPERTY_NAME, this.name, this.name = name);
}
}
h2. Databinding, transfer the user input to our model!
We now have a model that holds our name. We now have to listen for user input on the text widget and set the model accordingly. We of course don't want to do that manually, we want databinding to provide this functionality.
h2. A bit of theory: what the hell are observables?
JFace databinding does not operate on the level of SWT listeners. It offers its own observer pattern. The main benefit here is that both ends of a *MVC* dont differ any longer, there are no SWT listeners to listen to changes in widgets nor PropertyChangeSupprt listeners to act upon changes in a model. Jface databinding observers *Observables*. Any participant to the jface databinding framework must implement the Observable interface. It of course provides adapters that adapt the various observer implementations that exist in the wild.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-25-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-25...
h2. Databdining, adapt those beasts!
We need an *Observable* for our model since our model uses PropertyChangeSupport to notify observers. Jface databinding offers a factory that adapts the PropertyChangeSupport we used. To tell databindirng to observe changes in the name property we do the following:
IObservableValue beanPropertyObservable =
BeanProperties.value(CloudConnectionModel.class, "name").observe(connectionModel)
We also need to provide an observable for the text widget, that allows the user to enter the name of the connection. We tell the appropriate observable factory it to listen to text modifications on the text widget:
h2. Now connect both ends
Now that we have observables on both ends (model and widget), we can tell databinding to connect both ends of our *MVC* and transfer the values between them. Databinding does that if we instruct the *DataBindingContext* to create a bind them:
DataBindingContext dbc = new DataBindingContext();
dbc.bindValue(
WidgetProperties.text(SWT.Modify).observe(nameText),
BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel));
l)
h2. But hey, inputs are not always valid
We now told databinding to transfer the name the user enters in our text widget to our model and to update the widget if we set a new name to the model. What we still miss is the ability to constrain user inputs.
http://community.jboss.org/servlet/JiveServlet/showImage/10542/convert-va... http://community.jboss.org/servlet/JiveServlet/downloadImage/10542/conver...
Jface databinding offers the ability to convert and validate values while it transfers values from one end to the other. In other words we can tell it to validate the name before it sets the user input to the model.Databinding uses *IValidator* instances for that sake:
>
> private class CloudNameValidator implements IValidator {
>
> public IStatus validate(Object value) {
> String connectionName = (String) value;
> if (DeltaCloudManager.getDefault().findCloud(connectionName) != null) {
> return *ValidationStatus.error("The name chosen in already in use");*
> } else {
> return ValidationStatus.ok();
> }
> }
> }
>
The binding we created now has to be told to use our CloudNameValidator. We do that in a custom *UpdateValueStrategy*. As we saw above, databinding transfers values both ways: from the view to the model and the other way round. Databinding therefore offers strategies for both transfers. We only want to validate names that get transfered from the text widget, where the user may enter new names, to the model. We dont need validation where new names set in the model get propagated to the text widget. We therefore only set a single UpateValueStrategy and stick to the default (that does not validate) for the other strategy by indicating *null*.
>
> dbc.bindValue(
> WidgetProperties.text(SWT.Modify).observe(nameText),
> BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel),
> *new UpdateValueStrategy().setBeforeSetValidator(new CloudNameValidator()),*
> null
> );
>
>
h1. Disable finish button
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-25-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-25...
In non-technical pure logical terms there's a single trigger to all these markers: You entered a bad value to a field.
The wizard reacts by decorating the text field that holds a the duplicate name, it displays the error in the header and it disabled the Finish button.
Jface databinding offers a context that holds a global validity state for a form. If a form gets invalid, the golbal state gets invalid, too. A jface wizards is built upon several pages. Such a page is a form that may be globally valid or invalid.
> DataBindingContext dbc = new DataBindingContext();
To enable/disable the Finish button you now need to connect the wizard page to the DataBindingContext. Jface databinding will then enable/disable the Finish (or the Next Page button for instance) automatically for you. To bind the validity of the databinding context to the page validity, you only need 1 line of code:
> WizardPageSupport.create(this, dbc);
Jface databinding will now enable the finish button (or the next-page button) for you as soon as the form aka the databinding context is valid.
h2. WORK IN PROGRESS
h1. Conclusion
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-15964]
Create a new document in JBoss Tools at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
14 years, 11 months
[JBoss Tools] - How we use jface databinding in Deltacloud Tools
by Andre Dietisheim
Andre Dietisheim [http://community.jboss.org/people/adietish] modified the document:
"How we use jface databinding in Deltacloud Tools"
To view the document, visit: http://community.jboss.org/docs/DOC-15964
--------------------------------------------------------------
h1. Less code
If you use jface databinding to code your swt views in Eclipse you'll get spared from writing listeners and updating code by hand. JFace databinding offers very nice abstractions and automatisms that offer funcitonalities for the vast majority of the tasks where you have to listen for user input and update the view accordingly.
h1. *Premise*
If you implement a complex and highly dynamic UI in Eclipse you'll have to code many many many listener that wait for user actions. Those listeners mostly do nothing spectacular but update widgets and models in reaction to the user inputs. You end up with a lot of repetitive boilerplate code. UI frameworks in the non-java land (ex. http://qt.nokia.com/products/ Trolltechs QT) already have approaches that are far more elegant and slick than what we knew for Swing and SWT.
By luck Eclipse has progressed in this area (since 2005!) and offers neat abstractions that help a lot in this area and lead to far more concise and a less verbose implementations: Jface Databinding!
h1. Usecase
We had to implement a wizard page that allows a user to create a connection to a deltacloud server. The user has to supply a name, an url and the credentials for it.
http://community.jboss.org/servlet/JiveServlet/showImage/10530/cloud-conn... http://community.jboss.org/servlet/JiveServlet/downloadImage/10530/cloud-...
Sounds pretty simple at first sight. Looking closer at it you'll discover few buttons that shall be disabled if you enter inacurrate values. Furthermore we need to inform the user in a intuitive way and mark them by error decorations. The wizard page shall also show a global error message that reflects what's wrong in what the user entered.
http://community.jboss.org/servlet/JiveServlet/showImage/10531/invalid-ur... http://community.jboss.org/servlet/JiveServlet/downloadImage/10531/invali...
h1.
h1. Where's the source?
You may have a look at the implementation we discuss here at http://anonsvn.jboss.org/repos/jbosstools/trunk/deltacloud/plugins/org.jb... CloudConnectionPage.java
h1. *A first step: only use unique names*
Our GUI holds multiple connections to various deltacloud servers. The wizard allows you to edit existing connections or create new ones. The may of course not use names that are already picked for other connections.
http://community.jboss.org/servlet/JiveServlet/showImage/10533/duplicate-... http://community.jboss.org/servlet/JiveServlet/downloadImage/10533/duplic...
To be intuitive the wizard shall decorate the field that's invalid. The wizard shall also show you the full error text in the title area and disable the finish button if the user supplies invalid values.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-23-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-23...
h1. *How to decorate the name text field*
Let us take a first step and implement the code that will decorate our text field if we enter an name that's already used.
Jface databinding is a framework that is built upon the principle of model-view-controller (*MVC*). It connects a view to a model and transfers the values the user enters in the view to the model. It of course also operates the other way round and updates the view if new values are set to the model.
If a invalid value is detected while transfering it, an error is generated. If a user supplies a duplicate name to our connection, we'll be able show the error that occurs while transfering this name to the model.
h2. Let us create a model
As explained above, databinding operates on a model. We therefore need a model to store our values. We'll use a bean for that sake and provide notification capabilities with PropertyChangeSupport. PropertyChangeSupport, an implementation of the observer pattern, that's shipped with the jdk, allows jface databinding to observe value changes in our model. It will get notified as soon as we set new names to the model.
public class CloudConnectionModel extends ObservablePojo {
public static final String PROPERTY_NAME = "name";
private String name;
public CloudConnectionModel(String name) { this.name = name; }
public String getName() { return name; }
public void setName(String name) { getPropertyChangeSupport().firePropertyChange(PROPERTY_NAME, this.name, this.name = name); }}
h2. Databinding, transfer the user input to our model!
We now have a model that holds our name. We now have to listen for user input on the text widget and set the model accordingly. We of course don't want to do that manually, we want databinding to provide this functionality.
h2. A bit of theory: what the hell are observables?
JFace databinding does not operate on the level of SWT listeners. It offers its own observer pattern. The main benefit here is that both ends of a *MVC* dont differ any longer, there are no SWT listeners to listen to changes in widgets nor PropertyChangeSupprt listeners to act upon changes in a model. Jface databinding observers *Observables*. Any participant to the jface databinding framework must implement the Observable interface. It of course provides adapters that adapt the various observer implementations that exist in the wild.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-23-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-23...
h2. Databdining, adapt those beasts!
We need an *Observable* for our model since our model uses PropertyChangeSupport to notify observers. Jface databinding offers a factory that adapts the PropertyChangeSupport we used. To tell databindirng to observe changes in the name property we do the following:
> IObservableValue beanPropertyObservable = BeanProperties.value(CloudConnectionModel.class, "name")
>
> IObservableValue beanPropertyObservable = BeanProperties.value(CloudConnectionModel.class, "name").observe(connectionModel)
>
We also need to provide an observable for the text widget, that allows the user to enter the name of the connection. We tell the appropriate observable factory it to listen to text modifications on the text widget:
> IObservableValue textObservable = WidgetProperties.text(SWT.Modify).observe(nameText)
h2. Now connect both ends
Now that we have observables on both ends (model and widget), we can tell databinding to connect both ends of our *MVC* and transfer the values between them. Databinding does that if we instruct the *DataBindingContext* to create a bind them:
> DataBindingContext dbc = new DataBindingContext();
>
> dbc.bindValue(
> WidgetProperties.text(SWT.Modify).observe(nameText),
> BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel));
>
h2. But hey, inputs are not always valid
We now told databinding to transfer the name the user enters in our text widget to our model and to update the widget if we set a new name to the model. What we still miss is the ability to constrain user inputs.
http://community.jboss.org/servlet/JiveServlet/showImage/10542/convert-va... http://community.jboss.org/servlet/JiveServlet/downloadImage/10542/conver...
Jface databinding offers the ability to convert and validate values while it transfers values from one end to the other. In other words we can tell it to validate the name before it sets the user input to the model.Databinding uses *IValidator* instances for that sake:
>
> private class CloudNameValidator implements IValidator {
>
> public IStatus validate(Object value) {
> String connectionName = (String) value;
> if (DeltaCloudManager.getDefault().findCloud(connectionName) != null) {
> return *ValidationStatus.error("The name chosen in already in use");*
> } else {
> return ValidationStatus.ok();
> }
> }
> }
>
The binding we created now has to be told to use our CloudNameValidator. We do that in a custom *UpdateValueStrategy*. As we saw above, databinding transfers values both ways: from the view to the model and the other way round. Databinding therefore offers strategies for both transfers. We only want to validate names that get transfered from the text widget, where the user may enter new names, to the model. We dont need validation where new names set in the model get propagated to the text widget. We therefore only set a single UpateValueStrategy and stick to the default (that does not validate) for the other strategy by indicating *null*.
>
> dbc.bindValue(
> WidgetProperties.text(SWT.Modify).observe(nameText),
> BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel),
> *new UpdateValueStrategy().setBeforeSetValidator(new CloudNameValidator()),*
> null
> );
>
>
h1. Disable finish button
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-23-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-23...
In non-technical pure logical terms there's a single trigger to all these markers: You entered a bad value to a field.
The wizard reacts by decorating the text field that holds a the duplicate name, it displays the error in the header and it disabled the Finish button.
Jface databinding offers a context that holds a global validity state for a form. If a form gets invalid, the golbal state gets invalid, too. A jface wizards is built upon several pages. Such a page is a form that may be globally valid or invalid.
> DataBindingContext dbc = new DataBindingContext();
To enable/disable the Finish button you now need to connect the wizard page to the DataBindingContext. Jface databinding will then enable/disable the Finish (or the Next Page button for instance) automatically for you. To bind the validity of the databinding context to the page validity, you only need 1 line of code:
> WizardPageSupport.create(this, dbc);
Jface databinding will now enable the finish button (or the next-page button) for you as soon as the form aka the databinding context is valid.
h2. WORK IN PROGRESS
h1. Conclusion
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-15964]
Create a new document in JBoss Tools at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
14 years, 11 months
[JBoss Tools] - How we use jface databinding in Deltacloud Tools
by Andre Dietisheim
Andre Dietisheim [http://community.jboss.org/people/adietish] modified the document:
"How we use jface databinding in Deltacloud Tools"
To view the document, visit: http://community.jboss.org/docs/DOC-15964
--------------------------------------------------------------
h1. Less code
If you use jface databinding to code your swt views in Eclipse you'll get spared from writing listeners and updating code by hand. JFace databinding offers very nice abstractions and automatisms that offer funcitonalities for the vast majority of the tasks where you have to listen for user input and update the view accordingly.
h1. *Premise*
If you implement a complex and highly dynamic UI in Eclipse you'll have to code many many many listener that wait for user actions. Those listeners mostly do nothing spectacular but update widgets and models in reaction to the user inputs. You end up with a lot of repetitive boilerplate code. UI frameworks in the non-java land (ex. http://qt.nokia.com/products/ Trolltechs QT) already have approaches that are far more elegant and slick than what we knew for Swing and SWT.
By luck Eclipse has progressed in this area (since 2005!) and offers neat abstractions that help a lot in this area and lead to far more concise and a less verbose implementations: Jface Databinding!
h1. Usecase
We had to implement a wizard page that allows a user to create a connection to a deltacloud server. The user has to supply a name, an url and the credentials for it.
http://community.jboss.org/servlet/JiveServlet/showImage/10530/cloud-conn... http://community.jboss.org/servlet/JiveServlet/downloadImage/10530/cloud-...
Sounds pretty simple at first sight. Looking closer at it you'll discover few buttons that shall be disabled if you enter inacurrate values. Furthermore we need to inform the user in a intuitive way and mark them by error decorations. The wizard page shall also show a global error message that reflects what's wrong in what the user entered.
http://community.jboss.org/servlet/JiveServlet/showImage/10531/invalid-ur... http://community.jboss.org/servlet/JiveServlet/downloadImage/10531/invali...
h1. h1. Where's the source?
You may have a look at the implementation we discuss here at CloudConnectionPage.java (http://anonsvn.jboss.org/repos/jbosstools/trunk/deltacloud/plugins/org.jb...)
h1. *A first step: only use unique names*
Our GUI holds multiple connections to various deltacloud servers. The wizard allows you to edit existing connections or create new ones. The may of course not use names that are already picked for other connections.
http://community.jboss.org/servlet/JiveServlet/showImage/10533/duplicate-... http://community.jboss.org/servlet/JiveServlet/downloadImage/10533/duplic...
To be intuitive the wizard shall decorate the field that's invalid. The wizard shall also show you the full error text in the title area and disable the finish button if the user supplies invalid values.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-18-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-18...
h1. *How to decorate the name text field*
Let us take a first step and implement the code that will decorate our text field if we enter an name that's already used.
Jface databinding is a framework that is built upon the principle of model-view-controller (*MVC*). It connects a view to a model and transfers the values the user enters in the view to the model. It of course also operates the other way round and updates the view if new values are set to the model.
If a invalid value is detected while transfering it, an error is generated. If a user supplies a duplicate name to our connection, we'll be able show the error that occurs while transfering this name to the model.
h2. Let us create a model
As explained above, databinding operates on a model. We therefore need a model to store our values. We'll use a bean for that sake and provide notification capabilities with PropertyChangeSupport. PropertyChangeSupport, an implementation of the observer pattern, that's shipped with the jdk, allows jface databinding to observe value changes in our model. It will get notified as soon as we set new names to the model.
>
>
> public class CloudConnectionModel extends ObservablePojo {
> public static final String PROPERTY_NAME = "name";
> private String name;
> public CloudConnectionModel(String name) { this.name = name; }
> public String getName() { return name; }
> public void setName(String name) { getPropertyChangeSupport().firePropertyChange(PROPERTY_NAME, this.name, this.name = name); }}
h2. Databinding, transfer the user input to our model!
We now have a model that holds our name. We now have to listen for user input on the text widget and set the model accordingly. We of course don't want to do that manually, we want databinding to provide this functionality.
h2. A bit of theory: what the hell are observables?
JFace databinding does not operate on the level of SWT listeners. It offers its own observer pattern. The main benefit here is that both ends of a *MVC* dont differ any longer, there are no SWT listeners to listen to changes in widgets nor PropertyChangeSupprt listeners to act upon changes in a model. Jface databinding observers *Observables*. Any participant to the jface databinding framework must implement the Observable interface. It of course provides adapters that adapt the various observer implementations that exist in the wild.
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-18-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-18...
h2. Databdining, adapt those beasts!
We need an *Observable* for our model since our model uses PropertyChangeSupport to notify observers. Jface databinding offers a factory that adapts the PropertyChangeSupport we used. To tell databindirng to observe changes in the name property we do the following:
> IObservableValue beanPropertyObservable = BeanProperties.value(CloudConnectionModel.class, "name")
>
> IObservableValue beanPropertyObservable = BeanProperties.value(CloudConnectionModel.class, "name").observe(connectionModel)
>
We also need to provide an observable for the text widget, that allows the user to enter the name of the connection. We tell the appropriate observable factory it to listen to text modifications on the text widget:
> IObservableValue textObservable = WidgetProperties.text(SWT.Modify).observe(nameText)
h2. Now connect both ends
Now that we have observables on both ends (model and widget), we can tell databinding to connect both ends of our *MVC* and transfer the values between them. Databinding does that if we instruct the *DataBindingContext* to create a bind them:
> DataBindingContext dbc = new DataBindingContext();
>
> dbc.bindValue(
> WidgetProperties.text(SWT.Modify).observe(nameText),
> BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel));
>
h2. But hey, inputs are not always valid
We now told databinding to transfer the name the user enters in our text widget to our model and to update the widget if we set a new name to the model. What we still miss is the ability to constrain user inputs.
http://community.jboss.org/servlet/JiveServlet/showImage/10542/convert-va... http://community.jboss.org/servlet/JiveServlet/downloadImage/10542/conver...
Jface databinding offers the ability to convert and validate values while it transfers values from one end to the other. In other words we can tell it to validate the name before it sets the user input to the model.Databinding uses *IValidator* instances for that sake:
>
> private class CloudNameValidator implements IValidator {
>
> public IStatus validate(Object value) {
> String connectionName = (String) value;
> if (DeltaCloudManager.getDefault().findCloud(connectionName) != null) {
> return *ValidationStatus.error("The name chosen in already in use");*
> } else {
> return ValidationStatus.ok();
> }
> }
> }
>
The binding we created now has to be told to use our CloudNameValidator. We do that in a custom *UpdateValueStrategy*. As we saw above, databinding transfers values both ways: from the view to the model and the other way round. Databinding therefore offers strategies for both transfers. We only want to validate names that get transfered from the text widget, where the user may enter new names, to the model. We dont need validation where new names set in the model get propagated to the text widget. We therefore only set a single UpateValueStrategy and stick to the default (that does not validate) for the other strategy by indicating *null*.
>
> dbc.bindValue(
> WidgetProperties.text(SWT.Modify).observe(nameText),
> BeanProperties.value(CloudConnectionModel.class, CloudConnectionModel.PROPERTY_NAME).observe(connectionModel),
> *new UpdateValueStrategy().setBeforeSetValidator(new CloudNameValidator()),*
> null
> );
>
>
h1. Disable finish button
http://community.jboss.org/servlet/JiveServlet/showImage/102-15964-18-105... http://community.jboss.org/servlet/JiveServlet/downloadImage/102-15964-18...
In non-technical pure logical terms there's a single trigger to all these markers: You entered a bad value to a field.
The wizard reacts by decorating the text field that holds a the duplicate name, it displays the error in the header and it disabled the Finish button.
Jface databinding offers a context that holds a global validity state for a form. If a form gets invalid, the golbal state gets invalid, too. A jface wizards is built upon several pages. Such a page is a form that may be globally valid or invalid.
> DataBindingContext dbc = new DataBindingContext();
To enable/disable the Finish button you now need to connect the wizard page to the DataBindingContext. Jface databinding will then enable/disable the Finish (or the Next Page button for instance) automatically for you. To bind the validity of the databinding context to the page validity, you only need 1 line of code:
> WizardPageSupport.create(this, dbc);
Jface databinding will now enable the finish button (or the next-page button) for you as soon as the form aka the databinding context is valid.
h2. WORK IN PROGRESS
h1. Conclusion
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-15964]
Create a new document in JBoss Tools at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
14 years, 11 months