UI: Support disabled-hint for dropping in the tree-view API

A tree-view item's drop controller can now return a message for the user
explaining why dropping isn't possible with the dropped data. This is then
displayed in red text next to the cursor.

This isn't actually used yet, the follow up commit will do that.
This commit is contained in:
Julian Eisel 2021-10-26 18:48:24 +02:00
parent 03c0581c6e
commit 11e8a2ec5f
Notes: blender-bot 2023-02-14 03:59:42 +01:00
Referenced by issue #92434, Improve feedback when dragging assets into catalog isn't possible
5 changed files with 34 additions and 14 deletions

View File

@ -2777,7 +2777,9 @@ 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_can_drop(const uiTreeViewItemHandle *item_,
const struct wmDrag *drag,
const char **r_disabled_hint);
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);
bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle);

View File

@ -362,8 +362,13 @@ class AbstractTreeViewItemDropController {
/**
* 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 = 0;
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()

View File

@ -22,6 +22,8 @@
#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"
#include "WM_api.h"
#include "UI_interface.h"
@ -35,7 +37,12 @@ static bool ui_tree_view_drop_poll(bContext *C, wmDrag *drag, const wmEvent *eve
return false;
}
return UI_tree_view_item_can_drop(hovered_tree_item, drag);
if (drag->free_disabled_info) {
MEM_SAFE_FREE(drag->disabled_info);
}
drag->free_disabled_info = false;
return UI_tree_view_item_can_drop(hovered_tree_item, drag, &drag->disabled_info);
}
static char *ui_tree_view_drop_tooltip(bContext *C,

View File

@ -675,7 +675,9 @@ bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a_handle,
return a.matches_including_parents(b);
}
bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, const wmDrag *drag)
bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_,
const wmDrag *drag,
const char **r_disabled_hint)
{
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
@ -684,7 +686,7 @@ bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, const wmDrag
return false;
}
return drop_controller->can_drop(*drag);
return drop_controller->can_drop(*drag, r_disabled_hint);
}
char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item_, const wmDrag *drag)
@ -709,8 +711,9 @@ bool UI_tree_view_item_drop_handle(uiTreeViewItemHandle *item_, const ListBase *
std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
item.create_drop_controller();
const char *disabled_hint_dummy = nullptr;
LISTBASE_FOREACH (const wmDrag *, drag, drags) {
if (drop_controller->can_drop(*drag)) {
if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) {
return drop_controller->on_drop(*drag);
}
}

View File

@ -106,11 +106,11 @@ class AssetCatalogDropController : public ui::AbstractTreeViewItemDropController
explicit AssetCatalogDropController(AssetCatalogTreeView &tree_view,
AssetCatalogTreeItem &catalog_item);
bool can_drop(const wmDrag &drag) const override;
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
std::string drop_tooltip(const wmDrag &drag) const override;
bool on_drop(const wmDrag &drag) override;
static bool has_droppable_item(const wmDrag &drag);
static bool has_droppable_item(const wmDrag &drag, const char **r_disabled_hint);
static bool drop_into_catalog(const AssetCatalogTreeView &tree_view,
const wmDrag &drag,
CatalogID catalog_id,
@ -131,7 +131,7 @@ class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
struct DropController : public ui::AbstractTreeViewItemDropController {
DropController(AssetCatalogTreeView &tree_view);
bool can_drop(const wmDrag &drag) const override;
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
std::string drop_tooltip(const wmDrag &drag) const override;
bool on_drop(const wmDrag &drag) override;
};
@ -320,12 +320,12 @@ AssetCatalogDropController::AssetCatalogDropController(AssetCatalogTreeView &tre
{
}
bool AssetCatalogDropController::can_drop(const wmDrag &drag) const
bool AssetCatalogDropController::can_drop(const wmDrag &drag, const char **r_disabled_hint) const
{
if (drag.type != WM_DRAG_ASSET_LIST) {
return false;
}
return has_droppable_item(drag);
return has_droppable_item(drag, r_disabled_hint);
}
std::string AssetCatalogDropController::drop_tooltip(const wmDrag &drag) const
@ -377,10 +377,12 @@ bool AssetCatalogDropController::drop_into_catalog(const AssetCatalogTreeView &t
return true;
}
bool AssetCatalogDropController::has_droppable_item(const wmDrag &drag)
bool AssetCatalogDropController::has_droppable_item(const wmDrag &drag,
const char **r_disabled_hint)
{
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
*r_disabled_hint = nullptr;
/* There needs to be at least one asset from the current file. */
LISTBASE_FOREACH (const wmDragAssetListItem *, asset_item, asset_drags) {
if (!asset_item->is_external) {
@ -421,12 +423,13 @@ AssetCatalogTreeViewUnassignedItem::DropController::DropController(AssetCatalogT
{
}
bool AssetCatalogTreeViewUnassignedItem::DropController::can_drop(const wmDrag &drag) const
bool AssetCatalogTreeViewUnassignedItem::DropController::can_drop(
const wmDrag &drag, const char **r_disabled_hint) const
{
if (drag.type != WM_DRAG_ASSET_LIST) {
return false;
}
return AssetCatalogDropController::has_droppable_item(drag);
return AssetCatalogDropController::has_droppable_item(drag, r_disabled_hint);
}
std::string AssetCatalogTreeViewUnassignedItem::DropController::drop_tooltip(