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