FilteredList/SortedList
Richard Bair
richard.bair at oracle.com
Tue Jan 8 09:49:56 PST 2013
On Jan 8, 2013, at 9:36 AM, Martin Sladecek <martin.sladecek at oracle.com> wrote:
> On 01/08/2013 05:59 PM, Richard Bair wrote:
>> I don't think it is that complicated. The TableView would continue to sort the items just as it does today. The difference is that the developer can get the original unsorted list and perform view/model mapping by asking the list itself.
>>
>> That is:
>>
>> WrappedList items = new WrappedList(original);
>> tableView.setItems(items);
>>
>>
>> At any point, my "original" list is going to be untouched. The WrappedList has no comparator or other means for sorting / filtering, it just contains the mapping (say for sake of argument it extends from TransformationList so we can talk in terms of that API, but it wasn't created by sorted / filtered methods). The TableView continues to sort the WrappedList as it does today. In fact, at this point, the TableView would know no more about the WrappedList than it does about a normal observable list.
>
> I don't understand how this would work. Currently, the TableView calls FXCollections.sort on items.
> So the WrappedList would be some special kind of ObservableList which would be treated differently by FXCollections.sort and it will just store the new order of elements and provide mapping for it (through TransformationList interface?) ?
Why would it be treated differently? What happens if you take a transformation list and remove an element from it? Does it also remove the element from the underlying list? What happens if you rearrange the items in a transformation list? Does it also rearrange the items in the original list? My assumption was that if you were to do either of these things, it simply updates the mapping. So FXCollections.sort doesn't do anything special -- the TransformationList on the other hand does. When it is told to move items around, it will end up updating its mapping.
> This means all items list that we do not want to be manipulated by a TableView will have to be wrapped in WrappedList, otherwise they will be sorted directly.
> So for a modifiable lists we would get:
>
> tableView.setItems(list); // sorted directly
> tableView.setItems(wrapped = new WrappedList(list)); // wrapped maintains the mapping, list is not modified
>
> ... and for unmodifiable lists (which might be also something user wants to display in a TableView):
>
> tableView.setItems(list); // not possible to use sorting, will this throw some exception? (Jonathan?)
> tableView.setItems(wrapped = new WrappedList(list)); // wrapped maintains the mapping, list is not modified
Right, that's the idea.
> also it might not be clear that you have to use WrappedList for this purpose at first glance.
But, you won't get any bugs by accidentally using the wrong index. You will always map correctly from properties on the TableView back to your list. If you find you don't want your original list sorted, then you can discover the solution (wrap it). On the other hand, by having the mapping occur within the TableView, you are guaranteed to have provided an API which will produce bugs. Its just literally guaranteed to happen.
>>
>>> tableView.setItems(list);
>>> TransformationList items = tableView.getViewList();
>>> // Do something with items
>>>
>>> You don't have to care about Comparator (it's internally managed by the TableView). As we have no special interface for SortedList, there's no way how to change the Comparator through the TransformationList interface. Only table can do that, in case it used sorted(ObservableValue<Comparator>) method.
>>> If somebody wants some different order, sorted() can be used explicitly:
>>>
>>> tableView.setItems(list.sorted(basicOrderComparator));
>>> TransformationList items = tableView.getItemsList();
>>>
>>> Column order (if defined & used) always takes precedence over the basicOrderComapartor (as we basically have two sorted lists), and the user-defined order is used when column ordering is turned off.
>>>
>>> No need to special case anything in TableView, no differences in behaviour for different items types (plain ObservableList vs. SortedList), no changes to the provided list.
>> This is a much nicer suggestion than having the model-to-view conversion methods on Tableview itself (at least it is wrapped up in the TransformationList). However the downside is that the developer still has to know that none of the other indexes provided in the TableView API are in the same transform space as the original list of items -- all indexes are in view indexes (which is different than it is today, meaning all existing code is broken), and that the view list must be used for all index based operations, not the original list.
>>
>> Richard
> What about deprecating items property, leaving the behavior as-is + introducing setModel() and getViewList() for the newer code?
I think that is a reasonable approach if the pain is so acute that we have to resort to it. Obviously doing something like this has to be last-resort because it messes with the API (i.e.: any deprecation of API has to be done with great care because either we are going to keep this deprecated API around forever for compatibility in which case we've created two ways of doing the same thing which is not a good idea, or we actually will break people in a couple release time and the amount of pain that is going to cause has to be worth it).
So far I don't see why the design of wrapping the source list (if you don't want it to be sorted) is such a bad thing that it would require this level of pain? Especially because this is not an unexpected problem but was planned for from the start :-). It is normal that any API will have people that prefer it and people who don't prefer it -- if we're going to undertake something as painful as deprecation & replacement of API (and doing so with an API which is guaranteed to be the source of application bugs), then we had better do so because there is no way to acceptably make the current design work. Is there a reason the current design won't work?
Richard
More information about the openjfx-dev
mailing list