2.5
[blender-staging.git] / source / blender / editors / interface / interface_handlers.c
index 0987f0d2f2a8f6c47da5335f52194c622582c38f..5c3fc890144afa51072ab7b5156c7438d7e07bd1 100644 (file)
@@ -840,6 +840,9 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                        ui_apply_but_CHARTAB(C, but, data);
                        break;
 #endif
+               case HOTKEYEVT:
+                       ui_apply_but_BUT(C, but, data);
+                       break;
                case LINK:
                case INLINK:
                        ui_apply_but_LINK(C, but, data);
@@ -1801,6 +1804,60 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv
        return WM_UI_HANDLER_CONTINUE;
 }
 
+static int ui_do_but_HOTKEYEVT(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) {
+                       but->drawstr[0]= 0;
+                       button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+                       return WM_UI_HANDLER_BREAK;
+               }
+       }
+       else if(data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
+               short *sp= (short *)but->func_arg3;
+               
+               if(event->type == MOUSEMOVE)
+                       return WM_UI_HANDLER_CONTINUE;
+               
+               if(ELEM(event->type, ESCKEY, LEFTMOUSE)) {
+                       /* data->cancel doesnt work, this button opens immediate */
+                       ui_set_but_val(but, 0);
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       return WM_UI_HANDLER_BREAK;
+               }
+               
+               /* always set */
+               *sp= 0; 
+               if(event->shift)
+                       *sp |= KM_SHIFT;
+               if(event->alt)
+                       *sp |= KM_ALT;
+               if(event->ctrl)
+                       *sp |= KM_CTRL;
+               if(event->oskey)
+                       *sp |= KM_OSKEY;
+               
+               ui_check_but(but);
+               ED_region_tag_redraw(data->region);
+                       
+               if(event->val==KM_PRESS) {
+                       if(ISHOTKEY(event->type)) { 
+                               
+                               if(WM_key_event_string(event->type)[0])
+                                       ui_set_but_val(but, event->type);
+                               else
+                                       data->cancel= 1;
+                               
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               return WM_UI_HANDLER_BREAK;
+                       }
+               }
+       }
+       
+       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) {
@@ -3103,6 +3160,67 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
        return WM_UI_HANDLER_CONTINUE;
 }
 
+/* callback for hotkey change button/menu */
+static void do_menu_change_hotkey(bContext *C, void *but_v, void *key_v)
+{
+       uiBut *but= but_v;
+       IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
+       short *key= key_v;
+       char buf[512], *butstr, *cpoin;
+       
+       /* signal for escape */
+       if(key[0]==0) return;
+       
+       WM_key_event_operator_change(C, but->optype->idname, but->opcontext, prop, key[0], key[1]);
+
+       /* complex code to change name of button */
+       if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) {
+               
+               butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps");
+               
+               /* XXX but->str changed... should not, remove the hotkey from it */
+               cpoin= strchr(but->str, '|');
+               if(cpoin) *cpoin= 0;            
+
+               strcpy(butstr, but->str);
+               strcat(butstr, "|");
+               strcat(butstr, buf);
+               
+               but->str= but->strdata;
+               BLI_strncpy(but->str, butstr, sizeof(but->strdata));
+               MEM_freeN(butstr);
+               
+               ui_check_but(but);
+       }
+                               
+}
+
+
+static uiBlock *menu_change_hotkey(bContext *C, ARegion *ar, void *arg_but)
+{
+       uiBlock *block;
+       uiBut *but= arg_but;
+       wmOperatorType *ot= WM_operatortype_find(but->optype->idname, 1);
+       static short dummy[2];
+       char buf[OP_MAX_TYPENAME+10];
+       
+       dummy[0]= 0;
+       dummy[1]= 0;
+       
+       block= uiBeginBlock(C, ar, "_popup", UI_EMBOSSP);
+       uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_MOVEMOUSE_QUIT|UI_BLOCK_RET_1);
+       
+       BLI_strncpy(buf, ot->name, OP_MAX_TYPENAME);
+       strcat(buf, " |");
+       
+       but= uiDefHotKeyevtButS(block, 0, buf, 0, 0, 200, 20, dummy, dummy+1, "");
+       uiButSetFunc(but, do_menu_change_hotkey, arg_but, dummy);
+
+       uiPopupBoundsBlock(block, 6.0f, 50, -10);
+       uiEndBlock(C, block);
+       
+       return block;
+}
 
 static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
 {
@@ -3145,9 +3263,22 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                }
                /* handle menu */
                else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) {
-                       button_timers_tooltip_remove(C, but);
-                       ui_but_anim_menu(C, but);
-                       return WM_UI_HANDLER_BREAK;
+                       /* RMB has two options now */
+                       if(but->rnapoin.data && but->rnaprop) {
+                               button_timers_tooltip_remove(C, but);
+                               ui_but_anim_menu(C, but);
+                               return WM_UI_HANDLER_BREAK;
+                       }
+                       else if((but->block->flag & UI_BLOCK_LOOP) && but->optype) {
+                               IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
+                               char buf[512];
+                               
+                               if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) {
+                                       
+                                       uiPupBlock(C, menu_change_hotkey, but);
+
+                               }
+                       }
                }
        }
 
@@ -3176,6 +3307,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
        case KEYEVT:
                retval= ui_do_but_KEYEVT(C, but, data, event);
                break;
+       case HOTKEYEVT:
+               retval= ui_do_but_HOTKEYEVT(C, but, data, event);
+               break;
        case TOGBUT: 
        case TOG: 
        case TOGR: 
@@ -3521,6 +3655,10 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
        }
        button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
        
+       /* activate right away */
+       if(but->type==HOTKEYEVT)
+               button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+       
        if(type == BUTTON_ACTIVATE_OPEN) {
                button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);