]> git.tdb.fi Git - libs/gltk.git/commitdiff
Implement autosize() method for most widgets
authorMikko Rasa <tdb@tdb.fi>
Sun, 27 Feb 2011 16:38:33 +0000 (16:38 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 27 Feb 2011 16:38:33 +0000 (16:38 +0000)
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

19 files changed:
source/button.cpp
source/button.h
source/dropdown.cpp
source/dropdown.h
source/entry.cpp
source/entry.h
source/hslider.cpp
source/hslider.h
source/image.cpp
source/image.h
source/label.cpp
source/list.cpp
source/list.h
source/toggle.cpp
source/toggle.h
source/vslider.cpp
source/vslider.h
source/widget.cpp
source/widget.h

index 3c71499bde19cdc32794478687ef689e18f4e90b..5095379364b5c7a883d1d4fe615ec4d90655444a 100644 (file)
@@ -8,6 +8,9 @@ Distributed under the LGPL
 #include <msp/gl/immediate.h>
 #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;
index 8d4c3c6c2de27081ecf782bdf127035f0c0b9167..08c135dc53578b4e3ca438cca65bba04f70d8d8e 100644 (file)
@@ -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 *);
 
index b00438e54c40ef7bc21dfb887ecd1945229a72bb..801c8a6428cfe81de6b1d82ac5f86154f4d1e3d0 100644 (file)
@@ -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<unsigned>((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<Root *>(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)
index 51ba72434956d1c1728f1a6e021c73dfec73ad18..598ad8035bf35459471487b557e693b6261e39a2 100644 (file)
@@ -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);
index 271c49a4b6cda21ca063f9e7e7339ea460c96de5..2dc046646e49af2af9b07967a090e42f041f0c64 100644 (file)
@@ -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<unsigned>(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<unsigned>((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);
        }
index bc4a26bfb067513839760e5562c71f4fb72928c2..25acf7da4116427c56b7ab8014dbf29dccb86551 100644 (file)
@@ -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);
index e86cc4b17da02f56f8d26906eb2382ab59af0761..e855fcfb4d80bf6bf44bfa81dd12a039bc895f4a 100644 (file)
@@ -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")
index 493f00cf97ab50d396211b76a1166e9d211b8c29..12948420297605900c90becf42cc42e5f577ddcd 100644 (file)
@@ -27,6 +27,8 @@ public:
 
        virtual const char *get_class() const { return "hslider"; }
 
+       virtual void autosize();
+
 private:
        virtual void render_special(const Part &) const;
 
index 11003f4d1af56acbfb6b7367ec680f6e86bb1533..eb3bd6ef4da556337e712c14b81fa4fa656b6559 100644 (file)
@@ -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 <msp/gl/matrix.h>
 #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;
index efc814487f88c39f38e2cc209382b5d53db0a50e..afc4826e28c24f46e324ddcd30f994b1f10588d0 100644 (file)
@@ -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);
 
index e3a46234519757df692a81d23ce4fb96f940af58..30ccd62d16859a6555e95eb2bd7d3180e58c0fc5 100644 (file)
@@ -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);
        }
 }
 
index 65d2d6309d24cb612bb3b108fcd67533d20e8d25..ea3969ce16dbb466591a642bdcff01c1e1150ed5 100644 (file)
@@ -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<string>::iterator i=items.begin(); i!=items.end(); ++i)
+       if(items_part)
        {
-               unsigned w = static_cast<unsigned>(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<string>::iterator i=items.begin(); i!=items.end(); ++i)
+               {
+                       unsigned w = static_cast<unsigned>(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)
index b6cae50c876071747945d01cd8f3d1ee3d7231c1..b3b3a88704207470ef3825b16ca30c9161644338 100644 (file)
@@ -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 &);
index 43acaa3125b021161a489f91ab9603a044a7ec95..753257c775ce86fc81bd973898672e4783f86196 100644 (file)
@@ -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;
index ff65440a66f49fd1cc87bae8993b3c48c13b572a..58a03b6ea1aad0cdc5399213b1709946c4705679 100644 (file)
@@ -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; }
index 65cac69846f9763efc2dead8fddc06e04bde8048..874c38346c9e75a496058540ce1ec5b399685ec1 100644 (file)
@@ -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")
index 5c5e61f86959bdbd3fb0ef6c65479785876c0671..6590c2155cfd042004f27d8a34973cb2c69bdb4f 100644 (file)
@@ -23,6 +23,8 @@ public:
 
        virtual const char *get_class() const { return "vslider"; }
 
+       virtual void autosize();
+
 private:
        virtual void render_special(const Part &) const;
 
index 1442151262121406319c9bdf737f5f2f54a34d56..4e0c4890aa55eaeebe78a9fd0cc393acd6c05723 100644 (file)
@@ -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;
index 64db74e85a15d4b7f4a06fe5577a29140048966d..5522ba340e60a580e21497feeba50daee03cd632 100644 (file)
@@ -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.