aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CruUI/CruUI.vcxproj3
-rw-r--r--CruUI/CruUI.vcxproj.filters9
-rw-r--r--CruUI/graph/graph.cpp8
-rw-r--r--CruUI/graph/graph.h11
-rw-r--r--CruUI/main.cpp4
-rw-r--r--CruUI/ui/control.cpp2
-rw-r--r--CruUI/ui/control.h4
-rw-r--r--CruUI/ui/controls/linear_layout.h9
-rw-r--r--CruUI/ui/controls/text_block.cpp10
-rw-r--r--CruUI/ui/controls/text_block.h2
-rw-r--r--CruUI/ui/controls/toggle_button.cpp123
-rw-r--r--CruUI/ui/controls/toggle_button.h59
-rw-r--r--CruUI/ui/events/ui_event.h43
-rw-r--r--CruUI/ui/layout_base.cpp77
-rw-r--r--CruUI/ui/layout_base.h42
-rw-r--r--CruUI/ui/ui_base.h1
-rw-r--r--CruUI/ui/window.cpp66
-rw-r--r--CruUI/ui/window.h37
18 files changed, 386 insertions, 124 deletions
diff --git a/CruUI/CruUI.vcxproj b/CruUI/CruUI.vcxproj
index 7bf7eb98..4d2538d8 100644
--- a/CruUI/CruUI.vcxproj
+++ b/CruUI/CruUI.vcxproj
@@ -165,6 +165,7 @@
<ClInclude Include="global_macros.h" />
<ClInclude Include="ui\controls\linear_layout.h" />
<ClInclude Include="ui\controls\text_block.h" />
+ <ClInclude Include="ui\controls\toggle_button.h" />
<ClInclude Include="ui\events\ui_event.h" />
<ClInclude Include="ui\layout_base.h" />
<ClInclude Include="ui\window.h" />
@@ -173,12 +174,14 @@
<ItemGroup>
<ClCompile Include="application.cpp" />
<ClCompile Include="exception.cpp" />
+ <ClCompile Include="ui\layout_base.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="graph\graph.cpp" />
<ClCompile Include="timer.cpp" />
<ClCompile Include="ui\control.cpp" />
<ClCompile Include="ui\controls\linear_layout.cpp" />
<ClCompile Include="ui\controls\text_block.cpp" />
+ <ClCompile Include="ui\controls\toggle_button.cpp" />
<ClCompile Include="ui\events\ui_event.cpp" />
<ClCompile Include="ui\window.cpp" />
<ClCompile Include="ui\ui_base.cpp" />
diff --git a/CruUI/CruUI.vcxproj.filters b/CruUI/CruUI.vcxproj.filters
index ec7a6de9..64cb4299 100644
--- a/CruUI/CruUI.vcxproj.filters
+++ b/CruUI/CruUI.vcxproj.filters
@@ -63,6 +63,9 @@
<ClInclude Include="debug_base.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="ui\controls\toggle_button.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="application.cpp">
@@ -98,5 +101,11 @@
<ClCompile Include="ui\controls\linear_layout.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="ui\controls\toggle_button.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ui\layout_base.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/CruUI/graph/graph.cpp b/CruUI/graph/graph.cpp
index 00d5137d..94c7029e 100644
--- a/CruUI/graph/graph.cpp
+++ b/CruUI/graph/graph.cpp
@@ -213,5 +213,13 @@ namespace cru {
d2d1_factory_->ReloadSystemMetrics()
);
}
+
+ ComPtr<ID2D1SolidColorBrush> CreateSolidBrush(const D2D1_COLOR_F& color)
+ {
+ const auto device_context = graph::GraphManager::GetInstance()->GetD2D1DeviceContext();
+ ComPtr<ID2D1SolidColorBrush> solid_color_brush;
+ device_context->CreateSolidColorBrush(color, &solid_color_brush);
+ return solid_color_brush;
+ }
}
}
diff --git a/CruUI/graph/graph.h b/CruUI/graph/graph.h
index 990b51b3..fd062787 100644
--- a/CruUI/graph/graph.h
+++ b/CruUI/graph/graph.h
@@ -164,5 +164,16 @@ namespace cru
{
return graph_manager_->GetD2D1DeviceContext();
}
+
+ 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)
+ {
+ D2D1_MATRIX_3X2_F old_transform;
+ device_context->GetTransform(&old_transform);
+ device_context->SetTransform(old_transform * matrix);
+ action(device_context);
+ device_context->SetTransform(old_transform);
+ }
}
}
diff --git a/CruUI/main.cpp b/CruUI/main.cpp
index 0d1b4032..8e7a8672 100644
--- a/CruUI/main.cpp
+++ b/CruUI/main.cpp
@@ -2,12 +2,14 @@
#include "ui/window.h"
#include "ui/controls/linear_layout.h"
#include "ui/controls/text_block.h"
+#include "ui/controls/toggle_button.h"
using cru::Application;
using cru::ui::Window;
using cru::ui::controls::LinearLayout;
using cru::ui::controls::TextBlock;
+using cru::ui::controls::ToggleButton;
int APIENTRY wWinMain(
@@ -75,6 +77,8 @@ int APIENTRY wWinMain(
layout->AddChild(TextBlock::Create(L"Layout is clicked!"));
});
+ layout->AddChild(ToggleButton::Create());
+
const auto text_block = TextBlock::Create(L"Hello World!!!");
text_block->mouse_click_event.AddHandler([layout](cru::ui::events::MouseButtonEventArgs& args)
diff --git a/CruUI/ui/control.cpp b/CruUI/ui/control.cpp
index 7a705b4b..d2864fce 100644
--- a/CruUI/ui/control.cpp
+++ b/CruUI/ui/control.cpp
@@ -169,9 +169,9 @@ namespace cru {
if (old_position_ == position) // if cache has been refreshed and no pending notify
old_position_ = position_;
position_ = position;
+ LayoutManager::GetInstance()->InvalidateControlPositionCache(this);
if (auto window = GetWindow())
{
- window->GetLayoutManager()->InvalidateControlPositionCache(this);
window->Repaint();
}
}
diff --git a/CruUI/ui/control.h b/CruUI/ui/control.h
index b889fcd5..ca2dfb84 100644
--- a/CruUI/ui/control.h
+++ b/CruUI/ui/control.h
@@ -28,7 +28,7 @@ namespace cru
class Control : public Object
{
friend class Window;
- friend class WindowLayoutManager;
+ friend class LayoutManager;
protected:
struct WindowConstructorTag {}; //Used for constructor for class Window.
@@ -123,7 +123,7 @@ namespace cru
//Absolute point to local point.
Point AbsoluteToLocal(const Point& point) const;
- bool IsPointInside(const Point& point);
+ virtual bool IsPointInside(const Point& point);
//*************** region: graphic ***************
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_;
+ };
+}
diff --git a/CruUI/ui/events/ui_event.h b/CruUI/ui/events/ui_event.h
index ddf5f99f..4915d63d 100644
--- a/CruUI/ui/events/ui_event.h
+++ b/CruUI/ui/events/ui_event.h
@@ -46,7 +46,7 @@ namespace cru
MouseEventArgs(Object* sender, Object* original_sender, const std::optional<Point>& point = std::nullopt)
: UiEventArgs(sender, original_sender), point_(point)
{
-
+
}
MouseEventArgs(const MouseEventArgs& other) = default;
MouseEventArgs(MouseEventArgs&& other) = default;
@@ -67,7 +67,7 @@ namespace cru
MouseButtonEventArgs(Object* sender, Object* original_sender, const Point& point, const MouseButton button)
: MouseEventArgs(sender, original_sender, point), button_(button)
{
-
+
}
MouseButtonEventArgs(const MouseButtonEventArgs& other) = default;
MouseButtonEventArgs(MouseButtonEventArgs&& other) = default;
@@ -91,7 +91,7 @@ namespace cru
DrawEventArgs(Object* sender, Object* original_sender, ID2D1DeviceContext* device_context)
: UiEventArgs(sender, original_sender), device_context_(device_context)
{
-
+
}
DrawEventArgs(const DrawEventArgs& other) = default;
DrawEventArgs(DrawEventArgs&& other) = default;
@@ -115,7 +115,7 @@ namespace cru
PositionChangedEventArgs(Object* sender, Object* original_sender, const Point& old_position, const Point& new_position)
: UiEventArgs(sender, original_sender), old_position_(old_position), new_position_(new_position)
{
-
+
}
PositionChangedEventArgs(const PositionChangedEventArgs& other) = default;
PositionChangedEventArgs(PositionChangedEventArgs&& other) = default;
@@ -145,7 +145,7 @@ namespace cru
SizeChangedEventArgs(Object* sender, Object* original_sender, const Size& old_size, const Size& new_size)
: UiEventArgs(sender, original_sender), old_size_(old_size), new_size_(new_size)
{
-
+
}
SizeChangedEventArgs(const SizeChangedEventArgs& other) = default;
SizeChangedEventArgs(SizeChangedEventArgs&& other) = default;
@@ -171,10 +171,10 @@ namespace cru
class FocusChangeEventArgs : public UiEventArgs
{
public:
- FocusChangeEventArgs(Object* sender, Object* original_sender, const bool is_window =false)
- : UiEventArgs(sender, original_sender), is_window_(is_window)
+ FocusChangeEventArgs(Object* sender, Object* original_sender, const bool is_window = false)
+ : UiEventArgs(sender, original_sender), is_window_(is_window)
{
-
+
}
FocusChangeEventArgs(const FocusChangeEventArgs& other) = default;
FocusChangeEventArgs(FocusChangeEventArgs&& other) = default;
@@ -192,6 +192,30 @@ namespace cru
bool is_window_;
};
+ class ToggleEventArgs : public UiEventArgs
+ {
+ public:
+ ToggleEventArgs(Object* sender, Object* original_sender, bool new_state)
+ : UiEventArgs(sender, original_sender), new_state_(new_state)
+ {
+
+ }
+ ToggleEventArgs(const ToggleEventArgs& other) = default;
+ ToggleEventArgs(ToggleEventArgs&& other) = default;
+ ToggleEventArgs& operator=(const ToggleEventArgs& other) = default;
+ ToggleEventArgs& operator=(ToggleEventArgs&& other) = default;
+ ~ToggleEventArgs() override = default;
+
+ bool GetNewState() const
+ {
+ return new_state_;
+ }
+
+ private:
+ bool new_state_;
+ };
+
+
using UiEvent = Event<UiEventArgs>;
using MouseEvent = Event<MouseEventArgs>;
using MouseButtonEvent = Event<MouseButtonEventArgs>;
@@ -199,6 +223,7 @@ namespace cru
using PositionChangedEvent = Event<PositionChangedEventArgs>;
using SizeChangedEvent = Event<SizeChangedEventArgs>;
using FocusChangeEvent = Event<FocusChangeEventArgs>;
+ using ToggleEvent = Event<ToggleEventArgs>;
}
}
-}
+} \ No newline at end of file
diff --git a/CruUI/ui/layout_base.cpp b/CruUI/ui/layout_base.cpp
new file mode 100644
index 00000000..f04d1fe8
--- /dev/null
+++ b/CruUI/ui/layout_base.cpp
@@ -0,0 +1,77 @@
+#include "layout_base.h"
+
+#include "application.h"
+#include "control.h"
+
+namespace cru::ui
+{
+ LayoutManager* LayoutManager::GetInstance()
+ {
+ static LayoutManager layout_manager;
+ return &layout_manager;
+ }
+
+ void LayoutManager::InvalidateControlPositionCache(Control * control)
+ {
+ if (cache_invalid_controls_.count(control) == 1)
+ return;
+
+ // find descendant then erase it; find ancestor then just return.
+ for (auto i = cache_invalid_controls_.cbegin(); i != cache_invalid_controls_.cend(); ++i)
+ {
+ const auto result = IsAncestorOrDescendant(*i, control);
+ if (result == control)
+ cache_invalid_controls_.erase(i);
+ else if (result != nullptr)
+ return; // find a ancestor of "control", just return
+ }
+
+ cache_invalid_controls_.insert(control);
+
+ if (cache_invalid_controls_.size() == 1) // when insert just now and not repeat to "InvokeLater".
+ {
+ InvokeLater([this] {
+
+ RefreshInvalidControlPositionCache(); // first refresh position cache.
+ for (const auto i : cache_invalid_controls_) // traverse all descendants of position-invalid controls and notify position change event
+ i->TraverseDescendants([](Control* control)
+ {
+ control->CheckAndNotifyPositionChanged();
+ });
+ cache_invalid_controls_.clear(); // after update and notify, clear the set.
+
+ });
+ }
+ }
+
+ void LayoutManager::RefreshInvalidControlPositionCache()
+ {
+ for (const auto i : cache_invalid_controls_)
+ RefreshControlPositionCache(i);
+ }
+
+ void LayoutManager::RefreshControlPositionCache(Control * control)
+ {
+ auto point = Point::zero;
+ auto parent = control;
+ while ((parent = parent->GetParent())) {
+ const auto p = parent->GetPositionRelative();
+ point.x += p.x;
+ point.y += p.y;
+ }
+ RefreshControlPositionCacheInternal(control, point);
+ }
+
+ void LayoutManager::RefreshControlPositionCacheInternal(Control * control, const Point & parent_lefttop_absolute)
+ {
+ const auto position = control->GetPositionRelative();
+ 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) {
+ RefreshControlPositionCacheInternal(c, lefttop);
+ });
+ }
+}
diff --git a/CruUI/ui/layout_base.h b/CruUI/ui/layout_base.h
index bae01949..08f36769 100644
--- a/CruUI/ui/layout_base.h
+++ b/CruUI/ui/layout_base.h
@@ -1,9 +1,18 @@
#pragma once
+#include "system_headers.h"
+#include <unordered_set>
+
+#include "base.h"
+#include "ui_base.h"
+
namespace cru
{
namespace ui
{
+ class Control;
+
+
enum class MeasureMode
{
Exactly,
@@ -66,5 +75,38 @@ namespace cru
MeasureLength width;
MeasureLength height;
};
+
+
+ class LayoutManager : public Object
+ {
+ public:
+ static LayoutManager* GetInstance();
+
+ public:
+ LayoutManager() = default;
+ LayoutManager(const LayoutManager& other) = delete;
+ LayoutManager(LayoutManager&& other) = delete;
+ LayoutManager& operator=(const LayoutManager& other) = delete;
+ LayoutManager& operator=(LayoutManager&& other) = delete;
+ ~LayoutManager() override = default;
+
+ //Mark position cache of the control and its descendants invalid,
+ //(which is saved as an auto-managed list internal)
+ //and send a message to refresh them.
+ void InvalidateControlPositionCache(Control* control);
+
+ //Refresh position cache of the control and its descendants whose cache
+ //has been marked as invalid.
+ void RefreshInvalidControlPositionCache();
+
+ //Refresh position cache of the control and its descendants immediately.
+ static void RefreshControlPositionCache(Control* control);
+
+ private:
+ static void RefreshControlPositionCacheInternal(Control* control, const Point& parent_lefttop_absolute);
+
+ private:
+ std::unordered_set<Control*> cache_invalid_controls_;
+ };
}
}
diff --git a/CruUI/ui/ui_base.h b/CruUI/ui/ui_base.h
index 15847c1d..8ce82cdf 100644
--- a/CruUI/ui/ui_base.h
+++ b/CruUI/ui/ui_base.h
@@ -1,5 +1,6 @@
#pragma once
+
namespace cru
{
namespace ui
diff --git a/CruUI/ui/window.cpp b/CruUI/ui/window.cpp
index e09b150e..3f9d9f6c 100644
--- a/CruUI/ui/window.cpp
+++ b/CruUI/ui/window.cpp
@@ -77,70 +77,6 @@ namespace cru
return find_result->second;
}
- void WindowLayoutManager::InvalidateControlPositionCache(Control * control)
- {
- if (cache_invalid_controls_.count(control) == 1)
- return;
-
- // find descendant then erase it; find ancestor then just return.
- for (auto i = cache_invalid_controls_.cbegin(); i != cache_invalid_controls_.cend(); ++i)
- {
- const auto result = IsAncestorOrDescendant(*i, control);
- if (result == control)
- cache_invalid_controls_.erase(i);
- else if (result != nullptr)
- return; // find a ancestor of "control", just return
- }
-
- cache_invalid_controls_.insert(control);
-
- if (cache_invalid_controls_.size() == 1) // when insert just now and not repeat to "InvokeLater".
- {
- InvokeLater([this] {
-
- RefreshInvalidControlPositionCache(); // first refresh position cache.
- for (const auto i : cache_invalid_controls_) // traverse all descendants of position-invalid controls and notify position change event
- i->TraverseDescendants([](Control* control)
- {
- control->CheckAndNotifyPositionChanged();
- });
- cache_invalid_controls_.clear(); // after update and notify, clear the set.
-
- });
- }
- }
-
- void WindowLayoutManager::RefreshInvalidControlPositionCache()
- {
- for (const auto i : cache_invalid_controls_)
- RefreshControlPositionCache(i);
- }
-
- void WindowLayoutManager::RefreshControlPositionCache(Control * control)
- {
- auto point = Point::zero;
- auto parent = control;
- while ((parent = parent->GetParent())) {
- const auto p = parent->GetPositionRelative();
- point.x += p.x;
- point.y += p.y;
- }
- RefreshControlPositionCacheInternal(control, point);
- }
-
- void WindowLayoutManager::RefreshControlPositionCacheInternal(Control * control, const Point & parent_lefttop_absolute)
- {
- const auto position = control->GetPositionRelative();
- 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) {
- RefreshControlPositionCacheInternal(c, lefttop);
- });
- }
-
inline Point PiToDip(const POINT& pi_point)
{
return Point(
@@ -149,7 +85,7 @@ namespace cru
);
}
- Window::Window() : Control(WindowConstructorTag{}, this), layout_manager_(new WindowLayoutManager()), control_list_({ this }) {
+ Window::Window() : Control(WindowConstructorTag{}, this), control_list_({ this }) {
const auto app = Application::GetInstance();
hwnd_ = CreateWindowEx(0,
app->GetWindowManager()->GetGeneralWindowClass()->GetName(),
diff --git a/CruUI/ui/window.h b/CruUI/ui/window.h
index 92b084e1..790e3c32 100644
--- a/CruUI/ui/window.h
+++ b/CruUI/ui/window.h
@@ -76,34 +76,6 @@ namespace cru {
};
- class WindowLayoutManager : public Object
- {
- public:
- WindowLayoutManager() = default;
- WindowLayoutManager(const WindowLayoutManager& other) = delete;
- WindowLayoutManager(WindowLayoutManager&& other) = delete;
- WindowLayoutManager& operator=(const WindowLayoutManager& other) = delete;
- WindowLayoutManager& operator=(WindowLayoutManager&& other) = delete;
- ~WindowLayoutManager() override = default;
-
- //Mark position cache of the control and its descendants invalid,
- //(which is saved as an auto-managed list internal)
- //and send a message to refresh them.
- void InvalidateControlPositionCache(Control* control);
-
- //Refresh position cache of the control and its descendants whose cache
- //has been marked as invalid.
- void RefreshInvalidControlPositionCache();
-
- //Refresh position cache of the control and its descendants immediately.
- static void RefreshControlPositionCache(Control* control);
-
- private:
- static void RefreshControlPositionCacheInternal(Control* control, const Point& parent_lefttop_absolute);
-
- private:
- std::set<Control*> cache_invalid_controls_;
- };
class Window : public Control
{
@@ -117,13 +89,6 @@ namespace cru {
~Window() override;
public:
- //*************** region: managers ***************
- WindowLayoutManager* GetLayoutManager() const
- {
- return layout_manager_.get();
- }
-
-
//*************** region: handle ***************
//Get the handle of the window. Return null if window is invalid.
@@ -273,8 +238,6 @@ namespace cru {
void DispatchMouseHoverControlChangeEvent(Control* old_control, Control * new_control, const Point& point);
private:
- std::unique_ptr<WindowLayoutManager> layout_manager_;
-
HWND hwnd_ = nullptr;
std::shared_ptr<graph::WindowRenderTarget> render_target_{};