summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl_Flex.H2
-rw-r--r--FL/Fl_Group.H3
-rw-r--r--fluid/Fl_Group_Type.cxx2
-rw-r--r--src/Fl_Flex.cxx8
-rw-r--r--src/Fl_Group.cxx87
5 files changed, 98 insertions, 4 deletions
diff --git a/FL/Fl_Flex.H b/FL/Fl_Flex.H
index 1224fe828..87a1c6324 100644
--- a/FL/Fl_Flex.H
+++ b/FL/Fl_Flex.H
@@ -168,6 +168,8 @@ protected:
virtual int alloc_size(int size) const;
+ void on_remove(int); /* override */
+
public:
/** Returns the left margin size of the widget.
diff --git a/FL/Fl_Group.H b/FL/Fl_Group.H
index 1f6240070..6441b6149 100644
--- a/FL/Fl_Group.H
+++ b/FL/Fl_Group.H
@@ -74,6 +74,9 @@ protected:
void update_child(Fl_Widget& widget) const;
Fl_Rect *bounds();
int *sizes(); // FLTK 1.3 compatibility
+ virtual int on_insert(Fl_Widget*, int);
+ virtual int on_move(int, int);
+ virtual void on_remove(int);
public:
diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx
index 0ab8efcb0..5bc3525d9 100644
--- a/fluid/Fl_Group_Type.cxx
+++ b/fluid/Fl_Group_Type.cxx
@@ -550,7 +550,6 @@ void Fl_Table_Type::remove_child(Fl_Type* cc) {
void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) {
Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
- ((Fl_Group*)o)->remove(c->o);
((Fl_Group*)o)->insert(*(c->o), b);
o->redraw();
}
@@ -558,7 +557,6 @@ void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) {
void Fl_Table_Type::move_child(Fl_Type* cc, Fl_Type* before) {
Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
- ((Fl_Table*)o)->remove(*(c->o));
((Fl_Table*)o)->insert(*(c->o), b);
o->redraw();
}
diff --git a/src/Fl_Flex.cxx b/src/Fl_Flex.cxx
index 74e9ed13d..446d00aea 100644
--- a/src/Fl_Flex.cxx
+++ b/src/Fl_Flex.cxx
@@ -133,6 +133,14 @@ Fl_Flex::~Fl_Flex() {
free(set_size_);
}
+/*
+ Fl_Group calls this method when a child widget is about to be removed.
+ Make sure that the widget is also removed from our fixed list.
+ */
+void Fl_Flex::on_remove(int index) {
+ set_size(child(index), 0);
+}
+
void Fl_Flex::resize(int x, int y, int w, int h) {
Fl_Widget::resize(x, y, w, h);
diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx
index f5a2d02ea..d6b346f1f 100644
--- a/src/Fl_Group.cxx
+++ b/src/Fl_Group.cxx
@@ -412,6 +412,7 @@ void Fl_Group::clear() {
if (w->parent()==this) { // should always be true
if (children_>2) { // optimized removal
w->parent_ = 0; // reset child's parent
+ on_remove(idx);
children_--; // update counter
} else { // slow removal
remove(idx);
@@ -447,6 +448,60 @@ Fl_Group::~Fl_Group() {
}
/**
+ Allow derived groups to act when a widget is added as a child.
+
+ Widgets derived from Fl_Group may store additional data for their children.
+ Overriding this method will allow derived classes to generate these data
+ structures just before the child is added.
+
+ This method usually returns the same index that was given in the parameters.
+ By setting a new index, the position of other widgets in the child pointer
+ array can be preserved (e.g. Fl_Scroll keeps its scroll bars as the last
+ two children).
+
+ By returning -1, Fl_Group::insert will not add the child to
+ array_. This is not recommended, but Fl_Table does something similar to
+ forward children to a hidden group.
+
+ \param candidate the candidate will be added to the child array_ after this
+ method returns.
+ \param index add the child at this position in the array_
+ \return index to position the child as planned
+ \return a new index to force the child to a different position
+ \return -1 to keep the group from adding the candidate
+ */
+int Fl_Group::on_insert(Fl_Widget *candidate, int index) {
+ (void)candidate;
+ return index;
+}
+
+/**
+ Allow derived groups to act when a widget is moved within the group.
+
+ Widgets derived from Fl_Group may store additional data for their children.
+ Overriding this method will allow derived classes to move these data
+ structures just before the child itself is moved.
+
+ This method usually returns the new index that was given in the
+ parameters. By setting a different destination index, the position of other
+ widgets in the child pointer array can be preserved.
+
+ By returning -1, Fl_Group::insert will not move the child.
+
+ \param oldIndex the current index of the child that will be moved
+ \param newIndex the new index of the child, counted with the old
+ child already removed
+ \return index to position the child as planned
+ \return a new index to force the child to a different position
+ \return -1 to keep the group from moving the child
+ */
+int Fl_Group::on_move(int oldIndex, int newIndex) {
+ (void)oldIndex;
+ return newIndex;
+}
+
+
+/**
The widget is removed from its current group (if any) and then
inserted into this group. It is put at index n - or at the end,
if n >= children(). This can also be used to rearrange
@@ -456,12 +511,25 @@ void Fl_Group::insert(Fl_Widget &o, int index) {
if (o.parent()) {
Fl_Group* g = o.parent();
int n = g->find(o);
- if (g == this) {
+ if (g == this) { // avoid expensive remove() and add() if we just move a widget within the group
if (index > n) index--;
- if (index == n) return;
+ index = on_move(n, index);
+ if (index == n) return; // this includes (children_ == 1)
+ if (index >= children_ || index < 0) return;
+ if (index > n)
+ memmove(array_+n, array_+(n+1), (index-n) * sizeof(Fl_Widget*));
+ else
+ memmove(array_+(index+1), array_+index, (n-index) * sizeof(Fl_Widget*));
+ array_[index] = &o;
+ init_sizes();
+ return;
}
g->remove(n);
}
+
+ index = on_insert(&o, index);
+ if (index == -1) return;
+
o.parent_ = this;
if (children_ == 0) { // use array pointer to point at single child
child1_ = &o;
@@ -488,6 +556,19 @@ void Fl_Group::insert(Fl_Widget &o, int index) {
void Fl_Group::add(Fl_Widget &o) {insert(o, children_);}
/**
+ Allow derived groups to act when a child widget is removed from the group.
+
+ Widgets derived from Fl_Group may store additional data for their children.
+ Overriding this method will allow derived classes to remove these data
+ structures just before the child is removed.
+
+ \param index remove the child at this position in the array_
+ */
+void Fl_Group::on_remove(int index) {
+ (void)index;
+}
+
+/**
Removes the widget at \p index from the group but does not delete it.
This method does nothing if \p index is out of bounds.
@@ -499,6 +580,8 @@ void Fl_Group::add(Fl_Widget &o) {insert(o, children_);}
*/
void Fl_Group::remove(int index) {
if (index < 0 || index >= children_) return;
+ on_remove(index);
+
Fl_Widget &o = *child(index);
if (&o == savedfocus_) savedfocus_ = 0;
if (&o == resizable_) resizable_ = this;