tb_widget_animation.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #include "animation/tb_widget_animation.h"
  6. #include "tb_window.h"
  7. #include "tb_widgets.h"
  8. #include "tb_widgets_common.h"
  9. #include "tb_message_window.h"
  10. #include "tb_list.h"
  11. namespace tb {
  12. TBLinkListOf<TBWidgetAnimationObject> widget_animations;
  13. #define LERP(src, dst, progress) (src + (dst - src) * progress)
  14. // == TBWidgetAnimationObject =============================================================
  15. TBWidgetAnimationObject::TBWidgetAnimationObject(TBWidget *widget)
  16. : m_widget(widget)
  17. {
  18. widget_animations.AddLast(this);
  19. }
  20. TBWidgetAnimationObject::~TBWidgetAnimationObject()
  21. {
  22. widget_animations.Remove(this);
  23. }
  24. // == TBWidgetAnimationOpacity ============================================================
  25. TBWidgetAnimationOpacity::TBWidgetAnimationOpacity(TBWidget *widget, float src_opacity, float dst_opacity, bool die)
  26. : TBWidgetAnimationObject(widget)
  27. , m_src_opacity(src_opacity)
  28. , m_dst_opacity(dst_opacity)
  29. , m_die(die)
  30. {
  31. }
  32. void TBWidgetAnimationOpacity::OnAnimationStart()
  33. {
  34. // Make sure we don't stay idle if nothing is scheduled (hack).
  35. // FIX: fix this properly
  36. m_widget->Invalidate();
  37. m_widget->SetOpacity(m_src_opacity);
  38. }
  39. void TBWidgetAnimationOpacity::OnAnimationUpdate(float progress)
  40. {
  41. m_widget->SetOpacity(LERP(m_src_opacity, m_dst_opacity, progress));
  42. }
  43. void TBWidgetAnimationOpacity::OnAnimationStop(bool aborted)
  44. {
  45. // If we're aborted, it may be because the widget is being deleted
  46. if (m_die && !aborted)
  47. {
  48. TBWidgetSafePointer the_widget(m_widget);
  49. if (m_widget->GetParent())
  50. m_widget->GetParent()->RemoveChild(m_widget);
  51. if (the_widget.Get())
  52. delete the_widget.Get();
  53. }
  54. else
  55. m_widget->SetOpacity(m_dst_opacity);
  56. }
  57. // == TBWidgetAnimationRect ===============================================================
  58. TBWidgetAnimationRect::TBWidgetAnimationRect(TBWidget *widget, const TBRect &src_rect, const TBRect &dst_rect)
  59. : TBWidgetAnimationObject(widget)
  60. , m_src_rect(src_rect)
  61. , m_dst_rect(dst_rect)
  62. , m_mode(MODE_SRC_TO_DST)
  63. {
  64. }
  65. TBWidgetAnimationRect::TBWidgetAnimationRect(TBWidget *widget, const TBRect &delta_rect, MODE mode)
  66. : TBWidgetAnimationObject(widget)
  67. , m_delta_rect(delta_rect)
  68. , m_mode(mode)
  69. {
  70. assert(mode == MODE_DELTA_IN || mode == MODE_DELTA_OUT);
  71. }
  72. void TBWidgetAnimationRect::OnAnimationStart()
  73. {
  74. // Make sure we don't stay idle if nothing is scheduled (hack).
  75. // FIX: fix this properly
  76. m_widget->Invalidate();
  77. if (m_mode == MODE_SRC_TO_DST)
  78. m_widget->SetRect(m_src_rect);
  79. }
  80. void TBWidgetAnimationRect::OnAnimationUpdate(float progress)
  81. {
  82. if (m_mode == MODE_DELTA_IN || m_mode == MODE_DELTA_OUT)
  83. {
  84. m_dst_rect = m_src_rect = m_widget->GetRect();
  85. if (m_dst_rect.Equals(TBRect()))
  86. {
  87. // Widget hasn't been laid out yet,
  88. // the animation was started too soon.
  89. TBAnimationManager::AbortAnimation(this, true);
  90. return;
  91. }
  92. if (m_mode == MODE_DELTA_IN)
  93. {
  94. m_dst_rect.x += m_delta_rect.x;
  95. m_dst_rect.y += m_delta_rect.y;
  96. m_dst_rect.w += m_delta_rect.w;
  97. m_dst_rect.h += m_delta_rect.h;
  98. }
  99. else
  100. {
  101. m_src_rect.x += m_delta_rect.x;
  102. m_src_rect.y += m_delta_rect.y;
  103. m_src_rect.w += m_delta_rect.w;
  104. m_src_rect.h += m_delta_rect.h;
  105. }
  106. m_mode = MODE_SRC_TO_DST;
  107. }
  108. TBRect rect;
  109. rect.x = (int) LERP(m_src_rect.x, m_dst_rect.x, progress);
  110. rect.y = (int) LERP(m_src_rect.y, m_dst_rect.y, progress);
  111. rect.w = (int) LERP(m_src_rect.w, m_dst_rect.w, progress);
  112. rect.h = (int) LERP(m_src_rect.h, m_dst_rect.h, progress);
  113. m_widget->SetRect(rect);
  114. }
  115. void TBWidgetAnimationRect::OnAnimationStop(bool aborted)
  116. {
  117. if (m_mode == MODE_SRC_TO_DST) // m_dst_rect may still be unset if aborted.
  118. m_widget->SetRect(m_dst_rect);
  119. }
  120. // == TBWidgetsAnimationManager =====================================================
  121. TBWidgetsAnimationManager widgets_animation_manager;
  122. void TBWidgetsAnimationManager::Init()
  123. {
  124. TBWidgetListener::AddGlobalListener(&widgets_animation_manager);
  125. }
  126. void TBWidgetsAnimationManager::Shutdown()
  127. {
  128. TBWidgetListener::RemoveGlobalListener(&widgets_animation_manager);
  129. }
  130. void TBWidgetsAnimationManager::AbortAnimations(TBWidget *widget)
  131. {
  132. AbortAnimations(widget, nullptr);
  133. }
  134. void TBWidgetsAnimationManager::AbortAnimations(TBWidget *widget, TB_TYPE_ID type_id)
  135. {
  136. TBLinkListOf<TBWidgetAnimationObject>::Iterator iter = widget_animations.IterateForward();
  137. while (TBWidgetAnimationObject *wao = iter.GetAndStep())
  138. {
  139. if (wao->m_widget == widget)
  140. {
  141. // Skip this animation if we asked for a specific (and
  142. // different) animation type.
  143. if (type_id != nullptr && !wao->IsOfTypeId(type_id))
  144. continue;
  145. // Abort the animation. This will both autoremove itself
  146. // and delete it, so no need to do it here.
  147. TBAnimationManager::AbortAnimation(wao, true);
  148. }
  149. }
  150. }
  151. void TBWidgetsAnimationManager::OnWidgetDelete(TBWidget *widget)
  152. {
  153. // Kill and delete all animations running for the widget being deleted.
  154. AbortAnimations(widget);
  155. }
  156. bool TBWidgetsAnimationManager::OnWidgetDying(TBWidget *widget)
  157. {
  158. bool handled = false;
  159. if (TBWindow *window = TBSafeCast<TBWindow>(widget))
  160. {
  161. // Fade out dying windows
  162. if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(window, 1.f, TB_ALMOST_ZERO_OPACITY, true))
  163. TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER);
  164. handled = true;
  165. }
  166. if (TBMessageWindow *window = TBSafeCast<TBMessageWindow>(widget))
  167. {
  168. // Move out dying message windows
  169. if (TBAnimationObject *anim = new TBWidgetAnimationRect(window, TBRect(0, 50, 0, 0), TBWidgetAnimationRect::MODE_DELTA_IN))
  170. TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_SPEED_UP);
  171. handled = true;
  172. }
  173. if (TBDimmer *dimmer = TBSafeCast<TBDimmer>(widget))
  174. {
  175. // Fade out dying dim layers
  176. if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(dimmer, 1.f, TB_ALMOST_ZERO_OPACITY, true))
  177. TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER);
  178. handled = true;
  179. }
  180. return handled;
  181. }
  182. void TBWidgetsAnimationManager::OnWidgetAdded(TBWidget *parent, TBWidget *widget)
  183. {
  184. if (TBWindow *window = TBSafeCast<TBWindow>(widget))
  185. {
  186. // Fade in new windows
  187. if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(window, TB_ALMOST_ZERO_OPACITY, 1.f, false))
  188. TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER);
  189. }
  190. if (TBMessageWindow *window = TBSafeCast<TBMessageWindow>(widget))
  191. {
  192. // Move in new message windows
  193. if (TBAnimationObject *anim = new TBWidgetAnimationRect(window, TBRect(0, -50, 0, 0), TBWidgetAnimationRect::MODE_DELTA_OUT))
  194. TBAnimationManager::StartAnimation(anim);
  195. }
  196. if (TBDimmer *dimmer = TBSafeCast<TBDimmer>(widget))
  197. {
  198. // Fade in dim layer
  199. if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(dimmer, TB_ALMOST_ZERO_OPACITY, 1.f, false))
  200. TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER);
  201. }
  202. }
  203. void TBWidgetsAnimationManager::OnWidgetRemove(TBWidget *parent, TBWidget *widget)
  204. {
  205. }
  206. }; // namespace tb