mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-02 11:10:31 +03:00
Implemented two more eager-construction optimizations:
- Each option now uses one complete XML template containing both its row and control. - Those immutable XML templates are parsed once and reused through loadLayoutNodes().
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
#include "uitreeviewfs.hpp"
|
#include "uitreeviewfs.hpp"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#define PUGIXML_HEADER_ONLY
|
||||||
|
#include <pugixml/pugixml.hpp>
|
||||||
|
|
||||||
using namespace EE::UI::Models;
|
using namespace EE::UI::Models;
|
||||||
|
|
||||||
@@ -238,17 +240,36 @@ static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
|||||||
</vbox>
|
</vbox>
|
||||||
)xml";
|
)xml";
|
||||||
|
|
||||||
static constexpr const char* SETTINGS_ROW_LAYOUT = R"xml(
|
static std::string settingsRowLayout( std::string_view control ) {
|
||||||
|
return R"xml(
|
||||||
<vbox lw="mp" lh="wc" class="settings_option">
|
<vbox lw="mp" lh="wc" class="settings_option">
|
||||||
<hbox lw="mp" lh="wc" class="settings_option_content">
|
<hbox lw="mp" lh="wc" class="settings_option_content">
|
||||||
<vbox lw="0" lw8="1" lh="wc">
|
<vbox lw="0" lw8="1" lh="wc">
|
||||||
<TextView id="setting_name" lw="mp" lh="wc" class="settings_option_name" focusable="false" />
|
<TextView id="setting_name" lw="mp" lh="wc" class="settings_option_name" focusable="false" />
|
||||||
<TextView id="setting_description" lw="mp" lh="wc" class="settings_option_description" focusable="false" />
|
<TextView id="setting_description" lw="mp" lh="wc" class="settings_option_description" focusable="false" />
|
||||||
</vbox>
|
</vbox>
|
||||||
<hbox id="setting_control" lw="wc" lh="wc" class="settings_option_control" />
|
<hbox id="setting_control" lw="wc" lh="wc" class="settings_option_control">
|
||||||
|
)xml" + std::string( control ) +
|
||||||
|
R"xml(
|
||||||
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
)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(
|
static constexpr const char* SETTINGS_CATEGORY_HEADING_LAYOUT = R"xml(
|
||||||
<TextView lw="mp" lh="wc" class="settings_category_heading" visible="false" focusable="false" />
|
<TextView lw="mp" lh="wc" class="settings_category_heading" visible="false" focusable="false" />
|
||||||
@@ -256,16 +277,18 @@ static constexpr const char* SETTINGS_CATEGORY_HEADING_LAYOUT = R"xml(
|
|||||||
static constexpr const char* SETTINGS_SUBCATEGORY_HEADING_LAYOUT = R"xml(
|
static constexpr const char* SETTINGS_SUBCATEGORY_HEADING_LAYOUT = R"xml(
|
||||||
<TextView lw="mp" lh="wc" class="settings_subcategory_heading" visible="false" focusable="false" />
|
<TextView lw="mp" lh="wc" class="settings_subcategory_heading" visible="false" focusable="false" />
|
||||||
)xml";
|
)xml";
|
||||||
static constexpr const char* SETTINGS_BOOL_LAYOUT = R"xml(<CheckBox class="settings_bool" />)xml";
|
static const SettingsLayoutTemplate SETTINGS_BOOL_ROW_LAYOUT( settingsRowLayout(
|
||||||
static constexpr const char* SETTINGS_CHOICE_LAYOUT =
|
R"xml(<CheckBox id="setting_control_widget" class="settings_bool" />)xml" ) );
|
||||||
R"xml(<DropDownModelList class="settings_choice" />)xml";
|
static const SettingsLayoutTemplate SETTINGS_CHOICE_ROW_LAYOUT( settingsRowLayout(
|
||||||
static constexpr const char* SETTINGS_EDITABLE_CHOICE_LAYOUT =
|
R"xml(<DropDownModelList id="setting_control_widget" class="settings_choice" />)xml" ) );
|
||||||
R"xml(<ComboBox class="settings_editable_choice" popup-to-root="true" />)xml";
|
static const SettingsLayoutTemplate SETTINGS_EDITABLE_CHOICE_ROW_LAYOUT( settingsRowLayout(
|
||||||
static constexpr const char* SETTINGS_INTEGER_LAYOUT =
|
R"xml(<ComboBox id="setting_control_widget" class="settings_editable_choice" popup-to-root="true" />)xml" ) );
|
||||||
R"xml(<SpinBox class="settings_integer" />)xml";
|
static const SettingsLayoutTemplate SETTINGS_INTEGER_ROW_LAYOUT( settingsRowLayout(
|
||||||
static constexpr const char* SETTINGS_TEXT_LAYOUT = R"xml(<TextInput class="settings_text" />)xml";
|
R"xml(<SpinBox id="setting_control_widget" class="settings_integer" />)xml" ) );
|
||||||
static constexpr const char* SETTINGS_ACTION_LAYOUT =
|
static const SettingsLayoutTemplate SETTINGS_TEXT_ROW_LAYOUT( settingsRowLayout(
|
||||||
R"xml(<PushButton class="settings_action" />)xml";
|
R"xml(<TextInput id="setting_control_widget" class="settings_text" />)xml" ) );
|
||||||
|
static const SettingsLayoutTemplate SETTINGS_ACTION_ROW_LAYOUT( settingsRowLayout(
|
||||||
|
R"xml(<PushButton id="setting_control_widget" class="settings_action" />)xml" ) );
|
||||||
|
|
||||||
static void disableTabFocusTree( Node* node ) {
|
static void disableTabFocusTree( Node* node ) {
|
||||||
if ( node->isWidget() )
|
if ( node->isWidget() )
|
||||||
@@ -485,8 +508,9 @@ void SettingsPanel::setupCategories( PanelState& panel ) {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
UIWidget* SettingsPanel::createRow( PanelState& panel, SettingBinding& binding ) {
|
UIWidget* SettingsPanel::createRow( PanelState& panel, SettingBinding& binding,
|
||||||
auto* row = mApp->getUISceneNode()->loadLayoutFromString( SETTINGS_ROW_LAYOUT, panel.settings );
|
pugi::xml_node layout ) {
|
||||||
|
auto* row = mApp->getUISceneNode()->loadLayoutNodes( layout, panel.settings, 0 );
|
||||||
row->setId( "setting_" + binding.id );
|
row->setId( "setting_" + binding.id );
|
||||||
row->find<UITextView>( "setting_name" )->setText( binding.name );
|
row->find<UITextView>( "setting_name" )->setText( binding.name );
|
||||||
auto* description = row->find<UITextView>( "setting_description" );
|
auto* description = row->find<UITextView>( "setting_description" );
|
||||||
@@ -517,12 +541,9 @@ void SettingsPanel::addBool( PanelState& panel, SettingBinding binding, std::fun
|
|||||||
}
|
}
|
||||||
|
|
||||||
UICheckBox* SettingsPanel::createBoolControl( PanelState& panel, SettingBinding& binding ) {
|
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" );
|
row->addClass( "settings_boolean_option" );
|
||||||
auto* check = mApp->getUISceneNode()
|
auto* check = row->find<UICheckBox>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_BOOL_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UICheckBox>();
|
|
||||||
auto toggle = [check]( const Event* ) { check->setChecked( !check->isChecked() ); };
|
auto toggle = [check]( const Event* ) { check->setChecked( !check->isChecked() ); };
|
||||||
panel.connections +=
|
panel.connections +=
|
||||||
row->find<UITextView>( "setting_name" )->connect( Event::MouseClick, toggle );
|
row->find<UITextView>( "setting_name" )->connect( Event::MouseClick, toggle );
|
||||||
@@ -535,11 +556,8 @@ void SettingsPanel::addChoice( PanelState& panel, SettingBinding binding,
|
|||||||
const std::vector<String>& choices, std::function<size_t()> get,
|
const std::vector<String>& choices, std::function<size_t()> get,
|
||||||
std::function<void( size_t )> set,
|
std::function<void( size_t )> set,
|
||||||
std::vector<String> choiceDescriptions ) {
|
std::vector<String> choiceDescriptions ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding, SETTINGS_CHOICE_ROW_LAYOUT.root() );
|
||||||
auto* dropDown = mApp->getUISceneNode()
|
auto* dropDown = row->find<UIDropDownModelList>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_CHOICE_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UIDropDownModelList>();
|
|
||||||
auto model = ItemListOwnerModel<String>::create( choices );
|
auto model = ItemListOwnerModel<String>::create( choices );
|
||||||
dropDown->setModel( model );
|
dropDown->setModel( model );
|
||||||
const size_t selected = get();
|
const size_t selected = get();
|
||||||
@@ -566,11 +584,8 @@ void SettingsPanel::addEditableChoice( PanelState& panel, SettingBinding binding
|
|||||||
const std::vector<String>& choices,
|
const std::vector<String>& choices,
|
||||||
std::function<String()> get,
|
std::function<String()> get,
|
||||||
std::function<bool( const String& )> set ) {
|
std::function<bool( const String& )> set ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding, SETTINGS_EDITABLE_CHOICE_ROW_LAYOUT.root() );
|
||||||
auto* combo = mApp->getUISceneNode()
|
auto* combo = row->find<UIComboBox>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_EDITABLE_CHOICE_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UIComboBox>();
|
|
||||||
for ( const auto& choice : choices )
|
for ( const auto& choice : choices )
|
||||||
combo->getListBox()->addListBoxItem( choice );
|
combo->getListBox()->addListBoxItem( choice );
|
||||||
combo->setText( get() );
|
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,
|
void SettingsPanel::addInteger( PanelState& panel, SettingBinding binding, int min, int max,
|
||||||
std::function<int()> get, std::function<void( int )> set ) {
|
std::function<int()> get, std::function<void( int )> set ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding, SETTINGS_INTEGER_ROW_LAYOUT.root() );
|
||||||
auto* spin = mApp->getUISceneNode()
|
auto* spin = row->find<UISpinBox>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UISpinBox>();
|
|
||||||
spin->setMinValue( min )->setMaxValue( max );
|
spin->setMinValue( min )->setMaxValue( max );
|
||||||
spin->unsetTabFocusable();
|
spin->unsetTabFocusable();
|
||||||
spin->getButtonPushUp()->asType<UIWidget>()->unsetTabFocusable();
|
spin->getButtonPushUp()->asType<UIWidget>()->unsetTabFocusable();
|
||||||
@@ -610,11 +622,8 @@ void SettingsPanel::addText( PanelState& panel, SettingBinding binding,
|
|||||||
std::function<std::string()> get,
|
std::function<std::string()> get,
|
||||||
std::function<bool( const std::string& )> set,
|
std::function<bool( const std::string& )> set,
|
||||||
bool commitOnFocusLoss ) {
|
bool commitOnFocusLoss ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding, SETTINGS_TEXT_ROW_LAYOUT.root() );
|
||||||
auto* input = mApp->getUISceneNode()
|
auto* input = row->find<UITextInput>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_TEXT_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UITextInput>();
|
|
||||||
input->setText( String::fromUtf8( get() ) );
|
input->setText( String::fromUtf8( get() ) );
|
||||||
auto commit = [input, set = std::move( set )]( const Event* ) {
|
auto commit = [input, set = std::move( set )]( const Event* ) {
|
||||||
std::string text = input->getText().toUtf8();
|
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,
|
void SettingsPanel::addFloat( PanelState& panel, SettingBinding binding, double min, double max,
|
||||||
double step, std::function<double()> get,
|
double step, std::function<double()> get,
|
||||||
std::function<void( double )> set ) {
|
std::function<void( double )> set ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding, SETTINGS_INTEGER_ROW_LAYOUT.root() );
|
||||||
auto* spin = mApp->getUISceneNode()
|
auto* spin = row->find<UISpinBox>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UISpinBox>();
|
|
||||||
spin->setMinValue( min )->setMaxValue( max )->setClickStep( step );
|
spin->setMinValue( min )->setMaxValue( max )->setClickStep( step );
|
||||||
spin->allowFloatingPoint( true )->setValue( get() );
|
spin->allowFloatingPoint( true )->setValue( get() );
|
||||||
spin->unsetTabFocusable();
|
spin->unsetTabFocusable();
|
||||||
@@ -655,11 +661,8 @@ void SettingsPanel::addFloat( PanelState& panel, SettingBinding binding, double
|
|||||||
|
|
||||||
void SettingsPanel::addAction( PanelState& panel, SettingBinding binding, const String& buttonText,
|
void SettingsPanel::addAction( PanelState& panel, SettingBinding binding, const String& buttonText,
|
||||||
std::function<void()> action ) {
|
std::function<void()> action ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding, SETTINGS_ACTION_ROW_LAYOUT.root() );
|
||||||
auto* button = mApp->getUISceneNode()
|
auto* button = row->find<UIPushButton>( "setting_control_widget" );
|
||||||
->loadLayoutFromString( SETTINGS_ACTION_LAYOUT,
|
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
|
||||||
->asType<UIPushButton>();
|
|
||||||
button->setText( buttonText );
|
button->setText( buttonText );
|
||||||
panel.connections += button->connect(
|
panel.connections += button->connect(
|
||||||
Event::MouseClick, [action = std::move( action )]( const Event* ) { action(); } );
|
Event::MouseClick, [action = std::move( action )]( const Event* ) { action(); } );
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class SettingsPanel {
|
|||||||
std::function<double()> get, std::function<void( double )> set );
|
std::function<double()> get, std::function<void( double )> set );
|
||||||
void addAction( PanelState& state, SettingBinding binding, const String& buttonText,
|
void addAction( PanelState& state, SettingBinding binding, const String& buttonText,
|
||||||
std::function<void()> action );
|
std::function<void()> action );
|
||||||
UIWidget* createRow( PanelState& state, SettingBinding& binding );
|
UIWidget* createRow( PanelState& state, SettingBinding& binding, pugi::xml_node layout );
|
||||||
UICheckBox* createBoolControl( PanelState& state, SettingBinding& binding );
|
UICheckBox* createBoolControl( PanelState& state, SettingBinding& binding );
|
||||||
void setCategoryEnabled( PanelState& state, const std::string& category, bool enabled,
|
void setCategoryEnabled( PanelState& state, const std::string& category, bool enabled,
|
||||||
const std::string& excludedSetting = {} );
|
const std::string& excludedSetting = {} );
|
||||||
|
|||||||
Reference in New Issue
Block a user