]> git.tdb.fi Git - libs/gltk.git/commitdiff
Defer widget rebuild to just before they are rendered
authorMikko Rasa <tdb@tdb.fi>
Mon, 23 Sep 2019 20:59:24 +0000 (23:59 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 23 Sep 2019 20:59:24 +0000 (23:59 +0300)
This improves performance especially with complex widgets like Entry.

14 files changed:
source/button.cpp
source/container.cpp
source/container.h
source/dropdown.cpp
source/entry.cpp
source/image.cpp
source/label.cpp
source/list.cpp
source/root.cpp
source/root.h
source/slider.cpp
source/toggle.cpp
source/widget.cpp
source/widget.h

index fadd00a0cafedc4dd0d1996f8be7a0ec6ae8fdaf..abdc1f677b0ff379220813ae67cc0a16187c561a 100644 (file)
@@ -33,13 +33,13 @@ void Button::set_text(const std::string &t)
 {
        text = t;
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 void Button::set_icon(const GL::Texture2D *i)
 {
        icon = i;
-       rebuild();
+       mark_rebuild();
 }
 
 void Button::rebuild_special(const Part &part)
index e99d9939aefdf0b951feba1572804d95e38bd5cf..28e0e2feafff2105017c61bb35dda55656cf6d0e 100644 (file)
@@ -18,7 +18,8 @@ Container::Container():
        pointer_grabbed(false),
        input_focus(0),
        saved_input_focus(0),
-       touch_focus(0)
+       touch_focus(0),
+       children_rebuild_needed(false)
 { }
 
 Container::~Container()
@@ -33,6 +34,7 @@ void Container::add(Widget &wdg)
        children.push_back(create_child(&wdg));
        if(wdg.get_animation_interval())
                check_animation_interval();
+       children_rebuild_needed = true;
        on_child_added(wdg);
 }
 
@@ -185,6 +187,18 @@ void Container::check_animation_interval()
                set_animation_interval(shortest);
 }
 
+void Container::rebuild_hierarchy()
+{
+       Widget::rebuild_hierarchy();
+
+       if(children_rebuild_needed)
+       {
+               children_rebuild_needed = false;
+               for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
+                       (*i)->widget->rebuild_hierarchy();
+       }
+}
+
 void Container::button_press(int x, int y, unsigned btn)
 {
        if(Widget *child = get_pointer_target(x, y, false))
@@ -382,6 +396,7 @@ Container::Child::Child(Container &c, Widget *w):
        widget->signal_grab_pointer.connect(sigc::mem_fun(this, &Child::grab_pointer));
        widget->signal_ungrab_pointer.connect(sigc::mem_fun(this, &Child::ungrab_pointer));
        widget->signal_request_animation.connect(sigc::mem_fun(this, &Child::request_animation));
+       widget->signal_rebuild_needed.connect(sigc::mem_fun(this, &Child::rebuild_needed));
 }
 
 Container::Child::~Child()
@@ -436,5 +451,11 @@ void Container::Child::request_animation(const Time::TimeDelta &interval)
        container.check_animation_interval();
 }
 
+void Container::Child::rebuild_needed()
+{
+       container.children_rebuild_needed = true;
+       container.signal_rebuild_needed.emit();
+}
+
 } // namespace GLtk
 } // namespace Msp
index d98ce394c0506d9ad522c153aad1f875d10efd81..a80cc4e214551cda4348ee10a2986024b030684c 100644 (file)
@@ -34,6 +34,7 @@ protected:
                void grab_pointer();
                void ungrab_pointer();
                void request_animation(const Time::TimeDelta &);
+               void rebuild_needed();
        };
 
        std::list<Child *> children;
@@ -44,6 +45,7 @@ protected:
        Widget *input_focus;
        Widget *saved_input_focus;
        Widget *touch_focus;
+       bool children_rebuild_needed;
 
        Container();
 public:
@@ -72,6 +74,9 @@ public:
 private:
        void check_animation_interval();
 
+protected:
+       virtual void rebuild_hierarchy();
+
 public:
        virtual void button_press(int, int, unsigned);
        virtual void button_release(int, int, unsigned);
index f922001e2db0764c38000ec046bb9cd1c53150e4..1084612304f03b68a303af130aa2b3bd3b1b2f82 100644 (file)
@@ -191,7 +191,7 @@ void Dropdown::list_item_selected(unsigned index)
        text.set(list.get_data().get_string(index));
 
        signal_item_selected.emit(index);
-       rebuild();
+       mark_rebuild();
 }
 
 void Dropdown::list_selection_cleared()
index b00fc6bcdb3e4f4781b7bcb12dcd154a1de8cb61..ed0d7e2081a270a90894277f619f33c4daf4aeb5 100644 (file)
@@ -84,7 +84,7 @@ void Entry::insert(unsigned pos, const string &t)
        if(multiline)
                check_view_range();
 
-       rebuild();
+       mark_rebuild();
 }
 
 void Entry::erase(unsigned pos, unsigned len)
@@ -114,7 +114,7 @@ void Entry::erase(unsigned pos, unsigned len)
        if(multiline)
                check_view_range();
 
-       rebuild();
+       mark_rebuild();
 }
 
 bool Entry::get_selection(unsigned &start, unsigned &end) const
@@ -158,7 +158,7 @@ void Entry::set_multiline(bool m)
                        add(*slider);
                        slider->set_step(1);
                        slider->signal_value_changed.connect(sigc::mem_fun(this, &Entry::slider_value_changed));
-                       rebuild();
+                       mark_rebuild();
                }
                check_view_range();
        }
@@ -366,7 +366,7 @@ bool Entry::navigate(Navigation nav)
 void Entry::animate(const Time::TimeDelta &)
 {
        cursor_blink = !cursor_blink;
-       rebuild();
+       mark_rebuild();
 }
 
 void Entry::on_size_change()
@@ -429,7 +429,7 @@ void Entry::set_edit_position(unsigned ep, bool select)
 
        if(multiline)
                check_view_range();
-       rebuild();
+       mark_rebuild();
 }
 
 void Entry::erase_selection(bool emit_change)
@@ -495,7 +495,7 @@ void Entry::slider_value_changed(double value)
                first_row = text.get_n_lines()-visible_rows-static_cast<unsigned>(value);
                if(first_row!=old_first_row)
                        signal_scroll_position_changed.emit(first_row);
-               rebuild();
+               mark_rebuild();
        }
 }
 
index 1da782d28a2579e66d4079d8ffb915f703627255..bc9185672d13b5cb070333857e5a37c90143f6df 100644 (file)
@@ -39,7 +39,7 @@ void Image::set_image(const GL::Texture2D *i)
        image = i;
        icon_name = string();
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 void Image::set_icon(const string &n)
@@ -51,7 +51,7 @@ void Image::set_icon(const string &n)
 void Image::set_keep_aspect(bool ka)
 {
        keep_aspect = ka;
-       rebuild();
+       mark_rebuild();
 }
 
 void Image::update_icon()
@@ -66,7 +66,7 @@ void Image::update_icon()
                        else
                                image = &root->get_resources().get<GL::Texture2D>(icon_name);
                        signal_autosize_changed.emit();
-                       rebuild();
+                       mark_rebuild();
                        return;
                }
        }
index 263b2a4229d23c7c80747e37f3a66f880f2f5140..033bfd9296b07051bdd04691d0ba6d2d65985fff 100644 (file)
@@ -16,7 +16,7 @@ void Label::set_text(const string &t)
 {
        text = t;
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 void Label::autosize_special(const Part &part, Geometry &ageom) const
index 9eff09bb47566a1a6785ee909327da878f8a29ce..5493947c566b025df46b6aebbe26f865f3432f3f 100644 (file)
@@ -136,7 +136,7 @@ void List::set_data(ListData &d)
 void List::items_changed()
 {
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 List::Item *List::create_item(unsigned index)
@@ -404,7 +404,7 @@ void List::item_autosize_changed(Item *item)
 {
        item->autosize();
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 void List::reposition_items(bool record_rows)
@@ -527,7 +527,7 @@ void List::slider_value_changed(double value)
        if(max_scroll>0 && !ignore_slider_change)
        {
                first_row = max_scroll-static_cast<unsigned>(value);
-               rebuild();
+               mark_rebuild();
        }
 }
 
index 713477488a13ce6a5c2954c5daba94cc318ff487..64c7dd5548fa2af424df645ac414860221dfc482 100644 (file)
@@ -144,8 +144,10 @@ void Root::tick()
        }
 }
 
-void Root::render() const
+void Root::render()
 {
+       rebuild_hierarchy();
+
        GL::Bind bind_blend(GL::Blend::alpha());
 
        GL::Renderer renderer(&camera);
@@ -153,6 +155,11 @@ void Root::render() const
        Widget::render(renderer);
 }
 
+void Root::setup_frame(GL::Renderer &)
+{
+       rebuild_hierarchy();
+}
+
 void Root::render(GL::Renderer &renderer, const GL::Tag &tag) const
 {
        if(tag.id)
index 73ca276ed968a0e5241b5053c67ae89c96de39e6..effa55628262b484b39ab97980721af41b751498 100644 (file)
@@ -64,7 +64,8 @@ public:
        virtual unsigned get_height() const { return geom.h; }
 
        void tick();
-       void render() const;
+       void render();
+       virtual void setup_frame(GL::Renderer &);
        virtual void render(GL::Renderer &, const GL::Tag & = GL::Tag()) const;
 
 private:
index 1e763c639bf5309fba69d3a3ce3e680aba97eff1..5034b2475d8c46f20e4e09f2fe626c69c196d19a 100644 (file)
@@ -31,7 +31,7 @@ void Slider::set_value(double v)
        if(value!=old_value)
        {
                signal_value_changed.emit(value);
-               rebuild();
+               mark_rebuild();
        }
 }
 
index b0219fc82f8ec764b072404d067a2a1009daa392..daacd989af6999c9efb65385df569e2d063b2da3 100644 (file)
@@ -28,7 +28,7 @@ void Toggle::set_text(const string &t)
 {
        text = t;
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 void Toggle::set_exclusive(bool e)
index d6d57554fc5f324f02f22f48a48c5dbe3386903c..1c73d7640cc610c49ccb33f6e7f4b0fe315a83d0 100644 (file)
@@ -73,7 +73,7 @@ void Widget::set_geometry(const Geometry &g)
        if(size_changed)
        {
                on_size_change();
-               rebuild();
+               mark_rebuild();
        }
 }
 
@@ -141,7 +141,7 @@ void Widget::update_style()
 
        on_style_change();
        signal_autosize_changed.emit();
-       rebuild();
+       mark_rebuild();
 }
 
 void Widget::set_tooltip(const string &t)
@@ -184,7 +184,7 @@ void Widget::set_state(State mask, State bits)
        State old_state = state;
        state = (state&~mask)|bits;
        if(style && style->compare_states(old_state, state))
-               rebuild();
+               mark_rebuild();
 }
 
 void Widget::set_animation_interval(const Time::TimeDelta &iv)
@@ -201,6 +201,24 @@ void Widget::stop_animation()
        set_animation_interval(Time::zero);
 }
 
+void Widget::mark_rebuild()
+{
+       if(rebuild_needed)
+               return;
+
+       rebuild_needed = true;
+       signal_rebuild_needed.emit();
+}
+
+void Widget::rebuild_hierarchy()
+{
+       if(rebuild_needed)
+       {
+               rebuild_needed = false;
+               rebuild();
+       }
+}
+
 void Widget::rebuild()
 {
        if(!style)
index 2e8ef7ab09ae8002f4f1037b30dba36d4dc5c40e..7cbec37a5455e62957d7ad8e02ff0eda17f9fbad 100644 (file)
@@ -41,6 +41,7 @@ public:
        sigc::signal<void> signal_grab_pointer;
        sigc::signal<void> signal_ungrab_pointer;
        sigc::signal<void, const Time::TimeDelta &> signal_request_animation;
+       sigc::signal<void> signal_rebuild_needed;
 
 protected:
        Geometry geom;
@@ -52,6 +53,7 @@ protected:
        Container *parent;
        std::string tooltip;
        PartCache part_cache;
+       bool rebuild_needed;
        Time::TimeDelta anim_interval;
 
        Widget();
@@ -133,6 +135,8 @@ public:
        const Time::TimeDelta &get_animation_interval() const { return anim_interval; }
 
 protected:
+       void mark_rebuild();
+       virtual void rebuild_hierarchy();
        void rebuild();
        virtual void rebuild_special(const Part &);