diff options
| author | Yuqian Yang <crupest@crupest.life> | 2025-12-15 22:05:52 +0800 |
|---|---|---|
| committer | Yuqian Yang <crupest@crupest.life> | 2025-12-15 22:05:52 +0800 |
| commit | 6bbadfc6b1eaf14f68a27cb8e378f5e09ab38de6 (patch) | |
| tree | dbfdb1ed836d8e9f2692ecd52b3f8576808cef1b | |
| parent | c77072d586bf7aca58e6465ceab3d11a0be0021f (diff) | |
| download | cru-6bbadfc6b1eaf14f68a27cb8e378f5e09ab38de6.tar.gz cru-6bbadfc6b1eaf14f68a27cb8e378f5e09ab38de6.tar.bz2 cru-6bbadfc6b1eaf14f68a27cb8e378f5e09ab38de6.zip | |
| -rw-r--r-- | include/cru/ui/mapper/Mapper.h | 39 | ||||
| -rw-r--r-- | src/ui/mapper/ColorMapper.cpp | 10 | ||||
| -rw-r--r-- | src/ui/mapper/CursorMapper.cpp | 6 | ||||
| -rw-r--r-- | src/ui/mapper/MeasureLengthMapper.cpp | 4 | ||||
| -rw-r--r-- | src/ui/mapper/PointMapper.cpp | 4 | ||||
| -rw-r--r-- | src/ui/mapper/SizeMapper.cpp | 6 | ||||
| -rw-r--r-- | src/ui/mapper/StringMapper.cpp | 4 | ||||
| -rw-r--r-- | src/ui/mapper/ThicknessMapper.cpp | 4 |
8 files changed, 43 insertions, 34 deletions
diff --git a/include/cru/ui/mapper/Mapper.h b/include/cru/ui/mapper/Mapper.h index 68ad2ab0..e9e7b851 100644 --- a/include/cru/ui/mapper/Mapper.h +++ b/include/cru/ui/mapper/Mapper.h @@ -6,7 +6,7 @@ #include <cru/base/xml/XmlNode.h> #include <memory> -#include <type_traits> +#include <optional> #include <typeindex> namespace cru::ui::mapper { @@ -35,12 +35,9 @@ class CRU_UI_API MapperBase : public Object { template <typename T> class CRU_UI_API BasicMapper : public MapperBase { public: - static_assert(std::is_default_constructible_v<T>, - "T must be default constructible."); - BasicMapper() : MapperBase(typeid(T)) {} - virtual T MapFromString(std::string str) { + T MapFromString(std::string str) { if (!SupportMapFromString()) { throw Exception("This mapper does not support map from string."); } @@ -61,8 +58,36 @@ class CRU_UI_API BasicMapper : public MapperBase { } protected: - virtual T DoMapFromString(std::string str) { return {}; } - virtual T DoMapFromXml(xml::XmlElementNode* node) { return {}; } + virtual T DoMapFromString(std::string str) { NotImplemented(); } + virtual T DoMapFromXml(xml::XmlElementNode* node) { NotImplemented(); } + + T MapFromXmlAsStringValue(xml::XmlElementNode* node, + std::optional<T> default_value = std::nullopt) { + std::optional<T>& value = default_value; + + auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); + if (value_attr) { + value = DoMapFromString(*value_attr); + } + + for (auto child : node->GetChildren()) { + if (child->IsElementNode()) { + throw MapException("XML node can't contain element child."); + } else if (auto c = child->AsText()) { + auto text = c->GetText(); + if (!text.empty() && value.has_value()) { + throw MapException("XML node has multiple values specified."); + } + value = DoMapFromString(text); + } + } + + if (!value.has_value()) { + throw MapException("XML node has no value specified."); + } + + return *value; + } }; template <typename T> diff --git a/src/ui/mapper/ColorMapper.cpp b/src/ui/mapper/ColorMapper.cpp index 9283b828..0fd0731b 100644 --- a/src/ui/mapper/ColorMapper.cpp +++ b/src/ui/mapper/ColorMapper.cpp @@ -11,19 +11,15 @@ Color ColorMapper::DoMapFromString(std::string str) { } Color ColorMapper::DoMapFromXml(xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - Color result = colors::transparent; - if (value_attr) { - result = DoMapFromString(*value_attr); - } + auto value = MapFromXmlAsStringValue(node, colors::transparent); auto alpha_value_attr = node->GetOptionalAttributeValueCaseInsensitive("alpha"); if (alpha_value_attr) { - result.alpha = + value.alpha = cru::string::ParseToNumber<double>(*alpha_value_attr).value * 255; } - return result; + return value; } } // namespace cru::ui::mapper diff --git a/src/ui/mapper/CursorMapper.cpp b/src/ui/mapper/CursorMapper.cpp index c7a8d4fc..00b94b91 100644 --- a/src/ui/mapper/CursorMapper.cpp +++ b/src/ui/mapper/CursorMapper.cpp @@ -19,13 +19,11 @@ std::shared_ptr<ICursor> CursorMapper::DoMapFromString(std::string str) { } else if (cru::string::CaseInsensitiveCompare(str, "ibeam") == 0) { return cursor_manager->GetSystemCursor(SystemCursorType::IBeam); } else { - throw Exception("Unsupported cursor type."); + throw MapException("Unknown cursor name."); } } std::shared_ptr<ICursor> CursorMapper::DoMapFromXml(xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - if (!value_attr) return nullptr; - return DoMapFromString(*value_attr); + return MapFromXmlAsStringValue(node, nullptr); } } // namespace cru::ui::mapper diff --git a/src/ui/mapper/MeasureLengthMapper.cpp b/src/ui/mapper/MeasureLengthMapper.cpp index b695ebae..f35e65d2 100644 --- a/src/ui/mapper/MeasureLengthMapper.cpp +++ b/src/ui/mapper/MeasureLengthMapper.cpp @@ -19,8 +19,6 @@ render::MeasureLength MeasureLengthMapper::DoMapFromString(std::string str) { render::MeasureLength MeasureLengthMapper::DoMapFromXml( xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - if (!value_attr) return {}; - return DoMapFromString(*value_attr); + return MapFromXmlAsStringValue(node, render::MeasureLength::NotSpecified()); } } // namespace cru::ui::mapper diff --git a/src/ui/mapper/PointMapper.cpp b/src/ui/mapper/PointMapper.cpp index 3bfe03e2..5311522a 100644 --- a/src/ui/mapper/PointMapper.cpp +++ b/src/ui/mapper/PointMapper.cpp @@ -14,8 +14,6 @@ Point PointMapper::DoMapFromString(std::string str) { } Point PointMapper::DoMapFromXml(xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - if (!value_attr) return {}; - return DoMapFromString(*value_attr); + return MapFromXmlAsStringValue(node, Point{}); } } // namespace cru::ui::mapper diff --git a/src/ui/mapper/SizeMapper.cpp b/src/ui/mapper/SizeMapper.cpp index 6161f226..fdf54324 100644 --- a/src/ui/mapper/SizeMapper.cpp +++ b/src/ui/mapper/SizeMapper.cpp @@ -9,13 +9,11 @@ Size SizeMapper::DoMapFromString(std::string str) { } else if (values.size() == 1) { return {values[0], values[0]}; } else { - throw Exception("Invalid Point string."); + throw Exception("Invalid Size string."); } } Size SizeMapper::DoMapFromXml(xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - if (!value_attr) return {}; - return DoMapFromString(*value_attr); + return MapFromXmlAsStringValue(node, Size{}); } } // namespace cru::ui::mapper diff --git a/src/ui/mapper/StringMapper.cpp b/src/ui/mapper/StringMapper.cpp index a021de3a..193dc464 100644 --- a/src/ui/mapper/StringMapper.cpp +++ b/src/ui/mapper/StringMapper.cpp @@ -7,8 +7,6 @@ std::string StringMapper::DoMapFromString(std::string str) { } std::string StringMapper::DoMapFromXml(xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - if (value_attr) return *value_attr; - return {}; + return MapFromXmlAsStringValue(node, ""); } } // namespace cru::ui::mapper diff --git a/src/ui/mapper/ThicknessMapper.cpp b/src/ui/mapper/ThicknessMapper.cpp index ca062ddc..89bb2d98 100644 --- a/src/ui/mapper/ThicknessMapper.cpp +++ b/src/ui/mapper/ThicknessMapper.cpp @@ -18,8 +18,6 @@ Thickness ThicknessMapper::DoMapFromString(std::string str) { } Thickness ThicknessMapper::DoMapFromXml(xml::XmlElementNode* node) { - auto value_attr = node->GetOptionalAttributeValueCaseInsensitive("value"); - if (!value_attr) throw Exception("Thickness must have a 'value' attribute."); - return DoMapFromString(*value_attr); + return MapFromXmlAsStringValue(node, Thickness{}); } } // namespace cru::ui::mapper |
