FilteredList/SortedList
Martin Sladecek
martin.sladecek at oracle.com
Fri Jan 4 00:30:17 PST 2013
On 01/04/2013 05:08 AM, Jonathan Giles wrote:
> On 3/01/2013 10:10 p.m., Martin Sladecek wrote:
>>> 1) always in a sorted state
>> OK, this one should be simple.
>>
>> tableView.setItems(myList.transform().sorted( (o1,o2) ->
>> doSomeComparison(o1, o2) );
> Seems reasonable.
>>
>> Now this is sorting set explicitly by the developer, I understand you
>> might want to do some sorting based on columns. Then you can store
>> "items" internally (for the original order, they won't change) and
>> use some different field for the actual work, doing something like
>>
>> setCurrentItems(items.transform().sorted(currentColumnComparator));
> From a TableView perspective, I'm dealing in ObservableLists (not
> TransformationLists). I'm just wanting to clarify how you foresee
> things changing when this API is available.
>
> Presently when a sort occurs, I essentially create a Comparator (based
> on the Comparators of the sort columns), and then run
> FXCollections.sort(list, comparator) (or whatever the API is). This
> sorts the list in place.
>
> When we have transform() on all ObservableLists, is the recommended
> approach to always run a new list.transform().sorted(comparator) call
> every time the sort order changes, and then set the new result in the
> tableview items property?
Yes, but that would mean you'd have to create a filtered list on top of
it (again).
Maybe we should also have sorted(ObservableValue<? extends Comparator<?
super E>> comparator) to avoid recreation of the chain when
comparator/predicate changes.
>
> Also, I guess I can internally know that I can return to the original
> sort order when the tableview items list is an instance of a
> TransformationList, as then I can do something along the lines of
> tableView.setItems(tableView.getItems().getOriginalSource()). If the
> list is not a TransformationList, I will have to not support returning
> to the original sort order (as is the case now).
I think you should return to the original sort by using the list that
was passed to you as "items" if it's TransformationList or not. If the
developer uses a transformation list sorted by his own comparator, I
don't think we should change the order to some list underneath.
So thread items as ObservableList and do your transforms on top of it.
If you need to undo the transform, you can get back to "items" reference
to get the original sort order.
Now as I think of it, getOriginalSource() and getOriginalSourceIndex(int
index) might provide unexpected results in case when you called
transform on some TransformationList, thinking it's just a plain
ObservableList.
Both can be implemented using getSourceIndex() and getDirectSource() if
somebody needs it.
Instead, I'd like to have something like:
boolean isInTransformationChain(ObservableList<?> list);
int getSourceIndexFor(ObservableList<?> list, int index);
>>
>> To return back to the original order, this should be enough:
>>
>> setCurrentItems(items);
>>
>> To modify the table (like adding a new item), you would use items
>> directly. The actual position where to put the new item in "items"
>> can be determined by calling getOriginalSourceIndex(int index) on the
>> previous table item from "currentItems".
>>
>>> 2) able to filtered based on a user typing
>> Now this is something that was also problematic in the original API.
>> When the user types, the Predicate/Matcher changes, so originally we
>> had to keep the filteredlist reference and call
>> filteredList.setMatcher(matcher). As filtered list cannot rely on the
>> fact that the set matched by the new matcher is a subset of the
>> previous one, everything is processed again. Trying to create a
>> meaningful ListChangeListener.Change might result is a huge number of
>> sub-changes, so originally, I just fired a "everything was removed &
>> new items were added" change, which means whole table was rebuilt.
> If your concern is simply around the cost of rebuilding the table
> (rather than running the filter over all items), then I wouldn't worry
> about that. The TableView frequently rebuilds everything, and so that
> is a relatively cheap operation to perform.
>>
>> The same problems are in the new API -
>> * need to keep a reference to change the filter (in this case it's
>> the reference of the underlying list and a filtered() call on it when
>> the predicate changes)
>> * optimize cases where new predicate matches a superset/subset of
>> the previous predicate's set.
>>
>> What about having another method for "mutable" predicates, like this?
>>
>> filtered(ObservableValue<? extends Predicate<? super E>> predicate);
>>
>> The filtered list would bind to the ObservableValue (which could be a
>> property, expression, etc...) and refilter on change. As the user
>> types, you just need to update the property with the new Predicate.
> Sounds reasonable, but I'm really keen to test out these ideas in a
> simple UI app.
I will try to create some prototype.
>
> -- Jonathan
>
-Martin
More information about the openjfx-dev
mailing list