[Bf-blender-cvs] [d16e7326386] master: UI: Refactor dropping support for the tree-view API

Julian Eisel noreply at git.blender.org
Mon Oct 25 10:47:01 CEST 2021


Commit: d16e7326386d055fc5cdfa9f60bcd3d75bcbbed5
Author: Julian Eisel
Date:   Sun Oct 24 18:51:12 2021 +0200
Branches: master
https://developer.blender.org/rBd16e7326386d055fc5cdfa9f60bcd3d75bcbbed5

UI: Refactor dropping support for the tree-view API

Introduces a dropping-controller API for the tree-view items,
`AbstractTreeViewItemDropController`. This reduces responsibilities of the main
tree-view item classes, which are already getting quite big. As I expect even
more functionality to be needed for it (e.g. drag support), it's better to
start introducing such controller types already.

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/include/UI_tree_view.hh
M	source/blender/editors/interface/interface_dropboxes.cc
M	source/blender/editors/interface/tree_view.cc
M	source/blender/editors/space_file/asset_catalog_tree_view.cc

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 67d034f4ab6..de6b975a910 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2781,11 +2781,8 @@ 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);
+char *UI_tree_view_item_drop_tooltip(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);
 bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle);
 void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle);
 
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh
index b1ec22c57a6..f565c80193f 100644
--- a/source/blender/editors/include/UI_tree_view.hh
+++ b/source/blender/editors/include/UI_tree_view.hh
@@ -48,6 +48,7 @@ namespace blender::ui {
 
 class AbstractTreeView;
 class AbstractTreeViewItem;
+class AbstractTreeViewItemDropController;
 
 /* ---------------------------------------------------------------------- */
 /** \name Tree-View Item Container
@@ -242,17 +243,7 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
    * arguments for checking if the item is currently in an active state.
    */
   virtual void is_active(IsActiveFn is_active_fn);
-  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;
+
   /**
    * Queries if the tree-view item supports renaming in principle. Renaming may still fail, e.g. if
    * another item is already being renamed.
@@ -282,6 +273,15 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
    */
   virtual bool matches(const AbstractTreeViewItem &other) 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.
+   *
+   * \note This drop controller may be requested for each event. The tree-view doesn't keep a drop
+   *       controller around currently. So it can not contain persistent state.
+   */
+  virtual std::unique_ptr<AbstractTreeViewItemDropController> create_drop_controller() const;
+
   void begin_renaming();
   void end_renaming();
 
@@ -343,6 +343,45 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
 
 /** \} */
 
+/* ---------------------------------------------------------------------- */
+/** \name Drag 'n Drop
+ * \{ */
+
+/**
+ * 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().
+ */
+class AbstractTreeViewItemDropController {
+ protected:
+  AbstractTreeView &tree_view_;
+
+ public:
+  AbstractTreeViewItemDropController(AbstractTreeView &tree_view);
+  virtual ~AbstractTreeViewItemDropController() = default;
+
+  /**
+   * Check if the data dragged with \a drag can be dropped on the item this controller is for.
+   */
+  virtual bool can_drop(const wmDrag &drag) const = 0;
+  /**
+   * 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 wmDrag &drag) const = 0;
+  /**
+   * Execute the logic to apply a drop of the data dragged with \a drag onto/into the item this
+   * controller is for.
+   */
+  virtual bool on_drop(const wmDrag &drag) = 0;
+
+  template<class TreeViewType> inline TreeViewType &tree_view() const;
+};
+
+/** \} */
+
 /* ---------------------------------------------------------------------- */
 /** \name Predefined Tree-View Item Types
  *
@@ -390,4 +429,9 @@ inline ItemT &TreeViewItemContainer::add_tree_item(Args &&...args)
       add_tree_item(std::make_unique<ItemT>(std::forward<Args>(args)...)));
 }
 
+template<class TreeViewType> TreeViewType &AbstractTreeViewItemDropController::tree_view() const
+{
+  return static_cast<TreeViewType &>(tree_view_);
+}
+
 }  // namespace blender::ui
diff --git a/source/blender/editors/interface/interface_dropboxes.cc b/source/blender/editors/interface/interface_dropboxes.cc
index 62250a34cf4..ae626080a9a 100644
--- a/source/blender/editors/interface/interface_dropboxes.cc
+++ b/source/blender/editors/interface/interface_dropboxes.cc
@@ -50,7 +50,7 @@ static char *ui_tree_view_drop_tooltip(bContext *C,
     return nullptr;
   }
 
-  return UI_tree_view_item_drop_tooltip(hovered_tree_item, C, drag, event);
+  return UI_tree_view_item_drop_tooltip(hovered_tree_item, drag);
 }
 
 void ED_dropboxes_ui()
diff --git a/source/blender/editors/interface/tree_view.cc b/source/blender/editors/interface/tree_view.cc
index 88aa362deb5..946699d5115 100644
--- a/source/blender/editors/interface/tree_view.cc
+++ b/source/blender/editors/interface/tree_view.cc
@@ -354,22 +354,11 @@ void AbstractTreeViewItem::is_active(IsActiveFn is_active_fn)
   is_active_fn_ = is_active_fn;
 }
 
-bool AbstractTreeViewItem::on_drop(const wmDrag & /*drag*/)
+std::unique_ptr<AbstractTreeViewItemDropController> AbstractTreeViewItem::create_drop_controller()
+    const
 {
-  /* Do nothing by default. */
-  return false;
-}
-
-bool AbstractTreeViewItem::can_drop(const wmDrag & /*drag*/) const
-{
-  return false;
-}
-
-std::string AbstractTreeViewItem::drop_tooltip(const bContext & /*C*/,
-                                               const wmDrag & /*drag*/,
-                                               const wmEvent & /*event*/) const
-{
-  return TIP_("Drop into/onto tree item");
+  /* There's no drop controller (and hence no drop support) by default. */
+  return nullptr;
 }
 
 bool AbstractTreeViewItem::can_rename() const
@@ -553,6 +542,12 @@ void AbstractTreeViewItem::change_state_delayed()
     activate();
   }
 }
+/* ---------------------------------------------------------------------- */
+
+AbstractTreeViewItemDropController::AbstractTreeViewItemDropController(AbstractTreeView &tree_view)
+    : tree_view_(tree_view)
+{
+}
 
 /* ---------------------------------------------------------------------- */
 
@@ -683,16 +678,25 @@ bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a_handle,
 bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, const wmDrag *drag)
 {
   const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
-  return item.can_drop(*drag);
+  const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
+      item.create_drop_controller();
+  if (!drop_controller) {
+    return false;
+  }
+
+  return drop_controller->can_drop(*drag);
 }
 
-char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item_,
-                                     const bContext *C,
-                                     const wmDrag *drag,
-                                     const wmEvent *event)
+char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item_, const wmDrag *drag)
 {
   const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
-  return BLI_strdup(item.drop_tooltip(*C, *drag, *event).c_str());
+  const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
+      item.create_drop_controller();
+  if (!drop_controller) {
+    return NULL;
+  }
+
+  return BLI_strdup(drop_controller->drop_tooltip(*drag).c_str());
 }
 
 /**
@@ -702,10 +706,12 @@ char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item_,
 bool UI_tree_view_item_drop_handle(uiTreeViewItemHandle *item_, const ListBase *drags)
 {
   AbstractTreeViewItem &item = reinterpret_cast<AbstractTreeViewItem &>(*item_);
+  std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
+      item.create_drop_controller();
 
   LISTBASE_FOREACH (const wmDrag *, drag, drags) {
-    if (item.can_drop(*drag)) {
-      return item.on_drop(*drag);
+    if (drop_controller->can_drop(*drag)) {
+      return drop_controller->on_drop(*drag);
     }
   }
 
diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc
index c305a11daf4..68df4cc0544 100644
--- a/source/blender/editors/space_file/asset_catalog_tree_view.cc
+++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc
@@ -60,6 +60,7 @@ class AssetCatalogTreeView : public ui::AbstractTreeView {
   SpaceFile &space_file_;
 
   friend class AssetCatalogTreeViewItem;
+  friend class AssetCatalogDropController;
 
  public:
   AssetCatalogTreeView(::AssetLibrary *library,
@@ -86,25 +87,34 @@ class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem {
  public:
   AssetCatalogTreeViewItem(AssetCatalogTreeItem *catalog_item);
 
-  static bool has_droppable_item(const wmDrag &drag);
-  static bool drop_into_catalog(const AssetCatalogTreeView &tree_view,
-                                const wmDrag &drag

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list