summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <git@matthiasm.com>2021-12-08 20:52:33 +0100
committerMatthias Melcher <git@matthiasm.com>2021-12-08 20:52:51 +0100
commit1be158a840922aa03682d39926dc60ecb487063b (patch)
tree283dcc8e45f8a094db2ffe22a046f29ac83f3656
parentc1edba3137b371ea8aba60e5a111a1fa01c7b470 (diff)
STR 3460.b: fixed scrollbar update in widget_browser
Also fixed a bug where a Manu item was accessed by index, which already was out of sync.
-rw-r--r--fluid/Fl_Type.cxx94
-rw-r--r--fluid/Fl_Window_Type.cxx8
-rw-r--r--fluid/fluid.cxx4
-rw-r--r--fluid/fluid.h1
-rw-r--r--fluid/widget_browser.cxx94
-rw-r--r--fluid/widget_browser.h37
6 files changed, 155 insertions, 83 deletions
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
index 68094850f..cda6b7601 100644
--- a/fluid/Fl_Type.cxx
+++ b/fluid/Fl_Type.cxx
@@ -147,6 +147,7 @@ static void delete_children(Fl_Type *p) {
for (f = p; f && f->next && f->next->level > p->level; f = f->next) {/*empty*/}
for (; f != p; ) {
Fl_Type *g = f->prev;
+ widget_browser->deleting(f);
delete f;
f = g;
}
@@ -158,6 +159,7 @@ void delete_all(int selected_only) {
if (f->selected || !selected_only) {
delete_children(f);
Fl_Type *g = f->next;
+ widget_browser->deleting(f);
delete f;
f = g;
} else f = f->next;
@@ -250,13 +252,24 @@ const char* Fl_Type::title() {
return type_name();
}
-// add a list of widgets as a new child of p:
+/**
+ Add this list/tree of widgets as a new child of p.
+
+ \c this is not part of the widget browser. \c p should be in the
+ widget_browser, so \c Fl_Type::first and \c Fl_Type::last are valid for \c p.
+
+ This methods updates the widget_browser.
+
+ \param[in] p insert \c this tree as a child of \c p
+ */
void Fl_Type::add(Fl_Type *p) {
if (p && parent == p) return;
undo_checkpoint();
parent = p;
+ // p is not in the Widget_Browser, so we must run the linked list to find the last entry
Fl_Type *end = this;
while (end->next) end = end->next;
+ // run the list again to set the future node levels
Fl_Type *q;
int newlevel;
if (p) {
@@ -268,6 +281,7 @@ void Fl_Type::add(Fl_Type *p) {
}
for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
level = newlevel;
+ // now link this tree after p
if (q) {
prev = q->prev;
prev->next = this;
@@ -283,28 +297,52 @@ void Fl_Type::add(Fl_Type *p) {
last = end;
prev = end->next = 0;
}
+ // tell this that it was added, so it can update itself
if (p) p->add_child(this,0);
open_ = 1;
fixvisible(this);
set_modflag(1);
+ // run the p tree a last time to make sure the widget_browser updates correctly
+ Fl_Type *a = p;
+ for (Fl_Type *t = this; t && a != end; a = t, t = t->next)
+ widget_browser->inserting(a, t);
widget_browser->redraw();
}
-// add to a parent before another widget:
+/**
+ Add this list/tree of widgets as a new sibling before p.
+
+ \c this is not part of the widget browser. \c p should be in the
+ widget_browser, so \c Fl_Type::first and \c Fl_Type::last are valid for \c p.
+
+ This methods updates the widget_browser.
+
+ \param[in] p insert \c this tree as a child of \c p
+ */
void Fl_Type::insert(Fl_Type *g) {
+ // p is not in the Widget_Browser, so we must run the linked list to find the last entry
Fl_Type *end = this;
while (end->next) end = end->next;
+ // this wil get the sam parent as g
parent = g->parent;
+ // run the list again to set the future node levels
int newlevel = g->level;
visible = g->visible;
for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level;
level = newlevel;
+ // insert this in the list before g
prev = g->prev;
if (prev) prev->next = this; else first = this;
end->next = g;
g->prev = end;
fixvisible(this);
+ // tell parent that it has a new child, so it can update itself
if (parent) parent->add_child(this, g);
+ // run this tree a last time to make sure the widget_browser updates correctly
+ Fl_Type *a = prev;
+ for (Fl_Type *t = this; t && a != end; a = t, t = t->next)
+ if (a)
+ widget_browser->inserting(a, t);
widget_browser->redraw();
}
@@ -326,27 +364,39 @@ int Fl_Type::msgnum() {
/**
Remove this node and all its children from the parent node.
+
+ This does not delete anything. The resulting list//tree will no longer be in
+ the widget_browser, so \c Fl_Type::first and \c Fl_Type::last do not apply
+ to it.
+
\return the node that follows this node after the operation; can be NULL
*/
Fl_Type *Fl_Type::remove() {
- // -- find the last child of this node
+ // find the last child of this node
Fl_Type *end = this;
for (;;) {
- if (!end->next || end->next->level <= level) break;
+ if (!end->next || end->next->level <= level)
+ break;
end = end->next;
}
- // -- unlink this node from the previous one
- if (prev) prev->next = end->next;
- else first = end->next;
- // -- unlink the last child from their next node
- if (end->next) end->next->prev = prev;
- else last = prev;
+ // unlink this node from the previous one
+ if (prev)
+ prev->next = end->next;
+ else
+ first = end->next;
+ // unlink the last child from their next node
+ if (end->next)
+ end->next->prev = prev;
+ else
+ last = prev;
Fl_Type *r = end->next;
prev = end->next = 0;
- // -- allow the parent to update changes in the UI
+ // allow the parent to update changes in the UI
if (parent) parent->remove_child(this);
parent = 0;
- widget_browser->redraw_lines();
+ // tell the widget_browser that we removed some nodes
+ for (Fl_Type *t = this; t; t = t->next)
+ widget_browser->deleting(t);
widget_browser->redraw();
selection_changed(0);
return r;
@@ -388,14 +438,23 @@ void Fl_Type::open() {
printf("Open of '%s' is not yet implemented\n",type_name());
}
-// move f (and its children) into list before g:
// returns pointer to whatever is after f & children
+
+/**
+ Move this node (and its children) into list before g.
+ \param[in] p move \c this tree before \c p
+ */
void Fl_Type::move_before(Fl_Type* g) {
if (level != g->level) printf("move_before levels don't match! %d %d\n",
level, g->level);
+ // Find the last child in the list
Fl_Type* n;
- for (n = next; n && n->level > level; n = n->next) {/*empty*/}
+ for (n = next; n && n->level > level; n = n->next) ;
if (n == g) return;
+ // Tell the widget browser that we delete them
+ for (n = next; n && n->level > level; n = n->next)
+ widget_browser->deleting(n);
+ // now link this tree before g
Fl_Type *l = n ? n->prev : Fl_Type::last;
prev->next = n;
if (n) n->prev = prev; else Fl_Type::last = prev;
@@ -403,8 +462,13 @@ void Fl_Type::move_before(Fl_Type* g) {
l->next = g;
if (prev) prev->next = this; else Fl_Type::first = this;
g->prev = l;
+ // tell parent that it has a new child, so it can update itself
if (parent && is_widget()) parent->move_child(this,g);
- widget_browser->inserting(g, this);
+ // run this tree a last time to make sure the widget_browser updates correctly
+ Fl_Type *a = prev;
+ for (Fl_Type *t = this; t && a != n; a = t, t = t->next)
+ if (a)
+ widget_browser->inserting(a, t);
widget_browser->display(this);
widget_browser->redraw();
}
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
index c42d62af7..ea2e4da54 100644
--- a/fluid/Fl_Window_Type.cxx
+++ b/fluid/Fl_Window_Type.cxx
@@ -1089,7 +1089,7 @@ extern Fl_Menu_Item Main_Menu[];
// Calculate new bounding box of selected widgets:
void Fl_Window_Type::fix_overlay() {
- Main_Menu[40].label("Hide O&verlays");
+ overlay_item->label("Hide O&verlays");
overlays_invisible = 0;
recalc = 1;
((Overlay_Window *)(this->o))->redraw_overlay();
@@ -1120,8 +1120,10 @@ void redraw_overlays() {
void toggle_overlays(Fl_Widget *,void *) {
overlays_invisible = !overlays_invisible;
- if (overlays_invisible) Main_Menu[40].label("Show O&verlays");
- else Main_Menu[40].label("Hide O&verlays");
+ if (overlays_invisible)
+ overlay_item->label("Show O&verlays");
+ else
+ overlay_item->label("Hide O&verlays");
for (Fl_Type *o=Fl_Type::first; o; o=o->next)
if (o->is_window()) {
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
index 0779e600d..7fe776fa9 100644
--- a/fluid/fluid.cxx
+++ b/fluid/fluid.cxx
@@ -127,6 +127,9 @@ Fl_Menu_Item *widgetbin_item = NULL;
/// Menuitem to show or hide the source view, label will change if view is visible.
Fl_Menu_Item *sourceview_item = NULL;
+/// Menuitem to show or hide the editing overlay, label will change if overlay visibility changes.
+Fl_Menu_Item *overlay_item = NULL;
+
////////////////////////////////////////////////////////////////
/// Filename of the current .fl design file
@@ -1426,6 +1429,7 @@ void make_main_window() {
history_item = (Fl_Menu_Item*)main_menubar->find_item(open_history_cb);
widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb);
sourceview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_sourceview_cb);
+ overlay_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_overlays);
main_menubar->global();
fill_in_New_Menu();
main_window->end();
diff --git a/fluid/fluid.h b/fluid/fluid.h
index e2370359f..20045ab06 100644
--- a/fluid/fluid.h
+++ b/fluid/fluid.h
@@ -63,6 +63,7 @@ extern Fl_Menu_Item *save_item;
extern Fl_Menu_Item *history_item;
extern Fl_Menu_Item *widgetbin_item;
extern Fl_Menu_Item *sourceview_item;
+extern Fl_Menu_Item *overlay_item;
extern int modflag;
diff --git a/fluid/widget_browser.cxx b/fluid/widget_browser.cxx
index 6d4d1028a..7996d905e 100644
--- a/fluid/widget_browser.cxx
+++ b/fluid/widget_browser.cxx
@@ -47,26 +47,26 @@ Widget_Browser *widget_browser = NULL;
Shortcut to have the widget browser graphics refreshed soon.
*/
void redraw_browser() {
- widget_browser->redraw();
+ widget_browser->redraw();
}
/**
Shortcut to create the widget browser.
*/
Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
- return (widget_browser = new Widget_Browser(x,y,w,h));
+ return (widget_browser = new Widget_Browser(x,y,w,h));
}
/**
Make sure thet the caller is visible in the widget browser.
\param[in] caller scroll the browser in y so that caller
- is visible (may be NULL)
+ is visible (may be NULL)
*/
void redraw_widget_browser(Fl_Type *caller)
{
- if (caller)
- widget_browser->display(caller);
- widget_browser->redraw();
+ if (caller)
+ widget_browser->display(caller);
+ widget_browser->redraw();
}
/**
@@ -75,7 +75,7 @@ void redraw_widget_browser(Fl_Type *caller)
\oaram[in] v the new selection state (1=select, 0=de-select)
*/
void select(Fl_Type *o, int v) {
- widget_browser->select(o,v,1);
+ widget_browser->select(o,v,1);
}
/**
@@ -83,14 +83,14 @@ void select(Fl_Type *o, int v) {
\param[in] o select this node
*/
void select_only(Fl_Type *o) {
- widget_browser->select_only(o,1);
+ widget_browser->select_only(o,1);
}
/**
Deselect all nodes in the widget browser.
*/
void deselect() {
- widget_browser->deselect();
+ widget_browser->deselect();
}
/**
@@ -119,20 +119,20 @@ void reveal_in_browser(Fl_Type *t) {
// ---- local functions
/**
- Copy the given string str to buffer p with no more than maxl characters.
+ Copy the given string str to buffer p with no more than maxl characters.
- Add "..." if string was truncated.
+ Add "..." if string was truncated.
- Quote characters are NOT counted.
+ Quote characters are NOT counted.
- \param[out] p return the resulting string in this buffer, terminated with
+ \param[out] p return the resulting string in this buffer, terminated with
a NUL byte
- \param[in] str copy this string; utf8 aware
- \param[in] maxl maximum number of letter to copy until we print
+ \param[in] str copy this string; utf8 aware
+ \param[in] maxl maximum number of letter to copy until we print
the elipsis (...)
- \param[in] auote if set, the resulting string is embedded in double quotes
- \returns pointer to end of string (before terminating null byte).
- \note the buffer p must be large enough to hold (4 * (maxl+1) + 1) bytes
+ \param[in] auote if set, the resulting string is embedded in double quotes
+ \returns pointer to end of string (before terminating null byte).
+ \note the buffer p must be large enough to hold (4 * (maxl+1) + 1) bytes
or (4 * (maxl+1) + 3) bytes if quoted, e.g. "123..." because each UTF-8
character can consist of 4 bytes, "..." adds 3 bytes, quotes '""' add two
bytes, and the terminating null byte adds another byte.
@@ -177,7 +177,7 @@ static char *copy_trunc(char *p, const char *str, int maxl, int quote)
*/
Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l)
: Fl_Browser_(X,Y,W,H,l),
- pushedtitle(NULL)
+pushedtitle(NULL)
{
type(FL_MULTI_BROWSER);
Fl_Widget::callback(callback_stub);
@@ -254,26 +254,26 @@ int Widget_Browser::incr_height() const {
}
/**
- Draw an item in the widget browser.
+ Draw an item in the widget browser.
- A browser line starts with a variable size space. This space directly
- relates to the level of the type entry.
+ A browser line starts with a variable size space. This space directly
+ relates to the level of the type entry.
- If this type has the ability to store children, a triangle follows,
- pointing right (closed) or pointing down (open, children shown).
+ If this type has the ability to store children, a triangle follows,
+ pointing right (closed) or pointing down (open, children shown).
- Next follows an icon that is specific to the type. This makes it easy to
- spot certain types.
+ Next follows an icon that is specific to the type. This makes it easy to
+ spot certain types.
- Now follows some text. For classes and widgets, this is the type itself,
- followed by the name of the object. Other objects show their content as
- text, possibly abbreviated with an ellipsis.
+ Now follows some text. For classes and widgets, this is the type itself,
+ followed by the name of the object. Other objects show their content as
+ text, possibly abbreviated with an ellipsis.
- \param v v is a pointer to the actual widget type and can be cast safely
- to Fl_Type
- \param X,Y these give the position in window coordinates of the top left
- corner of this line
-*/
+ \param v v is a pointer to the actual widget type and can be cast safely
+ to Fl_Type
+ \param X,Y these give the position in window coordinates of the top left
+ corner of this line
+ */
void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
// cast to a more general type
Fl_Type *l = (Fl_Type *)v;
@@ -427,19 +427,19 @@ void Widget_Browser::callback() {
}
/**
- Override the event handling for this browser.
-
- The vertical mouse position corresponds to an entry in the type tree.
- The horizontal position has the following hot zones:
- - 0-3 is the widget frame and ignored
- - the next hot zone starts 12*indent pixels further to the right
- - the next 13 pixels refer to the arrow that indicates children for the item
- - 18 pixels follow for the icon
- - the remaining part is filled with text
-
- \param[in] e the incoming event type
- \return 0 if the event is not supported, and 1 if the event was "used up"
-*/
+ Override the event handling for this browser.
+
+ The vertical mouse position corresponds to an entry in the type tree.
+ The horizontal position has the following hot zones:
+ - 0-3 is the widget frame and ignored
+ - the next hot zone starts 12*indent pixels further to the right
+ - the next 13 pixels refer to the arrow that indicates children for the item
+ - 18 pixels follow for the icon
+ - the remaining part is filled with text
+
+ \param[in] e the incoming event type
+ \return 0 if the event is not supported, and 1 if the event was "used up"
+ */
int Widget_Browser::handle(int e) {
static Fl_Type *title;
Fl_Type *l;
diff --git a/fluid/widget_browser.h b/fluid/widget_browser.h
index c00d45052..dfcd4db35 100644
--- a/fluid/widget_browser.h
+++ b/fluid/widget_browser.h
@@ -34,29 +34,30 @@ extern void reveal_in_browser(Fl_Type *t);
class Widget_Browser : public Fl_Browser_
{
- friend class Fl_Type;
+ friend class Fl_Type;
- static void callback_stub(Fl_Widget *o, void *) {
- ((Widget_Browser *)o)->callback();
- }
+ static void callback_stub(Fl_Widget *o, void *) {
+ ((Widget_Browser *)o)->callback();
+ }
- Fl_Type* pushedtitle;
+ Fl_Type* pushedtitle;
- // required routines for Fl_Browser_ subclass:
- void *item_first() const ;
- void *item_next(void *) const ;
- void *item_prev(void *) const ;
- int item_selected(void *) const ;
- void item_select(void *,int);
- int item_width(void *) const ;
- int item_height(void *) const ;
- void item_draw(void *,int,int,int,int) const ;
- int incr_height() const ;
+ // required routines for Fl_Browser_ subclass:
+ void *item_first() const ;
+ void *item_next(void *) const ;
+ void *item_prev(void *) const ;
+ int item_selected(void *) const ;
+ void item_select(void *,int);
+ int item_width(void *) const ;
+ int item_height(void *) const ;
+ void item_draw(void *,int,int,int,int) const ;
+ int incr_height() const ;
public:
- int handle(int);
- void callback();
- Widget_Browser(int,int,int,int,const char * =0);
+ Widget_Browser(int,int,int,int,const char * =NULL);
+ int handle(int);
+ void callback();
+ void deleting(Fl_Type *inType) { Fl_Browser_::deleting((void*)inType); }
};
#endif // _FLUID_WIDGET_BROWSER_H