aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2018-09-19 01:15:01 +0800
committercrupest <crupest@outlook.com>2018-09-19 01:15:01 +0800
commit85bb4d466efeb2540363065d7c0987a9d60f70e9 (patch)
treeea5e5aa738afb37a2d3bc4e74f9be64c15f3d188
parent4710715102df3806479985679bd8048631ccaab5 (diff)
downloadcru-85bb4d466efeb2540363065d7c0987a9d60f70e9.tar.gz
cru-85bb4d466efeb2540363065d7c0987a9d60f70e9.tar.bz2
cru-85bb4d466efeb2540363065d7c0987a9d60f70e9.zip
finish animation!!!
-rw-r--r--CruUI/CruUI.vcxproj1
-rw-r--r--CruUI/CruUI.vcxproj.filters3
-rw-r--r--CruUI/application.cpp6
-rw-r--r--CruUI/application.h8
-rw-r--r--CruUI/base.h71
-rw-r--r--CruUI/builder.h42
-rw-r--r--CruUI/cru_event.h2
-rw-r--r--CruUI/debug_base.h10
-rw-r--r--CruUI/exception.cpp43
-rw-r--r--CruUI/exception.h78
-rw-r--r--CruUI/graph/graph.h2
-rw-r--r--CruUI/timer.cpp23
-rw-r--r--CruUI/timer.h18
-rw-r--r--CruUI/ui/animations/animation.cpp227
-rw-r--r--CruUI/ui/animations/animation.h176
-rw-r--r--CruUI/ui/control.cpp8
-rw-r--r--CruUI/ui/control.h6
-rw-r--r--CruUI/ui/controls/text_block.cpp15
-rw-r--r--CruUI/ui/controls/text_block.h17
-rw-r--r--CruUI/ui/controls/toggle_button.cpp13
-rw-r--r--CruUI/ui/window.h1
21 files changed, 419 insertions, 351 deletions
diff --git a/CruUI/CruUI.vcxproj b/CruUI/CruUI.vcxproj
index adc035f1..df67a297 100644
--- a/CruUI/CruUI.vcxproj
+++ b/CruUI/CruUI.vcxproj
@@ -162,7 +162,6 @@
<ClInclude Include="system_headers.h" />
<ClInclude Include="timer.h" />
<ClInclude Include="ui\animations\animation.h" />
- <ClInclude Include="builder.h" />
<ClInclude Include="ui\control.h" />
<ClInclude Include="global_macros.h" />
<ClInclude Include="ui\controls\linear_layout.h" />
diff --git a/CruUI/CruUI.vcxproj.filters b/CruUI/CruUI.vcxproj.filters
index af6853a9..a7ea8f69 100644
--- a/CruUI/CruUI.vcxproj.filters
+++ b/CruUI/CruUI.vcxproj.filters
@@ -69,9 +69,6 @@
<ClInclude Include="ui\animations\animation.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="builder.h">
- <Filter>Header Files</Filter>
- </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="application.cpp">
diff --git a/CruUI/application.cpp b/CruUI/application.cpp
index f1d57153..78b44d7e 100644
--- a/CruUI/application.cpp
+++ b/CruUI/application.cpp
@@ -2,6 +2,7 @@
#include <fmt/format.h>
+#include "exception.h"
#include "timer.h"
#include "ui/window.h"
#include "graph/graph.h"
@@ -96,13 +97,14 @@ namespace cru {
window_manager_ = std::make_unique<ui::WindowManager>();
graph_manager_ = std::make_unique<graph::GraphManager>();
timer_manager_ = std::make_unique<TimerManager>();
- animation_manager_ = std::make_unique<ui::animations::AnimationManager>();
+ animation_manager_ = std::make_unique<ui::animations::details::AnimationManager>();
god_window_ = std::make_unique<GodWindow>(this);
}
Application::~Application()
{
+ animation_manager_.reset();
instance_ = nullptr;
}
@@ -128,6 +130,6 @@ namespace cru {
auto p_action_copy = new InvokeLaterAction(std::move(action));
if (PostMessageW(Application::GetInstance()->GetGodWindow()->GetHandle(), invoke_later_message_id, reinterpret_cast<WPARAM>(p_action_copy), 0) == 0)
- throw std::runtime_error(fmt::format("Last error: {}.", ::GetLastError()));
+ throw Win32Error(::GetLastError(), "InvokeLater failed to post message.");
}
}
diff --git a/CruUI/application.h b/CruUI/application.h
index a0229bfa..fe7422d3 100644
--- a/CruUI/application.h
+++ b/CruUI/application.h
@@ -15,7 +15,7 @@ namespace cru
class WindowClass;
class WindowManager;
- namespace animations
+ namespace animations::details
{
class AnimationManager;
}
@@ -86,7 +86,7 @@ namespace cru
return timer_manager_.get();
}
- ui::animations::AnimationManager* GetAnimationManager() const
+ ui::animations::details::AnimationManager* GetAnimationManager() const
{
return animation_manager_.get();
}
@@ -107,12 +107,12 @@ namespace cru
std::unique_ptr<ui::WindowManager> window_manager_;
std::unique_ptr<graph::GraphManager> graph_manager_;
std::unique_ptr<TimerManager> timer_manager_;
- std::unique_ptr<ui::animations::AnimationManager> animation_manager_;
+ std::unique_ptr<ui::animations::details::AnimationManager> animation_manager_;
std::unique_ptr<GodWindow> god_window_;
};
- using InvokeLaterAction = Action<>;
+ using InvokeLaterAction = Function<void()>;
void InvokeLater(InvokeLaterAction&& action);
}
diff --git a/CruUI/base.h b/CruUI/base.h
index 99b493b1..542546fb 100644
--- a/CruUI/base.h
+++ b/CruUI/base.h
@@ -14,11 +14,19 @@
#include <folly/Function.h>
+#include <utility>
+#include <type_traits>
#include <stdexcept>
-
+#include <memory>
+#include <string_view>
+#include <chrono>
namespace cru
{
+ template<typename T> struct is_shared_ptr : std::false_type {};
+ template<typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
+ template<typename T> constexpr bool is_shared_ptr_v = is_shared_ptr<T>::value;
+
enum class FlowControl
{
Continue,
@@ -28,17 +36,31 @@ namespace cru
#ifdef CRU_DEBUG
using String = std::wstring;
#else
- using String = folly::basic_fbstring<wchar_t>;
+ using String = folly::basic_fbstring<wchar_t>;
#endif
+ using StringView = std::wstring_view;
+
template<typename FunctionType>
using Function = folly::Function<FunctionType>;
- template<typename... Args>
- using Action = Function<void(Args...)>;
+ template<typename FunctionType>
+ using FunctionPtr = std::shared_ptr<Function<FunctionType>>;
+
+ using Action = Function<void()>;
+ using ActionPtr = FunctionPtr<void()>;
- template<typename... Args>
- using FlowControlAction = Function<FlowControl(Args...)>;
+ template<typename Type, typename... Args>
+ Type CreatePtr(Args&&... args)
+ {
+ static_assert(is_shared_ptr_v<Type>);
+ return std::make_shared<typename Type::element_type>(std::forward<Args>(args)...);
+ }
+
+ inline ActionPtr CreateActionPtr(Action&& action)
+ {
+ return std::make_shared<Action>(std::move(action));
+ }
#ifdef CRU_DEBUG
template<typename T>
@@ -48,24 +70,33 @@ namespace cru
using Vector = folly::fbvector<T>;
#endif
+ using FloatSecond = std::chrono::duration<double, std::chrono::seconds::period>;
+
class Object
- {
- public:
- Object() = default;
- Object(const Object&) = default;
- Object& operator = (const Object&) = default;
- Object(Object&&) = default;
- Object& operator = (Object&&) = default;
- virtual ~Object() = default;
- };
-
- struct Interface
- {
- virtual ~Interface() = default;
- };
+ {
+ public:
+ Object() = default;
+ Object(const Object&) = default;
+ Object& operator = (const Object&) = default;
+ Object(Object&&) = default;
+ Object& operator = (Object&&) = default;
+ virtual ~Object() = default;
+ };
+
+ struct Interface
+ {
+ virtual ~Interface() = default;
+ };
[[noreturn]] inline void UnreachableCode()
{
throw std::logic_error("Unreachable code.");
}
+
+ struct ICancelable : virtual Interface
+ {
+ virtual void Cancel() = 0;
+ };
+
+ using CancelablePtr = std::shared_ptr<ICancelable>;
}
diff --git a/CruUI/builder.h b/CruUI/builder.h
deleted file mode 100644
index 3ae8724e..00000000
--- a/CruUI/builder.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-
-#include "base.h"
-
-namespace cru
-{
- template<typename T>
- class OneTimeBuilder : public Object
- {
- protected:
- OneTimeBuilder() = default;
-
- public:
- OneTimeBuilder(const OneTimeBuilder& other) = delete;
- OneTimeBuilder(OneTimeBuilder&& other) = delete;
- OneTimeBuilder& operator=(const OneTimeBuilder& other) = delete;
- OneTimeBuilder& operator=(OneTimeBuilder&& other) = delete;
- virtual ~OneTimeBuilder() = default;
-
- T* Create()
- {
- if (is_valid_)
- {
- is_valid_ = false;
- return OnCreate();
- }
- else
- throw std::runtime_error("OneTimeBuilder is invalid.");
- }
-
- bool IsValid() const
- {
- return is_valid_;
- }
-
- protected:
- virtual T* OnCreate() = 0;
-
- private:
- bool is_valid_ = true;
- };
-}
diff --git a/CruUI/cru_event.h b/CruUI/cru_event.h
index f5e548c0..3a2dccfa 100644
--- a/CruUI/cru_event.h
+++ b/CruUI/cru_event.h
@@ -46,7 +46,7 @@ namespace cru {
using ArgsType = TArgsType;
- using EventHandler = Action<ArgsType&>;
+ using EventHandler = Function<void(ArgsType&)>;
using EventHandlerPtr = std::shared_ptr<EventHandler>;
Event() = default;
diff --git a/CruUI/debug_base.h b/CruUI/debug_base.h
index f78decbd..7669b9df 100644
--- a/CruUI/debug_base.h
+++ b/CruUI/debug_base.h
@@ -2,8 +2,8 @@
#include "system_headers.h"
-#include <type_traits>
#include <chrono>
+#include <string_view>
#include <fmt/format.h>
#include "base.h"
@@ -11,7 +11,7 @@
namespace cru::debug
{
#ifdef CRU_DEBUG
- inline void DebugTime(Function<void()>&& action, const wchar_t* const hint_message)
+ inline void DebugTime(Function<void()>&& action, const StringView& hint_message)
{
const auto before = std::chrono::steady_clock::now();
action();
@@ -21,7 +21,7 @@ namespace cru::debug
}
template<typename TReturn>
- TReturn DebugTime(Function<TReturn()>&& action, const wchar_t* const hint_message)
+ TReturn DebugTime(Function<TReturn()>&& action, const StringView& hint_message)
{
const auto before = std::chrono::steady_clock::now();
auto&& result = action();
@@ -31,13 +31,13 @@ namespace cru::debug
return std::move(result);
}
#else
- inline void DebugTime(Function<void()>&& action, const wchar_t* const hint_message)
+ inline void DebugTime(Function<void()>&& action, const StringView& hint_message)
{
action();
}
template<typename TReturn>
- TReturn DebugTime(Function<TReturn()>&& action, const wchar_t* const hint_message)
+ TReturn DebugTime(Function<TReturn()>&& action, const StringView& hint_message)
{
return action();
}
diff --git a/CruUI/exception.cpp b/CruUI/exception.cpp
index 45af254d..38075247 100644
--- a/CruUI/exception.cpp
+++ b/CruUI/exception.cpp
@@ -1,29 +1,34 @@
#include "exception.h"
-#include <sstream>
-#include <iomanip>
+#include <fmt/format.h>
namespace cru
{
- HResultError::HResultError(const HRESULT h_result)
- : runtime_error(MakeMessage(h_result, std::nullopt)), h_result_(h_result)
- {
+ inline std::string HResultMakeMessage(HRESULT h_result, std::optional<std::string> message)
+ {
+ if (message.has_value())
+ return fmt::format("An HResultError is thrown. HRESULT: {:#08x}.\n", h_result);
+ else
+ return fmt::format("An HResultError is thrown. HRESULT: {:#08x}.\nAdditional message: {}\n", h_result, message.value());
+ }
- }
+ HResultError::HResultError(HRESULT h_result, std::optional<std::string_view> additional_message)
+ : runtime_error(HResultMakeMessage(h_result, std::nullopt)), h_result_(h_result)
+ {
- HResultError::HResultError(const HRESULT h_result, const std::string& message)
- : runtime_error(MakeMessage(h_result, std::make_optional(message))), h_result_(h_result)
- {
+ }
- }
+ inline std::string Win32MakeMessage(DWORD error_code, std::optional<std::string> message)
+ {
+ if (message.has_value())
+ return fmt::format("Last error code: {:#04x}.\n", error_code);
+ else
+ return fmt::format("Last error code: {:#04x}.\nAdditional message: {}\n", error_code, message.value());
+ }
- std::string HResultError::MakeMessage(HRESULT h_result, std::optional<std::string> message)
- {
- std::stringstream ss;
- ss << "An HResultError is thrown. HRESULT: 0x" << std::setfill('0')
- << std::setw(sizeof h_result * 2) << std::hex << h_result << ".";
- if (message.has_value())
- ss << "Additional message: " << message.value();
- return ss.str();
- }
+ Win32Error::Win32Error(DWORD error_code, std::optional<std::string_view> additional_message)
+ : runtime_error(Win32MakeMessage(error_code, std::nullopt)), error_code_(error_code)
+ {
+
+ }
}
diff --git a/CruUI/exception.h b/CruUI/exception.h
index c7d6f996..2817f261 100644
--- a/CruUI/exception.h
+++ b/CruUI/exception.h
@@ -2,41 +2,57 @@
#include "system_headers.h"
#include <optional>
+#include <string_view>
#include "base.h"
namespace cru {
- class HResultError : public std::runtime_error
- {
- public:
- explicit HResultError(HRESULT h_result);
- HResultError(HRESULT h_result, const std::string& message);
- HResultError(const HResultError& other) = default;
- HResultError(HResultError&& other) = default;
- HResultError& operator=(const HResultError& other) = default;
- HResultError& operator=(HResultError&& other) = default;
- ~HResultError() override = default;
-
- HRESULT GetHResult() const
- {
+ class HResultError : public std::runtime_error
+ {
+ public:
+ explicit HResultError(HRESULT h_result, std::optional<std::string_view> additional_message = std::nullopt);
+ HResultError(const HResultError& other) = default;
+ HResultError(HResultError&& other) = default;
+ HResultError& operator=(const HResultError& other) = default;
+ HResultError& operator=(HResultError&& other) = default;
+ ~HResultError() override = default;
+
+ HRESULT GetHResult() const
+ {
return h_result_;
- }
-
- private:
- static std::string MakeMessage(HRESULT h_result, std::optional<std::string> message);
-
- private:
- HRESULT h_result_;
- };
-
- inline void ThrowIfFailed(const HRESULT h_result) {
- if (FAILED(h_result))
- throw HResultError(h_result);
- }
-
- inline void ThrowIfFailed(const HRESULT h_result, const std::string& message) {
- if (FAILED(h_result))
- throw HResultError(h_result, message);
- }
+ }
+
+ private:
+ HRESULT h_result_;
+ };
+
+ inline void ThrowIfFailed(const HRESULT h_result) {
+ if (FAILED(h_result))
+ throw HResultError(h_result);
+ }
+
+ inline void ThrowIfFailed(const HRESULT h_result, const std::string& message) {
+ if (FAILED(h_result))
+ throw HResultError(h_result, message);
+ }
+
+ class Win32Error : public std::runtime_error
+ {
+ public:
+ explicit Win32Error(DWORD error_code, std::optional<std::string_view> additional_message = std::nullopt);
+ Win32Error(const Win32Error& other) = default;
+ Win32Error(Win32Error&& other) = default;
+ Win32Error& operator=(const Win32Error& other) = default;
+ Win32Error& operator=(Win32Error&& other) = default;
+ ~Win32Error() override = default;
+
+ HRESULT GetErrorCode() const
+ {
+ return error_code_;
+ }
+
+ private:
+ DWORD error_code_;
+ };
}
diff --git a/CruUI/graph/graph.h b/CruUI/graph/graph.h
index fd062787..01d95797 100644
--- a/CruUI/graph/graph.h
+++ b/CruUI/graph/graph.h
@@ -167,7 +167,7 @@ namespace cru
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> CreateSolidBrush(const D2D1_COLOR_F& color);
- inline void WithTransform(ID2D1DeviceContext* device_context, const D2D1_MATRIX_3X2_F matrix, Action<ID2D1DeviceContext*>&& action)
+ inline void WithTransform(ID2D1DeviceContext* device_context, const D2D1_MATRIX_3X2_F matrix, Function<void(ID2D1DeviceContext*)>&& action)
{
D2D1_MATRIX_3X2_F old_transform;
device_context->GetTransform(&old_transform);
diff --git a/CruUI/timer.cpp b/CruUI/timer.cpp
index 7435adde..f596dde4 100644
--- a/CruUI/timer.cpp
+++ b/CruUI/timer.cpp
@@ -2,14 +2,14 @@
namespace cru
{
- UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop, std::shared_ptr<Action<>> action)
+ UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop, ActionPtr action)
{
const auto id = current_count_++;
- ::SetTimer(Application::GetInstance()->GetGodWindow()->GetHandle(), 0, milliseconds, nullptr);
+ ::SetTimer(Application::GetInstance()->GetGodWindow()->GetHandle(), id, milliseconds, nullptr);
if (loop)
map_[id] = std::move(action);
else
- map_[id] = std::make_shared<Action<>>([this, action, id]() mutable {
+ map_[id] = CreateActionPtr([this, action, id]() mutable {
(*action)();
this->KillTimer(id);
});
@@ -26,7 +26,7 @@ namespace cru
}
}
- std::shared_ptr<Action<>> TimerManager::GetAction(const UINT_PTR id)
+ ActionPtr TimerManager::GetAction(const UINT_PTR id)
{
const auto find_result = map_.find(id);
if (find_result == map_.cend())
@@ -34,7 +34,7 @@ namespace cru
return find_result->second;
}
- class TimerTaskImpl : public ITimerTask
+ class TimerTaskImpl : public virtual ICancelable
{
public:
explicit TimerTaskImpl(UINT_PTR id);
@@ -61,20 +61,15 @@ namespace cru
TimerManager::GetInstance()->KillTimer(id_);
}
- inline UINT SecondToMillisecond(const double seconds)
+ TimerTask SetTimeout(std::chrono::milliseconds milliseconds, ActionPtr action)
{
- return static_cast<UINT>(seconds * 1000);
- }
-
- std::shared_ptr<ITimerTask> SetTimeout(double seconds, std::shared_ptr<Action<>> action)
- {
- auto id = TimerManager::GetInstance()->CreateTimer(SecondToMillisecond(seconds), false, std::move(action));
+ auto id = TimerManager::GetInstance()->CreateTimer(static_cast<UINT>(milliseconds.count()), false, std::move(action));
return std::make_shared<TimerTaskImpl>(id);
}
- std::shared_ptr<ITimerTask> SetInterval(double seconds, std::shared_ptr<Action<>> action)
+ TimerTask SetInterval(std::chrono::milliseconds milliseconds, ActionPtr action)
{
- auto id = TimerManager::GetInstance()->CreateTimer(SecondToMillisecond(seconds), true, std::move(action));
+ auto id = TimerManager::GetInstance()->CreateTimer(static_cast<UINT>(milliseconds.count()), true, std::move(action));
return std::make_shared<TimerTaskImpl>(id);
}
}
diff --git a/CruUI/timer.h b/CruUI/timer.h
index 70913775..9884e46a 100644
--- a/CruUI/timer.h
+++ b/CruUI/timer.h
@@ -2,10 +2,9 @@
#include "system_headers.h"
-#include <functional>
#include <memory>
#include <map>
-#include <optional>
+#include <chrono>
#include "base.h"
#include "application.h"
@@ -28,20 +27,17 @@ namespace cru
TimerManager& operator=(TimerManager&& other) = delete;
~TimerManager() override = default;
- UINT_PTR CreateTimer(UINT milliseconds, bool loop, std::shared_ptr<Action<>> action);
+ UINT_PTR CreateTimer(UINT milliseconds, bool loop, ActionPtr action);
void KillTimer(UINT_PTR id);
- std::shared_ptr<Action<>> GetAction(UINT_PTR id);
+ ActionPtr GetAction(UINT_PTR id);
private:
- std::map<UINT_PTR, std::shared_ptr<Action<>>> map_{};
+ std::map<UINT_PTR, ActionPtr> map_{};
UINT_PTR current_count_ = 0;
};
- struct ITimerTask : virtual Interface
- {
- virtual void Cancel() = 0;
- };
+ using TimerTask = CancelablePtr;
- std::shared_ptr<ITimerTask> SetTimeout(double seconds, std::shared_ptr<Action<>> action);
- std::shared_ptr<ITimerTask> SetInterval(double seconds, std::shared_ptr<Action<>> action);
+ TimerTask SetTimeout(std::chrono::milliseconds milliseconds, ActionPtr action);
+ TimerTask SetInterval(std::chrono::milliseconds milliseconds, ActionPtr action);
}
diff --git a/CruUI/ui/animations/animation.cpp b/CruUI/ui/animations/animation.cpp
index 26b7d5fc..9d05860a 100644
--- a/CruUI/ui/animations/animation.cpp
+++ b/CruUI/ui/animations/animation.cpp
@@ -5,99 +5,186 @@
namespace cru::ui::animations
{
- constexpr int frame_rate = 60;
- constexpr double frame_step_time = 1.0 / frame_rate;
-
- AnimationManager::AnimationManager()
- : timer_action_(new Action<>([this]()
+ namespace details
{
- for (auto& animation : animations_)
+ class AnimationDelegateImpl;
+ constexpr double frame_rate = 60;
+ constexpr AnimationTimeUnit frame_step_time = AnimationTimeUnit(1) / frame_rate;
+
+
+ class AnimationDelegateImpl : public virtual IAnimationDelegate
{
- if (animation.second->Step(frame_step_time))
- InvokeLater([=]
+ public:
+ explicit AnimationDelegateImpl(String tag)
+ : tag_(std::move(tag))
+ {
+
+ }
+ AnimationDelegateImpl(const AnimationDelegateImpl& other) = delete;
+ AnimationDelegateImpl(AnimationDelegateImpl&& other) = delete;
+ AnimationDelegateImpl& operator=(const AnimationDelegateImpl& other) = delete;
+ AnimationDelegateImpl& operator=(AnimationDelegateImpl&& other) = delete;
+ ~AnimationDelegateImpl() override = default;
+
+ void Cancel() override
+ {
+ AnimationManager::GetInstance()->RemoveAnimation(tag_);
+ }
+
+ private:
+ String tag_;
+ };
+
+
+ class Animation : public Object
+ {
+ public:
+ Animation(
+ String tag,
+ AnimationTimeUnit duration,
+ Vector<AnimationStepHandlerPtr> step_handlers,
+ Vector<AnimationStartHandlerPtr> start_handlers,
+ Vector<ActionPtr> finish_handlers,
+ Vector<ActionPtr> cancel_handlers,
+ AnimationDelegatePtr delegate
+ );
+ Animation(const Animation& other) = delete;
+ Animation(Animation&& other) = delete;
+ Animation& operator=(const Animation& other) = delete;
+ Animation& operator=(Animation&& other) = delete;
+ ~Animation() override;
+
+
+ // If finish or invalid, return false.
+ bool Step(AnimationTimeUnit time);
+
+ String GetTag() const
{
- RemoveAnimation(animation.second); //TODO!!!
- });
+ return tag_;
+ }
+
+ private:
+ const String tag_;
+ const AnimationTimeUnit duration_;
+ Vector<AnimationStepHandlerPtr> step_handlers_;
+ Vector<AnimationStartHandlerPtr> start_handlers_;
+ Vector<ActionPtr> finish_handlers_;
+ Vector<ActionPtr> cancel_handlers_;
+ AnimationDelegatePtr delegate_;
+
+ AnimationTimeUnit current_time_ = AnimationTimeUnit::zero();
+ };
+
+ AnimationManager::AnimationManager()
+ : timer_action_(CreateActionPtr([this]()
+ {
+ auto i = animations_.cbegin();
+ while (i != animations_.cend())
+ {
+ auto current_i = i++;
+ if (current_i->second->Step(frame_step_time))
+ animations_.erase(current_i);
+ }
+
+ if (animations_.empty())
+ KillTimer();
+ }))
+ {
+
}
- }))
- {
- }
+ AnimationManager::~AnimationManager()
+ {
+ KillTimer();
+ }
- AnimationManager::~AnimationManager()
- {
- for (auto& animation : animations_)
- delete animation.second;
+ AnimationDelegatePtr AnimationManager::CreateAnimation(String tag, AnimationTimeUnit duration,
+ Vector<AnimationStepHandlerPtr> step_handlers, Vector<AnimationStartHandlerPtr> start_handlers,
+ Vector<ActionPtr> finish_handlers, Vector<ActionPtr> cancel_handlers)
+ {
+ if (animations_.empty())
+ SetTimer();
- if (timer_)
- timer_->Cancel();
- }
+ auto delegate = std::make_shared<AnimationDelegateImpl>(tag);
- void AnimationManager::AddAnimation(Animation* animation)
- {
- if (animations_.empty())
- timer_ = SetInterval(frame_step_time, timer_action_);
+ animations_[tag] = std::make_unique<Animation>(tag, duration, std::move(step_handlers), std::move(start_handlers), std::move(finish_handlers), std::move(cancel_handlers), delegate);
- const auto find_result = animations_.find(animation->GetTag());
- if (find_result != animations_.cend())
- find_result->second->Cancel();
- animations_.insert_or_assign(animation->GetTag(), animation);
- }
+ return delegate;
+ }
- void AnimationManager::RemoveAnimation(Animation* animation)
- {
- const auto find_result = animations_.find(animation->GetTag());
- if (find_result != animations_.cend())
+ void AnimationManager::RemoveAnimation(const String& tag)
{
- delete find_result->second;
- animations_.erase(find_result);
+ const auto find_result = animations_.find(tag);
+ if (find_result != animations_.cend())
+ animations_.erase(find_result);
+
+ if (animations_.empty())
+ KillTimer();
}
- if (animations_.empty())
+ void AnimationManager::SetTimer()
{
- assert(timer_);
- timer_->Cancel();
- timer_ = nullptr;
+ if (timer_ == nullptr)
+ timer_ = SetInterval(std::chrono::duration_cast<std::chrono::milliseconds>(frame_step_time), timer_action_);
}
- }
- Animation::Animation(String tag, const double duration,
- const Vector<std::shared_ptr<Action<Animation*, double>>>& step_handlers,
- const Vector<std::shared_ptr<Action<Animation*>>>& start_handlers,
- const Vector<std::shared_ptr<Action<Animation*>>>& finish_handlers,
- const Vector<std::shared_ptr<Action<Animation*>>>& cancel_handlers
- ) : tag_(std::move(tag)), duration_(duration), step_handlers_(step_handlers),
- start_handlers_(start_handlers), finish_handlers_(finish_handlers), cancel_handlers_(cancel_handlers)
- {
- AnimationManager::GetInstance()->AddAnimation(this);
- }
+ void AnimationManager::KillTimer()
+ {
+ if (timer_ != nullptr)
+ {
+ timer_->Cancel();
+ timer_ = nullptr;
+ }
+ }
- bool Animation::Step(const double time)
- {
- current_time_ += time;
- if (current_time_ > duration_)
+ Animation::Animation(
+ String tag,
+ AnimationTimeUnit duration,
+ Vector<AnimationStepHandlerPtr> step_handlers,
+ Vector<AnimationStartHandlerPtr> start_handlers,
+ Vector<ActionPtr> finish_handlers,
+ Vector<ActionPtr> cancel_handlers,
+ AnimationDelegatePtr delegate
+ ) : tag_(std::move(tag)), duration_(duration),
+ step_handlers_(std::move(step_handlers)),
+ start_handlers_(std::move(start_handlers)),
+ finish_handlers_(std::move(finish_handlers)),
+ cancel_handlers_(std::move(cancel_handlers)),
+ delegate_(std::move(delegate))
+ {
+
+ }
+
+ Animation::~Animation()
{
- for (auto& handler : step_handlers_)
- (*handler)(this, 1);
- for (auto& handler : finish_handlers_)
- (*handler)(this);
- return true;
+ if (current_time_ < duration_)
+ for (auto& handler : cancel_handlers_)
+ (*handler)();
}
- else
+
+ bool Animation::Step(const AnimationTimeUnit time)
{
- for (auto& handler : step_handlers_)
- (*handler)(this, current_time_ / duration_);
- return false;
+ current_time_ += time;
+ if (current_time_ > duration_)
+ {
+ for (auto& handler : step_handlers_)
+ (*handler)(delegate_, 1);
+ for (auto& handler : finish_handlers_)
+ (*handler)();
+ return true;
+ }
+ else
+ {
+ for (auto& handler : step_handlers_)
+ (*handler)(delegate_, current_time_ / duration_);
+ return false;
+ }
}
+
}
- void Animation::Cancel()
+ AnimationDelegatePtr AnimationBuilder::Start() const
{
- for (auto& handler : cancel_handlers_)
- (*handler)(this);
- InvokeLater([this]
- {
- AnimationManager::GetInstance()->RemoveAnimation(this); //TODO!!!
- });
+ return details::AnimationManager::GetInstance()->CreateAnimation(tag, duration, step_handlers_, start_handlers_, finish_handlers_, cancel_handlers_);
}
}
diff --git a/CruUI/ui/animations/animation.h b/CruUI/ui/animations/animation.h
index fb6ba93e..69b08b0c 100644
--- a/CruUI/ui/animations/animation.h
+++ b/CruUI/ui/animations/animation.h
@@ -1,131 +1,107 @@
#pragma once
-#include <map>
+#include <unordered_map>
#include "base.h"
#include "application.h"
#include "timer.h"
-#include "builder.h"
namespace cru::ui::animations
{
- class Animation;
+ using AnimationTimeUnit = FloatSecond;
+
+ using IAnimationDelegate = ICancelable;
+ using AnimationDelegatePtr = CancelablePtr;
- class AnimationManager : public Object
- {
- public:
- static AnimationManager* GetInstance()
- {
- return Application::GetInstance()->GetAnimationManager();
- }
-
- public:
- AnimationManager();
- AnimationManager(const AnimationManager& other) = delete;
- AnimationManager(AnimationManager&& other) = delete;
- AnimationManager& operator=(const AnimationManager& other) = delete;
- AnimationManager& operator=(AnimationManager&& other) = delete;
- ~AnimationManager() override;
+ using AnimationStepHandlerPtr = FunctionPtr<void(AnimationDelegatePtr, double)>;
+ using AnimationStartHandlerPtr = FunctionPtr<void(AnimationDelegatePtr)>;
- void AddAnimation(Animation* animation);
- void RemoveAnimation(Animation* animation);
- private:
- std::map<String, Animation*> animations_;
- std::shared_ptr<ITimerTask> timer_;
- std::shared_ptr<Action<>> timer_action_;
- };
-
- class Animation : public Object
+ namespace details
{
- friend class AnimationManager;
- protected:
- Animation(
- String tag,
- double duration,
- const Vector<std::shared_ptr<Action<Animation*, double>>>& step_handlers,
- const Vector<std::shared_ptr<Action<Animation*>>>& start_handlers,
- const Vector<std::shared_ptr<Action<Animation*>>>& finish_handlers,
- const Vector<std::shared_ptr<Action<Animation*>>>& cancel_handlers
- );
+ class Animation;
+ using AnimationPtr = std::unique_ptr<Animation>;
- public:
- Animation(const Animation& other) = delete;
- Animation(Animation&& other) = delete;
- Animation& operator=(const Animation& other) = delete;
- Animation& operator=(Animation&& other) = delete;
- ~Animation() override = default; // The animation will never destroy by users.
-
- bool Step(double time);
- void Cancel();
- String GetTag() const
+ class AnimationManager : public Object
{
- return tag_;
- }
+ public:
+ static AnimationManager* GetInstance()
+ {
+ return Application::GetInstance()->GetAnimationManager();
+ }
- private:
- const String tag_;
- const double duration_;
- Vector<std::shared_ptr<Action<Animation*, double>>> step_handlers_;
- Vector<std::shared_ptr<Action<Animation*>>> start_handlers_;
- Vector<std::shared_ptr<Action<Animation*>>> finish_handlers_;
- Vector<std::shared_ptr<Action<Animation*>>> cancel_handlers_;
+ public:
+ AnimationManager();
+ AnimationManager(const AnimationManager& other) = delete;
+ AnimationManager(AnimationManager&& other) = delete;
+ AnimationManager& operator=(const AnimationManager& other) = delete;
+ AnimationManager& operator=(AnimationManager&& other) = delete;
+ ~AnimationManager() override;
+
+ AnimationDelegatePtr CreateAnimation(
+ String tag,
+ AnimationTimeUnit duration,
+ Vector<AnimationStepHandlerPtr> step_handlers,
+ Vector<AnimationStartHandlerPtr> start_handlers,
+ Vector<ActionPtr> finish_handlers,
+ Vector<ActionPtr> cancel_handlers
+ );
+ void RemoveAnimation(const String& tag);
- double current_time_ = 0;
+ private:
+ void SetTimer();
+ void KillTimer();
+ private:
+ std::unordered_map<String, AnimationPtr> animations_;
+ std::shared_ptr<ICancelable> timer_;
+ ActionPtr timer_action_;
+ };
+ }
+
+ class AnimationBuilder : public Object
+ {
public:
- class Builder : public OneTimeBuilder<Animation>
+ AnimationBuilder(String tag, const AnimationTimeUnit duration)
+ : tag(std::move(tag)), duration(duration)
{
- public:
- Builder(String tag, const double duration)
- : tag(std::move(tag)), duration(duration)
- {
- }
+ }
- String tag;
- double duration;
+ String tag;
+ AnimationTimeUnit duration;
- Builder& AddStepHandler(Action<Animation*, double>&& handler)
- {
- if (IsValid())
- step_handlers_.push_back(std::make_shared<Action<Animation*, double>>(std::move(handler)));
- return *this;
- }
+ AnimationBuilder& AddStepHandler(AnimationStepHandlerPtr handler)
+ {
+ step_handlers_.push_back(std::move(handler));
+ return *this;
+ }
- Builder& AddStartHandler(Action<Animation*>&& handler)
- {
- if (IsValid())
- start_handlers_.push_back(std::make_shared<Action<Animation*>>(std::move(handler)));
- return *this;
- }
+ AnimationBuilder& AddStartHandler(AnimationStartHandlerPtr handler)
+ {
+ start_handlers_.push_back(std::move(handler));
+ return *this;
+ }
- Builder& AddFinishHandler(Action<Animation*>&& handler)
- {
- if (IsValid())
- finish_handlers_.push_back(std::make_shared<Action<Animation*>>(std::move(handler)));
- return *this;
- }
+ AnimationBuilder& AddFinishHandler(ActionPtr handler)
+ {
+ finish_handlers_.push_back(std::move(handler));
+ return *this;
+ }
- Builder& AddCancelHandler(Action<Animation*>&& handler)
- {
- if (IsValid())
- cancel_handlers_.push_back(std::make_shared<Action<Animation*>>(std::move(handler)));
- return *this;
- }
+ AnimationBuilder& AddCancelHandler(ActionPtr handler)
+ {
+ cancel_handlers_.push_back(std::move(handler));
+ return *this;
+ }
- protected:
- Animation* OnCreate() override
- {
- return new Animation(std::move(tag), duration, step_handlers_, start_handlers_, finish_handlers_, cancel_handlers_);
- }
+ AnimationDelegatePtr Start() const;
- private:
- Vector<std::shared_ptr<Action<Animation*, double>>> step_handlers_;
- Vector<std::shared_ptr<Action<Animation*>>> start_handlers_;
- Vector<std::shared_ptr<Action<Animation*>>> finish_handlers_;
- Vector<std::shared_ptr<Action<Animation*>>> cancel_handlers_;
- };
+ private:
+ Vector<AnimationStepHandlerPtr> step_handlers_;
+ Vector<AnimationStartHandlerPtr> start_handlers_;
+ Vector<ActionPtr> finish_handlers_;
+ Vector<ActionPtr> cancel_handlers_;
};
}
diff --git a/CruUI/ui/control.cpp b/CruUI/ui/control.cpp
index d2864fce..1fa7a08d 100644
--- a/CruUI/ui/control.cpp
+++ b/CruUI/ui/control.cpp
@@ -46,14 +46,14 @@ namespace cru {
});
}
- void Control::ForeachChild(Action<Control*>&& predicate) const
+ void Control::ForeachChild(Function<void(Control*)>&& predicate) const
{
if (is_container_)
for (const auto child : children_)
predicate(child);
}
- void Control::ForeachChild(FlowControlAction<Control*>&& predicate) const
+ void Control::ForeachChild(Function<FlowControl(Control*)>&& predicate) const
{
if (is_container_)
for (const auto child : children_)
@@ -141,7 +141,7 @@ namespace cru {
return ancestor;
}
- void TraverseDescendantsInternal(Control* control, Action<Control*>& predicate)
+ void TraverseDescendantsInternal(Control* control, Function<void(Control*)>& predicate)
{
predicate(control);
control->ForeachChild([&predicate](Control* c) {
@@ -149,7 +149,7 @@ namespace cru {
});
}
- void Control::TraverseDescendants(Action<Control*>&& predicate)
+ void Control::TraverseDescendants(Function<void(Control*)>&& predicate)
{
if (is_container_)
TraverseDescendantsInternal(this, predicate);
diff --git a/CruUI/ui/control.h b/CruUI/ui/control.h
index ca2dfb84..daae1787 100644
--- a/CruUI/ui/control.h
+++ b/CruUI/ui/control.h
@@ -60,8 +60,8 @@ namespace cru
}
//Traverse the children
- void ForeachChild(Action<Control*>&& predicate) const;
- void ForeachChild(FlowControlAction<Control*>&& predicate) const;
+ void ForeachChild(Function<void(Control*)>&& predicate) const;
+ void ForeachChild(Function<FlowControl(Control*)>&& predicate) const;
//Return a vector of all children. This function will create a
//temporary copy of vector of children. If you just want to
@@ -93,7 +93,7 @@ namespace cru
}
//Traverse the tree rooted the control including itself.
- void TraverseDescendants(Action<Control*>&& predicate);
+ void TraverseDescendants(Function<void(Control*)>&& predicate);
//*************** region: position and size ***************
// Position and size part must be isolated from layout part.
diff --git a/CruUI/ui/controls/text_block.cpp b/CruUI/ui/controls/text_block.cpp
index beb799d3..294c456b 100644
--- a/CruUI/ui/controls/text_block.cpp
+++ b/CruUI/ui/controls/text_block.cpp
@@ -53,6 +53,19 @@ namespace cru
Repaint();
}
+ void TextBlock::AddTextLayoutHandler(TextLayoutHandlerPtr handler)
+ {
+ text_layout_handlers_.push_back(std::move(handler));
+ }
+
+ void TextBlock::RemoveTextLayoutHandler(const TextLayoutHandlerPtr& handler)
+ {
+ const auto find_result = std::find(text_layout_handlers_.cbegin(), text_layout_handlers_.cend(),
+ handler);
+ if (find_result != text_layout_handlers_.cend())
+ text_layout_handlers_.erase(find_result);
+ }
+
void TextBlock::OnSizeChangedCore(events::SizeChangedEventArgs& args)
{
Control::OnSizeChangedCore(args);
@@ -263,7 +276,7 @@ namespace cru
&text_layout_
));
- std::for_each(text_layout_handlers_.cbegin(), text_layout_handlers_.cend(), [this](const std::shared_ptr<TextLayoutHandler>& handler)
+ std::for_each(text_layout_handlers_.cbegin(), text_layout_handlers_.cend(), [this](const TextLayoutHandlerPtr& handler)
{
(*handler)(text_layout_);
});
diff --git a/CruUI/ui/controls/text_block.h b/CruUI/ui/controls/text_block.h
index db22e3c7..3fed2283 100644
--- a/CruUI/ui/controls/text_block.h
+++ b/CruUI/ui/controls/text_block.h
@@ -39,7 +39,7 @@ namespace cru
class TextBlock : public Control
{
public:
- using TextLayoutHandler = Action<Microsoft::WRL::ComPtr<IDWriteTextLayout>>;
+ using TextLayoutHandlerPtr = FunctionPtr<void(Microsoft::WRL::ComPtr<IDWriteTextLayout>)>;
static TextBlock* Create(
const String& text = L"",
@@ -85,16 +85,9 @@ namespace cru
void SetTextFormat(const Microsoft::WRL::ComPtr<IDWriteTextFormat>& text_format);
- void AddTextLayoutHandler(std::shared_ptr<TextLayoutHandler> handler)
- {
- text_layout_handlers_.push_back(std::move(handler));
- }
- void RemoveTextLayoutHandler(const std::shared_ptr<TextLayoutHandler>& handler)
- {
- const auto find_result = std::find(text_layout_handlers_.cbegin(), text_layout_handlers_.cend(), handler);
- if (find_result != text_layout_handlers_.cend())
- text_layout_handlers_.erase(find_result);
- }
+ void AddTextLayoutHandler(TextLayoutHandlerPtr handler);
+
+ void RemoveTextLayoutHandler(const TextLayoutHandlerPtr& handler);
protected:
void OnSizeChangedCore(events::SizeChangedEventArgs& args) override final;
@@ -122,7 +115,7 @@ namespace cru
Microsoft::WRL::ComPtr<IDWriteTextFormat> text_format_;
Microsoft::WRL::ComPtr<IDWriteTextLayout> text_layout_;
- Vector<std::shared_ptr<TextLayoutHandler>> text_layout_handlers_;
+ Vector<TextLayoutHandlerPtr> text_layout_handlers_;
bool is_selecting_ = false;
unsigned mouse_down_position_ = 0;
diff --git a/CruUI/ui/controls/toggle_button.cpp b/CruUI/ui/controls/toggle_button.cpp
index a22cfda8..033fa9fc 100644
--- a/CruUI/ui/controls/toggle_button.cpp
+++ b/CruUI/ui/controls/toggle_button.cpp
@@ -8,7 +8,7 @@
namespace cru::ui::controls
{
using graph::CreateSolidBrush;
- using animations::Animation;
+ using animations::AnimationBuilder;
// ui length parameters of toggle button.
constexpr float half_height = 15;
@@ -56,15 +56,16 @@ namespace cru::ui::controls
const auto previous_position = current_circle_position_;
const auto delta = destination_x - current_circle_position_;
- constexpr double total_time = 0.5;
+ constexpr auto total_time = FloatSecond(0.2);
- const auto time = total_time * std::abs(delta) / (inner_circle_x * 2);
+ const auto time = total_time * (std::abs(delta) / (inner_circle_x * 2));
- Animation::Builder(fmt::format(L"ToggleButton {}", reinterpret_cast<size_t>(this)), time).AddStepHandler([=](Animation*, const float percentage)
+ AnimationBuilder(fmt::format(L"ToggleButton {}", reinterpret_cast<size_t>(this)), time)
+ .AddStepHandler(CreatePtr<animations::AnimationStepHandlerPtr>([=](animations::AnimationDelegatePtr, const double percentage)
{
- current_circle_position_ = previous_position + delta * percentage;
+ current_circle_position_ = static_cast<float>(previous_position + delta * percentage);
Repaint();
- }).Create();
+ })).Start();
OnToggleInternal(state);
Repaint();
diff --git a/CruUI/ui/window.h b/CruUI/ui/window.h
index 790e3c32..5addf963 100644
--- a/CruUI/ui/window.h
+++ b/CruUI/ui/window.h
@@ -1,7 +1,6 @@
#pragma once
#include "system_headers.h"
-#include <set>
#include <map>
#include <list>
#include <memory>