2.5
authorTon Roosendaal <ton@blender.org>
Wed, 24 Dec 2008 14:52:17 +0000 (14:52 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 24 Dec 2008 14:52:17 +0000 (14:52 +0000)
Fix: popup menus were not freeing operators.
Made a new Popup menu call for this case:

uiPupmenuOperator(C, maxrow, op, propname, menustr);

It will set enum "propname" to the menu item and call operator,
register it optionally and free it. Use it in "invoke" calls.

Next: automatic menu generating for enum properties!

12 files changed:
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/object/object_edit.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/python/intern/bpy_operator.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_keymap.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/wm.h

index 29d1d653b39b6725b8a23ea662a8b09787eb01b1..6d0c12210de8b2216adbf9142de962add32572de 100644 (file)
@@ -35,6 +35,7 @@ struct ListBase;
 struct ARegion;
 struct wmWindow;
 struct wmWindowManager;
+struct wmOperator;
 struct AutoComplete;
 struct bContext;
 struct PointerRNA;
@@ -194,7 +195,10 @@ typedef struct uiMenuBlockHandle {
        int popup;
        void (*popup_func)(struct bContext *C, void *arg, int event);
        void *popup_arg;
-
+       /* for operator menus */
+       struct wmOperator *op_arg;
+       const char *propname;
+       
        /* return values */
        int butretval;
        int menuretval;
@@ -206,8 +210,9 @@ typedef uiBlock* (*uiBlockFuncFP)(struct bContext *C, struct uiMenuBlockHandle *
 typedef void (*uiPupmenuFunc)(struct bContext *C, void *arg, int event);
 
 void uiPupmenuSetActive(int val);
-void uiPupmenu(struct bContext *C, int maxrow, uiPupmenuFunc func, void *arg, char *str, ...);
 
+void uiPupmenuOperator(struct bContext *C, int maxrow, struct  wmOperator *op, const char *propname, char *str);
+void uiPupmenu(struct bContext *C, int maxrow, uiPupmenuFunc func, void *arg, char *str, ...);
 void uiPupmenuOkee(struct bContext *C, char *opname, char *str, ...);
 void uiPupmenuSaveOver(struct bContext *C, char *opname, char *filename, ...);
 void uiPupmenuNotice(struct bContext *C, char *str, ...);
index a368f488d1ae1e0b4754d88603f158def7d03d1d..d7235af14bc77390c9b7074753ca7a8d0eeccff2 100644 (file)
@@ -53,6 +53,8 @@
 #include "UI_text.h"
 #include "interface.h"
 
+#include "RNA_access.h"
+
 #include "WM_api.h"
 #include "WM_types.h"
 
@@ -214,7 +216,7 @@ static void ui_apply_but_funcs_after(bContext *C)
                        after->butm_func(C, after->butm_func_arg, after->a2);
 
                if(after->opname)
-                       WM_operator_call(C, after->opname, after->opcontext, after->opproperties);
+                       WM_operator_name_call(C, after->opname, after->opcontext, after->opproperties);
                if(after->opproperties) {
                        IDP_FreeProperty(after->opproperties);
                        MEM_freeN(after->opproperties);
@@ -3647,28 +3649,35 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata)
        return WM_UI_HANDLER_BREAK;
 }
 
+/* two types of popups, one with operator + enum, other with regular callbacks */
 static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
 {
        uiMenuBlockHandle *menu= userdata;
-       void (*popup_func)(struct bContext *C, void *arg, int event)= NULL;
-       void *popup_arg= NULL;
-       int retval= 0;
 
        ui_handle_menus_recursive(C, event, menu);
 
        /* free if done, does not free handle itself */
        if(menu->menuretval) {
-               if(menu->menuretval == UI_RETURN_OK) {
-                       popup_func= menu->popup_func;
-                       popup_arg= menu->popup_arg;
-                       retval= menu->retvalue;
-               }
-
+               /* copy values, we have to free first (closes region) */
+               uiMenuBlockHandle temp= *menu;
+               
                ui_menu_block_free(C, menu);
                WM_event_remove_ui_handler(&CTX_wm_window(C)->handlers, ui_handler_popup, ui_handler_remove_popup, menu);
 
-               if(popup_func)
-                       popup_func(C, popup_arg, retval);
+               if(temp.menuretval == UI_RETURN_OK) {
+                       if(temp.popup_func) {
+                               temp.popup_func(C, temp.op_arg, temp.retvalue);
+                       }
+                       else if(temp.op_arg) {
+                               if(temp.propname)
+                                       RNA_enum_set(temp.op_arg->ptr, temp.propname, temp.retvalue);
+                               WM_operator_call(C, temp.op_arg);
+                       }
+               }
+               /* always free operator */
+               else if(temp.op_arg)
+                       WM_operator_free(temp.op_arg);
+               
        }
        else {
                /* re-enable tooltips */
@@ -3704,4 +3713,3 @@ void UI_add_popup_handlers(ListBase *handlers, uiMenuBlockHandle *menu)
 {
        WM_event_add_ui_handler(NULL, handlers, ui_handler_popup, ui_handler_remove_popup, menu);
 }
-
index d5b49fa801d44524b55dcea7ce9d7da70368e017..fe7e236a841c2c28811a97ed602cc08a54c34bbb 100644 (file)
@@ -1629,6 +1629,33 @@ uiBlock *ui_block_func_PUPMENUCOL(bContext *C, uiMenuBlockHandle *handle, void *
        return block;
 }
 
+/* This one will set enum propname, call operator and register it, and free the operator itself, 
+   call it in op->invoke with returning OPERATOR_RUNNING_MODAL */
+/* Note: propname has to be static */
+void uiPupmenuOperator(bContext *C, int maxrow, wmOperator *op, const char *propname, char *str)
+{
+       wmWindow *window= CTX_wm_window(C);
+       uiPupMenuInfo info;
+       uiMenuBlockHandle *menu;
+       
+       memset(&info, 0, sizeof(info));
+       info.mx= window->eventstate->x;
+       info.my= window->eventstate->y;
+       info.maxrow= maxrow;
+       info.instr= str;
+       
+       menu= ui_menu_block_create(C, NULL, NULL, ui_block_func_PUPMENU, &info);
+       menu->popup= 1;
+       
+       UI_add_popup_handlers(&window->handlers, menu);
+       WM_event_add_mousemove(C);
+       
+       menu->op_arg= op;
+       menu->propname= propname;
+}
+
+
+/* this one only to be called with operatortype name option */
 void uiPupmenu(bContext *C, int maxrow, uiPupmenuFunc func, void *arg, char *str, ...)
 {
        wmWindow *window= CTX_wm_window(C);
@@ -1658,7 +1685,7 @@ static void operator_cb(bContext *C, void *arg, int retval)
        const char *opname= arg;
 
        if(opname && retval > 0)
-               WM_operator_call(C, opname, WM_OP_DEFAULT, NULL);
+               WM_operator_name_call(C, opname, WM_OP_DEFAULT, NULL);
 }
 
 static void vconfirm(bContext *C, char *opname, char *title, char *itemfmt, va_list ap)
index 7be4adcc0b8eef1759cf034ea5abb57a19171c82..6e7fed9acf7f2faf2d03fcd87e92ed5e5856e97c 100644 (file)
@@ -1512,16 +1512,6 @@ static int make_parent_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-static void makeparent_callback(bContext *C, void *arg, int event)
-{
-       wmOperator *op= (wmOperator *)arg;
-       
-       /* set the properties for the exec */
-       RNA_enum_set(op->ptr, "partype", event);
-       
-       make_parent_exec(C, op);
-}
-
 static int make_parent_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        Object *ob= CTX_data_active_object(C);
@@ -1549,7 +1539,7 @@ static int make_parent_invoke(bContext *C, wmOperator *op, wmEvent *event)
        else
                str += sprintf(str, formatstr, "Object", PAR_OBJECT);
        
-       uiPupmenu(C, 0, makeparent_callback, op, string);
+       uiPupmenuOperator(C, 0, op, "partype", string);
        
        return OPERATOR_RUNNING_MODAL;
 }
index 71637f5b1d643820b5316464fc5904c7f80b20b3..32425b59d7be7cb603dbab6b03ff8c6140132a20 100644 (file)
@@ -461,7 +461,7 @@ static void do_view3d_view_alignviewmenu(bContext *C, void *arg, int event)
 // XXX         mainqenter(PADASTERKEY, 1);
                break;
        case 6: /* Center View and Cursor to Origin */
-               WM_operator_call(C, "ED_VIEW3D_OT_viewcenter", WM_OP_REGION_WIN, NULL);
+               WM_operator_name_call(C, "ED_VIEW3D_OT_viewcenter", WM_OP_REGION_WIN, NULL);
                curs= give_cursor(scene, v3d);
                curs[0]=curs[1]=curs[2]= 0.0;
                break;
@@ -545,10 +545,10 @@ static void do_view3d_viewmenu(bContext *C, void *arg, int event)
                endlocalview(scene, sa);
                break;
        case 9: /* View All (Home) */
-               WM_operator_call(C, "ED_VIEW3D_OT_viewhome", WM_OP_REGION_WIN, NULL);
+               WM_operator_name_call(C, "ED_VIEW3D_OT_viewhome", WM_OP_REGION_WIN, NULL);
                break;
        case 11: /* View Selected */
-               WM_operator_call(C, "ED_VIEW3D_OT_viewcenter", WM_OP_REGION_WIN, NULL);
+               WM_operator_name_call(C, "ED_VIEW3D_OT_viewcenter", WM_OP_REGION_WIN, NULL);
                break;
        case 13: /* Play Back Animation */
                play_anim(0);
@@ -560,7 +560,7 @@ static void do_view3d_viewmenu(bContext *C, void *arg, int event)
                add_blockhandler(sa, VIEW3D_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
                break;
        case 17: /* Set Clipping Border */
-               WM_operator_call(C, "ED_VIEW3D_OT_clipping", WM_OP_REGION_WIN, NULL);
+               WM_operator_name_call(C, "ED_VIEW3D_OT_clipping", WM_OP_REGION_WIN, NULL);
                break;
        case 18: /* render preview */
                toggle_blockhandler(sa, VIEW3D_HANDLER_PREVIEW, 0);
@@ -5325,7 +5325,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event)
 
        switch(event) {
        case B_HOME:
-               WM_operator_call(C, "ED_VIEW3D_OT_viewhome", WM_OP_REGION_WIN, NULL);
+               WM_operator_name_call(C, "ED_VIEW3D_OT_viewhome", WM_OP_REGION_WIN, NULL);
                break;
        case B_SCENELOCK:
                if(v3d->scenelock) {
index 85badf18bb76d6dfb36ab815d29359241ac62274..0da0782c2d1c73a87066c6ae6269861ed5ce9bd7 100644 (file)
@@ -110,7 +110,7 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje
                }
        }
        
-       WM_operator_call(self->C, self->name, WM_OP_DEFAULT, properties);
+       WM_operator_name_call(self->C, self->name, WM_OP_DEFAULT, properties);
 
        if (properties) {
                IDP_FreeProperty(properties);
index 6a91e3c538bffbeaab959b9686b675dad6b2b29e..60f39e4dd9c4759cd318320d96f4a03b2e753e50 100644 (file)
@@ -114,11 +114,13 @@ int                       WM_operator_winactive   (struct bContext *C);
 void           WM_error(struct bContext *C, char *str);
 
                        /* operator api */
+void           WM_operator_free                (struct wmOperator *op);
 wmOperatorType *WM_operatortype_find(const char *idname);
 wmOperatorType *WM_operatortype_first(void);
 void           WM_operatortype_append  (void (*opfunc)(wmOperatorType*));
 
-int         WM_operator_call           (struct bContext *C, const char *opstring, int context, struct IDProperty *properties);
+int                    WM_operator_call                (struct bContext *C, struct wmOperator *op);
+int         WM_operator_name_call      (struct bContext *C, const char *opstring, int context, struct IDProperty *properties);
 
                        /* default operator callbacks for border/circle/lasso */
 int                    WM_border_select_invoke (struct bContext *C, wmOperator *op, struct wmEvent *event);
index 32d55fe62736bfecb7987be045a73df69c5dd31d..725e9cd989efd26b169fd19a367ffd4669a91fee 100644 (file)
@@ -51,7 +51,7 @@
 
 #define MAX_OP_REGISTERED      32
 
-void wm_operator_free(wmOperator *op)
+void WM_operator_free(wmOperator *op)
 {
        if(op->properties) {
                IDP_FreeProperty(op->properties);
@@ -80,7 +80,7 @@ void wm_operator_register(wmWindowManager *wm, wmOperator *op)
        while(tot>MAX_OP_REGISTERED) {
                wmOperator *opt= wm->operators.first;
                BLI_remlink(&wm->operators, opt);
-               wm_operator_free(opt);
+               WM_operator_free(opt);
                tot--;
        }
 }
@@ -144,7 +144,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
        
        while((op= wm->operators.first)) {
                BLI_remlink(&wm->operators, op);
-               wm_operator_free(op);
+               WM_operator_free(op);
        }
 
        while((km= wm->keymaps.first)) {
index d1047ca4e63edf834bae07db2f9e34c78a2e3da9..1342ebf78b9e432188280c114b630a6794fe82c3 100644 (file)
@@ -277,6 +277,22 @@ void wm_draw_update(bContext *C)
 
 /* ********************* operators ******************* */
 
+/* for running operators with frozen context (modal handlers, menus) */
+int WM_operator_call(bContext *C, wmOperator *op)
+{
+       int retval= OPERATOR_CANCELLED;
+       
+       if(op->type->exec)
+               retval= op->type->exec(C, op);
+       
+       if((retval & OPERATOR_FINISHED) && (op->type->flag & OPTYPE_REGISTER)) {
+               wm_operator_register(CTX_wm_manager(C), op);
+       }
+       else
+               WM_operator_free(op);   
+       
+       return retval;
+}
 
 static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, IDProperty *properties)
 {
@@ -284,7 +300,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, I
        int retval= OPERATOR_PASS_THROUGH;
 
        if(ot->poll==NULL || ot->poll(C)) {
-               wmOperator *op= MEM_callocN(sizeof(wmOperator), "wmOperator");
+               wmOperator *op= MEM_callocN(sizeof(wmOperator), ot->idname);    /* XXX operatortype names are static still. for debug */
 
                if(properties)
                        op->properties= IDP_CopyProperty(properties);
@@ -305,7 +321,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, I
                        wm_operator_register(wm, op);
                }
                else if(!(retval & OPERATOR_RUNNING_MODAL)) {
-                       wm_operator_free(op);
+                       WM_operator_free(op);
                }
        }
 
@@ -313,7 +329,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, I
 }
 
 /* invokes operator in context */
-int WM_operator_call(bContext *C, const char *opstring, int context, IDProperty *properties)
+int WM_operator_name_call(bContext *C, const char *opstring, int context, IDProperty *properties)
 {
        wmOperatorType *ot= WM_operatortype_find(opstring);
        wmWindow *window= CTX_wm_window(C);
@@ -404,7 +420,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
                                CTX_wm_region_set(C, region);
                        }
 
-                       wm_operator_free(handler->op);
+                       WM_operator_free(handler->op);
                }
                else if(handler->ui_remove) {
                        ScrArea *area= CTX_wm_area(C);
@@ -498,7 +514,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                                handler->op= NULL;
                        }
                        else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
-                               wm_operator_free(op);
+                               WM_operator_free(op);
                                handler->op= NULL;
                        }
                        
index dc53bff290d6dd6a40b1f3a864ea317dd6152384..22616a49af16ed398188f842c7c503a67bdb2875 100644 (file)
@@ -167,7 +167,6 @@ ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spacei
                BLI_strncpy(km->nameid, nameid, KMAP_MAX_NAME);
                km->spaceid= spaceid;
                km->regionid= regionid;
-               printf("added keymap %s %d %d\n", nameid, spaceid, regionid);
                BLI_addtail(&wm->keymaps, km);
        }
        
index 56909b425d25e253f6d08b0ab62732317e0f2249..b8b7f8fadaaa41ad6796559aa3cd93cc6297c723 100644 (file)
@@ -103,8 +103,10 @@ static void operator_callback(bContext *C, void *arg, int retval)
        
        if(op && retval > 0)
                op->type->exec(C, op);
+       
 }
 
+/* call anywhere */
 void WM_error(bContext *C, char *str)
 {
        char buf[148], testbuf[128];
@@ -115,16 +117,18 @@ void WM_error(bContext *C, char *str)
        
 }
 
+/* op->invoke */
 int WM_operator_confirm(bContext *C, wmOperator *op, wmEvent *event)
 {
        char buf[512];
        
        sprintf(buf, "OK? %%i%d%%t|%s", ICON_HELP, op->type->name);
-       uiPupmenu(C, 0, operator_callback, op, buf);
+       uiPupmenuOperator(C, 0, op, NULL, buf);
        
-       return 1;
+       return OPERATOR_RUNNING_MODAL;
 }
 
+/* op->poll */
 int WM_operator_winactive(bContext *C)
 {
        if(CTX_wm_window(C)==NULL) return 0;
@@ -177,8 +181,9 @@ static void recent_filelist(char *pup)
        }
 }
 
-static void recentfile_callback(bContext *C, void *arg, int event)
+static int recentfile_exec(bContext *C, wmOperator *op)
 {
+       int event= RNA_enum_get(op->ptr, "nr");
        
        if(event>0) {
                if (G.sce[0] && (event==1))
@@ -190,6 +195,7 @@ static void recentfile_callback(bContext *C, void *arg, int event)
                        }
                }
        }
+       return 0;
 }
 
 static int wm_recentfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
@@ -197,9 +203,9 @@ static int wm_recentfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
        char pup[2048];
        
        recent_filelist(pup);
-       uiPupmenu(C, 0, recentfile_callback, op, pup);
+       uiPupmenuOperator(C, 0, op, "nr", pup);
        
-       return 1;
+       return OPERATOR_RUNNING_MODAL;
 }
 
 static void WM_OT_open_recentfile(wmOperatorType *ot)
@@ -208,9 +214,13 @@ static void WM_OT_open_recentfile(wmOperatorType *ot)
        ot->idname= "WM_OT_open_recentfile";
        
        ot->invoke= wm_recentfile_invoke;
+       ot->exec= recentfile_exec;
        ot->poll= WM_operator_winactive;
        
        ot->flag= OPTYPE_REGISTER;
+       
+       RNA_def_property(ot->srna, "nr", PROP_ENUM, PROP_NONE);
+
 }
 
 /* *********************** */
index 139c360dfdab57974d2eb48b67459b85cee835e0..2dd4acd9be2347cfe5d3500265049c5fa77c0e62 100644 (file)
@@ -36,7 +36,6 @@ extern void wm_close_and_free_all(bContext *C, ListBase *);
 extern void wm_add_default(bContext *C);
 extern void wm_check(bContext *C);
                        
-void           wm_operator_free(wmOperator *op);
                        /* register to windowmanager for redo or macro */
 void           wm_operator_register(wmWindowManager *wm, wmOperator *op);