[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [33648] trunk/blender/source/blender/ editors: Menu UI feature common in other widget sets:

Campbell Barton ideasman42 at gmail.com
Tue Dec 14 03:38:39 CET 2010


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;





More information about the Bf-blender-cvs mailing list