Author: trilec
Date: 2007-06-10 17:27:33 -0400 (Sun, 10 Jun 2007)
New Revision: 5899
Log:
Moved List from Menu to the base Widget class. This we hope will allow widgets 
to be generated dynamically as they are first seen.


Modified:
   widget_has_children/fltk/Group.h
   widget_has_children/fltk/Menu.h
   widget_has_children/fltk/StringList.h
   widget_has_children/fltk/Widget.h
   widget_has_children/src/Browser.cxx
   widget_has_children/src/Group.cxx
   widget_has_children/src/InputBrowser.cxx
   widget_has_children/src/Menu.cxx
   widget_has_children/src/Menu_popup.cxx
   widget_has_children/src/StringList.cxx
   widget_has_children/src/Widget.cxx

Modified: widget_has_children/fltk/Group.h
===================================================================
--- widget_has_children/fltk/Group.h    2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/fltk/Group.h    2007-06-10 21:27:33 UTC (rev 5899)
@@ -44,7 +44,7 @@
   // for back-compatability:
   static Group* current() {return (Group*)constructorAddsTo();}
   static void current(Group* g) {constructorAddsTo(g);}
-  void clear() {destroyChildren();}
+  void clear() {list(0);}
 
   Group(int,int,int,int, const char * = 0, bool begin=false);
   virtual ~Group();

Modified: widget_has_children/fltk/Menu.h
===================================================================
--- widget_has_children/fltk/Menu.h     2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/fltk/Menu.h     2007-06-10 21:27:33 UTC (rev 5899)
@@ -28,14 +28,6 @@
 
 class FL_API Menu;
 
-class FL_API List {
-public:
-  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*);
-  virtual ~List();
-};
-
 enum { // Special flag values for add(), you can also use Flags.h values
   // These match values from Fl_Menu_Item in fltk 1.0:
   MENU_TOGGLE = 2,
@@ -45,22 +37,17 @@
 };
 
 class FL_API Menu : public Widget {
-  int value_;
-
 public:
 
   Menu(int,int,int,int, const char* l=0, bool begin=false);
-  List* list() const {return list_;}
-  void list(List* l) {list_ = l;}
   void layout();
 
   static NamedStyle* default_style;
 
   int children(const int* indexes, int level) const ;
-  int children(int index) const;
-  int children() const ;
   Widget* child(const int* indexes, int level) const ;
-  Widget* child(int index) const ;
+  unsigned children() const {return Widget::children();}
+  Widget* child(unsigned n) const {return Widget::child(n);}
 
   Widget* item() const {return item_;}
   Widget* item(Widget* v) {return item_ = v;}
@@ -140,7 +127,7 @@
   Widget *try_popup(const Rectangle&,const char* title=0,bool menubar=false);
        
 private:
-  List* list_;
+  int value_;
   Widget* item_;
 };
 

Modified: widget_has_children/fltk/StringList.h
===================================================================
--- widget_has_children/fltk/StringList.h       2007-06-10 18:04:52 UTC (rev 
5898)
+++ widget_has_children/fltk/StringList.h       2007-06-10 21:27:33 UTC (rev 
5899)
@@ -22,7 +22,8 @@
 #ifndef fltk_StringList_h
 #define fltk_StringList_h
 
-#include "Menu.h"
+#include "List.h"
+#include "Widget.h"
 
 namespace fltk {
 
@@ -30,10 +31,10 @@
   Widget* generated_item_;
 public:
   // fltk::List virtual functions:
-  virtual Widget* child(const Menu*, const int* indexes, int level);
+  virtual Widget* child(const Widget*, const int* indexes, int level, int 
column);
   // virtual functions to return hierarchy of strings:
-  virtual int children(const Menu*, const int* indexes, int level) = 0;
-  virtual const char* label(const Menu*, const int* indexes, int level)=0;
+  virtual int children(const Widget*, const int* indexes, int level) = 0;
+  virtual const char* label(const Widget*, const int* indexes, int level, int 
column)=0;
   // label() can mess with this item to change flags, font, etc:
   Widget* generated_item() {return generated_item_;}
   StringHierarchy() {generated_item_ = 0;}
@@ -43,11 +44,11 @@
 class FL_API StringList : public StringHierarchy {
 public:
   // overrides of StringHierarchy virtual functions:
-  virtual int children(const Menu*, const int* indexes, int level);
-  virtual const char* label(const Menu*, const int* indexes, int level);
+  virtual int children(const Widget*, const int* indexes, int level);
+  virtual const char* label(const Widget*, const int* indexes, int level, int 
column);
   // new virtual funcitons:
-  virtual int children(const Menu*) = 0;
-  virtual const char* label(const Menu*, int index) = 0;
+  virtual int children(const Widget*) = 0;
+  virtual const char* label(const Widget*, int index) = 0;
 };
 
 class FL_API StringArray : public StringList {
@@ -55,8 +56,8 @@
   int children_;
 public:
   // overrides of StringList virtual functions:
-  virtual int children(const Menu*);
-  virtual const char* label(const Menu*, int index);
+  virtual int children(const Widget*);
+  virtual const char* label(const Widget*, int index);
   // Constructors to use a constant array of strings:
   StringArray(const char*const* a, int n) : array(a), children_(n) {}
   StringArray(const char*const* a) {set(a);}

Modified: widget_has_children/fltk/Widget.h
===================================================================
--- widget_has_children/fltk/Widget.h   2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/fltk/Widget.h   2007-06-10 21:27:33 UTC (rev 5899)
@@ -30,6 +30,7 @@
 class FL_API Widget;
 class FL_API Window;
 class FL_API Symbol;
+class FL_API List;
 struct Cursor;
 
 typedef void (Callback )(Widget*, void*);
@@ -67,9 +68,12 @@
   void parent(Widget* w)       { parent_ = w; }
   Window* window() const       ;
 
-  bool hasChildren() const {return childVector != 0;}
-  unsigned children() const {return childVector?childVector->count : 0;}
-  Widget* child(unsigned n) const {return childVector->array[n];}
+  List* list() const {return list_;}
+  void list(List* v);
+  bool hasChildren() const {return list_ != 0;}
+  unsigned children() const;
+  Widget* child(unsigned n) const;
+  // These only work if you have not set list():
   unsigned find(const Widget*) const;
   unsigned find(const Widget& o) const {return find(&o);}
   void add(Widget&);
@@ -83,7 +87,6 @@
   void replace(unsigned index, Widget&);
   void replace(Widget& old, Widget& o) {replace(find(old),o);}
   void swap(unsigned indexA, unsigned indexB);
-  void destroyChildren();
 
   void begin() {constructorAddsTo_ = this;}
   void end() {constructorAddsTo_ = parent();}
@@ -321,8 +324,7 @@
   void*                        user_data_;
   const char*          tooltip_; // make this into another widget?
   Widget*              parent_;
-  struct ChildVector {Widget** array; unsigned count; unsigned alloc;};
-  ChildVector*         childVector;
+  List*                 list_; // this contains child widgets
   uchar                        type_;
   uchar                        damage_;
   uchar                        layout_damage_;

Modified: widget_has_children/src/Browser.cxx
===================================================================
--- widget_has_children/src/Browser.cxx 2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/src/Browser.cxx 2007-06-10 21:27:33 UTC (rev 5899)
@@ -31,6 +31,7 @@
 #include <fltk/draw.h>
 #include <fltk/error.h>
 #include <fltk/Cursor.h>
+#include <fltk/List.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>

Modified: widget_has_children/src/Group.cxx
===================================================================
--- widget_has_children/src/Group.cxx   2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/src/Group.cxx   2007-06-10 21:27:33 UTC (rev 5899)
@@ -52,6 +52,7 @@
 */
 
 #include <config.h>
+#include <fltk/List.h>
 #include <fltk/Window.h>
 #include <fltk/Box.h>
 #include <fltk/draw.h>
@@ -65,6 +66,187 @@
 
 ////////////////////////////////////////////////////////////////
 
+/*! \class fltk::List
+
+  This class returns child widgets. A Widget with children will have
+  a pointer to an instance of some subclass of List, and will ask it
+  for the child widgets. There is also additional methods of looking
+  up children in a hierarchy or multiple columns that is used by
+  browsers and menus.
+
+  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 fltk::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 fltk::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.
+*/
+
+/*! \fn int List::children(const Menu* menu, 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::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:
+
+\code
+int My_List::children(const fltk::Widget*, 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();
+}
+\endcode
+*/
+
+// Subclass of List that stores the child widgets of a typical widget
+class WidgetList : public List {
+public:
+  Widget** array;
+  unsigned count;
+  unsigned alloc;
+  int children(const Widget* menu, const int* indexes, int level);
+  Widget* child(const Widget* menu, const int* indexes,int level, int column);
+  void detach();
+  ~WidgetList();
+};
+
+int WidgetList::children(const Widget* menu, const int* indexes, int level) {
+  if (!level) return count;
+  int i = indexes[0];
+  // browser can return indexes pointing on -1 values so we must check this :
+  if (i < 0 || unsigned(i) >= count) return -1;    //if (i >= 
group->children()) return -1;
+  Widget* widget = array[i];
+  if (!widget->hasChildren()) return -1;
+  else return widget->list()->children(widget,indexes+1,level-1);
+}
+
+/*! \fn Widget* List::child(const Widget* menu, const int* indexes,int level, 
int column) {
+
+  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.
+
+  The column number is currently only used by multi-column Browser widgets.
+  Return null if it is non-zero.
+
+  Here is a sample implementation, where Node is a data type that you
+  have defined. This demonstrates how to create the dummy widget:
+
+\code
+fltk::Widget* My_List::child(const fltk::Menu*, const int* indexes, int level, 
int column) {
+  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::Widget::constructorAddsTo(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::STATE);
+  else widget->clear_flag(fltk::STATE);
+  return widget;
+}
+\endcode
+*/
+
+Widget* WidgetList::child(const Widget* menu, const int* indexes,int level, 
int column) {
+  if (column) return 0;
+  int i = indexes[0];
+  if (i < 0 || unsigned(i) >= count) return 0;
+  Widget* widget = array[i];
+  if (level <= 1) return widget;
+  else if (!widget->hasChildren()) return 0;
+  else return widget->list()->child(widget, indexes+1, level-1, column);
+}
+
+/*!
+  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::STATE and fltk::SELECTED flags are ever changed.
+
+  Here is a sample implementation, where Node is a data type that you
+  have defined:
+\code
+void My_List::flags_changed(const fltk::Menu*, fltk::Widget* widget) {
+  Node* node = (Node*)(widget->user_data());
+  node->open = widget->flag(fltk::STATE);
+  node->selected = widget->flag(fltk::SELECTED);
+}
+\endcode
+*/
+void List::flags_changed(const Widget*, Widget*) {}
+
+/*! This is called if the parent widget (a widget with this List as it's
+  list()) is destroyed or if the list pointer is changed. The list can
+  destroy itself or reduce a reference count, etc.
+*/
+void List::detach() {}
+
+void WidgetList::detach() {
+  delete this;
+}
+
+List::~List() {}
+
+WidgetList::~WidgetList() {
+  // destroy all the children in backwards order:
+  for (unsigned n = count; n--;) {
+    array[n]->parent(0); // stops it from calling remove()
+    delete array[n];
+  }
+  delete[] array;
+}
+
+////////////////////////////////////////////////////////////////
+
 FL_API Widget* Widget::constructorAddsTo_;
 
 static void revert(Style* s) {
@@ -92,37 +274,41 @@
   if (begin) this->begin();
 }
 
-/*! \e Deletes all children from the group and makes it empty.
-  This calls the destructor on all the children!!! If you don't
-  want to call the destructor, use remove_all().
+/*! Change the List object that is returning children widgets for
+  this widget. List::detach() is called on the old list. Setting this
+  to zero makes the widget have zero children and hasChildren()
+  will return false.
+
+  Warning: if you do this, you cannot call add() or remove(). These
+  methods assumme the list() is set to a specific internal class.
 */
-void Widget::destroyChildren() {
-  ChildVector* v = childVector;
-  if (!v) return;
-  // clear everything now, in case fix_focus recursively calls us:
-  childVector = 0;
-  // now destroy all the children in backwards order:
-  for (unsigned n = v->count; n--;) {
-    v->array[n]->parent_ = 0; // stops it from calling remove()
-    delete v->array[n];
+void Widget::list(List* newlist) {
+  if (list_) {
+    // set the pointer to zero to avoid recursion problems:
+    List* oldlist = list_; list_ = 0;
+    oldlist->detach();
   }
-  delete[] v->array;
-  delete v;
+  list_ = newlist;
 }
 
 Group::~Group() {}
 
-/*! \fn Widget* Widget::child(int n) const
-  Returns a child, n >= 0 && n < children(). <i>No range checking is done!</i>
-*/
+/*! Returns a child, or null if \a n is out of range. */
+Widget* Widget::child(unsigned n) const {
+  if (!list_) return 0;
+  else return list_->child(this, (int*)&n, 1,0);
+}
 
 /*! \fn bool Widget::hasChildren() const
-  Same as children()!=0 but slightly faster.
+  Fast check to see if the widget has any children. If a non-standard list()
+  is used this may return true while children() still returns 0, however.
 */
 
-/*! \fn int Widget::children() const
-  Returns how many child widgets this Widget has.
-*/
+/*! Returns how many child widgets this Widget has. */
+unsigned Widget::children() const {
+  if (!list_) return 0;
+  else return list_->children(this, 0, 0);
+}
 
 /*! \fn void Widget::insert(Widget& o, Widget* beforethis)
   This does insert(w, find(beforethis)). This will append the
@@ -146,15 +332,17 @@
     o.parent_->remove(n);
   }
   o.parent_ = this;
-  if (!childVector) {
+  if (!list_) {
     // initialize to one child
-    ChildVector* v = childVector = new ChildVector;
+    WidgetList* v = new WidgetList;
     v->alloc = 1;
     v->array = new Widget*[v->alloc];
     v->count = 1;
     v->array[0] = &o;
+    list_ = v;
   } else {
-    ChildVector* v = childVector;
+    // assert dynamic_cast<WidgetList*>(list_);
+    WidgetList* v = static_cast<WidgetList*>(list_);
     if (v->count >= v->alloc) {
       v->alloc = 2*v->count;
       Widget** newarray = new Widget*[v->alloc];
@@ -216,19 +404,15 @@
   if index is out of range.
 */
 void Widget::remove(unsigned index) {
-  ChildVector* v = childVector;
-  if (!v || index >= v->count) return;
-  if (v->count < 2) {remove_all(); return;}
+  if (!list_) return;
+  // assert dynamic_cast<WidgetList*>(list_);
+  WidgetList* v = static_cast<WidgetList*>(list_);
+  if (index >= v->count) return;
   Widget* o = v->array[index];
   o->parent_ = 0;
-  if (!--v->count) {
-    delete[] v->array;
-    delete v;
-    childVector = 0;
-  } else {
-    for (unsigned i=index; i < v->count; ++i)
-      v->array[i] = v->array[i+1];
-  }
+  --v->count;
+  for (unsigned i=index; i < v->count; ++i)
+    v->array[i] = v->array[i+1];
 }
 
 /*! \fn void Widget::remove(Widget& widget)
@@ -242,19 +426,22 @@
 */
 void Widget::remove_all()
 {
-  ChildVector* v = childVector;
-  if (!v) return;
-  childVector = 0;
+  if (!list_) return;
+  // assert dynamic_cast<WidgetList*>(list_);
+  WidgetList* v = static_cast<WidgetList*>(list_);
   for (unsigned n = v->count; n--;)
     v->array[n]->parent_ = 0;
-  delete[] v->array;
+  v->count = 0;
+  list_ = 0;
   delete v;
 }
 
 /*! Remove the indexed child and insert the passed widget in it's place. */
 void Widget::replace(unsigned index, Widget& o) {
-  ChildVector* v = childVector;
-  if (!v || index >= v->count) {add(o); return;}
+  if (!list_) {add(o); return;}
+  // assert dynamic_cast<WidgetList*>(list_);
+  WidgetList* v = static_cast<WidgetList*>(list_);
+  if (index >= v->count) {add(o); return;}
   o.parent(this);
   v->array[index]->parent(0);
   v->array[index] = &o;
@@ -267,7 +454,9 @@
 */
 
 void Widget::swap(unsigned indexA, unsigned indexB) {
-  ChildVector* v = childVector;
+  if (!list_) return;
+  // assert dynamic_cast<WidgetList*>(list_);
+  WidgetList* v = static_cast<WidgetList*>(list_);
   if (!v || indexA >= v->count || indexB >= v->count) return;
   Widget* o = v->array[indexA];
   v->array[indexA] = v->array[indexB];
@@ -278,18 +467,19 @@
   widget or of a parent of \a widget that is a child() of
   this. Returns children() if the widget is NULL or not found. */
 unsigned Widget::find(const Widget* widget) const {
-  ChildVector* v = childVector;
-  if (!v) return 0;
+  if (!list_) return 0;
   for (;;) {
-    if (!widget) return v->count;
+    if (!widget) return children();
     if (widget->parent() == this) break;
     widget = widget->parent();
   }
   // Search backwards so if children are deleted in backwards order
   // they are found quickly:
-  for (unsigned n = v->count; n--;)
-    if (v->array[n] == widget) return n;
-  return v->count;
+  int count = list_->children(this,0,0);
+  for (int n = count; n--;) {
+    if (list_->child(this, &n, 1,0) == widget) return unsigned(n);
+  }
+  return unsigned(count);
 }
 
 ////////////////////////////////////////////////////////////////

Modified: widget_has_children/src/InputBrowser.cxx
===================================================================
--- widget_has_children/src/InputBrowser.cxx    2007-06-10 18:04:52 UTC (rev 
5898)
+++ widget_has_children/src/InputBrowser.cxx    2007-06-10 21:27:33 UTC (rev 
5899)
@@ -26,6 +26,7 @@
 #include <fltk/InputBrowser.h>
 #include <fltk/MenuWindow.h>
 #include <fltk/Browser.h>
+#include <fltk/List.h>
 #include <fltk/Monitor.h>
 #include <fltk/events.h>
 #include <fltk/damage.h>
@@ -217,13 +218,13 @@
 class Share_List : public List {
 public:
   Menu* other;
-  int children(const Menu*, const int* indexes, int level) {
+  int children(const Widget*, const int* indexes, int level) {
     return other->children(indexes, level);
   }
-  Widget* child(const Menu*, const int* indexes, int level) {
+  Widget* child(const Widget*, const int* indexes, int level, int column) {
     return other->child(indexes, level);
   }
-  void flags_changed(const Menu*, Widget* widget) {
+  void flags_changed(const Widget*, Widget* widget) {
     other->list()->flags_changed(other,widget);
   }
 } share_list; // only one instance of this.
@@ -283,7 +284,7 @@
 
       // find next item in the list and replace the current
       int found=-1;
-      for (int i=0; i<children(); i++) {
+      for (unsigned i=0; i<children(); i++) {
          Widget* w=child(i);
          if (!strncmp(text(), w->label(), size())) {
              found=i; break;
@@ -435,7 +436,7 @@
 
   // find the currently selected item in the list
   list->value(0);
-  for (int i=0; i<list->children(); i++) {
+  for (unsigned i=0; i<list->children(); i++) {
     Widget* w=list->child(i);
     if (!strncmp(text(), w->label(), size())) {
       list->value(i);

Modified: widget_has_children/src/Menu.cxx
===================================================================
--- widget_has_children/src/Menu.cxx    2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/src/Menu.cxx    2007-06-10 21:27:33 UTC (rev 5899)
@@ -21,6 +21,7 @@
 
 #include <fltk/events.h>
 #include <fltk/Menu.h>
+#include <fltk/List.h>
 #include <fltk/damage.h>
 #include <fltk/Item.h> // for TOGGLE, RADIO
 #define checkmark(item) (item->type()>=Item::TOGGLE && 
item->type()<=Item::RADIO)
@@ -29,166 +30,6 @@
 
 ////////////////////////////////////////////////////////////////
 
-/*! \class fltk::List
-
-  Allows a Browser or Choice or other subclass of Menu to display a
-  hierarchy of data that is managed by the application rather than
-  FLTK.
-
-  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 fltk::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 fltk::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 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::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:
-
-\code
-int My_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();
-}
-\endcode
-*/
-int List::children(const Menu* menu, const int* indexes, int level) {
-  const Widget* group = menu;
-  while (level--) {
-    int i = *indexes++;
-    // browser can return indexes pointing on -1 values so we must check this :
-    if (i < 0) return -1;    //if (i >= group->children()) return -1;
-    Widget* widget = group->child(i);
-    if (!widget->is_group()) return -1;
-    group = widget;
-  }
-  return group->children();
-}
-
-/*!
-  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. This demonstrates how to create the dummy widget:
-
-\code
-fltk::Widget* My_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::Widget::constructorAddsTo(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::STATE);
-  else widget->clear_flag(fltk::STATE);
-  return widget;
-}
-\endcode
-*/
-Widget* List::child(const Menu* menu, const int* indexes,int level) {
-  const Widget* group = menu;
-  for (;;) {
-    int i = *indexes++;
-    if (i < 0 || unsigned(i) >= group->children()) return 0;
-    Widget* widget = group->child(i);
-    if (!level--) return widget;
-    if (!widget->is_group()) return 0;
-    group = 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::STATE and fltk::SELECTED flags are ever changed.
-
-  Here is a sample implementation, where Node is a data type that you
-  have defined:
-\code
-void My_List::flags_changed(const fltk::Menu*, fltk::Widget* widget) {
-  Node* node = (Node*)(widget->user_data());
-  node->open = widget->flag(fltk::STATE);
-  node->selected = widget->flag(fltk::SELECTED);
-}
-\endcode
-*/
-void List::flags_changed(const Menu*, Widget*) {}
-
-/*!
-  The destructor does nothing. It is mostly here to shut up compiler
-  warnings, and to allow subclasses that you want to dynamically
-  allocate to work.
-
-  Unfortunately C++ calls the destructor for static objects on program
-  exit. I consider this a mistake, particularily because the
-  destructor cannot assumme other objects (like the display
-  connection) still exist.  It also slows down program exit. As all
-  useable systems can harvest resources used by crashed programs,
-  calling these destructors serve no useful purpose.
-*/
-List::~List() {}
-
-static List default_list;
-
-////////////////////////////////////////////////////////////////
-
 /*! \class fltk::Menu
 
   The Menu base class is used by Browser, Choice, MenuBar, PopupMenu,
@@ -243,57 +84,17 @@
 NamedStyle* Menu::default_style = &::style;
 
 Menu::Menu(int x,int y,int w, int h,const char* l, bool begin)
-  : Widget(x,y,w,h,l), list_(&default_list), item_(0) {
+  : Widget(x,y,w,h,l), value_(0), item_(0) {
   if (begin) this->begin();
   callback(default_callback);
   style(default_style);
 }
 
-/*! \fn void Menu::list(List* list)
-  Set the List that generates widgets for the menu. By default this
-  is a dummy List that returns the child widgets of the Menu.
-*/
-
-/*! Calls list()->children(this, indexes, level) */
+/*! Calls list()->children(this, indexes, level ) */
 int Menu::children(const int* indexes, int level) const {
-  return list_->children(this, indexes, level);
+  return list()->children(this, indexes, level);
 }
 
-/*!
-  Returns the number of children at the top level. Same as children(0,0).
-
-  <i>This Overrides the method of the same name on fltk::Widget</i>. This is
-  so that an fltk::List can be used. However if no fltk::List is
-  specified the action is identical to fltk::Widget::children().
-*/
-int Menu::children() const {
-  return list_->children(this, 0, 0);
-}
-
-/*! Returns the number of children of some child. Same as children(&i,1). */
-int Menu::children(int i) const {
-  return list_->children(this, &i, 1);
-}
-
-/*! Calls list()->child(this, indexes, level).
-  If an fltk::List is used, the returned widget may be a temporary data
-  structure and may be overwritten by another call to child() in this
-  <i>or any other Menu</i>!
-*/
-Widget* Menu::child(const int* indexes, int level) const {
-  return list_->child(this, indexes, level);
-}
-
-/*! Returns the given top-level child. Same as child(&index,0).
-
-  <i>This Overrides the method of the same name on fltk::Widget</i>. This is
-  so that an fltk::List can be used. However if no fltk::List is
-  specified the action is identical to fltk::Widget::child(index).
-*/
-Widget* Menu::child(int n) const {
-  return list_->child(this, &n, 0);
-}
-
 ////////////////////////////////////////////////////////////////
 
 /*! \fn Widget* Menu::item() const
@@ -356,7 +157,7 @@
   int i = indexes[0];
   bool ret = false;
   if (value() != i) {value(i); ret = true;}
-  if (i < 0 || i >= children()) {
+  if (i < 0 || unsigned(i) >= children()) {
     item(0);
   } else {
     item(child(i));
@@ -365,7 +166,7 @@
       Menu* group = static_cast<Menu*>(item());
       int i = (j > level) ? -1 : indexes[j++];
       if (group->value() != i) {group->value(i); ret = true;}
-      if (i < 0 || i >= group->children()) break;
+      if (i < 0 || unsigned(i) >= group->children()) break;
       item(group->child(i));
     }
   }
@@ -386,12 +187,12 @@
 */
 Widget* Menu::get_item() {
   int i = value();
-  if (i < 0 || i >= children()) {item(0); return 0;}
+  if (i < 0 || unsigned(i) >= children()) {item(0); return 0;}
   item(child(i));
   while (item()->is_group()) {
     Menu* group = static_cast<Menu*>(item());
     int i = group->value();
-    if (i < 0 || i >= group->children()) break;
+    if (i < 0 || unsigned(i) >= group->children()) break;
     item(group->child(i));
   }
   return item();
@@ -416,7 +217,7 @@
   This is because generating every item in a list could take a very
   long time, possibly forever. */
 static Widget* shortcut_search(Menu* g) {
-  for (int i = 0; i < g->children(); i++) {
+  for (unsigned i = 0; i < g->children(); i++) {
     Widget* item = g->child(i);
     if (!item->active()) continue;
     if (item->test_shortcut(false)) {
@@ -455,8 +256,8 @@
 */
 int Menu::handle_shortcut() {
   //if (event_key_repeated()) return 0; // ignore repeating keys
-  int children = this->children();
-  for (int i = 0; i < children; i++) {
+  unsigned children = this->children();
+  for (unsigned i = 0; i < children; i++) {
     Widget* item = child(i);
     if (!item->active()) continue;
     if (item->test_shortcut(false)) {

Modified: widget_has_children/src/Menu_popup.cxx
===================================================================
--- widget_has_children/src/Menu_popup.cxx      2007-06-10 18:04:52 UTC (rev 
5898)
+++ widget_has_children/src/Menu_popup.cxx      2007-06-10 21:27:33 UTC (rev 
5899)
@@ -919,7 +919,7 @@
       if (!widget->takesevents()) break;
       Group* group = (Group*)widget;
       int item = group->focus_index();
-      if (item >= group->children()) break;
+      if (item < 0 || unsigned(item) >= group->children()) break;
       MWindow* mw = p.menus[p.level];
       int nX = mw->x() + mw->w();
       int nY = mw->y() + mw->ypos(p.indexes[p.level])-mw->ypos(0);

Modified: widget_has_children/src/StringList.cxx
===================================================================
--- widget_has_children/src/StringList.cxx      2007-06-10 18:04:52 UTC (rev 
5898)
+++ widget_has_children/src/StringList.cxx      2007-06-10 21:27:33 UTC (rev 
5899)
@@ -15,7 +15,7 @@
 
 */
 
-Widget* StringHierarchy::child(const Menu* group, const int* indexes,int level)
+Widget* StringHierarchy::child(const Widget* group, const int* indexes,int 
level,int column)
 {
   // Construct reusable widget:
   if (!generated_item_) {
@@ -28,7 +28,9 @@
   // We must clear flags so it does not accidentally think the item
   // is selected or (if a parent) is opened:
   generated_item_->clear_flag(fltk::STATE|fltk::OPENED);
-  generated_item_->label(label(group, indexes, level));
+  const char* c = label(group, indexes, level, column);
+  if (!c && column) return 0;
+  generated_item_->label(c);
   return generated_item_;
 }
 
@@ -54,36 +56,37 @@
 
   Typically you will create a subclass with the children() and
   label() functions overridden, and make a single static instance
-  of this class. It can be used by several menus, but the Menu*
+  of this class. It can be used by several menus, but the Widget*
   argument to children() and label() is used to differentiate them.
 
 \code
 class MyList : public StringList {
-  int children(const Menu* menu) {
-    return ((MyClass*)(menu->user_data()))->number_of_items();
+  int children(const Widget* widget) {
+    return ((MyClass*)(widget->user_data()))->number_of_items();
   }
-  const char* label(const Menu* menu, int index) {
-    return ((MyClass*)(menu->user_data()))->label(index);
+  const char* label(const Widget* widget, int index) {
+    return ((MyClass*)(widget->user_data()))->label(index);
   }
 };
 static MyList myList;
 
-Menu themenu;
+Widget themenu;
 MyClass myobject;
 themenu->list(&mylist);
 themenu->callback(mycallback, &myobject);
 \endcode
 */
 
-int StringList::children(const Menu* group, const int* indexes, int level) {
+int StringList::children(const Widget* group, const int* indexes, int level) {
   if (!level)
     return children(group);
   else
     return -1;
 }
 
-const char* StringList::label(const Menu* group, const int* indexes, int level)
+const char* StringList::label(const Widget* group, const int* indexes, int 
level,int column)
 {
+  if (column) return 0;
   return label(group, indexes[0]);
 }
 
@@ -102,9 +105,9 @@
   menu->list(list);
   \endcode
 */
-int StringArray::children(const Menu*) {return children_;}
+int StringArray::children(const Widget*) {return children_;}
 
-const char* StringArray::label(const Menu*, int index) {
+const char* StringArray::label(const Widget*, int index) {
   return array[index];
 }
 

Modified: widget_has_children/src/Widget.cxx
===================================================================
--- widget_has_children/src/Widget.cxx  2007-06-10 18:04:52 UTC (rev 5898)
+++ widget_has_children/src/Widget.cxx  2007-06-10 21:27:33 UTC (rev 5899)
@@ -66,7 +66,7 @@
 {
   style_       = default_style;
   parent_      = 0;
-  childVector   = 0;
+  list_         = 0;
   callback_    = default_callback;
   user_data_   = 0;
   label_       = L;
@@ -92,7 +92,7 @@
 Widget::~Widget() {
   remove_timeout();
   remove_shortcuts();
-  if (childVector) destroyChildren();
+  list(0); // calls detach and thus destroys WidgetList and child widgets
   if (parent_) parent_->remove(this);
   throw_focus();
   if (style_->dynamic()) {

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to