class fltk::List


Include Files

#include <fltk/Menu.h>

Description

Allows an fltk::Browser or fltk::Choice or other subclass of fltk::Menu to display a hierarchy of data that is managed by the application rather than FLTK. This is done by creating a "dummy" widget, typically a subclass of fltk::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, as fltk::Browser and fltk::Menu will usually ask for adjoining items.

If you wish to make a hierarcial fltk::Browser, you must have space in your data to store the state of the fltk::VALUE flag on each parent item, and must implement the flags_changed() method.

If you wish to use an fltk::MultiBrowser you must also have space in your data to store the state of the fltk::SELECTED flag on each item, and and must implement the flags_changed() method.

Methods

virtual int children(const fltk::Menu* group, const int* indexes, int level);

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 fltk::VALUE 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_fltk::List::children(const fltk::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();
}

virtual fltk::Widget* child(const fltk::Menu* group, const int* indexes, int level);

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 fltk::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:

fltk::Widget* My_fltk::List::child(const fltk::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 fltk::Widget* widget;
  if (!widget) {
    fltk::Group::current(0);
    widget = new fltk::Item();
  }
  widget->label(node->text());
  widget->w(0); // cause measure() to be called
  widget->user_data(node);
  if (node->selected) widget->set_flag(fltk::SELECTED);
  else widget->clear_flag(fltk::SELECTED);
  if (node->is_parent() && node->open) widget->set_flag(fltk::VALUE);
  else widget->clear_flag(fltk::VALUE);
  return widget;
}

virtual void flags_changed(const fltk::Menu* group, fltk::Widget* widget);

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 fltk::VALUE and fltk::SELECTED flags are ever changed.

Here is a sample implementation, where Node is a data type that you have defined:

void My_fltk::List::flags_changed(const fltk::Menu*, fltk::Widget* widget) {
  Node* node = (Node*)(widget->user_data());
  node->open = (widget->flags() & fltk::VALUE) !=0;
  node->selected = (widget->flags() & fltk::SELECTED) != 0;
}