diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/animations/animation.cpp | 114 | ||||
-rw-r--r-- | src/ui/animations/animation.h | 88 | ||||
-rw-r--r-- | src/ui/border_property.cpp | 31 | ||||
-rw-r--r-- | src/ui/border_property.h | 61 | ||||
-rw-r--r-- | src/ui/control.cpp | 102 | ||||
-rw-r--r-- | src/ui/control.h | 35 | ||||
-rw-r--r-- | src/ui/controls/button.cpp | 30 | ||||
-rw-r--r-- | src/ui/controls/button.h | 4 | ||||
-rw-r--r-- | src/ui/controls/linear_layout.cpp | 50 | ||||
-rw-r--r-- | src/ui/controls/text_box.cpp | 19 | ||||
-rw-r--r-- | src/ui/controls/text_box.h | 3 | ||||
-rw-r--r-- | src/ui/controls/text_control.cpp | 19 | ||||
-rw-r--r-- | src/ui/controls/text_control.h | 9 | ||||
-rw-r--r-- | src/ui/controls/toggle_button.cpp | 15 | ||||
-rw-r--r-- | src/ui/layout_base.cpp | 7 | ||||
-rw-r--r-- | src/ui/window.cpp | 11 | ||||
-rw-r--r-- | src/ui/window.h | 2 |
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, ¤t_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_; |