diff options
Diffstat (limited to 'source/blender/editors/interface/interface_handlers.c')
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 185 |
1 files changed, 173 insertions, 12 deletions
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7273dc2360e..b84bdcd958e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -89,6 +89,7 @@ typedef enum uiHandleButtonState { BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_TEXT_SELECTING, BUTTON_STATE_MENU_OPEN, + BUTTON_STATE_WAIT_DRAG, BUTTON_STATE_EXIT } uiHandleButtonState; @@ -602,6 +603,53 @@ static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *da } #endif +/* ****************** drag drop code *********************** */ + +static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event) +{ + rcti rect; + int x= event->x, y= event->y; + + ui_window_to_block(ar, but->block, &x, &y); + + rect.xmin= but->x1; rect.xmax= but->x2; + rect.ymin= but->y1; rect.ymax= but->y2; + + if(but->imb); /* use button size itself */ + else if(but->flag & UI_ICON_LEFT) { + rect.xmax= rect.xmin + (rect.ymax-rect.ymin); + } + else { + int delta= (rect.xmax-rect.xmin) - (rect.ymax-rect.ymin); + rect.xmin += delta/2; + rect.xmax -= delta/2; + } + + return BLI_in_rcti(&rect, x, y); +} + +#define UI_DRAG_THRESHOLD 3 +static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) +{ + /* prevent other WM gestures to start while we try to drag */ + WM_gestures_remove(C); + + if( ABS(data->dragstartx - event->x) + ABS(data->dragstarty - event->y) > UI_DRAG_THRESHOLD ) { + wmDrag *drag; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + data->cancel= 1; + + drag= WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but)); + if(but->imb) + WM_event_drag_image(drag, but->imb, but->imb_scale, but->x2-but->x1, but->y2-but->y1); + return 1; + } + + return 0; +} + +/* ********************** linklines *********************** */ static void ui_delete_active_linkline(uiBlock *block) { @@ -894,6 +942,30 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut but->editcumap= editcumap; } +/* ******************* drop event ******************** */ + +/* only call if event type is EVT_DROP */ +static void ui_but_drop(bContext *C, wmEvent *event, uiBut *but, uiHandleButtonData *data) +{ + wmDrag *wmd; + ListBase *drags= event->customdata; /* drop event type has listbase customdata by default */ + + for(wmd= drags->first; wmd; wmd= wmd->next) { + if(wmd->type==WM_DRAG_ID) { + /* align these types with UI_but_active_drop_name */ + if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { + ID *id= (ID *)wmd->poin; + + if(but->poin==NULL && but->rnapoin.data==NULL); + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + BLI_strncpy(data->str, id->name+2, data->maxlen); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } + } + +} + /* ******************* copy and paste ******************** */ /* c = copy, v = paste */ @@ -1984,13 +2056,40 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) { + if(data->state == BUTTON_STATE_HIGHLIGHT) { + + /* first handle click on icondrag type button */ + if(event->type==LEFTMOUSE && but->dragpoin) { + if(ui_but_mouse_inside_icon(but, data->region, event)) { + button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); + data->dragstartx= event->x; + data->dragstarty= event->y; + return WM_UI_HANDLER_BREAK; + } + } + if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } } - + else if(data->state == BUTTON_STATE_WAIT_DRAG) { + + /* this function also ends state */ + if(ui_but_start_drag(C, but, data, event)) { + return WM_UI_HANDLER_BREAK; + } + + /* pass on release as press for other keymaps XXX hack alert! */ + if(event->type==LEFTMOUSE && event->val==KM_RELEASE) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + event->val= KM_PRESS; + return WM_UI_HANDLER_CONTINUE; + } + + } + return WM_UI_HANDLER_CONTINUE; } @@ -2554,10 +2653,23 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return retval; } + static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) { if(data->state == BUTTON_STATE_HIGHLIGHT) { + + /* first handle click on icondrag type button */ + if(event->type==LEFTMOUSE && but->dragpoin && event->val==KM_PRESS) { + if(ui_but_mouse_inside_icon(but, data->region, event)) { + button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); + data->dragstartx= event->x; + data->dragstarty= event->y; + return WM_UI_HANDLER_BREAK; + } + } + + /* regular open menu */ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); return WM_UI_HANDLER_BREAK; @@ -2598,6 +2710,26 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm } } } + else if(data->state == BUTTON_STATE_WAIT_DRAG) { + + /* this function also ends state */ + if(ui_but_start_drag(C, but, data, event)) { + return WM_UI_HANDLER_BREAK; + } + + /* outside icon quit, not needed if drag activated */ + if(0==ui_but_mouse_inside_icon(but, data->region, event)) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + data->cancel= 1; + return WM_UI_HANDLER_BREAK; + } + + if(event->type==LEFTMOUSE && event->val==KM_RELEASE) { + button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); + return WM_UI_HANDLER_BREAK; + } + + } return WM_UI_HANDLER_CONTINUE; } @@ -3747,6 +3879,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) ui_but_copy_paste(C, but, data, (event->type == CKEY)? 'c': 'v'); return WM_UI_HANDLER_BREAK; } + /* handle drop */ + else if(event->type == EVT_DROP) { + ui_but_drop (C, event, but, data); + } /* handle keyframing */ else if(event->type == IKEY && event->val == KM_PRESS) { if(event->alt) @@ -3931,6 +4067,21 @@ int ui_button_is_active(ARegion *ar) return (ui_but_find_activated(ar) != NULL); } +/* returns TRUE if highlighted button allows drop of names */ +/* called in region context */ +int UI_but_active_drop_name(bContext *C) +{ + ARegion *ar= CTX_wm_region(C); + uiBut *but= ui_but_find_activated(ar); + + if(but) { + if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) + return 1; + } + + return 0; +} + static void ui_blocks_set_tooltips(ARegion *ar, int enable) { uiBlock *block; @@ -4018,8 +4169,8 @@ static uiBut *ui_but_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y) uiBut *but, *butover= NULL; int mx, my; - if(!win->active) - return NULL; +// if(!win->active) +// return NULL; if(!ui_mouse_inside_region(ar, x, y)) return NULL; @@ -4029,7 +4180,10 @@ static uiBut *ui_but_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y) ui_window_to_block(ar, block, &mx, &my); for(but=block->buttons.first; but; but= but->next) { - if(ELEM4(but->type, LABEL, ROUNDBOX, SEPR, LISTBOX)) + /* note, LABEL is included for hilights, this allows drags */ + if(but->type==LABEL && but->dragpoin==NULL) + continue; + if(ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX)) continue; if(but->flag & UI_HIDDEN) continue; @@ -4047,8 +4201,8 @@ static uiBut *ui_list_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y) uiBut *but; int mx, my; - if(!win->active) - return NULL; +// if(!win->active) +// return NULL; if(!ui_mouse_inside_region(ar, x, y)) return NULL; @@ -4095,8 +4249,9 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but) } } -static void button_tooltip_timer_reset(uiBut *but) +static void button_tooltip_timer_reset(bContext *C, uiBut *but) { + wmWindowManager *wm= CTX_wm_manager(C); uiHandleButtonData *data; data= but->active; @@ -4108,7 +4263,8 @@ static void button_tooltip_timer_reset(uiBut *but) if(U.flag & USER_TOOLTIPS) if(!but->block->tooltipdisabled) - data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY); + if(!wm->drags.first) + data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY); } static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state) @@ -4123,7 +4279,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s if(state == BUTTON_STATE_HIGHLIGHT) { but->flag &= ~UI_SELECT; - button_tooltip_timer_reset(but); + button_tooltip_timer_reset(C, but); /* automatic open pulldown block timer */ if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) { @@ -4190,6 +4346,11 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data); } } + + /* wait for mousemove to enable drag */ + if(state == BUTTON_STATE_WAIT_DRAG) { + but->flag &= ~UI_SELECT; + } data->state= state; @@ -4449,7 +4610,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) else if(event->x!=event->prevx || event->y!=event->prevy) { /* re-enable tooltip on mouse move */ ui_blocks_set_tooltips(ar, 1); - button_tooltip_timer_reset(but); + button_tooltip_timer_reset(C, but); } break; @@ -4555,8 +4716,8 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) retval= WM_UI_HANDLER_CONTINUE; } else { - ui_do_button(C, block, but, event); - retval= WM_UI_HANDLER_BREAK; + retval= ui_do_button(C, block, but, event); + // retval= WM_UI_HANDLER_BREAK; XXX why ? } if(data->state == BUTTON_STATE_EXIT) { |