UI: Generalize drop target API, support them for UI views #105963

Closed
Julian Eisel wants to merge 8 commits from JulianEisel:temp-ui-view-drop-controller into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 60 additions and 54 deletions
Showing only changes of commit a3886ebbbc - Show all commits

View File

@ -92,6 +92,29 @@ class DropTargetInterface {
virtual bool on_drop(bContext *C, const wmDrag &drag) const = 0;
};
/**
* Let a drop target handle a drop event.
* \return True if the dropping was successful.
*/
bool drop_target_apply_drop(bContext &C,
const DropTargetInterface &drop_target,
const ListBase &drags);
/**
* Call #DropTargetInterface::drop_tooltip() and return the result as newly allocated C string
* (unless the result is empty, returns null then). Needs freeing with MEM_freeN().
*/
char *drop_target_tooltip(const DropTargetInterface &drop_target, const wmDrag &drag);
std::unique_ptr<DropTargetInterface> view_drop_target(const uiViewHandle *view_handle);
std::unique_ptr<DropTargetInterface> view_item_drop_target(const uiViewItemHandle *item_handle);
/**
* Try to find a view item with a drop target under the mouse cursor, or if not found, a view
* with a drop target.
* \param xy: Coordinate to find a drop target at, in window space.
*/
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
const int xy[2]);
} // namespace blender::ui
enum eUIListFilterResult {
@ -148,33 +171,6 @@ void UI_list_filter_and_sort_items(uiList *ui_list,
const char *propname,
uiListItemGetNameFn get_name_fn = nullptr);
std::unique_ptr<blender::ui::DropTargetInterface> UI_view_drop_target(
const uiViewHandle *view_handle);
std::unique_ptr<blender::ui::DropTargetInterface> UI_view_item_drop_target(
const uiViewItemHandle *item_handle);
/**
* Let a drop target handle a drop event.
* \return True if the dropping was successful.
*/
bool UI_drop_target_apply_drop(bContext &C,
const blender::ui::DropTargetInterface &drop_target,
const ListBase &drags);
/**
* Call #DropTargetInterface::drop_tooltip() and return the result as newly allocated C string
* (unless the result is empty, returns null then). Needs freeing with MEM_freeN().
*/
char *UI_drop_target_tooltip(const blender::ui::DropTargetInterface &drop_target,
const wmDrag &drag);
/**
* Try to find a view item with a drop target under the mouse cursor, or if not found, a view
* with a drop target.
* \param xy: Coordinate to find a drop target at, in window space.
*/
std::unique_ptr<blender::ui::DropTargetInterface> UI_region_views_find_drop_target_at(
const ARegion *region, const int xy[2]);
/**
* Override this for all available view types.
*/

View File

@ -6,11 +6,11 @@
#include "UI_interface.hh"
using namespace blender::ui;
namespace blender::ui {
bool UI_drop_target_apply_drop(bContext &C,
const DropTargetInterface &drop_target,
const ListBase &drags)
bool drop_target_apply_drop(bContext &C,
const DropTargetInterface &drop_target,
const ListBase &drags)
{
const char *disabled_hint_dummy = nullptr;
@ -23,8 +23,10 @@ bool UI_drop_target_apply_drop(bContext &C,
return false;
}
char *UI_drop_target_tooltip(const DropTargetInterface &drop_target, const wmDrag &drag)
char *drop_target_tooltip(const DropTargetInterface &drop_target, const wmDrag &drag)
{
const std::string tooltip = drop_target.drop_tooltip(drag);
return tooltip.empty() ? nullptr : BLI_strdup(tooltip.c_str());
}
} // namespace blender::ui

View File

@ -32,7 +32,7 @@ static bool ui_view_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
const ARegion *region = CTX_wm_region(C);
std::unique_ptr<DropTargetInterface> drop_target = UI_region_views_find_drop_target_at(
std::unique_ptr<DropTargetInterface> drop_target = region_views_find_drop_target_at(
region, event->xy);
if (!drop_target) {
return false;
@ -49,10 +49,10 @@ static bool ui_view_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static char *ui_view_drop_tooltip(bContext *C, wmDrag *drag, const int xy[2], wmDropBox * /*drop*/)
{
const ARegion *region = CTX_wm_region(C);
std::unique_ptr<DropTargetInterface> drop_target = UI_region_views_find_drop_target_at(region,
std::unique_ptr<DropTargetInterface> drop_target = region_views_find_drop_target_at(region,
xy);
return UI_drop_target_tooltip(*drop_target, *drag);
return drop_target_tooltip(*drop_target, *drag);
}
/** \} */

View File

@ -2364,7 +2364,7 @@ static bool ui_view_drop_poll(bContext *C)
if (region == nullptr) {
return false;
}
return UI_region_views_find_drop_target_at(region, win->eventstate->xy) != nullptr;
return region_views_find_drop_target_at(region, win->eventstate->xy) != nullptr;
}
static int ui_view_drop_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *event)
@ -2374,10 +2374,10 @@ static int ui_view_drop_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *
}
const ARegion *region = CTX_wm_region(C);
std::unique_ptr<DropTargetInterface> drop_target = UI_region_views_find_drop_target_at(
std::unique_ptr<DropTargetInterface> drop_target = region_views_find_drop_target_at(
region, event->xy);
if (!UI_drop_target_apply_drop(
if (!drop_target_apply_drop(
*C, *drop_target, *static_cast<const ListBase *>(event->customdata))) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}

View File

@ -117,18 +117,16 @@ std::optional<rcti> AbstractView::get_bounds() const
/** \} */
} // namespace blender::ui
/* ---------------------------------------------------------------------- */
/** \name C-API
/** \name General API functions
* \{ */
using namespace blender::ui;
std::unique_ptr<DropTargetInterface> UI_view_drop_target(const uiViewHandle *view_handle)
std::unique_ptr<DropTargetInterface> view_drop_target(const uiViewHandle *view_handle)
{
const AbstractView &view = reinterpret_cast<const AbstractView &>(*view_handle);
return view.create_drop_target();
}
/** \} */
} // namespace blender::ui

View File

@ -217,6 +217,18 @@ bool AbstractViewItem::is_active() const
/** \} */
/* ---------------------------------------------------------------------- */
/** \name General API functions
* \{ */
std::unique_ptr<DropTargetInterface> view_item_drop_target(const uiViewItemHandle *item_handle)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
return item.create_drop_target();
}
/** \} */
} // namespace blender::ui
/* ---------------------------------------------------------------------- */
@ -309,10 +321,4 @@ bool UI_view_item_drag_start(bContext *C, const uiViewItemHandle *item_)
return ViewItemAPIWrapper::drag_start(*C, item);
}
std::unique_ptr<DropTargetInterface> UI_view_item_drop_target(const uiViewItemHandle *item_handle)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
return item.create_drop_target();
}
/** \} */

View File

@ -189,12 +189,14 @@ uiViewItemHandle *UI_region_views_find_active_item(const ARegion *region)
return item_but->view_item;
}
std::unique_ptr<DropTargetInterface> UI_region_views_find_drop_target_at(const ARegion *region,
const int xy[2])
namespace blender::ui {
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
const int xy[2])
{
const uiViewItemHandle *hovered_view_item = UI_region_views_find_item_at(region, xy);
if (hovered_view_item) {
std::unique_ptr<DropTargetInterface> drop_target = UI_view_item_drop_target(hovered_view_item);
std::unique_ptr<DropTargetInterface> drop_target = view_item_drop_target(hovered_view_item);
if (drop_target) {
return drop_target;
}
@ -204,7 +206,7 @@ std::unique_ptr<DropTargetInterface> UI_region_views_find_drop_target_at(const A
const uiStyle *style = UI_style_get_dpi();
const uiViewHandle *hovered_view = UI_region_view_find_at(region, xy, style->buttonspacex);
if (hovered_view) {
std::unique_ptr<DropTargetInterface> drop_target = UI_view_drop_target(hovered_view);
std::unique_ptr<DropTargetInterface> drop_target = view_drop_target(hovered_view);
if (drop_target) {
return drop_target;
}
@ -213,6 +215,8 @@ std::unique_ptr<DropTargetInterface> UI_region_views_find_drop_target_at(const A
return nullptr;
}
} // namespace blender::ui
static StringRef ui_block_view_find_idname(const uiBlock &block, const AbstractView &view)
{
/* First get the idname the of the view we're looking for. */