first of all, thanks for your great work and framework. :)
I'm trying to use a RangedEventList which is wrapping a
SortedEventList in an ObjectListTable.
I notice some exceptions when I try to clear the REL after having
changed the starting point of the list.
Right now my code looks like this
sortedList = EventLists.sortedEventList();
rangedEventList = EventLists.rangedEventList(sortedList);
ObjectListTable objectListTable = new ObjectListTable(renderer,
rangedEventList);
public void setData(List modelObjects) {
rangedEventList.clear();
rangedEventList.setMaxSize(0);
rangedEventList.addAll(modelObjects);
int maxSize = modelObjects.size() > getPageSize() ? getPageSize():
modelObjects.size();
assert modelObjects.size() >= 0;
assert getPageSize() > 0;
assert maxSize >= 0;
rangedEventList.setMaxSize(maxSize);
}
I set the max size to 0 bc I read a thread where some other gwt-stuff
user recommended that in order to avoid poor performance. (or is there
some other workaround available?) It also seems that the clear on the
REL just removes the range from start to max size of the displayed
list, not the whole backup list. Should normally triggering the clear
on the REL also delete the wrapped SLT? I also tried to call a clear
on both, but this lead to other IndexOutOfBoundsException.
So question 1): how is clear supposed to work when you have wrapped
event lists?
I'm also trying to implement a grouping functionality for same table
cells in a column. Right now I check in my renderer if the value I'm
going to render has been already rendered in the iteration before and
if it is the same value just render and empty label to the table. I'm
not to happy with the implementation, as it is difficult to know the
start of the rendering iterations. (in order to reset the
valueOfLastRendering to null)
2) Do you have any experience with grouping same cells in a column?
Could you give me perhaps a hint?
I also noticed on IE6 that when I set the data into the REL (around
200 sometimes) the browser freezes up until the table has rendered.
(2-3 seconds, althought the REL is only set to display 12 items) Is
this a know effect? Are there some hints on how to get good
performance?
Thanks for any valuable information you can give me on that. And
thanks in advance for your help. :)
Dominik
I could track it down to the listchanged() method in the
ListTableListEventListener of the OLT. If I clear the items (I know
clear the items on my base list, which is a simple EL, wrapped by a
SEL, wrapped by a REL, set into the OLT as EL) the listchanged event
propagates up to the OLT and fails in the listchanged() method with
index out of bounds exception, as it removes all the table rows but
then the REL still has some more elements which it removes and sends
events to the OLT. For a workaround i included a check to avoid the
IOB exception.
} else if (listEvent.isRemoved()) {
for (int i = listEvent.getIndexEnd() - 1; i >=
listEvent.getIndexStart(); i--) {
if(tbodies.size() > i){
final ObjectListTableBodyGroup bodyGroup =
(ObjectListTableBodyGroup)tbodies.get(i);
disown(bodyGroup);
}
}
}
Perhaps this gives you more details. :)
Dominik
On 20 Apr., 08:29, dominik_steiner <Dominik.J.Stei...@googlemail.com>
wrote:
one more adition. It was necessary in order to make this setData()
work on the wrapped EL's to not only setMaxSize() on the REL but also
setStart() to 0.
I'm wondering if I'm doing sth wrong or if this is a know issue. :)
Dominik
On 20 Apr., 09:25, dominik_steiner <Dominik.J.Stei...@googlemail.com>
I came across the same exception with a SortedEventList + a
RangedEventList a few weeks ago and I've fixed it in the trunk and now
have a unit test to make sure it doesn't happen again. :-)
There have been a ton of bug fixes and performance improvements since
the last release. I've cut a preview release for you (and anyone else)
linked below. The only feature that I know currently doesn't behave
correctly is the "SteadyRangedEventList".
http://code.google.com/p/gwt-stuff/downloads/detail?name=GWT-Stuff-20070420-preview.jar
I think if you try the preview release you shouldn't need the
setMaxSize(0) to get decent performance. That hack came about because
ObjectListTable would try to render every little change the EventList
it was based on, setting maxSize to 0 would temporarily "mute" the
EventList preventing the OLT from doing unneeded work.
In the SVN trunk (and that preview release), EventLists are smart
enough to indicate when a batch of changes are coming and OLT is smart
enough to suspend updates while a batch of changes are in progress and
then only render the final results. If you have a REL with a maxSize
of 10 and you add 1,000 elements, before that may render all 1,000
elements and then remove 990 them to only show the correct 10. Now it
should be smart enough to only render the 10 elements that should be
displayed when all is said and done.
HTH, I'll get back to you on the other stuff shortly.
--
Sandy McArthur
"He who dares not offend cannot be honest."
- Thomas Paine
Wow, great news that you already cut a preview release. I'll try it out and tell you how it works.
Thousand thanks for your effort and your fast feedback. :)
Dominik
-----Ursprüngliche Nachricht-----
Von: gwt-...@googlegroups.com [mailto:gwt-...@googlegroups.com] Im Auftrag von Sandy McArthur
Gesendet: Freitag, 20. April 2007 16:07
An: gwt-...@googlegroups.com
Betreff: Re: RangedEventList + SortedEventList in ObjectListTable
Just tried it out and I can confirm that the error didn't occur again. But in order to have decent performance I had to keep the setMax(0) in my code.
Seems that the performance for big lists of item is not the best, in spite of using REL.
Just wanted to give this feedback before going into the weekend. Thanks for your great support and your help. I'll keep you updated on how this issue evolves. :)
Have a great weekend too
A few comments on that setData. It looks like the code doesn't match
your intentions:
1. The call to rangedEventList.clear(); will clear all the elements
visible to the rangedEventList. If there are more than maxSize
elements in the deeper sortedList or REL's start is greater than 0
then the call to rangedEventList.clear() will leave some elements
behind.
2. The extra logic to figure out a maxSize isn't needed, just call
rangedEventList.setMaxSize(getPageSize()); and you'll get the same
behavior.
3. While this isn't a problem here, (if you were using a
FilteredEventList it might be) the call to rangedEventList.addAll()
instead of on the deeper sortedList could have some side effects with
other EventList types.
It's best to work with the deepest EventList for the model and just
use the other EventList types to build up your view. This setData
method will probably work better:
eventList = EventLists.eventList();
sortedList = EventLists.sortedEventList(eventList);
rangedEventList = EventLists.rangedEventList(sortedList);
ObjectListTable objectListTable = new ObjectListTable(renderer,
rangedEventList);
public void setData(List modelObjects) {
eventList.clear();
//rangedEventList.setMaxSize(0);
eventList.addAll(modelObjects);
//rangedEventList.setMaxSize(getPageSize());
}
A plain EventList doesn't transform it's contents in any way so it
behaves just like a java.util.List. For that reason I prefer to work
with the plain EventList because it behaves in the most consistent
manner. For example Collections.shuffle(sortedEventList) will corrupt
the list contents, but Collections.shuffle(plainEventList) will work
fine.
> I set the max size to 0 bc I read a thread where some other gwt-stuff
> user recommended that in order to avoid poor performance. (or is there
> some other workaround available?) It also seems that the clear on the
> REL just removes the range from start to max size of the displayed
> list, not the whole backup list. Should normally triggering the clear
> on the REL also delete the wrapped SLT? I also tried to call a clear
> on both, but this lead to other IndexOutOfBoundsException.
> So question 1): how is clear supposed to work when you have wrapped
> event lists?
EventList.clear() should remove the "visible" elements of that list by
propagating the needed changes to a deeper list. So a clear() on a
FilteredEventList or RangedEventList may not remove all of the
elements in the deepest EventList.
> I'm also trying to implement a grouping functionality for same table
> cells in a column. Right now I check in my renderer if the value I'm
> going to render has been already rendered in the iteration before and
> if it is the same value just render and empty label to the table. I'm
> not to happy with the implementation, as it is difficult to know the
> start of the rendering iterations. (in order to reset the
> valueOfLastRendering to null)
> 2) Do you have any experience with grouping same cells in a column?
> Could you give me perhaps a hint?
I haven't done anything like that and ObjectListTable does not lend
itself to doing that because of the way it uses row groups.
If I were to group data elements and render them with a
ObjectListTable I'd probably do this:
1. Create a DataGroup object that contains a List of Data objects.
2. Create an EventList of those DataGroup objects.
3. Create a OLT.Renderer for the DataGroup elements.
4. For each Data object in a DataGroup, I'd render a TableRow. Within
the Render.render method I would have the logic to only render some
columns once per group.
> I also noticed on IE6 that when I set the data into the REL (around
> 200 sometimes) the browser freezes up until the table has rendered.
> (2-3 seconds, althought the REL is only set to display 12 items) Is
> this a know effect? Are there some hints on how to get good
> performance?
Like I said in the other email, the ObjectListTable with batch
EventList operations in the svn trunk have some more optimizations.
The reason setting the maxSize of a RangedEventList to zero helps, is
it had the effect of muting changes to deeper EventLists because none
of those changes would be visible.
The SortedEventList does not perform well. It can definitely use a
smarter algrothim and by it's very nature it can cause many little
ListEvents to be fired because what may have been one event for
elements 10-20 is now 10 events for elements scattered all over the
place. I haven't had the time to optimize it. If you can have the
elements in your list pre-sorted that will help a lot. In your setData
example you may be able to do away with the sortedEventList and call
Colelctions.sort(modelObjects) before calling eventList.addAll.
Thanks again for your kind support. :)
The comments you gave me helped me to restructure my code so that the OLT works now good with REL and SEL.
The only thing where I'm still stucked is the grouping functionality I want to implement on OLT.
I fear that the solution you suggested doesn't work in my case.
Let's assume that we have following table
Header1 | Header2
Foo1 | foo2
Foo1 | foo3
Foo2 | foo4
Foo2 | foo2
So what I want to do is display the table as
Header1 | Header2
Foo1 | foo2
| foo3
Foo2 | foo4
| foo2
So to just render on row after another and see if a value of a column is the same as the preceding one and if it is just render a blank cell.
I think that the DataGroup solution you mentioned doesn't work if I should also be able to sort the columns of the table.
Because then I would have in my example 2 DataGroup's, but if I want to sort the second column it would have to split the DataGroups (which I set up for column 1) and create other DataGroups based on the second column.
As mentioned, I just want to display a cell value, only if it is different from its preceding one. So what I did is implement this functionality in my renderer by adding a GroupColumn to it for the columns that I want to be grouped. A GroupColumn just remembers the last rendered cell value of a column and returns the new value based on it.
This all works like expected, but not if the table is redrawn. (eg if I sort it or page through it). Then even the first cell in a column is not drawn if it happens that is has the same value that the column remembered from the last rendering.
What I would need is the ability to discern if the renderer row (or bodygroup) is the first one in the table.
But the method
/**
* @return List of {@link ObjectListTableBodyGroup}
*/
final List/*<ObjectListTableBodyGroup>*/ getTbodies() {
return tbodies;
}
in OLT is not public, so there's no way to get a handle on it.
Is there any way to solve this issue? I'm a bit at a loss on how to tackle it. (besides grabbing the source and making the above mentioned method public)
Thanks for your kind help in advance. :)
Dominik
-----Ursprüngliche Nachricht-----
Von: gwt-...@googlegroups.com [mailto:gwt-...@googlegroups.com] Im Auftrag von Sandy McArthur
Gesendet: Freitag, 20. April 2007 18:49
An: gwt-...@googlegroups.com
Betreff: Re: RangedEventList + SortedEventList in ObjectListTable
OLT.getObjects() returns the EventList that a OLT is using to base it's rows on.
If (currentObj == olt.getObjects().get(0)) {
// rendering first row, reset state here
}
That may do what you want to do but I think it still has problems.
As you know, OLT wasn't designed to expose that level of row control
because it tries to be smart behind the scenes and only (re)render
what it needs to. If you have elements like:
a1
a2
a3
b1
b2
and you only render a cell for the first row in group "a" and then
group "b" etc... What if you removed "a1" from the List? OLT will
remove a1's rows but it won't try to update a2's row because the OLT
doesn't think it needs to be updated.
I have one more optimization to OLT I plan to implement someday which
will work against you for your desired usage. Right now when you
reorder the rows, pretty much every row group gets re-rendered. I plan
on making OLT be smarter about when it disposes of a rendered group of
rows by detecting when this row that was removed here will be added
over there and just moving the row group without re-rendering it. This
would screw up your fine grained row control too.
You could get around this by using an AttachRenderer and
detaching/attaching the OLT table to force the OLT to let your
AttachRenderer have access to each row. But that is rather ugly and
will have suboptimal performance.
Sounds like what you really need is some kind of GroupRenderer
interface or a GroupOLT implementation that does the extra work to
keep things straight like you want. I don't have the time to implement
that right now but if you submit a ASL 2.0 licensed patch I'll
seriously consider adding it to GWT-Stuff.
On 4/24/07, Steiner Dominik, (QX59311)
Ok, then it seems that the problem is more difficult than expected.
I had to restructured my code again because of performance issues. I did away with the REL because I only load the amount of data objects from the db which I'm displaying in the table. This means more round trips to the server but helps me to not load 1000 of objects from the server at once. (some sort of lazy REL would be the optimal solution though)
Concerning the grouping stuff, how does a ASL 2.0 licensed patch look like?
I'll checkout the latest src from subversion and see if I can implement a GroupOLT. If I succeed I'm more than willing to send you that implementation.
Thanks for your great support again. :)
Dominik
-----Ursprüngliche Nachricht-----
Von: gwt-...@googlegroups.com [mailto:gwt-...@googlegroups.com] Im Auftrag von Sandy McArthur
Gesendet: Dienstag, 24. April 2007 18:00
ASL 2.0 is the Apache Software License version 2.0, it doesn't "look"
a specific way but you need to ask your boss (if you haven't already)
to make sure that code you write while employed by them can be made
available to the public under the terms of the ASL 2.0 license.
At least in the USA, employers seem to have ownership of everything
semi-related to an employee's job regardless if it was created on the
clock or off the clock. Because of this I have an agreement in writing
with my employer where they waive any claims on code I write off the
clock and release as open source. To cover myself legally and anyone
else who uses GWT-Stuff code, I'd appreciate it that if you contribute
a patch to existing GWT-Stuff code you get verbal statement from your
boss that they won't claim ownership on it. If you were to contribute
new code not based on any other existing code I'd ask for a scan or
fax of a signed letter stating that they won't claim ownership on it.