diff options
Diffstat (limited to 'fluid')
| -rw-r--r-- | fluid/Fl_Group_Type.cxx | 3 | ||||
| -rw-r--r-- | fluid/Fl_Type.cxx | 35 | ||||
| -rw-r--r-- | fluid/Fl_Window_Type.cxx | 2 | ||||
| -rw-r--r-- | fluid/Shortcut_Button.cxx | 3 | ||||
| -rw-r--r-- | fluid/fluid.cxx | 17 | ||||
| -rw-r--r-- | fluid/undo.cxx | 12 | ||||
| -rw-r--r-- | fluid/widget_browser.cxx | 74 | ||||
| -rw-r--r-- | fluid/widget_browser.h | 7 |
8 files changed, 121 insertions, 32 deletions
diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx index d5a832b17..eab62cb77 100644 --- a/fluid/Fl_Group_Type.cxx +++ b/fluid/Fl_Group_Type.cxx @@ -23,6 +23,7 @@ #include "fluid.h" #include "file.h" #include "code.h" +#include "widget_browser.h" #include <FL/Fl.H> #include <FL/Fl_Group.H> @@ -90,6 +91,7 @@ void group_cb(Fl_Widget *, void *) { t = nxt; } fix_group_size(n); + widget_browser->rebuild(); } void ungroup_cb(Fl_Widget *, void *) { @@ -114,6 +116,7 @@ void ungroup_cb(Fl_Widget *, void *) { n = nxt; } delete q; + widget_browser->rebuild(); } //////////////////////////////////////////////////////////////// diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx index 5608969ea..cbaab7b5e 100644 --- a/fluid/Fl_Type.cxx +++ b/fluid/Fl_Type.cxx @@ -112,7 +112,9 @@ void select_none_cb(Fl_Widget *,void *) { selection_changed(p); } -// move selected widgets in their parent's list: +/** + Callback to move all selected items before their previous unselected sibling. + */ void earlier_cb(Fl_Widget*,void*) { Fl_Type *f; int mod = 0; @@ -129,8 +131,13 @@ void earlier_cb(Fl_Widget*,void*) { f = nxt; } if (mod) set_modflag(1); + widget_browser->display(Fl_Type::current); + widget_browser->rebuild(); } +/** + Callback to move all selected items after their next unselected sibling. + */ void later_cb(Fl_Widget*,void*) { Fl_Type *f; int mod = 0; @@ -147,6 +154,8 @@ void later_cb(Fl_Widget*,void*) { f = prv; } if (mod) set_modflag(1); + widget_browser->display(Fl_Type::current); + widget_browser->rebuild(); } static void delete_children(Fl_Type *p) { @@ -154,7 +163,6 @@ 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; } @@ -166,7 +174,6 @@ 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; @@ -275,7 +282,6 @@ Fl_Type::Fl_Type() { */ Fl_Type::~Fl_Type() { // warning: destructor only works for widgets that have been add()ed. - if (widget_browser) widget_browser->deleting(this); if (prev) prev->next = next; else first = next; if (next) next->prev = prev; else last = prev; if (Fl_Type::last==this) Fl_Type::last = prev; @@ -394,8 +400,6 @@ void Fl_Type::add(Fl_Type *p, Strategy strategy) { // 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(); } @@ -430,9 +434,6 @@ void Fl_Type::insert(Fl_Type *g) { 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(); } @@ -485,8 +486,6 @@ Fl_Type *Fl_Type::remove() { if (parent) parent->remove_child(this); parent = 0; // 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; @@ -532,18 +531,17 @@ void Fl_Type::open() { /** Move this node (and its children) into list before g. + Both `this` and `g` must be in the widget browser. + The caller must make sure that the widget browser is rebuilt correctly. \param[in] g move \c this tree before \c g */ 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; + Fl_Type *n; 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; @@ -554,13 +552,6 @@ void Fl_Type::move_before(Fl_Type* g) { 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); - // 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 21eefe868..59ab189aa 100644 --- a/fluid/Fl_Window_Type.cxx +++ b/fluid/Fl_Window_Type.cxx @@ -1239,6 +1239,8 @@ int Fl_Window_Type::handle(int event) { popupx = 0x7FFFFFFF; popupy = 0x7FFFFFFF; // mark as invalid (MAXINT) in_this_only = NULL; + widget_browser->display(Fl_Type::current); + widget_browser->rebuild(); return 1; } case FL_PUSH: diff --git a/fluid/Shortcut_Button.cxx b/fluid/Shortcut_Button.cxx index b22d385ce..cb18aa2cc 100644 --- a/fluid/Shortcut_Button.cxx +++ b/fluid/Shortcut_Button.cxx @@ -37,6 +37,7 @@ copied or otherwise examined. #include "Fl_Window_Type.h" #include "factory.h" #include "widget_panel.h" +#include "widget_browser.h" #include <FL/platform.H> #include <FL/Fl_Button.H> @@ -185,6 +186,8 @@ int Widget_Bin_Window_Button::handle(int inEvent) w->position(Fl::event_x_root(), Fl::event_y_root()); } } + widget_browser->display(Fl_Type::current); + widget_browser->rebuild(); } return Fl_Button::handle(inEvent); } diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index f584e182d..df8a713a2 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -517,9 +517,11 @@ void revert_cb(Fl_Widget *,void *) { undo_suspend(); if (!read_file(filename, 0)) { undo_resume(); + widget_browser->rebuild(); fl_message("Can't read %s: %s", filename, strerror(errno)); return; } + widget_browser->rebuild(); undo_resume(); set_modflag(0, 0); undo_clear(); @@ -652,6 +654,7 @@ void open_cb(Fl_Widget *, void *v) { undo_suspend(); if (!read_file(c, v!=0)) { undo_resume(); + widget_browser->rebuild(); fl_message("Can't read %s: %s", c, strerror(errno)); free((void *)filename); filename = oldfilename; @@ -659,6 +662,7 @@ void open_cb(Fl_Widget *, void *v) { return; } undo_resume(); + widget_browser->rebuild(); if (v) { // Inserting a file; restore the original filename... free((void *)filename); @@ -697,6 +701,7 @@ void open_history_cb(Fl_Widget *, void *v) { if (!read_file(filename, 0)) { undo_resume(); undo_clear(); + widget_browser->rebuild(); fl_message("Can't read %s: %s", filename, strerror(errno)); free((void *)filename); filename = oldfilename; @@ -706,6 +711,7 @@ void open_history_cb(Fl_Widget *, void *v) { set_modflag(0, 0); undo_resume(); undo_clear(); + widget_browser->rebuild(); if (oldfilename) { free((void *)oldfilename); oldfilename = 0L; @@ -737,6 +743,7 @@ void new_cb(Fl_Widget *, void *v) { delete_all(); set_filename(NULL); set_modflag(0, 0); + widget_browser->rebuild(); } /** @@ -836,6 +843,7 @@ void new_from_template_cb(Fl_Widget *w, void *v) { } } + widget_browser->rebuild(); set_modflag(0); undo_clear(); } @@ -975,7 +983,7 @@ void cut_cb(Fl_Widget *, void *) { while (p && p->selected) p = p->parent; delete_all(1); if (p) select_only(p); - //widget_browser->redraw_lines(); + widget_browser->rebuild(); } /** @@ -993,6 +1001,7 @@ void delete_cb(Fl_Widget *, void *) { while (p && p->selected) p = p->parent; delete_all(1); if (p) select_only(p); + widget_browser->rebuild(); } /** @@ -1011,9 +1020,12 @@ void paste_cb(Fl_Widget*, void*) { if (Fl_Type::current && Fl_Type::current->is_group()) strategy = kAddAsLastChild; if (!read_file(cutfname(), 1, strategy)) { + widget_browser->rebuild(); fl_message("Can't read %s: %s", cutfname(), strerror(errno)); } undo_resume(); + widget_browser->display(Fl_Type::current); + widget_browser->rebuild(); pasteoffset = 0; ipasteoffset += 10; force_parent = 0; @@ -1042,6 +1054,8 @@ void duplicate_cb(Fl_Widget*, void*) { fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); } fl_unlink(cutfname(1)); + widget_browser->display(Fl_Type::current); + widget_browser->rebuild(); undo_resume(); force_parent = 0; @@ -1052,6 +1066,7 @@ void duplicate_cb(Fl_Widget*, void*) { */ static void sort_cb(Fl_Widget *,void *) { sort((Fl_Type*)NULL); + widget_browser->rebuild(); } /** diff --git a/fluid/undo.cxx b/fluid/undo.cxx index 09f2867d9..b7377b89f 100644 --- a/fluid/undo.cxx +++ b/fluid/undo.cxx @@ -82,6 +82,7 @@ void redo_cb(Fl_Widget *, void *) { undo_suspend(); if (!read_file(undo_filename(undo_current + 1), 0)) { // Unable to read checkpoint file, don't redo... + widget_browser->rebuild(); undo_resume(); return; } @@ -90,6 +91,7 @@ void redo_cb(Fl_Widget *, void *) { // Update modified flag... set_modflag(undo_current != undo_save); + widget_browser->rebuild(); // Update undo/redo menu items... if (undo_current >= undo_last) Main_Menu[redo_item].deactivate(); @@ -109,18 +111,17 @@ void undo_cb(Fl_Widget *, void *) { undo_suspend(); // Undo first deletes all widgets which resets the widget_tree browser. - // Save the current scroll position, so we don;t scroll back to 0 at undo. - int x = widget_browser->hposition(); - int y = widget_browser->position(); + // Save the current scroll position, so we don't scroll back to 0 at undo. + if (widget_browser) widget_browser->save_scroll_position(); if (!read_file(undo_filename(undo_current - 1), 0)) { // Unable to read checkpoint file, don't undo... + widget_browser->rebuild(); undo_resume(); return; } // Restore old browser position. // Ideally, we would save the browser position insied the undo file. - widget_browser->hposition(x); - widget_browser->position(y); + if (widget_browser) widget_browser->restore_scroll_position(); undo_current --; @@ -130,6 +131,7 @@ void undo_cb(Fl_Widget *, void *) { // Update undo/redo menu items... if (undo_current <= 0) Main_Menu[undo_item].deactivate(); Main_Menu[redo_item].activate(); + widget_browser->rebuild(); undo_resume(); } diff --git a/fluid/widget_browser.cxx b/fluid/widget_browser.cxx index 901680205..ac1e9da2e 100644 --- a/fluid/widget_browser.cxx +++ b/fluid/widget_browser.cxx @@ -175,9 +175,11 @@ static char *copy_trunc(char *p, const char *str, int maxl, int quote) \todo It would be nice to be able to grab one or more nodes and mmove them within the hierarchy. */ -Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l) -: Fl_Browser_(X,Y,W,H,l), -pushedtitle(NULL) +Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l) : + Fl_Browser_(X,Y,W,H,l), + pushedtitle(NULL), + saved_h_scroll_(0), + saved_v_scroll_(0) { type(FL_MULTI_BROWSER); Fl_Widget::callback(callback_stub); @@ -504,4 +506,70 @@ int Widget_Browser::handle(int e) { return Fl_Browser_::handle(e); } +/** + Save the current scrollbar postion during rebuild. + */ +void Widget_Browser::save_scroll_position() { + saved_h_scroll_ = hposition(); + saved_v_scroll_ = position(); +} + +/** + Restore the previous scrollbar postion after rebuild. + */ +void Widget_Browser::restore_scroll_position() { + hposition(saved_h_scroll_); + position(saved_v_scroll_); +} + +/** + Rebuild the browser layout to reflect multiple changes. + This clears internal caches, recalculates the scroll bar sizes, and + sends a redraw() request to the widget. + */ +void Widget_Browser::rebuild() { + save_scroll_position(); + new_list(); + damage(FL_DAMAGE_SCROLL); + redraw(); + restore_scroll_position(); +} + +/** + Rebuild the browser layout and make sure that the given item is visible. + \param[in] inNode pointer to a widget node derived from Fl_Type. + */ +void Widget_Browser::display(Fl_Type *inNode) { + if (!inNode) { + // Alternative: find the first (last?) visible selected item. + return; + } + // remeber our current scroll position + int currentV = position(), newV = currentV; + int nodeV = 0; + // find the inNode in the tree and check, if it is already visible + Fl_Type *p=Fl_Type::first; + for ( ; p && p!=inNode; p=p->next) { + if (p->visible) + nodeV += item_height(p); + } + if (p) { + int xx, yy, ww, hh; + bbox(xx, yy, ww, hh); + int frame_top = xx-x(); + int frame_bottom = frame_top + hh; + int node_height = item_height(inNode); + int margin_height = 2 * item_quick_height(inNode); + if (margin_height>hh/2) margin_height = hh/2; + // is the inNode above the current scroll position? + if (nodeV<currentV+margin_height) + newV = nodeV - margin_height; + else if (nodeV>currentV+frame_bottom-margin_height-node_height) + newV = nodeV - frame_bottom + margin_height + node_height; + if (newV<0) + newV = 0; + } + if (newV!=currentV) + position(newV); +} diff --git a/fluid/widget_browser.h b/fluid/widget_browser.h index dfcd4db35..f0e68f364 100644 --- a/fluid/widget_browser.h +++ b/fluid/widget_browser.h @@ -41,6 +41,8 @@ class Widget_Browser : public Fl_Browser_ } Fl_Type* pushedtitle; + int saved_h_scroll_; + int saved_v_scroll_; // required routines for Fl_Browser_ subclass: void *item_first() const ; @@ -57,7 +59,10 @@ public: Widget_Browser(int,int,int,int,const char * =NULL); int handle(int); void callback(); - void deleting(Fl_Type *inType) { Fl_Browser_::deleting((void*)inType); } + void save_scroll_position(); + void restore_scroll_position(); + void rebuild(); + void display(Fl_Type *); }; #endif // _FLUID_WIDGET_BROWSER_H |
