diff options
Diffstat (limited to 'source/blender/editors/include/UI_tree_view.hh')
-rw-r--r-- | source/blender/editors/include/UI_tree_view.hh | 94 |
1 files changed, 82 insertions, 12 deletions
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh index b1ec22c57a6..0d18eedeac9 100644 --- a/source/blender/editors/include/UI_tree_view.hh +++ b/source/blender/editors/include/UI_tree_view.hh @@ -48,6 +48,8 @@ namespace blender::ui { class AbstractTreeView; class AbstractTreeViewItem; +class AbstractTreeViewItemDropController; +class AbstractTreeViewItemDragController; /* ---------------------------------------------------------------------- */ /** \name Tree-View Item Container @@ -242,17 +244,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 +274,20 @@ 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. + * + * \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(); @@ -344,6 +350,62 @@ class AbstractTreeViewItem : public TreeViewItemContainer { /** \} */ /* ---------------------------------------------------------------------- */ +/** \name Drag 'n Drop + * \{ */ + +/** + * 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(). + */ +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. + * \param r_disabled_hint: Return a static string to display to the user, explaining why dropping + * isn't possible on this item. Shouldn't be done too aggressively, e.g. + * don't set this if the drag-type can't be dropped here; only if it can + * but there's another reason it can't be dropped. + * Can assume this is a non-null pointer. + */ + virtual bool can_drop(const wmDrag &drag, const char **r_disabled_hint) 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 * * Common, Basic Tree-View Item Types. @@ -357,9 +419,10 @@ class BasicTreeViewItem : public AbstractTreeViewItem { using ActivateFn = std::function<void(BasicTreeViewItem &new_active)>; BIFIconID icon; - BasicTreeViewItem(StringRef label, BIFIconID icon = ICON_NONE); + explicit BasicTreeViewItem(StringRef label, BIFIconID icon = ICON_NONE); void build_row(uiLayout &row) override; + void add_label(uiLayout &layout, StringRefNull label_override = ""); void on_activate(ActivateFn fn); protected: @@ -390,4 +453,11 @@ 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 +{ + static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value, + "Type must derive from and implement the AbstractTreeView interface"); + return static_cast<TreeViewType &>(tree_view_); +} + } // namespace blender::ui |