From f358843108e233aeba488d2dd033f35f947fd454 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 30 Jan 2024 17:44:56 +0100 Subject: [PATCH] UI: simplify layout panels C++ API This simplifies the C++ API for making layout panels. Now it is also more similar to the Python API. `uiLayoutPanel` is like `layout.panel` and `uiLayoutPanelProp` is like `layout.panel_prop`. Both, `uiLayoutPanel` and `uiLayoutPanelProp`, now exist in two variants. One that takes a label parameter and one that does not. If the label is passed in, only the panel body layout is returned. Otherwise, the header and body are returned for more customization. Pull Request: https://projects.blender.org/blender/blender/pulls/117670 --- .../blender/editors/include/UI_interface_c.hh | 47 +++++++++++++++---- .../editors/interface/interface_layout.cc | 44 +++++++++++++---- .../interface_template_node_inputs.cc | 4 +- source/blender/makesdna/DNA_screen_types.h | 2 +- source/blender/makesrna/intern/rna_ui_api.cc | 6 +-- .../intern/MOD_grease_pencil_color.cc | 4 +- .../intern/MOD_grease_pencil_mirror.cc | 4 +- .../intern/MOD_grease_pencil_noise.cc | 6 +-- .../intern/MOD_grease_pencil_offset.cc | 8 ++-- .../intern/MOD_grease_pencil_opacity.cc | 4 +- .../intern/MOD_grease_pencil_smooth.cc | 4 +- .../intern/MOD_grease_pencil_subdiv.cc | 4 +- .../intern/MOD_grease_pencil_thickness.cc | 4 +- .../intern/MOD_grease_pencil_tint.cc | 4 +- source/blender/modifiers/intern/MOD_nodes.cc | 20 ++++---- 15 files changed, 108 insertions(+), 57 deletions(-) diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index f98d8abd2d4..f70dd0e6945 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -2302,25 +2302,52 @@ struct PanelLayout { * \return A #PanelLayout containing layouts for both the header row and the panel body. If the * panel is closed and should not be drawn, the body layout will be NULL. */ -PanelLayout uiLayoutPanelWithHeader(const bContext *C, - uiLayout *layout, - PointerRNA *open_prop_owner, - const char *open_prop_name); +PanelLayout uiLayoutPanelProp(const bContext *C, + uiLayout *layout, + PointerRNA *open_prop_owner, + const char *open_prop_name); /** - * Variant of #uiLayoutPanelWithHeader() that automatically creates the header row with the - * given label name and only returns the body layout. + * Variant of #uiLayoutPanelProp that automatically creates the header row with the + * given label and only returns the body layout. * - * \param name: Text that's shown in the panel header. It should already be translated. + * \param label: Text that's shown in the panel header. It should already be translated. + * + * \return NULL if the panel is closed and should not be drawn, otherwise the layout where the + * sub-panel should be inserted into. + */ +uiLayout *uiLayoutPanelProp(const bContext *C, + uiLayout *layout, + PointerRNA *open_prop_owner, + const char *open_prop_name, + const char *label); + +/** + * Variant of #uiLayoutPanelProp that automatically stores the open-close-state in the root + * panel. When a dynamic number of panels is required, it's recommended to use #uiLayoutPanelProp + * instead of passing in generated idnames. + * + * \param idname: String that identifies the open-close-state in the root panel. + */ +PanelLayout uiLayoutPanel(const bContext *C, + uiLayout *layout, + const char *idname, + bool default_closed); + +/** + * Variant of #uiLayoutPanel that automatically creates the header row with the given label and + * only returns the body layout. + * + * \param label: Text that's shown in the panel header. It should already be translated. * * \return NULL if the panel is closed and should not be drawn, otherwise the layout where the * sub-panel should be inserted into. */ uiLayout *uiLayoutPanel(const bContext *C, uiLayout *layout, - const char *name, - PointerRNA *open_prop_owner, - const char *open_prop_name); + const char *idname, + bool default_closed, + const char *label); bool uiLayoutEndsWithPanelHeader(const uiLayout &layout); diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index cd5b443e8a6..82f76c2f106 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -4974,10 +4974,10 @@ uiLayout *uiLayoutRow(uiLayout *layout, bool align) return litem; } -PanelLayout uiLayoutPanelWithHeader(const bContext *C, - uiLayout *layout, - PointerRNA *open_prop_owner, - const char *open_prop_name) +PanelLayout uiLayoutPanelProp(const bContext *C, + uiLayout *layout, + PointerRNA *open_prop_owner, + const char *open_prop_name) { const ARegion *region = CTX_wm_region(C); @@ -5035,14 +5035,40 @@ PanelLayout uiLayoutPanelWithHeader(const bContext *C, return panel_layout; } +uiLayout *uiLayoutPanelProp(const bContext *C, + uiLayout *layout, + PointerRNA *open_prop_owner, + const char *open_prop_name, + const char *label) +{ + PanelLayout panel = uiLayoutPanelProp(C, layout, open_prop_owner, open_prop_name); + uiItemL(panel.header, label, ICON_NONE); + + return panel.body; +} + +PanelLayout uiLayoutPanel(const bContext *C, + uiLayout *layout, + const char *idname, + const bool default_closed) +{ + Panel *panel = uiLayoutGetRootPanel(layout); + BLI_assert(panel != nullptr); + + LayoutPanelState *state = BKE_panel_layout_panel_state_ensure(panel, idname, default_closed); + PointerRNA state_ptr = RNA_pointer_create(nullptr, &RNA_LayoutPanelState, state); + + return uiLayoutPanelProp(C, layout, &state_ptr, "is_open"); +} + uiLayout *uiLayoutPanel(const bContext *C, uiLayout *layout, - const char *name, - PointerRNA *open_prop_owner, - const char *open_prop_name) + const char *idname, + const bool default_closed, + const char *label) { - PanelLayout panel = uiLayoutPanelWithHeader(C, layout, open_prop_owner, open_prop_name); - uiItemL(panel.header, name, ICON_NONE); + PanelLayout panel = uiLayoutPanel(C, layout, idname, default_closed); + uiItemL(panel.header, label, ICON_NONE); return panel.body; } diff --git a/source/blender/editors/interface/interface_template_node_inputs.cc b/source/blender/editors/interface/interface_template_node_inputs.cc index 5b4c90f1417..d93c5385043 100644 --- a/source/blender/editors/interface/interface_template_node_inputs.cc +++ b/source/blender/editors/interface/interface_template_node_inputs.cc @@ -92,8 +92,8 @@ static void handle_node_declaration_items(bContext *C, LayoutPanelState *state = BKE_panel_layout_panel_state_ensure( root_panel, panel_idname.c_str(), panel_decl->default_collapsed); PointerRNA state_ptr = RNA_pointer_create(nullptr, &RNA_LayoutPanelState, state); - uiLayout *panel_layout = uiLayoutPanel( - C, layout, IFACE_(panel_decl->name.c_str()), &state_ptr, "is_open"); + uiLayout *panel_layout = uiLayoutPanelProp( + C, layout, &state_ptr, "is_open", IFACE_(panel_decl->name.c_str())); /* Draw panel buttons at the top of each panel section. */ if (panel_layout && panel_decl->draw_buttons) { panel_decl->draw_buttons(panel_layout, C, node_ptr); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index d118451aee4..dbea45671bb 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -173,7 +173,7 @@ typedef struct Panel { /** * List of #LayoutPanelState. This stores the open-close-state of layout-panels created with - * `layout.panel(...)` in Python. For more information on layout-panels, see `uiLayoutPanel`. + * `layout.panel(...)` in Python. For more information on layout-panels, see `uiLayoutPanelProp`. */ ListBase layout_panel_states; diff --git a/source/blender/makesrna/intern/rna_ui_api.cc b/source/blender/makesrna/intern/rna_ui_api.cc index bcc0279cf5f..efa639158c4 100644 --- a/source/blender/makesrna/intern/rna_ui_api.cc +++ b/source/blender/makesrna/intern/rna_ui_api.cc @@ -796,7 +796,7 @@ void rna_uiLayoutPanelProp(uiLayout *layout, return; } - PanelLayout panel_layout = uiLayoutPanelWithHeader(C, layout, data, property); + PanelLayout panel_layout = uiLayoutPanelProp(C, layout, data, property); *r_layout_header = panel_layout.header; *r_layout_body = panel_layout.body; } @@ -816,9 +816,7 @@ void rna_uiLayoutPanel(uiLayout *layout, *r_layout_body = nullptr; return; } - LayoutPanelState *state = BKE_panel_layout_panel_state_ensure(panel, idname, default_closed); - PointerRNA state_ptr = RNA_pointer_create(nullptr, &RNA_LayoutPanelState, state); - PanelLayout panel_layout = uiLayoutPanelWithHeader(C, layout, &state_ptr, "is_open"); + PanelLayout panel_layout = uiLayoutPanel(C, layout, idname, default_closed); *r_layout_header = panel_layout.header; *r_layout_body = panel_layout.body; } diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_color.cc b/source/blender/modifiers/intern/MOD_grease_pencil_color.cc index b7d940d7974..052644f48d8 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_color.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_color.cc @@ -227,8 +227,8 @@ static void panel_draw(const bContext *C, Panel *panel) panel, "influence", true); PointerRNA influence_state_ptr = RNA_pointer_create( nullptr, &RNA_LayoutPanelState, influence_panel_state); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", &influence_state_ptr, "is_open")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, &influence_state_ptr, "is_open", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_mirror.cc b/source/blender/modifiers/intern/MOD_grease_pencil_mirror.cc index f03f39c4cfa..43cdaf0dccb 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_mirror.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_mirror.cc @@ -224,8 +224,8 @@ static void panel_draw(const bContext *C, Panel *panel) PointerRNA influence_state_ptr = RNA_pointer_create( nullptr, &RNA_LayoutPanelState, influence_panel_state); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", &influence_state_ptr, "is_open")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, &influence_state_ptr, "is_open", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_noise.cc b/source/blender/modifiers/intern/MOD_grease_pencil_noise.cc index ad361ff8f80..160a745279b 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_noise.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_noise.cc @@ -262,7 +262,7 @@ static void panel_draw(const bContext *C, Panel *panel) uiItemR(col, ptr, "noise_offset", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(col, ptr, "seed", UI_ITEM_NONE, nullptr, ICON_NONE); - if (uiLayout *random_layout = uiLayoutPanel(C, layout, "Random", ptr, "open_random_panel")) { + if (uiLayout *random_layout = uiLayoutPanelProp(C, layout, ptr, "open_random_panel", "Random")) { uiItemR(random_layout, ptr, "use_random", UI_ITEM_NONE, IFACE_("Randomize"), ICON_NONE); uiLayout *random_col = uiLayoutColumn(random_layout, false); @@ -277,8 +277,8 @@ static void panel_draw(const bContext *C, Panel *panel) } } - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", ptr, "open_influence_panel")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, ptr, "open_influence_panel", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_offset.cc b/source/blender/modifiers/intern/MOD_grease_pencil_offset.cc index ec6b1a07389..13bdad1ad06 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_offset.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_offset.cc @@ -395,8 +395,8 @@ static void panel_draw(const bContext *C, Panel *panel) panel, "advanced", true); PointerRNA advanced_state_ptr = RNA_pointer_create( nullptr, &RNA_LayoutPanelState, advanced_panel_state); - if (uiLayout *advanced_panel = uiLayoutPanel( - C, layout, "Advanced", &advanced_state_ptr, "is_open")) + if (uiLayout *advanced_panel = uiLayoutPanelProp( + C, layout, &advanced_state_ptr, "is_open", "Advanced")) { uiItemR(advanced_panel, ptr, "offset_mode", UI_ITEM_NONE, nullptr, ICON_NONE); @@ -429,8 +429,8 @@ static void panel_draw(const bContext *C, Panel *panel) panel, "influence", true); PointerRNA influence_state_ptr = RNA_pointer_create( nullptr, &RNA_LayoutPanelState, influence_panel_state); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", &influence_state_ptr, "is_open")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, &influence_state_ptr, "is_open", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_opacity.cc b/source/blender/modifiers/intern/MOD_grease_pencil_opacity.cc index 87f37406297..ab30d69c8f8 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_opacity.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_opacity.cc @@ -260,8 +260,8 @@ static void panel_draw(const bContext *C, Panel *panel) panel, "influence", true); PointerRNA influence_state_ptr = RNA_pointer_create( nullptr, &RNA_LayoutPanelState, influence_panel_state); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", &influence_state_ptr, "is_open")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, &influence_state_ptr, "is_open", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_smooth.cc b/source/blender/modifiers/intern/MOD_grease_pencil_smooth.cc index 58f8255914a..fdc3427730c 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_smooth.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_smooth.cc @@ -218,8 +218,8 @@ static void panel_draw(const bContext *C, Panel *panel) uiItemR(col, ptr, "use_keep_shape", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(col, ptr, "use_smooth_ends", UI_ITEM_NONE, nullptr, ICON_NONE); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", ptr, "open_influence_panel")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, ptr, "open_influence_panel", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc b/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc index 57caba9f880..0dc6209abf3 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc @@ -160,8 +160,8 @@ static void panel_draw(const bContext *C, Panel *panel) uiItemR(layout, ptr, "subdivision_type", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(layout, ptr, "level", UI_ITEM_NONE, IFACE_("Subdivisions"), ICON_NONE); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", ptr, "open_influence_panel")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, ptr, "open_influence_panel", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_thickness.cc b/source/blender/modifiers/intern/MOD_grease_pencil_thickness.cc index 3b4647a53cc..cfff04dc4b2 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_thickness.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_thickness.cc @@ -197,8 +197,8 @@ static void panel_draw(const bContext *C, Panel *panel) uiItemR(row, ptr, "use_weight_factor", UI_ITEM_NONE, "", ICON_MOD_VERTEX_WEIGHT); } - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", ptr, "open_influence_panel")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, ptr, "open_influence_panel", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_tint.cc b/source/blender/modifiers/intern/MOD_grease_pencil_tint.cc index d1fae9038f2..b36b8d55303 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_tint.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_tint.cc @@ -437,8 +437,8 @@ static void panel_draw(const bContext *C, Panel *panel) panel, "influence", true); PointerRNA influence_state_ptr = RNA_pointer_create( nullptr, &RNA_LayoutPanelState, influence_panel_state); - if (uiLayout *influence_panel = uiLayoutPanel( - C, layout, "Influence", &influence_state_ptr, "is_open")) + if (uiLayout *influence_panel = uiLayoutPanelProp( + C, layout, &influence_state_ptr, "is_open", "Influence")) { modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr); modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr); diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index e3772a52fec..ff447d7568f 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1874,8 +1874,8 @@ static void draw_interface_panel_content(const bContext *C, NodesModifierPanel *panel = find_panel_by_id(nmd, sub_interface_panel.identifier); PointerRNA panel_ptr = RNA_pointer_create( modifier_ptr->owner_id, &RNA_NodesModifierPanel, panel); - if (uiLayout *panel_layout = uiLayoutPanel( - C, layout, sub_interface_panel.name, &panel_ptr, "is_open")) + if (uiLayout *panel_layout = uiLayoutPanelProp( + C, layout, &panel_ptr, "is_open", sub_interface_panel.name)) { draw_interface_panel_content(C, panel_layout, modifier_ptr, nmd, sub_interface_panel); } @@ -2002,13 +2002,13 @@ static void draw_manage_panel(const bContext *C, PointerRNA *modifier_ptr, NodesModifierData &nmd) { - if (uiLayout *panel_layout = uiLayoutPanel( - C, layout, IFACE_("Bake"), modifier_ptr, "open_bake_panel")) + if (uiLayout *panel_layout = uiLayoutPanelProp( + C, layout, modifier_ptr, "open_bake_panel", IFACE_("Bake"))) { draw_bake_panel(panel_layout, modifier_ptr); } - if (uiLayout *panel_layout = uiLayoutPanel( - C, layout, IFACE_("Named Attributes"), modifier_ptr, "open_named_attributes_panel")) + if (uiLayout *panel_layout = uiLayoutPanelProp( + C, layout, modifier_ptr, "open_named_attributes_panel", IFACE_("Named Attributes"))) { draw_named_attributes_panel(panel_layout, nmd); } @@ -2058,14 +2058,14 @@ static void panel_draw(const bContext *C, Panel *panel) modifier_panel_end(layout, ptr); if (has_output_attribute(*nmd)) { - if (uiLayout *panel_layout = uiLayoutPanel( - C, layout, IFACE_("Output Attributes"), ptr, "open_output_attributes_panel")) + if (uiLayout *panel_layout = uiLayoutPanelProp( + C, layout, ptr, "open_output_attributes_panel", IFACE_("Output Attributes"))) { draw_output_attributes_panel(C, panel_layout, *nmd, ptr); } } - if (uiLayout *panel_layout = uiLayoutPanel( - C, layout, IFACE_("Manage"), ptr, "open_manage_panel")) + if (uiLayout *panel_layout = uiLayoutPanelProp( + C, layout, ptr, "open_manage_panel", IFACE_("Manage"))) { draw_manage_panel(C, panel_layout, ptr, *nmd); }