Revision: 18672
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18672
Author:   ton
Date:     2009-01-25 21:22:05 +0100 (Sun, 25 Jan 2009)

Log Message:
-----------
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

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/blenkernel/intern/screen.c
    branches/blender2.5/blender/source/blender/editors/include/UI_interface.h
    branches/blender2.5/blender/source/blender/editors/interface/interface.c
    
branches/blender2.5/blender/source/blender/editors/interface/interface_handlers.c
    
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
    branches/blender2.5/blender/source/blender/editors/mesh/mesh_ops.c
    branches/blender2.5/blender/source/blender/editors/object/object_edit.c
    branches/blender2.5/blender/source/blender/editors/object/object_intern.h
    branches/blender2.5/blender/source/blender/editors/object/object_ops.c
    branches/blender2.5/blender/source/blender/editors/screen/screen_ops.c

Modified: branches/blender2.5/blender/source/blender/blenkernel/intern/screen.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/screen.c       
2009-01-25 17:49:39 UTC (rev 18671)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/screen.c       
2009-01-25 20:22:05 UTC (rev 18672)
@@ -222,13 +222,14 @@
                
                if(art && art->free)
                        art->free(ar);
+               
+               if(ar->regiondata)
+                       printf("regiondata free error\n");
        }
        else if(ar->type && ar->type->free)
                ar->type->free(ar);
 
        if(ar) {
-               if(ar->regiondata)
-                       printf("regiondata free error\n");
                BLI_freelistN(&ar->panels);
        }
 }

Modified: 
branches/blender2.5/blender/source/blender/editors/include/UI_interface.h
===================================================================
--- branches/blender2.5/blender/source/blender/editors/include/UI_interface.h   
2009-01-25 17:49:39 UTC (rev 18671)
+++ branches/blender2.5/blender/source/blender/editors/include/UI_interface.h   
2009-01-25 20:22:05 UTC (rev 18672)
@@ -219,6 +219,23 @@
 void uiPupmenuError(struct bContext *C, char *str, ...);
 void uiPupmenuReports(struct bContext *C, struct ReportList *reports);
 
+/* Custom popup menus and toolbox */
+typedef struct uiMenuItem uiMenuItem;
+
+uiMenuItem *uiMenuBegin(const char *title);
+
+void uiMenuFunc(uiMenuItem *head, void (*eventfunc)(struct bContext *, void *, 
int), void *argv);
+void uiMenuContext(uiMenuItem *head, int opcontext);
+
+void uiMenuItemVal(uiMenuItem *head, const char *name, int icon, int argval);
+void uiMenuItemEnumO(uiMenuItem *head, char *opname, char *propname, int 
value);
+void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname);
+void uiMenuItemO(uiMenuItem *head, char *name, int icon);
+void uiMenuLevel(uiMenuItem *head, const char *name, void 
(*newlevel)(uiMenuItem *));
+void uiMenuLevelEnumO(uiMenuItem *head, char *opname, char *propname);
+
+void uiMenuEnd(struct bContext *C, struct uiMenuItem *head);
+
 /* Block */
 
 uiBlock *uiBeginBlock(const struct bContext *C, struct ARegion *region, char 
*name, short dt, short font);

Modified: 
branches/blender2.5/blender/source/blender/editors/interface/interface.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/interface/interface.c    
2009-01-25 17:49:39 UTC (rev 18671)
+++ branches/blender2.5/blender/source/blender/editors/interface/interface.c    
2009-01-25 20:22:05 UTC (rev 18672)
@@ -486,7 +486,8 @@
 
        /* XXX bounds? */
        for(but=block->buttons.first; but; but=but->next) {
-               if(but->opname) {
+               /* only hotkey for menus without properties */
+               if(but->opname && but->opptr==NULL) {
                        if(WM_key_event_operator_string(C, but->opname, 
but->opcontext, buf, sizeof(buf))) {
                                butstr= 
MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps");
                                strcpy(butstr, but->str);

Modified: 
branches/blender2.5/blender/source/blender/editors/interface/interface_handlers.c
===================================================================
--- 
branches/blender2.5/blender/source/blender/editors/interface/interface_handlers.c
   2009-01-25 17:49:39 UTC (rev 18671)
+++ 
branches/blender2.5/blender/source/blender/editors/interface/interface_handlers.c
   2009-01-25 20:22:05 UTC (rev 18672)
@@ -3340,12 +3340,12 @@
                                                but= ui_but_find_activated(ar);
                                                if(but) {
                                                        if(ELEM(event->type, 
DOWNARROWKEY, WHEELDOWNMOUSE)) {
-                                                               
if(block->direction & UI_DOWN) but= ui_but_next(but);
-                                                               else but= 
ui_but_prev(but);
+                                                               
if(block->direction & UI_TOP) but= ui_but_prev(but);
+                                                               else but= 
ui_but_next(but);
                                                        }
                                                        else {
-                                                               
if(block->direction & UI_DOWN) but= ui_but_prev(but);
-                                                               else but= 
ui_but_next(but);
+                                                               
if(block->direction & UI_TOP) but= ui_but_next(but);
+                                                               else but= 
ui_but_prev(but);
                                                        }
 
                                                        if(but)

Modified: 
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
===================================================================
--- 
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
    2009-01-25 17:49:39 UTC (rev 18671)
+++ 
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
    2009-01-25 20:22:05 UTC (rev 18672)
@@ -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 @@
        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;
+       

@@ Diff output truncated at 10240 characters. @@

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

Reply via email to