forked from bartvdbraak/blender
2.5
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!
This commit is contained in:
parent
9bb7babd2c
commit
3c612bc0e2
@ -35,6 +35,7 @@ struct ListBase;
|
||||
struct ARegion;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
struct wmOperator;
|
||||
struct AutoComplete;
|
||||
struct bContext;
|
||||
struct PointerRNA;
|
||||
@ -194,6 +195,9 @@ 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;
|
||||
@ -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, ...);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
/* *********************** */
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user