aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-03-02 22:07:33 +0800
committercrupest <crupest@outlook.com>2022-03-02 22:07:33 +0800
commit57353bd3acd97957cb5f970016fec52977cc6e95 (patch)
tree6e47a50f33466f7bcdce7c7aa9bf15b82fe4a58a /src
parent7adfe813c23d20abe936aa0624fd68e0112717b3 (diff)
downloadcru-57353bd3acd97957cb5f970016fec52977cc6e95.tar.gz
cru-57353bd3acd97957cb5f970016fec52977cc6e95.tar.bz2
cru-57353bd3acd97957cb5f970016fec52977cc6e95.zip
...
Diffstat (limited to 'src')
-rw-r--r--src/platform/graphics/Geometry.cpp11
-rw-r--r--src/theme_builder/components/conditions/CompoundConditionEditor.cpp16
-rw-r--r--src/theme_builder/components/conditions/CompoundConditionEditor.h5
-rw-r--r--src/ui/CMakeLists.txt3
-rw-r--r--src/ui/ThemeManager.cpp4
-rw-r--r--src/ui/components/PopupButton.cpp17
-rw-r--r--src/ui/controls/IconButton.cpp50
-rw-r--r--src/ui/mapper/MapperRegistry.cpp2
-rw-r--r--src/ui/mapper/StringMapper.cpp16
-rw-r--r--src/ui/render/BorderRenderObject.cpp12
-rw-r--r--src/ui/render/GeometryRenderObject.cpp110
-rw-r--r--src/ui/render/RenderObject.cpp13
12 files changed, 243 insertions, 16 deletions
diff --git a/src/platform/graphics/Geometry.cpp b/src/platform/graphics/Geometry.cpp
index d4d36eb4..389b97f5 100644
--- a/src/platform/graphics/Geometry.cpp
+++ b/src/platform/graphics/Geometry.cpp
@@ -1,8 +1,10 @@
#include "cru/platform/graphics/Geometry.h"
+#include "cru/common/Exception.h"
+#include "cru/platform/graphics/Factory.h"
+
#include <cmath>
#include <unordered_set>
-#include "cru/common/Exception.h"
namespace cru::platform::graphics {
constexpr float PI = 3.14159265358979323846f;
@@ -365,4 +367,11 @@ void IGeometryBuilder::ParseAndApplySvgPathData(StringView path_d) {
}
}
+std::unique_ptr<IGeometry> CreateGeometryFromSvgPathData(
+ IGraphicsFactory* factory, StringView path_d) {
+ auto builder = factory->CreateGeometryBuilder();
+ builder->ParseAndApplySvgPathData(path_d);
+ return builder->Build();
+}
+
} // namespace cru::platform::graphics
diff --git a/src/theme_builder/components/conditions/CompoundConditionEditor.cpp b/src/theme_builder/components/conditions/CompoundConditionEditor.cpp
index beede667..a0985eff 100644
--- a/src/theme_builder/components/conditions/CompoundConditionEditor.cpp
+++ b/src/theme_builder/components/conditions/CompoundConditionEditor.cpp
@@ -6,6 +6,7 @@
#include "NoConditionEditor.h"
#include "cru/common/ClonablePtr.h"
#include "cru/platform/Color.h"
+#include "cru/ui/Base.h"
#include "cru/ui/ThemeManager.h"
#include "cru/ui/controls/FlexLayout.h"
#include "cru/ui/style/Condition.h"
@@ -20,9 +21,11 @@ CompoundConditionEditorChild::CompoundConditionEditorChild(
remove_button_.GetStyleRuleSet()->SetParent(
ui::ThemeManager::GetInstance()->GetResourceStyleRuleSet(
u"cru.theme_builder.icon-button.style"));
- remove_button_.SetChild(&remove_button_text_);
- remove_button_text_.SetText(u"x");
- remove_button_text_.SetTextColor(ui::colors::red);
+ remove_button_.SetIconWithSvgPathDataStringResourceKey(u"icon.close",
+ {0, 0, 16, 16});
+ remove_button_.SetPreferredSize({24, 24});
+ remove_button_.SetPadding(ui::Thickness(4));
+ remove_button_.SetIconFillColor(ui::colors::red);
container_.AddChild(condition_editor_->GetRootControl());
@@ -44,8 +47,11 @@ CompoundConditionEditor::CompoundConditionEditor() {
add_child_button_.GetButton()->GetStyleRuleSet()->SetParent(
ui::ThemeManager::GetInstance()->GetResourceStyleRuleSet(
u"cru.theme_builder.icon-button.style"));
- add_child_button_.SetButtonText(u"+");
- add_child_button_.SetButtonTextColor(ui::colors::green);
+ add_child_button_.GetButton()->SetIconWithSvgPathDataStringResourceKey(
+ u"icon.plus-square", {0, 0, 16, 16});
+ add_child_button_.GetButton()->SetPreferredSize({24, 24});
+ add_child_button_.GetButton()->SetPadding(ui::Thickness(4));
+ add_child_button_.GetButton()->SetIconFillColor(ui::colors::green);
add_child_button_.SetMenuItems({u"And Condition", u"Or Condition",
u"Click State Condition", u"Focus Condition",
u"Checked Condition", u"No Condition"});
diff --git a/src/theme_builder/components/conditions/CompoundConditionEditor.h b/src/theme_builder/components/conditions/CompoundConditionEditor.h
index 471087ae..f80896c8 100644
--- a/src/theme_builder/components/conditions/CompoundConditionEditor.h
+++ b/src/theme_builder/components/conditions/CompoundConditionEditor.h
@@ -25,8 +25,7 @@ class CompoundConditionEditorChild : public ui::components::Component {
private:
ui::controls::FlexLayout container_;
- ui::controls::Button remove_button_;
- ui::controls::TextBlock remove_button_text_;
+ ui::controls::IconButton remove_button_;
std::unique_ptr<ConditionEditor> condition_editor_;
Event<std::nullptr_t> remove_event_;
@@ -43,7 +42,7 @@ class CompoundConditionEditor : public ConditionEditor {
bool trigger_change = true);
private:
- ui::components::PopupMenuTextButton add_child_button_;
+ ui::components::PopupMenuIconButton add_child_button_;
ui::controls::FlexLayout children_container_;
std::vector<std::unique_ptr<CompoundConditionEditorChild>> children_;
};
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index e3819800..ce67c12c 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -11,6 +11,7 @@ add_library(cru_ui SHARED
controls/Container.cpp
controls/Control.cpp
controls/FlexLayout.cpp
+ controls/IconButton.cpp
controls/NoChildControl.cpp
controls/Popup.cpp
controls/RootControl.cpp
@@ -37,6 +38,7 @@ add_library(cru_ui SHARED
mapper/MeasureLengthMapper.cpp
mapper/PointMapper.cpp
mapper/SizeMapper.cpp
+ mapper/StringMapper.cpp
mapper/ThicknessMapper.cpp
mapper/style/AndConditionMapper.cpp
mapper/style/BorderStylerMapper.cpp
@@ -55,6 +57,7 @@ add_library(cru_ui SHARED
render/BorderRenderObject.cpp
render/CanvasRenderObject.cpp
render/FlexLayoutRenderObject.cpp
+ render/GeometryRenderObject.cpp
render/LayoutHelper.cpp
render/RenderObject.cpp
render/ScrollBar.cpp
diff --git a/src/ui/ThemeManager.cpp b/src/ui/ThemeManager.cpp
index 1adbddaf..93dc9a9f 100644
--- a/src/ui/ThemeManager.cpp
+++ b/src/ui/ThemeManager.cpp
@@ -49,6 +49,10 @@ void ThemeManager::PrependThemeResourceDictionary(
theme_resource_change_event_.Raise(nullptr);
}
+String ThemeManager::GetResourceString(const String& key) {
+ return GetResource<String>(key);
+}
+
std::shared_ptr<platform::graphics::IBrush> ThemeManager::GetResourceBrush(
const String& key) {
return GetResource<std::shared_ptr<platform::graphics::IBrush>>(key);
diff --git a/src/ui/components/PopupButton.cpp b/src/ui/components/PopupButton.cpp
index f09bf2d1..41e0ad6c 100644
--- a/src/ui/components/PopupButton.cpp
+++ b/src/ui/components/PopupButton.cpp
@@ -21,4 +21,21 @@ void PopupMenuTextButton::SetMenuItems(std::vector<String> items) {
std::move(items[i]), [this, i] { menu_item_selected_event_.Raise(i); });
}
}
+
+PopupMenuIconButton::PopupMenuIconButton() : popup_menu_(&button_) {
+ button_.ClickEvent()->AddHandler([this](const helper::ClickEventArgs& args) {
+ popup_menu_.SetPosition(args.GetDownPointOfScreen());
+ popup_menu_.Show();
+ });
+}
+
+PopupMenuIconButton::~PopupMenuIconButton() {}
+
+void PopupMenuIconButton::SetMenuItems(std::vector<String> items) {
+ popup_menu_.GetMenu()->ClearItems();
+ for (Index i = 0; i < items.size(); i++) {
+ popup_menu_.GetMenu()->AddTextItem(
+ std::move(items[i]), [this, i] { menu_item_selected_event_.Raise(i); });
+ }
+}
} // namespace cru::ui::components
diff --git a/src/ui/controls/IconButton.cpp b/src/ui/controls/IconButton.cpp
new file mode 100644
index 00000000..01ecabdd
--- /dev/null
+++ b/src/ui/controls/IconButton.cpp
@@ -0,0 +1,50 @@
+#include "cru/ui/controls/IconButton.h"
+
+#include "../Helper.h"
+#include "cru/platform/graphics/Factory.h"
+#include "cru/platform/graphics/Geometry.h"
+#include "cru/ui/ThemeManager.h"
+
+namespace cru::ui::controls {
+IconButton::IconButton()
+ : container_render_object_(new render::BorderRenderObject()),
+ geometry_render_object_(new render::GeometryRenderObject()),
+ click_detector_(this) {
+ container_render_object_->SetChild(geometry_render_object_.get());
+ container_render_object_->SetAttachedControl(this);
+ geometry_render_object_->SetAttachedControl(this);
+
+ container_render_object_->SetBorderEnabled(true);
+ GetStyleRuleSet()->SetParent(
+ ThemeManager::GetInstance()->GetResourceStyleRuleSet(
+ u"icon-button.style"));
+}
+
+IconButton::IconButton(StringView icon_svg_path_data_string,
+ const Rect& view_port)
+ : IconButton() {
+ SetIconWithSvgPathDataString(icon_svg_path_data_string, view_port);
+}
+
+IconButton::~IconButton() {}
+
+void IconButton::SetIconFillColor(const Color& color) {
+ SetIconFillBrush(GetGraphicsFactory()->CreateSolidColorBrush(color));
+}
+
+void IconButton::SetIconWithSvgPathDataString(
+ StringView icon_svg_path_data_string, const Rect& view_port) {
+ SetIconGeometry(platform::graphics::CreateGeometryFromSvgPathData(
+ GetGraphicsFactory(), icon_svg_path_data_string),
+ view_port);
+}
+
+void IconButton::SetIconWithSvgPathDataStringResourceKey(
+ StringView icon_svg_path_data_string_resource_key, const Rect& view_port) {
+ SetIconWithSvgPathDataString(
+ ThemeManager::GetInstance()->GetResourceString(
+ icon_svg_path_data_string_resource_key.ToString()),
+ view_port);
+}
+
+} // namespace cru::ui::controls
diff --git a/src/ui/mapper/MapperRegistry.cpp b/src/ui/mapper/MapperRegistry.cpp
index ad5b7e8d..f599c1ed 100644
--- a/src/ui/mapper/MapperRegistry.cpp
+++ b/src/ui/mapper/MapperRegistry.cpp
@@ -8,6 +8,7 @@
#include "cru/ui/mapper/MeasureLengthMapper.h"
#include "cru/ui/mapper/PointMapper.h"
#include "cru/ui/mapper/SizeMapper.h"
+#include "cru/ui/mapper/StringMapper.h"
#include "cru/ui/mapper/ThicknessMapper.h"
#include "cru/ui/mapper/style/AndConditionMapper.h"
#include "cru/ui/mapper/style/BorderStylerMapper.h"
@@ -39,6 +40,7 @@ MapperRegistry::MapperRegistry() {
RegisterMapper(new MeasureLengthMapper());
RegisterMapper(new PointMapper());
RegisterMapper(new SizeMapper());
+ RegisterMapper(new StringMapper());
RegisterMapper(new ThicknessMapper());
RegisterMapper(new BorderStyleMapper());
RegisterMapper(new ColorMapper());
diff --git a/src/ui/mapper/StringMapper.cpp b/src/ui/mapper/StringMapper.cpp
new file mode 100644
index 00000000..9e73b7f1
--- /dev/null
+++ b/src/ui/mapper/StringMapper.cpp
@@ -0,0 +1,16 @@
+#include "cru/ui/mapper/StringMapper.h"
+#include "cru/xml/XmlNode.h"
+
+namespace cru::ui::mapper {
+StringMapper::StringMapper() { SetAllowedTags({u"String"}); }
+
+StringMapper::~StringMapper() {}
+
+String StringMapper::DoMapFromString(String str) { return std::move(str); }
+
+String StringMapper::DoMapFromXml(xml::XmlElementNode* node) {
+ auto value_attr = node->GetOptionalAttributeCaseInsensitive(u"value");
+ if (value_attr) return *value_attr;
+ return {};
+}
+} // namespace cru::ui::mapper
diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp
index 40ab506a..8e93e205 100644
--- a/src/ui/render/BorderRenderObject.cpp
+++ b/src/ui/render/BorderRenderObject.cpp
@@ -130,10 +130,16 @@ void BorderRenderObject::OnLayoutContent(const Rect& content_rect) {
void BorderRenderObject::OnResize(const Size& new_size) { RecreateGeometry(); }
-Thickness BorderRenderObject::GetOuterSpaceThickness() const {
+Thickness BorderRenderObject::GetTotalSpaceThickness() const {
return is_border_enabled_
- ? RenderObject::GetOuterSpaceThickness() + GetBorderThickness()
- : RenderObject::GetOuterSpaceThickness();
+ ? RenderObject::GetTotalSpaceThickness() + GetBorderThickness()
+ : RenderObject::GetTotalSpaceThickness();
+}
+
+Thickness BorderRenderObject::GetInnerSpaceThickness() const {
+ return is_border_enabled_
+ ? RenderObject::GetInnerSpaceThickness() + GetBorderThickness()
+ : RenderObject::GetInnerSpaceThickness();
}
Rect BorderRenderObject::GetPaddingRect() const {
diff --git a/src/ui/render/GeometryRenderObject.cpp b/src/ui/render/GeometryRenderObject.cpp
new file mode 100644
index 00000000..ea9b6e11
--- /dev/null
+++ b/src/ui/render/GeometryRenderObject.cpp
@@ -0,0 +1,110 @@
+#include "cru/ui/render/GeometryRenderObject.h"
+#include "cru/platform/graphics/Brush.h"
+#include "cru/platform/graphics/Geometry.h"
+#include "cru/platform/graphics/Painter.h"
+#include "cru/ui/render/RenderObject.h"
+
+namespace cru::ui::render {
+GeometryRenderObject::GeometryRenderObject() {}
+
+GeometryRenderObject::~GeometryRenderObject() {}
+
+std::shared_ptr<platform::graphics::IGeometry>
+GeometryRenderObject::GetGeometry() const {
+ return geometry_;
+}
+
+void GeometryRenderObject::SetGeometry(
+ std::shared_ptr<platform::graphics::IGeometry> geometry,
+ std::optional<Rect> view_port) {
+ geometry_ = std::move(geometry);
+ if (view_port) {
+ view_port_ = *view_port;
+ } else {
+ view_port_ = geometry_ ? geometry_->GetBounds() : Rect{};
+ }
+}
+
+Rect GeometryRenderObject::GetViewPort() const { return view_port_; }
+
+void GeometryRenderObject::SetViewPort(const Rect& view_port) {
+ view_port_ = view_port;
+ InvalidatePaint();
+}
+
+std::shared_ptr<platform::graphics::IBrush> GeometryRenderObject::GetFillBrush()
+ const {
+ return fill_brush_;
+}
+
+void GeometryRenderObject::SetFillBrush(
+ std::shared_ptr<platform::graphics::IBrush> brush) {
+ fill_brush_ = std::move(brush);
+ InvalidatePaint();
+}
+
+std::shared_ptr<platform::graphics::IBrush>
+GeometryRenderObject::GetStrokeBrush() const {
+ return stroke_brush_;
+}
+
+void GeometryRenderObject::SetStrokeBrush(
+ std::shared_ptr<platform::graphics::IBrush> brush) {
+ stroke_brush_ = std::move(brush);
+ InvalidatePaint();
+}
+
+float GeometryRenderObject::GetStrokeWidth() const { return stroke_width_; }
+
+void GeometryRenderObject::SetStrokeWidth(float width) {
+ stroke_width_ = width;
+ InvalidatePaint();
+}
+
+void GeometryRenderObject::Draw(platform::graphics::IPainter* painter) {
+ if (!geometry_) return;
+
+ painter->PushState();
+
+ auto content_rect = GetContentRect();
+
+ painter->ConcatTransform(Matrix::Translation(content_rect.GetLeftTop()));
+
+ painter->ConcatTransform(
+ Matrix::Translation(view_port_.GetLeftTop().Negate()) *
+ Matrix::Scale(content_rect.width / view_port_.width,
+ content_rect.height / view_port_.height));
+
+ if (fill_brush_) {
+ painter->FillGeometry(geometry_.get(), fill_brush_.get());
+ }
+
+ if (stroke_brush_ && stroke_width_) {
+ painter->StrokeGeometry(geometry_.get(), stroke_brush_.get(),
+ stroke_width_);
+ }
+
+ painter->PopState();
+}
+
+RenderObject* GeometryRenderObject::HitTest(const Point& point) {
+ return GetPaddingRect().IsPointInside(point) ? this : nullptr;
+}
+
+Size GeometryRenderObject::OnMeasureContent(
+ const MeasureRequirement& requirement, const MeasureSize& preferred_size) {
+ Size result = GetViewPort().GetSize();
+
+ if (preferred_size.width.IsSpecified()) {
+ result.width = preferred_size.width.GetLengthOrUndefined();
+ }
+
+ if (preferred_size.height.IsSpecified()) {
+ result.height = preferred_size.height.GetLengthOrUndefined();
+ }
+
+ return requirement.Coerce(result);
+}
+
+void GeometryRenderObject::OnLayoutContent(const Rect& content_rect) {}
+} // namespace cru::ui::render
diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp
index b6de5782..a2ecab8b 100644
--- a/src/ui/render/RenderObject.cpp
+++ b/src/ui/render/RenderObject.cpp
@@ -1,6 +1,7 @@
#include "cru/ui/render/RenderObject.h"
#include "cru/common/log/Logger.h"
+#include "cru/platform/GraphicsBase.h"
#include "cru/ui/DebugFlags.h"
#include "cru/ui/controls/Control.h"
#include "cru/ui/host/WindowHost.h"
@@ -109,13 +110,15 @@ void RenderObject::Layout(const Point& offset) {
OnLayoutCore();
}
-Thickness RenderObject::GetOuterSpaceThickness() const {
+Thickness RenderObject::GetTotalSpaceThickness() const {
return margin_ + padding_;
}
+Thickness RenderObject::GetInnerSpaceThickness() const { return padding_; }
+
Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) {
- const Thickness outer_space = GetOuterSpaceThickness();
+ const Thickness outer_space = GetTotalSpaceThickness();
const Size space_size{outer_space.GetHorizontalTotal(),
outer_space.GetVerticalTotal()};
@@ -124,8 +127,10 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
content_requirement.max = content_requirement.max.Minus(space_size);
content_requirement.min = content_requirement.min.Minus(space_size);
+ auto inner_space = GetInnerSpaceThickness();
MeasureSize content_preferred_size =
- content_requirement.Coerce(preferred_size.Minus(space_size));
+ content_requirement.Coerce(preferred_size.Minus(
+ {inner_space.GetHorizontalTotal(), inner_space.GetVerticalTotal()}));
const auto content_size =
OnMeasureContent(content_requirement, content_preferred_size);
@@ -135,7 +140,7 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
void RenderObject::OnLayoutCore() {
Size total_size = GetDesiredSize();
- const Thickness outer_space = GetOuterSpaceThickness();
+ const Thickness outer_space = GetTotalSpaceThickness();
const Size space_size{outer_space.GetHorizontalTotal(),
outer_space.GetVerticalTotal()};