Make uiLists placed in popups usable

It's still not completely working - there are still some glitches - but far better than before.
To make buttons of the uiList work, you have to add a 'check' callback to the operator that invokes the menu. Only if it returns True, the uiList gets refreshed. To avoid this we have to make the region refresh tagging in the entire button handling a bit smarter.

Changes I had to do:
* Call uiList handling from menu/popup handling if needed.
* Make uiList handling use special popup refresh tag if placed in menu.
* Allow popups invoked from py operator to tag for refresh by using operator 'check' callback.
* Tag popup for refresh when resizing uiList.

Mostly fixes T48612.
This commit is contained in:
Julian Eisel 2016-06-08 15:51:01 +02:00
parent 37fc4b575f
commit fc96110bb5
Notes: blender-bot 2023-02-14 19:46:34 +01:00
Referenced by commit 936c176a71, Fix T48743: Broken menu key accelerators
Referenced by issue #48743, Moving the mouse ever so slightly breaks hotkey combos in menus
Referenced by issue blender/blender-addons#48612, template_list doesn't refresh in popup
3 changed files with 37 additions and 10 deletions

View File

@ -8436,6 +8436,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
uiListDyn *dyn_data;
int retval = WM_UI_HANDLER_CONTINUE;
int type = event->type, val = event->val;
bool redraw = false;
int mx, my;
ui_list = listbox->custom_data;
@ -8525,7 +8526,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
ui_apply_but_undo(listbox);
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(ar);
redraw = true;
}
retval = WM_UI_HANDLER_BREAK;
}
@ -8537,8 +8538,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
ui_list->list_grip += (type == WHEELUPMOUSE) ? -1 : 1;
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(ar);
redraw = true;
retval = WM_UI_HANDLER_BREAK;
}
else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
@ -8546,13 +8547,22 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
/* list template will clamp */
ui_list->list_scroll += (type == WHEELUPMOUSE) ? -1 : 1;
ED_region_tag_redraw(ar);
redraw = true;
retval = WM_UI_HANDLER_BREAK;
}
}
}
if (redraw) {
if (listbox->block->flag & UI_BLOCK_POPUP) {
/* popups need special refreshing */
ED_region_tag_refresh_ui(ar);
}
else {
ED_region_tag_redraw(ar);
}
}
return retval;
}
@ -9794,11 +9804,21 @@ static int ui_handle_menus_recursive(
}
else {
uiBlock *block = menu->region->uiblocks.first;
uiBut *listbox = ui_list_find_mouse_over(menu->region, event);
if (block->flag & UI_BLOCK_RADIAL)
if (block->flag & UI_BLOCK_RADIAL) {
retval = ui_pie_handler(C, event, menu);
else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK)
retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
}
else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) {
if (listbox) {
retval = ui_handle_list_event(C, event, menu->region, listbox);
}
if (retval == WM_UI_HANDLER_CONTINUE) {
retval = ui_handle_menu_event(
C, event, menu, level,
is_parent_inside, is_parent_menu, is_floating);
}
}
}
}

View File

@ -2818,7 +2818,7 @@ static void uilist_prepare(
layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
}
static void uilist_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSED(arg2))
static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiList *ui_list = arg1;
uiListDyn *dyn_data = ui_list->dyn_data;
@ -2831,6 +2831,9 @@ static void uilist_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSE
dyn_data->resize_prev += diff * UI_UNIT_Y;
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
}
/* In case uilist is in popup, we need special refreshing */
ED_region_tag_refresh_ui(CTX_wm_menu(C));
}
static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)

View File

@ -1391,7 +1391,7 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
}
}
static void dialog_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
static void popup_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
{
wmOperator *op = op_ptr;
if (op->type->check) {
@ -1423,7 +1423,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
UI_block_func_set(block, dialog_check_cb, op, NULL);
UI_block_func_set(block, popup_check_cb, op, NULL);
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
@ -1463,9 +1463,13 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
UI_block_func_set(block, popup_check_cb, op, NULL);
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
UI_block_func_set(block, NULL, NULL, NULL);
UI_block_bounds_set_popup(block, 4, 0, 0);
return block;