Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_dragdrop.c
| Show First 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | default: | ||||
| drag->poin = poin; | drag->poin = poin; | ||||
| break; | break; | ||||
| } | } | ||||
| drag->value = value; | drag->value = value; | ||||
| return drag; | return drag; | ||||
| } | } | ||||
| /** | |||||
| * Additional work to cleanly end dragging. Additional because this doesn't actually remove the | |||||
| * drag items. Should be called whenever dragging is stopped (successful or not, also when | |||||
| * canceled). | |||||
| */ | |||||
| void wm_drags_exit(wmWindowManager *wm, wmWindow *win) | |||||
| { | |||||
| bool any_active = false; | |||||
| LISTBASE_FOREACH (const wmDrag *, drag, &wm->drags) { | |||||
| if (drag->active_dropbox) { | |||||
| any_active = true; | |||||
| } | |||||
| } | |||||
| /* If there is no active drop-box #wm_drags_check_ops() set a stop-cursor, which needs to be | |||||
| * restored. */ | |||||
| if (!any_active) { | |||||
| WM_cursor_modal_restore(win); | |||||
| /* Ensure the correct area cursor is restored. */ | |||||
| win->tag_cursor_refresh = true; | |||||
| WM_event_add_mousemove(win); | |||||
| } | |||||
| } | |||||
| void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy) | void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy) | ||||
| { | { | ||||
| drag->imb = imb; | drag->imb = imb; | ||||
| drag->scale = scale; | drag->scale = scale; | ||||
| drag->sx = sx; | drag->sx = sx; | ||||
| drag->sy = sy; | drag->sy = sy; | ||||
| } | } | ||||
| Show All 17 Lines | |||||
| void WM_drag_free(wmDrag *drag) | void WM_drag_free(wmDrag *drag) | ||||
| { | { | ||||
| if (drag->active_dropbox && drag->active_dropbox->draw_deactivate) { | if (drag->active_dropbox && drag->active_dropbox->draw_deactivate) { | ||||
| drag->active_dropbox->draw_deactivate(drag->active_dropbox, drag); | drag->active_dropbox->draw_deactivate(drag->active_dropbox, drag); | ||||
| } | } | ||||
| if (drag->flags & WM_DRAG_FREE_DATA) { | if (drag->flags & WM_DRAG_FREE_DATA) { | ||||
| WM_drag_data_free(drag->type, drag->poin); | WM_drag_data_free(drag->type, drag->poin); | ||||
| } | } | ||||
| if (drag->free_disabled_info) { | |||||
| MEM_SAFE_FREE(drag->disabled_info); | |||||
| } | |||||
| BLI_freelistN(&drag->ids); | BLI_freelistN(&drag->ids); | ||||
| LISTBASE_FOREACH_MUTABLE (wmDragAssetListItem *, asset_item, &drag->asset_items) { | LISTBASE_FOREACH_MUTABLE (wmDragAssetListItem *, asset_item, &drag->asset_items) { | ||||
| if (asset_item->is_external) { | if (asset_item->is_external) { | ||||
| wm_drag_free_asset_data(&asset_item->asset_data.external_info); | wm_drag_free_asset_data(&asset_item->asset_data.external_info); | ||||
| } | } | ||||
| BLI_freelinkN(&drag->asset_items, asset_item); | BLI_freelinkN(&drag->asset_items, asset_item); | ||||
| } | } | ||||
| MEM_freeN(drag); | MEM_freeN(drag); | ||||
| Show All 21 Lines | static char *dropbox_tooltip(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop) | ||||
| return tooltip; | return tooltip; | ||||
| } | } | ||||
| static wmDropBox *dropbox_active(bContext *C, | static wmDropBox *dropbox_active(bContext *C, | ||||
| ListBase *handlers, | ListBase *handlers, | ||||
| wmDrag *drag, | wmDrag *drag, | ||||
| const wmEvent *event) | const wmEvent *event) | ||||
| { | { | ||||
| if (drag->free_disabled_info) { | |||||
| MEM_SAFE_FREE(drag->disabled_info); | |||||
| } | |||||
| drag->disabled_info = NULL; | |||||
| LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { | LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { | ||||
| if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { | if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) { | ||||
| wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; | wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base; | ||||
| if (handler->dropboxes) { | if (handler->dropboxes) { | ||||
| LISTBASE_FOREACH (wmDropBox *, drop, handler->dropboxes) { | LISTBASE_FOREACH (wmDropBox *, drop, handler->dropboxes) { | ||||
| if (drop->poll(C, drag, event) && | if (!drop->poll(C, drag, event)) { | ||||
| WM_operator_poll_context(C, drop->ot, drop->opcontext)) { | /* If the drop's poll fails, don't set the disabled-info. This would be too aggressive. | ||||
| * Instead show it only if the drop box could be used in principle, but the operator | |||||
| * can't be executed. */ | |||||
| continue; | |||||
| } | |||||
| if (WM_operator_poll_context(C, drop->ot, drop->opcontext)) { | |||||
| return drop; | return drop; | ||||
| } | } | ||||
| /* Attempt to set the disabled hint when the poll fails. Will always be the last hint set | |||||
| * when there are multiple failing polls (could allow multiple disabled-hints too). */ | |||||
| bool free_disabled_info = false; | |||||
| const char *disabled_hint = CTX_wm_operator_poll_msg_get(C, &free_disabled_info); | |||||
| if (disabled_hint) { | |||||
| drag->disabled_info = disabled_hint; | |||||
| drag->free_disabled_info = free_disabled_info; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* return active operator tooltip/name when mouse is in box */ | /* return active operator tooltip/name when mouse is in box */ | ||||
| static wmDropBox *wm_dropbox_active(bContext *C, wmDrag *drag, const wmEvent *event) | static wmDropBox *wm_dropbox_active(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| { | { | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| wmDropBox *drop = dropbox_active(C, &win->handlers, drag, event); | wmDropBox *drop = dropbox_active(C, &win->handlers, drag, event); | ||||
| if (!drop) { | if (!drop) { | ||||
| ScrArea *area = CTX_wm_area(C); | ScrArea *area = CTX_wm_area(C); | ||||
| drop = dropbox_active(C, &area->handlers, drag, event); | drop = dropbox_active(C, &area->handlers, drag, event); | ||||
| } | } | ||||
| if (!drop) { | if (!drop) { | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| drop = dropbox_active(C, ®ion->handlers, drag, event); | drop = dropbox_active(C, ®ion->handlers, drag, event); | ||||
| } | } | ||||
| return drop; | return drop; | ||||
| } | } | ||||
| static void wm_drop_operator_options(bContext *C, wmDrag *drag, const wmEvent *event) | /** | ||||
| * Update dropping information for the current mouse position in \a event. | |||||
| */ | |||||
| static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *event) | |||||
| { | { | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| const int winsize_x = WM_window_pixels_x(win); | const int winsize_x = WM_window_pixels_x(win); | ||||
| const int winsize_y = WM_window_pixels_y(win); | const int winsize_y = WM_window_pixels_y(win); | ||||
| /* for multiwin drags, we only do this if mouse inside */ | /* for multiwin drags, we only do this if mouse inside */ | ||||
| if (event->xy[0] < 0 || event->xy[1] < 0 || event->xy[0] > winsize_x || | if (event->xy[0] < 0 || event->xy[1] < 0 || event->xy[0] > winsize_x || | ||||
| event->xy[1] > winsize_y) { | event->xy[1] > winsize_y) { | ||||
| Show All 9 Lines | if (drop != drop_prev) { | ||||
| } | } | ||||
| if (drop && drop->draw_activate) { | if (drop && drop->draw_activate) { | ||||
| drop->draw_activate(drop, drag); | drop->draw_activate(drop, drag); | ||||
| } | } | ||||
| drag->active_dropbox = drop; | drag->active_dropbox = drop; | ||||
| } | } | ||||
| } | } | ||||
| void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop) | |||||
| { | |||||
| /* Optionally copy drag information to operator properties. Don't call it if the | |||||
| * operator fails anyway, it might do more than just set properties (e.g. | |||||
| * typically import an asset). */ | |||||
| if (drop->copy && WM_operator_poll_context(C, drop->ot, drop->opcontext)) { | |||||
| drop->copy(drag, drop); | |||||
| } | |||||
| wm_drags_exit(CTX_wm_manager(C), CTX_wm_window(C)); | |||||
| } | |||||
| /* called in inner handler loop, region context */ | /* called in inner handler loop, region context */ | ||||
| void wm_drags_check_ops(bContext *C, const wmEvent *event) | void wm_drags_check_ops(bContext *C, const wmEvent *event) | ||||
| { | { | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| bool any_active = false; | |||||
| LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) { | LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) { | ||||
| wm_drop_operator_options(C, drag, event); | wm_drop_update_active(C, drag, event); | ||||
| if (drag->active_dropbox) { | |||||
| any_active = true; | |||||
| } | |||||
| } | |||||
| /* Change the cursor to display that dropping isn't possible here. But only if there is something | |||||
| * being dragged actually. Cursor will be restored in #wm_drags_exit(). */ | |||||
| if (!BLI_listbase_is_empty(&wm->drags)) { | |||||
| WM_cursor_modal_set(CTX_wm_window(C), any_active ? WM_CURSOR_DEFAULT : WM_CURSOR_STOP); | |||||
| } | } | ||||
| } | } | ||||
| /* ************** IDs ***************** */ | /* ************** IDs ***************** */ | ||||
| void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent) | void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent) | ||||
| { | { | ||||
| /* Don't drag the same ID twice. */ | /* Don't drag the same ID twice. */ | ||||
| ▲ Show 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | static void wm_drop_operator_draw(const char *name, int x, int y) | ||||
| float col_fg[4], col_bg[4]; | float col_fg[4], col_bg[4]; | ||||
| rgba_uchar_to_float(col_fg, wcol->text); | rgba_uchar_to_float(col_fg, wcol->text); | ||||
| rgba_uchar_to_float(col_bg, wcol->inner); | rgba_uchar_to_float(col_bg, wcol->inner); | ||||
| UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); | UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); | ||||
| } | } | ||||
| static void wm_drop_redalert_draw(const char *redalert_str, int x, int y) | |||||
| { | |||||
| const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; | |||||
| const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; | |||||
| float col_fg[4]; | |||||
| UI_GetThemeColor4fv(TH_REDALERT, col_fg); | |||||
| UI_fontstyle_draw_simple_backdrop(fstyle, x, y, redalert_str, col_fg, col_bg); | |||||
| } | |||||
| const char *WM_drag_get_item_name(wmDrag *drag) | const char *WM_drag_get_item_name(wmDrag *drag) | ||||
| { | { | ||||
| switch (drag->type) { | switch (drag->type) { | ||||
| case WM_DRAG_ID: { | case WM_DRAG_ID: { | ||||
| ID *id = WM_drag_get_local_ID(drag, 0); | ID *id = WM_drag_get_local_ID(drag, 0); | ||||
| bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1); | bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1); | ||||
| if (single) { | if (single) { | ||||
| ▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2]) | ||||
| if (UI_but_active_drop_name(C)) { | if (UI_but_active_drop_name(C)) { | ||||
| tooltip = IFACE_("Paste name"); | tooltip = IFACE_("Paste name"); | ||||
| } | } | ||||
| else if (drag->active_dropbox) { | else if (drag->active_dropbox) { | ||||
| tooltip = dropbox_tooltip(C, drag, xy, drag->active_dropbox); | tooltip = dropbox_tooltip(C, drag, xy, drag->active_dropbox); | ||||
| free_tooltip = true; | free_tooltip = true; | ||||
| } | } | ||||
| if (tooltip) { | if (!tooltip && !drag->disabled_info) { | ||||
| return; | |||||
| } | |||||
| const int winsize_y = WM_window_pixels_y(win); | const int winsize_y = WM_window_pixels_y(win); | ||||
| int x, y; | int x, y; | ||||
| if (drag->imb) { | if (drag->imb) { | ||||
| x = xy[0] - drag->sx / 2; | x = xy[0] - drag->sx / 2; | ||||
| if (xy[1] + drag->sy / 2 + padding + iconsize < winsize_y) { | if (xy[1] + drag->sy / 2 + padding + iconsize < winsize_y) { | ||||
| y = xy[1] + drag->sy / 2 + padding; | y = xy[1] + drag->sy / 2 + padding; | ||||
| } | } | ||||
| else { | else { | ||||
| y = xy[1] - drag->sy / 2 - padding - iconsize - padding - iconsize; | y = xy[1] - drag->sy / 2 - padding - iconsize - padding - iconsize; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| x = xy[0] - 2 * padding; | x = xy[0] - 2 * padding; | ||||
| if (xy[1] + iconsize + iconsize < winsize_y) { | if (xy[1] + iconsize + iconsize < winsize_y) { | ||||
| y = (xy[1] + iconsize) + padding; | y = (xy[1] + iconsize) + padding; | ||||
| } | } | ||||
| else { | else { | ||||
| y = (xy[1] - iconsize) - padding; | y = (xy[1] - iconsize) - padding; | ||||
| } | } | ||||
| } | } | ||||
| if (tooltip) { | |||||
| wm_drop_operator_draw(tooltip, x, y); | wm_drop_operator_draw(tooltip, x, y); | ||||
| if (free_tooltip) { | if (free_tooltip) { | ||||
| MEM_freeN((void *)tooltip); | MEM_freeN((void *)tooltip); | ||||
| } | } | ||||
| } | } | ||||
| else if (drag->disabled_info) { | |||||
| wm_drop_redalert_draw(drag->disabled_info, x, y); | |||||
| } | |||||
| } | } | ||||
| static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2]) | static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2]) | ||||
| { | { | ||||
| int xy_tmp[2] = {UNPACK2(xy)}; | int xy_tmp[2] = {UNPACK2(xy)}; | ||||
| /* Image or icon. */ | /* Image or icon. */ | ||||
| wm_drag_draw_icon(C, win, drag, xy_tmp); | wm_drag_draw_icon(C, win, drag, xy_tmp); | ||||
| ▲ Show 20 Lines • Show All 60 Lines • Show Last 20 Lines | |||||