UI: Support pressing Ctrl+F over UI lists to search

Adds an operator invoked by default with Ctrl+F that while hovering a UI
list, opens the search field of the list and enables text input for it.
With this commit the search button may actually be out of view after
Ctrl+F still. The following commit adds auto-scroll to solve that.

A downside is that in the Properties, there also is Ctrl+F to start
the editor-wide search. That's not unusual in Blender though (e.g.
scolling with the mouse over a UI list also scrolls the list, not the
region).
This commit is contained in:
Julian Eisel 2021-07-13 15:44:44 +02:00 committed by Sybren A. Stüvel
parent 87c1c8112f
commit 89fd3afd1e
Notes: blender-bot 2023-02-14 09:02:41 +01:00
Referenced by issue #96705, Regression: Crash when pressing F3 outside a Blender window if Developer extras is on
2 changed files with 89 additions and 5 deletions

View File

@ -730,6 +730,8 @@ def km_user_interface(_params):
("anim.keyingset_button_add", {"type": 'K', "value": 'PRESS'}, None),
("anim.keyingset_button_remove", {"type": 'K', "value": 'PRESS', "alt": True}, None),
("ui.reset_default_button", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("all", True)]}),
# UI lists (polls check if there's a UI list under the cursor).
("ui.list_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
])
return keymap

View File

@ -74,6 +74,32 @@
#include "ED_screen.h"
#include "ED_text.h"
/* -------------------------------------------------------------------- */
/** \name Immediate redraw helper
*
* Generally handlers shouldn't do any redrawing, that includes the layout/button definitions. That
* violates the Model-View-Controller pattern.
*
* But there are some operators which really need to re-run the layout definitions for various
* reasons. For example, "Edit Source" does it to find out which exact Python code added a button.
* Other operators may need to access buttons that aren't currently visible. In Blender's UI code
* design that typically means just not adding the button in the first place, for a particular
* redraw. So the operator needs to change context and re-create the layout, so the button becomes
* available to act on.
*
* \{ */
static void ui_region_redraw_immediately(bContext *C, ARegion *region)
{
ED_region_do_layout(C, region);
WM_draw_region_viewport_bind(region);
ED_region_do_draw(C, region);
WM_draw_region_viewport_unbind(region);
region->do_draw = false;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Copy Data Path Operator
* \{ */
@ -1379,11 +1405,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
ED_region_do_layout(C, region);
WM_draw_region_viewport_bind(region);
ED_region_do_draw(C, region);
WM_draw_region_viewport_unbind(region);
region->do_draw = false;
ui_region_redraw_immediately(C, region);
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
BLI_ghashIterator_done(&ghi) == false;
@ -1835,6 +1857,64 @@ static void UI_OT_drop_color(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI List Search Operator
* \{ */
static bool ui_list_focused_poll(bContext *C)
{
const ARegion *region = CTX_wm_region(C);
const wmWindow *win = CTX_wm_window(C);
const uiList *list = UI_list_find_mouse_over(region, win->eventstate);
return list != NULL;
}
/**
* Ensure the filter options are set to be visible in the UI list.
* \return if the visibility changed, requiring a redraw.
*/
static bool ui_list_unhide_filter_options(uiList *list)
{
if (list->filter_flag & UILST_FLT_SHOW) {
/* Nothing to be done. */
return false;
}
list->filter_flag |= UILST_FLT_SHOW;
return true;
}
static int ui_list_start_filter_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
uiList *list = UI_list_find_mouse_over(region, event);
/* Poll should check. */
BLI_assert(list != NULL);
if (ui_list_unhide_filter_options(list)) {
ui_region_redraw_immediately(C, region);
}
if (!UI_textbutton_activate_rna(C, region, list, "filter_name")) {
return OPERATOR_CANCELLED;
}
return OPERATOR_FINISHED;
}
static void UI_OT_list_start_filter(wmOperatorType *ot)
{
ot->name = "List Filter";
ot->idname = "UI_OT_list_start_filter";
ot->description = "Start entering filter text for the list in focus";
ot->invoke = ui_list_start_filter_invoke;
ot->poll = ui_list_focused_poll;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operator & Keymap Registration
* \{ */
@ -1860,6 +1940,8 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_button_execute);
WM_operatortype_append(UI_OT_button_string_clear);
WM_operatortype_append(UI_OT_list_start_filter);
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
WM_operatortype_append(UI_OT_eyedropper_colorramp);