From 47948ee8882fe0d182a2d141dd2939ca62e43182 Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 27 Mar 2015 18:35:42 -0300 Subject: [PATCH] Move app::Tabs animation related stuff to app::AnimatedWidget --- src/app/ui/animated_widget.h | 84 ++++++++++++++++++++++++++++++++++++ src/app/ui/tabs.cpp | 64 +++++++++------------------ src/app/ui/tabs.h | 22 +++++----- 3 files changed, 115 insertions(+), 55 deletions(-) create mode 100644 src/app/ui/animated_widget.h diff --git a/src/app/ui/animated_widget.h b/src/app/ui/animated_widget.h new file mode 100644 index 000000000..de0b1a005 --- /dev/null +++ b/src/app/ui/animated_widget.h @@ -0,0 +1,84 @@ +// Aseprite +// Copyright (C) 2001-2015 David Capello +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. + +#ifndef APP_UI_ANIMATED_WIDGET_H_INCLUDED +#define APP_UI_ANIMATED_WIDGET_H_INCLUDED +#pragma once + +#include "base/connection.h" +#include "ui/timer.h" + +namespace app { + + class AnimatedWidget { + public: + AnimatedWidget() + : m_timer(1000/60) + , m_animation(0) + { + m_scopedConn = m_timer.Tick.connect(&AnimatedWidget::onTick, this); + } + + ~AnimatedWidget() { + m_timer.stop(); + } + + // For each animation frame + virtual void onAnimationStart() { } + virtual void onAnimationStop() { } + virtual void onAnimationFrame() { } + + protected: + void startAnimation(int animation, int lifespan) { + // Stop previous animation + if (m_animation) + stopAnimation(); + + m_animation = animation; + m_animationTime = 0; + m_animationLifespan = lifespan; + m_timer.start(); + + onAnimationStart(); + } + + void stopAnimation() { + m_animation = 0; + m_timer.stop(); + onAnimationStop(); + } + + int animation() const { + return m_animation; + } + + double animationTime() const { + return double(m_animationTime) / double(m_animationLifespan); + } + + private: + void onTick() { + if (m_animation) { + if (m_animationTime == m_animationLifespan) + stopAnimation(); + else + ++m_animationTime; + + onAnimationFrame(); + } + } + + ui::Timer m_timer; + int m_animation; + int m_animationTime; + int m_animationLifespan; + ScopedConnection m_scopedConn; + }; + +} // namespace app + +#endif diff --git a/src/app/ui/tabs.cpp b/src/app/ui/tabs.cpp index 4dd6f4e0b..c573f908b 100644 --- a/src/app/ui/tabs.cpp +++ b/src/app/ui/tabs.cpp @@ -61,8 +61,6 @@ Tabs::Tabs(TabsDelegate* delegate) , m_clickedCloseButton(false) , m_selected(nullptr) , m_delegate(delegate) - , m_timer(1000/60, this) - , m_ani(ANI_NONE) , m_removedTab(nullptr) , m_isDragging(false) , m_floatingTab(nullptr) @@ -80,7 +78,7 @@ Tabs::~Tabs() } // Stop animation - stopAni(); + stopAnimation(); // Remove all tabs for (Tab* tab : m_list) @@ -91,7 +89,7 @@ Tabs::~Tabs() void Tabs::addTab(TabView* tabView, int pos) { resetOldPositions(); - startAni(ANI_ADDING_TAB, ANI_ADDING_TAB_TICKS); + startAnimation(ANI_ADDING_TAB, ANI_ADDING_TAB_TICKS); Tab* tab = new Tab(tabView); if (pos < 0) @@ -137,7 +135,7 @@ void Tabs::removeTab(TabView* tabView) tab->view = nullptr; // The view will be destroyed after Tabs::removeTab() anyway resetOldPositions(); - startAni(ANI_REMOVING_TAB, ANI_REMOVING_TAB_TICKS); + startAnimation(ANI_REMOVING_TAB, ANI_REMOVING_TAB_TICKS); updateTabs(); } @@ -270,9 +268,9 @@ bool Tabs::onProcessMessage(Message* msg) m_list.insert(m_list.begin()+i, m_selected); m_dragTabIndex = i; - resetOldPositions(double(m_ani_t) / double(m_ani_T)); + resetOldPositions(animationTime()); updateTabs(); - startAni(ANI_REORDER_TABS, ANI_REORDER_TABS_TICKS); + startAnimation(ANI_REORDER_TABS, ANI_REORDER_TABS_TICKS); } if (justDocked) @@ -367,18 +365,6 @@ bool Tabs::onProcessMessage(Message* msg) return true; } - case kTimerMessage: { - if (m_ani != ANI_NONE) { - if (m_ani_t == m_ani_T) - stopAni(); - else - ++m_ani_t; - - invalidate(); - } - break; - } - } return Widget::onProcessMessage(msg); @@ -390,7 +376,7 @@ void Tabs::onPaint(PaintEvent& ev) Graphics* g = ev.getGraphics(); gfx::Rect rect = getClientBounds(); gfx::Rect box(rect.x, rect.y, rect.w, - (m_list.empty() && m_ani == ANI_NONE ? 0: + (m_list.empty() && animation() == ANI_NONE ? 0: theme->dimensions.tabsHeight() - theme->dimensions.tabsEmptyHeight())); g->fillRect(theme->colors.windowFace(), g->getClipBounds()); @@ -410,7 +396,7 @@ void Tabs::onPaint(PaintEvent& ev) } // Draw deleted tab - if (m_ani == ANI_REMOVING_TAB && m_removedTab) { + if (animation() == ANI_REMOVING_TAB && m_removedTab) { m_removedTab->width = 0; box = getTabBounds(m_removedTab); drawTab(g, box, m_removedTab, 0, @@ -420,12 +406,12 @@ void Tabs::onPaint(PaintEvent& ev) // Tab that is being dragged if (m_selected && m_selected != m_floatingTab) { - double t = double(m_ani_t) / double(m_ani_T); + double t = animationTime(); Tab* tab = m_selected; box = getTabBounds(tab); int dy = 0; - if (m_ani == ANI_ADDING_TAB) + if (animation() == ANI_ADDING_TAB) dy = int(box.h - box.h * t); drawTab(g, box, m_selected, dy, (tab == m_hot), true); @@ -443,7 +429,7 @@ void Tabs::onPreferredSize(PreferredSizeEvent& ev) SkinTheme* theme = static_cast(this->getTheme()); gfx::Size reqsize(0, 0); - if (m_list.empty() && m_ani == ANI_NONE) + if (m_list.empty() && animation() == ANI_NONE) reqsize.h = theme->dimensions.tabsEmptyHeight(); else reqsize.h = theme->dimensions.tabsHeight(); @@ -665,23 +651,13 @@ void Tabs::resetOldPositions(double t) } } -void Tabs::startAni(Ani ani, int T) +void Tabs::onAnimationFrame() { - // Stop previous animation - if (m_ani != ANI_NONE) - stopAni(); - - m_ani = ani; - m_ani_t = 0; - m_ani_T = T; - m_timer.start(); + invalidate(); } -void Tabs::stopAni() +void Tabs::onAnimationStop() { - m_ani = ANI_NONE; - m_timer.stop(); - if (m_list.empty()) { Widget* root = getRoot(); if (root) @@ -711,9 +687,9 @@ void Tabs::stopDrag() m_selected->oldWidth = m_selected->width; } - resetOldPositions(double(m_ani_t) / double(m_ani_T)); + resetOldPositions(animationTime()); updateTabs(); - startAni(ANI_REORDER_TABS, ANI_REORDER_TABS_TICKS); + startAnimation(ANI_REORDER_TABS, ANI_REORDER_TABS_TICKS); } gfx::Rect Tabs::getTabBounds(Tab* tab) @@ -721,12 +697,12 @@ gfx::Rect Tabs::getTabBounds(Tab* tab) SkinTheme* theme = static_cast(this->getTheme()); gfx::Rect rect = getClientBounds(); gfx::Rect box(rect.x, rect.y, rect.w, - (m_list.empty() && m_ani == ANI_NONE ? 0: + (m_list.empty() && animation() == ANI_NONE ? 0: theme->dimensions.tabsHeight() - theme->dimensions.tabsEmptyHeight())); int startX = m_border*guiscale(); - double t = double(m_ani_t) / double(m_ani_T); + double t = animationTime(); - if (m_ani == ANI_NONE) { + if (animation() == ANI_NONE) { box.x = startX + tab->x; box.w = tab->width; } @@ -773,7 +749,7 @@ void Tabs::createFloatingTab(Tab* tab) m_floatingTab = tab; m_removedTab = nullptr; - startAni(ANI_REMOVING_TAB, ANI_REMOVING_TAB_TICKS); + startAnimation(ANI_REMOVING_TAB, ANI_REMOVING_TAB_TICKS); updateTabs(); } @@ -790,7 +766,7 @@ void Tabs::destroyFloatingTab() m_floatingTab = nullptr; resetOldPositions(); - startAni(ANI_ADDING_TAB, ANI_ADDING_TAB_TICKS); + startAnimation(ANI_ADDING_TAB, ANI_ADDING_TAB_TICKS); updateTabs(); tab->oldX = tab->x; diff --git a/src/app/ui/tabs.h b/src/app/ui/tabs.h index 696e30d51..b20796397 100644 --- a/src/app/ui/tabs.h +++ b/src/app/ui/tabs.h @@ -9,6 +9,7 @@ #define APP_UI_TABS_H_INCLUDED #pragma once +#include "app/ui/animated_widget.h" #include "ui/mouse_buttons.h" #include "ui/timer.h" #include "ui/widget.h" @@ -74,7 +75,8 @@ namespace app { }; // Tabs control. Used to show opened documents. - class Tabs : public ui::Widget { + class Tabs : public ui::Widget + , public AnimatedWidget { struct Tab { TabView* view; std::string text; @@ -90,10 +92,12 @@ namespace app { typedef std::vector TabsList; typedef TabsList::iterator TabsListIterator; - enum Ani { ANI_NONE, - ANI_ADDING_TAB, - ANI_REMOVING_TAB, - ANI_REORDER_TABS }; + enum Ani : int { + ANI_NONE, + ANI_ADDING_TAB, + ANI_REMOVING_TAB, + ANI_REORDER_TABS + }; public: Tabs(TabsDelegate* delegate); @@ -113,12 +117,12 @@ namespace app { void onPaint(ui::PaintEvent& ev) override; void onResize(ui::ResizeEvent& ev) override; void onPreferredSize(ui::PreferredSizeEvent& ev) override; + void onAnimationFrame() override; + void onAnimationStop() override; private: void resetOldPositions(); void resetOldPositions(double t); - void startAni(Ani ani, int T); - void stopAni(); void selectTabInternal(Tab* tab); void drawTab(ui::Graphics* g, const gfx::Rect& box, Tab* tab, int dy, bool hover, bool selected); @@ -146,10 +150,6 @@ namespace app { TabsDelegate* m_delegate; // Variables for animation purposes - ui::Timer m_timer; - Ani m_ani; // Current animation - int m_ani_t; // Number of ticks from the beginning of the transition/animation - int m_ani_T; // Number of ticks in total for the current transition/animation Tab* m_removedTab; // Drag-and-drop