remove unused includes
[blender.git] / source / blender / editors / interface / interface_handlers.c
index 9bd29532628848dfb145d1bdfd04791d5dae0312..e1a760628b05b090605ef7dc62f28f23a049c3d2 100644 (file)
  */
 
 #include <float.h>
+#include <limits.h>
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -42,7 +44,6 @@
 #include "BKE_idprop.h"
 #include "BKE_report.h"
 #include "BKE_texture.h"
-#include "BKE_utildefines.h"
 
 #include "ED_screen.h"
 #include "ED_util.h"
@@ -176,6 +177,7 @@ typedef struct uiAfterFunc {
        int autokey;
 } uiAfterFunc;
 
+static int ui_but_contains_pt(uiBut *but, int mx, int my);
 static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
 static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata);
@@ -184,11 +186,16 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but);
 
 /* ******************** menu navigation helpers ************** */
 
+static int ui_but_editable(uiBut *but)
+{
+       return ELEM5(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
+}
+
 static uiBut *ui_but_prev(uiBut *but)
 {
        while(but->prev) {
                but= but->prev;
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
        }
        return NULL;
 }
@@ -197,7 +204,7 @@ static uiBut *ui_but_next(uiBut *but)
 {
        while(but->next) {
                but= but->next;
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
        }
        return NULL;
 }
@@ -208,7 +215,7 @@ static uiBut *ui_but_first(uiBlock *block)
        
        but= block->buttons.first;
        while(but) {
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
                but= but->next;
        }
        return NULL;
@@ -220,7 +227,7 @@ static uiBut *ui_but_last(uiBlock *block)
        
        but= block->buttons.last;
        while(but) {
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
                but= but->prev;
        }
        return NULL;
@@ -229,7 +236,7 @@ static uiBut *ui_but_last(uiBlock *block)
 static int ui_is_a_warp_but(uiBut *but)
 {
        if(U.uiflag & USER_CONTINUOUS_MOUSE)
-               if(ELEM(but->type, NUM, NUMABS))
+               if(ELEM3(but->type, NUM, NUMABS, HSVCIRCLE))
                        return TRUE;
 
        return FALSE;
@@ -777,6 +784,8 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
                        break;
        }
        if(bt && bt!=but) {
+               if (!ELEM(bt->type, LINK, INLINK) || !ELEM(but->type, LINK, INLINK))
+                       return;
                
                if(but->type==LINK) ui_add_link(but, bt);
                else ui_add_link(bt, but);
@@ -962,7 +971,7 @@ static void ui_but_drop(bContext *C, wmEvent *event, uiBut *but, uiHandleButtonD
                        if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
                                ID *id= (ID *)wmd->poin;
                                
-                               if(but->poin==NULL && but->rnapoin.data==NULL);
+                               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);
@@ -1004,7 +1013,11 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
                
                if(but->poin==NULL && but->rnapoin.data==NULL);
                else if(mode=='c') {
-                       sprintf(buf, "%f", ui_get_but_val(but));
+                       if(ui_is_but_float(but))
+                               sprintf(buf, "%f", ui_get_but_val(but));
+                       else
+                               sprintf(buf, "%d", (int)ui_get_but_val(but));
+
                        WM_clipboard_text_set(buf, 0);
                }
                else {
@@ -1142,7 +1155,7 @@ static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
        int len= strlen(str);
        int change= 0;
        if(but->selsta != but->selend && len) {
-               memmove( str+but->selsta, str+but->selend, len+1 );
+               memmove( str+but->selsta, str+but->selend, len-but->selsta+1 );
                change= 1;
        }
        
@@ -1150,6 +1163,7 @@ static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
        return change;
 }
 
+/* note, but->block->aspect is used here, when drawing button style is getting scaled too */
 static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, short x)
 {
        uiStyle *style= U.uistyles.first;       // XXX pass on as arg
@@ -1160,7 +1174,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
        uiStyleFontSet(fstyle);
 
        if (fstyle->kerning==1) /* for BLF_width */
-               BLF_enable(BLF_KERNING_DEFAULT);
+               BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
        
        origstr= MEM_callocN(sizeof(char)*data->maxlen, "ui_textedit origstr");
        
@@ -1183,17 +1197,19 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
                
                while (i > 0) {
                        i--;
-                       if (BLF_width(origstr+i) > (startx - x)*0.25) break;    // 0.25 == scale factor for less sensitivity
+                       if (BLF_width(fstyle->uifont_id, origstr+i) > (startx - x)*0.25) break; // 0.25 == scale factor for less sensitivity
                }
                but->ofs = i;
                but->pos = but->ofs;
        }
        /* mouse inside the widget */
        else if (x >= startx) {
+               float aspect= sqrt(but->block->aspect);
+               
                but->pos= strlen(origstr)-but->ofs;
                
                /* XXX does not take zoom level into account */
-               while (startx + BLF_width(origstr+but->ofs) > x) {
+               while (aspect*startx + aspect*BLF_width(fstyle->uifont_id, origstr+but->ofs) > x) {
                        if (but->pos <= 0) break;
                        but->pos--;
                        origstr[but->pos+but->ofs] = 0;
@@ -1203,7 +1219,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
        }
        
        if (fstyle->kerning == 1)
-               BLF_disable(BLF_KERNING_DEFAULT);
+               BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
        
        MEM_freeN(origstr);
 }
@@ -1519,6 +1535,19 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
        data->str= MEM_callocN(sizeof(char)*data->maxlen + 1, "textedit str");
        ui_get_but_string(but, data->str, data->maxlen);
 
+       if(ELEM3(but->type, NUM, NUMABS, NUMSLI)) {
+               /* XXX: we dont have utf editing yet so for numbers its best to strip out utf chars 
+                * this is so the deg' synbol isnt included in number editing fields: bug 22274 */
+               int i;
+               for(i=0; data->str[i]; i++) {
+                       if(!isascii(data->str[i])) {
+                               data->str[i]= '\0';
+                               break;
+                       }
+               }
+       }
+       
+       
        data->origstr= BLI_strdup(data->str);
        data->selextend= 0;
        data->selstartx= 0;
@@ -1645,7 +1674,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                my= event->y;
                                ui_window_to_block(data->region, block, &mx, &my);
 
-                               if ((but->y1 <= my) && (my <= but->y2) && (but->x1 <= mx) && (mx <= but->x2)) {
+                               if (ui_but_contains_pt(but, mx, my)) {
                                        ui_textedit_set_cursor_pos(but, data, mx);
                                        but->selsta = but->selend = but->pos;
                                        data->selstartx= mx;
@@ -1751,7 +1780,11 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                if(event->ascii && (retval == WM_UI_HANDLER_CONTINUE)) {
                        changed= ui_textedit_type_ascii(but, data, event->ascii);
                        retval= WM_UI_HANDLER_BREAK;
+                       
                }
+               /* textbutton with magnifier icon: do live update for search button */
+               if(but->icon==ICON_VIEWZOOM)
+                       update= 1;
        }
 
        if(changed) {
@@ -1981,14 +2014,17 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
                if(event->type == MOUSEMOVE)
                        return WM_UI_HANDLER_CONTINUE;
                
-               if(event->type == ESCKEY) {
-                       /* data->cancel doesnt work, this button opens immediate */
-                       if(but->flag & UI_BUT_IMMEDIATE)
-                               ui_set_but_val(but, 0);
-                       else
-                               data->cancel= 1;
-                       button_activate_state(C, but, BUTTON_STATE_EXIT);
-                       return WM_UI_HANDLER_BREAK;
+               if(event->type == LEFTMOUSE && event->val==KM_PRESS) {
+                       /* only cancel if click outside the button */
+                       if(ui_mouse_inside_button(but->active->region, but, event->x, event->y) == 0) {
+                               /* data->cancel doesnt work, this button opens immediate */
+                               if(but->flag & UI_BUT_IMMEDIATE)
+                                       ui_set_but_val(but, 0);
+                               else
+                                       data->cancel= 1;
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               return WM_UI_HANDLER_BREAK;
+                       }
                }
                
                /* always set */
@@ -2022,15 +2058,11 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
        return WM_UI_HANDLER_CONTINUE;
 }
 
-
 static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
                if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
-                       short event= (short)ui_get_but_val(but);
-                       /* hardcoded prevention from editing or assigning ESC */
-                       if(event!=ESCKEY)
-                               button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+                       button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
                        return WM_UI_HANDLER_BREAK;
                }
        }
@@ -2039,7 +2071,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w
                        return WM_UI_HANDLER_CONTINUE;
 
                if(event->val==KM_PRESS) {
-                       if(event->type!=ESCKEY && WM_key_event_string(event->type)[0])
+                       if(WM_key_event_string(event->type)[0])
                                ui_set_but_val(but, event->type);
                        else
                                data->cancel= 1;
@@ -2106,8 +2138,13 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
                }
                
                if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+                       int ret = WM_UI_HANDLER_BREAK;
+                       /* XXX (a bit ugly) Special case handling for filebrowser drag button */
+                       if(but->dragpoin && but->imb && ui_but_mouse_inside_icon(but, data->region, event)) {
+                               ret = WM_UI_HANDLER_CONTINUE;
+                       }
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
-                       return WM_UI_HANDLER_BREAK;
+                       return ret;
                }
        }
        else if(data->state == BUTTON_STATE_WAIT_DRAG) {
@@ -2200,7 +2237,6 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
        softmax= but->softmax;
        softrange= softmax - softmin;
 
-
        if(ui_is_a_warp_but(but)) {
                /* Mouse location isn't screen clamped to the screen so use a linear mapping
                 * 2px == 1-int, or 1px == 1-ClickStep */
@@ -2260,15 +2296,18 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                /* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
                deler= 500;
                if(!ui_is_but_float(but)) {
-                       if((softrange)<100) deler= 200.0;
-                       if((softrange)<25) deler= 50.0;
+                       /* prevent large ranges from getting too out of control */
+                       if (softrange > 600) deler = powf(softrange, 0.75);
+                       
+                       if (softrange < 100) deler= 200.0;
+                       if (softrange < 25) deler= 50.0;
                }
                deler /= fac;
 
-               if(ui_is_but_float(but) && softrange > 11) {
+               if(softrange > 11) {
                        /* non linear change in mouse input- good for high precicsion */
                        data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
-               } else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
+               } else if (softrange > 129) { /* only scale large int buttons */
                        /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
                        data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
                } else {
@@ -2276,8 +2315,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                        data->dragf+= ((float)(mx-data->draglastx))/deler ;
                }
        
-               if(data->dragf>1.0) data->dragf= 1.0;
-               if(data->dragf<0.0) data->dragf= 0.0;
+               CLAMP(data->dragf, 0.0, 1.0);
                data->draglastx= mx;
                tempf= (softmin + data->dragf*softrange);
 
@@ -2289,7 +2327,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
 
                        CLAMP(temp, softmin, softmax);
                        lvalue= (int)data->value;
-
+                       
                        if(temp != lvalue) {
                                data->dragchange= 1;
                                data->value= (double)temp;
@@ -2937,6 +2975,8 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
                if (color_profile)
                        hsv[2] = srgb_to_linearrgb(hsv[2]);
                
+               if (hsv[2] > but->softmax)
+                       hsv[2] = but->softmax;
        }
 
        hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
@@ -3020,7 +3060,7 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
        return WM_UI_HANDLER_CONTINUE;
 }
 
-static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx, int my)
+static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx, int my, int shift)
 {
        rcti rect;
        int changed= 1;
@@ -3034,13 +3074,29 @@ static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx
        
        /* exception, when using color wheel in 'locked' value state:
         * allow choosing a hue for black values, by giving a tiny increment */
-       if (but->a2 == 1) { // lock
+       if (but->flag & UI_BUT_COLOR_LOCK) { // lock
                if (hsv[2] == 0.f) hsv[2] = 0.0001f;
        }
-               
+
+       if(U.uiflag & USER_CONTINUOUS_MOUSE) {
+               float fac= shift ? 0.05 : 1.0f;
+               /* slow down the mouse, this is fairly picky */
+               mx = (data->dragstartx*(1.0f-fac) + mx*fac);
+               my = (data->dragstarty*(1.0f-fac) + my*fac);
+       }
+
        ui_hsvcircle_vals_from_pos(hsv, hsv+1, &rect, (float)mx, (float)my);
-       
+
+       if(but->flag & UI_BUT_COLOR_CUBIC)
+               hsv[1]= 1.0f - sqrt3f(1.0f - hsv[1]);
+
        hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+
+       if((but->flag & UI_BUT_VEC_SIZE_LOCK) && (rgb[0] || rgb[1] || rgb[2])) {
+               normalize_v3(rgb);
+               mul_v3_fl(rgb, but->a2);
+       }
+
        ui_set_but_vectorf(but, rgb);
        
        data->draglastx= mx;
@@ -3067,7 +3123,7 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
                        button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                        
                        /* also do drag the first time */
-                       if(ui_numedit_but_HSVCIRCLE(but, data, mx, my))
+                       if(ui_numedit_but_HSVCIRCLE(but, data, mx, my, event->shift))
                                ui_numedit_apply(C, block, but, data);
                        
                        return WM_UI_HANDLER_BREAK;
@@ -3118,7 +3174,7 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
                }
                else if(event->type == MOUSEMOVE) {
                        if(mx!=data->draglastx || my!=data->draglasty) {
-                               if(ui_numedit_but_HSVCIRCLE(but, data, mx, my))
+                               if(ui_numedit_but_HSVCIRCLE(but, data, mx, my, event->shift))
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
@@ -3194,24 +3250,8 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
 
                        if(event->ctrl) {
                                /* insert new key on mouse location */
-                               if(coba->tot < MAXCOLORBAND-1) {
-                                       float pos= ((float)(mx - but->x1))/(but->x2-but->x1);
-                                       float col[4];
-                                       
-                                       do_colorband(coba, pos, col);   /* executes it */
-                                       
-                                       coba->tot++;
-                                       coba->cur= coba->tot-1;
-                                       
-                                       coba->data[coba->cur].r= col[0];
-                                       coba->data[coba->cur].g= col[1];
-                                       coba->data[coba->cur].b= col[2];
-                                       coba->data[coba->cur].a= col[3];
-                                       coba->data[coba->cur].pos= pos;
-
-                                       ui_colorband_update(coba);
-                               }
-
+                               float pos= ((float)(mx - but->x1))/(but->x2-but->x1);
+                               colorband_element_add(coba, pos);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
                        else {
@@ -4293,6 +4333,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
        case ROW:
        case LISTROW:
        case BUT_IMAGE:
+       case PROGRESSBAR:
                retval= ui_do_but_EXIT(C, but, data, event);
                break;
        case HISTOGRAM:
@@ -5148,7 +5189,8 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
                        button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
                }
                else {
-                       if(event->type != MOUSEMOVE) {
+                       if (ISKEYBOARD(event->type)) {
+                               /* keyboard menu hierarchy navigation, going back to previous level */
                                but->active->used_mouse= 0;
                                button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
                        }
@@ -5587,8 +5629,7 @@ static int ui_handler_region(bContext *C, wmEvent *event, void *userdata)
        /* either handle events for already activated button or try to activate */
        but= ui_but_find_activated(ar);
 
-       if(!but || !button_modal_state(but->active->state))
-               retval= ui_handler_panel_region(C, event);
+       retval= ui_handler_panel_region(C, event);
 
        if(retval == WM_UI_HANDLER_CONTINUE)
                retval= ui_handle_list_event(C, event, ar);