]> git.tdb.fi Git - libs/gltk.git/commitdiff
Add Container class
authorMikko Rasa <tdb@tdb.fi>
Wed, 16 Sep 2009 19:16:18 +0000 (19:16 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 16 Sep 2009 19:16:18 +0000 (19:16 +0000)
Derive all Widgets that contain other Widgets from Container
Communicate various things to a Widget's parent with signals
Make List::slider not a pointer

source/container.cpp [new file with mode: 0644]
source/container.h [new file with mode: 0644]
source/dropdown.cpp
source/dropdown.h
source/list.cpp
source/list.h
source/panel.cpp
source/panel.h
source/root.cpp
source/widget.cpp
source/widget.h

diff --git a/source/container.cpp b/source/container.cpp
new file mode 100644 (file)
index 0000000..a755644
--- /dev/null
@@ -0,0 +1,167 @@
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "container.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GLtk {
+
+Container::Container(const Resources &r):
+       Widget(r),
+       click_focus(0),
+       click_button(0)
+{ }
+
+Container::~Container()
+{
+       while(!children.empty())
+               delete children.front()->widget;
+}
+
+void Container::add(Widget &wdg)
+{
+       set_parent(wdg, this);
+       children.push_back(create_child(&wdg));
+}
+
+void Container::remove(Widget &wdg)
+{
+       for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
+               if((*i)->widget==&wdg)
+               {
+                       set_parent(wdg, 0);
+                       delete *i;
+                       children.erase(i);
+                       return;
+               }
+
+       throw InvalidState("That Widget is not in this Container");
+}
+
+list<Widget *> Container::get_children() const
+{
+       list<Widget *> result;
+       for(list<Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
+               result.push_back((*i)->widget);
+       return result;
+}
+
+Widget *Container::get_child_at(int x, int y)
+{
+       for(list<Child *>::iterator i=children.end(); i!=children.begin();)
+               if((*--i)->widget->is_visible() && (*i)->widget->get_geometry().is_inside(x, y))
+                       return (*i)->widget;
+
+       return 0;
+}
+
+Widget *Container::get_descendant_at(int x, int y)
+{
+       Widget *wdg=get_child_at(x, y);
+       if(Container *cont=dynamic_cast<Container *>(wdg))
+       {
+               const Geometry &cgeom=wdg->get_geometry();
+               return cont->get_descendant_at(x-cgeom.x, y-cgeom.y);
+       }
+       return wdg;
+}
+
+void Container::button_press(int x, int y, unsigned btn)
+{
+       if(click_focus)
+       {
+               const Geometry &cgeom=click_focus->get_geometry();
+               click_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
+       }
+       else
+       {
+               if(Widget *wdg=get_child_at(x, y))
+               {
+                       click_focus=wdg;
+                       click_button=btn;
+
+                       const Geometry &cgeom=wdg->get_geometry();
+                       wdg->button_press(x-cgeom.x, y-cgeom.y, btn);
+               }
+       }
+}
+
+void Container::button_release(int x, int y, unsigned btn)
+{
+       if(click_focus)
+       {
+               Widget *wdg=click_focus;
+
+               if(btn==click_button)
+                       click_focus=0;
+
+               const Geometry &cgeom=wdg->get_geometry();
+               wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
+       }
+       else
+       {
+               if(Widget *wdg=get_child_at(x, y))
+               {
+                       const Geometry &cgeom=wdg->get_geometry();
+                       wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
+               }
+       }
+}
+
+void Container::pointer_motion(int x, int y)
+{
+       if(click_focus)
+       {
+               const Geometry &cgeom=click_focus->get_geometry();
+               click_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
+       }
+       else
+       {
+               Widget *wdg=get_child_at(x, y);
+               if(wdg)
+               {
+                       const Geometry &cgeom=wdg->get_geometry();
+                       wdg->pointer_motion(x-cgeom.x, y-cgeom.y);
+               }
+       }
+}
+
+void Container::pointer_leave()
+{
+       Widget::pointer_leave();
+       click_focus=0;
+}
+
+Container::Child *Container::create_child(Widget *wdg)
+{
+       return new Child(*this, wdg);
+}
+
+
+Container::Child::Child(Container &c, Widget *w):
+       container(c),
+       widget(w)
+{
+       widget->signal_visibility_changed.connect(sigc::mem_fun(this, &Child::visibility_changed));
+}
+
+Container::Child::~Child()
+{
+       if(widget==container.click_focus)
+               container.click_focus=0;
+}
+
+void Container::Child::visibility_changed(bool v)
+{
+       if(!v && widget==container.click_focus)
+               container.click_focus=0;
+}
+
+} // namespace GLtk
+} // namespace Msp
diff --git a/source/container.h b/source/container.h
new file mode 100644 (file)
index 0000000..32e8157
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GLTK_CONTAINER_H_
+#define MSP_GLTK_CONTAINER_H_
+
+#include <list>
+#include <sigc++/trackable.h>
+#include "widget.h"
+
+namespace Msp {
+namespace GLtk {
+
+class Container: virtual public Widget
+{
+protected:
+       struct Child: public sigc::trackable
+       {
+               Container &container;
+               Widget *widget;
+
+               Child(Container &, Widget *);
+               virtual ~Child();
+
+               void visibility_changed(bool);
+       };
+
+       std::list<Child *> children;
+       Widget *click_focus;
+       unsigned click_button;
+
+       Container(const Resources &);
+public:
+       virtual ~Container();
+
+       void add(Widget &);
+       void remove(Widget &);
+       std::list<Widget *> get_children() const;
+       Widget *get_child_at(int, int);
+       Widget *get_descendant_at(int, int);
+
+       virtual void button_press(int, int, unsigned);
+       virtual void button_release(int, int, unsigned);
+       virtual void pointer_motion(int, int);
+       virtual void pointer_leave();
+protected:
+       virtual Child *create_child(Widget *);
+};
+
+} // namespace GLtk
+} // namespace Msp
+
+#endif
index a4816d48d593bb430e8b1aa764c35aac131b5744..cbd7ee437111bc3726b1c0ba988471638142140b 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -19,19 +19,16 @@ namespace GLtk {
 
 Dropdown::Dropdown(const Resources &r):
        Widget(r),
+       Container(r),
        list(r),
-       dropped(false),
-       list_active(false)
+       dropped(false)
 {
+       add(list);
        list.signal_item_selected.connect(sigc::mem_fun(this, &Dropdown::list_item_selected));
 
        update_style();
 }
 
-Dropdown::~Dropdown()
-{
-}
-
 void Dropdown::append(const string &item)
 {
        list.append(item);
@@ -78,47 +75,21 @@ int Dropdown::get_selected_index() const
 
 void Dropdown::button_press(int x, int y, unsigned btn)
 {
-       if(list.get_geometry().is_inside(x, y))
-       {
-               const Geometry &lgeom=list.get_geometry();
-               list.button_press(x-lgeom.x, y-lgeom.y, btn);
-               list_active=true;
-       }
-       else if(dropped)
+       if(dropped)
        {
-               dropped=false;
-               state&=~ACTIVE;
-               parent->ungrab_pointer(*this);
+               Container::button_press(x, y, btn);
+               if(!click_focus)
+               {
+                       dropped=false;
+                       state&=~ACTIVE;
+                       signal_ungrab_pointer.emit();
+               }
        }
        else if(btn==1)
        {
                dropped=true;
                state|=ACTIVE;
-
-               if(parent)
-               {
-                       parent->raise(*this);
-                       parent->grab_pointer(*this);
-               }
-       }
-}
-
-void Dropdown::button_release(int x, int y, unsigned btn)
-{
-       if(list_active)
-       {
-               const Geometry &lgeom=list.get_geometry();
-               list.button_release(x-lgeom.x, y-lgeom.y, btn);
-               list_active=false;
-       }
-}
-
-void Dropdown::pointer_motion(int x, int y)
-{
-       if(list_active)
-       {
-               const Geometry &lgeom=list.get_geometry();
-               list.pointer_motion(x-lgeom.x, y-lgeom.y);
+               signal_grab_pointer.emit();
        }
 }
 
@@ -144,7 +115,7 @@ void Dropdown::resize_list()
        unsigned n_items=list.get_n_items();
        const Style &stl=list.get_style();
        const GL::Font &font=*stl.get_font();
-       unsigned h=min(max(n_items, 1U), 20U)*static_cast<unsigned>((font.get_ascent()-font.get_descent())*font.get_default_size());
+       unsigned h=min(max(n_items, 1U), 10U)*static_cast<unsigned>((font.get_ascent()-font.get_descent())*font.get_default_size());
        for(std::list<Part>::const_iterator i=stl.get_parts().begin(); i!=stl.get_parts().end(); ++i)
                if(i->get_name()=="items")
                {
@@ -158,11 +129,9 @@ void Dropdown::list_item_selected(unsigned index, const std::string &item)
 {
        if(dropped)
        {
-               list_active=false;
                dropped=false;
                state&=~ACTIVE;
-               if(parent)
-                       parent->ungrab_pointer(*this);
+               signal_ungrab_pointer.emit();
        }
 
        signal_item_selected.emit(index, item);
@@ -177,7 +146,7 @@ Dropdown::Loader::Loader(Dropdown &d):
 
 void Dropdown::Loader::item(const string &str)
 {
-       static_cast<Dropdown &>(wdg).append(str);
+       dynamic_cast<Dropdown &>(wdg).append(str);
 }
 
 } // namespace GLtk
index ecba9753cb5cace6957f74fa52162887703e202e..7428ebf086d24eb1e0660f0d703fea45cb0b74ee 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -17,7 +17,7 @@ namespace GLtk {
 
 class List;
 
-class Dropdown: public Widget
+class Dropdown: virtual public Widget, private Container
 {
 public:
        class Loader: public Widget::Loader
@@ -31,13 +31,11 @@ public:
 private:
        List list;
        bool dropped;
-       bool list_active;
 
 public:
        sigc::signal<void, int, const std::string &> signal_item_selected;
 
        Dropdown(const Resources &);
-       ~Dropdown();
 
        void append(const std::string &);
        void insert(unsigned, const std::string &);
@@ -50,8 +48,6 @@ public:
        int get_selected_index() const;
 
        virtual void button_press(int, int, unsigned);
-       virtual void button_release(int, int, unsigned);
-       virtual void pointer_motion(int, int);
 
 private:
        virtual const char *get_class() const { return "dropdown"; }
index 5bef36732e601ebd4a30023d04e51a9f14f2db78..cc9f707efa1d9dadf008e585101f0a6365c15782 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -21,25 +21,21 @@ namespace GLtk {
 
 List::List(const Resources &r):
        Widget(r),
+       Container(r),
        sel_index(-1),
        first(0),
        n_visible(1),
        row_height(1),
        items_part(0),
-       slider(new VSlider(res)),
-       slider_active(false)
+       slider(res)
 {
-       slider->set_step(1);
-       slider->signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
+       add(slider);
+       slider.set_step(1);
+       slider.signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
 
        update_style();
 }
 
-List::~List()
-{
-       delete slider;
-}
-
 void List::append(const string &v)
 {
        items.push_back(v);
@@ -100,13 +96,8 @@ const string &List::get_selected() const
 
 void List::button_press(int x, int y, unsigned btn)
 {
-       if(slider->get_geometry().is_inside(x, y))
-       {
-               const Geometry &sgeom=slider->get_geometry();
-               slider->button_press(x-sgeom.x, y-sgeom.y, btn);
-               slider_active=true;
-       }
-       else if(btn==1)
+       Container::button_press(x, y, btn);
+       if(!click_focus && btn==1)
        {
                if(items_part)
                        y+=items_part->get_margin().top;
@@ -121,25 +112,6 @@ void List::button_press(int x, int y, unsigned btn)
        }
 }
 
-void List::button_release(int x, int y, unsigned btn)
-{
-       if(slider_active)
-       {
-               const Geometry &sgeom=slider->get_geometry();
-               slider->button_release(x-sgeom.x, y-sgeom.y, btn);
-               slider_active=false;
-       }
-}
-
-void List::pointer_motion(int x, int y)
-{
-       if(slider_active)
-       {
-               const Geometry &sgeom=slider->get_geometry();
-               slider->pointer_motion(x-sgeom.x, y-sgeom.y);
-       }
-}
-
 void List::render_special(const Part &part) const
 {
        if(part.get_name()=="items")
@@ -193,7 +165,7 @@ void List::render_special(const Part &part) const
                }
        }
        else if(part.get_name()=="slider")
-               slider->render();
+               slider.render();
 }
 
 void List::on_geometry_change()
@@ -225,7 +197,7 @@ void List::reposition_slider()
                {
                        Geometry sgeom=i->get_geometry();
                        i->get_alignment().apply(sgeom, geom, i->get_margin());
-                       slider->set_geometry(sgeom);
+                       slider.set_geometry(sgeom);
                }
 }
 
@@ -250,13 +222,13 @@ void List::recalculate_parameters()
 
        if(items.size()>n_visible)
        {
-               slider->set_range(0, items.size()-n_visible);
-               slider->set_value(items.size()-n_visible-first);
+               slider.set_range(0, items.size()-n_visible);
+               slider.set_value(items.size()-n_visible-first);
        }
        else
        {
-               slider->set_range(0, 0);
-               slider->set_value(0);
+               slider.set_range(0, 0);
+               slider.set_value(0);
        }
 }
 
@@ -275,7 +247,7 @@ List::Loader::Loader(List &l):
 
 void List::Loader::item(const string &v)
 {
-       static_cast<List &>(wdg).append(v);
+       dynamic_cast<List &>(wdg).append(v);
 }
 
 } // namespace GLtk
index 770cc2f4517366a0b777d3e33df26f7f86b1a31f..dee57ed55c98587182976bf5b338a5683b79f93c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -9,18 +9,17 @@ Distributed under the LGPL
 #define MSP_GLTK_LIST_H_
 
 #include <sigc++/signal.h>
-#include "widget.h"
+#include "container.h"
+#include "vslider.h"
 
 namespace Msp {
 namespace GLtk {
 
-class VSlider;
-
 /**
 Shows a list of items, allowing the user to select one.  A slider is included
 to allow scrolling through a long list.
 */
-class List: public Widget
+class List: virtual public Widget, private Container
 {
 public:
        class Loader: public Widget::Loader
@@ -40,14 +39,12 @@ private:
 
        const Part *items_part;
 
-       VSlider *slider;
-       bool slider_active;
+       VSlider slider;
 
 public:
        sigc::signal<void, unsigned, const std::string &> signal_item_selected;
 
        List(const Resources &);
-       ~List();
 
        void append(const std::string &);
        void insert(unsigned, const std::string &);
@@ -60,8 +57,6 @@ public:
        int get_selected_index() const { return sel_index; }
 
        virtual void button_press(int, int, unsigned);
-       virtual void button_release(int, int, unsigned);
-       virtual void pointer_motion(int, int);
 
 private:
        virtual const char *get_class() const { return "list"; }
index aeca9e71a61e83d6889e351cb678ddd1493f2741..14e9b6ea8cc3dbf97b9c57f4f673df53870bacc2 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -27,114 +27,73 @@ namespace GLtk {
 
 Panel::Panel(const Resources &r):
        Widget(r),
+       Container(r),
        pointer_focus(0),
-       pointer_grab(0),
+       pointer_grabbed(false),
        input_focus(0)
 {
        update_style();
 }
 
-Panel::~Panel()
-{
-       while(!children.empty())
-               delete children.front();
-}
-
-void Panel::add(Widget &wdg)
-{
-       set_parent(wdg, this);
-       children.push_back(&wdg);
-}
-
-void Panel::remove(Widget &wdg)
-{
-       list<Widget *>::iterator i=find(children.begin(), children.end(), &wdg);
-       if(i==children.end())
-               throw InvalidState("That Widget is not in this Panel");
-
-       if(&wdg==pointer_focus)
-               set_pointer_focus(0, 0);
-       if(&wdg==input_focus)
-               set_input_focus(0);
-
-       set_parent(wdg, 0);
-       children.erase(i);
-}
-
 void Panel::raise(Widget &wdg)
 {
-       list<Widget *>::iterator i=find(children.begin(), children.end(), &wdg);
-       if(i==children.end())
-               throw InvalidState("That Widget is not in this Panel");
+       for(list<Container::Child *>::iterator i=children.begin(); i!=children.end(); ++i)
+               if((*i)->widget==&wdg)
+               {
+                       children.splice(children.end(), children, i);
+                       return;
+               }
 
-       children.erase(i);
-       children.push_back(&wdg);
+       throw InvalidState("That Widget is not in this Panel");
 }
 
 void Panel::button_press(int x, int y, unsigned btn)
 {
-       if(pointer_grab>0)
+       if(pointer_grabbed)
        {
                const Geometry &cgeom=pointer_focus->get_geometry();
                pointer_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
        }
-       else if(geom.is_inside_relative(x, y))
+       else
        {
                if(Widget *wdg=get_child_at(x, y))
                {
-                       set_pointer_focus(wdg, btn);
+                       set_pointer_focus(wdg);
                        set_input_focus(wdg);
-
-                       const Geometry &cgeom=wdg->get_geometry();
-                       wdg->button_press(x-cgeom.x, y-cgeom.y, btn);
                }
+               Container::button_press(x, y, btn);
        }
 }
 
 void Panel::button_release(int x, int y, unsigned btn)
 {
-       if(pointer_grab>0)
+       if(pointer_grabbed)
        {
-               Widget *wdg=pointer_focus;
-
-               if(btn==pointer_grab)
-                       set_pointer_focus(get_child_at(x, y), 0);
-
-               const Geometry &cgeom=wdg->get_geometry();
-               wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
-       }
-       else if(geom.is_inside_relative(x, y))
-       {
-               if(Widget *wdg=get_child_at(x, y))
-               {
-                       const Geometry &cgeom=wdg->get_geometry();
-                       wdg->button_release(x-cgeom.x, y-cgeom.y, btn);
-               }
+               const Geometry &cgeom=pointer_focus->get_geometry();
+               pointer_focus->button_release(x-cgeom.x, y-cgeom.y, btn);
        }
+       else
+               Container::button_release(x, y, btn);
 }
 
 void Panel::pointer_motion(int x, int y)
 {
-       if(pointer_grab>0)
+       if(pointer_grabbed)
        {
                const Geometry &cgeom=pointer_focus->get_geometry();
                pointer_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
        }
-       else if(geom.is_inside_relative(x, y))
+       else
        {
-               Widget *wdg=get_child_at(x, y);
-               set_pointer_focus(wdg, 0);
-               if(wdg)
-               {
-                       const Geometry &cgeom=wdg->get_geometry();
-                       wdg->pointer_motion(x-cgeom.x, y-cgeom.y);
-               }
+               set_pointer_focus(get_child_at(x, y));
+               Container::pointer_motion(x, y);
        }
 }
 
 void Panel::pointer_leave()
 {
-       set_pointer_focus(0, 0);
+       Container::pointer_leave();
+       set_pointer_focus(0);
 }
 
 void Panel::key_press(unsigned key, unsigned mod, wchar_t ch)
@@ -154,64 +113,23 @@ void Panel::focus_out()
        set_input_focus(0);
 }
 
-void Panel::child_hidden(Widget &wdg)
-{
-       if(&wdg==pointer_focus)
-               set_pointer_focus(0, 0);
-       if(&wdg==input_focus)
-               set_input_focus(0);
-}
-
-void Panel::grab_pointer(Widget &wdg)
-{
-       if(pointer_grab==0 || pointer_focus==&wdg)
-       {
-               set_pointer_focus(&wdg, 255);
-               if(parent)
-                       parent->grab_pointer(*this);
-       }
-       else
-               throw InvalidState("Pointer is already grabbed");
-}
-
-void Panel::ungrab_pointer(Widget &wdg)
-{
-       if(pointer_focus==&wdg)
-       {
-               set_pointer_focus(0, 0);
-               if(parent)
-                       parent->ungrab_pointer(*this);
-       }
-       else if(pointer_grab>0)
-               throw Exception("Someone is trying to steal the pointer!");
-}
-
-void Panel::grab_focus(Widget &wdg)
-{
-       list<Widget *>::iterator i=find(children.begin(), children.end(), &wdg);
-       if(i==children.end())
-               throw InvalidState("That Widget is not in this Panel");
-       
-       set_input_focus(&wdg);
-       if(parent)
-               parent->grab_focus(*this);
-}
-
 void Panel::render_special(const Part &part) const
 {
        if(part.get_name()=="children")
        {
-               for(list<Widget *>::const_iterator i=children.begin(); i!=children.end(); ++i)
-                       if((*i)->is_visible())
-                               (*i)->render();
+               for(list<Container::Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
+                       if((*i)->widget->is_visible())
+                               (*i)->widget->render();
        }
 }
 
-void Panel::set_pointer_focus(Widget *wdg, int grab)
+Panel::Child *Panel::create_child(Widget *wdg)
 {
-       if(grab>0 && !wdg)
-               throw InvalidParameterValue("Can't grab on null widget");
+       return new Child(*this, wdg);
+}
 
+void Panel::set_pointer_focus(Widget *wdg)
+{
        if(wdg!=pointer_focus)
        {
                if(pointer_focus)
@@ -222,8 +140,6 @@ void Panel::set_pointer_focus(Widget *wdg, int grab)
                if(pointer_focus)
                        pointer_focus->pointer_enter();
        }
-
-       pointer_grab=grab;
 }
 
 void Panel::set_input_focus(Widget *wdg)
@@ -236,19 +152,13 @@ void Panel::set_input_focus(Widget *wdg)
                input_focus=wdg;
 
                if(input_focus)
+               {
+                       raise(*wdg);
                        input_focus->focus_in();
+               }
        }
 }
 
-Widget *Panel::get_child_at(int x, int y)
-{
-       for(list<Widget *>::reverse_iterator i=children.rbegin(); i!=children.rend(); ++i)
-               if((*i)->is_visible() && (*i)->get_geometry().is_inside(x, y))
-                       return *i;
-
-       return 0;
-}
-
 
 Panel::Loader::Loader(Panel &p, map<string, Widget *> &m):
        Widget::Loader(p),
@@ -285,5 +195,60 @@ void Panel::Loader::panel(const string &n)
        wdg_map[n]=p.release();
 }
 
+
+Panel::Child::Child(Panel &p, Widget *w):
+       Container::Child(p, w)
+{
+       widget->signal_visibility_changed.connect(sigc::mem_fun(this, &Child::visibility_changed));
+       widget->signal_request_focus.connect(sigc::mem_fun(this, &Child::request_focus));
+       widget->signal_grab_pointer.connect(sigc::mem_fun(this, &Child::grab_pointer));
+       widget->signal_ungrab_pointer.connect(sigc::mem_fun(this, &Child::ungrab_pointer));
+}
+
+Panel::Child::~Child()
+{
+       visibility_changed(false);
+}
+
+void Panel::Child::visibility_changed(bool v)
+{
+       if(!v)
+       {
+               Panel &panel=static_cast<Panel &>(container);
+               if(widget==panel.pointer_focus)
+                       panel.set_pointer_focus(0);
+               if(widget==panel.input_focus)
+                       panel.set_input_focus(0);
+       }
+}
+
+void Panel::Child::request_focus()
+{
+       static_cast<Panel &>(container).set_input_focus(widget);
+}
+
+void Panel::Child::grab_pointer()
+{
+       Panel &panel=static_cast<Panel &>(container);
+       if(!panel.pointer_grabbed)
+       {
+               panel.set_pointer_focus(widget);
+               panel.pointer_grabbed=true;
+               panel.signal_grab_pointer.emit();
+       }
+}
+
+void Panel::Child::ungrab_pointer()
+{
+       Panel &panel=static_cast<Panel &>(container);
+       if(panel.pointer_grabbed && panel.pointer_focus==widget)
+       {
+               // XXX Should set to the widget under pointer
+               panel.set_pointer_focus(0);
+               panel.pointer_grabbed=false;
+               panel.signal_ungrab_pointer.emit();
+       }
+}
+
 } // namespace GLtk
 } // namespace Msp
index e269ca21819748185e2574758b459f8c532fb4b5..b431a854cdcc284ad751fa45e926ea082e274962 100644 (file)
@@ -1,14 +1,14 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #ifndef MSP_GLTK_PANEL_H_
 #define MSP_GLTK_PANEL_H_
 
-#include "widget.h"
+#include "container.h"
 
 namespace Msp {
 namespace GLtk {
@@ -18,7 +18,7 @@ Panels are containers for other widgets.  Panel styles should have a special
 part "children" to render the child widgets.  All properties of this part are
 ignored.
 */
-class Panel: public Widget
+class Panel: public Container
 {
 public:
        class Loader: public Widget::Loader
@@ -36,22 +36,28 @@ public:
        };
 
 private:
-       std::list<Widget *> children;
+       struct Child: public Container::Child
+       {
+               Child(Panel &, Widget *);
+               virtual ~Child();
+
+               void visibility_changed(bool);
+               void request_focus();
+               void grab_pointer();
+               void ungrab_pointer();
+               void raise();
+       };
+
        Widget *pointer_focus;
-       unsigned pointer_grab;
+       bool pointer_grabbed;
        Widget *input_focus;
 
        Panel(const Panel &);
        Panel &operator=(const Panel &);
 public:
        Panel(const Resources &);
-       ~Panel();
 
-       void add(Widget &);
-       void remove(Widget &);
-       const std::list<Widget *> &get_children() const { return children; }
        void raise(Widget &);
-       void set_focus(Widget &);
 
        virtual void button_press(int, int, unsigned);
        virtual void button_release(int, int, unsigned);
@@ -60,19 +66,13 @@ public:
        virtual void key_press(unsigned, unsigned, wchar_t);
        virtual void key_release(unsigned, unsigned);
        virtual void focus_out();
-
-       // These functions are not intended to be called from outside GLtk
-       void child_hidden(Widget &);
-       void grab_pointer(Widget &);
-       void ungrab_pointer(Widget &);
-       void grab_focus(Widget &);
 private:
        virtual const char *get_class() const { return "panel"; }
        virtual void render_special(const Part &) const;
+       virtual Child *create_child(Widget *);
 
-       void set_pointer_focus(Widget *, int);
+       void set_pointer_focus(Widget *);
        void set_input_focus(Widget *);
-       Widget *get_child_at(int, int);
 };
 
 } // namespace GLtk
index 9d02c4a70f4a1698124263f55414969573489f54..6bc5793df6e0c4b5140660a9f96f8d3095e58c5f 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -12,6 +12,7 @@ namespace Msp {
 namespace GLtk {
 
 Root::Root(const Resources &r, Graphics::Window &w):
+       Widget(r),
        Panel(r),
        window(w)
 {
index 48b647b71850b464bf8da56f102170d64bc8cf6e..84d042573ec18aff63230eca34cada3e150dbab3 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -65,8 +65,7 @@ void Widget::set_visible(bool v)
 
        visible=v;
 
-       if(!visible && parent)
-               parent->child_hidden(*this);
+       signal_visibility_changed.emit(visible);
 }
 
 void Widget::set_focus()
@@ -76,7 +75,7 @@ void Widget::set_focus()
        if(!visible)
                throw InvalidState("Can't set focus on invisible widget");
 
-       parent->grab_focus(*this);
+       signal_request_focus.emit();
 }
 
 void Widget::render() const
@@ -158,16 +157,16 @@ void Widget::update_style()
        on_style_change();
 }
 
-void Widget::set_parent(Panel *p)
+void Widget::set_parent(Container *p)
 {
        if(parent && p)
-               throw InvalidState("Widget is already in a Panel");
+               throw InvalidState("Widget is already in a Container");
        parent=p;
 
        on_reparent();
 }
 
-void Widget::set_parent(Widget &w, Panel *p)
+void Widget::set_parent(Widget &w, Container *p)
 {
        w.set_parent(p);
 }
index 8cf67d439b7c7e2a27c2b360623d21b5aa607751..6774cbec10e66991a438836e38bebd692c8f77ff 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -15,7 +15,7 @@ Distributed under the LGPL
 namespace Msp {
 namespace GLtk {
 
-class Panel;
+class Container;
 class Part;
 class Resources;
 class Style;
@@ -41,6 +41,12 @@ public:
                void style(const std::string &);
        };
 
+       sigc::signal<void, bool> signal_visibility_changed;
+       sigc::signal<void> signal_request_focus;
+       sigc::signal<void> signal_grab_pointer;
+       sigc::signal<void> signal_ungrab_pointer;
+       sigc::signal<void> signal_request_raise;
+
 protected:
        const Resources &res;
        Geometry geom;
@@ -48,7 +54,7 @@ protected:
        const Style *style;
        State state;
        bool visible;
-       Panel *parent;
+       Container *parent;
 
        Widget(const Resources &);
 public:
@@ -104,12 +110,12 @@ protected:
        Sets the widget's parent Panel.  The widget must be unparented when calling
        this function with a nonzero parameter.
        */
-       void set_parent(Panel *);
+       void set_parent(Container *);
 
        /**
        A helper function to set the parent of another widget.
        */
-       void set_parent(Widget &, Panel *);
+       void set_parent(Widget &, Container *);
 
        // More events
        virtual void on_geometry_change() { }