diff options
Diffstat (limited to 'CruUI/ui/controls')
-rw-r--r-- | CruUI/ui/controls/linear_layout.h | 9 | ||||
-rw-r--r-- | CruUI/ui/controls/text_block.cpp | 10 | ||||
-rw-r--r-- | CruUI/ui/controls/text_block.h | 2 | ||||
-rw-r--r-- | CruUI/ui/controls/toggle_button.cpp | 123 | ||||
-rw-r--r-- | CruUI/ui/controls/toggle_button.h | 59 |
5 files changed, 193 insertions, 10 deletions
diff --git a/CruUI/ui/controls/linear_layout.h b/CruUI/ui/controls/linear_layout.h index 74c504cb..ead56081 100644 --- a/CruUI/ui/controls/linear_layout.h +++ b/CruUI/ui/controls/linear_layout.h @@ -18,9 +18,16 @@ namespace cru::ui::controls return new LinearLayout(orientation); } - private: + protected: explicit LinearLayout(Orientation orientation = Orientation::Vertical); + public: + LinearLayout(const LinearLayout& other) = delete; + LinearLayout(LinearLayout&& other) = delete; + LinearLayout& operator=(const LinearLayout& other) = delete; + LinearLayout& operator=(LinearLayout&& other) = delete; + ~LinearLayout() override = default; + protected: Size OnMeasure(const Size& available_size) override; void OnLayout(const Rect& rect) override; diff --git a/CruUI/ui/controls/text_block.cpp b/CruUI/ui/controls/text_block.cpp index a3dc23c5..beb799d3 100644 --- a/CruUI/ui/controls/text_block.cpp +++ b/CruUI/ui/controls/text_block.cpp @@ -11,19 +11,13 @@ namespace cru { namespace controls { + using graph::CreateSolidBrush; + inline Microsoft::WRL::ComPtr<IDWriteFactory> GetDWriteFactory() { return graph::GraphManager::GetInstance()->GetDWriteFactory(); } - Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> CreateSolidBrush(const D2D1_COLOR_F& color) - { - const auto device_context = graph::GraphManager::GetInstance()->GetD2D1DeviceContext(); - Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solid_color_brush; - device_context->CreateSolidColorBrush(color, &solid_color_brush); - return solid_color_brush; - } - TextBlock::TextBlock(const Microsoft::WRL::ComPtr<IDWriteTextFormat>& init_text_format, const Microsoft::WRL::ComPtr<ID2D1Brush>& init_brush) : Control(false) { diff --git a/CruUI/ui/controls/text_block.h b/CruUI/ui/controls/text_block.h index be2a1da2..db22e3c7 100644 --- a/CruUI/ui/controls/text_block.h +++ b/CruUI/ui/controls/text_block.h @@ -51,7 +51,7 @@ namespace cru return text_block; } - private: + protected: explicit TextBlock( const Microsoft::WRL::ComPtr<IDWriteTextFormat>& init_text_format = nullptr, const Microsoft::WRL::ComPtr<ID2D1Brush>& init_brush = nullptr diff --git a/CruUI/ui/controls/toggle_button.cpp b/CruUI/ui/controls/toggle_button.cpp new file mode 100644 index 00000000..ea2329ea --- /dev/null +++ b/CruUI/ui/controls/toggle_button.cpp @@ -0,0 +1,123 @@ +#include "toggle_button.h" + +#include "graph/graph.h" + +namespace cru::ui::controls +{ + using graph::CreateSolidBrush; + + // ui length parameters of toggle button. + constexpr float half_height = 15; + constexpr float half_width = half_height * 2; + constexpr float stroke_width = 3; + constexpr float inner_circle_radius = half_height - stroke_width; + constexpr float inner_circle_x = half_width - half_height; + + ToggleButton::ToggleButton() + { + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRoundedRectangleGeometry(D2D1::RoundedRect(D2D1::RectF(-half_width, -half_height, half_width, half_height), half_height, half_height), &frame_path_); + + on_brush_ = CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::LightBlue)); + off_brush_ = CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::LightGray)); + } + + inline D2D1_POINT_2F ConvertPoint(const Point& point) + { + return D2D1::Point2F(point.x, point.y); + } + + bool ToggleButton::IsPointInside(const Point& point) + { + const auto size = GetSize(); + const auto transform = D2D1::Matrix3x2F::Translation(size.width / 2, size.height / 2); + BOOL contains; + frame_path_->FillContainsPoint(ConvertPoint(point), transform, &contains); + if (!contains) + frame_path_->StrokeContainsPoint(ConvertPoint(point), stroke_width, nullptr, transform, &contains); + return contains != 0; + } + + void ToggleButton::SetState(const bool state) + { + if (state != state_) + { + state_ = state; + OnToggleInternal(state); + Repaint(); + } + } + + void ToggleButton::Toggle() + { + SetState(!GetState()); + } + + void ToggleButton::OnToggle(events::ToggleEventArgs& args) + { + + } + + void ToggleButton::OnDraw(ID2D1DeviceContext* device_context) + { + const auto size = GetSize(); + graph::WithTransform(device_context, D2D1::Matrix3x2F::Translation(size.width / 2, size.height / 2), [this](ID2D1DeviceContext* device_context) + { + if (state_) + { + device_context->DrawGeometry(frame_path_.Get(), on_brush_.Get(), stroke_width); + device_context->FillEllipse(D2D1::Ellipse(D2D1::Point2F(inner_circle_x, 0), inner_circle_radius, inner_circle_radius), on_brush_.Get()); + } + else + { + device_context->DrawGeometry(frame_path_.Get(), off_brush_.Get(), stroke_width); + device_context->FillEllipse(D2D1::Ellipse(D2D1::Point2F(-inner_circle_x, 0), inner_circle_radius, inner_circle_radius), off_brush_.Get()); + } + }); + } + + void ToggleButton::OnMouseClickCore(events::MouseButtonEventArgs& args) + { + Control::OnMouseClickCore(args); + Toggle(); + } + + Size ToggleButton::OnMeasure(const Size& available_size) + { + const auto layout_params = GetLayoutParams(); + + auto&& get_measure_length = [](const MeasureLength& layout_length, const float available_length, const float fix_length) -> float + { + switch (layout_length.mode) + { + case MeasureMode::Exactly: + { + return std::max(std::min(layout_length.length, available_length), fix_length); + } + case MeasureMode::Stretch: + { + return std::max(available_length, fix_length); + } + case MeasureMode::Content: + { + return fix_length; + } + default: + UnreachableCode(); + } + }; + + const Size result_size( + get_measure_length(layout_params->width, available_size.width, half_width * 2 + stroke_width), + get_measure_length(layout_params->height, available_size.height, half_height * 2 + stroke_width) + ); + + return result_size; + } + + void ToggleButton::OnToggleInternal(bool new_state) + { + events::ToggleEventArgs args(this, this, new_state); + OnToggle(args); + toggle_event.Raise(args); + } +} diff --git a/CruUI/ui/controls/toggle_button.h b/CruUI/ui/controls/toggle_button.h new file mode 100644 index 00000000..d2e49473 --- /dev/null +++ b/CruUI/ui/controls/toggle_button.h @@ -0,0 +1,59 @@ +#pragma once + +#include "ui/control.h" + +namespace cru::ui::controls +{ + class ToggleButton : public Control + { + public: + static ToggleButton* Create() + { + return new ToggleButton(); + } + + protected: + ToggleButton(); + + public: + ToggleButton(const ToggleButton& other) = delete; + ToggleButton(ToggleButton&& other) = delete; + ToggleButton& operator=(const ToggleButton& other) = delete; + ToggleButton& operator=(ToggleButton&& other) = delete; + ~ToggleButton() override = default; + + bool IsPointInside(const Point& point) override; + + bool GetState() const + { + return state_; + } + + void SetState(bool state); + + void Toggle(); + + public: + events::ToggleEvent toggle_event; + + protected: + virtual void OnToggle(events::ToggleEventArgs& args); + + protected: + void OnDraw(ID2D1DeviceContext* device_context) override; + + void OnMouseClickCore(events::MouseButtonEventArgs& args) override; + + Size OnMeasure(const Size& available_size) override; + + private: + void OnToggleInternal(bool new_state); + + private: + bool state_ = false; + + Microsoft::WRL::ComPtr<ID2D1RoundedRectangleGeometry> frame_path_; + Microsoft::WRL::ComPtr<ID2D1Brush> on_brush_; + Microsoft::WRL::ComPtr<ID2D1Brush> off_brush_; + }; +} |