diff options
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 1 | ||||
-rw-r--r-- | source/blender/editors/include/UI_tree_view.hh | 18 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 38 | ||||
-rw-r--r-- | source/blender/editors/interface/tree_view.cc | 31 |
4 files changed, 79 insertions, 9 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 12fdda2092c..0f290d4255b 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2777,6 +2777,7 @@ void UI_interface_tag_script_reload(void); bool UI_tree_view_item_is_active(const uiTreeViewItemHandle *item); bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a, const uiTreeViewItemHandle *b); +bool UI_tree_view_item_drag_start(struct bContext *C, uiTreeViewItemHandle *item_); bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, const struct wmDrag *drag, const char **r_disabled_hint); diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh index 905181a7251..0990d844d48 100644 --- a/source/blender/editors/include/UI_tree_view.hh +++ b/source/blender/editors/include/UI_tree_view.hh @@ -49,6 +49,7 @@ namespace blender::ui { class AbstractTreeView; class AbstractTreeViewItem; class AbstractTreeViewItemDropController; +class AbstractTreeViewItemDragController; /* ---------------------------------------------------------------------- */ /** \name Tree-View Item Container @@ -274,6 +275,11 @@ class AbstractTreeViewItem : public TreeViewItemContainer { virtual bool matches(const AbstractTreeViewItem &other) const; /** + * If an item wants to support being dragged, it has to return a drag controller here. + * That is an object implementing #AbstractTreeViewItemDragController. + */ + virtual std::unique_ptr<AbstractTreeViewItemDragController> create_drag_controller() const; + /** * If an item wants to support dropping data into it, it has to return a drop controller here. * That is an object implementing #AbstractTreeViewItemDropController. * @@ -348,6 +354,18 @@ class AbstractTreeViewItem : public TreeViewItemContainer { * \{ */ /** + * Class to enable dragging a tree-item. An item can return a drop controller for itself via a + * custom implementation of #AbstractTreeViewItem::create_drag_controller(). + */ +class AbstractTreeViewItemDragController { + public: + virtual ~AbstractTreeViewItemDragController() = default; + + virtual int get_drag_type() const = 0; + virtual void *create_drag_data() const = 0; +}; + +/** * Class to customize the drop behavior of a tree-item, plus the behavior when dragging over this * item. An item can return a drop controller for itself via a custom implementation of * #AbstractTreeViewItem::create_drop_controller(). diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b21d2127030..6dd6f9eb359 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2145,6 +2145,12 @@ static bool ui_but_drag_init(bContext *C, return false; } } + else if (but->type == UI_BTYPE_TREEROW) { + uiButTreeRow *tree_row_but = (uiButTreeRow *)but; + if (tree_row_but->tree_item) { + UI_tree_view_item_drag_start(C, tree_row_but->tree_item); + } + } else { wmDrag *drag = WM_event_start_drag( C, @@ -4821,19 +4827,33 @@ static int ui_do_but_TREEROW(bContext *C, if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE) { - if (event->val == KM_CLICK) { - button_activate_state(C, but, BUTTON_STATE_EXIT); - return WM_UI_HANDLER_BREAK; - } - if (event->val == KM_DBL_CLICK) { - data->cancel = true; + switch (event->val) { + case KM_PRESS: + /* Extra icons have priority, don't mess with them. */ + if (ui_but_extra_operator_icon_mouse_over_get(but, data, event)) { + return WM_UI_HANDLER_BREAK; + } + button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); + data->dragstartx = event->xy[0]; + data->dragstarty = event->xy[1]; + return WM_UI_HANDLER_CONTINUE; - UI_tree_view_item_begin_rename(tree_row_but->tree_item); - ED_region_tag_redraw(CTX_wm_region(C)); - return WM_UI_HANDLER_BREAK; + case KM_CLICK: + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_BREAK; + + case KM_DBL_CLICK: + data->cancel = true; + UI_tree_view_item_begin_rename(tree_row_but->tree_item); + ED_region_tag_redraw(CTX_wm_region(C)); + return WM_UI_HANDLER_BREAK; } } } + else if (data->state == BUTTON_STATE_WAIT_DRAG) { + /* Let "default" button handling take care of the drag logic. */ + return ui_do_but_EXIT(C, but, data, event); + } return WM_UI_HANDLER_CONTINUE; } diff --git a/source/blender/editors/interface/tree_view.cc b/source/blender/editors/interface/tree_view.cc index 04d7a066b36..c08fa51d5a5 100644 --- a/source/blender/editors/interface/tree_view.cc +++ b/source/blender/editors/interface/tree_view.cc @@ -29,6 +29,7 @@ #include "UI_interface.h" +#include "WM_api.h" #include "WM_types.h" #include "UI_tree_view.hh" @@ -354,6 +355,13 @@ void AbstractTreeViewItem::is_active(IsActiveFn is_active_fn) is_active_fn_ = is_active_fn; } +std::unique_ptr<AbstractTreeViewItemDragController> AbstractTreeViewItem::create_drag_controller() + const +{ + /* There's no drag controller (and hence no drag support) by default. */ + return nullptr; +} + std::unique_ptr<AbstractTreeViewItemDropController> AbstractTreeViewItem::create_drop_controller() const { @@ -686,6 +694,29 @@ bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a_handle, return a.matches_including_parents(b); } +/** + * Attempt to start dragging the tree-item \a item_. This will not work if the tree item doesn't + * support dragging, i.e. it won't create a drag-controller upon request. + * \return True if dragging started successfully, otherwise false. + */ +bool UI_tree_view_item_drag_start(bContext *C, uiTreeViewItemHandle *item_) +{ + const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_); + const std::unique_ptr<AbstractTreeViewItemDragController> drag_controller = + item.create_drag_controller(); + if (!drag_controller) { + return false; + } + + WM_event_start_drag(C, + ICON_NONE, + drag_controller->get_drag_type(), + drag_controller->create_drag_data(), + 0, + WM_DRAG_FREE_DATA); + return true; +} + bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, const wmDrag *drag, const char **r_disabled_hint) |