aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/osx/graphics/quartz/Font.h2
-rw-r--r--include/cru/platform/graphics/Font.h1
-rw-r--r--include/cru/ui/components/Input.h77
-rw-r--r--src/osx/graphics/quartz/Font.cpp3
-rw-r--r--src/theme_builder/CMakeLists.txt1
-rw-r--r--src/theme_builder/components/properties/FontPropertyEditor.cpp19
-rw-r--r--src/theme_builder/components/properties/FontPropertyEditor.h3
-rw-r--r--src/ui/CMakeLists.txt1
-rw-r--r--src/ui/components/Input.cpp94
9 files changed, 195 insertions, 6 deletions
diff --git a/include/cru/osx/graphics/quartz/Font.h b/include/cru/osx/graphics/quartz/Font.h
index d53c6a20..50703dfe 100644
--- a/include/cru/osx/graphics/quartz/Font.h
+++ b/include/cru/osx/graphics/quartz/Font.h
@@ -17,9 +17,11 @@ class OsxCTFont : public OsxQuartzResource, public virtual IFont {
CTFontRef GetCTFont() const { return ct_font_; }
+ String GetFontName() override;
float GetFontSize() override;
private:
+ String name_;
CTFontRef ct_font_;
};
} // namespace cru::platform::graphics::osx::quartz
diff --git a/include/cru/platform/graphics/Font.h b/include/cru/platform/graphics/Font.h
index 24c35f7c..7144fdc2 100644
--- a/include/cru/platform/graphics/Font.h
+++ b/include/cru/platform/graphics/Font.h
@@ -3,6 +3,7 @@
namespace cru::platform::graphics {
struct CRU_PLATFORM_GRAPHICS_API IFont : virtual IGraphicsResource {
+ virtual String GetFontName() = 0;
virtual float GetFontSize() = 0;
};
} // namespace cru::platform::graphics
diff --git a/include/cru/ui/components/Input.h b/include/cru/ui/components/Input.h
new file mode 100644
index 00000000..e808afd7
--- /dev/null
+++ b/include/cru/ui/components/Input.h
@@ -0,0 +1,77 @@
+#pragma once
+#include "../controls/TextBox.h"
+#include "Component.h"
+
+namespace cru::ui::components {
+struct CRU_UI_API InputValidateResult {
+ bool valid;
+ String message;
+};
+
+struct CRU_UI_API IInputValidator : public virtual Interface {
+ virtual InputValidateResult Validate(StringView text) const = 0;
+};
+
+struct CRU_UI_API InputChangeEventArgs {
+ String text;
+ bool valid;
+ String message;
+};
+
+class CRU_UI_API Input : public Component {
+ public:
+ Input();
+ ~Input() override;
+
+ public:
+ controls::Control* GetRootControl() override;
+
+ String GetText() const;
+ void SetText(String text);
+
+ IInputValidator* GetValidator() const;
+ void SetValidator(IInputValidator* validator);
+
+ InputValidateResult Validate();
+ InputValidateResult GetLastValidateResult() const;
+
+ IEvent<InputChangeEventArgs>* ChangeEvent() { return &change_event_; }
+
+ private:
+ controls::TextBox text_box_;
+ IInputValidator* validator_;
+ InputValidateResult last_validate_result_;
+
+ Event<InputChangeEventArgs> change_event_;
+};
+
+class CRU_UI_API FloatInputValidator : public Object,
+ public virtual IInputValidator {
+ public:
+ InputValidateResult Validate(StringView text) const override;
+
+ std::optional<float> min;
+ std::optional<float> max;
+};
+
+class CRU_UI_API FloatInput : public Input {
+ public:
+ FloatInput();
+ ~FloatInput() override;
+
+ public:
+ float GetValue() const;
+ void SetValue(float value);
+
+ std::optional<float> GetMax() const;
+ void SetMax(std::optional<float> max);
+
+ std::optional<float> GetMin() const;
+ void SetMin(std::optional<float> min);
+
+ private:
+ float value_;
+
+ FloatInputValidator validator_;
+};
+} // namespace cru::ui::components
diff --git a/src/osx/graphics/quartz/Font.cpp b/src/osx/graphics/quartz/Font.cpp
index 605a1453..a1b8bac2 100644
--- a/src/osx/graphics/quartz/Font.cpp
+++ b/src/osx/graphics/quartz/Font.cpp
@@ -9,7 +9,7 @@ using cru::platform::osx::Convert;
OsxCTFont::OsxCTFont(IGraphicsFactory* graphics_factory, const String& name,
float size)
- : OsxQuartzResource(graphics_factory) {
+ : OsxQuartzResource(graphics_factory), name_(name) {
CFStringRef n = Convert(name);
if (name.empty()) {
@@ -25,5 +25,6 @@ OsxCTFont::OsxCTFont(IGraphicsFactory* graphics_factory, const String& name,
OsxCTFont::~OsxCTFont() { CFRelease(ct_font_); }
+String OsxCTFont::GetFontName() { return name_; }
float OsxCTFont::GetFontSize() { return CTFontGetSize(ct_font_); }
} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/theme_builder/CMakeLists.txt b/src/theme_builder/CMakeLists.txt
index 40d23c4a..d1f30d61 100644
--- a/src/theme_builder/CMakeLists.txt
+++ b/src/theme_builder/CMakeLists.txt
@@ -13,6 +13,7 @@ add_executable(cru_theme_builder
components/properties/CheckBoxPropertyEditor.cpp
components/properties/ColorPropertyEditor.cpp
components/properties/CornerRadiusPropertyEditor.cpp
+ components/properties/FontPropertyEditor.cpp
components/properties/MeasureLengthPropertyEditor.cpp
components/properties/PointPropertyEditor.cpp
components/properties/SelectPropertyEditor.cpp
diff --git a/src/theme_builder/components/properties/FontPropertyEditor.cpp b/src/theme_builder/components/properties/FontPropertyEditor.cpp
index b4f5fa06..927ada7d 100644
--- a/src/theme_builder/components/properties/FontPropertyEditor.cpp
+++ b/src/theme_builder/components/properties/FontPropertyEditor.cpp
@@ -24,13 +24,14 @@ FontPropertyEditor::FontPropertyEditor() {
font_size_container_.SetFlexDirection(FlexDirection::Horizontal);
font_size_container_.AddChild(&font_size_label_);
- font_size_container_.AddChild(&font_size_text_);
+ font_size_container_.AddChild(font_size_input_.GetRootControl());
font_size_label_.SetText(u"Font Size");
+ font_size_input_.SetMin(0.0f);
font_family_text_.TextChangeEvent()->AddSpyOnlyHandler(
[this] { RaiseChangeEvent(); });
- font_size_text_.TextChangeEvent()->AddSpyOnlyHandler(
+ font_size_input_.ChangeEvent()->AddSpyOnlyHandler(
[this] { RaiseChangeEvent(); });
}
@@ -42,8 +43,18 @@ std::shared_ptr<platform::graphics::IFont> FontPropertyEditor::GetValue()
const {
return platform::gui::IUiApplication::GetInstance()
->GetGraphicsFactory()
- ->CreateFont(font_family_text_.GetText(),
- font_size_text_.GetText().ParseToFloat());
+ ->CreateFont(font_family_text_.GetText(), font_size_input_.GetValue());
}
+void FontPropertyEditor::SetValue(
+ std::shared_ptr<platform::graphics::IFont> value, bool trigger_change) {
+ SuppressNextChangeEvent();
+ font_family_text_.SetText(value->GetFontName());
+ SuppressNextChangeEvent();
+ font_size_input_.SetValue(value->GetFontSize());
+
+ if (trigger_change) {
+ RaiseChangeEvent();
+ }
+}
} // namespace cru::theme_builder::components::properties
diff --git a/src/theme_builder/components/properties/FontPropertyEditor.h b/src/theme_builder/components/properties/FontPropertyEditor.h
index f7dd0362..d349f1f2 100644
--- a/src/theme_builder/components/properties/FontPropertyEditor.h
+++ b/src/theme_builder/components/properties/FontPropertyEditor.h
@@ -1,6 +1,7 @@
#pragma once
#include "../Editor.h"
#include "cru/platform/graphics/Font.h"
+#include "cru/ui/components/Input.h"
#include "cru/ui/controls/Control.h"
#include "cru/ui/controls/FlexLayout.h"
#include "cru/ui/controls/TextBlock.h"
@@ -32,6 +33,6 @@ class FontPropertyEditor : public Editor {
ui::controls::TextBox font_family_text_;
ui::controls::FlexLayout font_size_container_;
ui::controls::TextBlock font_size_label_;
- ui::controls::TextBox font_size_text_;
+ ui::components::FloatInput font_size_input_;
};
} // namespace cru::theme_builder::components::properties
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index c9f0df8e..408c93d8 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,6 +3,7 @@ add_library(cru_ui SHARED
ThemeManager.cpp
ThemeResourceDictionary.cpp
components/Component.cpp
+ components/Input.cpp
components/Menu.cpp
components/PopupButton.cpp
components/Select.cpp
diff --git a/src/ui/components/Input.cpp b/src/ui/components/Input.cpp
new file mode 100644
index 00000000..daca68c4
--- /dev/null
+++ b/src/ui/components/Input.cpp
@@ -0,0 +1,94 @@
+#include "cru/ui/components/Input.h"
+#include <cmath>
+#include <optional>
+#include "cru/common/StringToNumberConverter.h"
+#include "cru/ui/controls/Control.h"
+
+namespace cru::ui::components {
+Input::Input() : last_validate_result_{true, u"Good value"} {
+ text_box_.TextChangeEvent()->AddSpyOnlyHandler([this] {
+ auto text = text_box_.GetText();
+ auto validate_result = Validate();
+ this->change_event_.Raise({std::move(text), validate_result.valid,
+ std::move(validate_result.message)});
+ });
+}
+
+Input::~Input() {}
+
+controls::Control* Input::GetRootControl() { return &text_box_; }
+
+String Input::GetText() const { return text_box_.GetText(); }
+
+void Input::SetText(String text) { text_box_.SetText(std::move(text)); }
+
+IInputValidator* Input::GetValidator() const { return validator_; }
+
+void Input::SetValidator(IInputValidator* validator) {
+ validator_ = validator;
+ Validate();
+}
+
+InputValidateResult Input::Validate() {
+ if (validator_)
+ last_validate_result_ = validator_->Validate(text_box_.GetTextView());
+ else
+ last_validate_result_ = {true, u"Good value"};
+ return last_validate_result_;
+}
+
+InputValidateResult Input::GetLastValidateResult() const {
+ return last_validate_result_;
+}
+
+InputValidateResult FloatInputValidator::Validate(StringView text) const {
+ auto result =
+ text.ParseToFloat(nullptr, StringToNumberFlags::kAllowLeadingSpaces &
+ StringToNumberFlags::kAllowTrailingSpaces);
+ if (std::isnan(result)) {
+ return InputValidateResult{false, u"Invalid number."};
+ }
+
+ if (min && result < *min) {
+ return InputValidateResult{false, u"Value is less than minimum."};
+ }
+
+ if (max && result > *max) {
+ return InputValidateResult{false, u"Value is greater than maximum."};
+ }
+
+ return InputValidateResult{true, u"Good number"};
+}
+
+FloatInput::FloatInput() {
+ SetValidator(&validator_);
+
+ ChangeEvent()->AddHandler([this](const InputChangeEventArgs& args) {
+ if (args.valid) {
+ value_ = args.text.ParseToFloat(
+ nullptr, StringToNumberFlags::kAllowLeadingSpaces &
+ StringToNumberFlags::kAllowTrailingSpaces);
+ }
+ });
+}
+
+FloatInput::~FloatInput() {}
+
+float FloatInput::GetValue() const { return value_; }
+
+void FloatInput::SetValue(float value) { SetText(ToString(value)); }
+
+std::optional<float> FloatInput::GetMin() const { return validator_.min; }
+
+void FloatInput::SetMin(std::optional<float> min) {
+ validator_.min = std::move(min);
+ Validate();
+}
+
+std::optional<float> FloatInput::GetMax() const { return validator_.max; }
+
+void FloatInput::SetMax(std::optional<float> max) {
+ validator_.max = std::move(max);
+ Validate();
+}
+} // namespace cru::ui::components