This improves performance especially with complex widgets like Entry.
{
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)
pointer_grabbed(false),
input_focus(0),
saved_input_focus(0),
- touch_focus(0)
+ touch_focus(0),
+ children_rebuild_needed(false)
{ }
Container::~Container()
children.push_back(create_child(&wdg));
if(wdg.get_animation_interval())
check_animation_interval();
+ children_rebuild_needed = true;
on_child_added(wdg);
}
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))
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()
container.check_animation_interval();
}
+void Container::Child::rebuild_needed()
+{
+ container.children_rebuild_needed = true;
+ container.signal_rebuild_needed.emit();
+}
+
} // namespace GLtk
} // namespace Msp
void grab_pointer();
void ungrab_pointer();
void request_animation(const Time::TimeDelta &);
+ void rebuild_needed();
};
std::list<Child *> children;
Widget *input_focus;
Widget *saved_input_focus;
Widget *touch_focus;
+ bool children_rebuild_needed;
Container();
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);
text.set(list.get_data().get_string(index));
signal_item_selected.emit(index);
- rebuild();
+ mark_rebuild();
}
void Dropdown::list_selection_cleared()
if(multiline)
check_view_range();
- rebuild();
+ mark_rebuild();
}
void Entry::erase(unsigned pos, unsigned len)
if(multiline)
check_view_range();
- rebuild();
+ mark_rebuild();
}
bool Entry::get_selection(unsigned &start, unsigned &end) const
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();
}
void Entry::animate(const Time::TimeDelta &)
{
cursor_blink = !cursor_blink;
- rebuild();
+ mark_rebuild();
}
void Entry::on_size_change()
if(multiline)
check_view_range();
- rebuild();
+ mark_rebuild();
}
void Entry::erase_selection(bool emit_change)
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();
}
}
image = i;
icon_name = string();
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
}
void Image::set_icon(const string &n)
void Image::set_keep_aspect(bool ka)
{
keep_aspect = ka;
- rebuild();
+ mark_rebuild();
}
void Image::update_icon()
else
image = &root->get_resources().get<GL::Texture2D>(icon_name);
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
return;
}
}
{
text = t;
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
}
void Label::autosize_special(const Part &part, Geometry &ageom) const
void List::items_changed()
{
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
}
List::Item *List::create_item(unsigned index)
{
item->autosize();
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
}
void List::reposition_items(bool record_rows)
if(max_scroll>0 && !ignore_slider_change)
{
first_row = max_scroll-static_cast<unsigned>(value);
- rebuild();
+ mark_rebuild();
}
}
}
}
-void Root::render() const
+void Root::render()
{
+ rebuild_hierarchy();
+
GL::Bind bind_blend(GL::Blend::alpha());
GL::Renderer renderer(&camera);
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)
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:
if(value!=old_value)
{
signal_value_changed.emit(value);
- rebuild();
+ mark_rebuild();
}
}
{
text = t;
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
}
void Toggle::set_exclusive(bool e)
if(size_changed)
{
on_size_change();
- rebuild();
+ mark_rebuild();
}
}
on_style_change();
signal_autosize_changed.emit();
- rebuild();
+ mark_rebuild();
}
void Widget::set_tooltip(const string &t)
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)
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)
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;
Container *parent;
std::string tooltip;
PartCache part_cache;
+ bool rebuild_needed;
Time::TimeDelta anim_interval;
Widget();
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 &);