Public Member Functions | |
virtual int | children (const Menu *, const int *indexes, int level) |
virtual Widget * | child (const Menu *, const int *indexes, int level) |
virtual void | flags_changed (const Menu *, Widget *) |
This is done by making a subclass of List which creats a "dummy" widget, typically a subclass of Item, that describes a particular item that the browser or menu should display. Only one item is examined at any time and thus the dummy widget can be reused, so there is very little space overhead.
This is designed for data formats where finding the Nth child of a parent is a very quick operation, ie an array. If your data is a list you can search it, the performance is probably acceptable for small lists with less than a hundred or so items. For a bidirectional list it may be useful to cache the last request and do a relative search, a Browser and Menu will usually ask for adjoining items.
If you wish to use a MultiBrowser you must also have space in your data to store the state of the SELECTED flag on each item, and and must implement the flags_changed() method.
If you wish to make a hierarcial Browser, you may want to have space in your data to store the state of the STATE flag on each parent item, and implement the flags_changed() method. If you don't do this the browser is only able to keep one item open at each level.
The base List class returns the child widgets from the Menu that owns it. All Menus share a single instance of this by default, so the default behavior is that child widgets appear as items in the menu or browser. Subclasses of List may want to call the base class to allow normal widgets to be prepended to whatever they return.
|
Return a given child as a widget. draw() and measure() will be called on this widget to figure out where to place it and to draw it. Typical implementations create a reusable Item and fill it in with the correct data. This should return NULL if there is anything illegal about the indexes. Here is a sample implementation, where Node is a data type that you have defined. This demonstrates how to create the dummy widget:
Widget* My_List::child(const Menu*, const int* indexes, int level) { Node* node = root; for (int l = 0; l <= level; l++) { if (!node->is_parent()) return 0; if (indexes[l] >= node->children_count()) return 0; node = node->child(indexes[l]); } static Widget* widget; if (!widget) { Group::current(0); widget = new Item(); } widget->label(node->text()); widget->w(0); // cause measure() to be called widget->user_data(node); if (node->selected) widget->set_flag(SELECTED); else widget->clear_flag(SELECTED); if (node->is_parent() && node->open) widget->set_flag(STATE); else widget->clear_flag(STATE); return widget; } |
|
Return how many children are under a given item. If level is zero, this should return how many items are at the top level. Otherwise indexes is an array of level numbers indicating the index of an item at the top level, the index of the an item that is the child of that, and so on. This should return -1 if the item is not a "parent" item or the index array is illegal. It is not necessary to return the correct value until the parent is "open", which means the STATE flag was set in it, so if it is expensive to calculate the number you can return 1 for any closed parent. Here is a sample implementation, where Node is a data type that you have defined:
int My_List::children(const Menu*, const int* indexes, int level) { Node* node = root; for (int l = 0; l < level; l++) { if (indexes[l] >= node->children_count()) return -1; node = node->child(indexes[l]); if (!node->is_parent()) return -1; } return node->children_count(); } |
|
This is called if the browser changes any flags on a widget, so that you can copy the values to permanent storage, and perhaps change other displays of the selection. Currently only the STATE and SELECTED flags are ever changed. Here is a sample implementation, where Node is a data type that you have defined: |