TableView filtering and sorting (was Re: FilteredList/SortedList)
swpalmer at gmail.com
Mon Jan 14 21:46:00 PST 2013
On 2013-01-14, at 10:11 PM, Richard Bair <richard.bair at oracle.com> wrote:
> On Jan 14, 2013, at 5:34 AM, Martin Sladecek <martin.sladecek at oracle.com> wrote:
>> On 01/10/2013 06:00 PM, Richard Bair wrote:
>>>> This doesn't have to break. All existing APIs are View-based. The current API for setting the items in the table is assumed to be setting the View, since when sorting it is updated in place.
>>>> There currently isn't any API for setting a model independent of the view, so one could be added. As long as the list added via the new method is not modified in place and the existing APIs set and return the items in "view" order.. all is well.
>>>> We need about four new APIs.
>>>> void setModel(ObservableList)
>>>> ObservableList getModel()
>>>> int getModelIndex(int viewIndex)
>>>> int getViewIndex(int modelIndex)
>>>> Sorting happens internally on the "Items" list, not the "Model" list.
>>>> If you call setModel(), a view list ("Items") is created for you and anything you may have set it to previously is toast.
>>>> If you call setItems(), indicating you wish to use the old API, the model could be forced to null, or a copy of the view list could be made in it's place. But you have two APIs that are overlapping slightly. That's just what you have to live with.
>>>> Any existing APIs continue to work based on view coordinates.
>>> So, the obvious issues:
>>> - As you mentioned the APIs overlap slightly. Or even if they don't the names are ambiguous so there is some sadness that would just have to be lived with
>>> - Because "items" is mutable, we actually have all the same problems Martin is trying to avoid. For example, if the list has been sorted, and you insert an item at a specific location in the items list, then what happens? Once the TableView supports UI for filtering, and you insert and item into items, then what happens?
>> The items would be mutable only when set directly using the setItems() methods. It would be user's responsibility to handle that correctly, if he provided a mutable list as "items".
>> Otherwise, the items would be created immutable for the provided model.
> That would break current users who can:
>> It's the same with your approach. We have either mutable list as items (set directly) or an immutable one (wrapper). There will be some ambiguity in the API and different approach will have to be used when model is set directly, or in your case, when a wrapper is used.
>> E.g. if we want to scroll to a specific element (which is, as you called it, a model based method).
>> When view == model, which in both cases means setItems was called with our list, then you can use scrollTo directly with the index from our list.
> Really I want a mutable ObservableList for filtering. That was the original intent :-(. Or do you mean we have to deal with unmodifiable lists in either case?
>> In case we do not wish TableView to modify our model, we need to treat "model-based" API differently. In case of what Scott proposed, it would be like this (say we have some the index stored in listIndex property):
>> ...in case of your API:
>> WrapperList wrapper = new WrapperList(list);
>> I'm afraid we have no other option if we do not wish to deprecate the items property.
> Right, in my case where there is only "items", the items are always view based and if you want to map you use an API on the list vs on the control. But none of the mapping concepts are on any control, just relegated to the list.
Say we keep the one "view" list. How do we gain control of it so that the TableView isn't mucking it up behind our (program's) back? How is the link back to our model list maintained? The current big problem is that the control is sorting the list internally. If none of the mapping concepts are on any control, how is the control connected to the column sorting feature?
I don't really think it is all that bad if, for example, getItems().setAll(...) threw in the case of my "setModel" proposal. If you didn't set the items list yourself you shouldn't assume it is mutable. More specifically if you *elected to use the alternative model-based API*, then you would know of course that the items or "view" list is off-limits. You should not be surprised if it throws when you try to modify it directly. Surly the concept of a read-only ObservableList isn't that scary. Let the control keep the mutable version of the view list private and expose a read-only wrapper via getItems() in the case of a call to setModel(). Once setModel is documented as replacing the Items list with a read-only view, things make sense.
Otherwise just make an entirely new control and get it right from the beginning. I.e. make "Table", a model-based version that never tries to mess with your list directly and truly only "views" it... Everyone can make fun of the fact that the control names appear to have been switched and move on... :-)
More information about the openjfx-dev