Cleanup: Move dragging code for buttons to own file

Moves code for managing dragging data from buttons to a separate file.
This way all this closely related code is in one location, making it
easier to see how it all relates, and easier to find.
This commit is contained in:
Julian Eisel 2022-05-31 15:06:57 +02:00
parent 16f5d51109
commit 9634f7fae3
9 changed files with 195 additions and 156 deletions

View File

@ -851,33 +851,6 @@ void UI_block_translate(uiBlock *block, int x, int y);
int UI_but_return_value_get(uiBut *but);
void UI_but_drag_set_id(uiBut *but, struct ID *id);
/**
* Set an image to display while dragging. This works for any drag type (`WM_DRAG_XXX`).
* Not to be confused with #UI_but_drag_set_image(), which sets up dragging of an image.
*/
void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale);
/**
* \param asset: May be passed from a temporary variable, drag data only stores a copy of this.
*/
void UI_but_drag_set_asset(uiBut *but,
const struct AssetHandle *asset,
const char *path,
struct AssetMetaData *metadata,
int import_type, /* eFileAssetImportType */
int icon,
struct ImBuf *imb,
float scale);
void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr);
void UI_but_drag_set_path(uiBut *but, const char *path, bool use_free);
void UI_but_drag_set_name(uiBut *but, const char *name);
/**
* Value from button itself.
*/
void UI_but_drag_set_value(uiBut *but);
void UI_but_drag_set_image(
uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, bool use_free);
uiBut *UI_but_active_drop_name_button(const struct bContext *C);
/**
* Returns true if highlighted button allows drop of names.
@ -1783,6 +1756,38 @@ AutoComplete *UI_autocomplete_begin(const char *startname, size_t maxlen);
void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name);
int UI_autocomplete_end(AutoComplete *autocpl, char *autoname);
/* Button drag-data (interface_drag.cc).
*
* Functions to set drag data for buttons. This enables dragging support, whereby the drag data is
* "dragged", not the button itself. */
void UI_but_drag_set_id(uiBut *but, struct ID *id);
/**
* Set an image to display while dragging. This works for any drag type (`WM_DRAG_XXX`).
* Not to be confused with #UI_but_drag_set_image(), which sets up dragging of an image.
*/
void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale);
/**
* \param asset: May be passed from a temporary variable, drag data only stores a copy of this.
*/
void UI_but_drag_set_asset(uiBut *but,
const struct AssetHandle *asset,
const char *path,
struct AssetMetaData *metadata,
int import_type, /* eFileAssetImportType */
int icon,
struct ImBuf *imb,
float scale);
void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr);
void UI_but_drag_set_path(uiBut *but, const char *path, bool use_free);
void UI_but_drag_set_name(uiBut *but, const char *name);
/**
* Value from button itself.
*/
void UI_but_drag_set_value(uiBut *but);
void UI_but_drag_set_image(
uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, bool use_free);
/* Panels
*
* Functions for creating, freeing and drawing panels. The API here

View File

@ -31,6 +31,7 @@ set(SRC
interface_button_group.c
interface_context_menu.c
interface_context_path.cc
interface_drag.cc
interface_draw.c
interface_dropboxes.cc
interface_eyedropper.c

View File

@ -3445,9 +3445,7 @@ static void ui_but_free(const bContext *C, uiBut *but)
IMB_freeImBuf((struct ImBuf *)but->poin);
}
if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
WM_drag_data_free(but->dragtype, but->dragpoin);
}
ui_but_drag_free(but);
ui_but_extra_operator_icons_free(but);
BLI_assert(UI_butstore_is_registered(but->block, but) == false);
@ -5881,104 +5879,6 @@ int UI_but_return_value_get(uiBut *but)
return but->retval;
}
void UI_but_drag_set_id(uiBut *but, ID *id)
{
but->dragtype = WM_DRAG_ID;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)id;
}
void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, const float scale)
{
but->imb = imb;
but->imb_scale = scale;
}
void UI_but_drag_set_asset(uiBut *but,
const AssetHandle *asset,
const char *path,
struct AssetMetaData *metadata,
int import_type,
int icon,
struct ImBuf *imb,
float scale)
{
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, metadata, path, import_type);
/* FIXME: This is temporary evil solution to get scene/viewlayer/etc in the copy callback of the
* #wmDropBox.
* TODO: Handle link/append in operator called at the end of the drop process, and NOT in its
* copy callback.
* */
asset_drag->evil_C = static_cast<bContext *>(but->block->evil_C);
but->dragtype = WM_DRAG_ASSET;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
}
but->dragpoin = asset_drag;
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
UI_but_drag_attach_image(but, imb, scale);
}
void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr)
{
but->dragtype = WM_DRAG_RNA;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)ptr;
}
void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)path;
if (use_free) {
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
}
}
void UI_but_drag_set_name(uiBut *but, const char *name)
{
but->dragtype = WM_DRAG_NAME;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)name;
}
void UI_but_drag_set_value(uiBut *but)
{
but->dragtype = WM_DRAG_VALUE;
}
void UI_but_drag_set_image(
uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)path;
if (use_free) {
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
}
UI_but_drag_attach_image(but, imb, scale);
}
PointerRNA *UI_but_operator_ptr_get(uiBut *but)
{
if (but->optype && !but->opptr) {

View File

@ -0,0 +1,144 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edinterface
*/
#include "UI_interface.h"
#include "WM_api.h"
#include "interface_intern.h"
void UI_but_drag_set_id(uiBut *but, ID *id)
{
but->dragtype = WM_DRAG_ID;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)id;
}
void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, const float scale)
{
but->imb = imb;
but->imb_scale = scale;
}
void UI_but_drag_set_asset(uiBut *but,
const AssetHandle *asset,
const char *path,
struct AssetMetaData *metadata,
int import_type,
int icon,
struct ImBuf *imb,
float scale)
{
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, metadata, path, import_type);
/* FIXME: This is temporary evil solution to get scene/viewlayer/etc in the copy callback of the
* #wmDropBox.
* TODO: Handle link/append in operator called at the end of the drop process, and NOT in its
* copy callback.
* */
asset_drag->evil_C = static_cast<bContext *>(but->block->evil_C);
but->dragtype = WM_DRAG_ASSET;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
}
but->dragpoin = asset_drag;
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
UI_but_drag_attach_image(but, imb, scale);
}
void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr)
{
but->dragtype = WM_DRAG_RNA;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)ptr;
}
void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)path;
if (use_free) {
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
}
}
void UI_but_drag_set_name(uiBut *but, const char *name)
{
but->dragtype = WM_DRAG_NAME;
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)name;
}
void UI_but_drag_set_value(uiBut *but)
{
but->dragtype = WM_DRAG_VALUE;
}
void UI_but_drag_set_image(
uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
}
but->dragpoin = (void *)path;
if (use_free) {
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
}
UI_but_drag_attach_image(but, imb, scale);
}
void ui_but_drag_free(uiBut *but)
{
if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
WM_drag_data_free(but->dragtype, but->dragpoin);
}
}
bool ui_but_drag_is_draggable(const uiBut *but)
{
return but->dragpoin != nullptr;
}
void ui_but_drag_start(bContext *C, uiBut *but)
{
wmDrag *drag = WM_event_start_drag(C,
but->icon,
but->dragtype,
but->dragpoin,
ui_but_value_get(but),
(but->dragflag & UI_BUT_DRAGPOIN_FREE) ? WM_DRAG_FREE_DATA :
WM_DRAG_NOP);
/* wmDrag has ownership over dragpoin now, stop messing with it. */
but->dragpoin = NULL;
if (but->imb) {
WM_event_drag_image(drag, but->imb, but->imb_scale);
}
/* Special feature for assets: We add another drag item that supports multiple assets. It
* gets the assets from context. */
if (ELEM(but->dragtype, WM_DRAG_ASSET, WM_DRAG_ID)) {
WM_event_start_drag(C, ICON_NONE, WM_DRAG_ASSET_LIST, NULL, 0, WM_DRAG_NOP);
}
}

View File

@ -2135,25 +2135,7 @@ static bool ui_but_drag_init(bContext *C,
}
}
else {
wmDrag *drag = WM_event_start_drag(
C,
but->icon,
but->dragtype,
but->dragpoin,
ui_but_value_get(but),
(but->dragflag & UI_BUT_DRAGPOIN_FREE) ? WM_DRAG_FREE_DATA : WM_DRAG_NOP);
/* wmDrag has ownership over dragpoin now, stop messing with it. */
but->dragpoin = NULL;
if (but->imb) {
WM_event_drag_image(drag, but->imb, but->imb_scale);
}
/* Special feature for assets: We add another drag item that supports multiple assets. It
* gets the assets from context. */
if (ELEM(but->dragtype, WM_DRAG_ASSET, WM_DRAG_ID)) {
WM_event_start_drag(C, ICON_NONE, WM_DRAG_ASSET_LIST, NULL, 0, WM_DRAG_NOP);
}
ui_but_drag_start(C, but);
}
return true;
}
@ -4830,7 +4812,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* First handle click on icon-drag type button. */
if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) && but->dragpoin) {
if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) && ui_but_drag_is_draggable(but)) {
if (ui_but_contains_point_px_icon(but, data->region, event)) {
/* tell the button to wait and keep checking further events to
@ -4853,7 +4835,8 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
/* XXX: (a bit ugly) Special case handling for file-browser drag button. */
if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) {
if (ui_but_drag_is_draggable(but) && but->imb &&
ui_but_contains_point_px_icon(but, data->region, event)) {
ret = WM_UI_HANDLER_CONTINUE;
}
/* Same special case handling for UI lists. Return CONTINUE so that a tweak or CLICK event
@ -6007,7 +5990,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* First handle click on icon-drag type button. */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
if (event->type == LEFTMOUSE && ui_but_drag_is_draggable(but) && event->val == KM_PRESS) {
if (ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->xy[0];
@ -6193,7 +6176,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* First handle click on icon-drag type button. */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
if (event->type == LEFTMOUSE && ui_but_drag_is_draggable(but) && event->val == KM_PRESS) {
ui_palette_set_active(color_but);
if (ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
@ -9476,7 +9459,7 @@ static bool ui_list_is_hovering_draggable_but(bContext *C,
}
}
return (hovered_but && hovered_but->dragpoin);
return (hovered_but && ui_but_drag_is_draggable(hovered_but));
}
static int ui_list_handle_click_drag(bContext *C,

View File

@ -1321,6 +1321,12 @@ void ui_button_group_add_but(uiBlock *block, uiBut *but);
void ui_button_group_replace_but_ptr(uiBlock *block, const void *old_but_ptr, uiBut *new_but);
void ui_block_free_button_groups(uiBlock *block);
/* interface_drag.cc */
void ui_but_drag_free(uiBut *but);
bool ui_but_drag_is_draggable(const uiBut *but);
void ui_but_drag_start(struct bContext *C, uiBut *but);
/* interface_align.c */
bool ui_but_can_align(const uiBut *but) ATTR_WARN_UNUSED_RESULT;

View File

@ -64,12 +64,12 @@ bool ui_but_is_interactive_ex(const uiBut *but, const bool labeledit, const bool
if (but->type == UI_BTYPE_LABEL) {
if (for_tooltip) {
/* It's important labels are considered interactive for the purpose of showing tooltip. */
if (but->dragpoin == nullptr && but->tip_func == nullptr) {
if (!ui_but_drag_is_draggable(but) && but->tip_func == nullptr) {
return false;
}
}
else {
if (but->dragpoin == nullptr) {
if (!ui_but_drag_is_draggable(but)) {
return false;
}
}

View File

@ -1536,8 +1536,8 @@ static void template_ID_tabs(const bContext *C,
0.0f,
"");
UI_but_funcN_set(&tab->but, template_ID_set_property_exec_fn, MEM_dupallocN(template), id);
UI_but_drag_set_id(&tab->but, id);
tab->but.custom_data = (void *)id;
tab->but.dragpoin = id;
tab->menu = mt;
UI_but_drawflag_enable(&tab->but, but_align);

View File

@ -1419,7 +1419,7 @@ static void widget_draw_icon(
const bool has_theme = UI_icon_get_theme_color(icon, color);
/* to indicate draggable */
if (but->dragpoin && (but->flag & UI_ACTIVE)) {
if (ui_but_drag_is_draggable(but) && (but->flag & UI_ACTIVE)) {
UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
}
else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW))) {