mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 05:34:58 +00:00
LibGUI: Port rest of the classes to property deserializers
This commit is contained in:
parent
bd56d2f508
commit
1f4b15dcaa
9 changed files with 164 additions and 211 deletions
|
@ -22,7 +22,7 @@ BoxLayout::BoxLayout(Orientation orientation, Margins margins, int spacing)
|
|||
, m_orientation(orientation)
|
||||
{
|
||||
register_property(
|
||||
"orientation", [this] { return m_orientation == Gfx::Orientation::Vertical ? "Vertical" : "Horizontal"; }, nullptr);
|
||||
"orientation"sv, [this] { return m_orientation == Gfx::Orientation::Vertical ? "Vertical" : "Horizontal"; }, nullptr, nullptr);
|
||||
}
|
||||
|
||||
UISize BoxLayout::preferred_size() const
|
||||
|
|
|
@ -21,7 +21,8 @@ Layout::Layout(Margins initial_margins, int spacing)
|
|||
REGISTER_INT_PROPERTY("spacing", spacing, set_spacing);
|
||||
REGISTER_MARGINS_PROPERTY("margins", margins, set_margins);
|
||||
|
||||
register_property("entries",
|
||||
register_property(
|
||||
"entries"sv,
|
||||
[this] {
|
||||
JsonArray entries_array;
|
||||
for (auto& entry : m_entries) {
|
||||
|
@ -37,7 +38,8 @@ Layout::Layout(Margins initial_margins, int spacing)
|
|||
entries_array.must_append(move(entry_object));
|
||||
}
|
||||
return entries_array;
|
||||
});
|
||||
},
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
Layout::~Layout() = default;
|
||||
|
|
|
@ -139,30 +139,15 @@ private:
|
|||
|
||||
#define REGISTER_MARGINS_PROPERTY(property_name, getter, setter) \
|
||||
register_property( \
|
||||
property_name, [this]() { \
|
||||
auto m = getter(); \
|
||||
JsonObject margins_object; \
|
||||
margins_object.set("left", m.left()); \
|
||||
margins_object.set("right", m.right()); \
|
||||
margins_object.set("top", m.top()); \
|
||||
margins_object.set("bottom", m.bottom()); \
|
||||
return margins_object; }, \
|
||||
[this](auto& value) { \
|
||||
if (!value.is_array()) \
|
||||
return false; \
|
||||
auto size = value.as_array().size(); \
|
||||
if (size == 0 || size > 4) \
|
||||
return false; \
|
||||
int m[4]; \
|
||||
for (size_t i = 0; i < size; ++i) \
|
||||
m[i] = value.as_array().at(i).to_i32(); \
|
||||
if (size == 1) \
|
||||
setter({ m[0] }); \
|
||||
else if (size == 2) \
|
||||
setter({ m[0], m[1] }); \
|
||||
else if (size == 3) \
|
||||
setter({ m[0], m[1], m[2] }); \
|
||||
else \
|
||||
setter({ m[0], m[1], m[2], m[3] }); \
|
||||
return true; \
|
||||
});
|
||||
property_name##sv, \
|
||||
[this]() { \
|
||||
auto m = getter(); \
|
||||
JsonObject margins_object; \
|
||||
margins_object.set("left", m.left()); \
|
||||
margins_object.set("right", m.right()); \
|
||||
margins_object.set("top", m.top()); \
|
||||
margins_object.set("bottom", m.bottom()); \
|
||||
return margins_object; \
|
||||
}, \
|
||||
::GUI::PropertyDeserializer<::GUI::Margins> {}, \
|
||||
[this](auto const& value) { return setter(value); });
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "PropertyDeserializer.h"
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibGUI/Margins.h>
|
||||
#include <LibGUI/UIDimensions.h>
|
||||
#include <LibGfx/Color.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
|
||||
namespace GUI {
|
||||
|
@ -114,4 +117,73 @@ ErrorOr<Gfx::IntSize> PropertyDeserializer<Gfx::IntSize>::operator()(JsonValue c
|
|||
return size;
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<GUI::Margins> PropertyDeserializer<GUI::Margins>::operator()(JsonValue const& value) const
|
||||
{
|
||||
if (!value.is_array() || value.as_array().size() < 1 || value.as_array().size() > 4)
|
||||
return Error::from_string_literal("Expected non-empty array with up to 4 integers");
|
||||
|
||||
auto const& array = value.as_array();
|
||||
auto size = array.size();
|
||||
|
||||
int m[4];
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
auto const& margin = array[i];
|
||||
if (!margin.is_integer<i32>())
|
||||
return Error::from_string_literal("Margin value should be an integer");
|
||||
m[i] = margin.to_i32();
|
||||
}
|
||||
|
||||
if (size == 1)
|
||||
return GUI::Margins { m[0] };
|
||||
else if (size == 2)
|
||||
return GUI::Margins { m[0], m[1] };
|
||||
else if (size == 3)
|
||||
return GUI::Margins { m[0], m[1], m[2] };
|
||||
else
|
||||
return GUI::Margins { m[0], m[1], m[2], m[3] };
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<UIDimension> PropertyDeserializer<UIDimension>::operator()(JsonValue const& value) const
|
||||
{
|
||||
auto result = UIDimension::construct_from_json_value(value);
|
||||
if (result.has_value())
|
||||
return result.release_value();
|
||||
return Error::from_string_literal("Value is not a valid UIDimension");
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<UISize> PropertyDeserializer<UISize>::operator()(JsonValue const& value) const
|
||||
{
|
||||
if (!value.is_object() || !value.as_object().has("width"sv) || !value.as_object().has("height"sv))
|
||||
return Error::from_string_literal("Object with keys \"width\" and \"height\" is expected");
|
||||
|
||||
auto const& object = value.as_object();
|
||||
|
||||
auto const& width = object.get("width"sv).value();
|
||||
auto result_width = GUI::UIDimension::construct_from_json_value(width);
|
||||
if (!result_width.has_value())
|
||||
return Error::from_string_literal("width is not a valid UIDimension");
|
||||
|
||||
auto const& height = object.get("height"sv).value();
|
||||
auto result_height = GUI::UIDimension::construct_from_json_value(height);
|
||||
if (!result_height.has_value())
|
||||
return Error::from_string_literal("height is not a valid UIDimension");
|
||||
|
||||
return UISize { result_width.value(), result_height.value() };
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Color> PropertyDeserializer<Color>::operator()(JsonValue const& value) const
|
||||
{
|
||||
if (value.is_string()) {
|
||||
auto c = Color::from_string(value.as_string());
|
||||
if (c.has_value())
|
||||
return c.release_value();
|
||||
}
|
||||
return Error::from_string_literal("Color is expected");
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -37,18 +37,7 @@ TabWidget::TabWidget()
|
|||
{ TabPosition::Bottom, "Bottom" },
|
||||
{ TabPosition::Left, "Left" },
|
||||
{ TabPosition::Right, "Right" }, );
|
||||
|
||||
register_property(
|
||||
"text_alignment",
|
||||
[this] { return Gfx::to_string(text_alignment()); },
|
||||
[this](auto& value) {
|
||||
auto alignment = Gfx::text_alignment_from_string(value.to_byte_string());
|
||||
if (alignment.has_value()) {
|
||||
set_text_alignment(alignment.value());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
REGISTER_TEXT_ALIGNMENT_PROPERTY("text_alignment", text_alignment, set_text_alignment);
|
||||
}
|
||||
|
||||
ErrorOr<void> TabWidget::try_add_widget(Widget& widget)
|
||||
|
|
|
@ -296,58 +296,44 @@ inline auto clamp<GUI::UIDimension>(GUI::UIDimension const& input, GUI::UIDimens
|
|||
|
||||
}
|
||||
|
||||
#define REGISTER_UI_DIMENSION_PROPERTY(property_name, getter, setter) \
|
||||
register_property( \
|
||||
property_name, \
|
||||
[this] { \
|
||||
return this->getter().as_json_value(); \
|
||||
}, \
|
||||
[this](auto& value) { \
|
||||
auto result = GUI::UIDimension::construct_from_json_value(value); \
|
||||
if (result.has_value()) \
|
||||
this->setter(result.value()); \
|
||||
return result.has_value(); \
|
||||
});
|
||||
#define REGISTER_UI_DIMENSION_PROPERTY(property_name, getter, setter) \
|
||||
register_property( \
|
||||
property_name##sv, \
|
||||
[this] { \
|
||||
return this->getter().as_json_value(); \
|
||||
}, \
|
||||
::GUI::PropertyDeserializer<::GUI::UIDimension> {}, \
|
||||
[this](auto const& value) { return setter(value); });
|
||||
|
||||
#define REGISTER_READONLY_UI_DIMENSION_PROPERTY(property_name, getter) \
|
||||
register_property( \
|
||||
property_name, \
|
||||
property_name##sv, \
|
||||
[this] { \
|
||||
return this->getter().as_json_value(); \
|
||||
});
|
||||
}, \
|
||||
nullptr, nullptr);
|
||||
|
||||
#define REGISTER_UI_SIZE_PROPERTY(property_name, getter, setter) \
|
||||
register_property( \
|
||||
property_name, \
|
||||
[this] { \
|
||||
auto size = this->getter(); \
|
||||
JsonObject size_object; \
|
||||
size_object.set("width"sv, size.width().as_json_value()); \
|
||||
size_object.set("height"sv, size.height().as_json_value()); \
|
||||
return size_object; \
|
||||
}, \
|
||||
[this](auto& value) { \
|
||||
if (!value.is_object()) \
|
||||
return false; \
|
||||
auto result_width = GUI::UIDimension::construct_from_json_value( \
|
||||
value.as_object().get("width"sv).value_or({})); \
|
||||
auto result_height = GUI::UIDimension::construct_from_json_value( \
|
||||
value.as_object().get("height"sv).value_or({})); \
|
||||
if (result_width.has_value() && result_height.has_value()) { \
|
||||
GUI::UISize size(result_width.value(), result_height.value()); \
|
||||
setter(size); \
|
||||
return true; \
|
||||
} \
|
||||
return false; \
|
||||
});
|
||||
#define REGISTER_UI_SIZE_PROPERTY(property_name, getter, setter) \
|
||||
register_property( \
|
||||
property_name##sv, \
|
||||
[this] { \
|
||||
auto size = this->getter(); \
|
||||
JsonObject size_object; \
|
||||
size_object.set("width"sv, size.width().as_json_value()); \
|
||||
size_object.set("height"sv, size.height().as_json_value()); \
|
||||
return size_object; \
|
||||
}, \
|
||||
::GUI::PropertyDeserializer<::GUI::UISize> {}, \
|
||||
[this](auto const& value) { return setter(value); });
|
||||
|
||||
#define REGISTER_READONLY_UI_SIZE_PROPERTY(property_name, getter) \
|
||||
register_property( \
|
||||
property_name, \
|
||||
property_name##sv, \
|
||||
[this] { \
|
||||
auto size = this->getter(); \
|
||||
JsonObject size_object; \
|
||||
size_object.set("width", size.width().as_json_value()); \
|
||||
size_object.set("height", size.height().as_json_value()); \
|
||||
return size_object; \
|
||||
});
|
||||
}, \
|
||||
nullptr, nullptr);
|
||||
|
|
|
@ -45,12 +45,12 @@ Widget::Widget()
|
|||
REGISTER_DEPRECATED_STRING_PROPERTY("name", name, set_name);
|
||||
|
||||
register_property(
|
||||
"address", [this] { return FlatPtr(this); },
|
||||
[](auto&) { return false; });
|
||||
"address"sv, [this] { return FlatPtr(this); },
|
||||
nullptr, nullptr);
|
||||
|
||||
register_property(
|
||||
"parent", [this] { return FlatPtr(this->parent()); },
|
||||
[](auto&) { return false; });
|
||||
"parent"sv, [this] { return FlatPtr(this->parent()); },
|
||||
nullptr, nullptr);
|
||||
|
||||
REGISTER_RECT_PROPERTY("relative_rect", relative_rect, set_relative_rect);
|
||||
REGISTER_BOOL_PROPERTY("fill_with_background_color", fill_with_background_color, set_fill_with_background_color);
|
||||
|
@ -90,119 +90,52 @@ Widget::Widget()
|
|||
|
||||
REGISTER_BOOL_PROPERTY("font_fixed_width", is_font_fixed_width, set_font_fixed_width)
|
||||
register_property(
|
||||
"font_type", [this] { return m_font->is_fixed_width() ? "FixedWidth" : "Normal"; },
|
||||
[this](auto& value) {
|
||||
if (value.to_byte_string() == "FixedWidth") {
|
||||
set_font_fixed_width(true);
|
||||
return true;
|
||||
"font_type"sv, [this] { return m_font->is_fixed_width() ? "FixedWidth" : "Normal"; },
|
||||
[](JsonValue const& value) -> ErrorOr<bool> {
|
||||
if (value.is_string()) {
|
||||
auto string = value.as_string();
|
||||
if (string == "FixedWidth")
|
||||
return true;
|
||||
if (string == "Normal")
|
||||
return false;
|
||||
}
|
||||
if (value.to_byte_string() == "Normal") {
|
||||
set_font_fixed_width(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return Error::from_string_literal("\"FixedWidth\" or \"Normal\" is expected");
|
||||
},
|
||||
[this](auto const& value) { return set_font_fixed_width(value); });
|
||||
|
||||
REGISTER_ENUM_PROPERTY("focus_policy", focus_policy, set_focus_policy, GUI::FocusPolicy,
|
||||
{ GUI::FocusPolicy::ClickFocus, "ClickFocus" },
|
||||
{ GUI::FocusPolicy::NoFocus, "NoFocus" },
|
||||
{ GUI::FocusPolicy::TabFocus, "TabFocus" },
|
||||
{ GUI::FocusPolicy::StrongFocus, "StrongFocus" });
|
||||
|
||||
register_property(
|
||||
"foreground_color"sv,
|
||||
[this]() { return palette().color(foreground_role()).to_byte_string(); },
|
||||
::GUI::PropertyDeserializer<Color> {},
|
||||
[this](Gfx::Color const& color) {
|
||||
auto _palette = palette();
|
||||
_palette.set_color(foreground_role(), color);
|
||||
set_palette(_palette);
|
||||
});
|
||||
|
||||
register_property(
|
||||
"focus_policy", [this]() -> JsonValue {
|
||||
auto policy = focus_policy();
|
||||
if (policy == GUI::FocusPolicy::ClickFocus)
|
||||
return "ClickFocus";
|
||||
if (policy == GUI::FocusPolicy::NoFocus)
|
||||
return "NoFocus";
|
||||
if (policy == GUI::FocusPolicy::TabFocus)
|
||||
return "TabFocus";
|
||||
if (policy == GUI::FocusPolicy::StrongFocus)
|
||||
return "StrongFocus";
|
||||
return JsonValue(); },
|
||||
[this](auto& value) {
|
||||
if (!value.is_string())
|
||||
return false;
|
||||
if (value.as_string() == "ClickFocus") {
|
||||
set_focus_policy(GUI::FocusPolicy::ClickFocus);
|
||||
return true;
|
||||
}
|
||||
if (value.as_string() == "NoFocus") {
|
||||
set_focus_policy(GUI::FocusPolicy::NoFocus);
|
||||
return true;
|
||||
}
|
||||
if (value.as_string() == "TabFocus") {
|
||||
set_focus_policy(GUI::FocusPolicy::TabFocus);
|
||||
return true;
|
||||
}
|
||||
if (value.as_string() == "StrongFocus") {
|
||||
set_focus_policy(GUI::FocusPolicy::StrongFocus);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
"background_color"sv,
|
||||
[this]() { return palette().color(background_role()).to_byte_string(); },
|
||||
::GUI::PropertyDeserializer<Color> {},
|
||||
[this](Gfx::Color const& color) {
|
||||
set_background_color(color);
|
||||
});
|
||||
|
||||
register_property(
|
||||
"foreground_color", [this]() -> JsonValue { return palette().color(foreground_role()).to_byte_string(); },
|
||||
[this](auto& value) {
|
||||
auto c = Color::from_string(value.to_byte_string());
|
||||
if (c.has_value()) {
|
||||
auto _palette = palette();
|
||||
_palette.set_color(foreground_role(), c.value());
|
||||
set_palette(_palette);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
register_property(
|
||||
"background_color", [this]() -> JsonValue { return palette().color(background_role()).to_byte_string(); },
|
||||
[this](JsonValue const& value) {
|
||||
auto color_str = String::from_byte_string(value.to_byte_string());
|
||||
if (color_str.is_error())
|
||||
return false;
|
||||
|
||||
return set_background_color(color_str.release_value());
|
||||
});
|
||||
|
||||
register_property(
|
||||
"foreground_role", [this]() -> JsonValue { return Gfx::to_string(foreground_role()); },
|
||||
[this](auto& value) {
|
||||
if (!value.is_string())
|
||||
return false;
|
||||
auto str = value.as_string();
|
||||
if (str == "NoRole") {
|
||||
set_foreground_role(Gfx::ColorRole::NoRole);
|
||||
return true;
|
||||
}
|
||||
#define __ENUMERATE_COLOR_ROLE(role) \
|
||||
{ Gfx::ColorRole::role, #role },
|
||||
REGISTER_ENUM_PROPERTY("foreground_role", foreground_role, set_foreground_role, Gfx::ColorRole,
|
||||
{ Gfx::ColorRole::NoRole, "NoRole" },
|
||||
ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE));
|
||||
REGISTER_ENUM_PROPERTY("background_role", background_role, set_background_role, Gfx::ColorRole,
|
||||
{ Gfx::ColorRole::NoRole, "NoRole" },
|
||||
ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE));
|
||||
#undef __ENUMERATE_COLOR_ROLE
|
||||
#define __ENUMERATE_COLOR_ROLE(role) \
|
||||
else if (str == #role) \
|
||||
{ \
|
||||
set_foreground_role(Gfx::ColorRole::role); \
|
||||
return true; \
|
||||
}
|
||||
ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE)
|
||||
#undef __ENUMERATE_COLOR_ROLE
|
||||
return false;
|
||||
});
|
||||
|
||||
register_property(
|
||||
"background_role", [this]() -> JsonValue { return Gfx::to_string(background_role()); },
|
||||
[this](auto& value) {
|
||||
if (!value.is_string())
|
||||
return false;
|
||||
auto str = value.as_string();
|
||||
if (str == "NoRole") {
|
||||
set_background_role(Gfx::ColorRole::NoRole);
|
||||
return true;
|
||||
}
|
||||
#undef __ENUMERATE_COLOR_ROLE
|
||||
#define __ENUMERATE_COLOR_ROLE(role) \
|
||||
else if (str == #role) \
|
||||
{ \
|
||||
set_background_role(Gfx::ColorRole::role); \
|
||||
return true; \
|
||||
}
|
||||
ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE)
|
||||
#undef __ENUMERATE_COLOR_ROLE
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
Widget::~Widget() = default;
|
||||
|
@ -1082,15 +1015,6 @@ void Widget::set_foreground_role(ColorRole role)
|
|||
update();
|
||||
}
|
||||
|
||||
bool Widget::set_background_color(String color_str)
|
||||
{
|
||||
auto color = Color::from_string(color_str.to_byte_string());
|
||||
if (!color.has_value())
|
||||
return false;
|
||||
set_background_color(color.release_value());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Widget::set_background_color(Gfx::Color color)
|
||||
{
|
||||
auto _palette = palette();
|
||||
|
|
|
@ -254,7 +254,6 @@ public:
|
|||
Gfx::ColorRole foreground_role() const { return m_foreground_role; }
|
||||
void set_foreground_role(Gfx::ColorRole);
|
||||
|
||||
bool set_background_color(String);
|
||||
void set_background_color(Gfx::Color);
|
||||
|
||||
void set_autofill(bool b) { set_fill_with_background_color(b); }
|
||||
|
|
|
@ -85,16 +85,12 @@ Window::Window(Core::EventReceiver* parent)
|
|||
m_floating_rect = { -5000, -5000, 0, 0 };
|
||||
m_title_when_windowless = "GUI::Window";
|
||||
|
||||
register_property(
|
||||
"title",
|
||||
[this] { return title(); },
|
||||
[this](auto& value) {
|
||||
set_title(value.to_byte_string());
|
||||
return true;
|
||||
});
|
||||
REGISTER_DEPRECATED_STRING_PROPERTY("title", title, set_title)
|
||||
|
||||
register_property("visible", [this] { return is_visible(); });
|
||||
register_property("active", [this] { return is_active(); });
|
||||
register_property(
|
||||
"visible"sv, [this] { return is_visible(); }, nullptr, nullptr);
|
||||
register_property(
|
||||
"active"sv, [this] { return is_active(); }, nullptr, nullptr);
|
||||
|
||||
REGISTER_BOOL_PROPERTY("minimizable", is_minimizable, set_minimizable);
|
||||
REGISTER_BOOL_PROPERTY("resizable", is_resizable, set_resizable);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue