diff --git a/include/xwidgets/xall.hpp b/include/xwidgets/xall.hpp index f74f72c..7c31dcc 100644 --- a/include/xwidgets/xall.hpp +++ b/include/xwidgets/xall.hpp @@ -53,6 +53,7 @@ namespace xw using AllWidgets = std::tuple< accordion, audio, + box, button, checkbox, color_picker, @@ -102,6 +103,7 @@ namespace xw checkbox_style, description_style, html_style, + label_style, progress_style, slider_style, text_style, diff --git a/include/xwidgets/xbox.hpp b/include/xwidgets/xbox.hpp index 5ed8b89..7cef059 100644 --- a/include/xwidgets/xbox.hpp +++ b/include/xwidgets/xbox.hpp @@ -57,13 +57,14 @@ namespace xw protected: xbox(); - using base_type::base_type; private: void set_defaults(); }; + using box = xmaterialize; + /******************** * hbox declaration * ********************/ @@ -216,12 +217,12 @@ namespace xw template inline void xbox::set_defaults() { - this->_model_name() = "BoxModel"; - this->_view_name() = "BoxView"; this->_model_module() = "@jupyter-widgets/controls"; - this->_view_module() = "@jupyter-widgets/controls"; this->_model_module_version() = XWIDGETS_CONTROLS_VERSION; + this->_model_name() = "BoxModel"; + this->_view_module() = "@jupyter-widgets/controls"; this->_view_module_version() = XWIDGETS_CONTROLS_VERSION; + this->_view_name() = "BoxView"; } /************************ @@ -230,7 +231,6 @@ namespace xw template inline xhbox::xhbox() - : base_type() { set_defaults(); } @@ -248,7 +248,6 @@ namespace xw template inline xvbox::xvbox() - : base_type() { set_defaults(); } diff --git a/include/xwidgets/xlabel.hpp b/include/xwidgets/xlabel.hpp index a4b9e4c..a05b8af 100644 --- a/include/xwidgets/xlabel.hpp +++ b/include/xwidgets/xlabel.hpp @@ -9,12 +9,53 @@ #ifndef XWIDGETS_LABEL_HPP #define XWIDGETS_LABEL_HPP -#include "xhtml.hpp" +#include + +#include + #include "xmaterialize.hpp" #include "xstring.hpp" +#include "xstyle.hpp" namespace xw { + + /***************************** + * label_style declaration * + *****************************/ + + template + class xlabel_style : public xstyle + { + public: + + using base_type = xstyle; + using derived_type = D; + + void serialize_state(nl::json&, xeus::buffer_sequence&) const; + void apply_patch(const nl::json&, const xeus::buffer_sequence&); + + XPROPERTY(xtl::xoptional, derived_type, background); + XPROPERTY(std::string, derived_type, description_width); + XPROPERTY(xtl::xoptional, derived_type, font_family); + XPROPERTY(xtl::xoptional, derived_type, font_size); + XPROPERTY(xtl::xoptional, derived_type, font_style); + XPROPERTY(xtl::xoptional, derived_type, font_variant); + XPROPERTY(xtl::xoptional, derived_type, font_weight); + XPROPERTY(xtl::xoptional, derived_type, text_color); + XPROPERTY(xtl::xoptional, derived_type, text_decoration); + + protected: + + xlabel_style(); + + private: + + void set_defaults(); + }; + + using label_style = xmaterialize; + /********************* * label declaration * *********************/ @@ -30,12 +71,11 @@ namespace xw void serialize_state(nl::json&, xeus::buffer_sequence&) const; void apply_patch(const nl::json&, const xeus::buffer_sequence&); - XPROPERTY(::xw::html_style, derived_type, style); + XPROPERTY(::xw::label_style, derived_type, style); protected: xlabel(); - using base_type::base_type; private: @@ -44,6 +84,56 @@ namespace xw using label = xmaterialize; + /********************************* + * xlabel_style implementation * + *********************************/ + + template + inline void xlabel_style::serialize_state(nl::json& state, xeus::buffer_sequence& buffers) const + { + base_type::serialize_state(state, buffers); + + xwidgets_serialize(background(), state["background"], buffers); + xwidgets_serialize(description_width(), state["description_width"], buffers); + xwidgets_serialize(font_family(), state["font_family"], buffers); + xwidgets_serialize(font_size(), state["font_size"], buffers); + xwidgets_serialize(font_style(), state["font_style"], buffers); + xwidgets_serialize(font_variant(), state["font_variant"], buffers); + xwidgets_serialize(font_weight(), state["font_weight"], buffers); + xwidgets_serialize(text_color(), state["text_color"], buffers); + xwidgets_serialize(text_decoration(), state["text_decoration"], buffers); + } + + template + inline void xlabel_style::apply_patch(const nl::json& patch, const xeus::buffer_sequence& buffers) + { + base_type::apply_patch(patch, buffers); + + set_property_from_patch(background, patch, buffers); + set_property_from_patch(description_width, patch, buffers); + set_property_from_patch(font_family, patch, buffers); + set_property_from_patch(font_size, patch, buffers); + set_property_from_patch(font_style, patch, buffers); + set_property_from_patch(font_variant, patch, buffers); + set_property_from_patch(font_weight, patch, buffers); + set_property_from_patch(text_color, patch, buffers); + set_property_from_patch(text_decoration, patch, buffers); + } + + template + inline xlabel_style::xlabel_style() + { + set_defaults(); + } + + template + inline void xlabel_style::set_defaults() + { + this->_model_module() = "@jupyter-widgets/controls"; + this->_model_module_version() = XWIDGETS_CONTROLS_VERSION; + this->_model_name() = "LabelStyleModel"; + } + /************************* * xlabel implementation * *************************/ @@ -74,8 +164,8 @@ namespace xw template inline void xlabel::set_defaults() { - this->_model_name() = "HTMLModel"; - this->_view_name() = "HTMLView"; + this->_model_name() = "LabelModel"; + this->_view_name() = "LabelView"; } /********************* diff --git a/include/xwidgets/xstyle.hpp b/include/xwidgets/xstyle.hpp index dc468fe..aaa59d2 100644 --- a/include/xwidgets/xstyle.hpp +++ b/include/xwidgets/xstyle.hpp @@ -31,7 +31,6 @@ namespace xw protected: xstyle(); - using base_type::base_type; private: @@ -56,7 +55,6 @@ namespace xw template inline xstyle::xstyle() - : base_type() { set_defaults(); } diff --git a/test/test_widget_model.cpp b/test/test_widget_model.cpp index 0918923..40a3859 100644 --- a/test/test_widget_model.cpp +++ b/test/test_widget_model.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,8 @@ namespace xw nl::json serialize(); template std::string model_name(); + auto all_widget_model_names() -> std::array>; + auto all_style_model_names() -> std::array>; #ifndef XWIDGETS_MODELS_FILE #error "XWIDGETS_MODELS_FILE must be defined pointing to model file" @@ -78,6 +81,56 @@ namespace xw TEST_CASE_TEMPLATE_APPLY(packages_widgets, AllWidgets); TEST_CASE_TEMPLATE_APPLY(packages_widgets, AllStyles); + + TEST_CASE("missing") + { + auto widgets_contains = [](auto const& val) + { + static auto const all_widgets = all_widget_model_names(); + return std::find(all_widgets.begin(), all_widgets.end(), val) < all_widgets.end(); + }; + + auto styles_contains = [](auto const& val) + { + static auto const all_styles = all_style_model_names(); + return std::find(all_styles.begin(), all_styles.end(), val) < all_styles.end(); + }; + + // Missing widgets tracked in https://github.com/jupyter-xeus/xwidgets/issues/249 + // This test is still useful even with the todo so that we don't get model names + // wrong. + auto todo_contains = [](auto const& val) + { + static auto const todo = std::array{ + "ColorsInputModel", + "ComboboxModel", + "DatePickerModel", + "DatetimeModel", + "FileUploadModel", + "FloatLogSliderModel", + "FloatRangeSliderModel", + "FloatsInputModel", + "GridBoxModel", + "HTMLMathModel", + "HTMLMathStyleModel", + "IntRangeSliderModel", + "IntsInputModel", + "NaiveDatetimeModel", + "StackModel", + "TagsInputModel", + "TimeModel", + }; + return std::find(todo.begin(), todo.end(), val) < todo.end(); + }; + + for (auto const& [model, _] : schemas) + { + // Somehow using `model` directly in the macro does not compile on clang 15.0.7 + auto const& model_that_pleases_clang = model; + INFO("Checking for model ", model_that_pleases_clang); + CHECK((widgets_contains(model) || styles_contains(model) || todo_contains(model))); + } + } } /*************************************** @@ -253,4 +306,25 @@ namespace xw throw std::invalid_argument("Widget does not have a model name"); } + template + struct all_model_names_impl; + + template + struct all_model_names_impl> + { + static auto get() + { + return std::array{model_name()...}; + } + }; + + auto all_widget_model_names() -> std::array> + { + return all_model_names_impl{}.get(); + } + + auto all_style_model_names() -> std::array> + { + return all_model_names_impl{}.get(); + } } diff --git a/test/test_xwidgets.cpp b/test/test_xwidgets.cpp index c76abcd..e4f9832 100644 --- a/test/test_xwidgets.cpp +++ b/test/test_xwidgets.cpp @@ -77,6 +77,20 @@ namespace xw CHECK_EQ(true, c.indent()); } + TEST_CASE("checkbox.style") + { + checkbox c; + c.style = checkbox_style::initialize() // + .background("black") + .description_width("3") + .finalize(); + REQUIRE_EQ("black", c.style().background()); + REQUIRE_EQ("3", c.style().description_width()); + + c.style().description_width = "50"; + REQUIRE_EQ("50", c.style().description_width()); + } + TEST_CASE("html") { html h;