From b18defbffbf9171f26ab6ccabe5cb5609ad842a9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 28 Jan 2009 23:29:27 +0000 Subject: 2.5: * Automatic shortcut keys in menus now compare operator properties as well. Implemented IDP_EqualsProperties for this. * I imagine all these compares may be a bit slow, for this case it's not so bad though because it only happens for one menu when it is opened. --- source/blender/blenkernel/BKE_idprop.h | 2 + source/blender/blenkernel/intern/idprop.c | 54 ++++++++++++++++++++++ source/blender/editors/interface/interface.c | 27 ++++++++--- .../blender/editors/interface/interface_intern.h | 4 +- .../blender/editors/interface/interface_regions.c | 3 ++ source/blender/editors/space_image/image_header.c | 1 + source/blender/windowmanager/WM_api.h | 2 +- source/blender/windowmanager/intern/wm_keymap.c | 53 ++++++++++++--------- 8 files changed, 115 insertions(+), 31 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 4f57e1d6d14..1980ba78c86 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -142,6 +142,8 @@ void IDP_FreeIterBeforeEnd(void *vself); struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed); struct IDProperty *IDP_CopyProperty(struct IDProperty *prop); +int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2); + /* Allocate a new ID. diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index c2474e847ae..3be47778674 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -527,6 +527,60 @@ IDProperty *IDP_GetProperties(ID *id, int create_if_needed) } } +int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) +{ + if(prop1 == NULL && prop2 == NULL) + return 1; + else if(prop1 == NULL || prop2 == NULL) + return 0; + else if(prop1->type != prop2->type) + return 0; + + if(prop1->type == IDP_INT) + return (IDP_Int(prop1) == IDP_Int(prop2)); + else if(prop1->type == IDP_FLOAT) + return (IDP_Float(prop1) == IDP_Float(prop2)); + else if(prop1->type == IDP_DOUBLE) + return (IDP_Double(prop1) == IDP_Double(prop2)); + else if(prop1->type == IDP_STRING) + return BSTR_EQ(IDP_String(prop1), IDP_String(prop2)); + else if(prop1->type == IDP_ARRAY) { + if(prop1->len == prop2->len && prop1->subtype == prop2->subtype) + return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[prop1->subtype]*prop1->len); + else + return 0; + } + else if(prop1->type == IDP_GROUP) { + IDProperty *link1, *link2; + + if(BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) + return 0; + + for(link1=prop1->data.group.first; link1; link1=link1->next) { + link2= IDP_GetPropertyFromGroup(prop2, link1->name); + + if(!IDP_EqualsProperties(link1, link2)) + return 0; + } + + return 1; + } + else if(prop1->type == IDP_IDPARRAY) { + IDProperty *array1= IDP_IDPArray(prop1); + IDProperty *array2= IDP_IDPArray(prop2); + int i; + + if(prop1->len != prop2->len) + return 0; + + for(i=0; ilen; i++) + if(!IDP_EqualsProperties(&array1[i], &array2[i])) + return 0; + } + + return 1; +} + IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name) { IDProperty *prop=NULL; diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d2c1e6859cb..5b8dda2f3b4 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -207,11 +207,17 @@ void ui_window_to_region(const ARegion *ar, int *x, int *y) /* ******************* block calc ************************* */ -/* only for pulldowns */ void uiTextBoundsBlock(uiBlock *block, int addval) +{ + block->textbounds= addval; + block->dotextbounds= 1; +} + +/* only for pulldowns */ +static void ui_text_bounds_block(uiBlock *block) { uiBut *bt; - int i = 0, j, x1addval= 0, nextcol; + int i = 0, j, x1addval= 0, nextcol, addval= block->textbounds; bt= block->buttons.first; while(bt) { @@ -482,13 +488,15 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) { uiBut *but; + IDProperty *prop; char buf[512], *butstr; + int bounds= 0;; - /* XXX bounds? */ for(but=block->buttons.first; but; but=but->next) { - /* only hotkey for menus without properties */ - if(but->opname && but->opptr==NULL) { - if(WM_key_event_operator_string(C, but->opname, but->opcontext, buf, sizeof(buf))) { + if(but->opname) { + prop= (but->opptr)? but->opptr->data: NULL; + + if(WM_key_event_operator_string(C, but->opname, but->opcontext, prop, buf, sizeof(buf))) { butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps"); strcpy(butstr, but->str); strcat(butstr, "|"); @@ -499,6 +507,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) MEM_freeN(butstr); ui_check_but(but); + bounds= 1; } } } @@ -526,9 +535,12 @@ void uiEndBlock(const bContext *C, uiBlock *block) /* handle pending stuff */ if(block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block); + if(block->dotextbounds) ui_text_bounds_block(block); /* after keymaps! */ if(block->autofill) ui_autofill(block); if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0); if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block); + + block->endblock= 1; } /* ************** BLOCK DRAWING FUNCTION ************* */ @@ -537,6 +549,9 @@ void uiDrawBlock(const bContext *C, uiBlock *block) { uiBut *but; + if(!block->endblock) + uiEndBlock(C, block); + /* we set this only once */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index f4e37867fc3..43b7e280170 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -214,7 +214,9 @@ struct uiBlock { int lock; char *lockstr; - float xofs, yofs; // offset to parent button + float xofs, yofs; // offset to parent button + int textbounds, dotextbounds; // for doing delayed + int endblock; // uiEndBlock done? rctf safety; // pulldowns, to detect outside, can differ per case how it is created ListBase saferct; // uiSafetyRct list diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index d29cf6103fe..90385ab2897 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -651,6 +651,9 @@ uiMenuBlockHandle *ui_menu_block_create(bContext *C, ARegion *butregion, uiBut * block= block_func(C, handle, arg); block->handle= handle; + if(!block->endblock) + uiEndBlock(C, block); + /* if this is being created from a button */ if(but) { if(ELEM(but->type, BLOCK, PULLDOWN)) diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c index f9601e175ce..e015d5aeedf 100644 --- a/source/blender/editors/space_image/image_header.c +++ b/source/blender/editors/space_image/image_header.c @@ -112,6 +112,7 @@ static uiBlock *image_view_viewnavmenu(bContext *C, uiMenuBlockHandle *handle, v /* position menu */ uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); + uiEndBlock(C, block); return block; } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 8eb12543b86..cb6d26a1506 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -81,7 +81,7 @@ ListBase *WM_keymap_listbase (struct wmWindowManager *wm, const char *nameid, int spaceid, int regionid); char *WM_key_event_string(short type); -char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, char *str, int len); +char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); /* handlers */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 864146a8576..46a5c45a30d 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -37,6 +37,7 @@ #include "BKE_blender.h" #include "BKE_context.h" +#include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_utildefines.h" @@ -507,13 +508,35 @@ static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len) return str; } -char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, char *str, int len) +static char *wm_keymap_item_find(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, char *str, int len) { wmEventHandler *handler; wmKeymapItem *kmi; - ListBase *handlers= NULL; - /* find right handler list based on specified context */ + /* find keymap item in handlers */ + for(handler=handlers->first; handler; handler=handler->next) + if(handler->keymap) + for(kmi=handler->keymap->first; kmi; kmi=kmi->next) + if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) + if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) + return wm_keymap_item_to_string(kmi, str, len); + + return NULL; +} + +char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len) +{ + char *found= NULL; + + /* look into multiple handler lists to find the item */ + if(CTX_wm_window(C)) + if((found= wm_keymap_item_find(&CTX_wm_window(C)->handlers, opname, opcontext, properties, str, len))) + return found; + + if(CTX_wm_area(C)) + if((found= wm_keymap_item_find(&CTX_wm_area(C)->handlers, opname, opcontext, properties, str, len))) + return found; + if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { if(CTX_wm_area(C)) { ARegion *ar= CTX_wm_area(C)->regionbase.first; @@ -522,32 +545,16 @@ char *WM_key_event_operator_string(const bContext *C, const char *opname, int op break; if(ar) - handlers= &ar->handlers; + if((found= wm_keymap_item_find(&ar->handlers, opname, opcontext, properties, str, len))) + return found; } } - else if(ELEM(opcontext, WM_OP_EXEC_AREA, WM_OP_INVOKE_AREA)) { - if(CTX_wm_area(C)) - handlers= &CTX_wm_area(C)->handlers; - } - else if(ELEM(opcontext, WM_OP_EXEC_SCREEN, WM_OP_INVOKE_SCREEN)) { - if(CTX_wm_window(C)) - handlers= &CTX_wm_window(C)->handlers; - } else { if(CTX_wm_region(C)) - handlers= &CTX_wm_region(C)->handlers; + if((found= wm_keymap_item_find(&CTX_wm_region(C)->handlers, opname, opcontext, properties, str, len))) + return found; } - if(!handlers) - return NULL; - - /* find keymap item in handlers */ - for(handler=handlers->first; handler; handler=handler->next) - if(handler->keymap) - for(kmi=handler->keymap->first; kmi; kmi=kmi->next) - if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) - return wm_keymap_item_to_string(kmi, str, len); - return NULL; } -- cgit v1.2.3