Hi guys,
I'm experiencing an annoying problem with my SelectionModel beeing out
of synch in respect of the data stored in my ListDataProvider. Maybe
I'm doing something wrong, but I guess there is a suddle bug that
prevents to correctly update the selection model when the data in the
ListDataProvider change.
Below, I pasted a contrived working example that you can test to
expose the blamed behavior. Basically, you start with a table that
contains two rows. Then you add a new row (click the add button) and
you should see the "baz" row. Now select it and click remove.
Everything is fine, good. Do it once more: add a row and delete it
and... you get an expection, that is because of the assertion I've
introduce in the remove button click handler. Check the code and the
assertion is there only to expose the fact that the SelectionModel has
more than one eIement in the set... it actually holds two elements,
the currently selected row (which is good) and the one that was
deleted before....aaaargh?! So it looks like the the set of selected
elements hold in the SelectionModel is not in synch with the data hold
by the ListDataProvider, this despite all Foo's objects are different
(look at the FooKeys).
Opinions?
public class TestTable implements EntryPoint {
private static int counter = 0;
class Foo {
int id;
String text;
Foo(String text) {
this.id = ++TestTable.counter;
this.text = text;
}
}
class FooKeys implements ProvidesKey<Foo> {
@Override
public Object getKey(Foo item) {
return
item.id;
}
}
private final List<Foo> backend = new ArrayList<Foo>();
public void onModuleLoad() {
backend.add(new Foo("foo"));
backend.add(new Foo("bar"));
ProvidesKey<Foo> keys = new FooKeys();
final ListDataProvider<Foo> dataProvider = new
ListDataProvider<Foo>(keys);
final CellTable<Foo> table = new CellTable<Foo>(15, keys);
final MultiSelectionModel<Foo> selectionModel = new
MultiSelectionModel<Foo>(keys);
table.setSelectionModel(selectionModel);
dataProvider.addDataDisplay(table);
table.addColumn(new TextColumn<Foo>() {
@Override
public String getValue(Foo object) {
return object.text;
}
});
FlowPanel panel = new FlowPanel();
panel.add(table);
Button add = new Button("Add");
add.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Foo e = new Foo("baz");
List<Foo> res = new ArrayList<Foo>(backend);
res.add(e);
dataProvider.setList(res);
}
});
panel.add(add);
Button remove = new Button("Remove");
remove.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Set<Foo> els = selectionModel.getSelectedSet();
Foo foo = (Foo) els.toArray()[0];
assert (els.size() == 1); // this fails!
dataProvider.setList(backend);
}
});
panel.add(remove);
RootPanel.get().add(panel);
dataProvider.setList(new ArrayList<Foo>(backend));
}
}
-- Mirco