DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Data Engineering
  3. Databases
  4. Galileo: EMF-Databinding – Part 5

Galileo: EMF-Databinding – Part 5

Tom Schindl user avatar by
Tom Schindl
·
Jun. 28, 09 · Interview
Like (1)
Save
Tweet
Share
6.09K Views

Join the DZone community and get the full member experience.

Join For Free

though the main focus of this article is going to be the usage of the properties api to setup a tableviewer there are some important parts i didn’t explain in part 4 of this series, so this is using the properties api in master detail continued.

showing validation states

the first interesting thing is how to present validation errors to user. i’m personally not a friend of controldecorations but prefer to display the validation error in the form-header.
detail area error
this means the header presents an aggregation of all binding states and because this a quite common thing eclipse-databinding has built in support for this kind of thing.

private void addstatussupport(observablesmanager mgr,
final databindingcontext ctx)
{
aggregatevalidationstatus aggregatestatus =
new aggregatevalidationstatus(
ctx.getvalidationstatusproviders(),
aggregatevalidationstatus.max_severity
);

aggregatestatus.addvaluechangelistener(
new ivaluechangelistener()
{
public void handlevaluechange(valuechangeevent event)
{
handlestatechange(
(istatus)event.diff.getnewvalue(),
ctx
);
}
});
mgr.addobservable(aggregatestatus);
}

the above aggregates the validation states of all validation status providers. by the default there’s a provider for binding states attached to a databinding context but one can attach also custom ones which opens an interesting opportunity e.g. when used inconjunction with the emf-validation framework (probably a topic for another blog post in the next weeks).
the final task is to display the status to the user through the form header control like this

private void handlestatechange(istatus currentstatus,
databindingcontext ctx)
{
if (form.isdisposed() || form.gethead().isdisposed())
{
return;
}

if (currentstatus != null
&& currentstatus.getseverity() != istatus.ok)
{
int type = converttype(currentstatus.getseverity());

list<imessage> list = new arraylist<imessage>();
iterator< ? > it = ctx.getvalidationstatusproviders()
.iterator()
;

while (it.hasnext())
{
validationstatusprovider validationstatusprovider =
(validationstatusprovider)it.next()
;
final istatus status = (istatus)
validationstatusprovider.getvalidationstatus()
.getvalue()
;

if (!status.isok())
{
list.add(new imessage()
{
public control getcontrol()
{
return null;
}

public object getdata()
{
return null;
}

public object getkey()
{
return null;
}

public string getprefix()
{
return null;
}

public string getmessage()
{
return status.getmessage();
}

public int getmessagetype()
{
return converttype(status.getseverity());
}
});
}
}
form.setmessage("data invalid",
type,
list.toarray(new imessage [0])
);
}
else
{
form.setmessage(null);
}
}

master-detail, validation and null

that’s kind of a strange title but and not easy to track down but an undiscovered regression in eclipse-databinding since about 2 years and was discovered too late to get fixed in 3.5 timeframe.

in short the problem is that if you are producing an validation error in for a model attribute which initially had the value null the wrong value on the target (=ui-widget) is not cleared when modifing master. believe this sounds more complex than it is reality and bug 278301 holds an nice example to reproduce the behaviour.

nonetheless we need a working solution for now because of the location of the problem we won’t see a fix until 3.6 ships which is 1 year from now. i’m demonstrating in the following code a possible work-around but there are also other solutions. my solution uses the aggregatevalidationstatus-support and forces an target update when the master observable is changed and the current validation status is not ok .

public class util
{
public static void masterdetailfixup(
final databindingcontext ctx,
iobservablevalue master)
{
final aggregatevalidationstatus s =
new aggregatevalidationstatus(
ctx,
aggregatevalidationstatus.max_severity);

master.addchangelistener(new ichangelistener()
{

public void handlechange(changeevent event)
{
istatus status = (istatus)s.getvalue();
if (status != null && !status.isok())
{
ctx.updatetargets();
}
}
});
}
}

setting up a tableviewer with emf-databinding

let’s now take a look a the next topic for this post where we are going to set up a tableviewer using eclipse-databinding for jface/swt and emf. the tableviewer is taking up the complete lower right part of the application
table viewer

in part 3 we saw how to setup a treeviewer, in part 4 we saw how we are setting up a tableviewer without columns and as you’ll see setting up a tableviewer with multiple columns is very similar. let’s take a look at the code first

private void init(iviewsite site,
ctabfolder folder,
databindingcontext ctx,
editingdomain editingdomain,
iobservablevalue master)
{
final tableviewer viewer = new tableviewer(
folder, swt.full_selection
);

viewer.gettable().setheadervisible(true);
observablelistcontentprovider cp =
new observablelistcontentprovider()
;

{
iobservablemap[] attributemap = new iobservablemap [2];
attributemap[0] = emfeditproperties.value(
editingdomain,
featurepath.fromlist(
projectpackage.literals.committer_ship__person,
projectpackage.literals.person__lastname
)
).observedetail(cp.getknownelements());

attributemap[1] = emfeditproperties.value(
editingdomain,
featurepath.fromlist(
projectpackage.literals.committer_ship__person,
projectpackage.literals.person__firstname
)
).observedetail(cp.getknownelements());

tableviewercolumn column = new tableviewercolumn(
viewer, swt.none
);
column.getcolumn().settext("name");
column.getcolumn().setwidth(150);
column.setlabelprovider(
new genericmapcelllabelprovider(
"{0}, {1}",
attributemap
)
);
}

{
iobservablemap attributemap = emfeditproperties.value(
editingdomain,
projectpackage.literals.committer_ship__start
).observedetail(cp.getknownelements());

tableviewercolumn column = new tableviewercolumn(
viewer, swt.none
);
column.getcolumn().settext("start");
column.getcolumn().setwidth(100);
column.setlabelprovider(
new genericmapcelllabelprovider(
"{0,date,short}",
attributemap
)
);
}

{
iobservablemap attributemap = emfeditproperties.value(
editingdomain,
projectpackage.literals.committer_ship__end
).observedetail(cp.getknownelements());

tableviewercolumn column = new tableviewercolumn(
viewer, swt.none
);
column.getcolumn().settext("end");
column.getcolumn().setwidth(100);
column.setlabelprovider(
new genericmapcelllabelprovider(
"{0,date,short}",
attributemap
)
);
}

ilistproperty prop = emfeditproperties.list(
editingdomain,
projectpackage.literals.project__committers
);
viewer.setcontentprovider(cp);
viewer.setinput(prop.observedetail(master));

menumanager mgr = new menumanager();
mgr.add(
new action(
"hide historic committers",
iaction.as_check_box
)
{
@override
public void run()
{
if (ischecked())
{
viewer.addfilter(new viewerfilterimpl());
}
else
{
viewer.setfilters(new viewerfilter [0]);
}
}
});

viewer.getcontrol().setmenu(
mgr.createcontextmenu(viewer.getcontrol())
);
site.registercontextmenu(
activator.plugin_id + ".committers", mgr, viewer);
}

the only thing not already explained before is a special type of celllabelprovider which allows one to use messageformat-syntax to specify how the label is constructed. this label provider is not part of the jface-databinding implementation but written by me but it’s quite easy to implement.

public class genericmapcelllabelprovider
extends observablemapcelllabelprovider
{
private iobservablemap[] attributemaps;
private string messagepattern;

/**
* create a new label provider
* @param messagepattern the message pattern
* @param attributemaps the values to observe
*/
public genericmapcelllabelprovider(
string messagepattern,
iobservablemap... attributemaps)
{
super(attributemaps);
this.messagepattern = messagepattern;
this.attributemaps = attributemaps;
}

@override
public void update(viewercell cell)
{
object element = cell.getelement();
object[] values = new object [attributemaps.length];
int i = 0;
for (iobservablemap m : attributemaps)
{
values[i++] = m.get(element);
if (values[i - 1] == null)
{
cell.settext("");
return;
}
}
cell.settext(
messageformat.format(messagepattern, values)
);
}
}

that’s all we need to have a working tableviewer though there’s even more one can do with the databinding-api e.g. inline-editing is supported and there are helpers to setup viewers in even less lines of code.

from http://tomsondev.bestsolution.at

Galileo (operating system) master Column (database) Binding (linguistics) Label POST (HTTP) Property (programming) application IT

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How To Choose the Right Streaming Database
  • Testing Level Dynamics: Achieving Confidence From Testing
  • Microservices Testing
  • Using Swagger for Creating a PingFederate Admin API Java Wrapper

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: