From: Mikko Rasa Date: Wed, 26 Jun 2013 16:17:54 +0000 (+0300) Subject: Refactor widget autosizing X-Git-Url: http://git.tdb.fi/?p=libs%2Fgltk.git;a=commitdiff_plain;h=d2d5b4c4dedf90a42dd2baff8334318b1d000f64 Refactor widget autosizing Widget::autosize is no longer virtual. Instead there's autosize_special, which handles one part at a time. This way all the important checks and finalisations are done in one place. --- diff --git a/source/button.cpp b/source/button.cpp index 5582230..58fc134 100644 --- a/source/button.cpp +++ b/source/button.cpp @@ -16,31 +16,16 @@ Button::Button(const std::string &t): set_text(t); } -void Button::autosize() +void Button::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(const Part *text_part = style->get_part("text")) - { - const Sides &margin = text_part->get_margin(); - geom.w = max(geom.w, text.get_width()+margin.left+margin.right); - geom.h = max(geom.h, text.get_height()+margin.top+margin.bottom); - } - - if(icon) + if(part.get_name()=="text") + text.autosize(part, ageom); + else if(part.get_name()=="icon" && icon) { - if(const Part *icon_part = style->get_part("icon")) - { - const Sides &margin = icon_part->get_margin(); - geom.w = max(geom.w, icon->get_width()+margin.left+margin.right); - geom.h = max(geom.h, icon->get_height()+margin.top+margin.bottom); - } + const Sides &margin = part.get_margin(); + ageom.w = max(ageom.w, icon->get_width()+margin.left+margin.right); + ageom.h = max(ageom.h, icon->get_height()+margin.top+margin.bottom); } - - rebuild(); } void Button::set_text(const std::string &t) diff --git a/source/button.h b/source/button.h index e75ba9f..edf0b62 100644 --- a/source/button.h +++ b/source/button.h @@ -36,8 +36,10 @@ public: virtual const char *get_class() const { return "button"; } - virtual void autosize(); +private: + virtual void autosize_special(const Part &, Geometry &); +public: void set_text(const std::string &); void set_icon(const GL::Texture2D *); diff --git a/source/dropdown.cpp b/source/dropdown.cpp index ce0ba71..2aac55e 100644 --- a/source/dropdown.cpp +++ b/source/dropdown.cpp @@ -33,18 +33,16 @@ void Dropdown::init() list.signal_autosize_changed.connect(sigc::mem_fun(this, &Dropdown::list_autosize_changed)); } -void Dropdown::autosize() +void Dropdown::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - list.autosize(); - geom.w = max(geom.w, list.get_geometry().w); - - if(const Part *text_part = style->get_part("text")) + if(part.get_name()=="list") + { + list.autosize(); + ageom.w = max(ageom.w, list.get_geometry().w); + } + else if(part.get_name()=="text") { - const Sides &margin = text_part->get_margin(); + const Sides &margin = part.get_margin(); const GL::Font &font = style->get_font(); float font_size = style->get_font_size(); @@ -55,10 +53,10 @@ void Dropdown::autosize() unsigned w = static_cast(font.get_string_width(data.get_string(i))*font_size); max_w = max(max_w, w); } - geom.w = max(geom.w, max_w+margin.left+margin.right); + ageom.w = max(ageom.w, max_w+margin.left+margin.right); unsigned line_height = static_cast((font.get_ascent()-font.get_descent())*font_size); - geom.h = max(geom.h, line_height+margin.top+margin.bottom); + ageom.h = max(ageom.h, line_height+margin.top+margin.bottom); } rebuild(); diff --git a/source/dropdown.h b/source/dropdown.h index 43bde10..eaa29c1 100644 --- a/source/dropdown.h +++ b/source/dropdown.h @@ -38,8 +38,10 @@ private: public: virtual const char *get_class() const { return "dropdown"; } - virtual void autosize(); +private: + virtual void autosize_special(const Part &, Geometry &); +public: void set_data(ListData &d) { list.set_data(d); } ListData &get_data() { return list.get_data(); } const ListData &get_data() const { return list.get_data(); } diff --git a/source/entry.cpp b/source/entry.cpp index a635101..9129e1b 100644 --- a/source/entry.cpp +++ b/source/entry.cpp @@ -28,55 +28,40 @@ Entry::Entry(const string &t): set_text(t); } -void Entry::autosize() +void Entry::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(text_part) + if(part.get_name()=="text") { - const Sides &margin = text_part->get_margin(); + const Sides &margin = part.get_margin(); const GL::Font &font = style->get_font(); unsigned en_width = static_cast(font.get_string_width("n")*style->get_font_size()); - geom.w = max(geom.w, edit_width*en_width+margin.left+margin.right); + ageom.w = max(ageom.w, edit_width*en_width+margin.left+margin.right); unsigned line_height = static_cast((font.get_ascent()-font.get_descent())*style->get_font_size()); if(multiline) { unsigned line_spacing = style->get_font_size()*6/5; - geom.h = max(geom.h, line_height+line_spacing*(edit_height-1)+margin.top+margin.bottom); + ageom.h = max(ageom.h, line_height+line_spacing*(edit_height-1)+margin.top+margin.bottom); } else - geom.h = max(geom.h, line_height+margin.top+margin.bottom); + ageom.h = max(ageom.h, line_height+margin.top+margin.bottom); } - - if(multiline) + else if(part.get_name()=="slider" && multiline) { - if(const Part *slider_part = style->get_part("slider")) + Geometry sgeom = part.get_geometry(); + if(!sgeom.w || !sgeom.h) { - Geometry sgeom = slider_part->get_geometry(); - if(!sgeom.w || !sgeom.h) - { - slider->autosize(); - if(!sgeom.w) - sgeom.w = slider->get_geometry().w; - if(!sgeom.h) - sgeom.h = slider->get_geometry().h; - } - - const Sides &margin = slider_part->get_margin(); - geom.w = max(geom.w, sgeom.w+margin.left+margin.right); - geom.h = max(geom.h, sgeom.h+margin.top+margin.bottom); - - reposition_slider(); + slider->autosize(); + if(!sgeom.w) + sgeom.w = slider->get_geometry().w; + if(!sgeom.h) + sgeom.h = slider->get_geometry().h; } - check_view_range(); + const Sides &margin = part.get_margin(); + ageom.w = max(ageom.w, sgeom.w+margin.left+margin.right); + ageom.h = max(ageom.h, sgeom.h+margin.top+margin.bottom); } - - rebuild(); } void Entry::set_text(const string &t) diff --git a/source/entry.h b/source/entry.h index edea4c3..1594c68 100644 --- a/source/entry.h +++ b/source/entry.h @@ -41,8 +41,10 @@ public: virtual const char *get_class() const { return "entry"; } - virtual void autosize(); +private: + virtual void autosize_special(const Part &, Geometry &); +public: void set_text(const std::string &); const std::string &get_text() const { return text.get(); } diff --git a/source/hslider.cpp b/source/hslider.cpp index 837b2ba..35d0a41 100644 --- a/source/hslider.cpp +++ b/source/hslider.cpp @@ -12,19 +12,14 @@ HSlider::HSlider(): slider_size(1) { } -void HSlider::autosize() +void HSlider::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(const Part *slider_part = style->get_part("slider")) + if(part.get_name()=="slider") { - const Sides &margin = slider_part->get_margin(); - const Geometry &pgeom = slider_part->get_geometry(); - geom.w = std::max(geom.w, pgeom.w*3/2+margin.left+margin.right); - geom.h = std::max(geom.h, pgeom.h+margin.top+margin.bottom); + const Sides &margin = part.get_margin(); + const Geometry &pgeom = part.get_geometry(); + ageom.w = std::max(ageom.w, pgeom.w*3/2+margin.left+margin.right); + ageom.h = std::max(ageom.h, pgeom.h+margin.top+margin.bottom); } } diff --git a/source/hslider.h b/source/hslider.h index cb02527..cadae59 100644 --- a/source/hslider.h +++ b/source/hslider.h @@ -20,9 +20,8 @@ public: virtual const char *get_class() const { return "hslider"; } - virtual void autosize(); - private: + virtual void autosize_special(const Part &, Geometry &); virtual void rebuild_special(const Part &); public: diff --git a/source/image.cpp b/source/image.cpp index 2735ab6..8e14328 100644 --- a/source/image.cpp +++ b/source/image.cpp @@ -15,29 +15,22 @@ Image::Image(const GL::Texture2D *i): focusable = false; } -void Image::autosize() +void Image::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(const Part *image_part = style->get_part("image")) + if(part.get_name()=="image") { - const Sides &margin = image_part->get_margin(); + const Sides &margin = part.get_margin(); if(image) { - geom.w = max(geom.w, image->get_width()+margin.left+margin.right); - geom.h = max(geom.h, image->get_height()+margin.top+margin.bottom); + ageom.w = max(ageom.w, image->get_width()+margin.left+margin.right); + ageom.h = max(ageom.h, image->get_height()+margin.top+margin.bottom); } else { - geom.w = max(geom.w, margin.left+margin.right); - geom.h = max(geom.h, margin.top+margin.bottom); + ageom.w = max(ageom.w, margin.left+margin.right); + ageom.h = max(ageom.h, margin.top+margin.bottom); } } - - rebuild(); } void Image::set_image(const GL::Texture2D *i) diff --git a/source/image.h b/source/image.h index 234f19f..8c5a9d5 100644 --- a/source/image.h +++ b/source/image.h @@ -21,8 +21,10 @@ public: virtual const char *get_class() const { return "image"; } - virtual void autosize(); +private: + virtual void autosize_special(const Part &, Geometry &); +public: void set_image(const GL::Texture2D *); void set_keep_aspect(bool); diff --git a/source/label.cpp b/source/label.cpp index f426467..e6b7efb 100644 --- a/source/label.cpp +++ b/source/label.cpp @@ -13,23 +13,6 @@ Label::Label(const string &t) set_text(t); } -void Label::autosize() -{ - if(!style) - return; - - Widget::autosize(); - - if(const Part *text_part = style->get_part("text")) - { - const Sides &margin = text_part->get_margin(); - geom.w = max(geom.w, text.get_width()+margin.left+margin.right); - geom.h = max(geom.h, text.get_height()+margin.top+margin.bottom); - } - - rebuild(); -} - void Label::set_text(const string &t) { text = t; @@ -37,6 +20,12 @@ void Label::set_text(const string &t) rebuild(); } +void Label::autosize_special(const Part &part, Geometry &ageom) +{ + if(part.get_name()=="text") + text.autosize(part, ageom); +} + void Label::rebuild_special(const Part &part) { if(part.get_name()=="text") diff --git a/source/label.h b/source/label.h index 3e753dd..f227934 100644 --- a/source/label.h +++ b/source/label.h @@ -29,10 +29,10 @@ public: virtual const char *get_class() const { return "label"; } - virtual void autosize(); void set_text(const std::string &); private: + virtual void autosize_special(const Part &, Geometry &); virtual void rebuild_special(const Part &); virtual void on_style_change(); diff --git a/source/layout.cpp b/source/layout.cpp index 743b30e..7902902 100644 --- a/source/layout.cpp +++ b/source/layout.cpp @@ -317,12 +317,13 @@ void Layout::update() (*i)->widget.set_geometry((*i)->geom); } -void Layout::autosize() +void Layout::autosize(Geometry &geom) { solve_constraints(HORIZONTAL, AUTOSIZE); solve_constraints(VERTICAL, AUTOSIZE); - container->set_size(autosize_geom.w, autosize_geom.h); + geom.w = max(geom.w, autosize_geom.w); + geom.h = max(geom.h, autosize_geom.h); } void Layout::solve_constraints(int dir, SolveMode mode) diff --git a/source/layout.h b/source/layout.h index a8ea3bf..38d45ba 100644 --- a/source/layout.h +++ b/source/layout.h @@ -226,7 +226,7 @@ public: void set_ghost(Widget &, bool); void update(); - void autosize(); + void autosize(Geometry &); private: void solve_constraints(int, SolveMode); diff --git a/source/list.cpp b/source/list.cpp index c74af90..b969ec0 100644 --- a/source/list.cpp +++ b/source/list.cpp @@ -47,16 +47,11 @@ List::~List() delete data; } -void List::autosize() +void List::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(const Part *items_part = style->get_part("items")) + if(part.get_name()=="items") { - const Sides &margin = items_part->get_margin(); + const Sides &margin = part.get_margin(); unsigned max_w = 0; unsigned total_h = 0; @@ -72,12 +67,9 @@ void List::autosize() if(!items.empty() && items.size()get_part("children")) + if(part.get_name()=="children") { - const Sides &margin = part->get_margin(); + const Sides &margin = part.get_margin(); for(list::const_iterator i=children.begin(); i!=children.end(); ++i) { const Geometry &cgeom = (*i)->widget->get_geometry(); - geom.w = max(geom.w, cgeom.x+cgeom.w+margin.right); - geom.h = max(geom.h, cgeom.y+cgeom.h+margin.top); + ageom.w = max(ageom.w, cgeom.x+cgeom.w+margin.right); + ageom.h = max(ageom.h, cgeom.y+cgeom.h+margin.top); } } } diff --git a/source/list.h b/source/list.h index dd44f3b..1032db7 100644 --- a/source/list.h +++ b/source/list.h @@ -47,7 +47,9 @@ protected: public: virtual const char *get_class() const { return "listitem"; } - virtual void autosize(); + protected: + virtual void autosize_special(const Part &, Geometry &); + public: void set_active(bool); virtual void render_special(const Part &, GL::Renderer &) const; @@ -91,8 +93,10 @@ public: virtual const char *get_class() const { return "list"; } - virtual void autosize(); +private: + virtual void autosize_special(const Part &, Geometry &); +public: void set_data(ListData &); ListData &get_data() { return *data; } const ListData &get_data() const { return *data; } diff --git a/source/panel.cpp b/source/panel.cpp index f9ea0d4..ab8f54f 100644 --- a/source/panel.cpp +++ b/source/panel.cpp @@ -39,10 +39,10 @@ void Panel::set_layout(Layout *l) layout = l; } -void Panel::autosize() +void Panel::autosize_special(const Part &part, Geometry &ageom) { - if(layout) - layout->autosize(); + if(part.get_name()=="children" && layout) + layout->autosize(ageom); } void Panel::render_special(const Part &part, GL::Renderer &renderer) const diff --git a/source/panel.h b/source/panel.h index ee2859c..8d83b66 100644 --- a/source/panel.h +++ b/source/panel.h @@ -65,9 +65,9 @@ public: virtual const char *get_class() const { return "panel"; } void set_layout(Layout *); - virtual void autosize(); protected: + virtual void autosize_special(const Part &, Geometry &); virtual void render_special(const Part &, GL::Renderer &) const; virtual void on_geometry_change(); diff --git a/source/text.cpp b/source/text.cpp index 4d80ad5..a0f53c2 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -66,6 +66,13 @@ unsigned Text::get_height() const return line_height+(lines.size()-1)*line_spacing; } +void Text::autosize(const Part &part, Geometry &geom) const +{ + const Sides &margin = part.get_margin(); + geom.w = max(geom.w, get_width()+margin.left+margin.right); + geom.h = max(geom.h, get_height()+margin.top+margin.bottom); +} + void Text::set(const string &t) { text = t; diff --git a/source/text.h b/source/text.h index 03cc787..db58b24 100644 --- a/source/text.h +++ b/source/text.h @@ -40,6 +40,7 @@ public: unsigned get_width() const; unsigned get_height() const; + void autosize(const Part &, Geometry &) const; void set(const std::string &); void erase(unsigned, unsigned); diff --git a/source/toggle.cpp b/source/toggle.cpp index 4519269..fe6518d 100644 --- a/source/toggle.cpp +++ b/source/toggle.cpp @@ -17,21 +17,10 @@ Toggle::Toggle(const string &t): set_text(t); } -void Toggle::autosize() +void Toggle::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(const Part *text_part = style->get_part("text")) - { - const Sides &margin = text_part->get_margin(); - geom.w = max(geom.w, text.get_width()+margin.left+margin.right); - geom.h = max(geom.h, text.get_height()+margin.top+margin.bottom); - } - - rebuild(); + if(part.get_name()=="text") + text.autosize(part, ageom); } void Toggle::set_text(const string &t) diff --git a/source/toggle.h b/source/toggle.h index de8c5d2..9bba268 100644 --- a/source/toggle.h +++ b/source/toggle.h @@ -36,8 +36,10 @@ public: virtual const char *get_class() const { return "toggle"; } - virtual void autosize(); +private: + virtual void autosize_special(const Part &, Geometry &); +public: void set_text(const std::string &); void set_exclusive(bool); bool get_exclusive() const { return exclusive; } diff --git a/source/vslider.cpp b/source/vslider.cpp index 6a21c53..53c8f51 100644 --- a/source/vslider.cpp +++ b/source/vslider.cpp @@ -12,19 +12,14 @@ VSlider::VSlider(): slider_size(1) { } -void VSlider::autosize() +void VSlider::autosize_special(const Part &part, Geometry &ageom) { - if(!style) - return; - - Widget::autosize(); - - if(const Part *slider_part = style->get_part("slider")) + if(part.get_name()=="slider") { - const Sides &margin = slider_part->get_margin(); - const Geometry &pgeom = slider_part->get_geometry(); - geom.w = std::max(geom.w, pgeom.w+margin.left+margin.right); - geom.h = std::max(geom.h, pgeom.h*3/2+margin.top+margin.bottom); + const Sides &margin = part.get_margin(); + const Geometry &pgeom = part.get_geometry(); + ageom.w = std::max(ageom.w, pgeom.w+margin.left+margin.right); + ageom.h = std::max(ageom.h, pgeom.h*3/2+margin.top+margin.bottom); } } diff --git a/source/vslider.h b/source/vslider.h index 854b075..a994aac 100644 --- a/source/vslider.h +++ b/source/vslider.h @@ -16,9 +16,8 @@ public: virtual const char *get_class() const { return "vslider"; } - virtual void autosize(); - private: + virtual void autosize_special(const Part &, Geometry &); virtual void rebuild_special(const Part &); public: diff --git a/source/widget.cpp b/source/widget.cpp index f642004..7496f8b 100644 --- a/source/widget.cpp +++ b/source/widget.cpp @@ -43,17 +43,22 @@ void Widget::autosize() if(!style) return; - geom.w = 0; - geom.h = 0; + Geometry ageom; const Style::PartSeq &parts = style->get_parts(); for(Style::PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i) + { if(i->get_name().empty()) { const Geometry &pgeom = i->get_geometry(); const Sides &pmargin = i->get_margin(); - geom.w = max(geom.w, pgeom.w+pmargin.left+pmargin.right); - geom.h = max(geom.h, pgeom.h+pmargin.top+pmargin.bottom); + ageom.w = max(ageom.w, pgeom.w+pmargin.left+pmargin.right); + ageom.h = max(ageom.h, pgeom.h+pmargin.top+pmargin.bottom); } + else + autosize_special(*i, ageom); + } + + set_geometry(ageom); } void Widget::set_geometry(const Geometry &g) diff --git a/source/widget.h b/source/widget.h index 50e3279..5c81b80 100644 --- a/source/widget.h +++ b/source/widget.h @@ -61,7 +61,10 @@ public: void set_position(int, int); void set_size(unsigned, unsigned); - virtual void autosize(); + void autosize(); +protected: + virtual void autosize_special(const Part &, Geometry &) { } +public: void set_geometry(const Geometry &); const Geometry &get_geometry() const { return geom; }