From e3d4cf9b3d0ebbea62df2134af0228a006d489f1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 26 Sep 2023 18:37:28 +0200 Subject: [PATCH] UI: Allow popover panels to register own notifier listeners This is necessary to let popovers redraw when asynchronously loading data. For example to display assets or asset catalogs as they get loaded. Needed for the asset shelf catalog selector popover. Menus already do the same to allow populating the menu with assets as they get loaded. --- source/blender/blenkernel/BKE_screen.hh | 5 +++++ source/blender/editors/interface/interface.cc | 9 +++++++++ source/blender/editors/interface/interface_intern.hh | 4 ++++ source/blender/editors/interface/interface_layout.cc | 9 +++++---- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_screen.hh b/source/blender/blenkernel/BKE_screen.hh index 0a42158df85..a85ea5c9ebf 100644 --- a/source/blender/blenkernel/BKE_screen.hh +++ b/source/blender/blenkernel/BKE_screen.hh @@ -293,6 +293,11 @@ struct PanelType { void (*draw_header_preset)(const bContext *C, Panel *panel); /* draw entirely, view changes should be handled here */ void (*draw)(const bContext *C, Panel *panel); + /** + * Listener to redraw the region this is contained in on changes. Only used for panels displayed + * in popover regions. + */ + void (*listener)(const wmRegionListenerParams *params); /* For instanced panels corresponding to a list: */ diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index dd2e0a1eb71..1b7799e84e7 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -3682,6 +3682,15 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eU return block; } +void ui_block_add_dynamic_listener(uiBlock *block, + void (*listener_func)(const wmRegionListenerParams *params)) +{ + uiBlockDynamicListener *listener = static_cast( + MEM_mallocN(sizeof(*listener), __func__)); + listener->listener_func = listener_func; + BLI_addtail(&block->dynamic_listeners, listener); +} + eUIEmbossType UI_block_emboss_get(uiBlock *block) { return block->emboss; diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index c06a8ac7d7f..aef2dc8a7fb 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -664,6 +664,10 @@ void ui_region_to_window(const ARegion *region, int *x, int *y); */ void ui_region_winrct_get_no_margin(const ARegion *region, rcti *r_rect); +/** Register a listener callback to this block to tag the area/region for redraw. */ +void ui_block_add_dynamic_listener(uiBlock *block, + void (*listener_func)(const wmRegionListenerParams *params)); + /** * Reallocate the button (new address is returned) for a new button type. * This should generally be avoided and instead the correct type be created right away. diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index 1fb5268ccca..82c22a326e0 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -5928,10 +5928,7 @@ void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout) } if (mt->listener) { /* Forward the menu type listener to the block we're drawing in. */ - uiBlockDynamicListener *listener = static_cast( - MEM_mallocN(sizeof(*listener), __func__)); - listener->listener_func = mt->listener; - BLI_addtail(&block->dynamic_listeners, listener); + ui_block_add_dynamic_listener(block, mt->listener); } if (layout->context) { @@ -5973,6 +5970,10 @@ static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, panel->type = pt; panel->flag = PNL_POPOVER; + if (pt->listener) { + ui_block_add_dynamic_listener(uiLayoutGetBlock(layout), pt->listener); + } + uiLayout *last_item = static_cast(layout->items.last); /* Draw main panel. */