diff options
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 5 | ||||
-rw-r--r-- | source/blender/editors/include/UI_tree_view.hh | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_context_menu.c | 12 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 8 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_ops.c | 44 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_query.c | 15 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_view.cc | 10 | ||||
-rw-r--r-- | source/blender/editors/interface/tree_view.cc | 13 |
9 files changed, 109 insertions, 0 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index c536eff771d..ddd5e77cbb6 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2783,7 +2783,12 @@ char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item, bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle); void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle); +void UI_tree_view_item_context_menu_build(struct bContext *C, + const uiTreeViewItemHandle *item, + uiLayout *column); + uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const struct ARegion *region, int x, int y); +uiTreeViewItemHandle *UI_block_tree_view_find_active_item(const struct ARegion *region); #ifdef __cplusplus } diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh index 272439a2ae9..ae85375ed2f 100644 --- a/source/blender/editors/include/UI_tree_view.hh +++ b/source/blender/editors/include/UI_tree_view.hh @@ -234,6 +234,7 @@ class AbstractTreeViewItem : public TreeViewItemContainer { virtual ~AbstractTreeViewItem() = default; virtual void build_row(uiLayout &row) = 0; + virtual void build_context_menu(bContext &C, uiLayout &column) const; virtual void on_activate(); /** diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index bb9e813ea50..d327124484b 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -925,6 +925,18 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev } } + { + const ARegion *region = CTX_wm_region(C); + uiButTreeRow *treerow_but = (uiButTreeRow *)ui_tree_row_find_mouse_over( + region, event->x, event->y); + if (treerow_but) { + BLI_assert(treerow_but->but.type == UI_BTYPE_TREEROW); + UI_tree_view_item_context_menu_build( + C, treerow_but->tree_item, uiLayoutColumn(layout, false)); + uiItemS(layout); + } + } + /* If the button represents an id, it can set the "id" context pointer. */ if (U.experimental.use_extended_asset_browser && ED_asset_can_mark_single_from_context(C)) { ID *id = CTX_data_pointer_get_type(C, "id", &RNA_ID).data; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bf9b37c00fa..e1f8d18ce35 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -7961,6 +7961,14 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * /* handle menu */ if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) && (event->val == KM_PRESS)) { + /* For some button types that are typically representing entire sets of data, right-clicking + * to spawn the context menu should also activate the item. This makes it clear which item + * will be operated on. + * Apply the button immediately, so context menu polls get the right active item. */ + if (ELEM(but->type, UI_BTYPE_TREEROW)) { + ui_apply_but(C, but->block, but, but->active, true); + } + /* RMB has two options now */ if (ui_popup_context_menu_for_button(C, but, event)) { return WM_UI_HANDLER_BREAK; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index e7a728efce1..c7781d65058 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -1177,6 +1177,7 @@ uiBut *ui_list_row_find_from_index(const struct ARegion *region, const int index, uiBut *listbox) ATTR_WARN_UNUSED_RESULT; uiBut *ui_tree_row_find_mouse_over(const struct ARegion *region, const int x, const int y); +uiBut *ui_tree_row_find_active(const struct ARegion *region); typedef bool (*uiButFindPollFn)(const uiBut *but, const void *customdata); uiBut *ui_but_find_mouse_over_ex(const struct ARegion *region, diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 1fc07bce341..423950d4dbd 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1963,6 +1963,49 @@ static void UI_OT_tree_view_drop(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name UI Tree-View Item Rename Operator + * + * General purpose renaming operator for tree-views. Thanks to this, to add a rename button to + * context menus for example, tree-view API users don't have to implement own renaming operators + * with the same logic as they already have for their #ui::AbstractTreeViewItem::rename() override. + * + * \{ */ + +static bool ui_tree_view_item_rename_poll(bContext *C) +{ + const ARegion *region = CTX_wm_region(C); + const uiTreeViewItemHandle *active_item = UI_block_tree_view_find_active_item(region); + return active_item != NULL && UI_tree_view_item_can_rename(active_item); +} + +static int ui_tree_view_item_rename_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ARegion *region = CTX_wm_region(C); + uiTreeViewItemHandle *active_item = UI_block_tree_view_find_active_item(region); + + UI_tree_view_item_begin_rename(active_item); + ED_region_tag_redraw(region); + + return OPERATOR_FINISHED; +} + +static void UI_OT_tree_view_item_rename(wmOperatorType *ot) +{ + ot->name = "Rename Tree-View Item"; + ot->idname = "UI_OT_tree_view_item_rename"; + ot->description = "Rename the active item in the tree"; + + ot->exec = ui_tree_view_item_rename_exec; + ot->poll = ui_tree_view_item_rename_poll; + /* Could get a custom tooltip via the `get_description()` callback and another overridable + * function of the tree-view. */ + + ot->flag = OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Operator & Keymap Registration * \{ */ @@ -1990,6 +2033,7 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_list_start_filter); WM_operatortype_append(UI_OT_tree_view_drop); + WM_operatortype_append(UI_OT_tree_view_item_rename); /* external */ WM_operatortype_append(UI_OT_eyedropper_color); diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c index 2f6bda3252d..8674f1e435a 100644 --- a/source/blender/editors/interface/interface_query.c +++ b/source/blender/editors/interface/interface_query.c @@ -473,6 +473,21 @@ uiBut *ui_tree_row_find_mouse_over(const ARegion *region, const int x, const int return ui_but_find_mouse_over_ex(region, x, y, false, ui_but_is_treerow, NULL); } +static bool ui_but_is_active_treerow(const uiBut *but, const void *customdata) +{ + if (!ui_but_is_treerow(but, customdata)) { + return false; + } + + const uiButTreeRow *treerow_but = (const uiButTreeRow *)but; + return UI_tree_view_item_is_active(treerow_but->tree_item); +} + +uiBut *ui_tree_row_find_active(const ARegion *region) +{ + return ui_but_find(region, ui_but_is_active_treerow, NULL); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/interface/interface_view.cc b/source/blender/editors/interface/interface_view.cc index 8122b965892..fdd8eb0cc71 100644 --- a/source/blender/editors/interface/interface_view.cc +++ b/source/blender/editors/interface/interface_view.cc @@ -94,6 +94,16 @@ uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const ARegion *region, return tree_row_but->tree_item; } +uiTreeViewItemHandle *UI_block_tree_view_find_active_item(const ARegion *region) +{ + uiButTreeRow *tree_row_but = (uiButTreeRow *)ui_tree_row_find_active(region); + if (!tree_row_but) { + return nullptr; + } + + return tree_row_but->tree_item; +} + static StringRef ui_block_view_find_idname(const uiBlock &block, const AbstractTreeView &view) { /* First get the idname the of the view we're looking for. */ diff --git a/source/blender/editors/interface/tree_view.cc b/source/blender/editors/interface/tree_view.cc index 3f66810b7f6..3f3a8c5bce5 100644 --- a/source/blender/editors/interface/tree_view.cc +++ b/source/blender/editors/interface/tree_view.cc @@ -369,6 +369,11 @@ bool AbstractTreeViewItem::rename(StringRefNull new_name) return true; } +void AbstractTreeViewItem::build_context_menu(bContext & /*C*/, uiLayout & /*column*/) const +{ + /* No context menu by default. */ +} + void AbstractTreeViewItem::update_from_old(const AbstractTreeViewItem &old) { is_open_ = old.is_open_; @@ -707,3 +712,11 @@ void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle) AbstractTreeViewItem &item = reinterpret_cast<AbstractTreeViewItem &>(*item_handle); item.begin_renaming(); } + +void UI_tree_view_item_context_menu_build(bContext *C, + const uiTreeViewItemHandle *item_handle, + uiLayout *column) +{ + const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); + item.build_context_menu(*C, *column); +} |