merge with 2.5 at r18679
[blender.git] / source / blender / editors / interface / interface_handlers.c
index 057f9863278da9714572d0841c7e1992c4b33185..bfe6057cfce429114fa865435d491b91d6142a77 100644 (file)
@@ -41,8 +41,9 @@
 #include "PIL_time.h"
 
 #include "BKE_colortools.h"
+#include "BKE_context.h"
 #include "BKE_idprop.h"
-#include "BKE_global.h"
+#include "BKE_report.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 
 
 #include "UI_interface.h"
 #include "UI_text.h"
-#include "interface.h"
+#include "interface_intern.h"
+
+#include "RNA_access.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
 /***************** structs and defines ****************/
 
-#define BUTTON_TOOLTIP_DELAY           500
-#define BUTTON_FLASH_DELAY                     20
+#define BUTTON_TOOLTIP_DELAY           0.500
+#define BUTTON_FLASH_DELAY                     0.020
 #define BUTTON_AUTO_OPEN_THRESH                0.3
 #define BUTTON_MOUSE_TOWARDS_THRESH    1.0
 
@@ -93,7 +96,7 @@ typedef struct uiHandleButtonData {
        uiHandleButtonState state;
        int cancel, retval;
        int applied, appliedinteractive;
-       wmTimerHandle *flashtimer;
+       wmTimer *flashtimer;
 
        /* edited value */
        char *str, *origstr;
@@ -105,8 +108,8 @@ typedef struct uiHandleButtonData {
 
        /* tooltip */
        ARegion *tooltip;
-       wmTimerHandle *tooltiptimer;
-       wmTimerHandle *autoopentimer;
+       wmTimer *tooltiptimer;
+       wmTimer *autoopentimer;
 
        /* text selection/editing */
        int maxlen, selextend, selstartx;
@@ -144,7 +147,10 @@ typedef struct uiAfterFunc {
 
        const char *opname;
        int opcontext;
-       IDProperty *opproperties;
+       PointerRNA *opptr;
+
+       PointerRNA rnapoin;
+       PropertyRNA *rnaprop;
 } uiAfterFunc;
 
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
@@ -165,7 +171,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
         * handling is done, i.e. menus are closed, in order to avoid conflicts
         * with these functions removing the buttons we are working with */
 
-       if(but->func || block->handle_func || (but->type == BUTM && block->butm_func)) {
+       if(but->func || block->handle_func || (but->type == BUTM && block->butm_func) || but->opname || but->rnaprop) {
                after= MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc");
 
                after->func= but->func;
@@ -184,11 +190,14 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
 
                after->opname= but->opname;
                after->opcontext= but->opcontext;
-               after->opproperties= but->opproperties;
+               after->opptr= but->opptr;
+
+               after->rnapoin= but->rnapoin;
+               after->rnaprop= but->rnaprop;
 
                but->opname= NULL;
                but->opcontext= 0;
-               but->opproperties= NULL;
+               but->opptr= NULL;
 
                BLI_addtail(&UIAfterFuncs, after);
        }
@@ -213,11 +222,14 @@ static void ui_apply_but_funcs_after(bContext *C)
                        after->butm_func(C, after->butm_func_arg, after->a2);
 
                if(after->opname)
-                       WM_operator_call(C, after->opname, after->opcontext, after->opproperties);
-               if(after->opproperties) {
-                       IDP_FreeProperty(after->opproperties);
-                       MEM_freeN(after->opproperties);
+                       WM_operator_name_call(C, after->opname, after->opcontext, after->opptr);
+               if(after->opptr) {
+                       WM_operator_properties_free(after->opptr);
+                       MEM_freeN(after->opptr);
                }
+
+               if(after->rnapoin.data)
+                       RNA_property_update(C, &after->rnapoin, after->rnaprop);
        }
 
        BLI_freelistN(&funcs);
@@ -345,7 +357,7 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
                /* XXX 2.50 missing python api */
 #if 0
                if(BPY_button_eval(data->str, &data->value)) {
-                       WM_report(C, WM_LOG_WARNING, "Invalid Python expression, check console");
+                       BKE_report(CTX_reports(C), RPT_WARNING, "Invalid Python expression, check console");
                        data->value = 0.0f; /* Zero out value on error */
                        
                        if(data->str[0]) {
@@ -1414,7 +1426,7 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
        }
 
        /* this makes adjacent blocks auto open from now on */
-       if(but->block->auto_open==0) but->block->auto_open= 1;
+       //if(but->block->auto_open==0) but->block->auto_open= 1;
 }
 
 static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -2536,14 +2548,14 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
        if(ELEM(event->type, LEFTMOUSE, RETKEY)) {
                if(but->lock) {
                        if(but->lockstr) {
-                               WM_report(C, WM_LOG_WARNING, but->lockstr);
+                               BKE_report(CTX_reports(C), RPT_WARNING, but->lockstr);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                return WM_UI_HANDLER_BREAK;
                        }
                } 
                else if(but->pointype && but->poin==0) {
                        /* there's a pointer needed */
-                       WM_reportf(C, WM_LOG_WARNING, "DoButton pointer error: %s", but->str);
+                       BKE_reportf(CTX_reports(C), RPT_WARNING, "DoButton pointer error: %s", but->str);
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                        return WM_UI_HANDLER_BREAK;
                }
@@ -2760,7 +2772,7 @@ static void button_tooltip_timer_reset(uiBut *but)
 
        if(U.flag & USER_TOOLTIPS)
                if(!but->block->tooltipdisabled)
-                       data->tooltiptimer= WM_event_add_window_timer(data->window, BUTTON_TOOLTIP_DELAY, ~0);
+                       data->tooltiptimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_TOOLTIP_DELAY);
 }
 
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@@ -2788,7 +2800,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                                else time= -1;
 
                                if(time >= 0)
-                                       data->autoopentimer= WM_event_add_window_timer(data->window, time*20, ~0);
+                                       data->autoopentimer= WM_event_add_window_timer(data->window, TIMER, 0.02*(double)time);
                        }
                }
        }
@@ -2830,7 +2842,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
 
        /* add a short delay before exiting, to ensure there is some feedback */
        if(state == BUTTON_STATE_WAIT_FLASH) {
-               data->flashtimer= WM_event_add_window_timer(data->window, BUTTON_FLASH_DELAY, ~0);
+               data->flashtimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_FLASH_DELAY);
        }
        else if(data->flashtimer) {
                WM_event_remove_window_timer(data->window, data->flashtimer);
@@ -2862,9 +2874,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
 
        /* setup struct */
        data= MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
-       data->window= C->window;
+       data->window= CTX_wm_window(C);
        data->region= ar;
-       data->interactive= 0;
+       data->interactive= 1;
        data->state = BUTTON_STATE_INIT;
 
        /* activate button */
@@ -3326,16 +3338,15 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiMenuBlockHandle *menu, i
                                if(inside || (block->flag & UI_BLOCK_LOOP)) {
                                        if(event->val) {
                                                but= ui_but_find_activated(ar);
-
                                                if(but) {
-                                                       if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) {
-                                                               if(block->direction & UI_TOP) but= ui_but_next(but);
-                                                               else but= ui_but_prev(but);
-                                                       }
-                                                       else {
+                                                       if(ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) {
                                                                if(block->direction & UI_TOP) but= ui_but_prev(but);
                                                                else but= ui_but_next(but);
                                                        }
+                                                       else {
+                                                               if(block->direction & UI_TOP) but= ui_but_next(but);
+                                                               else but= ui_but_prev(but);
+                                                       }
 
                                                        if(but)
                                                                ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
@@ -3498,6 +3509,7 @@ static int ui_handle_menu_closed_submenu(bContext *C, wmEvent *event, uiMenuBloc
 
        but= ui_but_find_activated(ar);
        data= but->active;
+       submenu= data->menu;
 
        if(submenu->menuretval) {
                /* first decide if we want to close our own menu cascading, if
@@ -3555,7 +3567,7 @@ static int ui_handler_region(bContext *C, wmEvent *event, void *userdata)
        int retval;
 
        /* here we handle buttons at the region level, non-modal */
-       ar= C->region;
+       ar= CTX_wm_region(C);
        retval= WM_UI_HANDLER_CONTINUE;
 
        if(ar==NULL) return retval;
@@ -3564,10 +3576,15 @@ 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)
-               retval= ui_handle_button_event(C, event, but);
-       else
-               retval= ui_handle_button_over(C, event, ar);
+       if(!but || !button_modal_state(but->active->state))
+               retval= ui_handler_panel_region(C, event);
+
+       if(retval == WM_UI_HANDLER_CONTINUE) {
+               if(but)
+                       retval= ui_handle_button_event(C, event, but);
+               else
+                       retval= ui_handle_button_over(C, event, ar);
+       }
 
        /* re-enable tooltips */
        if(event->type == MOUSEMOVE && (event->x!=event->prevx || event->y!=event->prevy))
@@ -3584,12 +3601,12 @@ static void ui_handler_remove_region(bContext *C, void *userdata)
        bScreen *sc;
        ARegion *ar;
 
-       ar= C->region;
+       ar= CTX_wm_region(C);
        if(ar == NULL) return;
 
        uiFreeBlocks(C, &ar->uiblocks);
        
-       sc= C->screen;
+       sc= CTX_wm_screen(C);
        if(sc == NULL) return;
 
        /* delayed apply callbacks, but not for screen level regions, those
@@ -3608,7 +3625,7 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata)
 
        /* here we handle buttons at the window level, modal, for example
         * while number sliding, text editing, or when a menu block is open */
-       ar= C->region;
+       ar= CTX_wm_region(C);
        but= ui_but_find_activated(ar);
 
        if(but) {
@@ -3645,6 +3662,7 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata)
        return WM_UI_HANDLER_BREAK;
 }
 
+/* two types of popups, one with operator + enum, other with regular callbacks */
 static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
 {
        uiMenuBlockHandle *menu= userdata;
@@ -3653,11 +3671,26 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
 
        /* free if done, does not free handle itself */
        if(menu->menuretval) {
+               /* copy values, we have to free first (closes region) */
+               uiMenuBlockHandle temp= *menu;
+               
                ui_menu_block_free(C, menu);
-               WM_event_remove_ui_handler(&C->window->handlers, ui_handler_popup, ui_handler_remove_popup, menu);
+               WM_event_remove_ui_handler(&CTX_wm_window(C)->handlers, ui_handler_popup, ui_handler_remove_popup, menu);
 
-               if(menu->menuretval == UI_RETURN_OK && menu->popup_func)
-                       menu->popup_func(C, menu->popup_arg, menu->retvalue);
+               if(temp.menuretval == UI_RETURN_OK) {
+                       if(temp.popup_func) {
+                               temp.popup_func(C, temp.op_arg, temp.retvalue);
+                       }
+                       else if(temp.op_arg) {
+                               if(temp.propname)
+                                       RNA_enum_set(temp.op_arg->ptr, temp.propname, temp.retvalue);
+                               WM_operator_call(C, temp.op_arg);
+                       }
+               }
+               /* always free operator */
+               else if(temp.op_arg)
+                       WM_operator_free(temp.op_arg);
+               
        }
        else {
                /* re-enable tooltips */
@@ -3693,4 +3726,3 @@ void UI_add_popup_handlers(ListBase *handlers, uiMenuBlockHandle *menu)
 {
        WM_event_add_ui_handler(NULL, handlers, ui_handler_popup, ui_handler_remove_popup, menu);
 }
-