| Summary: | TreeViewer doesn't accept IViewerLabelProvider as label provider | ||
|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Nicolas Bros <nicolas.bros> |
| Component: | UI | Assignee: | Platform-UI-Inbox <Platform-UI-Inbox> |
| Status: | RESOLVED WORKSFORME | QA Contact: | |
| Severity: | major | ||
| Priority: | P3 | CC: | tom.schindl |
| Version: | 3.6 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | |||
I don't think this is a regression I've take an look at e.g. version 1.60 of TreeViewer and there the same check is in TreeViewer.
I don't think one could have ever set a plain IViewerLabelProvider but had to write code like this:
-------8<-------
public class MyLabelProvider extends LabelProvider implements IViewerLabelProvider {
// ...
}
-------8<-------
I did not look into the internals so I can't say whether the omission of IViewerLabelProvider was done by intention.
Did you have code that worked in 3.2 but does not in 3.6, which would indicate that impression is wrong?
I assumed LabelProvider was only a convenience class, and implementing ILabelProvider or IViewerLabelProvider would be enough.
I'll give you more context: I'm trying to implement a "lazy" label provider, that computes labels in a background Job, and updates the label once the computation is done. For this, I want to avoid synchronous calls to getText, getImage, etc.
I tried extending LabelProvider and implementing IViewerLabelProvider, but ViewerLabel.setText doesn't seem to work in this code. The label stays "loading...":
public class MyLabelProvider extends LabelProvider implements IViewerLabelProvider {
public void updateLabel(final ViewerLabel label, final Object element) {
label.setText("loading...");
Job job = new Job("Update tree element") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
final String text = getText(element);
Display.getDefault().syncExec(new Runnable() {
public void run() {
label.setText(text);
}
});
return Status.OK_STATUS;
}
};
// delay by 3000 ms to test the lazy behavior
job.schedule(3000);
}
...
}
> Did you have code that worked in 3.2 but does not in 3.6,
> which would indicate that impression is wrong?
No, I'm trying to use IViewerLabelProvider, and seeing Bug 174355 I thought it could be a regression.
I found that the ViewerLabel passed to IViewerLabelProvider is not meant to be used asynchrously, so IViewerLabelProvider is not usable in my case. But I found that if I used a CellLabelProvider instead, I could update the ViewerCell asynchronously. Thanks for your help. I'm marking this bug as fixed, since the problems I had with IViewerLabelProvider seem to come from a misunderstanding on my part. IViewerLabelProvider can't be used this way - the viewerlabel instance is created and passed to the LabelProvider and afterwards it is forgotten.
You need to implement this your own somehow using. E.g.
public class MyLabelProvider extends CellLabelProvider {
private ColumnViewer viewer;
private Map<Object,String> labelCache = new HashMap<Object,String>();
public MyLabelProvider(ColumnViewer viewer) {
this.viewer = viewer;
}
public void update(ViewerCell cell) {
final Object o = cell.getElement();
if( labelCache.contains(o) ) {
cell.setText(labelCache.get(o));
} else {
Job job = new Job("Update tree element") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
final String text = getText(element);
Display.getDefault().syncExec(new Runnable() {
public void run() {
labelCache.set(o,text);
viewer.update(o);
}
});
return Status.OK_STATUS;
}
};
job.schedule(3000);
}
}
}
I'm closing this as works for me because I can't see a problem in our implementation.
(In reply to comment #3) > I found that the ViewerLabel passed to IViewerLabelProvider is not meant to be > used asynchrously, so IViewerLabelProvider is not usable in my case. > > But I found that if I used a CellLabelProvider instead, I could update the > ViewerCell asynchronously. > UUUhh - this might give you headaches - you can't cache the ViewerCell passed but need to make a clone. We are reusing the ViewerCell instance The code to directly work on ViewerCell in an Async way is: public void update(ViewerCell cell) { ViewerCell clone = cell.getViewerRow().getCell(cell.getColumnIndex()); // ... } Thanks. Very helpful! |
When I try to give a TreeViewer an IViewerLabelProvider as label provider, I get an AssertionFailedException. setLabelProvider doesn't seem to accept IViewerLabelProvider : public void setLabelProvider(IBaseLabelProvider labelProvider) { Assert.isTrue(labelProvider instanceof ITableLabelProvider || labelProvider instanceof ILabelProvider || labelProvider instanceof CellLabelProvider); ... } Bug 174355 seems to indicate this should work. Is this a regression? I'm using Helios (I20100608-0911)