UI: Support C defined menu types to listen to notifiers

Needed to dynamically load assets as menu items, see cf98518055 and
99e5024e97. The next commit will add the listener for the node add menu.
This commit is contained in:
Julian Eisel 2022-11-01 17:36:36 +01:00
parent bcc2656299
commit 78a7d5cfcc
7 changed files with 39 additions and 5 deletions

View File

@ -385,6 +385,7 @@ typedef struct MenuType {
bool (*poll)(const struct bContext *C, struct MenuType *mt);
/* draw entirely, view changes should be handled here */
void (*draw)(const struct bContext *C, struct Menu *menu);
void (*listener)(const wmRegionListenerParams *params);
/* RNA integration */
ExtensionRNA rna_ext;

View File

@ -784,6 +784,9 @@ void UI_block_set_search_only(uiBlock *block, bool search_only);
* Can be called with C==NULL.
*/
void UI_block_free(const struct bContext *C, uiBlock *block);
void UI_block_listen(const uiBlock *block, const struct wmRegionListenerParams *listener_params);
/**
* Can be called with C==NULL.
*/
@ -3198,9 +3201,6 @@ void UI_interface_tag_script_reload(void);
/* Support click-drag motion which presses the button and closes a popover (like a menu). */
#define USE_UI_POPOVER_ONCE
void UI_block_views_listen(const uiBlock *block,
const struct wmRegionListenerParams *listener_params);
bool UI_view_item_is_active(const uiViewItemHandle *item_handle);
bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle);
/**

View File

@ -3474,6 +3474,7 @@ void UI_block_free(const bContext *C, uiBlock *block)
BLI_freelistN(&block->saferct);
BLI_freelistN(&block->color_pickers.list);
BLI_freelistN(&block->dynamic_listeners);
ui_block_free_button_groups(block);
ui_block_free_views(block);
@ -3481,6 +3482,20 @@ void UI_block_free(const bContext *C, uiBlock *block)
MEM_freeN(block);
}
void UI_block_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
{
/* Don't need to let invisible blocks (old blocks from previous redraw) listen. */
if (!block->active) {
return;
}
LISTBASE_FOREACH (uiBlockDynamicListener *, listener, &block->dynamic_listeners) {
listener->listener_func(listener_params);
}
ui_block_views_listen(block, listener_params);
}
void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
{
ARegion *region = CTX_wm_region(C);

View File

@ -477,6 +477,12 @@ typedef enum uiButtonGroupFlag {
} uiButtonGroupFlag;
ENUM_OPERATORS(uiButtonGroupFlag, UI_BUTTON_GROUP_PANEL_HEADER);
typedef struct uiBlockDynamicListener {
struct uiBlockDynamicListener *next, *prev;
void (*listener_func)(const struct wmRegionListenerParams *params);
} uiBlockDynamicListener;
struct uiBlock {
uiBlock *next, *prev;
@ -499,6 +505,8 @@ struct uiBlock {
* state that is persistent over redraws (e.g. collapsed tree-view items). */
ListBase views;
ListBase dynamic_listeners; /* #uiBlockDynamicListener */
char name[UI_MAX_NAME_STR];
float winmat[4][4];
@ -1540,6 +1548,8 @@ void ui_interface_tag_script_reload_queries(void);
/* interface_view.cc */
void ui_block_free_views(struct uiBlock *block);
void ui_block_views_listen(const uiBlock *block,
const struct wmRegionListenerParams *listener_params);
uiViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block,
const uiViewHandle *new_view);

View File

@ -5814,6 +5814,14 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
}
if (mt->listener) {
/* Forward the menu type listener to the block we're drawing in. */
uiBlock *block = uiLayoutGetBlock(layout);
uiBlockDynamicListener *listener = MEM_mallocN(sizeof(*listener), "uiBlockDynamicListener");
listener->listener_func = mt->listener;
BLI_addtail(&block->dynamic_listeners, listener);
}
if (layout->context) {
CTX_store_set(C, layout->context);
}

View File

@ -81,7 +81,7 @@ void ui_block_free_views(uiBlock *block)
}
}
void UI_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
{
ARegion *region = listener_params->region;

View File

@ -147,7 +147,7 @@ void ED_region_do_listen(wmRegionListenerParams *params)
}
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
UI_block_views_listen(block, params);
UI_block_listen(block, params);
}
LISTBASE_FOREACH (uiList *, list, &region->ui_lists) {