Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-12-14 05:38:29 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-12-14 05:38:29 +0300
commit35f431b3d0edda651fda97cb0156181fab07562c (patch)
tree463161e5b71e2842ff16e9baf33b925aa872e9e4 /source/blender
parent17bd906de3ba02c8d7bf848b1f61465f09fc631c (diff)
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.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface.c73
-rw-r--r--source/blender/editors/interface/interface_handlers.c57
-rw-r--r--source/blender/editors/interface/interface_intern.h5
-rw-r--r--source/blender/editors/interface/interface_style.c14
-rw-r--r--source/blender/editors/interface/interface_widgets.c39
6 files changed, 186 insertions, 4 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index ef74052f217..19e2a86f644 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -749,6 +749,8 @@ void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct Prop
/* 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);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 60928f03ea7..4e3e9786a5a 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -29,6 +29,7 @@
#include <limits.h>
#include <math.h>
#include <string.h>
+#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -585,6 +586,77 @@ int uiButActiveOnly(const bContext *C, uiBlock *block, uiBut *but)
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 @@ void uiEndBlock(const bContext *C, uiBlock *block)
/* 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! */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 85359267ffd..e15696d7e80 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -5635,8 +5635,65 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
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;
+ }
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index a7c03a6b95d..72f6e72cd5d 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -237,9 +237,10 @@ struct uiBut {
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;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index ec9ac300ca2..af0b2189a99 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -136,7 +136,9 @@ static uiFont *uifont_to_blfont(int id)
/* *************** 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,6 +173,16 @@ void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, const char *str)
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 */
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index a3a8e40abe6..319d51cdf75 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -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 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
// int transopts;
char *cpoin = NULL;
+ /* for underline drawing */
+ float font_xofs, font_yofs;
+
uiStyleFontSet(fstyle);
if(but->editstr || (but->flag & UI_TEXT_LEFT))
@@ -1038,7 +1042,40 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
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) {