Further work on new "text search" button.

- Now allows to browse items (mouse, arrow key)
- Assigns active value
- Uses different backdrop to distinguish from popup menus
- Cleaned API for it, so it can be used nicely generic

Also added a search menu, which shows all currently working
operators: CTRL+ALT+F. (mind the looks, it needs some tweaks!)

To make a menu activating a button I've added a new event...
could use some tweaks.

Important note: the callback to pass on "old string" for text
button (bone rename) couldn't work yet, added first code for new
callback, but has to be worked on further. When bone rename gets
added it can be tested.
This commit is contained in:
2009-06-03 18:31:37 +00:00
parent 9b86975586
commit 7c3c9df2c0
10 changed files with 350 additions and 54 deletions

View File

@@ -436,31 +436,30 @@ uiBut *uiFindInlink(uiBlock *block, void *poin);
*
* uiButSetNFunc will free the argument with MEM_freeN. */
typedef struct uiSearchItems {
int maxitem, totitem, maxstrlen;
char **names;
void **pointers;
} uiSearchItems;
typedef struct uiSearchItems uiSearchItems;
typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2);
typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr);
typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
typedef void (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, char *str, uiSearchItems *items);
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
/* use inside searchfunc to add items */
int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin);
/* bfunc gets search item *poin as arg2, or if NULL the old string */
void uiButSetSearchFunc (uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc);
void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg);
void uiBlockSetButmFunc (uiBlock *block, uiMenuHandleFunc func, void *arg);
void uiBlockSetFunc (uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2);
void uiBlockSetRenameFunc(uiBlock *block, uiButHandleRenameFunc func, void *arg1);
void uiButSetFunc (uiBut *but, uiButHandleFunc func, void *arg1, void *arg2);
void uiButSetNFunc (uiBut *but, uiButHandleNFunc func, void *argN, void *arg2);
void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg);
void uiButSetSearchFunc (uiBut *but, uiButSearchFunc func, void *arg);
void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(struct bContext *C, uiBlock *block));

View File

@@ -2963,6 +2963,11 @@ void uiBlockSetFunc(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2
block->func_arg2= arg2;
}
void uiBlockSetRenameFunc(uiBlock *block, uiButHandleRenameFunc func, void *arg1)
{
}
void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)())
{
block->drawextra= func;
@@ -3083,7 +3088,7 @@ void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1,
ui_check_but(but);
}
/* arg is pointer to string/name, use callbacks below to make this work */
/* arg is pointer to string/name, use uiButSetSearchFunc() below to make this work */
uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, char *tip)
{
uiBut *but= ui_def_but(block, SEARCH_MENU, retval, "", x1, y1, x2, y2, arg, 0.0, maxlen, 0.0, 0.0, tip);
@@ -3099,10 +3104,13 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle
return but;
}
void uiButSetSearchFunc(uiBut *but, uiButSearchFunc func, void *arg)
/* arg is user value, searchfunc and handlefunc both get it as arg */
void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc)
{
but->search_func= func;
but->search_func= sfunc;
but->search_arg= arg;
uiButSetFunc(but, bfunc, arg, NULL);
}

View File

@@ -142,7 +142,8 @@ typedef struct uiAfterFunc {
uiButHandleFunc func;
void *func_arg1;
void *func_arg2;
void *func_arg3;
uiButHandleNFunc funcN;
void *func_argN;
@@ -233,6 +234,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->func= but->func;
after->func_arg1= but->func_arg1;
after->func_arg2= but->func_arg2;
after->func_arg3= but->func_arg3;
after->funcN= but->funcN;
after->func_argN= but->func_argN;
@@ -418,9 +420,10 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
/* give butfunc the original text too */
/* feature used for bone renaming, channels, etc */
if(but->func_arg2==NULL) but->func_arg2= data->origstr;
/* XXX goes via uiButHandleRenameFunc now */
// if(but->func_arg2==NULL) but->func_arg2= data->origstr;
ui_apply_but_func(C, but);
if(but->func_arg2==data->origstr) but->func_arg2= NULL;
// if(but->func_arg2==data->origstr) but->func_arg2= NULL;
data->retval= but->retval;
data->applied= 1;
@@ -888,7 +891,7 @@ static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char asc
}
}
return WM_UI_HANDLER_BREAK;
return changed;
}
void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction, int select, int jump)
@@ -1047,7 +1050,7 @@ static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directio
else { /* backspace */
if(len!=0) {
if ((but->selend - but->selsta) > 0) {
ui_textedit_delete_selection(but, data);
changed= ui_textedit_delete_selection(but, data);
}
else if(but->pos>0) {
for(x=but->pos; x<len; x++)
@@ -1175,12 +1178,16 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
if(but) {
but->editstr= 0;
but->pos= -1;
if(data->searchbox)
if(data->searchbox) {
if(data->cancel==0)
ui_searchbox_apply(but, data->searchbox);
ui_searchbox_free(C, data->searchbox);
data->searchbox= NULL;
data->searchbox= NULL;
}
but->editstr= NULL;
but->pos= -1;
}
}
@@ -1232,11 +1239,17 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
{
int mx, my, changed= 0, retval= WM_UI_HANDLER_CONTINUE;
int mx, my, changed= 0, inbox=0, retval= WM_UI_HANDLER_CONTINUE;
switch(event->type) {
case MOUSEMOVE:
if(data->searchbox)
ui_searchbox_event(data->searchbox, event);
break;
case RIGHTMOUSE:
case ESCKEY:
data->cancel= 1;
@@ -1244,6 +1257,11 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
retval= WM_UI_HANDLER_BREAK;
break;
case LEFTMOUSE: {
/* exit on LMB only on RELEASE for searchbox, to mimic other popups, and allow multiple menu levels */
if(data->searchbox)
inbox= BLI_in_rcti(&data->searchbox->winrct, event->x, event->y);
if(event->val==KM_PRESS) {
mx= event->x;
my= event->y;
@@ -1257,11 +1275,15 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
button_activate_state(C, but, BUTTON_STATE_TEXT_SELECTING);
retval= WM_UI_HANDLER_BREAK;
}
else {
else if(inbox==0) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
retval= WM_UI_HANDLER_BREAK;
}
}
else if(inbox) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
retval= WM_UI_HANDLER_BREAK;
}
break;
}
}
@@ -1291,11 +1313,21 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
retval= WM_UI_HANDLER_BREAK;
break;
case DOWNARROWKEY:
if(data->searchbox) {
ui_searchbox_event(data->searchbox, event);
break;
}
/* pass on purposedly */
case ENDKEY:
ui_textedit_move_end(but, data, 1, event->shift);
retval= WM_UI_HANDLER_BREAK;
break;
case UPARROWKEY:
if(data->searchbox) {
ui_searchbox_event(data->searchbox, event);
break;
}
/* pass on purposedly */
case HOMEKEY:
ui_textedit_move_end(but, data, 0, event->shift);
retval= WM_UI_HANDLER_BREAK;
@@ -1579,7 +1611,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w
static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
{
if(data->state == BUTTON_STATE_HIGHLIGHT) {
if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
if(ELEM4(event->type, LEFTMOUSE, PADENTER, RETKEY, EVT_BUT_OPEN) && event->val==KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
return WM_UI_HANDLER_BREAK;
}
@@ -3013,7 +3045,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
data= MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
data->window= CTX_wm_window(C);
data->region= ar;
data->interactive= but->type==BUT_CURVE?0:1; // XXX temp
if( ELEM(but->type, BUT_CURVE, SEARCH_MENU) ); // XXX curve is temp
else data->interactive= 1;
data->state = BUTTON_STATE_INIT;
/* activate button */
@@ -3115,16 +3149,35 @@ void ui_button_active_cancel(const bContext *C, uiBut *but)
/************** handle activating a button *************/
static uiBut *uit_but_find_open_event(ARegion *ar, wmEvent *event)
{
uiBlock *block;
uiBut *but;
for(block=ar->uiblocks.first; block; block=block->next) {
for(but=block->buttons.first; but; but= but->next)
if(but==event->customdata)
return but;
}
return NULL;
}
static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar)
{
uiBut *but;
if(event->type == MOUSEMOVE) {
but= ui_but_find_mouse_over(ar, event->x, event->y);
if(but)
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
else if(event->type == EVT_BUT_OPEN) {
but= uit_but_find_open_event(ar, event);
if(but) {
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
ui_do_button(C, but->block, but, event);
}
}
return WM_UI_HANDLER_CONTINUE;
}

View File

@@ -164,6 +164,7 @@ struct uiBut {
uiButHandleFunc func;
void *func_arg1;
void *func_arg2;
void *func_arg3;
uiButHandleNFunc funcN;
void *func_argN;
@@ -354,8 +355,11 @@ uiBlock *ui_block_func_COL(struct bContext *C, uiPopupBlockHandle *handle, void
struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
/* searchbox for string button */
ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but);
void ui_searchbox_event(struct ARegion *ar, struct wmEvent *event);
void ui_searchbox_apply(uiBut *but, struct ARegion *ar);
void ui_searchbox_free(struct bContext *C, struct ARegion *ar);
typedef uiBlock* (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1);
@@ -396,6 +400,8 @@ extern int ui_button_is_active(struct ARegion *ar);
/* interface_widgets.c */
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
extern void ui_draw_but(ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
/* theme color init */
struct ThemeUI;

View File

@@ -386,15 +386,121 @@ void ui_tooltip_free(bContext *C, ARegion *ar)
/************************* Creating Search Box **********************/
struct uiSearchItems {
int maxitem, totitem, maxstrlen;
char **names;
void **pointers;
};
typedef struct uiSearchboxData {
rcti bbox;
uiFontStyle fstyle;
uiSearchItems items;
int active;
} uiSearchboxData;
#define SEARCH_ITEMS 10
/* exported for use by search callbacks */
/* returns zero if nothing to add */
int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin)
{
if(items->totitem>=items->maxitem)
return 0;
BLI_strncpy(items->names[items->totitem], name, items->maxstrlen);
items->pointers[items->totitem]= poin;
items->totitem++;
return items->totitem<items->maxitem;
}
/* ar is the search box itself */
static void ui_searchbox_select(ARegion *ar, int step)
{
uiSearchboxData *data= ar->regiondata;
/* apply step */
data->active+= step;
if(data->items.totitem==0)
data->active= 0;
else if(data->active> data->items.totitem)
data->active= 1;
else if(data->active < 0)
data->active= data->items.totitem;
ED_region_tag_redraw(ar);
}
static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
{
int buth= (data->bbox.ymax-data->bbox.ymin - 2*MENU_SEPR_HEIGHT)/SEARCH_ITEMS;
*rect= data->bbox;
rect->xmin= data->bbox.xmin + 3.0f;
rect->xmax= data->bbox.xmax - 3.0f;
rect->ymax= data->bbox.ymax - MENU_SEPR_HEIGHT - itemnr*buth;
rect->ymin= rect->ymax - buth;
}
/* string validated to be of correct length (but->hardmax) */
void ui_searchbox_apply(uiBut *but, ARegion *ar)
{
uiSearchboxData *data= ar->regiondata;
but->func_arg2= NULL;
if(data->active) {
char *name= data->items.names[data->active-1];
char *cpoin= strchr(name, '|');
if(cpoin) cpoin[0]= 0;
BLI_strncpy(but->editstr, name, data->items.maxstrlen);
if(cpoin) cpoin[0]= '|';
but->func_arg2= data->items.pointers[data->active-1];
}
}
void ui_searchbox_event(ARegion *ar, wmEvent *event)
{
uiSearchboxData *data= ar->regiondata;
switch(event->type) {
case UPARROWKEY:
ui_searchbox_select(ar, -1);
break;
case DOWNARROWKEY:
ui_searchbox_select(ar, 1);
break;
case MOUSEMOVE:
if(BLI_in_rcti(&ar->winrct, event->x, event->y)) {
rcti rect;
int a;
for(a=0; a<data->items.totitem; a++) {
ui_searchbox_butrect(&rect, data, a);
if(BLI_in_rcti(&rect, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin)) {
if( data->active!= a+1) {
data->active= a+1;
ui_searchbox_select(ar, 0);
break;
}
}
}
}
break;
}
}
/* ar is the search box itself */
void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but)
{
@@ -402,7 +508,12 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but)
/* callback */
data->items.totitem= 0;
but->search_func(C, but->search_arg, but->editstr, &data->items);
data->active= 0;
if(but->search_func)
but->search_func(C, but->search_arg, but->editstr, &data->items);
/* validate selected item */
ui_searchbox_select(ar, 0);
ED_region_tag_redraw(ar);
}
@@ -411,25 +522,21 @@ static void ui_searchbox_region_draw(const bContext *C, ARegion *ar)
{
uiSearchboxData *data= ar->regiondata;
ui_draw_menu_back(U.uistyles.first, NULL, &data->bbox);
/* pixel space */
wmOrtho2(-0.01f, ar->winx-0.01f, -0.01f, ar->winy-0.01f);
ui_draw_search_back(U.uistyles.first, NULL, &data->bbox);
/* draw text */
if(data->items.totitem) {
rcti rect;
int a, buth;
int a;
/* draw items */
buth= (data->bbox.ymax-data->bbox.ymin - 2*MENU_SEPR_HEIGHT)/SEARCH_ITEMS;
rect= data->bbox;
rect.xmin= data->bbox.xmin + 3.0f;
rect.xmax= data->bbox.xmax - 3.0f;
rect.ymax= data->bbox.ymax - MENU_SEPR_HEIGHT;
rect.ymin= rect.ymax - buth;
for(a=0; a<data->items.totitem; a++) {
ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], a==0?UI_ACTIVE:0);
rect.ymax -= buth;
rect.ymin -= buth;
ui_searchbox_butrect(&rect, data, a);
ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], (a+1)==data->active?UI_ACTIVE:0);
}
}
}
@@ -533,7 +640,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
ar->winrct.xmin= x1 - MENU_SHADOW_SIDE;
ar->winrct.xmax= x2 + MENU_SHADOW_SIDE;
ar->winrct.ymin= y1 - MENU_SHADOW_BOTTOM;
ar->winrct.ymax= y2 + MENU_TOP;
ar->winrct.ymax= y2;
/* adds subwindow */
ED_region_init(C, ar);
@@ -879,8 +986,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
/* get winmat now that we actually have the subwindow */
wmSubWindowSet(window, ar->swinid);
// XXX ton, AA pixel space...
wmOrtho2(0.0, (float)ar->winrct.xmax-ar->winrct.xmin+1, 0.0, (float)ar->winrct.ymax-ar->winrct.ymin+1);
wm_subwindow_getmatrix(window, ar->swinid, block->winmat);
@@ -892,7 +997,9 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
{
ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
/* XXX ton added, chrash on load file with popup open... need investigate */
if(CTX_wm_screen(C))
ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
MEM_freeN(handle);
}

View File

@@ -1913,6 +1913,23 @@ void ui_draw_menu_back(uiStyle *style, uiBlock *block, rcti *rect)
}
void ui_draw_search_back(uiStyle *style, uiBlock *block, rcti *rect)
{
uiWidgetType *wt= widget_type(UI_WTYPE_BOX);
glEnable(GL_BLEND);
widget_softshadow(rect, 15, 5.0f, 8.0f);
glDisable(GL_BLEND);
wt->state(wt, 0);
if(block)
wt->draw(&wt->wcol, rect, block->flag, 15);
else
wt->draw(&wt->wcol, rect, 0, 15);
}
/* helper call to draw a menu item without button */
/* state: UI_ACTIVE or 0 */
void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
@@ -1932,7 +1949,10 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
/* cut string in 2 parts? */
cpoin= strchr(name, '|');
if(cpoin) *cpoin= 0;
if(cpoin) {
*cpoin= 0;
rect->xmax -= BLF_width(cpoin+1) -10;
}
glColor3ubv(wt->wcol.text);
uiStyleFontDraw(fstyle, rect, name);
@@ -1940,7 +1960,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
/* part text right aligned */
if(cpoin) {
fstyle->align= UI_STYLE_TEXT_RIGHT;
rect->xmax-=5;
rect->xmax= _rect.xmax - 5;
uiStyleFontDraw(fstyle, rect, cpoin+1);
*cpoin= '|';
}

View File

@@ -837,6 +837,11 @@ void ED_region_init(bContext *C, ARegion *ar)
ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
/* UI convention */
wmLoadIdentity();
wmOrtho2(-0.01f, ar->winx-0.01f, -0.01f, ar->winy-0.01f);
}

View File

@@ -387,6 +387,14 @@ static void scene_idpoin_handle(bContext *C, ID *id, int event)
}
}
static void operator_call_cb(struct bContext *C, void *arg1, void *arg2)
{
wmOperatorType *ot= arg2;
if(ot)
WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
}
static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
{
wmOperatorType *ot = WM_operatortype_first();
@@ -395,19 +403,19 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u
if(BLI_strcasestr(ot->name, str)) {
if(ot->poll==NULL || ot->poll((bContext *)C)) {
char name[256];
int len= strlen(ot->name);
BLI_strncpy(items->names[items->totitem], ot->name, items->maxstrlen);
/* display name for menu, can hold hotkey */
BLI_strncpy(name, ot->name, 256);
/* check for hotkey */
if(len < items->maxstrlen-6) {
if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, items->names[items->totitem]+len+1, items->maxstrlen-len-1)) {
items->names[items->totitem][len]= '|';
}
if(len < 256-6) {
if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
name[len]= '|';
}
items->totitem++;
if(items->totitem>=items->maxitem)
if(0==uiSearchItemAdd(items, name, ot))
break;
}
}
@@ -483,7 +491,7 @@ void info_header_buttons(const bContext *C, ARegion *ar)
static char search[256]= "";
uiBut *but= uiDefSearchBut(block, search, 0, ICON_PROP_ON, 256, xco+5, yco, 120, 19, "");
uiButSetSearchFunc(but, operator_search_cb, NULL);
uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb);
xco+= 125;
}

View File

@@ -373,6 +373,93 @@ static void WM_OT_debug_menu(wmOperatorType *ot)
RNA_def_int(ot->srna, "debugval", 0, -10000, 10000, "Debug Value", "", INT_MIN, INT_MAX);
}
/* ***************** Search menu ************************* */
static void operator_call_cb(struct bContext *C, void *arg1, void *arg2)
{
wmOperatorType *ot= arg2;
if(ot)
WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
}
static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
{
wmOperatorType *ot = WM_operatortype_first();
for(; ot; ot= ot->next) {
if(BLI_strcasestr(ot->name, str)) {
if(ot->poll==NULL || ot->poll((bContext *)C)) {
char name[256];
int len= strlen(ot->name);
/* display name for menu, can hold hotkey */
BLI_strncpy(name, ot->name, 256);
/* check for hotkey */
if(len < 256-6) {
if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
name[len]= '|';
}
if(0==uiSearchItemAdd(items, name, ot))
break;
}
}
}
}
static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *arg_op)
{
static char search[256]= "";
wmEvent event;
wmWindow *win= CTX_wm_window(C);
uiBlock *block;
uiBut *but;
block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1);
but= uiDefSearchBut(block, search, 0, ICON_PROP_ON, 256, 10, 10, 180, 19, "");
uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb);
uiPopupBoundsBlock(block, 0.0f, 0, -20); /* move it downwards, mouse over button */
uiEndBlock(C, block);
event= *(win->eventstate); /* XXX huh huh? make api call */
event.type= EVT_BUT_OPEN;
event.val= KM_PRESS;
event.customdata= but;
event.customdatafree= FALSE;
wm_event_add(win, &event);
return block;
}
static int wm_search_menu_exec(bContext *C, wmOperator *op)
{
return OPERATOR_FINISHED;
}
static int wm_search_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
uiPupBlock(C, wm_block_search_menu, op);
return OPERATOR_CANCELLED;
}
static void WM_OT_search_menu(wmOperatorType *ot)
{
ot->name= "Search Menu";
ot->idname= "WM_OT_search_menu";
ot->invoke= wm_search_menu_invoke;
ot->exec= wm_search_menu_exec;
ot->poll= WM_operator_winactive;
}
/* ************ window / screen operator definitions ************** */
@@ -1437,6 +1524,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_save_mainfile);
WM_operatortype_append(WM_OT_ten_timer);
WM_operatortype_append(WM_OT_debug_menu);
WM_operatortype_append(WM_OT_search_menu);
}
/* default keymap for windows and screens, only call once per WM */
@@ -1461,6 +1549,7 @@ void wm_window_keymap(wmWindowManager *wm)
/* debug/testing */
WM_keymap_verify_item(keymap, "WM_OT_ten_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_search_menu", FKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
}

View File

@@ -238,6 +238,7 @@
#define EVT_FILESELECT_EXEC 3
#define EVT_FILESELECT_CANCEL 4
#define EVT_BUT_OPEN 0x5021
#endif /* WM_EVENT_TYPES_H */