diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2022-05-11 12:53:07 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-05-21 22:25:33 +0200 |
commit | 4edc33b4a6382175d3122270a5fab11b685a1afa (patch) | |
tree | 5f5d830ad48709f36ceb10276f0a01e3dd854f62 /Userland/Applications/ThemeEditor | |
parent | 423383e9aa1c0b66a1a6f73566ea6e1b4dbda8e5 (diff) | |
download | serenity-4edc33b4a6382175d3122270a5fab11b685a1afa.zip |
ThemeEditor: Arrange the theme properties into groups
This makes it clearer which properties are related, instead of them all
being in one list per tab.
Diffstat (limited to 'Userland/Applications/ThemeEditor')
-rw-r--r-- | Userland/Applications/ThemeEditor/MainWidget.cpp | 421 | ||||
-rw-r--r-- | Userland/Applications/ThemeEditor/MainWidget.h | 7 |
2 files changed, 231 insertions, 197 deletions
diff --git a/Userland/Applications/ThemeEditor/MainWidget.cpp b/Userland/Applications/ThemeEditor/MainWidget.cpp index b2bacf17fa..21f00d8c88 100644 --- a/Userland/Applications/ThemeEditor/MainWidget.cpp +++ b/Userland/Applications/ThemeEditor/MainWidget.cpp @@ -22,6 +22,7 @@ #include <LibGUI/Button.h> #include <LibGUI/FilePicker.h> #include <LibGUI/Frame.h> +#include <LibGUI/GroupBox.h> #include <LibGUI/Icon.h> #include <LibGUI/ItemListModel.h> #include <LibGUI/Label.h> @@ -36,129 +37,149 @@ namespace ThemeEditor { static const PropertyTab window_tab { "Windows", { - { Gfx::FlagRole::IsDark }, - { Gfx::AlignmentRole::TitleAlignment }, - { Gfx::MetricRole::TitleHeight }, - { Gfx::MetricRole::TitleButtonWidth }, - { Gfx::MetricRole::TitleButtonHeight }, - { Gfx::PathRole::TitleButtonIcons }, - { Gfx::FlagRole::TitleButtonsIconOnly }, - - { Gfx::MetricRole::BorderThickness }, - { Gfx::MetricRole::BorderRadius }, - - { Gfx::ColorRole::ActiveWindowBorder1 }, - { Gfx::ColorRole::ActiveWindowBorder2 }, - { Gfx::ColorRole::ActiveWindowTitle }, - { Gfx::ColorRole::ActiveWindowTitleShadow }, - { Gfx::ColorRole::ActiveWindowTitleStripes }, - { Gfx::PathRole::ActiveWindowShadow }, - - { Gfx::ColorRole::InactiveWindowBorder1 }, - { Gfx::ColorRole::InactiveWindowBorder2 }, - { Gfx::ColorRole::InactiveWindowTitle }, - { Gfx::ColorRole::InactiveWindowTitleShadow }, - { Gfx::ColorRole::InactiveWindowTitleStripes }, - { Gfx::PathRole::InactiveWindowShadow }, - - { Gfx::ColorRole::HighlightWindowBorder1 }, - { Gfx::ColorRole::HighlightWindowBorder2 }, - { Gfx::ColorRole::HighlightWindowTitle }, - { Gfx::ColorRole::HighlightWindowTitleShadow }, - { Gfx::ColorRole::HighlightWindowTitleStripes }, - - { Gfx::ColorRole::MovingWindowBorder1 }, - { Gfx::ColorRole::MovingWindowBorder2 }, - { Gfx::ColorRole::MovingWindowTitle }, - { Gfx::ColorRole::MovingWindowTitleShadow }, - { Gfx::ColorRole::MovingWindowTitleStripes }, - - { Gfx::ColorRole::Window }, - { Gfx::ColorRole::WindowText }, - - { Gfx::ColorRole::DesktopBackground }, - { Gfx::PathRole::TaskbarShadow }, + { "General", + { { Gfx::FlagRole::IsDark }, + { Gfx::AlignmentRole::TitleAlignment }, + { Gfx::MetricRole::TitleHeight }, + { Gfx::MetricRole::TitleButtonWidth }, + { Gfx::MetricRole::TitleButtonHeight }, + { Gfx::PathRole::TitleButtonIcons }, + { Gfx::FlagRole::TitleButtonsIconOnly } } }, + + { "Border", + { { Gfx::MetricRole::BorderThickness }, + { Gfx::MetricRole::BorderRadius } } }, + + { "Active Window", + { { Gfx::ColorRole::ActiveWindowBorder1 }, + { Gfx::ColorRole::ActiveWindowBorder2 }, + { Gfx::ColorRole::ActiveWindowTitle }, + { Gfx::ColorRole::ActiveWindowTitleShadow }, + { Gfx::ColorRole::ActiveWindowTitleStripes }, + { Gfx::PathRole::ActiveWindowShadow } } }, + + { "Inactive Window", + { { Gfx::ColorRole::InactiveWindowBorder1 }, + { Gfx::ColorRole::InactiveWindowBorder2 }, + { Gfx::ColorRole::InactiveWindowTitle }, + { Gfx::ColorRole::InactiveWindowTitleShadow }, + { Gfx::ColorRole::InactiveWindowTitleStripes }, + { Gfx::PathRole::InactiveWindowShadow } } }, + + { "Highlighted Window", + { { Gfx::ColorRole::HighlightWindowBorder1 }, + { Gfx::ColorRole::HighlightWindowBorder2 }, + { Gfx::ColorRole::HighlightWindowTitle }, + { Gfx::ColorRole::HighlightWindowTitleShadow }, + { Gfx::ColorRole::HighlightWindowTitleStripes } } }, + + { "Moving Window", + { { Gfx::ColorRole::MovingWindowBorder1 }, + { Gfx::ColorRole::MovingWindowBorder2 }, + { Gfx::ColorRole::MovingWindowTitle }, + { Gfx::ColorRole::MovingWindowTitleShadow }, + { Gfx::ColorRole::MovingWindowTitleStripes } } }, + + { "Contents", + { { Gfx::ColorRole::Window }, + { Gfx::ColorRole::WindowText } } }, + + { "Desktop", + { { Gfx::ColorRole::DesktopBackground }, + { Gfx::PathRole::TaskbarShadow } } }, } }; static const PropertyTab widgets_tab { "Widgets", { - { Gfx::ColorRole::Accent }, - { Gfx::ColorRole::Base }, - { Gfx::ColorRole::ThreedHighlight }, - { Gfx::ColorRole::ThreedShadow1 }, - { Gfx::ColorRole::ThreedShadow2 }, - { Gfx::ColorRole::HoverHighlight }, - - { Gfx::ColorRole::BaseText }, - { Gfx::ColorRole::DisabledTextFront }, - { Gfx::ColorRole::DisabledTextBack }, - { Gfx::ColorRole::PlaceholderText }, - - { Gfx::ColorRole::Link }, - { Gfx::ColorRole::ActiveLink }, - { Gfx::ColorRole::VisitedLink }, - - { Gfx::ColorRole::Button }, - { Gfx::ColorRole::ButtonText }, - - { Gfx::ColorRole::Tooltip }, - { Gfx::ColorRole::TooltipText }, - { Gfx::PathRole::TooltipShadow }, - - { Gfx::ColorRole::Tray }, - { Gfx::ColorRole::TrayText }, - - { Gfx::ColorRole::Ruler }, - { Gfx::ColorRole::RulerBorder }, - { Gfx::ColorRole::RulerActiveText }, - { Gfx::ColorRole::RulerInactiveText }, - - { Gfx::ColorRole::Gutter }, - { Gfx::ColorRole::GutterBorder }, - - { Gfx::ColorRole::RubberBandBorder }, - { Gfx::ColorRole::RubberBandFill }, - - { Gfx::ColorRole::MenuBase }, - { Gfx::ColorRole::MenuBaseText }, - { Gfx::ColorRole::MenuSelection }, - { Gfx::ColorRole::MenuSelectionText }, - { Gfx::ColorRole::MenuStripe }, - { Gfx::PathRole::MenuShadow }, - - { Gfx::ColorRole::FocusOutline }, - { Gfx::ColorRole::TextCursor }, - { Gfx::ColorRole::Selection }, - { Gfx::ColorRole::SelectionText }, - { Gfx::ColorRole::InactiveSelection }, - { Gfx::ColorRole::InactiveSelectionText }, - { Gfx::ColorRole::HighlightSearching }, - { Gfx::ColorRole::HighlightSearchingText }, + { "General", + { { Gfx::ColorRole::Accent }, + { Gfx::ColorRole::Base }, + { Gfx::ColorRole::ThreedHighlight }, + { Gfx::ColorRole::ThreedShadow1 }, + { Gfx::ColorRole::ThreedShadow2 }, + { Gfx::ColorRole::HoverHighlight } } }, + + { "Text", + { { Gfx::ColorRole::BaseText }, + { Gfx::ColorRole::DisabledTextFront }, + { Gfx::ColorRole::DisabledTextBack }, + { Gfx::ColorRole::PlaceholderText } } }, + + { "Links", + { { Gfx::ColorRole::Link }, + { Gfx::ColorRole::ActiveLink }, + { Gfx::ColorRole::VisitedLink } } }, + + { "Buttons", + { { Gfx::ColorRole::Button }, + { Gfx::ColorRole::ButtonText } } }, + + { "Tooltips", + { { Gfx::ColorRole::Tooltip }, + { Gfx::ColorRole::TooltipText }, + { Gfx::PathRole::TooltipShadow } } }, + + { "Trays", + { { Gfx::ColorRole::Tray }, + { Gfx::ColorRole::TrayText } } }, + + { "Ruler", + { { Gfx::ColorRole::Ruler }, + { Gfx::ColorRole::RulerBorder }, + { Gfx::ColorRole::RulerActiveText }, + { Gfx::ColorRole::RulerInactiveText } } }, + + { "Gutter", + { { Gfx::ColorRole::Gutter }, + { Gfx::ColorRole::GutterBorder } } }, + + { "Rubber Band", + { { Gfx::ColorRole::RubberBandBorder }, + { Gfx::ColorRole::RubberBandFill } } }, + + { "Menus", + { { Gfx::ColorRole::MenuBase }, + { Gfx::ColorRole::MenuBaseText }, + { Gfx::ColorRole::MenuSelection }, + { Gfx::ColorRole::MenuSelectionText }, + { Gfx::ColorRole::MenuStripe }, + { Gfx::PathRole::MenuShadow } } }, + + { "Selection", + { { Gfx::ColorRole::FocusOutline }, + { Gfx::ColorRole::TextCursor }, + { Gfx::ColorRole::Selection }, + { Gfx::ColorRole::SelectionText }, + { Gfx::ColorRole::InactiveSelection }, + { Gfx::ColorRole::InactiveSelectionText }, + { Gfx::ColorRole::HighlightSearching }, + { Gfx::ColorRole::HighlightSearchingText } } }, } }; static const PropertyTab syntax_highlighting_tab { "Syntax Highlighting", { - { Gfx::ColorRole::SyntaxComment }, - { Gfx::ColorRole::SyntaxControlKeyword }, - { Gfx::ColorRole::SyntaxIdentifier }, - { Gfx::ColorRole::SyntaxKeyword }, - { Gfx::ColorRole::SyntaxNumber }, - { Gfx::ColorRole::SyntaxOperator }, - { Gfx::ColorRole::SyntaxPreprocessorStatement }, - { Gfx::ColorRole::SyntaxPreprocessorValue }, - { Gfx::ColorRole::SyntaxPunctuation }, - { Gfx::ColorRole::SyntaxString }, - { Gfx::ColorRole::SyntaxType }, - { Gfx::ColorRole::SyntaxFunction }, - { Gfx::ColorRole::SyntaxVariable }, - { Gfx::ColorRole::SyntaxCustomType }, - { Gfx::ColorRole::SyntaxNamespace }, - { Gfx::ColorRole::SyntaxMember }, - { Gfx::ColorRole::SyntaxParameter }, + { "General", + { { Gfx::ColorRole::SyntaxComment }, + { Gfx::ColorRole::SyntaxControlKeyword }, + { Gfx::ColorRole::SyntaxIdentifier }, + { Gfx::ColorRole::SyntaxKeyword }, + { Gfx::ColorRole::SyntaxNumber }, + { Gfx::ColorRole::SyntaxOperator }, + { Gfx::ColorRole::SyntaxPreprocessorStatement }, + { Gfx::ColorRole::SyntaxPreprocessorValue }, + { Gfx::ColorRole::SyntaxPunctuation }, + { Gfx::ColorRole::SyntaxString }, + { Gfx::ColorRole::SyntaxType }, + { Gfx::ColorRole::SyntaxFunction }, + { Gfx::ColorRole::SyntaxVariable }, + { Gfx::ColorRole::SyntaxCustomType }, + { Gfx::ColorRole::SyntaxNamespace }, + { Gfx::ColorRole::SyntaxMember }, + { Gfx::ColorRole::SyntaxParameter } } }, } }; @@ -362,91 +383,99 @@ void MainWidget::add_property_tab(PropertyTab const& property_tab) properties_list->layout()->set_spacing(12); properties_list->layout()->set_margins({ 8 }); - for (auto const& property : property_tab.properties) { - NonnullRefPtr<GUI::Widget> row_widget = properties_list->add<GUI::Widget>(); - row_widget->set_fixed_height(24); - - property.role.visit( - [&](Gfx::AlignmentRole role) { - row_widget->load_from_gml(alignment_property_gml); - - auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); - name_label.set_text(to_string(role)); - - auto& alignment_picker = *row_widget->find_descendant_of_type_named<GUI::ComboBox>("combo_box"); - alignment_picker.set_model(*m_alignment_model); - alignment_picker.on_change = [&, role](auto&, auto& index) { - set_alignment(role, index.data(GUI::ModelRole::Custom).to_text_alignment(Gfx::TextAlignment::CenterLeft)); - }; - alignment_picker.set_selected_index(m_alignment_model->index_of(m_preview_widget->preview_palette().alignment(role)), GUI::AllowCallback::No); - - VERIFY(m_alignment_inputs[to_underlying(role)].is_null()); - m_alignment_inputs[to_underlying(role)] = alignment_picker; - }, - [&](Gfx::ColorRole role) { - row_widget->load_from_gml(color_property_gml); - - auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); - name_label.set_text(to_string(role)); - - auto& color_input = *row_widget->find_descendant_of_type_named<GUI::ColorInput>("color_input"); - color_input.on_change = [&, role] { - set_color(role, color_input.color()); - }; - color_input.set_color(m_preview_widget->preview_palette().color(role), GUI::AllowCallback::No); - - VERIFY(m_color_inputs[to_underlying(role)].is_null()); - m_color_inputs[to_underlying(role)] = color_input; - }, - [&](Gfx::FlagRole role) { - row_widget->load_from_gml(flag_property_gml); - - auto& checkbox = *row_widget->find_descendant_of_type_named<GUI::CheckBox>("checkbox"); - checkbox.set_text(to_string(role)); - checkbox.on_checked = [&, role](bool checked) { - set_flag(role, checked); - }; - checkbox.set_checked(m_preview_widget->preview_palette().flag(role), GUI::AllowCallback::No); - - VERIFY(m_flag_inputs[to_underlying(role)].is_null()); - m_flag_inputs[to_underlying(role)] = checkbox; - }, - [&](Gfx::MetricRole role) { - row_widget->load_from_gml(metric_property_gml); - - auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); - name_label.set_text(to_string(role)); - - auto& spin_box = *row_widget->find_descendant_of_type_named<GUI::SpinBox>("spin_box"); - spin_box.on_change = [&, role](int value) { - set_metric(role, value); - }; - spin_box.set_value(m_preview_widget->preview_palette().metric(role), GUI::AllowCallback::No); - - VERIFY(m_metric_inputs[to_underlying(role)].is_null()); - m_metric_inputs[to_underlying(role)] = spin_box; - }, - [&](Gfx::PathRole role) { - row_widget->load_from_gml(path_property_gml); - - auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); - name_label.set_text(to_string(role)); - - auto& path_input = *row_widget->find_descendant_of_type_named<GUI::TextBox>("path_input"); - path_input.on_change = [&, role] { - set_path(role, path_input.text()); - }; - path_input.set_text(m_preview_widget->preview_palette().path(role), GUI::AllowCallback::No); - - auto& path_picker_button = *row_widget->find_descendant_of_type_named<GUI::Button>("path_picker_button"); - auto picker_target = (role == Gfx::PathRole::TitleButtonIcons) ? PathPickerTarget::Folder : PathPickerTarget::File; - path_picker_button.on_click = [&, role, picker_target](auto) { - show_path_picker_dialog(to_string(role), path_input, picker_target); - }; - - VERIFY(m_path_inputs[to_underlying(role)].is_null()); - m_path_inputs[to_underlying(role)] = path_input; - }); + for (auto const& group : property_tab.property_groups) { + NonnullRefPtr<GUI::GroupBox> group_box = properties_list->add<GUI::GroupBox>(group.title); + group_box->set_layout<GUI::VerticalBoxLayout>(); + group_box->layout()->set_spacing(12); + // 1px less on the left makes the text line up with the group title. + group_box->layout()->set_margins({ 8, 8, 8, 7 }); + group_box->set_shrink_to_fit(true); + + for (auto const& property : group.properties) { + NonnullRefPtr<GUI::Widget> row_widget = group_box->add<GUI::Widget>(); + row_widget->set_fixed_height(22); + property.role.visit( + [&](Gfx::AlignmentRole role) { + row_widget->load_from_gml(alignment_property_gml); + + auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); + name_label.set_text(to_string(role)); + + auto& alignment_picker = *row_widget->find_descendant_of_type_named<GUI::ComboBox>("combo_box"); + alignment_picker.set_model(*m_alignment_model); + alignment_picker.on_change = [&, role](auto&, auto& index) { + set_alignment(role, index.data(GUI::ModelRole::Custom).to_text_alignment(Gfx::TextAlignment::CenterLeft)); + }; + alignment_picker.set_selected_index(m_alignment_model->index_of(m_preview_widget->preview_palette().alignment(role)), GUI::AllowCallback::No); + + VERIFY(m_alignment_inputs[to_underlying(role)].is_null()); + m_alignment_inputs[to_underlying(role)] = alignment_picker; + }, + [&](Gfx::ColorRole role) { + row_widget->load_from_gml(color_property_gml); + + auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); + name_label.set_text(to_string(role)); + + auto& color_input = *row_widget->find_descendant_of_type_named<GUI::ColorInput>("color_input"); + color_input.on_change = [&, role] { + set_color(role, color_input.color()); + }; + color_input.set_color(m_preview_widget->preview_palette().color(role), GUI::AllowCallback::No); + + VERIFY(m_color_inputs[to_underlying(role)].is_null()); + m_color_inputs[to_underlying(role)] = color_input; + }, + [&](Gfx::FlagRole role) { + row_widget->load_from_gml(flag_property_gml); + + auto& checkbox = *row_widget->find_descendant_of_type_named<GUI::CheckBox>("checkbox"); + checkbox.set_text(to_string(role)); + checkbox.on_checked = [&, role](bool checked) { + set_flag(role, checked); + }; + checkbox.set_checked(m_preview_widget->preview_palette().flag(role), GUI::AllowCallback::No); + + VERIFY(m_flag_inputs[to_underlying(role)].is_null()); + m_flag_inputs[to_underlying(role)] = checkbox; + }, + [&](Gfx::MetricRole role) { + row_widget->load_from_gml(metric_property_gml); + + auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); + name_label.set_text(to_string(role)); + + auto& spin_box = *row_widget->find_descendant_of_type_named<GUI::SpinBox>("spin_box"); + spin_box.on_change = [&, role](int value) { + set_metric(role, value); + }; + spin_box.set_value(m_preview_widget->preview_palette().metric(role), GUI::AllowCallback::No); + + VERIFY(m_metric_inputs[to_underlying(role)].is_null()); + m_metric_inputs[to_underlying(role)] = spin_box; + }, + [&](Gfx::PathRole role) { + row_widget->load_from_gml(path_property_gml); + + auto& name_label = *row_widget->find_descendant_of_type_named<GUI::Label>("name"); + name_label.set_text(to_string(role)); + + auto& path_input = *row_widget->find_descendant_of_type_named<GUI::TextBox>("path_input"); + path_input.on_change = [&, role] { + set_path(role, path_input.text()); + }; + path_input.set_text(m_preview_widget->preview_palette().path(role), GUI::AllowCallback::No); + + auto& path_picker_button = *row_widget->find_descendant_of_type_named<GUI::Button>("path_picker_button"); + auto picker_target = (role == Gfx::PathRole::TitleButtonIcons) ? PathPickerTarget::Folder : PathPickerTarget::File; + path_picker_button.on_click = [&, role, picker_target](auto) { + show_path_picker_dialog(to_string(role), path_input, picker_target); + }; + + VERIFY(m_path_inputs[to_underlying(role)].is_null()); + m_path_inputs[to_underlying(role)] = path_input; + }); + } } } diff --git a/Userland/Applications/ThemeEditor/MainWidget.h b/Userland/Applications/ThemeEditor/MainWidget.h index 8dfad9b105..d9df4b6c38 100644 --- a/Userland/Applications/ThemeEditor/MainWidget.h +++ b/Userland/Applications/ThemeEditor/MainWidget.h @@ -66,11 +66,16 @@ struct Property { Variant<Gfx::AlignmentRole, Gfx::ColorRole, Gfx::FlagRole, Gfx::MetricRole, Gfx::PathRole> role; }; -struct PropertyTab { +struct PropertyGroup { String title; Vector<Property> properties; }; +struct PropertyTab { + String title; + Vector<PropertyGroup> property_groups; +}; + class MainWidget final : public GUI::Widget { C_OBJECT(MainWidget); |