The list container differs from the list widget in several ways. First it is optimised for performance instead of a memory usage, and second, the list container supports both homogenous and heterogeneous lists. In terms of implementation the list widget only uses one widget to represent all of the items in the list while the list container will create separate widgets for each visible item.
The list container widget is attached to a model. The model will be responsible for supplying the widgets for the list. The model can either be a ListContainerModel that will create the list items on demand or a TypedListModel/ListModel that contains all the pre-populated widgets.
The list container widget is implemented in terms of a set of widgets visible through a "window". Each widget in the set will represent a visible list item. For performance reasons some extra non-visible, adjacent, list items would also be populated to help live scrolls perform well. The "window" in this case is simply a container.
To better explain how the list container is implemented consider the following diagram:
List container design overview - ^ - - - - - - | I 0 I -<--|-->+ I I | - - - - - - <------=-------- Offset 0 (The zero offset can move, zero is where V I 1 I | PROP_TOPINDEX was last set via IWidget_SetProperty) + I I | - - - - - - | I 2 I | I I | - - - - - - | I 3 I | I I |<------- Window offset ___________ | | 4 | | | | | ___________ | | 5 | | | | | ___________ | | 6 | | --|---------|-- - - | ___________ | | | | 7 | | | | | | | | | ___________ | | | | 8 | | | | | | | |<--- Window size | ___________ | | | | 9 | | | | | | | | | ___________ | | | | 10 | | | --|---------|-- - ___________ I 11 I I I - - - - - -
This diagram represents a list with 12 elements. In this diagram the list items in "solid" lines (items 4-10) represent list items that have been created, and the list item in "broken" lines (items 0 - 3 and 11) represent items that haven't been created. The list was initialized with PROP_TOPINDEX set to 1 so the list's offset will start at the item with index 1. The "window"'s current position allows the user to see part of item 6, items 7 - 9 and part of item 10. If the user was to move the window so that item 11 became visible then the list container would ask it's model to provide it with item 11. In order to provide a quick start up time the list container widget only creates the list items that are required, therefore on start up it will only create the list items required to fill the visible "window".
When the user drags the list in one direction the appearance of the list scrolling will be created by moving the set of widgets, within the "window", by the same distance as the drag. Basically the "window" will act as a viewport onto the larger list. If during the dragging of the set of widgets a new row/column (not yet created) is about to become visible the list container will ask it's model to create the new row/column of widgets on the fly.
The list container also uses a cache, when a list item are no longer needed because it is "far enough" from the "window" then the list container will be put the item in the cache. When the list container has to create a list item it will first check if there is a list item of that type in the cache. Caching only applies when a ListContainerModel is attached to the list container.
The list container doesn't do any drawing itself, when it is asked to draw it simply asks each of its visible children to draw themselves.
To create a list container, an application must do the following
1) Call ISHELL_CreateInstance() with a class ID of either AEECLSID_ListContainerWidget, AEECLSID_PickListContainerWidget or AEECLSID_GridListContainer. 2) Create either an IListContainerModel, an ITypedListModel or an IListModel. 3) Call IWidget_SetModel() to attach the appropriate model to the list 4) Optionally call IWIDGET_SetRows/IWIDGET_SetCols or IWIDGET_SetHintRows/IWIDGET_SetHintCols followed by IWIDGET_GetPreferredExtent. 6) Call IWidget_SetExtent on the ListContainer with the desired extent.
The list container is implemented by a trio of similar widgets -- the list (AEECLSID_ListContainerWidget), pick (AEECLSID_PickListContainerWidget), and grid (AEECLSID_GridListContainer) widgets -- each of which is used to collect multiple, related items, either for view or for selection. These widgets share common behaviors, such as how they handle events or interact with their attached model, but differ in how they arrange the items they contain. For more information on the pick list container and the grid list container widgets see their respective files.
List Container WidgetThe list container widget lays out its items in a vertical list. For example, an application that manages baseball statistics might choose to present to the user a list of player names in alphabetic order. This list could be implemented using a list container widget that displays each item as static text. Visually, the items of a list container widget might be laid out as follows.
+-----------------------+ | List item 1 | |-----------------------| | List item 2 | |-----------------------| | List item 3 | |-----------------------| | List item 4 | |-----------------------| | List item 5 | +-----------------------+
Variable List Items
The list container supports heterogeneous lists. To build a list where each list item is represented by a widget, with a different structure, the user must supply either an ITypedListModel, or IListModel, where each item is different or supply a ILisContainerModel that returns a different type for each list index.