From 3e32a68f384d380ea9ce0a0a6fbf47c9ad2a78e4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 27 Oct 2021 15:50:14 +0200 Subject: UI: Refactor how dragging onto text buttons works, fixing issues There was a bunch of special handling to support dropping data-blocks onto string or search-menu buttons, to change the value of these. This refactor makes that case use the normal drop-box design, where an operator is executed on drop that gets input properties set by the drop-box. This should also make it easier to add support for dragging assets into these buttons. In addition this fixes an issue: Two tooltips were shown when dragging assets over text buttons. None should be shown, because this isn't supported. --- .../editors/interface/interface_dropboxes.cc | 23 ++++++ .../blender/editors/interface/interface_handlers.c | 85 ++++++++-------------- .../blender/editors/interface/interface_intern.h | 1 + source/blender/editors/interface/interface_ops.c | 34 +++++++++ 4 files changed, 90 insertions(+), 53 deletions(-) (limited to 'source/blender/editors/interface') diff --git a/source/blender/editors/interface/interface_dropboxes.cc b/source/blender/editors/interface/interface_dropboxes.cc index ab0c7e088e2..81a1354cbe7 100644 --- a/source/blender/editors/interface/interface_dropboxes.cc +++ b/source/blender/editors/interface/interface_dropboxes.cc @@ -24,6 +24,8 @@ #include "MEM_guardedalloc.h" +#include "RNA_access.h" + #include "WM_api.h" #include "UI_interface.h" @@ -59,6 +61,21 @@ static char *ui_tree_view_drop_tooltip(bContext *C, return UI_tree_view_item_drop_tooltip(hovered_tree_item, drag); } +/* ---------------------------------------------------------------------- */ + +static bool ui_drop_name_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event)) +{ + return UI_but_active_drop_name(C) && (drag->type == WM_DRAG_ID); +} + +static void ui_drop_name_copy(wmDrag *drag, wmDropBox *drop) +{ + const ID *id = WM_drag_get_local_ID(drag, 0); + RNA_string_set(drop->ptr, "string", id->name + 2); +} + +/* ---------------------------------------------------------------------- */ + void ED_dropboxes_ui() { ListBase *lb = WM_dropboxmap_find("User Interface", SPACE_EMPTY, 0); @@ -69,4 +86,10 @@ void ED_dropboxes_ui() nullptr, nullptr, ui_tree_view_drop_tooltip); + WM_dropbox_add(lb, + "UI_OT_drop_name", + ui_drop_name_poll, + ui_drop_name_copy, + WM_drag_free_imported_drag_ID, + nullptr); } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6dd6f9eb359..51ebe5399b3 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2442,39 +2442,6 @@ static void ui_apply_but( /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Button Drop Event - * \{ */ - -/* only call if event type is EVT_DROP */ -static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleButtonData *data) -{ - ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */ - - LISTBASE_FOREACH (wmDrag *, wmd, drags) { - /* TODO: asset dropping. */ - if (wmd->type == WM_DRAG_ID) { - /* align these types with UI_but_active_drop_name */ - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { - ID *id = WM_drag_get_local_ID(wmd, 0); - - button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); - - ui_textedit_string_set(but, data, id->name + 2); - - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) { - but->changed = true; - ui_searchbox_update(C, data->searchbox, but, true); - } - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - } - } -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Button Copy & Paste * \{ */ @@ -2672,15 +2639,9 @@ static void ui_but_copy_text(uiBut *but, char *output, int output_len_max) static void ui_but_paste_text(bContext *C, uiBut *but, uiHandleButtonData *data, char *buf_paste) { - button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); - ui_textedit_string_set(but, but->active, buf_paste); - - if (but->type == UI_BTYPE_SEARCH_MENU) { - but->changed = true; - ui_searchbox_update(C, data->searchbox, but, true); - } - - button_activate_state(C, but, BUTTON_STATE_EXIT); + BLI_assert(but->active == data); + UNUSED_VARS_NDEBUG(data); + ui_but_set_string_interactive(C, but, buf_paste); } static void ui_but_copy_colorband(uiBut *but) @@ -3024,6 +2985,24 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], /** \name Button Text Selection/Editing * \{ */ +/** + * Use handling code to set a string for the button. Handles the case where the string is set for a + * search button while the search menu is open, so the results are updated accordingly. + * This is basically the same as pasting the string into the button. + */ +void ui_but_set_string_interactive(bContext *C, uiBut *but, const char *value) +{ + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + ui_textedit_string_set(but, but->active, value); + + if (but->type == UI_BTYPE_SEARCH_MENU && but->active) { + but->changed = true; + ui_searchbox_update(C, but->active->searchbox, but, true); + } + + button_activate_state(C, but, BUTTON_STATE_EXIT); +} + void ui_but_active_string_clear_and_exit(bContext *C, uiBut *but) { if (!but->active) { @@ -7949,7 +7928,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * /* Only hard-coded stuff here, button interactions with configurable * keymaps are handled using operators (see #ED_keymap_ui). */ - if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) { + if (data->state == BUTTON_STATE_HIGHLIGHT) { /* handle copy and paste */ bool is_press_ctrl_but_no_shift = event->val == KM_PRESS && IS_EVENT_MOD(event, ctrl, oskey) && @@ -7998,11 +7977,6 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * return WM_UI_HANDLER_BREAK; } - /* handle drop */ - if (event->type == EVT_DROP) { - ui_but_drop(C, event, but, data); - } - if ((data->state == BUTTON_STATE_HIGHLIGHT) && ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, EVT_PADENTER, EVT_RETKEY) && (event->val == KM_RELEASE) && @@ -11716,20 +11690,25 @@ void UI_screen_free_active_but(const bContext *C, bScreen *screen) } } -/* returns true if highlighted button allows drop of names */ -/* called in region context */ -bool UI_but_active_drop_name(bContext *C) +uiBut *UI_but_active_drop_name_button(const bContext *C) { ARegion *region = CTX_wm_region(C); uiBut *but = ui_region_find_active_but(region); if (but) { if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { - return true; + return but; } } - return false; + return NULL; +} + +/* returns true if highlighted button allows drop of names */ +/* called in region context */ +bool UI_but_active_drop_name(const bContext *C) +{ + return UI_but_active_drop_name_button(C) != NULL; } bool UI_but_active_drop_color(bContext *C) diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 28227c2331a..f766bb1465f 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -680,6 +680,7 @@ extern bool ui_but_string_eval_number(struct bContext *C, extern int ui_but_string_get_max_length(uiBut *but); /* Clear & exit the active button's string. */ extern void ui_but_active_string_clear_and_exit(struct bContext *C, uiBut *but) ATTR_NONNULL(); +extern void ui_but_set_string_interactive(struct bContext *C, uiBut *but, const char *value); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); void ui_def_but_icon(uiBut *but, const int icon, const int flag); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 1a1d52b0425..c962a1107ae 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1863,6 +1863,39 @@ static void UI_OT_drop_color(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Drop Name Operator + * \{ */ + +static int drop_name_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + uiBut *but = UI_but_active_drop_name_button(C); + char *str = RNA_string_get_alloc(op->ptr, "string", NULL, 0, NULL); + + if (str) { + ui_but_set_string_interactive(C, but, str); + MEM_freeN(str); + } + + return OPERATOR_FINISHED; +} + +static void UI_OT_drop_name(wmOperatorType *ot) +{ + ot->name = "Drop Name"; + ot->idname = "UI_OT_drop_name"; + ot->description = "Drop name to button"; + + ot->poll = ED_operator_regionactive; + ot->invoke = drop_name_invoke; + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + + RNA_def_string( + ot->srna, "string", NULL, 0, "String", "The string value to drop into the button"); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name UI List Search Operator * \{ */ @@ -2025,6 +2058,7 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_copy_to_selected_button); WM_operatortype_append(UI_OT_jump_to_target_button); WM_operatortype_append(UI_OT_drop_color); + WM_operatortype_append(UI_OT_drop_name); #ifdef WITH_PYTHON WM_operatortype_append(UI_OT_editsource); WM_operatortype_append(UI_OT_edittranslation_init); -- cgit v1.2.3