[Bf-blender-cvs] [4ee2d9df428] master: UI: Support easy dropping into/onto rows in new tree-view API

Julian Eisel noreply at git.blender.org
Thu Sep 30 16:39:33 CEST 2021


Commit: 4ee2d9df428d16f07e351f5554b951ae75804ea0
Author: Julian Eisel
Date:   Thu Sep 30 16:26:56 2021 +0200
Branches: master
https://developer.blender.org/rB4ee2d9df428d16f07e351f5554b951ae75804ea0

UI: Support easy dropping into/onto rows in new tree-view API

Adds an easy way to add drop support for tree-view rows.

Most of the work is handled by the tree-view UI code. The tree items can
simply override a few functions (`can_drop()`, `on_drop()`,
`drop_tooltip()`) to implement their custom drop behavior.

While dragging over a tree-view item that can be dropped into/onto, the
item can show a custom and dynamic tooltip explaining what's gonna
happen on drop.

This isn't used yet, but will soon be for asset catalogs.

See documentation here:
https://wiki.blender.org/wiki/Source/Interface/Views#Further_Customizations

===================================================================

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/include/UI_tree_view.hh
M	source/blender/editors/interface/CMakeLists.txt
A	source/blender/editors/interface/interface_dropboxes.cc
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_ops.c
M	source/blender/editors/interface/interface_query.c
M	source/blender/editors/interface/interface_view.cc
M	source/blender/editors/interface/tree_view.cc
M	source/blender/editors/screen/area.c
M	source/blender/editors/space_api/spacetypes.c

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 106f6166760..f642895f64e 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2593,6 +2593,7 @@ typedef struct uiDragColorHandle {
 
 void ED_operatortypes_ui(void);
 void ED_keymap_ui(struct wmKeyConfig *keyconf);
+void ED_dropboxes_ui(void);
 void ED_uilisttypes_ui(void);
 
 void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
@@ -2763,6 +2764,14 @@ 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_can_drop(const uiTreeViewItemHandle *item_, const struct wmDrag *drag);
+bool UI_tree_view_item_drop_handle(uiTreeViewItemHandle *item_, const struct ListBase *drags);
+char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item,
+                                     const struct bContext *C,
+                                     const struct wmDrag *drag,
+                                     const struct wmEvent *event);
+
+uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const struct ARegion *region, int x, int y);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh
index 81a614cd195..d36e688dd65 100644
--- a/source/blender/editors/include/UI_tree_view.hh
+++ b/source/blender/editors/include/UI_tree_view.hh
@@ -29,11 +29,14 @@
 
 #include "UI_resources.h"
 
+struct bContext;
 struct PointerRNA;
 struct uiBlock;
 struct uiBut;
 struct uiButTreeRow;
 struct uiLayout;
+struct wmEvent;
+struct wmDrag;
 
 namespace blender::ui {
 
@@ -185,10 +188,19 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
   virtual void build_row(uiLayout &row) = 0;
 
   virtual void on_activate();
-
-  /** Copy persistent state (e.g. is-collapsed flag, selection, etc.) from a matching item of the
-   * last redraw to this item. If sub-classes introduce more advanced state they should override
-   * this and make it update their state accordingly. */
+  virtual bool on_drop(const wmDrag &drag);
+  virtual bool can_drop(const wmDrag &drag) const;
+  /** Custom text to display when dragging over a tree item. Should explain what happens when
+   * dropping the data onto this item. Will only be used if #AbstractTreeViewItem::can_drop()
+   * returns true, so the implementing override doesn't have to check that again.
+   * The returned value must be a translated string. */
+  virtual std::string drop_tooltip(const bContext &C,
+                                   const wmDrag &drag,
+                                   const wmEvent &event) const;
+
+  /** Copy persistent state (e.g. is-collapsed flag, selection, etc.) from a matching item of
+   * the last redraw to this item. If sub-classes introduce more advanced state they should
+   * override this and make it update their state accordingly. */
   virtual void update_from_old(const AbstractTreeViewItem &old);
   /** Compare this item to \a other to check if they represent the same data. This is critical for
    * being able to recognize an item from a previous redraw, to be able to keep its state (e.g.
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 79e08f46292..8fcc704a301 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
   interface_button_group.c
   interface_context_menu.c
   interface_draw.c
+  interface_dropboxes.cc
   interface_eyedropper.c
   interface_eyedropper_color.c
   interface_eyedropper_colorband.c
diff --git a/source/blender/editors/interface/interface_dropboxes.cc b/source/blender/editors/interface/interface_dropboxes.cc
new file mode 100644
index 00000000000..cb33e7f736e
--- /dev/null
+++ b/source/blender/editors/interface/interface_dropboxes.cc
@@ -0,0 +1,66 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ */
+
+#include "BKE_context.h"
+
+#include "DNA_space_types.h"
+
+#include "WM_api.h"
+
+#include "UI_interface.h"
+
+static bool ui_tree_view_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+{
+  const ARegion *region = CTX_wm_region(C);
+  const uiTreeViewItemHandle *hovered_tree_item = UI_block_tree_view_find_item_at(
+      region, event->x, event->y);
+  if (!hovered_tree_item) {
+    return false;
+  }
+
+  return UI_tree_view_item_can_drop(hovered_tree_item, drag);
+}
+
+static char *ui_tree_view_drop_tooltip(bContext *C,
+                                       wmDrag *drag,
+                                       const wmEvent *event,
+                                       wmDropBox *UNUSED(drop))
+{
+  const ARegion *region = CTX_wm_region(C);
+  const uiTreeViewItemHandle *hovered_tree_item = UI_block_tree_view_find_item_at(
+      region, event->x, event->y);
+  if (!hovered_tree_item) {
+    return nullptr;
+  }
+
+  return UI_tree_view_item_drop_tooltip(hovered_tree_item, C, drag, event);
+}
+
+void ED_dropboxes_ui()
+{
+  ListBase *lb = WM_dropboxmap_find("User Interface", SPACE_EMPTY, 0);
+
+  WM_dropbox_add(lb,
+                 "UI_OT_tree_view_drop",
+                 ui_tree_view_drop_poll,
+                 nullptr,
+                 nullptr,
+                 ui_tree_view_drop_tooltip);
+}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 95e6791b359..8b45d9faae6 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1171,6 +1171,7 @@ uiBut *ui_list_row_find_mouse_over(const struct ARegion *region,
 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);
 
 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 7b59a6f7263..1fc07bce341 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1917,6 +1917,51 @@ static void UI_OT_list_start_filter(wmOperatorType *ot)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name UI Tree-View Drop Operator
+ * \{ */
+
+static bool ui_tree_view_drop_poll(bContext *C)
+{
+  const wmWindow *win = CTX_wm_window(C);
+  const ARegion *region = CTX_wm_region(C);
+  const uiTreeViewItemHandle *hovered_tree_item = UI_block_tree_view_find_item_at(
+      region, win->eventstate->x, win->eventstate->y);
+
+  return hovered_tree_item != NULL;
+}
+
+static int ui_tree_view_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+  if (event->custom != EVT_DATA_DRAGDROP) {
+    return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+  }
+
+  const ARegion *region = CTX_wm_region(C);
+  uiTreeViewItemHandle *hovered_tree_item = UI_block_tree_view_find_item_at(
+      region, event->x, event->y);
+
+  if (!UI_tree_view_item_drop_handle(hovered_tree_item, event->customdata)) {
+    return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+  }
+
+  return OPERATOR_FINISHED;
+}
+
+static void UI_OT_tree_view_drop(wmOperatorType *ot)
+{
+  ot->name = "Tree View drop";
+  ot->idname = "UI_OT_tree_view_drop";
+  ot->description = "Drag and drop items onto a tree item";
+
+  ot->invoke = ui_tree_view_drop_invoke;
+  ot->poll = ui_tree_view_drop_poll;
+
+  ot->flag = OPTYPE_INTERNAL;
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Operator & Keymap Registration
  * \{ */
@@ -1944,6 +1989,8 @@ void ED_operatortypes_ui(void)
 
   WM_operatortype_append(UI_OT_list_start_filter);
 
+  WM_operatortype_append(UI_OT_tree_view_drop);
+
   /* external */
   WM_operatortype_append(UI_OT_eyedropper_color);
   WM_operatortype_append(UI_OT_eyedropper_colorramp);
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index 15d1d2f2eec..2f6bda3252d 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -463,6 +463,16 @@ uiBut *ui_list_row_find_from_index(const ARegion *region, const int index, uiBut
   return ui_but_find(region, ui_but_is_listrow_at_index, &data);
 }
 
+static bool ui_but_is_treerow(const uiBut *but, const void *UNUSED(customdata))
+{
+  return but->type == UI_BTYPE_TREEROW;
+}
+
+uiBut *ui_tree_row_find_mouse_over(const ARegion *region, const int x, const int y)
+{
+  return ui_but_find_mouse_over_ex(region, x, y, false, ui_but_is_treerow, NULL);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/interface/interface_view.cc b/source/blender/editors/interface/interface_view.cc
index 7419f21cbc6..b199ce9562e 100644
--- a/source/blender/editors/interface/interface_view.cc
+++ b/source/blender/editors/interface/interface_view.cc
@@ -26,6 +26,8 @@
 #incl

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list