Revision: 33648
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=33648
Author:   campbellbarton
Date:     2010-12-14 03:38:29 +0100 (Tue, 14 Dec 2010)

Log Message:
-----------
Menu UI feature common in other widget sets:
 Automatically assign menu keys based on name, alternative to pressing number 
0-9 on menus items.

 keys are assigned by first giving each menu item the first character of any 
word, if that fails any key in the name is used.

- active key is shown underlined.
- only ascii keys are assigned currently.
- can run operators, open menu items.
- currently this only works in cases where number buttons were used 
(UI_BLOCK_NUMSELECT), but could be enabled for file menu, splash etc by 
removing this check.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/include/UI_interface.h
    trunk/blender/source/blender/editors/interface/interface.c
    trunk/blender/source/blender/editors/interface/interface_handlers.c
    trunk/blender/source/blender/editors/interface/interface_intern.h
    trunk/blender/source/blender/editors/interface/interface_style.c
    trunk/blender/source/blender/editors/interface/interface_widgets.c

Modified: trunk/blender/source/blender/editors/include/UI_interface.h
===================================================================
--- trunk/blender/source/blender/editors/include/UI_interface.h 2010-12-14 
01:19:51 UTC (rev 33647)
+++ trunk/blender/source/blender/editors/include/UI_interface.h 2010-12-14 
02:38:29 UTC (rev 33648)
@@ -749,6 +749,8 @@
 
 /* Styled text draw */
 void uiStyleFontSet(struct uiFontStyle *fs);
+void uiStyleFontDrawExt(struct uiFontStyle *fs, struct rcti *rect, const char 
*str,
+       float *r_xofs, float *r_yofs);
 void uiStyleFontDraw(struct uiFontStyle *fs, struct rcti *rect, const char 
*str);
 void uiStyleFontDrawRotated(struct uiFontStyle *fs, struct rcti *rect, const 
char *str);
 

Modified: trunk/blender/source/blender/editors/interface/interface.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface.c  2010-12-14 
01:19:51 UTC (rev 33647)
+++ trunk/blender/source/blender/editors/interface/interface.c  2010-12-14 
02:38:29 UTC (rev 33648)
@@ -29,6 +29,7 @@
 #include <limits.h>
 #include <math.h>
 #include <string.h>
+#include <ctype.h>
  
 #include "MEM_guardedalloc.h"
 
@@ -585,6 +586,77 @@
        return 1;
 }
 
+/* assigns automatic keybindings to menu items for fast access
+ * (underline key in menu) */
+static void ui_menu_block_set_keyaccels(uiBlock *block)
+{
+       uiBut *but;
+
+       unsigned int meny_key_mask= 0;
+       unsigned char menu_key;
+       const char *str_pt;
+       int pass;
+       int tot_missing= 0;
+
+       /* only do it before bounding */
+       if(block->minx != block->maxx)
+               return;
+
+       for(pass=0; pass<2; pass++) {
+               /* 2 Passes, on for first letter only, second for any letter if 
first fails
+                * fun first pass on all buttons so first word chars always get 
first priority */
+
+               for(but=block->buttons.first; but; but=but->next) {
+                       if(!ELEM4(but->type, BUT, MENU, BLOCK, PULLDOWN) || 
(but->flag & UI_HIDDEN)) {
+                               /* pass */
+                       }
+                       else if(but->menu_key=='\0') {
+                               if(but->str) {
+                                       for(str_pt= but->str; *str_pt; ) {
+                                               menu_key= tolower(*str_pt);
+                                               if((menu_key >= 'a' && menu_key 
<= 'z') && !(meny_key_mask & 1<<(menu_key-'a'))) {
+                                                       meny_key_mask |= 
1<<(menu_key-'a');
+                                                       break;
+                                               }
+
+                                               if(pass==0) {
+                                                       /* Skip to next 
delimeter on first pass (be picky) */
+                                                       while(isalpha(*str_pt))
+                                                               str_pt++;
+
+                                                       if(*str_pt)
+                                                               str_pt++;
+                                               }
+                                               else {
+                                                       /* just step over every 
char second pass and find first usable key */
+                                                       str_pt++;
+                                               }
+                                       }
+
+                                       if(*str_pt) {
+                                               but->menu_key= menu_key;
+                                       }
+                                       else {
+                                               /* run second pass */
+                                               tot_missing++;
+                                       }
+
+                                       /* if all keys have been used just 
exit, unlikely */
+                                       if(meny_key_mask == (1<<26)-1) {
+                                               return;
+                                       }
+                               }
+                       }
+               }
+
+               /* check if second pass is needed */
+               if(!tot_missing) {
+                       break;
+               }
+       }
+}
+
+
 void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
 {
        uiBut *but;
@@ -658,6 +730,7 @@
        /* handle pending stuff */
        if(block->layouts.first) uiBlockLayoutResolve(block, NULL, NULL);
        ui_block_do_align(block);
+       if((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) 
ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
        if(block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block);
        
        /* after keymaps! */

Modified: trunk/blender/source/blender/editors/interface/interface_handlers.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_handlers.c 
2010-12-14 01:19:51 UTC (rev 33647)
+++ trunk/blender/source/blender/editors/interface/interface_handlers.c 
2010-12-14 02:38:29 UTC (rev 33648)
@@ -5635,8 +5635,65 @@
 
                                                retval= WM_UI_HANDLER_BREAK;
                                        }
+                                       break;
 
+                               /* Handle keystrokes on menu items */
+                               case AKEY:
+                               case BKEY:
+                               case CKEY:
+                               case DKEY:
+                               case EKEY:
+                               case FKEY:
+                               case GKEY:
+                               case HKEY:
+                               case IKEY:
+                               case JKEY:
+                               case KKEY:
+                               case LKEY:
+                               case MKEY:
+                               case NKEY:
+                               case OKEY:
+                               case PKEY:
+                               case QKEY:
+                               case RKEY:
+                               case SKEY:
+                               case TKEY:
+                               case UKEY:
+                               case VKEY:
+                               case WKEY:
+                               case XKEY:
+                               case YKEY:
+                               case ZKEY:
+                               {
+                                       if(event->val == KM_PRESS) {
+                                               count= 0;
+                                               for(but= block->buttons.first; 
but; but= but->next) {
+
+                                                       
if(but->menu_key==event->type) {
+                                                               if(but->type == 
BUT) {
+                                                                       /* 
mainly for operator buttons */
+                                                                       
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY);
+                                                               }
+                                                               else 
if(ELEM(but->type, BLOCK, PULLDOWN)) {
+                                                                       /* open 
submenus (like right arrow key) */
+                                                                       
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
+                                                               }
+                                                               else if 
(but->type == MENU) {
+                                                                       /* 
activate menu items */
+                                                                       
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+                                                               }
+                                                               else {
+                                                                       
printf("Error, but->menu_key type: %d\n", but->type);
+                                                               }
+
+                                                               break;
+                                                       }
+                                               }
+
+                                               retval= WM_UI_HANDLER_BREAK;
+                                       }
                                        break;
+                               }
                        }
                }
                

Modified: trunk/blender/source/blender/editors/interface/interface_intern.h
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_intern.h   
2010-12-14 01:19:51 UTC (rev 33647)
+++ trunk/blender/source/blender/editors/interface/interface_intern.h   
2010-12-14 02:38:29 UTC (rev 33648)
@@ -237,9 +237,10 @@
        struct IDProperty *opproperties;
        struct PointerRNA *opptr;
        short opcontext;
-       
+       unsigned char menu_key; /* 'a'-'z', always lower case */
+
        /* Draggable data, type is WM_DRAG_... */
-       short dragtype;
+       char dragtype;
        void *dragpoin;
        struct ImBuf *imb;
        float imb_scale;

Modified: trunk/blender/source/blender/editors/interface/interface_style.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_style.c    
2010-12-14 01:19:51 UTC (rev 33647)
+++ trunk/blender/source/blender/editors/interface/interface_style.c    
2010-12-14 02:38:29 UTC (rev 33648)
@@ -136,7 +136,9 @@
 
 /* *************** draw ************************ */
 
-void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, const char *str)
+
+void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str,
+       float *r_xofs, float *r_yofs)
 {
        float height;
        int xofs=0, yofs;
@@ -171,8 +173,18 @@
                BLF_disable(fs->uifont_id, BLF_SHADOW);
        if (fs->kerning == 1)
                BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+       *r_xofs= xofs;
+       *r_yofs= yofs;
 }
 
+void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, const char *str)
+{
+       float xofs, yofs;
+       uiStyleFontDrawExt(fs, rect, str,
+               &xofs, &yofs);
+}
+
 /* drawn same as above, but at 90 degree angle */
 void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str)
 {

Modified: trunk/blender/source/blender/editors/interface/interface_widgets.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_widgets.c  
2010-12-14 01:19:51 UTC (rev 33647)
+++ trunk/blender/source/blender/editors/interface/interface_widgets.c  
2010-12-14 02:38:29 UTC (rev 33648)
@@ -35,6 +35,7 @@
 #include "BLI_math.h"
 #include "BLI_listbase.h"
 #include "BLI_rect.h"
+#include "BLI_string.h"
 
 #include "BKE_context.h"
 #include "BKE_curve.h"
@@ -961,6 +962,9 @@
 //     int transopts;
        char *cpoin = NULL;
        
+       /* for underline drawing */
+       float font_xofs, font_yofs;
+
        uiStyleFontSet(fstyle);
        
        if(but->editstr || (but->flag & UI_TEXT_LEFT))
@@ -1038,8 +1042,41 @@
        }
        
        glColor3ubv((unsigned char*)wcol->text);
-       uiStyleFontDraw(fstyle, rect, but->drawstr+but->ofs);
 
+       uiStyleFontDrawExt(fstyle, rect, but->drawstr+but->ofs, &font_xofs, 
&font_yofs);
+
+       if(but->menu_key != '\0') {
+               char fixedbuf[128];
+               char *str;
+
+               BLI_strncpy(fixedbuf, but->drawstr + but->ofs, 
sizeof(fixedbuf));
+
+               str= strchr(fixedbuf, but->menu_key-32); /* upper case */
+               if(str==NULL)
+                       str= strchr(fixedbuf, but->menu_key);
+
+               if(str) {
+                       int ul_index= -1;
+                       float ul_advance;
+
+                       ul_index= (int)(str - fixedbuf);
+
+                       if (fstyle->kerning == 1) {
+                               BLF_enable(fstyle->uifont_id, 
BLF_KERNING_DEFAULT);
+                       }
+
+                       fixedbuf[ul_index]= '\0';
+                       ul_advance= BLF_width(fstyle->uifont_id, fixedbuf);
+
+                       BLF_position(fstyle->uifont_id, rect->xmin+font_xofs + 
ul_advance, rect->ymin+font_yofs, 0.0f);
+                       BLF_draw(fstyle->uifont_id, "_", 2);
+
+                       if (fstyle->kerning == 1) {
+                               BLF_disable(fstyle->uifont_id, 
BLF_KERNING_DEFAULT);
+                       }
+               }
+       }
+
        /* part text right aligned */
        if(cpoin) {
                fstyle->align= UI_STYLE_TEXT_RIGHT;


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to