]> git.tdb.fi Git - libs/gltk.git/commitdiff
Add a system for animating widgets
authorMikko Rasa <tdb@tdb.fi>
Sun, 8 Sep 2019 14:17:02 +0000 (17:17 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 8 Sep 2019 14:17:02 +0000 (17:17 +0300)
source/container.cpp
source/container.h
source/root.cpp
source/root.h
source/widget.cpp
source/widget.h

index 91fa48758c8a60ec90cba48331798b3201906ae1..62e6e125429bb7a10ca10b33476bc5d36fbd1a92 100644 (file)
@@ -30,6 +30,8 @@ void Container::add(Widget &wdg)
 {
        wdg.set_parent(this);
        children.push_back(create_child(&wdg));
+       if(wdg.get_animation_interval())
+               check_animation_interval();
        on_child_added(wdg);
 }
 
@@ -41,6 +43,8 @@ void Container::remove(Widget &wdg)
                        wdg.set_parent(0);
                        delete *i;
                        children.erase(i);
+                       if(wdg.get_animation_interval())
+                               check_animation_interval();
                        on_child_removed(wdg);
                        return;
                }
@@ -165,6 +169,20 @@ Widget *Container::get_final_input_focus() const
        return input_focus;
 }
 
+void Container::check_animation_interval()
+{
+       Time::TimeDelta shortest;
+       for(list<Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
+       {
+               const Time::TimeDelta &child_iv = (*i)->widget->get_animation_interval();
+               if(child_iv && (!shortest || child_iv<shortest))
+                       shortest = child_iv;
+       }
+
+       if(shortest!=anim_interval)
+               set_animation_interval(shortest);
+}
+
 void Container::button_press(int x, int y, unsigned btn)
 {
        if(Widget *child = get_pointer_target(x, y, false))
@@ -310,6 +328,24 @@ bool Container::navigate(Navigation nav)
                return false;
 }
 
+void Container::animate(const Time::TimeDelta &dt)
+{
+       for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
+       {
+               const Time::TimeDelta &child_iv = (*i)->widget->get_animation_interval();
+               if(!child_iv)
+                       continue;
+
+               (*i)->time_since_animate += dt;
+               if((*i)->time_since_animate>=child_iv)
+               {
+                       Time::TimeDelta child_dt = (*i)->time_since_animate;
+                       (*i)->time_since_animate = min((*i)->time_since_animate-child_iv, child_iv);
+                       (*i)->widget->animate(child_dt);
+               }
+       }
+}
+
 void Container::on_reparent()
 {
        for(list<Child *>::iterator i=children.begin(); i!=children.end(); ++i)
@@ -329,6 +365,7 @@ Container::Child::Child(Container &c, Widget *w):
        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));
+       widget->signal_request_animation.connect(sigc::mem_fun(this, &Child::request_animation));
 }
 
 Container::Child::~Child()
@@ -377,5 +414,12 @@ void Container::Child::ungrab_pointer()
        }
 }
 
+void Container::Child::request_animation(const Time::TimeDelta &interval)
+{
+       if(!interval)
+               time_since_animate = Time::zero;
+       container.check_animation_interval();
+}
+
 } // namespace GLtk
 } // namespace Msp
index b463ff2273815874f1df71ef2358f9f4ac6ba028..f68d81fcee59c85afbfa1f0ed74d4c59a7cff6a7 100644 (file)
@@ -24,6 +24,7 @@ protected:
        {
                Container &container;
                Widget *widget;
+               Time::TimeDelta time_since_animate;
 
                Child(Container &, Widget *);
                virtual ~Child();
@@ -32,6 +33,7 @@ protected:
                void request_focus();
                void grab_pointer();
                void ungrab_pointer();
+               void request_animation(const Time::TimeDelta &);
        };
 
        std::list<Child *> children;
@@ -66,6 +68,10 @@ public:
        Widget *get_input_focus() const { return input_focus; }
        Widget *get_final_input_focus() const;
 
+private:
+       void check_animation_interval();
+
+public:
        virtual void button_press(int, int, unsigned);
        virtual void button_release(int, int, unsigned);
        virtual void pointer_motion(int, int);
@@ -81,6 +87,7 @@ public:
        virtual bool character(wchar_t);
        virtual void focus_out();
        virtual bool navigate(Navigation);
+       virtual void animate(const Time::TimeDelta &);
 protected:
        virtual void on_reparent();
        virtual void on_child_added(Widget &) { }
index 4a2d611d84c8c9692840fc9564325ff50389f8d1..ad1ca5b7936cbef133056a0aa7296d7474055b6f 100644 (file)
@@ -91,6 +91,12 @@ Root::~Root()
 
 void Root::tick()
 {
+       Time::TimeStamp t = Time::now();
+       Time::TimeDelta dt = (last_tick ? t-last_tick : Time::zero);
+       last_tick = t;
+
+       animate(dt);
+
        if(tooltip_timeout && Time::now()>tooltip_timeout)
        {
                std::string tip;
index 7d5a592805f187a096e1fbc5e6f1a40822981d78..5de362619b02ddf03faba1300b4739830038428e 100644 (file)
@@ -39,6 +39,7 @@ private:
        int pointer_x;
        int pointer_y;
        Time::TimeStamp tooltip_timeout;
+       Time::TimeStamp last_tick;
        Widget *tooltip_target;
        Msp::GL::Camera camera;
        Msp::GL::Program *shprog;
index aa05675b97c1c989c499916247173785593dad5c..b40aa75214f2855def232ebbd48a6f85b7b3fb66 100644 (file)
@@ -188,6 +188,20 @@ void Widget::set_state(State mask, State bits)
                rebuild();
 }
 
+void Widget::set_animation_interval(const Time::TimeDelta &iv)
+{
+       if(iv<Time::zero)
+               throw invalid_argument("Widget::set_animation_interval");
+
+       anim_interval = iv;
+       signal_request_animation.emit(anim_interval);
+}
+
+void Widget::stop_animation()
+{
+       set_animation_interval(Time::zero);
+}
+
 void Widget::rebuild()
 {
        if(!style)
index eb8fa2324350b42335eb92a0bd8aec7fc70e2f7b..94ee7f69ff4b3a4d0b00b42ac9f02fa185c3c0cc 100644 (file)
@@ -40,6 +40,7 @@ public:
        sigc::signal<void> signal_request_focus;
        sigc::signal<void> signal_grab_pointer;
        sigc::signal<void> signal_ungrab_pointer;
+       sigc::signal<void, const Time::TimeDelta &> signal_request_animation;
 
 protected:
        Geometry geom;
@@ -51,6 +52,7 @@ protected:
        Container *parent;
        std::string tooltip;
        PartCache part_cache;
+       Time::TimeDelta anim_interval;
 
        Widget();
 private:
@@ -124,6 +126,12 @@ protected:
 public:
        State get_state() const { return state; }
 
+protected:
+       void set_animation_interval(const Time::TimeDelta &);
+       void stop_animation();
+public:
+       const Time::TimeDelta &get_animation_interval() const { return anim_interval; }
+
 protected:
        void rebuild();
        virtual void rebuild_special(const Part &);
@@ -149,6 +157,7 @@ public:
        virtual void focus_in();
        virtual void focus_out();
        virtual bool navigate(Navigation) { return false; }
+       virtual void animate(const Time::TimeDelta &) { }
 protected:
        virtual void on_geometry_change() { }
        virtual void on_style_change() { }