]> git.tdb.fi Git - libs/gltk.git/commitdiff
Move all child widget handling into Container
authorMikko Rasa <tdb@tdb.fi>
Sun, 2 Dec 2012 09:44:11 +0000 (11:44 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 2 Dec 2012 09:44:11 +0000 (11:44 +0200)
This solves some problems like the slider of a list not receiving pointer
enter/leave events.  There are no obvious downsides either.  Widgets can
always override event handlers if they want to prevent something from
happening.

The event handlers are currently just combinations of those of the Panel
and Container classes.  They'll be smoothed out shortly.

source/container.cpp
source/container.h
source/panel.cpp
source/panel.h

index bec206602a95248c72f53ad4de28f41444b71659..fade54edbb00e58eb87283bb42f460bf99052dfe 100644 (file)
@@ -12,7 +12,10 @@ hierarchy_error::hierarchy_error(const string &w):
 
 Container::Container():
        click_focus(0),
-       click_button(0)
+       click_button(0),
+       pointer_focus(0),
+       pointer_grabbed(false),
+       input_focus(0)
 { }
 
 Container::~Container()
@@ -78,29 +81,100 @@ Widget *Container::get_descendant_at(int x, int y)
        return wdg;
 }
 
+void Container::raise(Widget &wdg)
+{
+       for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
+               if((*i)->widget==&wdg)
+               {
+                       children.splice(children.end(), children, i);
+                       return;
+               }
+
+       throw hierarchy_error("widget not in container");
+}
+
+void Container::set_pointer_focus(Widget *wdg)
+{
+       if(wdg!=pointer_focus)
+       {
+               if(pointer_focus)
+                       pointer_focus->pointer_leave();
+
+               pointer_focus = wdg;
+
+               if(pointer_focus)
+                       pointer_focus->pointer_enter();
+       }
+}
+
+void Container::set_input_focus(Widget *wdg)
+{
+       if(wdg!=input_focus)
+       {
+               if(input_focus)
+                       input_focus->focus_out();
+
+               input_focus = wdg;
+
+               if(input_focus)
+               {
+                       raise(*wdg);
+                       input_focus->focus_in();
+               }
+       }
+}
+
+Widget *Container::get_final_input_focus() const
+{
+       if(Container *container = dynamic_cast<Container *>(input_focus))
+               if(Widget *focus = container->get_final_input_focus())
+                       return focus;
+
+       return input_focus;
+}
+
 void Container::button_press(int x, int y, unsigned btn)
 {
-       if(click_focus)
+       if(pointer_grabbed)
        {
-               const Geometry &cgeom = click_focus->get_geometry();
-               click_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
+               const Geometry &cgeom = pointer_focus->get_geometry();
+               pointer_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;
+                       set_pointer_focus(wdg);
+                       if(wdg->is_focusable())
+                               set_input_focus(wdg);
+               }
+               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);
+                               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)
+       if(pointer_grabbed)
+       {
+               const Geometry &cgeom = pointer_focus->get_geometry();
+               pointer_focus->button_release(x-cgeom.x, y-cgeom.y, btn);
+       }
+       else if(click_focus)
        {
                Widget *wdg = click_focus;
 
@@ -122,18 +196,27 @@ void Container::button_release(int x, int y, unsigned btn)
 
 void Container::pointer_motion(int x, int y)
 {
-       if(click_focus)
+       if(pointer_grabbed)
        {
-               const Geometry &cgeom = click_focus->get_geometry();
-               click_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
+               const Geometry &cgeom = pointer_focus->get_geometry();
+               pointer_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
        }
        else
        {
-               Widget *wdg = get_child_at(x, y);
-               if(wdg)
+               set_pointer_focus(get_child_at(x, y));
+               if(click_focus)
                {
-                       const Geometry &cgeom = wdg->get_geometry();
-                       wdg->pointer_motion(x-cgeom.x, y-cgeom.y);
+                       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);
+                       }
                }
        }
 }
@@ -142,6 +225,31 @@ void Container::pointer_leave()
 {
        Widget::pointer_leave();
        click_focus = 0;
+       set_pointer_focus(0);
+}
+
+void Container::key_press(unsigned key, unsigned mod)
+{
+       if(input_focus)
+               input_focus->key_press(key, mod);
+}
+
+void Container::key_release(unsigned key, unsigned mod)
+{
+       if(input_focus)
+               input_focus->key_release(key, mod);
+}
+
+void Container::character(wchar_t ch)
+{
+       if(input_focus)
+               input_focus->character(ch);
+}
+
+void Container::focus_out()
+{
+       set_input_focus(0);
+       Widget::focus_out();
 }
 
 void Container::on_reparent()
@@ -160,18 +268,55 @@ Container::Child::Child(Container &c, Widget *w):
        widget(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));
 }
 
 Container::Child::~Child()
 {
-       if(widget==container.click_focus)
-               container.click_focus = 0;
+       visibility_changed(false);
 }
 
 void Container::Child::visibility_changed(bool v)
 {
-       if(!v && widget==container.click_focus)
-               container.click_focus = 0;
+       if(!v)
+       {
+               if(widget==container.click_focus)
+                       container.click_focus = 0;
+               if(widget==container.pointer_focus)
+                       container.set_pointer_focus(0);
+               if(widget==container.input_focus)
+                       container.set_input_focus(0);
+       }
+}
+
+void Container::Child::request_focus()
+{
+       container.set_input_focus(widget);
+       if(container.parent && container.visible)
+               container.set_focus();
+}
+
+void Container::Child::grab_pointer()
+{
+       if(!container.pointer_grabbed)
+       {
+               container.set_pointer_focus(widget);
+               container.pointer_grabbed = true;
+               container.signal_grab_pointer.emit();
+       }
+}
+
+void Container::Child::ungrab_pointer()
+{
+       if(container.pointer_grabbed && container.pointer_focus==widget)
+       {
+               // XXX Should set to the widget under pointer
+               container.set_pointer_focus(0);
+               container.pointer_grabbed = false;
+               container.signal_ungrab_pointer.emit();
+       }
 }
 
 } // namespace GLtk
index d1120cd8c36bb1e25fb845f6a20831cc264c057c..bca1c59cff79815872c9dd8dca20bcfd0a70ae23 100644 (file)
@@ -29,11 +29,17 @@ protected:
                virtual ~Child();
 
                void visibility_changed(bool);
+               void request_focus();
+               void grab_pointer();
+               void ungrab_pointer();
        };
 
        std::list<Child *> children;
        Widget *click_focus;
        unsigned click_button;
+       Widget *pointer_focus;
+       bool pointer_grabbed;
+       Widget *input_focus;
 
        Container();
 public:
@@ -47,11 +53,23 @@ public:
        std::list<Widget *> get_children() const;
        Widget *get_child_at(int, int);
        Widget *get_descendant_at(int, int);
+       void raise(Widget &);
+
+protected:
+       void set_pointer_focus(Widget *);
+       void set_input_focus(Widget *);
+public:
+       Widget *get_input_focus() const { return input_focus; }
+       Widget *get_final_input_focus() const;
 
        virtual void button_press(int, int, unsigned);
        virtual void button_release(int, int, unsigned);
        virtual void pointer_motion(int, int);
        virtual void pointer_leave();
+       virtual void key_press(unsigned, unsigned);
+       virtual void key_release(unsigned, unsigned);
+       virtual void character(wchar_t);
+       virtual void focus_out();
 protected:
        virtual void on_reparent();
        virtual void on_child_added(Widget &) { }
index 11d90e40349b04d1c49534119be5f36f100998b4..c7b1574979d7883d8f03c44816dc6152eb1daf4a 100644 (file)
@@ -20,10 +20,7 @@ namespace Msp {
 namespace GLtk {
 
 Panel::Panel():
-       layout(0),
-       pointer_focus(0),
-       pointer_grabbed(false),
-       input_focus(0)
+       layout(0)
 { }
 
 Panel::~Panel()
@@ -45,34 +42,6 @@ void Panel::autosize()
                layout->autosize();
 }
 
-Panel::Child *Panel::create_child(Widget *wdg)
-{
-       return new Child(*this, wdg);
-}
-
-void Panel::raise(Widget &wdg)
-{
-       for(list<Container::Child *>::iterator i=children.begin(); i!=children.end(); ++i)
-               if((*i)->widget==&wdg)
-               {
-                       children.splice(children.end(), children, i);
-                       return;
-               }
-
-       throw hierarchy_error("widget not in panel");
-}
-
-Widget *Panel::get_final_input_focus() const
-{
-       if(Panel *panel = dynamic_cast<Panel *>(input_focus))
-       {
-               Widget *focus = panel->get_final_input_focus();
-               if(focus)
-                       return focus;
-       }
-       return input_focus;
-}
-
 void Panel::render_special(const Part &part, GL::Renderer &renderer) const
 {
        if(part.get_name()=="children")
@@ -83,80 +52,6 @@ void Panel::render_special(const Part &part, GL::Renderer &renderer) const
        }
 }
 
-void Panel::button_press(int x, int y, unsigned btn)
-{
-       if(pointer_grabbed)
-       {
-               const Geometry &cgeom = pointer_focus->get_geometry();
-               pointer_focus->button_press(x-cgeom.x, y-cgeom.y, btn);
-       }
-       else
-       {
-               if(Widget *wdg = get_child_at(x, y))
-               {
-                       set_pointer_focus(wdg);
-                       if(wdg->is_focusable())
-                               set_input_focus(wdg);
-               }
-               Container::button_press(x, y, btn);
-       }
-}
-
-void Panel::button_release(int x, int y, unsigned btn)
-{
-       if(pointer_grabbed)
-       {
-               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_grabbed)
-       {
-               const Geometry &cgeom = pointer_focus->get_geometry();
-               pointer_focus->pointer_motion(x-cgeom.x, y-cgeom.y);
-       }
-       else
-       {
-               set_pointer_focus(get_child_at(x, y));
-               Container::pointer_motion(x, y);
-       }
-}
-
-void Panel::pointer_leave()
-{
-       Container::pointer_leave();
-       set_pointer_focus(0);
-}
-
-void Panel::key_press(unsigned key, unsigned mod)
-{
-       if(input_focus)
-               input_focus->key_press(key, mod);
-}
-
-void Panel::key_release(unsigned key, unsigned mod)
-{
-       if(input_focus)
-               input_focus->key_release(key, mod);
-}
-
-void Panel::character(wchar_t ch)
-{
-       if(input_focus)
-               input_focus->character(ch);
-}
-
-void Panel::focus_out()
-{
-       set_input_focus(0);
-       Widget::focus_out();
-}
-
 void Panel::on_geometry_change()
 {
        if(layout)
@@ -181,37 +76,6 @@ void Panel::on_child_removed(Widget &wdg)
        }
 }
 
-void Panel::set_pointer_focus(Widget *wdg)
-{
-       if(wdg!=pointer_focus)
-       {
-               if(pointer_focus)
-                       pointer_focus->pointer_leave();
-
-               pointer_focus = wdg;
-
-               if(pointer_focus)
-                       pointer_focus->pointer_enter();
-       }
-}
-
-void Panel::set_input_focus(Widget *wdg)
-{
-       if(wdg!=input_focus)
-       {
-               if(input_focus)
-                       input_focus->focus_out();
-
-               input_focus = wdg;
-
-               if(input_focus)
-               {
-                       raise(*wdg);
-                       input_focus->focus_in();
-               }
-       }
-}
-
 
 Panel::Loader::Loader(Panel &p, map<string, Widget *> &m):
        Widget::Loader(p),
@@ -248,63 +112,5 @@ 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()
-{
-       Panel &panel = static_cast<Panel &>(container);
-       panel.set_input_focus(widget);
-       if(panel.parent && panel.visible)
-               panel.set_focus();
-}
-
-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 170364dae0d1b5e1dd8df444593c7445ab7361e5..c50725b9b940cb255ed635ad665cc82c55bddfe7 100644 (file)
@@ -34,21 +34,7 @@ public:
        };
 
 protected:
-       struct Child: public Container::Child
-       {
-               Child(Panel &, Widget *);
-               virtual ~Child();
-
-               void visibility_changed(bool);
-               void request_focus();
-               void grab_pointer();
-               void ungrab_pointer();
-       };
-
        Layout *layout;
-       Widget *pointer_focus;
-       bool pointer_grabbed;
-       Widget *input_focus;
 
        Panel(const Panel &);
        Panel &operator=(const Panel &);
@@ -61,33 +47,12 @@ public:
        void set_layout(Layout *);
        virtual void autosize();
 
-protected:
-       virtual Child *create_child(Widget *);
-
-public:
-       void raise(Widget &);
-       Widget *get_input_focus() const { return input_focus; }
-       Widget *get_final_input_focus() const;
-
 protected:
        virtual void render_special(const Part &, GL::Renderer &) const;
 
-public:
-       virtual void button_press(int, int, unsigned);
-       virtual void button_release(int, int, unsigned);
-       virtual void pointer_motion(int, int);
-       virtual void pointer_leave();
-       virtual void key_press(unsigned, unsigned);
-       virtual void key_release(unsigned, unsigned);
-       virtual void character(wchar_t);
-       virtual void focus_out();
-protected:
        virtual void on_geometry_change();
        virtual void on_child_added(Widget &);
        virtual void on_child_removed(Widget &);
-
-       void set_pointer_focus(Widget *);
-       void set_input_focus(Widget *);
 };
 
 } // namespace GLtk