From 43ac7c4514658754d09552463425bcd344fb9ded Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 27 Feb 2011 16:38:33 +0000 Subject: [PATCH] Implement autosize() method for most widgets Only take content size into account if the relevant Part exists Change List autosize() to set a height suitable for five rows Additional methods to autosize for a set number of rows or all rows Make sure that a Dropdown's List fits inside the Root --- source/button.cpp | 28 ++++++++++++++++++++++ source/button.h | 2 ++ source/dropdown.cpp | 48 ++++++++++++++++++++++++++++++++++--- source/dropdown.h | 2 ++ source/entry.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++ source/entry.h | 2 ++ source/hslider.cpp | 16 +++++++++++++ source/hslider.h | 2 ++ source/image.cpp | 26 +++++++++++++++++++- source/image.h | 2 ++ source/label.cpp | 10 ++++---- source/list.cpp | 53 ++++++++++++++++++++++++++++++++--------- source/list.h | 2 ++ source/toggle.cpp | 16 +++++++++++++ source/toggle.h | 2 ++ source/vslider.cpp | 16 +++++++++++++ source/vslider.h | 2 ++ source/widget.cpp | 13 ++++++++++ source/widget.h | 5 ++-- 19 files changed, 283 insertions(+), 22 deletions(-) diff --git a/source/button.cpp b/source/button.cpp index 3c71499..5095379 100644 --- a/source/button.cpp +++ b/source/button.cpp @@ -8,6 +8,9 @@ Distributed under the LGPL #include #include "button.h" #include "part.h" +#include "style.h" + +using namespace std; namespace Msp { namespace GLtk { @@ -20,6 +23,31 @@ Button::Button(const std::string &t): set_text(t); } +void Button::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); + } + + if(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); + } + } +} + void Button::set_text(const std::string &t) { text = t; diff --git a/source/button.h b/source/button.h index 8d4c3c6..08c135d 100644 --- a/source/button.h +++ b/source/button.h @@ -43,6 +43,8 @@ public: virtual const char *get_class() const { return "button"; } + virtual void autosize(); + void set_text(const std::string &); void set_icon(const GL::Texture2D *); diff --git a/source/dropdown.cpp b/source/dropdown.cpp index b00438e..801c8a6 100644 --- a/source/dropdown.cpp +++ b/source/dropdown.cpp @@ -10,6 +10,7 @@ Distributed under the LGPL #include "list.h" #include "panel.h" #include "part.h" +#include "root.h" #include "style.h" #include "text.h" @@ -25,6 +26,24 @@ Dropdown::Dropdown(): list.signal_item_selected.connect(sigc::mem_fun(this, &Dropdown::list_item_selected)); } +void Dropdown::autosize() +{ + if(!style) + return; + + Widget::autosize(); + geom.w = max(geom.w, list.get_geometry().w); + + if(const Part *text_part = style->get_part("text")) + { + const Sides &margin = text_part->get_margin(); + const GL::Font *font = style->get_font(); + float font_size = font->get_default_size(); + unsigned line_height = static_cast((font->get_ascent()-font->get_descent())*font_size); + geom.h = max(geom.h, line_height+margin.top+margin.bottom); + } +} + void Dropdown::append(const string &item) { list.append(item); @@ -112,9 +131,32 @@ void Dropdown::on_style_change() void Dropdown::resize_list() { - list.autosize(); - const Geometry &lgeom = list.get_geometry(); - list.set_geometry(Geometry(0, -lgeom.h, max(geom.w, lgeom.w), lgeom.h)); + list.autosize_all(); + Geometry lgeom = list.get_geometry(); + lgeom.x = 0; + lgeom.y = -lgeom.h; + lgeom.w = max(geom.w, lgeom.w); + int root_x = geom.x; + int root_y = geom.y; + for(Widget *p=parent; p; p=p->get_parent()) + { + root_x += p->get_geometry().x; + root_y += p->get_geometry().y; + if(Root *root = dynamic_cast(p)) + { + const Geometry &rgeom = root->get_geometry(); + if(lgeom.h*2>rgeom.h) + lgeom.h = rgeom.h/2; + if(root_y+lgeom.y<0) + lgeom.y = -root_y; + if(root_y+lgeom.y+lgeom.h>rgeom.h) + lgeom.y = rgeom.h-lgeom.h-root_y; + if(root_x+lgeom.x+lgeom.w>rgeom.w) + lgeom.x = rgeom.w-lgeom.w-root_x; + break; + } + } + list.set_geometry(lgeom); } void Dropdown::list_item_selected(unsigned index, const std::string &item) diff --git a/source/dropdown.h b/source/dropdown.h index 51ba724..598ad80 100644 --- a/source/dropdown.h +++ b/source/dropdown.h @@ -39,6 +39,8 @@ public: virtual const char *get_class() const { return "dropdown"; } + virtual void autosize(); + void append(const std::string &); void insert(unsigned, const std::string &); void remove(unsigned); diff --git a/source/entry.cpp b/source/entry.cpp index 271c49a..2dc0466 100644 --- a/source/entry.cpp +++ b/source/entry.cpp @@ -32,6 +32,55 @@ Entry::Entry(const string &t): set_text(t); } +void Entry::autosize() +{ + if(!style) + return; + + Widget::autosize(); + + if(text_part) + { + const Sides &margin = text_part->get_margin(); + const GL::Font &font = *style->get_font(); + unsigned en_width = static_cast(font.get_string_width("n")*font.get_native_size()); + geom.w = max(geom.w, 10*en_width+margin.left+margin.right); + + unsigned line_height = static_cast((font.get_ascent()-font.get_descent())*font.get_native_size()); + if(multiline) + { + unsigned line_spacing = font.get_native_size()*6/5; + geom.h = max(geom.h, line_height+line_spacing*2+margin.top+margin.bottom); + } + else + geom.h = max(geom.h, line_height+margin.top+margin.bottom); + } + + if(multiline) + { + if(const Part *slider_part = style->get_part("slider")) + { + 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(); + } + + check_view_range(); + } +} + void Entry::set_text(const string &t) { text = t; @@ -180,6 +229,15 @@ void Entry::reposition_slider() if(const Part *slider_part = style->get_part("slider")) { 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; + } + slider_part->get_alignment().apply(sgeom, geom, slider_part->get_margin()); slider->set_geometry(sgeom); } diff --git a/source/entry.h b/source/entry.h index bc4a26b..25acf7d 100644 --- a/source/entry.h +++ b/source/entry.h @@ -51,6 +51,8 @@ public: virtual const char *get_class() const { return "entry"; } + virtual void autosize(); + void set_text(const std::string &); const std::string &get_text() const { return text.get(); } void set_multiline(bool); diff --git a/source/hslider.cpp b/source/hslider.cpp index e86cc4b..e855fcf 100644 --- a/source/hslider.cpp +++ b/source/hslider.cpp @@ -19,6 +19,22 @@ HSlider::HSlider(): slider_size(1) { } +void HSlider::autosize() +{ + if(!style) + return; + + Widget::autosize(); + + if(const Part *slider_part = style->get_part("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); + } +} + void HSlider::render_special(const Part &part) const { if(part.get_name()=="slider") diff --git a/source/hslider.h b/source/hslider.h index 493f00c..1294842 100644 --- a/source/hslider.h +++ b/source/hslider.h @@ -27,6 +27,8 @@ public: virtual const char *get_class() const { return "hslider"; } + virtual void autosize(); + private: virtual void render_special(const Part &) const; diff --git a/source/image.cpp b/source/image.cpp index 11003f4..eb3bd6e 100644 --- a/source/image.cpp +++ b/source/image.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgltk -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2010-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -10,6 +10,7 @@ Distributed under the LGPL #include #include "image.h" #include "part.h" +#include "style.h" using namespace std; @@ -23,6 +24,29 @@ Image::Image(const GL::Texture2D *i): focusable = false; } +void Image::autosize() +{ + if(!style) + return; + + Widget::autosize(); + + if(const Part *image_part = style->get_part("image")) + { + const Sides &margin = image_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); + } + else + { + geom.w = max(geom.w, margin.left+margin.right); + geom.h = max(geom.h, margin.top+margin.bottom); + } + } +} + void Image::set_image(const GL::Texture2D *i) { image = i; diff --git a/source/image.h b/source/image.h index efc8144..afc4826 100644 --- a/source/image.h +++ b/source/image.h @@ -28,6 +28,8 @@ public: virtual const char *get_class() const { return "image"; } + virtual void autosize(); + void set_image(const GL::Texture2D *); void set_keep_aspect(bool); diff --git a/source/label.cpp b/source/label.cpp index e3a4623..30ccd62 100644 --- a/source/label.cpp +++ b/source/label.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgltk -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007, 2009-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -25,13 +25,13 @@ void Label::autosize() if(!style) return; - geom.h = text.get_height(); - geom.w = text.get_width(); + Widget::autosize(); + if(const Part *text_part = style->get_part("text")) { const Sides &margin = text_part->get_margin(); - geom.w += margin.left+margin.right; - geom.h += margin.top+margin.bottom; + geom.w = max(geom.w, text.get_width()+margin.left+margin.right); + geom.h = max(geom.h, text.get_height()+margin.top+margin.bottom); } } diff --git a/source/list.cpp b/source/list.cpp index 65d2d63..ea3969c 100644 --- a/source/list.cpp +++ b/source/list.cpp @@ -33,27 +33,58 @@ List::List(): } void List::autosize() +{ + autosize_rows(5); +} + +void List::autosize_rows(unsigned n) { if(!style) return; - float font_size = style->get_font()->get_default_size(); + Widget::autosize(); - geom.w = 0; - for(vector::iterator i=items.begin(); i!=items.end(); ++i) + if(items_part) { - unsigned w = static_cast(style->get_font()->get_string_width(*i)*font_size); - geom.w = max(geom.w, w); - } + const Sides &margin = items_part->get_margin(); + float font_size = style->get_font()->get_default_size(); - geom.h = items.size()*row_height; + unsigned max_w = 0; + for(vector::iterator i=items.begin(); i!=items.end(); ++i) + { + unsigned w = static_cast(style->get_font()->get_string_width(*i)*font_size); + max_w = max(max_w, w); + } - if(items_part) + geom.w = max(geom.w, max_w+margin.left+margin.right); + geom.h = max(geom.h, n*row_height+margin.top+margin.bottom); + } + + if(const Part *slider_part = style->get_part("slider")) { - const Sides &margin = items_part->get_margin(); - geom.w += margin.left+margin.right; - geom.h += margin.top+margin.bottom; + 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(); } + + check_view_range(); +} + +void List::autosize_all() +{ + autosize_rows(items.size()); } void List::append(const string &v) diff --git a/source/list.h b/source/list.h index b6cae50..b3b3a88 100644 --- a/source/list.h +++ b/source/list.h @@ -49,6 +49,8 @@ public: virtual const char *get_class() const { return "list"; } virtual void autosize(); + void autosize_rows(unsigned); + void autosize_all(); void append(const std::string &); void insert(unsigned, const std::string &); diff --git a/source/toggle.cpp b/source/toggle.cpp index 43acaa3..753257c 100644 --- a/source/toggle.cpp +++ b/source/toggle.cpp @@ -7,6 +7,7 @@ Distributed under the LGPL #include "panel.h" #include "part.h" +#include "style.h" #include "toggle.h" using namespace std; @@ -23,6 +24,21 @@ Toggle::Toggle(const string &t): set_text(t); } +void Toggle::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); + } +} + void Toggle::set_text(const string &t) { text = t; diff --git a/source/toggle.h b/source/toggle.h index ff65440..58a03b6 100644 --- a/source/toggle.h +++ b/source/toggle.h @@ -44,6 +44,8 @@ public: virtual const char *get_class() const { return "toggle"; } + virtual void autosize(); + 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 65cac69..874c383 100644 --- a/source/vslider.cpp +++ b/source/vslider.cpp @@ -19,6 +19,22 @@ VSlider::VSlider(): slider_size(1) { } +void VSlider::autosize() +{ + if(!style) + return; + + Widget::autosize(); + + if(const Part *slider_part = style->get_part("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); + } +} + void VSlider::render_special(const Part &part) const { if(part.get_name()=="slider") diff --git a/source/vslider.h b/source/vslider.h index 5c5e61f..6590c21 100644 --- a/source/vslider.h +++ b/source/vslider.h @@ -23,6 +23,8 @@ public: virtual const char *get_class() const { return "vslider"; } + virtual void autosize(); + private: virtual void render_special(const Part &) const; diff --git a/source/widget.cpp b/source/widget.cpp index 1442151..4e0c489 100644 --- a/source/widget.cpp +++ b/source/widget.cpp @@ -47,6 +47,19 @@ void Widget::set_size(unsigned w, unsigned h) on_geometry_change(); } +void Widget::autosize() +{ + geom.w = 0; + geom.h = 0; + const Style::PartSeq &parts = style->get_parts(); + for(Style::PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i) + if(i->get_name().empty()) + { + geom.w = max(geom.w, i->get_geometry().w); + geom.h = max(geom.h, i->get_geometry().h); + } +} + void Widget::set_geometry(const Geometry &g) { geom = g; diff --git a/source/widget.h b/source/widget.h index 64db74e..5522ba3 100644 --- a/source/widget.h +++ b/source/widget.h @@ -66,7 +66,7 @@ public: void set_position(int, int); void set_size(unsigned, unsigned); - virtual void autosize() { } + virtual void autosize(); void set_geometry(const Geometry &); const Geometry &get_geometry() const { return geom; } @@ -76,8 +76,9 @@ protected: calling this function with a non-null parameter. */ void set_parent(Container *); - public: + Container *get_parent() const { return parent; } + /** Sets the widget style. The final style name is constructed by concatenating the widget class and the style name with a dash. -- 2.43.0