TableView filtering and sorting (was Re: FilteredList/SortedList)
Martin Sladecek
martin.sladecek at oracle.com
Wed Jan 16 01:17:35 PST 2013
On 01/15/2013 07:18 PM, Richard Bair wrote:
>>> I also thing we didn't explore details on Richard's solution much. I have some questions about how the implementation would look like:
> Let me start by describing some of what we were thinking way back when we decided to sort the items list directly and not maintain a mapping in the control itself. There are a number of issues involved here.
>
> 1) In Swing, GlazedLists was quite popular and was based on the idea of decorating (or wrapping) lists within lists.
> 2) In Swing, TableModel etc. contained both view & model data (which sometimes led to oddities such as column information in both the TableModel and the TableColumnModel which would conflict at times)
> 3) In Swing, retrofitting with built in sorting / filtering as problematic due to the number of "index" APIs that had to be either view or model based
> 4) The popular thing in 2005 was to say that Swing should have just used beans & collections as its model, and a number of projects had APIs to do this by providing custom table models, list models, etc.
> 5) Sometimes you want a sort or filter to happen clear on the back-end (in the database for example) rather than on the control
>
> Our thinking was that by separating the sorting / filtering out into the ObservableList, we provide a much nicer solution to each of these design points.
>
> 1) GlazedLists was popular in Swing, so adopting a similar API design would be popular in FX. Right? :-)
> 2) By not having TableModel we don't have some view state in the model.
> 3) All indexes have intuitive meaning -- they map exactly to the indexes in the items list
> 4) By just having any old ObservableList as the data items, people are free to give us anything they want (even things that are not naturally a list but implement the ObservableList interface. For example, a RowSet or some other JDBC class could be wrapped by something implementing ObservableList). The design scales from the simplest samples to the most complex. And we didn't have to invent a new interface to achieve it.
> 5) Because we sort the supplied ObservableList directly, and because you can create an ObservableList implementation that wraps, say, a ResultSet or RowSet, you could get notification of a sort and perform it directly on the backend database. In this case some dev-level coordination will probably be needed (specify both the RowSetObservableList on the TableView and the comparators on the TableView columns such that when a sort happens you can determine which comparators are involved and construct the appropriate SQL query). This would require some additional API beyond just ObservableList (such as the FilteredList and SortedList we had almost shipped previously), such that the TableView can pass the comparators / predicates along.
Sounds reasonable.
>
> The sticking point seemed to be around how to handle add / remove on a FilteredList and SortedList. Specifically, the following are not always true:
>
> filteredList.add(10, item);
> assert item == filteredList.get(10);
>
> int size = filteredList.size();
> filteredList.add(item);
> assert size + 1 == filteredList.size();
>
> sortedList.add(10, item);
> assert item == sortedList.get(10);
>
> And other such related tests. IMO this doesn't matter unless you are using a FilteredList as a general purpose list and passing it to general purpose APIs and expecting it to behave in a standard way. But if there is one thing that is true about the Java collection APIs, it is that they are tailored to be practical rather than theoretical or elegant. And I think having a FilteredList or SortedList that is true to the spirit but not the letter of the List API is very practical, though maybe not as a general purpose construct. Maybe it is only really applicable to the UI world. Of course, we could just throw UnsupportedOperationException on add / remove, and instead have alternative methods that need to be called on these classes, and special case the FXCollections.sort so that it calls the right methods instead of add / remove, and that would seem to solve the issue?
We definitely should throw UnsupportedOperationException on list methods
and have a different interface with well-defined modification methods
for table/list/etc... models.
I doubt that implementing List methods would be practical. Maybe
controls team will use it in a safe way, but there are numerous ways how
something might just get terribly wrong:
* A new TransformationList will be added to the API, with some different
"practical" implementation of List API, breaking some control that
expected only sorted/filtered list behaviour and was safe with those two.
* Chains will behave differently than single transformation lists.
* I honestly wouldn't want to use such API in my own controls. You don't
know which transformation list you are dealing with, you don't know what
will work and what will not. Somebody might want to use FXCollections.
or Collections. method or some third party library, blowing up the whole
application unexpectedly when some specific order or content occurs.
-Martin
More information about the openjfx-dev
mailing list