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:
authorTon Roosendaal <ton@blender.org>2009-01-25 23:22:05 +0300
committerTon Roosendaal <ton@blender.org>2009-01-25 23:22:05 +0300
commit3c088f3434f7900d430b01d2e210a0aa529c93bc (patch)
treec5739218b7fafa62736389813f199edffb9996f0 /source/blender/editors/interface/interface_regions.c
parentcfd93426002d20a29827503e195d8773d45bef23 (diff)
2.5
Simple toolbox-style menu system. Brecht will review it though, and/or check on way to use it for menus. I tried to avoid uiBlock and rna stuff all over. :) Quick image test: http://www.blender.org/bf/rt.jpg Examples you can read in: - editors/screen/screen_ops.c:testing123() (press F5) - editors/object/object_edit.c:object_add_primitive_invoke() (press SHIFT+A) Concept is simple: uiMenuBegin(): returns a handle. uiMenuEnd(): puts it all to work. In between you can add items like: uiMenuItemVal(): a name, icon, retval (use uiMenuFunc()) uiMenuItemO(): an operator + icon uiMenuItemEnumO(): an operator, property name, value Sublevels go easy too: uiMenuLevel(): creates item for sublevel, with function pointer. Inside that function you can use all menu calls again. Levels can go as deep you want. uiMenuLevelEnumO(): creates operator sublevel for an enum
Diffstat (limited to 'source/blender/editors/interface/interface_regions.c')
-rw-r--r--source/blender/editors/interface/interface_regions.c431
1 files changed, 431 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index f100a0f8965..d0343f55db3 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -49,6 +49,8 @@
#include "wm_subwindow.h"
#include "wm_window.h"
+#include "RNA_access.h"
+
#include "BIF_gl.h"
#include "UI_interface.h"
@@ -1796,3 +1798,432 @@ void uiPupmenuReports(bContext *C, ReportList *reports)
BLI_dynstr_free(ds);
}
+/* ******************* customize own menus, toolbox *************** */
+
+/* prototype */
+static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiMenuBlockHandle *handle, void *arg_info);
+
+#define MAX_MENU_STR 64
+
+/* type, internal */
+#define MENU_ITEM_TITLE 0
+#define MENU_ITEM_ITEM 1
+#define MENU_ITEM_OPNAME 2
+#define MENU_ITEM_OPNAME_ENUM 3
+#define MENU_ITEM_LEVEL 4
+#define MENU_ITEM_LEVEL_ENUM 5
+
+struct uiMenuItem {
+ struct uiMenuItem *next, *prev;
+
+ int type;
+ int icon;
+ char name[MAX_MENU_STR];
+
+ char *opname; /* static string */
+ char *propname; /* static string */
+
+ int retval;
+ int opcontext;
+ void (*eventfunc)(bContext *, void *, int);
+ void *argv;
+ void (*newlevel)(uiMenuItem *);
+
+ ListBase items;
+};
+
+typedef struct uiMenuInfo {
+ uiMenuItem *head;
+ int mx, my;
+ int startx, starty;
+} uiMenuInfo;
+
+/* internal add func */
+static uiMenuItem *ui_menu_add_item(uiMenuItem *head, const char *name, int icon, int argval)
+{
+ uiMenuItem *item= MEM_callocN(sizeof(uiMenuItem), "menu item");
+
+ BLI_strncpy(item->name, name, MAX_MENU_STR);
+ if(icon)
+ item->icon= icon;
+ else
+ item->icon= ICON_BLANK1;
+ item->retval= argval;
+ item->opcontext= WM_OP_EXEC_REGION_WIN;
+
+ BLI_addtail(&head->items, item);
+
+ return item;
+}
+
+
+/* only return handler, and set optional title */
+uiMenuItem *uiMenuBegin(const char *title)
+{
+ uiMenuItem *item= MEM_callocN(sizeof(uiMenuItem), "menu start");
+
+ item->type = MENU_ITEM_TITLE;
+ item->opcontext= WM_OP_EXEC_REGION_WIN;
+
+ /* NULL is no title */
+ if(title)
+ BLI_strncpy(item->name, title, MAX_MENU_STR);
+
+ return item;
+}
+
+/* set callback for regular items */
+void uiMenuFunc(uiMenuItem *head, void (*eventfunc)(bContext *, void *, int), void *argv)
+{
+ head->eventfunc= eventfunc;
+ head->argv= argv;
+}
+
+/* optionally set different context for all items in one level */
+void uiMenuContext(uiMenuItem *head, int opcontext)
+{
+ head->opcontext= opcontext;
+}
+
+
+/* regular item, with retval */
+void uiMenuItemVal(uiMenuItem *head, const char *name, int icon, int argval)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, argval);
+
+ item->type = MENU_ITEM_ITEM;
+}
+
+/* regular operator item */
+void uiMenuItemO(uiMenuItem *head, char *name, int icon)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+
+ item->opname= name; // static!
+ item->type = MENU_ITEM_OPNAME;
+}
+
+/* Single operator item with property */
+void uiMenuItemEnumO(uiMenuItem *head, char *opname, char *propname, int value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->retval= value;
+ item->type = MENU_ITEM_OPNAME_ENUM;
+}
+
+/* Add all operator items with property */
+void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname)
+{
+ wmOperatorType *ot;
+
+ ot= WM_operatortype_find(opname);
+ if(ot) {
+ PointerRNA *opptr= MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
+ PropertyRNA *prop;
+
+ WM_operator_properties_create(opptr, opname);
+ prop= RNA_struct_find_property(opptr, propname);
+
+ if(prop) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(opptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++) {
+ uiMenuItemEnumO(head, opname, propname, item[i].value);
+ }
+ }
+ WM_operator_properties_free(opptr);
+ MEM_freeN(opptr);
+ }
+}
+
+
+/* generic new menu level */
+void uiMenuLevel(uiMenuItem *head, const char *name, void (*newlevel)(uiMenuItem *))
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, 0, 0);
+
+ item->type = MENU_ITEM_LEVEL;
+ item->newlevel= newlevel;
+}
+
+/* make a new level from enum properties */
+void uiMenuLevelEnumO(uiMenuItem *head, char *opname, char *propname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+ wmOperatorType *ot;
+
+ item->type = MENU_ITEM_LEVEL_ENUM;
+ ot= WM_operatortype_find(opname);
+ if(ot)
+ BLI_strncpy(item->name, ot->name, MAX_MENU_STR);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+
+ BLI_addtail(&head->items, item);
+}
+
+/* set the whole structure to work */
+void uiMenuEnd(bContext *C, uiMenuItem *head)
+{
+ wmWindow *window= CTX_wm_window(C);
+ uiMenuInfo info;
+ uiMenuBlockHandle *menu;
+
+ memset(&info, 0, sizeof(info));
+ info.mx= window->eventstate->x;
+ info.my= window->eventstate->y;
+ info.head= head;
+
+ menu= ui_menu_block_create(C, NULL, NULL, ui_block_func_MENU_ITEM, &info);
+ menu->popup= 1;
+
+ UI_add_popup_handlers(&window->handlers, menu);
+ WM_event_add_mousemove(C);
+
+ BLI_freelistN(&head->items);
+ MEM_freeN(head);
+}
+
+/* *********** internal code for menu/toolbox system */
+
+const char *ui_menu_enumpropname(PointerRNA *opptr, const char *propname, int retval)
+{
+ PropertyRNA *prop;
+
+ prop= RNA_struct_find_property(opptr, propname);
+
+ if(prop) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(opptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++) {
+ if(item[i].value==retval)
+ return item[i].name;
+ }
+ }
+ return "";
+}
+
+/* make a menu level from uiMenuItems */
+static uiBlock *menu_item_makemenu(bContext *C, uiMenuBlockHandle *handle, void *arg)
+{
+ uiBlock *block;
+ uiMenuInfo info;
+ uiMenuItem *head;
+ void (*newlevel)(uiMenuItem *)= arg;
+
+ if(arg==NULL) return NULL;
+
+ head= MEM_callocN(sizeof(uiMenuItem), "sub level item");
+ head->opcontext= WM_OP_EXEC_REGION_WIN;
+
+ newlevel(head);
+
+ memset(&info, 0, sizeof(info));
+ info.head= head;
+
+ block= ui_block_func_MENU_ITEM(C, handle, &info);
+ block->direction= UI_RIGHT;
+
+ BLI_freelistN(&head->items);
+ MEM_freeN(head);
+
+ return block;
+}
+
+/* make a menu level from enum properties */
+static uiBlock *menu_item_enum_menu(bContext *C, uiMenuBlockHandle *handle, void *arg)
+{
+ uiBlock *block;
+ uiBut *but= arg; /* parent caller */
+ wmOperatorType *ot;
+ uiMenuInfo info;
+ uiMenuItem *head;
+
+ head= MEM_callocN(sizeof(uiMenuItem), "sub level item");
+ head->opcontext= WM_OP_EXEC_REGION_WIN;
+
+ ot= WM_operatortype_find(but->func_arg1);
+ if(ot) {
+ PointerRNA *opptr= MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
+ PropertyRNA *prop;
+
+ WM_operator_properties_create(opptr, but->func_arg1);
+ prop= RNA_struct_find_property(opptr, but->func_arg2);
+
+ if(prop) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(opptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++) {
+ uiMenuItemEnumO(head, but->func_arg1, but->func_arg2, item[i].value);
+ }
+ }
+ WM_operator_properties_free(opptr);
+ MEM_freeN(opptr);
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.head= head;
+
+ block= ui_block_func_MENU_ITEM(C, handle, &info);
+ block->direction= UI_RIGHT;
+
+ BLI_freelistN(&head->items);
+ MEM_freeN(head);
+
+ return block;
+}
+
+static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiMenuBlockHandle *handle, void *arg_info)
+{
+ uiBlock *block;
+ uiBut *but;
+ uiMenuInfo *info= arg_info;
+ uiMenuItem *head, *item;
+ static int counter= 0;
+ int width, height, xmax, ymax;
+ int startx, starty, endx, endy, x1, y1;
+ char str[16];
+
+ head= info->head;
+ height= 0;
+
+ /* block stuff first, need to know the font */
+ sprintf(str, "tb %d", counter++);
+ block= uiBeginBlock(C, handle->region, str, UI_EMBOSSP, UI_HELV);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
+ uiBlockSetButmFunc(block, head->eventfunc, head->argv);
+ block->themecol= TH_MENU_ITEM;
+ block->direction= UI_DOWN;
+
+ /* size and location, title slightly bigger for bold */
+ if(head->name[0]) {
+ width= 2*strlen(head->name)+UI_GetStringWidth(uiBlockGetCurFont(block), head->name, ui_translate_buttons());
+ }
+ else width= UI_GetStringWidth(uiBlockGetCurFont(block), "Standardtext", ui_translate_buttons());
+
+ for(item= head->items.first; item; item= item->next) {
+ xmax= UI_GetStringWidth(uiBlockGetCurFont(block), item->name, ui_translate_buttons());
+ if(xmax>width) width= xmax;
+
+ if(0) height+= PUP_LABELH; // XXX sepr line
+ else height+= MENU_BUTTON_HEIGHT;
+ }
+
+ width+= 10;
+ if (width<50) width=50;
+
+ wm_window_get_size(CTX_wm_window(C), &xmax, &ymax);
+
+ /* boundbox */
+
+ startx= info->mx-(0.8*(width));
+ starty= info->my-height+MENU_BUTTON_HEIGHT/2;
+
+ if(startx<10) {
+ startx= 10;
+ }
+ if(starty<10) {
+ starty= 10;
+ }
+
+ endx= startx+width;
+ endy= starty+height;
+
+ if(endx>xmax) {
+ endx= xmax-10;
+ startx= endx-width;
+ }
+ if(endy>ymax-20) {
+ endy= ymax-20;
+ starty= endy-height;
+ }
+
+ /* here we go! */
+ if(head->name[0]) {
+ char titlestr[256];
+ uiSetCurFont(block, UI_HELVB);
+
+ if(head->icon) {
+ width+= 20;
+ sprintf(titlestr, " %s", head->name);
+ uiDefIconTextBut(block, LABEL, 0, head->icon, titlestr, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ but= uiDefBut(block, LABEL, 0, head->name, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ but->flag= UI_TEXT_LEFT;
+ }
+ uiSetCurFont(block, UI_HELV);
+
+ //uiDefBut(block, SEPR, 0, "", startx, (short)(starty+height)-MENU_SEPR_HEIGHT, width, MENU_SEPR_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ }
+
+ x1= startx;
+ y1= starty + height - MENU_BUTTON_HEIGHT; // - MENU_SEPR_HEIGHT;
+
+ for(item= head->items.first; item; item= item->next) {
+
+ if(0) { // SEPR
+ uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, "");
+ y1 -= PUP_LABELH;
+ }
+ else if(item->type==MENU_ITEM_LEVEL) {
+ uiDefIconTextBlockBut(block, menu_item_makemenu, item->newlevel, ICON_RIGHTARROW_THIN, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_LEVEL_ENUM) {
+ but= uiDefIconTextBlockBut(block, menu_item_enum_menu, NULL, ICON_RIGHTARROW_THIN, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+ /* XXX warning, abuse of func_arg! */
+ but->poin= (char *)but;
+ but->func_arg1= item->opname;
+ but->func_arg2= item->propname;
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_ENUM) {
+ PointerRNA *opptr= MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
+ char bname[64];
+ const char *name;
+
+ WM_operator_properties_create(opptr, item->opname);
+ RNA_enum_set(opptr, item->propname, item->retval);
+ name= ui_menu_enumpropname(opptr, item->propname, item->retval);
+ BLI_strncpy(bname, name, 64);
+
+ but= uiDefIconTextBut(block, BUTM, item->retval, ICON_BLANK1, bname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+
+ but->opptr= opptr;
+ but->opname= item->opname;
+ but->opcontext= head->opcontext;
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME) {
+ uiDefIconTextButO(block, BUTM, item->opname, head->opcontext, ICON_BLANK1, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else {
+ uiDefIconTextButF(block, BUTM, B_NOP, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, 0.0, 0.0, 0, item->retval, "");
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ }
+
+ uiBoundsBlock(block, 1);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+