ListProperty and ListBinding
Michael Heinrichs
michael.heinrichs at oracle.com
Wed Dec 21 08:06:00 PST 2011
Hi Richard,
as I did not get any other suggestion, my understanding is, that this proposal was accepted.
Thanks,
Michael
On 19.12.2011, at 16:46, Michael Heinrichs wrote:
> Yeah, I know. As you know, this is more of a hack, because size() and isEmpty(), which would feel more natural, are not available. Any other suggestion?
>
> - Michael
>
>
>
> On 17.12.2011, at 01:38, Richard Bair wrote:
>
>> As usual, I think this has been really well thought out. I get a little concerned over sizeProperty and emptyProperty just because it seems out of place. I'm good with this change though, and excited to have the ability to bind lists!
>>
>> Richard
>>
>> On Dec 15, 2011, at 6:49 AM, Michael Heinrichs wrote:
>>
>>> Hi,
>>>
>>> the last couple of days, I have mainly worked on the design to close the gap between the binding API and our observable collections. Here is the proposal. I am only talking about ObservableList, the other collections would be treaded similar.
>>>
>>> public interface ObservableListValue<E> extends ObservableObjectValue<ObservableList<E>>, ObservableList<E> {}
>>> public interface WritableListValue<E> extends WritableObjectValue<ObservableList<E>>, ObservableList<E> {}
>>>
>>> Notice that this is different than all other ObservableValues and WritableValues, that we have so far, because ObservableListValue and WritableListValue also extend ObservableList. A "real" ObservableList and implementations of ObservableListValue/WritableListValue have a lot in common, while playing with the prototype I often found myself writing the same functionality for both types. By making ObservableListValue/WritableListValue extend ObservableList, this became a lot easier. To implement the List functionality, ObservableListValue and WritableListValue simply forward the call to the referenced ObservableList. If they reference null, it is treaded like an immutable empty list.
>>>
>>> Next element in the hierarchy is the ListExpression. As with other expression classes, it is the super class of list bindings and list properties. It provides as much common functionality as possible without using any fields. This is left to the actual implementations. In more detail, it implements all List methods, adds some methods for the fluent API and defines two properties: size and empty. For size I also added a getSize() method to follow Java Bean conventions more closely. (The method isEmpty() is already defined in List.)
>>>
>>> public abstract class ListExpression<E> implements ObservableListValue<E> {
>>> public static <E> ListExpression<E> listExpression(final ObservableListValue<E> value) {...}
>>>
>>> public abstract int getSize();
>>> public abstract ReadOnlyIntegerProperty sizeProperty();
>>>
>>> public abstract ReadOnlyBooleanProperty emptyProperty();
>>>
>>> public ObjectBinding<E> valueAt(int index) {...}
>>> public ObjectBinding<E> valueAt(ObservableIntegerValue index) {...}
>>>
>>> public BooleanBinding isEqualTo(final ObservableList<?> other) {...}
>>> public BooleanBinding isNotEqualTo(final ObservableList<?> other) {...}
>>>
>>> public BooleanBinding isNull() {...}
>>> public BooleanBinding isNotNull() {...}
>>>
>>> public StringBinding asString() {...}
>>> }
>>>
>>> ListBinding allows to define custom list bindings exactly as you would for all other types:
>>>
>>> public abstract class ListBinding<E> extends ListExpression<E> implements Binding<ObservableList<E>> {...}
>>>
>>> The class ReadOnlyListProperty defines the functionality of a read only property that references a list. It provides as much functionality as possible without using a field. It is very similar to other read only properties, but in addition it has four new methods to define a content-binding. A content binding means, that the values are copied from one list to another. This way a read only property like Group.children can be bound to other lists.
>>>
>>> public abstract class ReadOnlyListProperty<E> extends ListExpression<E> implements ReadOnlyProperty<ObservableList<E>> {
>>> public void bindContentBidirectional(ObservableList<E> list) {...}
>>> public void unbindContentBidirectional(Object object) {...}
>>>
>>> public void bindContent(ObservableList<E> list) {...}
>>> public void unbindContent(Object object) {...}
>>> }
>>>
>>> The class ReadOnlyListPropertyBase is similar to other ReadOnlyPropertyBase classes. The main difference is, that there are two fireValueChangedEvent methods() that you have to call. The usual method without parameters needs to be called, if the reference changes, the second method that takes a Change object needs to be called, every time the referenced list itself changes:
>>>
>>> public abstract class ReadOnlyListPropertyBase<E> extends ReadOnlyListProperty<E> {
>>> protected void fireValueChangedEvent() {...}
>>> protected void fireValueChangedEvent(ListChangeListener.Change<? extends E> change) {...}
>>> }
>>>
>>> I think the classes ReadOnlyListWrapper, ListProperty, ListPropertyBase, and SimpleListProperty really work exactly like the classes for the other types.
>>>
>>> public class ReadOnlyListWrapper<E> extends SimpleListProperty<E> {...}
>>>
>>> public abstract class ListProperty<E> extends ReadOnlyListProperty<E> implements Property<ObservableList<E>>, WritableListValue<E> {...}
>>>
>>> public abstract class ListPropertyBase<E> extends ListProperty<E> {...}
>>>
>>> public class SimpleListProperty<E> extends ListPropertyBase<E> {...}
>>>
>>> The class Bindings will get a bunch of new methods:
>>> public static <E> void bindContentBidirectional(ObservableList<E> list1, ObservableList<E> list2) {...}
>>> public static void unbindContentBidirectional(Object obj1, Object obj2) {...}
>>>
>>> public static <E> void bindContent(List<E> list1, ObservableList<? extends E> list2) {...}
>>> public static void unbindContent(Object obj1, Object obj2) {...}
>>>
>>> public static <E> IntegerBinding size(final ObservableList<E> op) {...}
>>> public static <E> BooleanBinding isEmpty(final ObservableList<E> op) {...}
>>>
>>> public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final int index) {...}
>>> public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final ObservableIntegerValue index) {...}
>>>
>>> public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final int index) {...}
>>> public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final ObservableIntegerValue index) {...}
>>>
>>> public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final int index) {...}
>>> public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {...}
>>>
>>> public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final int index) {...}
>>> public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {...}
>>>
>>> public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final int index) {...}
>>> public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {...}
>>>
>>> public static LongBinding longValueAt(final ObservableList<? extends Number> op, final int index) {...}
>>> public static LongBinding longValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {...}
>>>
>>> public static StringBinding stringValueAt(final ObservableList<? extends Number> op, final int index) {...}
>>> public static StringBinding stringValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {...}
>>>
>>> Any thoughts?
>>>
>>> Thanks,
>>> Michael
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>
>
More information about the openjfx-dev
mailing list