]> git.tdb.fi Git - libs/gltk.git/commitdiff
Add Dropdown widget
authorMikko Rasa <tdb@tdb.fi>
Sat, 29 Dec 2007 08:44:09 +0000 (08:44 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sat, 29 Dec 2007 08:44:09 +0000 (08:44 +0000)
Allow widgets to grab the pointer
Support raising widgets
Fix Button and Toggle logic a bit
Bugfixes

source/button.cpp
source/dropdown.cpp [new file with mode: 0644]
source/dropdown.h [new file with mode: 0644]
source/list.cpp
source/list.h
source/panel.cpp
source/panel.h
source/toggle.cpp
source/toggle.h

index bc6fd274d7362dae651c7d15f37eafdbb62f7be7..3661c0148a0f56f61d35e85ad08de4074e3a4f4b 100644 (file)
@@ -12,7 +12,8 @@ namespace Msp {
 namespace GLtk {
 
 Button::Button(const Resources &r, const std::string &t):
-       Widget(r)
+       Widget(r),
+       pressed(false)
 {
        set_text(t);
        update_style();
@@ -26,12 +27,15 @@ void Button::set_text(const std::string &t)
 void Button::button_press(int, int, unsigned btn)
 {
        if(btn==1)
+       {
+               pressed=true;
                state=ACTIVE;
+       }
 }
 
 void Button::button_release(int x, int y, unsigned btn)
 {
-       if(btn==1)
+       if(pressed && btn==1)
        {
                if(geom.is_inside_relative(x, y))
                {
@@ -40,6 +44,8 @@ void Button::button_release(int x, int y, unsigned btn)
                }
                else
                        state=NORMAL;
+               
+               pressed=false;
        }
 }
 
diff --git a/source/dropdown.cpp b/source/dropdown.cpp
new file mode 100644 (file)
index 0000000..bc44f27
--- /dev/null
@@ -0,0 +1,120 @@
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "dropdown.h"
+#include "list.h"
+#include "panel.h"
+#include "part.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GLtk {
+
+Dropdown::Dropdown(const Resources &r):
+       Widget(r),
+       list(new List(res)),
+       list_active(false)
+{
+       list->signal_item_selected.connect(sigc::mem_fun(this, &Dropdown::list_item_selected));
+
+       update_style();
+}
+
+Dropdown::~Dropdown()
+{
+       delete list;
+}
+
+void Dropdown::append(const string &item)
+{
+       list->append(item);
+}
+
+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(state==ACTIVE)
+       {
+               state=HOVER;
+               parent->ungrab_pointer(*this);
+       }
+       else if(btn==1)
+       {
+               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);
+       }
+}
+
+void Dropdown::pointer_enter()
+{
+       if(state==NORMAL)
+               state=HOVER;
+}
+
+void Dropdown::pointer_leave()
+{
+       if(state==HOVER)
+               state=NORMAL;
+}
+
+void Dropdown::render_special(const Part &part) const
+{
+       if(part.get_name()=="text")
+               render_text(part, text);
+       else if(part.get_name()=="list" && state==ACTIVE)
+               list->render();
+}
+
+void Dropdown::on_geometry_change()
+{
+       list->set_geometry(Geometry(0, -100, geom.w, 100));
+}
+
+void Dropdown::list_item_selected(unsigned index, const std::string &item)
+{
+       text=item;
+
+       list_active=false;
+       state=NORMAL;
+       if(parent)
+               parent->ungrab_pointer(*this);
+
+       signal_item_selected.emit(index, item);
+}
+
+} // namespace GLtk
+} // namespace Msp
diff --git a/source/dropdown.h b/source/dropdown.h
new file mode 100644 (file)
index 0000000..825b800
--- /dev/null
@@ -0,0 +1,51 @@
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GLTK_DROPDOWN_H_
+#define MSP_GLTK_DROPDOWN_H_
+
+#include <sigc++/signal.h>
+#include "widget.h"
+
+namespace Msp {
+namespace GLtk {
+
+class List;
+
+class Dropdown: public Widget
+{
+private:
+       List *list;
+       std::string text;
+       bool list_active;
+
+public:
+       sigc::signal<void, int, const std::string &> signal_item_selected;
+
+       Dropdown(const Resources &);
+       ~Dropdown();
+
+       void append(const std::string &);
+
+       virtual void button_press(int, int, unsigned);
+       virtual void button_release(int, int, unsigned);
+       virtual void pointer_motion(int, int);
+       virtual void pointer_enter();
+       virtual void pointer_leave();
+private:
+       virtual const char *get_class() const { return "dropdown"; }
+       virtual void render_special(const Part &) const;
+
+       virtual void on_geometry_change();
+
+       void list_item_selected(unsigned, const std::string &);
+};
+
+} // namespace GLtk
+} // namespace Msp
+
+#endif
index 73f427bff7fdf2dbadb84eaa4e67b55152e27d0d..4f8b27c649a909ddd8fabd7ce7c7db1f273d2c30 100644 (file)
@@ -33,6 +33,11 @@ List::List(const Resources &r):
        update_style();
 }
 
+List::~List()
+{
+       delete slider;
+}
+
 void List::append(const string &v)
 {
        items.push_back(v);
index edcec3395a8f18e3255b6023f6ebcce5620f1757..77d7e9f49166ac53e62c5a06785e0e14bd12ed28 100644 (file)
@@ -46,6 +46,8 @@ 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 &);
        void remove(unsigned);
index 22ccb1b97fbe9bde56fd38186e7233157f698f46..f17439a5eca810b8510d3537fc750a53c2b5868a 100644 (file)
@@ -7,6 +7,7 @@ Distributed under the LGPL
 
 #include <msp/core/refptr.h>
 #include "button.h"
+#include "dropdown.h"
 #include "entry.h"
 #include "hslider.h"
 #include "indicator.h"
@@ -53,6 +54,16 @@ void Panel::remove(Widget &wdg)
        }
 }
 
+void Panel::raise(Widget &wdg)
+{
+       ChildSeq::iterator i=find(children.begin(), children.end(), &wdg);
+       if(i!=children.end())
+       {
+               children.erase(i);
+               children.push_back(&wdg);
+       }
+}
+
 void Panel::button_press(int x, int y, unsigned btn)
 {
        if(pointer_grab>0)
@@ -140,6 +151,22 @@ void Panel::child_hidden(Widget &wdg)
                set_pointer_focus(0, 0);
 }
 
+void Panel::grab_pointer(Widget &wdg)
+{
+       if(pointer_grab==0 || pointer_focus==&wdg)
+               set_pointer_focus(&wdg, 255);
+       else
+               throw InvalidState("Pointer is already grabbed");
+}
+
+void Panel::ungrab_pointer(Widget &wdg)
+{
+       if(pointer_focus==&wdg)
+               set_pointer_focus(0, 0);
+       else if(pointer_grab>0)
+               throw Exception("Someone is trying to steal the pointer!");
+}
+
 void Panel::render_special(const Part &part) const
 {
        if(part.get_name()=="children")
@@ -199,6 +226,7 @@ Panel::Loader::Loader(Panel &p, map<string, Widget *> &m):
        wdg_map(m)
 {
        add("button",    &Loader::child<Button>);
+       add("dropdown",  &Loader::child<Dropdown>);
        add("entry",     &Loader::child<Entry>);
        add("hslider",   &Loader::child<HSlider>);
        add("indicator", &Loader::child<Indicator>);
index ad89a52b8f03ee20eed1dd71416e23c68484bccd..529354ddb92959cce47bea069a74a0efe4036c06 100644 (file)
@@ -51,6 +51,7 @@ public:
 
        void add(Widget &);
        void remove(Widget &);
+       void raise(Widget &);
 
        virtual void button_press(int, int, unsigned);
        virtual void button_release(int, int, unsigned);
@@ -59,10 +60,14 @@ public:
        virtual void key_press(unsigned, unsigned, wchar_t);
        virtual void key_release(unsigned, unsigned);
        virtual void focus_out();
+
        void child_hidden(Widget &);
+       void grab_pointer(Widget &);
+       void ungrab_pointer(Widget &);
 private:
        virtual const char *get_class() const { return "panel"; }
        virtual void render_special(const Part &) const;
+
        void set_pointer_focus(Widget *, int);
        void set_input_focus(Widget *);
        Widget *get_child_at(int, int);
index 2e3488ac24a465fe890820d2dff877cfdb2bfc7d..1495344219f89013e790636e4d621f21e8399013 100644 (file)
@@ -13,23 +13,37 @@ namespace GLtk {
 
 Toggle::Toggle(const Resources &r):
        Widget(r),
+       pressed(false),
        value(false)
 {
        update_style();
 }
 
-void Toggle::button_release(int x, int y, unsigned btn)
+void Toggle::set_value(bool v)
+{
+       value=v;
+       state=(value ? ACTIVE : HOVER);
+}
+
+void Toggle::button_press(int, int, unsigned btn)
 {
        if(btn==1)
+               pressed=true;
+}
+
+void Toggle::button_release(int x, int y, unsigned btn)
+{
+       if(pressed && btn==1)
        {
                if(geom.is_inside_relative(x, y))
                {
-                       value=!value;
-                       state=(value ? ACTIVE : HOVER);
+                       set_value(!value);
                        signal_toggled.emit(value);
                }
                else
                        state=NORMAL;
+
+               pressed=false;
        }
 }
 
@@ -64,5 +78,11 @@ Toggle &Toggle::Loader::get_object() const
        return static_cast<Toggle &>(wdg);
 }
 
+void Toggle::Loader::finish()
+{
+       Toggle &tgl=static_cast<Toggle &>(wdg);
+       tgl.state=(tgl.value ? ACTIVE : NORMAL);
+}
+
 } // namespace GLtk
 } // namespace Msp
index 305c3ca0617f4d2707c509958a3fe72a07469456..6e3d6326fb0388784e7f0b50c6e46329b8be5c98 100644 (file)
@@ -25,10 +25,13 @@ public:
        public:
                Loader(Toggle &);
                Toggle &get_object() const;
+       private:
+               virtual void finish();
        };
 
 private:
        std::string text;
+       bool pressed;
        bool value;
 
 public:
@@ -36,8 +39,10 @@ public:
 
        Toggle(const Resources &);
 
+       void set_value(bool);
        bool get_value() const { return value; }
 
+       virtual void button_press(int, int, unsigned);
        virtual void button_release(int, int, unsigned);
        virtual void pointer_enter();
        virtual void pointer_leave();