diff --git a/src/tools/ecode/settingspanel.cpp b/src/tools/ecode/settingspanel.cpp index 479ad2154..04b467cdf 100644 --- a/src/tools/ecode/settingspanel.cpp +++ b/src/tools/ecode/settingspanel.cpp @@ -4,6 +4,8 @@ #include "uitreeviewfs.hpp" #include #include +#define PUGIXML_HEADER_ONLY +#include using namespace EE::UI::Models; @@ -238,17 +240,36 @@ static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml( )xml"; -static constexpr const char* SETTINGS_ROW_LAYOUT = R"xml( +static std::string settingsRowLayout( std::string_view control ) { + return R"xml( - + +)xml" + std::string( control ) + + R"xml( + )xml"; +} + +class SettingsLayoutTemplate { + public: + explicit SettingsLayoutTemplate( const std::string& layout ) { + [[maybe_unused]] auto result = + mDocument.load_string( layout.c_str(), pugi::parse_default | pugi::parse_ws_pcdata ); + eeASSERT( result ); + } + + pugi::xml_node root() const { return mDocument.first_child(); } + + private: + pugi::xml_document mDocument; +}; static constexpr const char* SETTINGS_CATEGORY_HEADING_LAYOUT = R"xml( @@ -256,16 +277,18 @@ static constexpr const char* SETTINGS_CATEGORY_HEADING_LAYOUT = R"xml( static constexpr const char* SETTINGS_SUBCATEGORY_HEADING_LAYOUT = R"xml( )xml"; -static constexpr const char* SETTINGS_BOOL_LAYOUT = R"xml()xml"; -static constexpr const char* SETTINGS_CHOICE_LAYOUT = - R"xml()xml"; -static constexpr const char* SETTINGS_EDITABLE_CHOICE_LAYOUT = - R"xml()xml"; -static constexpr const char* SETTINGS_INTEGER_LAYOUT = - R"xml()xml"; -static constexpr const char* SETTINGS_TEXT_LAYOUT = R"xml()xml"; -static constexpr const char* SETTINGS_ACTION_LAYOUT = - R"xml()xml"; +static const SettingsLayoutTemplate SETTINGS_BOOL_ROW_LAYOUT( settingsRowLayout( + R"xml()xml" ) ); +static const SettingsLayoutTemplate SETTINGS_CHOICE_ROW_LAYOUT( settingsRowLayout( + R"xml()xml" ) ); +static const SettingsLayoutTemplate SETTINGS_EDITABLE_CHOICE_ROW_LAYOUT( settingsRowLayout( + R"xml()xml" ) ); +static const SettingsLayoutTemplate SETTINGS_INTEGER_ROW_LAYOUT( settingsRowLayout( + R"xml()xml" ) ); +static const SettingsLayoutTemplate SETTINGS_TEXT_ROW_LAYOUT( settingsRowLayout( + R"xml()xml" ) ); +static const SettingsLayoutTemplate SETTINGS_ACTION_ROW_LAYOUT( settingsRowLayout( + R"xml()xml" ) ); static void disableTabFocusTree( Node* node ) { if ( node->isWidget() ) @@ -485,8 +508,9 @@ void SettingsPanel::setupCategories( PanelState& panel ) { } ); } -UIWidget* SettingsPanel::createRow( PanelState& panel, SettingBinding& binding ) { - auto* row = mApp->getUISceneNode()->loadLayoutFromString( SETTINGS_ROW_LAYOUT, panel.settings ); +UIWidget* SettingsPanel::createRow( PanelState& panel, SettingBinding& binding, + pugi::xml_node layout ) { + auto* row = mApp->getUISceneNode()->loadLayoutNodes( layout, panel.settings, 0 ); row->setId( "setting_" + binding.id ); row->find( "setting_name" )->setText( binding.name ); auto* description = row->find( "setting_description" ); @@ -517,12 +541,9 @@ void SettingsPanel::addBool( PanelState& panel, SettingBinding binding, std::fun } UICheckBox* SettingsPanel::createBoolControl( PanelState& panel, SettingBinding& binding ) { - auto* row = createRow( panel, binding ); + auto* row = createRow( panel, binding, SETTINGS_BOOL_ROW_LAYOUT.root() ); row->addClass( "settings_boolean_option" ); - auto* check = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_BOOL_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* check = row->find( "setting_control_widget" ); auto toggle = [check]( const Event* ) { check->setChecked( !check->isChecked() ); }; panel.connections += row->find( "setting_name" )->connect( Event::MouseClick, toggle ); @@ -535,11 +556,8 @@ void SettingsPanel::addChoice( PanelState& panel, SettingBinding binding, const std::vector& choices, std::function get, std::function set, std::vector choiceDescriptions ) { - auto* row = createRow( panel, binding ); - auto* dropDown = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_CHOICE_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* row = createRow( panel, binding, SETTINGS_CHOICE_ROW_LAYOUT.root() ); + auto* dropDown = row->find( "setting_control_widget" ); auto model = ItemListOwnerModel::create( choices ); dropDown->setModel( model ); const size_t selected = get(); @@ -566,11 +584,8 @@ void SettingsPanel::addEditableChoice( PanelState& panel, SettingBinding binding const std::vector& choices, std::function get, std::function set ) { - auto* row = createRow( panel, binding ); - auto* combo = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_EDITABLE_CHOICE_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* row = createRow( panel, binding, SETTINGS_EDITABLE_CHOICE_ROW_LAYOUT.root() ); + auto* combo = row->find( "setting_control_widget" ); for ( const auto& choice : choices ) combo->getListBox()->addListBoxItem( choice ); combo->setText( get() ); @@ -589,11 +604,8 @@ void SettingsPanel::addEditableChoice( PanelState& panel, SettingBinding binding void SettingsPanel::addInteger( PanelState& panel, SettingBinding binding, int min, int max, std::function get, std::function set ) { - auto* row = createRow( panel, binding ); - auto* spin = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* row = createRow( panel, binding, SETTINGS_INTEGER_ROW_LAYOUT.root() ); + auto* spin = row->find( "setting_control_widget" ); spin->setMinValue( min )->setMaxValue( max ); spin->unsetTabFocusable(); spin->getButtonPushUp()->asType()->unsetTabFocusable(); @@ -610,11 +622,8 @@ void SettingsPanel::addText( PanelState& panel, SettingBinding binding, std::function get, std::function set, bool commitOnFocusLoss ) { - auto* row = createRow( panel, binding ); - auto* input = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_TEXT_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* row = createRow( panel, binding, SETTINGS_TEXT_ROW_LAYOUT.root() ); + auto* input = row->find( "setting_control_widget" ); input->setText( String::fromUtf8( get() ) ); auto commit = [input, set = std::move( set )]( const Event* ) { std::string text = input->getText().toUtf8(); @@ -636,11 +645,8 @@ void SettingsPanel::addText( PanelState& panel, SettingBinding binding, void SettingsPanel::addFloat( PanelState& panel, SettingBinding binding, double min, double max, double step, std::function get, std::function set ) { - auto* row = createRow( panel, binding ); - auto* spin = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* row = createRow( panel, binding, SETTINGS_INTEGER_ROW_LAYOUT.root() ); + auto* spin = row->find( "setting_control_widget" ); spin->setMinValue( min )->setMaxValue( max )->setClickStep( step ); spin->allowFloatingPoint( true )->setValue( get() ); spin->unsetTabFocusable(); @@ -655,11 +661,8 @@ void SettingsPanel::addFloat( PanelState& panel, SettingBinding binding, double void SettingsPanel::addAction( PanelState& panel, SettingBinding binding, const String& buttonText, std::function action ) { - auto* row = createRow( panel, binding ); - auto* button = mApp->getUISceneNode() - ->loadLayoutFromString( SETTINGS_ACTION_LAYOUT, - row->find( "setting_control" ) ) - ->asType(); + auto* row = createRow( panel, binding, SETTINGS_ACTION_ROW_LAYOUT.root() ); + auto* button = row->find( "setting_control_widget" ); button->setText( buttonText ); panel.connections += button->connect( Event::MouseClick, [action = std::move( action )]( const Event* ) { action(); } ); diff --git a/src/tools/ecode/settingspanel.hpp b/src/tools/ecode/settingspanel.hpp index 609ec0585..82e7c19aa 100644 --- a/src/tools/ecode/settingspanel.hpp +++ b/src/tools/ecode/settingspanel.hpp @@ -88,7 +88,7 @@ class SettingsPanel { std::function get, std::function set ); void addAction( PanelState& state, SettingBinding binding, const String& buttonText, std::function action ); - UIWidget* createRow( PanelState& state, SettingBinding& binding ); + UIWidget* createRow( PanelState& state, SettingBinding& binding, pugi::xml_node layout ); UICheckBox* createBoolControl( PanelState& state, SettingBinding& binding ); void setCategoryEnabled( PanelState& state, const std::string& category, bool enabled, const std::string& excludedSetting = {} );