aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/animations/animation.cpp114
-rw-r--r--src/ui/animations/animation.h88
-rw-r--r--src/ui/border_property.cpp31
-rw-r--r--src/ui/border_property.h61
-rw-r--r--src/ui/control.cpp102
-rw-r--r--src/ui/control.h35
-rw-r--r--src/ui/controls/button.cpp30
-rw-r--r--src/ui/controls/button.h4
-rw-r--r--src/ui/controls/linear_layout.cpp50
-rw-r--r--src/ui/controls/text_box.cpp19
-rw-r--r--src/ui/controls/text_box.h3
-rw-r--r--src/ui/controls/text_control.cpp19
-rw-r--r--src/ui/controls/text_control.h9
-rw-r--r--src/ui/controls/toggle_button.cpp15
-rw-r--r--src/ui/layout_base.cpp7
-rw-r--r--src/ui/window.cpp11
-rw-r--r--src/ui/window.h2
17 files changed, 254 insertions, 346 deletions
diff --git a/src/ui/animations/animation.cpp b/src/ui/animations/animation.cpp
index 9d05860a..ca0fe8bc 100644
--- a/src/ui/animations/animation.cpp
+++ b/src/ui/animations/animation.cpp
@@ -1,6 +1,5 @@
#include "animation.h"
-#include <cassert>
#include <utility>
namespace cru::ui::animations
@@ -39,15 +38,12 @@ namespace cru::ui::animations
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(AnimationInfo info, AnimationDelegatePtr delegate)
+ : info_(std::move(info)), delegate_(std::move(delegate))
+ {
+
+ }
+
Animation(const Animation& other) = delete;
Animation(Animation&& other) = delete;
Animation& operator=(const Animation& other) = delete;
@@ -60,35 +56,17 @@ namespace cru::ui::animations
String GetTag() const
{
- return tag_;
+ return info_.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_;
+ const AnimationInfo info_;
+ const 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();
- }))
{
}
@@ -98,16 +76,14 @@ namespace cru::ui::animations
KillTimer();
}
- AnimationDelegatePtr AnimationManager::CreateAnimation(String tag, AnimationTimeUnit duration,
- Vector<AnimationStepHandlerPtr> step_handlers, Vector<AnimationStartHandlerPtr> start_handlers,
- Vector<ActionPtr> finish_handlers, Vector<ActionPtr> cancel_handlers)
+ AnimationDelegatePtr AnimationManager::CreateAnimation(AnimationInfo info)
{
if (animations_.empty())
SetTimer();
+ const auto tag = info.tag;
auto delegate = std::make_shared<AnimationDelegateImpl>(tag);
-
- 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);
+ animations_[tag] = std::make_unique<Animation>(std::move(info), delegate);
return delegate;
}
@@ -124,67 +100,63 @@ namespace cru::ui::animations
void AnimationManager::SetTimer()
{
- if (timer_ == nullptr)
- timer_ = SetInterval(std::chrono::duration_cast<std::chrono::milliseconds>(frame_step_time), timer_action_);
+ if (!timer_.has_value())
+ timer_ = SetInterval(std::chrono::duration_cast<std::chrono::milliseconds>(frame_step_time), [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();
+ });
}
void AnimationManager::KillTimer()
{
- if (timer_ != nullptr)
+ if (timer_.has_value())
{
- timer_->Cancel();
- timer_ = nullptr;
+ timer_.value().Cancel();
+ timer_ = std::nullopt;
}
}
- 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()
{
- if (current_time_ < duration_)
- for (auto& handler : cancel_handlers_)
- (*handler)();
+ if (current_time_ < info_.duration)
+ for (const auto& handler : info_.cancel_handlers)
+ handler();
}
bool Animation::Step(const AnimationTimeUnit time)
{
current_time_ += time;
- if (current_time_ > duration_)
+ if (current_time_ > info_.duration)
{
- for (auto& handler : step_handlers_)
- (*handler)(delegate_, 1);
- for (auto& handler : finish_handlers_)
- (*handler)();
+ for (const auto& handler : info_.step_handlers)
+ handler(delegate_, 1);
+ for (const auto& handler : info_.finish_handlers)
+ handler();
return true;
}
else
{
- for (auto& handler : step_handlers_)
- (*handler)(delegate_, current_time_ / duration_);
+ for (const auto& handler : info_.step_handlers)
+ handler(delegate_, current_time_ / info_.duration);
return false;
}
}
}
- AnimationDelegatePtr AnimationBuilder::Start() const
+ AnimationDelegatePtr AnimationBuilder::Start()
{
- return details::AnimationManager::GetInstance()->CreateAnimation(tag, duration, step_handlers_, start_handlers_, finish_handlers_, cancel_handlers_);
+ CheckValid();
+ valid_ = false;
+ return details::AnimationManager::GetInstance()->CreateAnimation(std::move(info_));
}
}
diff --git a/src/ui/animations/animation.h b/src/ui/animations/animation.h
index 69b08b0c..91a666c9 100644
--- a/src/ui/animations/animation.h
+++ b/src/ui/animations/animation.h
@@ -10,19 +10,46 @@ namespace cru::ui::animations
{
using AnimationTimeUnit = FloatSecond;
-
- using IAnimationDelegate = ICancelable;
- using AnimationDelegatePtr = CancelablePtr;
+ struct IAnimationDelegate : virtual Interface
+ {
+ virtual void Cancel() = 0;
+ };
- using AnimationStepHandlerPtr = FunctionPtr<void(AnimationDelegatePtr, double)>;
- using AnimationStartHandlerPtr = FunctionPtr<void(AnimationDelegatePtr)>;
+ using AnimationDelegatePtr = std::shared_ptr<IAnimationDelegate>;
+ using AnimationStepHandler = std::function<void(AnimationDelegatePtr, double)>;
+ using AnimationStartHandler = std::function<void(AnimationDelegatePtr)>;
+ using AnimationFinishHandler = std::function<void()>;
+ using AnimationCancelHandler = std::function<void()>;
namespace details
{
class Animation;
using AnimationPtr = std::unique_ptr<Animation>;
+ class AnimationInfo
+ {
+ public:
+ AnimationInfo(String tag, const AnimationTimeUnit duration)
+ : tag(std::move(tag)),
+ duration(duration)
+ {
+
+ }
+ AnimationInfo(const AnimationInfo& other) = default;
+ AnimationInfo(AnimationInfo&& other) = default;
+ AnimationInfo& operator=(const AnimationInfo& other) = default;
+ AnimationInfo& operator=(AnimationInfo&& other) = default;
+ ~AnimationInfo() = default;
+
+ String tag;
+ AnimationTimeUnit duration;
+ std::vector<AnimationStepHandler> step_handlers{};
+ std::vector<AnimationStartHandler> start_handlers{};
+ std::vector<AnimationFinishHandler> finish_handlers{};
+ std::vector<AnimationCancelHandler> cancel_handlers{};
+ };
+
class AnimationManager : public Object
{
public:
@@ -39,14 +66,7 @@ namespace cru::ui::animations
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
- );
+ AnimationDelegatePtr CreateAnimation(AnimationInfo info);
void RemoveAnimation(const String& tag);
private:
@@ -55,8 +75,7 @@ namespace cru::ui::animations
private:
std::unordered_map<String, AnimationPtr> animations_;
- std::shared_ptr<ICancelable> timer_;
- ActionPtr timer_action_;
+ std::optional<TimerTask> timer_;
};
}
@@ -64,44 +83,49 @@ namespace cru::ui::animations
{
public:
AnimationBuilder(String tag, const AnimationTimeUnit duration)
- : tag(std::move(tag)), duration(duration)
+ : info_(std::move(tag), duration)
{
}
- String tag;
- AnimationTimeUnit duration;
-
- AnimationBuilder& AddStepHandler(AnimationStepHandlerPtr handler)
+ AnimationBuilder& AddStepHandler(const AnimationStepHandler& handler)
{
- step_handlers_.push_back(std::move(handler));
+ CheckValid();
+ info_.step_handlers.push_back(handler);
return *this;
}
- AnimationBuilder& AddStartHandler(AnimationStartHandlerPtr handler)
+ AnimationBuilder& AddStartHandler(const AnimationStartHandler& handler)
{
- start_handlers_.push_back(std::move(handler));
+ CheckValid();
+ info_.start_handlers.push_back(handler);
return *this;
}
- AnimationBuilder& AddFinishHandler(ActionPtr handler)
+ AnimationBuilder& AddFinishHandler(const AnimationFinishHandler& handler)
{
- finish_handlers_.push_back(std::move(handler));
+ CheckValid();
+ info_.finish_handlers.push_back(handler);
return *this;
}
- AnimationBuilder& AddCancelHandler(ActionPtr handler)
+ AnimationBuilder& AddCancelHandler(const AnimationCancelHandler& handler)
{
- cancel_handlers_.push_back(std::move(handler));
+ CheckValid();
+ info_.cancel_handlers.push_back(handler);
return *this;
}
- AnimationDelegatePtr Start() const;
+ AnimationDelegatePtr Start();
private:
- Vector<AnimationStepHandlerPtr> step_handlers_;
- Vector<AnimationStartHandlerPtr> start_handlers_;
- Vector<ActionPtr> finish_handlers_;
- Vector<ActionPtr> cancel_handlers_;
+ void CheckValid() const
+ {
+ if (!valid_)
+ throw std::runtime_error("The animation builder is invalid.");
+ }
+
+ bool valid_ = true;
+ details::AnimationInfo info_;
};
}
diff --git a/src/ui/border_property.cpp b/src/ui/border_property.cpp
index 03cae16e..f716a8be 100644
--- a/src/ui/border_property.cpp
+++ b/src/ui/border_property.cpp
@@ -4,40 +4,13 @@
namespace cru::ui
{
- BorderProperty::BorderProperty()
+ BorderProperty::BorderProperty(): BorderProperty(graph::CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Black)))
{
- brush_ = graph::CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Black));
- }
-
- void BorderProperty::SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> brush)
- {
- if (brush == nullptr)
- throw std::invalid_argument("Brush of BorderProperty mustn't be null.");
- brush_ = std::move(brush);
- RaisePropertyChangedEvent(brush_property_name);
- }
-
- void BorderProperty::SetWidth(const float width)
- {
- stroke_width_ = width;
- RaisePropertyChangedEvent(width_property_name);
- }
- void BorderProperty::SetStrokeStyle(Microsoft::WRL::ComPtr<ID2D1StrokeStyle> stroke_style)
- {
- stroke_style_ = std::move(stroke_style);
- RaisePropertyChangedEvent(stroke_style_property_name);
}
- void BorderProperty::SetRadiusX(const float radius_x)
+ BorderProperty::BorderProperty(Microsoft::WRL::ComPtr<ID2D1Brush> brush): brush_(std::move(brush))
{
- radius_x_ = radius_x;
- RaisePropertyChangedEvent(radius_x_property_name);
- }
- void BorderProperty::SetRadiusY(const float radius_y)
- {
- radius_y_ = radius_y;
- RaisePropertyChangedEvent(radius_y_property_name);
}
}
diff --git a/src/ui/border_property.h b/src/ui/border_property.h
index 71ec0e7d..ce16dea7 100644
--- a/src/ui/border_property.h
+++ b/src/ui/border_property.h
@@ -7,28 +7,16 @@
namespace cru::ui
{
- class BorderProperty final : public PropertyChangedNotifyObject
+ class BorderProperty final
{
public:
- constexpr static auto brush_property_name = L"Brush";
- constexpr static auto width_property_name = L"StrokeWidth";
- constexpr static auto stroke_style_property_name = L"StrokeStyle";
- constexpr static auto radius_x_property_name = L"RadiusX";
- constexpr static auto radius_y_property_name = L"RadiusY";
-
- using Ptr = std::shared_ptr<BorderProperty>;
-
- static Ptr Create()
- {
- return std::make_shared<BorderProperty>();
- }
-
BorderProperty();
- BorderProperty(const BorderProperty& other) = delete;
- BorderProperty(BorderProperty&& other) = delete;
- BorderProperty& operator=(const BorderProperty& other) = delete;
- BorderProperty& operator=(BorderProperty&& other) = delete;
- ~BorderProperty() override = default;
+ explicit BorderProperty(Microsoft::WRL::ComPtr<ID2D1Brush> brush);
+ BorderProperty(const BorderProperty& other) = default;
+ BorderProperty(BorderProperty&& other) = default;
+ BorderProperty& operator=(const BorderProperty& other) = default;
+ BorderProperty& operator=(BorderProperty&& other) = default;
+ ~BorderProperty() = default;
Microsoft::WRL::ComPtr<ID2D1Brush> GetBrush() const
@@ -56,14 +44,37 @@ namespace cru::ui
return radius_y_;
}
- void SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> brush);
- void SetWidth(float width);
- void SetStrokeStyle(Microsoft::WRL::ComPtr<ID2D1StrokeStyle> stroke_style);
- void SetRadiusX(float radius_x);
- void SetRadiusY(float radius_y);
+ void SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> brush)
+ {
+ Require(brush == nullptr, "Brush of BorderProperty mustn't be null.");
+ brush_ = std::move(brush);
+ }
+
+ void SetStrokeWidth(const float stroke_width)
+ {
+ Require(stroke_width >= 0.0f, "Stroke width must be no less than 0.");
+ stroke_width_ = stroke_width;
+ }
+
+ void SetStrokeStyle(Microsoft::WRL::ComPtr<ID2D1StrokeStyle> stroke_style)
+ {
+ stroke_style_ = std::move(stroke_style);
+ }
+
+ void SetRadiusX(const float radius_x)
+ {
+ Require(radius_x >= 0.0f, "Radius-x must be no less than 0.");
+ radius_x_ = radius_x;
+ }
+
+ void SetRadiusY(const float radius_y)
+ {
+ Require(radius_y >= 0.0f, "Radius-y must be no less than 0.");
+ radius_y_ = radius_y;
+ }
private:
- Microsoft::WRL::ComPtr<ID2D1Brush> brush_ = nullptr;
+ Microsoft::WRL::ComPtr<ID2D1Brush> brush_;
float stroke_width_ = 1.0f;
Microsoft::WRL::ComPtr<ID2D1StrokeStyle> stroke_style_ = nullptr;
float radius_x_ = 0.0f;
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 838747bc..37e6d2b8 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -1,5 +1,7 @@
#include "control.h"
+#include <algorithm>
+
#include "window.h"
#include "graph/graph.h"
#include "exception.h"
@@ -9,13 +11,7 @@ namespace cru {
using namespace events;
Control::Control(const bool container) :
- is_container_(container),
- border_property_changed_listener_(CreatePtr<PropertyChangedNotifyObject::PropertyChangedHandlerPtr>([this](const StringView& property_name)
- {
- if (property_name == BorderProperty::width_property_name)
- InvalidateLayout();
- Repaint();
- }))
+ is_container_(container)
{
}
@@ -27,27 +23,10 @@ namespace cru {
Control::~Control()
{
- ForeachChild([](auto control)
+ for (auto control: GetChildren())
{
delete control;
- });
- }
-
- void Control::ForeachChild(Function<void(Control*)>&& predicate) const
- {
- if (is_container_)
- for (const auto child : children_)
- predicate(child);
- }
-
- void Control::ForeachChild(Function<FlowControl(Control*)>&& predicate) const
- {
- if (is_container_)
- for (const auto child : children_)
- {
- if (predicate(child) == FlowControl::Break)
- break;
- }
+ }
}
void AddChildCheck(Control* control)
@@ -59,6 +38,11 @@ namespace cru {
throw std::invalid_argument("Can't add a window as child.");
}
+ const std::vector<Control*>& Control::GetChildren() const
+ {
+ return children_;
+ }
+
void Control::AddChild(Control* control)
{
ThrowIfNotContainer();
@@ -128,15 +112,17 @@ namespace cru {
return ancestor;
}
- void TraverseDescendantsInternal(Control* control, Function<void(Control*)>& predicate)
+ void TraverseDescendantsInternal(Control* control, const std::function<void(Control*)>& predicate)
{
predicate(control);
- control->ForeachChild([&predicate](Control* c) {
- TraverseDescendantsInternal(c, predicate);
- });
+ if (control->IsContainer())
+ for (auto c: control->GetChildren())
+ {
+ TraverseDescendantsInternal(c, predicate);
+ }
}
- void Control::TraverseDescendants(Function<void(Control*)>&& predicate)
+ void Control::TraverseDescendants(const std::function<void(Control*)>& predicate)
{
if (is_container_)
TraverseDescendantsInternal(this, predicate);
@@ -305,13 +291,13 @@ namespace cru {
return result;
if (is_bordered_)
- Shrink(result, Thickness(border_property_->GetStrokeWidth() / 2.0f));
+ Shrink(result, Thickness(GetBorderProperty().GetStrokeWidth() / 2.0f));
if (range == RectRange::HalfBorder)
return result;
if (is_bordered_)
- Shrink(result, Thickness(border_property_->GetStrokeWidth() / 2.0f));
+ Shrink(result, Thickness(GetBorderProperty().GetStrokeWidth() / 2.0f));
if (range == RectRange::Padding)
return result;
@@ -321,15 +307,8 @@ namespace cru {
return result;
}
- void Control::SetBorderProperty(BorderProperty::Ptr border_property)
+ void Control::InvalidateBorder()
{
- if (border_property == nullptr)
- throw std::invalid_argument("Border property mustn't be null.");
-
- if (border_property_ != nullptr)
- border_property_->RemovePropertyChangedListener(border_property_changed_listener_);
- border_property_ = std::move(border_property);
- border_property_->AddPropertyChangedListener(border_property_changed_listener_);
InvalidateLayout();
Repaint();
}
@@ -338,28 +317,11 @@ namespace cru {
{
if (bordered != is_bordered_)
{
- if (bordered && border_property_ == nullptr) // create border property.
- {
- border_property_ = BorderProperty::Create();
- border_property_->AddPropertyChangedListener(border_property_changed_listener_);
- }
-
is_bordered_ = bordered;
- InvalidateLayout();
- Repaint();
+ InvalidateBorder();
}
}
- void Control::SetCursor(const Cursor::Ptr& cursor)
- {
-
- }
-
- Cursor::Ptr Control::GetCursorInherit()
- {
-
- }
-
void Control::OnAddChild(Control* child)
{
if (auto window = GetWindow())
@@ -419,12 +381,12 @@ namespace cru {
device_context->DrawRoundedRectangle(
D2D1::RoundedRect(
Convert(border_rect),
- border_property_->GetRadiusX(),
- border_property_->GetRadiusY()
+ GetBorderProperty().GetRadiusX(),
+ GetBorderProperty().GetRadiusY()
),
- border_property_->GetBrush().Get(),
- border_property_->GetStrokeWidth(),
- border_property_->GetStrokeStyle().Get()
+ GetBorderProperty().GetBrush().Get(),
+ GetBorderProperty().GetStrokeWidth(),
+ GetBorderProperty().GetStrokeStyle().Get()
);
}
}
@@ -713,7 +675,7 @@ namespace cru {
auto border_size = Size::Zero();
if (is_bordered_)
{
- const auto border_width = border_property_->GetStrokeWidth();
+ const auto border_width = GetBorderProperty().GetStrokeWidth();
border_size = Size(border_width * 2.0f, border_width * 2.0f);
}
@@ -777,7 +739,7 @@ namespace cru {
auto border_width = 0.0f;
if (is_bordered_)
{
- border_width = border_property_->GetStrokeWidth();
+ border_width = GetBorderProperty().GetStrokeWidth();
}
const Rect content_rect(
@@ -793,7 +755,7 @@ namespace cru {
Size Control::OnMeasureContent(const Size& available_size)
{
auto max_child_size = Size::Zero();
- ForeachChild([&max_child_size, available_size](Control* control)
+ for (auto control: GetChildren())
{
control->Measure(available_size);
const auto&& size = control->GetDesiredSize();
@@ -801,13 +763,13 @@ namespace cru {
max_child_size.width = size.width;
if (max_child_size.height < size.height)
max_child_size.height = size.height;
- });
+ }
return max_child_size;
}
void Control::OnLayoutContent(const Rect& rect)
{
- ForeachChild([rect](Control* control)
+ for (auto control: GetChildren())
{
const auto layout_params = control->GetLayoutParams();
const auto size = control->GetDesiredSize();
@@ -831,7 +793,7 @@ namespace cru {
calculate_anchor(rect.left, layout_params->width.alignment, rect.width, size.width),
calculate_anchor(rect.top, layout_params->height.alignment, rect.height, size.height)
), size));
- });
+ }
}
void Control::CheckAndNotifyPositionChanged()
diff --git a/src/ui/control.h b/src/ui/control.h
index e88228d0..25cd5c0a 100644
--- a/src/ui/control.h
+++ b/src/ui/control.h
@@ -5,9 +5,9 @@
#include <any>
#include <typeinfo>
#include <utility>
-#include <fmt/format.h>
#include "base.h"
+#include "format.h"
#include "ui_base.h"
#include "layout_base.h"
#include "events/ui_event.h"
@@ -63,6 +63,8 @@ namespace cru
public:
//*************** region: tree ***************
+ //TODO!
+ //virtual StringView GetControlType() const = 0;
bool IsContainer() const
{
@@ -75,17 +77,8 @@ namespace cru
return parent_;
}
- //Traverse the children
- 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
- //traverse all children, just call ForeachChild.
- Vector<Control*> GetChildren() const
- {
- return children_;
- }
+ //Return a immutable vector of all children.
+ const std::vector<Control*>& GetChildren() const;
//Add a child at tail.
void AddChild(Control* control);
@@ -109,7 +102,7 @@ namespace cru
}
//Traverse the tree rooted the control including itself.
- void TraverseDescendants(Function<void(Control*)>&& predicate);
+ void TraverseDescendants(const std::function<void(Control*)>& predicate);
//*************** region: position and size ***************
// Position and size part must be isolated from layout part.
@@ -187,12 +180,12 @@ namespace cru
//*************** region: border ***************
- BorderProperty::Ptr GetBorderProperty() const
+ BorderProperty& GetBorderProperty()
{
return border_property_;
}
- void SetBorderProperty(BorderProperty::Ptr border_property);
+ void InvalidateBorder();
bool IsBordered() const
{
@@ -216,7 +209,7 @@ namespace cru
}
catch (const std::bad_any_cast&)
{
- throw std::runtime_error(fmt::format("Key \"{}\" is not of the type {}.", ToUtf8String(key), typeid(T).name()));
+ throw std::runtime_error(Format("Key \"{}\" is not of the type {}.", ToUtf8String(key), typeid(T).name()));
}
}
@@ -234,6 +227,8 @@ namespace cru
//*************** region: cursor ***************
+ //TODO!
+ /*
Cursor::Ptr GetCursor() const
{
return cursor_;
@@ -242,6 +237,7 @@ namespace cru
void SetCursor(const Cursor::Ptr& cursor);
Cursor::Ptr GetCursorInherit();
+ */
//*************** region: events ***************
@@ -380,7 +376,7 @@ namespace cru
private:
Control * parent_ = nullptr;
- Vector<Control*> children_{};
+ std::vector<Control*> children_{};
// When position is changed and notification hasn't been
// sent, it will be the old position. When position is changed
@@ -406,8 +402,7 @@ namespace cru
Size desired_size_ = Size::Zero();
bool is_bordered_ = false;
- BorderProperty::Ptr border_property_;
- PropertyChangedNotifyObject::PropertyChangedHandlerPtr border_property_changed_listener_;
+ BorderProperty border_property_;
std::unordered_map<String, std::any> additional_properties_{};
@@ -461,6 +456,6 @@ namespace cru
return control;
}
- constexpr std::initializer_list<Control*> ControlList(std::initializer_list<Control*> &&li) { return li; }
+ using ControlList = std::initializer_list<Control*>;
}
}
diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp
index db0b71c2..e600eb89 100644
--- a/src/ui/controls/button.cpp
+++ b/src/ui/controls/button.cpp
@@ -6,33 +6,31 @@ namespace cru::ui::controls
{
using graph::CreateSolidBrush;
- Button::Button() : Control(true)
+ Button::Button() : Control(true),
+ normal_border_{CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::RoyalBlue))},
+ pressed_border_{CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Blue))}
{
- normal_border_ = BorderProperty::Create();
- normal_border_->SetBrush(CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::RoyalBlue)));
- normal_border_->SetWidth(2);
- normal_border_->SetRadiusX(6);
- normal_border_->SetRadiusY(6);
+ normal_border_.SetStrokeWidth(2);
+ normal_border_.SetRadiusX(6);
+ normal_border_.SetRadiusY(6);
- pressed_border_ = BorderProperty::Create();
- pressed_border_->SetBrush(CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Blue)));
- pressed_border_->SetWidth(2);
- pressed_border_->SetRadiusX(6);
- pressed_border_->SetRadiusY(6);
+ pressed_border_.SetStrokeWidth(2);
+ pressed_border_.SetRadiusX(6);
+ pressed_border_.SetRadiusY(6);
SetBordered(true);
- SetBorderProperty(normal_border_);
+ GetBorderProperty() = normal_border_;
}
void Button::OnMouseClickBegin(MouseButton button)
{
- SetBorderProperty(pressed_border_);
- Repaint();
+ GetBorderProperty() = pressed_border_;
+ InvalidateBorder();
}
void Button::OnMouseClickEnd(MouseButton button)
{
- SetBorderProperty(normal_border_);
- Repaint();
+ GetBorderProperty() = normal_border_;
+ InvalidateBorder();
}
}
diff --git a/src/ui/controls/button.h b/src/ui/controls/button.h
index 011f97d2..e0ece85a 100644
--- a/src/ui/controls/button.h
+++ b/src/ui/controls/button.h
@@ -32,7 +32,7 @@ namespace cru::ui::controls
void OnMouseClickEnd(MouseButton button) override final;
private:
- BorderProperty::Ptr normal_border_;
- BorderProperty::Ptr pressed_border_;
+ BorderProperty normal_border_;
+ BorderProperty pressed_border_;
};
}
diff --git a/src/ui/controls/linear_layout.cpp b/src/ui/controls/linear_layout.cpp
index 7921745a..fb5d3db7 100644
--- a/src/ui/controls/linear_layout.cpp
+++ b/src/ui/controls/linear_layout.cpp
@@ -1,5 +1,7 @@
#include "linear_layout.h"
+#include <algorithm>
+
namespace cru::ui::controls
{
LinearLayout::LinearLayout(const Orientation orientation)
@@ -28,33 +30,33 @@ namespace cru::ui::controls
// First measure Content and Exactly and count Stretch.
if (orientation_ == Orientation::Horizontal)
- ForeachChild([&](Control* const control)
- {
- const auto mode = control->GetLayoutParams()->width.mode;
- if (mode == MeasureMode::Content || mode == MeasureMode::Exactly)
+ for(auto control: GetChildren())
{
- control->Measure(AtLeast0(rest_available_size_for_children));
- const auto size = control->GetDesiredSize();
- rest_available_size_for_children.width -= size.width;
- secondary_side_child_max_length = std::max(size.height, secondary_side_child_max_length);
+ const auto mode = control->GetLayoutParams()->width.mode;
+ if (mode == MeasureMode::Content || mode == MeasureMode::Exactly)
+ {
+ control->Measure(AtLeast0(rest_available_size_for_children));
+ const auto size = control->GetDesiredSize();
+ rest_available_size_for_children.width -= size.width;
+ secondary_side_child_max_length = std::max(size.height, secondary_side_child_max_length);
+ }
+ else
+ stretch_control_list.push_back(control);
}
- else
- stretch_control_list.push_back(control);
- });
else
- ForeachChild([&](Control* const control)
- {
- const auto mode = control->GetLayoutParams()->height.mode;
- if (mode == MeasureMode::Content || mode == MeasureMode::Exactly)
+ for(auto control: GetChildren())
{
- control->Measure(AtLeast0(rest_available_size_for_children));
- const auto size = control->GetDesiredSize();
- rest_available_size_for_children.height -= size.height;
- secondary_side_child_max_length = std::max(size.width, secondary_side_child_max_length);
+ const auto mode = control->GetLayoutParams()->height.mode;
+ if (mode == MeasureMode::Content || mode == MeasureMode::Exactly)
+ {
+ control->Measure(AtLeast0(rest_available_size_for_children));
+ const auto size = control->GetDesiredSize();
+ rest_available_size_for_children.height -= size.height;
+ secondary_side_child_max_length = std::max(size.width, secondary_side_child_max_length);
+ }
+ else
+ stretch_control_list.push_back(control);
}
- else
- stretch_control_list.push_back(control);
- });
if (orientation_ == Orientation::Horizontal)
{
@@ -97,7 +99,7 @@ namespace cru::ui::controls
void LinearLayout::OnLayoutContent(const Rect& rect)
{
float current_main_side_anchor = 0;
- ForeachChild([this, &current_main_side_anchor, rect](Control* control)
+ for(auto control: GetChildren())
{
const auto layout_params = control->GetLayoutParams();
const auto size = control->GetDesiredSize();
@@ -133,6 +135,6 @@ namespace cru::ui::controls
control->Layout(calculate_rect(calculate_secondary_side_anchor(rect.width, size.width), current_main_side_anchor));
current_main_side_anchor += size.height;
}
- });
+ }
}
}
diff --git a/src/ui/controls/text_box.cpp b/src/ui/controls/text_box.cpp
index 54b2f7ab..d6c3d132 100644
--- a/src/ui/controls/text_box.cpp
+++ b/src/ui/controls/text_box.cpp
@@ -1,6 +1,7 @@
#include "text_box.h"
#include <cwctype>
+#include <cassert>
#include "graph/graph.h"
#include "exception.h"
@@ -21,12 +22,6 @@ namespace cru::ui::controls
caret_brush_ = CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Black));
- caret_action_ = CreateActionPtr([this]
- {
- is_caret_show_ = !is_caret_show_;
- Repaint();
- });
-
SetBordered(true);
}
@@ -48,17 +43,21 @@ namespace cru::ui::controls
void TextBox::OnGetFocusCore(events::FocusChangeEventArgs& args)
{
TextControl::OnGetFocusCore(args);
- assert(caret_timer_ == nullptr);
+ assert(!caret_timer_.has_value());
is_caret_show_ = true;
- caret_timer_ = SetInterval(Application::GetInstance()->GetCaretInfo().caret_blink_duration, caret_action_);
+ caret_timer_ = SetInterval(Application::GetInstance()->GetCaretInfo().caret_blink_duration, [this]
+ {
+ is_caret_show_ = !is_caret_show_;
+ Repaint();
+ });
}
void TextBox::OnLoseFocusCore(events::FocusChangeEventArgs& args)
{
Control::OnLoseFocusCore(args);
- assert(caret_timer_ != nullptr);
+ assert(caret_timer_.has_value());
caret_timer_->Cancel();
- caret_timer_ = nullptr;
+ caret_timer_ = std::nullopt;
is_caret_show_ = false;
}
diff --git a/src/ui/controls/text_box.h b/src/ui/controls/text_box.h
index 37e04835..a2f4e6e8 100644
--- a/src/ui/controls/text_box.h
+++ b/src/ui/controls/text_box.h
@@ -46,8 +46,7 @@ namespace cru::ui::controls
private:
unsigned caret_position_ = 0;
- TimerTask caret_timer_;
- ActionPtr caret_action_;
+ std::optional<TimerTask> caret_timer_{};
Microsoft::WRL::ComPtr<ID2D1Brush> caret_brush_;
bool is_caret_show_ = false;
};
diff --git a/src/ui/controls/text_control.cpp b/src/ui/controls/text_control.cpp
index 3c5d7c33..5769af58 100644
--- a/src/ui/controls/text_control.cpp
+++ b/src/ui/controls/text_control.cpp
@@ -3,6 +3,7 @@
#include "ui/window.h"
#include "graph/graph.h"
#include "exception.h"
+#include <cassert>
namespace cru::ui::controls
{
@@ -49,19 +50,6 @@ namespace cru::ui::controls
Repaint();
}
- void TextControl::AddTextLayoutHandler(TextLayoutHandlerPtr handler)
- {
- text_layout_handlers_.push_back(std::move(handler));
- }
-
- void TextControl::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 TextControl::SetSelectable(const bool is_selectable)
{
if (!is_selectable)
@@ -115,7 +103,7 @@ namespace cru::ui::controls
ThrowIfFailed(layout->GetMetrics(&text_metrics));
const auto metrics_count = text_metrics.lineCount * text_metrics.maxBidiReorderingDepth;
- Vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count);
+ std::vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count);
UINT32 actual_count;
layout->HitTestTextRange(
range.value().position, range.value().count,
@@ -238,8 +226,5 @@ namespace cru::ui::controls
size.width, size.height,
&text_layout_
));
-
- for (const auto& handler : text_layout_handlers_)
- (*handler)(text_layout_);
}
}
diff --git a/src/ui/controls/text_control.h b/src/ui/controls/text_control.h
index 01bb5565..18a258f2 100644
--- a/src/ui/controls/text_control.h
+++ b/src/ui/controls/text_control.h
@@ -12,8 +12,6 @@ namespace cru::ui::controls
const Microsoft::WRL::ComPtr<ID2D1Brush>& init_brush
);
public:
- using TextLayoutHandlerPtr = FunctionPtr<void(Microsoft::WRL::ComPtr<IDWriteTextLayout>)>;
-
TextControl(const TextControl& other) = delete;
TextControl(TextControl&& other) = delete;
TextControl& operator=(const TextControl& other) = delete;
@@ -41,11 +39,6 @@ namespace cru::ui::controls
void SetTextFormat(const Microsoft::WRL::ComPtr<IDWriteTextFormat>& text_format);
-
- void AddTextLayoutHandler(TextLayoutHandlerPtr handler);
-
- void RemoveTextLayoutHandler(const TextLayoutHandlerPtr& handler);
-
bool IsSelectable() const
{
return is_selectable_;
@@ -96,8 +89,6 @@ namespace cru::ui::controls
Microsoft::WRL::ComPtr<IDWriteTextLayout> text_layout_;
private:
- Vector<TextLayoutHandlerPtr> text_layout_handlers_;
-
bool is_selectable_ = false;
bool is_selecting_ = false;
diff --git a/src/ui/controls/toggle_button.cpp b/src/ui/controls/toggle_button.cpp
index 3cd5d3ef..c0244bb6 100644
--- a/src/ui/controls/toggle_button.cpp
+++ b/src/ui/controls/toggle_button.cpp
@@ -1,7 +1,5 @@
#include "toggle_button.h"
-#include <fmt/format.h>
-
#include "graph/graph.h"
#include "ui/animations/animation.h"
@@ -61,12 +59,13 @@ namespace cru::ui::controls
const auto time = total_time * (std::abs(delta) / (inner_circle_x * 2));
// ReSharper disable once CppExpressionWithoutSideEffects
- AnimationBuilder(fmt::format(L"ToggleButton {}", reinterpret_cast<size_t>(this)), time)
- .AddStepHandler(CreatePtr<animations::AnimationStepHandlerPtr>([=](animations::AnimationDelegatePtr, const double percentage)
- {
- current_circle_position_ = static_cast<float>(previous_position + delta * percentage);
- Repaint();
- })).Start();
+ AnimationBuilder(Format(L"ToggleButton {}", reinterpret_cast<size_t>(this)), time)
+ .AddStepHandler([=](auto, const double percentage)
+ {
+ current_circle_position_ = static_cast<float>(previous_position + delta * percentage);
+ Repaint();
+ })
+ .Start();
RaiseToggleEvent(state);
Repaint();
diff --git a/src/ui/layout_base.cpp b/src/ui/layout_base.cpp
index 40c7a724..0ffe3870 100644
--- a/src/ui/layout_base.cpp
+++ b/src/ui/layout_base.cpp
@@ -87,13 +87,14 @@ namespace cru::ui
void LayoutManager::RefreshControlPositionCacheInternal(Control * control, const Point & parent_lefttop_absolute)
{
const auto position = control->GetPositionRelative();
- Point lefttop(
+ const Point lefttop(
parent_lefttop_absolute.x + position.x,
parent_lefttop_absolute.y + position.y
);
control->position_cache_.lefttop_position_absolute = lefttop;
- control->ForeachChild([lefttop](Control* c) {
+ for(auto c : control->GetChildren())
+ {
RefreshControlPositionCacheInternal(c, lefttop);
- });
+ }
}
}
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index 8889e032..323a4307 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -1,7 +1,5 @@
#include "window.h"
-#include <fmt/format.h>
-
#include "application.h"
#include "graph/graph.h"
#include "exception.h"
@@ -77,9 +75,9 @@ namespace cru
return find_result->second;
}
- Vector<Window*> WindowManager::GetAllWindows() const
+ std::vector<Window*> WindowManager::GetAllWindows() const
{
- Vector<Window*> windows;
+ std::vector<Window*> windows;
for (auto [key, value] : window_map_)
windows.push_back(value);
return windows;
@@ -464,11 +462,10 @@ namespace cru
Size Window::OnMeasureContent(const Size& available_size)
{
- ForeachChild([available_size](Control* control)
+ for (auto control: GetChildren())
{
control->Measure(available_size);
- });
-
+ }
return available_size;
}
diff --git a/src/ui/window.h b/src/ui/window.h
index e4e89776..15b3db57 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -70,7 +70,7 @@ namespace cru {
//Return a pointer to the Window object related to the HWND or nullptr if the hwnd is not in the map.
Window* FromHandle(HWND hwnd);
- Vector<Window*> GetAllWindows() const;
+ std::vector<Window*> GetAllWindows() const;
private:
std::unique_ptr<WindowClass> general_window_class_;