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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-01-30 15:18:08 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-01-30 15:18:08 +0300
commit8036342ea8c20ede363d5d3fe5459cc2af58a0f6 (patch)
tree1579a7a80e7d63fa655ebb4c0058b413d30b9c7e /source/blender/editors/interface
parent445bbdf75d94dbe4db25e9a81f6fed47c59acb5a (diff)
2.5: UI & Menus
* Cleaned up UI_interface.h a bit, and added some comments to organize things a bit and indicate what should be used when. * uiMenu* functions can now be used to create menus for headers too, this is done with a uiDefMenuBut, which takes a pointer to a uiMenuCreateFunc, that will then call uiMenu* functions. * Renamed uiMenuBegin/End to uiPupMenuBegin/End, as these are specific to making popup menus. Will convert the other conformation popup menu functions to use this too so we can remove some code. * Extended uiMenu functions, now there is is also: BooleanO, FloatO, BooleanR, EnumR, LevelEnumR, Separator. * Converted image window headers to use uiMenu functions, simplifies menu code further here. Did not remove the uiDefMenu functions as they are used in sequencer/view3d in some places now (will fix). * Also tried to simplify and fix bounds computation a bit better for popup menus. It tried to find out in advance what the size of the menu was but this is difficult with keymap strings in there, now uiPopupBoundsBlock can figure this out afterwards and ensure the popup is within the window bounds. Will convert some other functions to use this too.
Diffstat (limited to 'source/blender/editors/interface')
-rw-r--r--source/blender/editors/interface/interface.c193
-rw-r--r--source/blender/editors/interface/interface_draw.c3
-rw-r--r--source/blender/editors/interface/interface_handlers.c65
-rw-r--r--source/blender/editors/interface/interface_intern.h69
-rw-r--r--source/blender/editors/interface/interface_panel.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c968
6 files changed, 775 insertions, 525 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 5b8dda2f3b4..ff4e1f46145 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -207,17 +207,27 @@ void ui_window_to_region(const ARegion *ar, int *x, int *y)
/* ******************* block calc ************************* */
-void uiTextBoundsBlock(uiBlock *block, int addval)
+static void ui_block_translate(uiBlock *block, int x, int y)
{
- block->textbounds= addval;
- block->dotextbounds= 1;
+ uiBut *bt;
+
+ for(bt= block->buttons.first; bt; bt=bt->next) {
+ bt->x1 += x;
+ bt->y1 += y;
+ bt->x2 += x;
+ bt->y2 += y;
+ }
+
+ block->minx += x;
+ block->miny += y;
+ block->maxx += x;
+ block->maxy += y;
}
-/* only for pulldowns */
-static void ui_text_bounds_block(uiBlock *block)
+static void ui_text_bounds_block(uiBlock *block, float offset)
{
uiBut *bt;
- int i = 0, j, x1addval= 0, nextcol, addval= block->textbounds;
+ int i = 0, j, x1addval= offset, nextcol;
bt= block->buttons.first;
while(bt) {
@@ -239,25 +249,22 @@ static void ui_text_bounds_block(uiBlock *block)
else nextcol= 0;
bt->x1 = x1addval;
- bt->x2 = bt->x1 + i + addval;
+ bt->x2 = bt->x1 + i + block->bounds;
ui_check_but(bt); // clips text again
if(nextcol)
- x1addval+= i + addval;
+ x1addval+= i + block->bounds;
bt= bt->next;
}
}
-void uiBoundsBlock(uiBlock *block, int addval)
+void ui_bounds_block(uiBlock *block)
{
uiBut *bt;
int xof;
- if(block==NULL)
- return;
-
if(block->buttons.first==NULL) {
if(block->panel) {
block->minx= 0.0; block->maxx= block->panel->sizex;
@@ -280,10 +287,10 @@ void uiBoundsBlock(uiBlock *block, int addval)
bt= bt->next;
}
- block->minx -= addval;
- block->miny -= addval;
- block->maxx += addval;
- block->maxy += addval;
+ block->minx -= block->bounds;
+ block->miny -= block->bounds;
+ block->maxx += block->bounds;
+ block->maxy += block->bounds;
}
/* hardcoded exception... but that one is annoying with larger safety */
@@ -297,34 +304,80 @@ void uiBoundsBlock(uiBlock *block, int addval)
block->safety.ymax= block->maxy+xof;
}
-void uiBlockTranslate(uiBlock *block, int x, int y)
+static void ui_popup_bounds_block(const bContext *C, uiBlock *block)
{
- uiBut *bt;
+ int startx, starty, endx, endy, width, height;
+ int oldbounds, mx, my, xmax, ymax;
- for(bt= block->buttons.first; bt; bt=bt->next) {
- bt->x1 += x;
- bt->y1 += y;
- bt->x2 += x;
- bt->y2 += y;
+ oldbounds= block->bounds;
+
+ /* compute bounds */
+ ui_bounds_block(block);
+ mx= block->minx;
+ my= block->miny;
+
+ wm_window_get_size(CTX_wm_window(C), &xmax, &ymax);
+
+ /* first we ensure wide enough text bounds */
+ block->bounds= 50;
+ ui_text_bounds_block(block, block->minx);
+
+ /* next we recompute bounds */
+ block->bounds= oldbounds;
+ ui_bounds_block(block);
+
+ /* and we adjust the position to fit within window */
+ width= block->maxx - block->minx;
+ height= block->maxy - block->miny;
+
+ startx= mx-(0.8*(width));
+ starty= my;
+
+ 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;
}
- block->minx += x;
- block->miny += y;
- block->maxx += x;
- block->maxy += y;
+ ui_block_translate(block, startx - block->minx, starty - block->miny);
+
+ /* now recompute bounds and safety */
+ ui_bounds_block(block);
}
-void uiBlockOrigin(uiBlock *block)
+/* used for various cases */
+void uiBoundsBlock(uiBlock *block, int addval)
{
- uiBut *bt;
- int minx= 10000, miny= 10000;
+ if(block==NULL)
+ return;
+
+ block->bounds= addval;
+ block->dobounds= 1;
+}
- for(bt= block->buttons.first; bt; bt=bt->next) {
- if(bt->x1 < minx) minx= bt->x1;
- if(bt->y1 < miny) miny= bt->y1;
- }
+/* used for pulldowns */
+void uiTextBoundsBlock(uiBlock *block, int addval)
+{
+ block->bounds= addval;
+ block->dobounds= 2;
+}
- uiBlockTranslate(block, -minx, -miny);
+/* used for menu popups */
+void uiPopupBoundsBlock(uiBlock *block, int addval)
+{
+ block->bounds= addval;
+ block->dobounds= 3;
}
void ui_autofill(uiBlock *block)
@@ -485,12 +538,15 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
return found;
}
-static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
+void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
{
uiBut *but;
IDProperty *prop;
char buf[512], *butstr;
- int bounds= 0;;
+
+ /* only do it before bounding */
+ if(block->minx != block->maxx)
+ return;
for(but=block->buttons.first; but; but=but->next) {
if(but->opname) {
@@ -507,7 +563,6 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
MEM_freeN(butstr);
ui_check_but(but);
- bounds= 1;
}
}
}
@@ -535,7 +590,12 @@ void uiEndBlock(const bContext *C, uiBlock *block)
/* handle pending stuff */
if(block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block);
- if(block->dotextbounds) ui_text_bounds_block(block); /* after keymaps! */
+
+ /* after keymaps! */
+ if(block->dobounds == 1) ui_bounds_block(block);
+ else if(block->dobounds == 2) ui_text_bounds_block(block, 0.0f);
+ else if(block->dobounds == 3) ui_popup_bounds_block(C, block);
+
if(block->autofill) ui_autofill(block);
if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0);
if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block);
@@ -1782,6 +1842,7 @@ static int ui_auto_themecol(uiBut *but)
case TEX:
return TH_BUT_TEXTFIELD;
case PULLDOWN:
+ case HMENU:
case BLOCK:
case MENU:
case BUTM:
@@ -2118,6 +2179,18 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
freestr= 1;
}
+ else if(type == ROW && proptype == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int i, totitem;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+ for(i=0; i<totitem; i++)
+ if(item[i].value == (int)max)
+ str= (char*)item[i].name;
+
+ if(!str)
+ str= (char*)RNA_property_ui_name(ptr, prop);
+ }
else
str= (char*)RNA_property_ui_name(ptr, prop);
}
@@ -2579,7 +2652,7 @@ uiBut *uiDefMenuSep(uiBlock *block)
return uiDefBut(block, SEPR, 0, "", 0, y, MENU_WIDTH, MENU_SEP_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
}
-uiBut *uiDefMenuSub(uiBlock *block, uiBlockFuncFP func, char *name)
+uiBut *uiDefMenuSub(uiBlock *block, uiBlockCreateFunc func, char *name)
{
int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
return uiDefIconTextBlockBut(block, func, NULL, ICON_RIGHTARROW_THIN, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, "");
@@ -2813,24 +2886,48 @@ uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, int
return but;
}
-uiBut *uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
+uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
{
uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->block_func= func;
+ but->block_create_func= func;
ui_check_but(but);
return but;
}
-uiBut *uiDefPulldownBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
+uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
{
uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->block_func= func;
+ but->block_create_func= func;
+ ui_check_but(but);
+ return but;
+}
+
+uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, HMENU, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->menu_create_func= func;
+ ui_check_but(but);
+ return but;
+}
+
+uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, HMENU, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+
+ but->flag|= UI_ICON_LEFT;
+ but->flag|= UI_ICON_RIGHT;
+
+ but->menu_create_func= func;
ui_check_but(but);
+
return but;
}
/* Block button containing both string label and icon */
-uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
+uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
{
uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
@@ -2840,14 +2937,14 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int
but->flag|= UI_ICON_LEFT;
but->flag|= UI_ICON_RIGHT;
- but->block_func= func;
+ but->block_create_func= func;
ui_check_but(but);
return but;
}
/* Block button containing icon */
-uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip)
+uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip)
{
uiBut *but= ui_def_but(block, BLOCK, retval, "", x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
@@ -2857,7 +2954,7 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retv
but->flag|= UI_ICON_LEFT;
but->flag|= UI_ICON_RIGHT;
- but->block_func= func;
+ but->block_create_func= func;
ui_check_but(but);
return but;
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 799c1cc743c..db9f621c1fd 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -3214,7 +3214,8 @@ void ui_set_embossfunc(uiBut *but, int drawtype)
// standard builtin first:
if(but->type==LABEL || but->type==ROUNDBOX) but->embossfunc= ui_draw_nothing;
- else if(but->type==PULLDOWN) but->embossfunc= ui_draw_pulldown_round;
+ else if(ELEM(but->type, PULLDOWN, HMENU) && !(but->block->flag & UI_BLOCK_LOOP))
+ but->embossfunc= ui_draw_pulldown_round;
else if(drawtype==UI_EMBOSSM) but->embossfunc= ui_draw_minimal;
else if(drawtype==UI_EMBOSSN) but->embossfunc= ui_draw_nothing;
else if(drawtype==UI_EMBOSSP) but->embossfunc= ui_draw_pulldown_item;
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 85735a42026..61ea1b1b8e3 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -122,7 +122,7 @@ typedef struct uiHandleButtonData {
CBData *dragcbd;
/* menu open */
- uiMenuBlockHandle *menu;
+ uiPopupBlockHandle *menu;
int menuretval;
/* post activate */
@@ -598,6 +598,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
case ICONTEXTROW:
case BLOCK:
case PULLDOWN:
+ case HMENU:
case COL:
ui_apply_but_BLOCK(C, but, data);
break;
@@ -1429,13 +1430,19 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- uiBlockFuncFP func= NULL;
+ uiBlockCreateFunc func= NULL;
+ uiBlockHandleCreateFunc handlefunc= NULL;
+ uiMenuCreateFunc menufunc= NULL;
void *arg= NULL;
switch(but->type) {
case BLOCK:
case PULLDOWN:
- func= but->block_func;
+ func= but->block_create_func;
+ arg= but->poin;
+ break;
+ case HMENU:
+ menufunc= but->menu_create_func;
arg= but->poin;
break;
case MENU:
@@ -1443,15 +1450,15 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
data->value= data->origvalue;
but->editval= &data->value;
- func= ui_block_func_MENU;
+ handlefunc= ui_block_func_MENU;
arg= but;
break;
case ICONROW:
- func= ui_block_func_ICONROW;
+ handlefunc= ui_block_func_ICONROW;
arg= but;
break;
case ICONTEXTROW:
- func= ui_block_func_ICONTEXTROW;
+ handlefunc= ui_block_func_ICONTEXTROW;
arg= but;
break;
case COL:
@@ -1459,13 +1466,18 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
VECCOPY(data->vec, data->origvec);
but->editvec= data->vec;
- func= ui_block_func_COL;
+ handlefunc= ui_block_func_COL;
arg= but;
break;
}
- if(func) {
- data->menu= ui_menu_block_create(C, data->region, but, func, arg);
+ if(func || handlefunc) {
+ data->menu= ui_popup_block_create(C, data->region, but, func, handlefunc, arg);
+ if(but->block->handle)
+ data->menu->popup= but->block->handle->popup;
+ }
+ else if(menufunc) {
+ data->menu= ui_popup_menu_create(C, data->region, but, menufunc, arg);
if(but->block->handle)
data->menu->popup= but->block->handle->popup;
}
@@ -1484,7 +1496,7 @@ static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
}
if(data->menu) {
- ui_menu_block_free(C, data->menu);
+ ui_popup_block_free(C, data->menu);
data->menu= NULL;
}
}
@@ -2658,6 +2670,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
break;
case BLOCK:
case PULLDOWN:
+ case HMENU:
retval= ui_do_but_BLOCK(C, but, data, event);
break;
case BUTM:
@@ -2835,7 +2848,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
button_tooltip_timer_reset(but);
/* automatic open pulldown block timer */
- if(but->type==BLOCK || but->type==MENU || but->type==PULLDOWN || but->type==ICONTEXTROW) {
+ if(ELEM5(but->type, BLOCK, MENU, PULLDOWN, HMENU, ICONTEXTROW)) {
if(!data->autoopentimer) {
int time;
@@ -2975,7 +2988,7 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b
* value to the button value and the menu return value to ok, the
* menu return value will be picked up and the menu will close */
if(block->handle && !(block->flag & UI_BLOCK_KEEP_OPEN) && !data->cancel) {
- uiMenuBlockHandle *menu;
+ uiPopupBlockHandle *menu;
menu= block->handle;
menu->butretval= data->retval;
@@ -3184,7 +3197,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
static void ui_handle_button_closed_submenu(bContext *C, wmEvent *event, uiBut *but)
{
uiHandleButtonData *data;
- uiMenuBlockHandle *menu;
+ uiPopupBlockHandle *menu;
data= but->active;
menu= data->menu;
@@ -3226,7 +3239,7 @@ static void ui_handle_button_closed_submenu(bContext *C, wmEvent *event, uiBut *
* - only for 1 second
*/
-static void ui_mouse_motion_towards_init(uiMenuBlockHandle *menu, int mx, int my)
+static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, int mx, int my)
{
if(!menu->dotowards) {
menu->dotowards= 1;
@@ -3236,7 +3249,7 @@ static void ui_mouse_motion_towards_init(uiMenuBlockHandle *menu, int mx, int my
}
}
-static int ui_mouse_motion_towards_check(uiBlock *block, uiMenuBlockHandle *menu, int mx, int my)
+static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, int mx, int my)
{
int fac, dx, dy, domx, domy;
@@ -3290,7 +3303,7 @@ static int ui_mouse_motion_towards_check(uiBlock *block, uiMenuBlockHandle *menu
return menu->dotowards;
}
-int ui_handle_menu_event(bContext *C, wmEvent *event, uiMenuBlockHandle *menu, int topmenu)
+int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int topmenu)
{
ARegion *ar;
uiBlock *block;
@@ -3514,13 +3527,13 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiMenuBlockHandle *menu, i
return retval;
}
-static int ui_handle_menu_closed_submenu(bContext *C, wmEvent *event, uiMenuBlockHandle *menu)
+static int ui_handle_menu_closed_submenu(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
{
ARegion *ar;
uiBut *but;
uiBlock *block;
uiHandleButtonData *data;
- uiMenuBlockHandle *submenu;
+ uiPopupBlockHandle *submenu;
ar= menu->region;
block= ar->uiblocks.first;
@@ -3550,11 +3563,11 @@ static int ui_handle_menu_closed_submenu(bContext *C, wmEvent *event, uiMenuBloc
return WM_UI_HANDLER_BREAK;
}
-static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiMenuBlockHandle *menu)
+static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
{
uiBut *but;
uiHandleButtonData *data;
- uiMenuBlockHandle *submenu;
+ uiPopupBlockHandle *submenu;
int retval= WM_UI_HANDLER_CONTINUE;
/* check if we have a submenu, and handle events for it first */
@@ -3683,16 +3696,16 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata)
/* 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;
+ uiPopupBlockHandle *menu= userdata;
ui_handle_menus_recursive(C, event, menu);
/* free if done, does not free handle itself */
if(menu->menuretval) {
/* copy values, we have to free first (closes region) */
- uiMenuBlockHandle temp= *menu;
+ uiPopupBlockHandle temp= *menu;
- ui_menu_block_free(C, menu);
+ ui_popup_block_free(C, menu);
WM_event_remove_ui_handler(&CTX_wm_window(C)->handlers, ui_handler_popup, ui_handler_remove_popup, menu);
if(temp.menuretval == UI_RETURN_OK) {
@@ -3725,10 +3738,10 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
static void ui_handler_remove_popup(bContext *C, void *userdata)
{
- uiMenuBlockHandle *menu= userdata;
+ uiPopupBlockHandle *menu= userdata;
/* free menu block if window is closed for some reason */
- ui_menu_block_free(C, menu);
+ ui_popup_block_free(C, menu);
/* delayed apply callbacks */
ui_apply_but_funcs_after(C);
@@ -3740,7 +3753,7 @@ void UI_add_region_handlers(ListBase *handlers)
WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL);
}
-void UI_add_popup_handlers(ListBase *handlers, uiMenuBlockHandle *menu)
+void UI_add_popup_handlers(ListBase *handlers, uiPopupBlockHandle *menu)
{
WM_event_add_ui_handler(NULL, handlers, ui_handler_popup, ui_handler_remove_popup, menu);
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 43b7e280170..d66c6e4129e 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -121,14 +121,14 @@ struct uiBut {
float a1, a2, hsv[3]; // hsv is temp memory for hsv buttons
float aspect;
- void (*func)(struct bContext*, void *, void *);
+ uiButHandleFunc func;
void *func_arg1;
void *func_arg2;
void (*embossfunc)(int , int , float, float, float, float, float, int);
void (*sliderfunc)(int , float, float, float, float, float, float, int);
- void (*autocomplete_func)(struct bContext*, char *, void *);
+ uiButCompleteFunc autocomplete_func;
void *autofunc_arg;
uiLink *link;
@@ -143,19 +143,22 @@ struct uiBut {
short lock, win;
short iconadd, dt;
- /* IDPOIN data */
+ /* IDPOIN data */
uiIDPoinFuncFP idpoin_func;
ID **idpoin_idpp;
- /* BLOCK data */
- uiBlockFuncFP block_func;
+ /* BLOCK data */
+ uiBlockCreateFunc block_create_func;
- /* RNA */
+ /* HMENU data */
+ uiMenuCreateFunc menu_create_func;
+
+ /* RNA data */
struct PointerRNA rnapoin;
struct PropertyRNA *rnaprop;
int rnaindex;
- /* Operator */
+ /* Operator data */
const char *opname;
int opcontext;
struct IDProperty *opproperties;
@@ -188,14 +191,14 @@ struct uiBlock {
float minx, miny, maxx, maxy;
float aspect;
- void (*func)(struct bContext*, void *arg1, void *arg2);
+ uiButHandleFunc func;
void *func_arg1;
void *func_arg2;
- void (*butm_func)(struct bContext*, void *arg, int but_a2);
+ uiMenuHandleFunc butm_func;
void *butm_func_arg;
- void (*handle_func)(struct bContext*, void *arg, int event);
+ uiBlockHandleFunc handle_func;
void *handle_func_arg;
/* extra draw function for custom blocks */
@@ -215,13 +218,13 @@ struct uiBlock {
char *lockstr;
float xofs, yofs; // offset to parent button
- int textbounds, dotextbounds; // for doing delayed
+ int bounds, dobounds; // for doing delayed
int endblock; // uiEndBlock done?
rctf safety; // pulldowns, to detect outside, can differ per case how it is created
ListBase saferct; // uiSafetyRct list
- uiMenuBlockHandle *handle; // handle
+ uiPopupBlockHandle *handle; // handle
int tooltipdisabled; // to avoid tooltip after click
int handler; // for panels in other windows than buttonswin... just event code
@@ -260,18 +263,46 @@ extern void ui_autofill(uiBlock *block);
extern int ui_is_but_float(uiBut *but);
extern void ui_update_block_buts_hsv(uiBlock *block, float *hsv);
+extern void ui_bounds_block(uiBlock *block);
+
/* interface_regions.c */
-uiBlock *ui_block_func_MENU(struct bContext *C, uiMenuBlockHandle *handle, void *arg_but);
-uiBlock *ui_block_func_ICONROW(struct bContext *C, uiMenuBlockHandle *handle, void *arg_but);
-uiBlock *ui_block_func_ICONTEXTROW(struct bContext *C, uiMenuBlockHandle *handle, void *arg_but);
-uiBlock *ui_block_func_COL(struct bContext *C, uiMenuBlockHandle *handle, void *arg_but);
+
+struct uiPopupBlockHandle {
+ /* internal */
+ struct ARegion *region;
+ int towardsx, towardsy;
+ double towardstime;
+ int dotowards;
+
+ 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;
+ float retvalue;
+ float retvec[3];
+};
+
+uiBlock *ui_block_func_MENU(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+uiBlock *ui_block_func_ICONROW(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+uiBlock *ui_block_func_ICONTEXTROW(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+uiBlock *ui_block_func_COL(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
-uiMenuBlockHandle *ui_menu_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
- uiBlockFuncFP block_func, void *arg);
-void ui_menu_block_free(struct bContext *C, uiMenuBlockHandle *handle);
+typedef uiBlock* (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1);
+
+uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg);
+uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiMenuCreateFunc create_func, void *arg);
+void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
void ui_set_name_menu(uiBut *but, int value);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 0d6aa4082d3..74cd888df26 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -266,7 +266,7 @@ static void ui_scale_panel_block(uiBlock *block)
if(block->autofill) ui_autofill(block);
/* buttons min/max centered, offset calculated */
- uiBoundsBlock(block, 0);
+ ui_bounds_block(block);
if( block->maxx-block->minx > block->panel->sizex - 2*PNL_SAFETY ) {
facx= (block->panel->sizex - (2*PNL_SAFETY))/( block->maxx-block->minx );
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 90385ab2897..7fb3567033b 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -622,18 +622,18 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
uiDrawBlock(C, block);
}
-uiMenuBlockHandle *ui_menu_block_create(bContext *C, ARegion *butregion, uiBut *but, uiBlockFuncFP block_func, void *arg)
+uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg)
{
wmWindow *window= CTX_wm_window(C);
static ARegionType type;
ARegion *ar;
uiBlock *block;
uiBut *bt;
- uiMenuBlockHandle *handle;
+ uiPopupBlockHandle *handle;
uiSafetyRct *saferct;
/* create handle */
- handle= MEM_callocN(sizeof(uiMenuBlockHandle), "uiMenuBlockHandle");
+ handle= MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
/* create area region */
ar= ui_add_temporary_region(CTX_wm_screen(C));
@@ -648,7 +648,10 @@ uiMenuBlockHandle *ui_menu_block_create(bContext *C, ARegion *butregion, uiBut *
ar->regiondata= handle;
/* create ui block */
- block= block_func(C, handle, arg);
+ if(create_func)
+ block= create_func(C, handle->region, arg);
+ else
+ block= handle_create_func(C, handle, arg);
block->handle= handle;
if(!block->endblock)
@@ -656,7 +659,7 @@ uiMenuBlockHandle *ui_menu_block_create(bContext *C, ARegion *butregion, uiBut *
/* if this is being created from a button */
if(but) {
- if(ELEM(but->type, BLOCK, PULLDOWN))
+ if(ELEM3(but->type, BLOCK, PULLDOWN, HMENU))
block->xofs = -2; /* for proper alignment */
/* only used for automatic toolbox, so can set the shift flag */
@@ -712,7 +715,7 @@ uiMenuBlockHandle *ui_menu_block_create(bContext *C, ARegion *butregion, uiBut *
return handle;
}
-void ui_menu_block_free(bContext *C, uiMenuBlockHandle *handle)
+void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
{
ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
MEM_freeN(handle);
@@ -720,7 +723,7 @@ void ui_menu_block_free(bContext *C, uiMenuBlockHandle *handle)
/***************************** Menu Button ***************************/
-uiBlock *ui_block_func_MENU(bContext *C, uiMenuBlockHandle *handle, void *arg_but)
+uiBlock *ui_block_func_MENU(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
{
uiBut *but= arg_but;
uiBlock *block;
@@ -836,7 +839,7 @@ uiBlock *ui_block_func_MENU(bContext *C, uiMenuBlockHandle *handle, void *arg_bu
return block;
}
-uiBlock *ui_block_func_ICONROW(bContext *C, uiMenuBlockHandle *handle, void *arg_but)
+uiBlock *ui_block_func_ICONROW(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
{
uiBut *but= arg_but;
uiBlock *block;
@@ -857,7 +860,7 @@ uiBlock *ui_block_func_ICONROW(bContext *C, uiMenuBlockHandle *handle, void *arg
return block;
}
-uiBlock *ui_block_func_ICONTEXTROW(bContext *C, uiMenuBlockHandle *handle, void *arg_but)
+uiBlock *ui_block_func_ICONTEXTROW(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
{
uiBut *but= arg_but;
uiBlock *block;
@@ -1262,7 +1265,7 @@ void uiBlockPickerButtons(uiBlock *block, float *col, float *hsv, float *old, ch
uiBlockEndAlign(block);
}
-uiBlock *ui_block_func_COL(bContext *C, uiMenuBlockHandle *handle, void *arg_but)
+uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
{
uiBut *but= arg_but;
uiBlock *block;
@@ -1287,7 +1290,7 @@ uiBlock *ui_block_func_COL(bContext *C, uiMenuBlockHandle *handle, void *arg_but
static int pupmenu_set= 0;
-void uiPupmenuSetActive(int val)
+void uiPupMenuSetActive(int val)
{
pupmenu_set= val;
}
@@ -1322,7 +1325,7 @@ typedef struct uiPupMenuInfo {
int maxrow;
} uiPupMenuInfo;
-uiBlock *ui_block_func_PUPMENU(bContext *C, uiMenuBlockHandle *handle, void *arg_info)
+uiBlock *ui_block_func_PUPMENU(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
{
uiBlock *block;
uiPupMenuInfo *info;
@@ -1486,7 +1489,7 @@ uiBlock *ui_block_func_PUPMENU(bContext *C, uiMenuBlockHandle *handle, void *arg
return block;
}
-uiBlock *ui_block_func_PUPMENUCOL(bContext *C, uiMenuBlockHandle *handle, void *arg_info)
+uiBlock *ui_block_func_PUPMENUCOL(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
{
uiBlock *block;
uiPupMenuInfo *info;
@@ -1641,205 +1644,304 @@ 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;
-}
-
+/************************** Menu Definitions ***************************/
-/* 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);
- 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;
+/* prototype */
+static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle, void *arg_info);
- UI_add_popup_handlers(&window->handlers, menu);
- WM_event_add_mousemove(C);
+#define MAX_MENU_STR 64
- menu->popup_func= func;
- menu->popup_arg= arg;
-}
+/* type, internal */
+#define MENU_ITEM_TITLE 0
+#define MENU_ITEM_ITEM 1
+#define MENU_ITEM_OPNAME 2
+#define MENU_ITEM_OPNAME_BOOL 3
+#define MENU_ITEM_OPNAME_ENUM 4
+#define MENU_ITEM_OPNAME_FLOAT 5
+#define MENU_ITEM_RNA_BOOL 6
+#define MENU_ITEM_RNA_ENUM 7
+#define MENU_ITEM_LEVEL 8
+#define MENU_ITEM_LEVEL_OPNAME_ENUM 9
+#define MENU_ITEM_LEVEL_RNA_ENUM 10
+#define MENU_ITEM_SEPARATOR 11
-/* standard pupmenus */
+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, enumval, boolval;
+ float fltval;
+ int opcontext;
+ uiMenuHandleFunc eventfunc;
+ void *argv;
+ uiMenuCreateFunc newlevel;
+ PointerRNA rnapoin;
+
+ ListBase items;
+};
-static void operator_cb(bContext *C, void *arg, int retval)
-{
- const char *opname= arg;
+typedef struct uiMenuInfo {
+ uiMenuItem *head;
+ int mx, my, popup, slideout;
+ int startx, starty;
+} uiMenuInfo;
- if(opname && retval > 0)
- WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
-}
+/************************ Menu Definitions to uiBlocks ***********************/
-static void vconfirm(bContext *C, char *opname, char *title, char *itemfmt, va_list ap)
+const char *ui_menu_enumpropname(char *opname, const char *propname, int retval)
{
- char *s, buf[512];
+ wmOperatorType *ot= WM_operatortype_find(opname);
+ PointerRNA ptr;
+ PropertyRNA *prop;
- s= buf;
- if (title) s+= sprintf(s, "%s%%t|", title);
- vsprintf(s, itemfmt, ap);
+ if(!ot || !ot->srna)
+ return "";
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop= RNA_struct_find_property(&ptr, propname);
+
+ if(prop) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(&ptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++) {
+ if(item[i].value==retval)
+ return item[i].name;
+ }
+ }
- uiPupmenu(C, 0, operator_cb, opname, buf);
+ return "";
}
-static void confirm(bContext *C, char *opname, char *title, char *itemfmt, ...)
+/* make a menu level from enum properties */
+static void menu_item_enum_opname_menu(bContext *C, uiMenuItem *head, void *arg)
{
- va_list ap;
+ uiBut *but= arg; /* parent caller */
+ char *opname= but->func_arg1;
+ char *propname= but->func_arg2;
- va_start(ap, itemfmt);
- vconfirm(C, opname, title, itemfmt, ap);
- va_end(ap);
+ uiMenuItemsEnumO(head, opname, propname);
}
-void uiPupmenuOkee(bContext *C, char *opname, char *str, ...)
+static void menu_item_enum_rna_menu(bContext *C, uiMenuItem *head, void *arg)
{
- va_list ap;
- char titlestr[256];
-
- sprintf(titlestr, "OK? %%i%d", ICON_HELP);
+ uiBut *but= arg; /* parent caller */
+ char *propname= but->func_arg1;
- va_start(ap, str);
- vconfirm(C, opname, titlestr, str, ap);
- va_end(ap);
+ uiMenuItemsEnumR(head, &but->rnapoin, propname);
}
-void uiPupmenuSaveOver(bContext *C, char *opname, char *filename, ...)
+static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
{
- size_t len= strlen(filename);
-
- if(len==0)
- return;
+ uiBlock *block;
+ uiBut *but;
+ uiMenuInfo *info= arg_info;
+ uiMenuItem *head, *item;
+ ScrArea *sa;
+ ARegion *ar;
+ static int counter= 0;
+ int width, height, icon;
+ int startx, starty, 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);
+ uiBlockSetButmFunc(block, head->eventfunc, head->argv);
+ block->themecol= TH_MENU_ITEM;
+ block->direction= UI_DOWN;
- if(BLI_exists(filename)==0)
- operator_cb(C, opname, 1);
+ width= 50; // fixed with, uiPopupBoundsBlock will compute actual width
- if(filename[len-1]=='/' || filename[len-1]=='\\') {
- uiPupmenuError(C, "Cannot overwrite a directory");
- return;
+ for(item= head->items.first; item; item= item->next) {
+ if(0) height+= PUP_LABELH; // XXX sepr line
+ else height+= MENU_BUTTON_HEIGHT;
}
- confirm(C, opname, "Save over", filename);
-}
-
-void uiPupmenuNotice(bContext *C, char *str, ...)
-{
- va_list ap;
-
- va_start(ap, str);
- vconfirm(C, NULL, NULL, str, ap);
- va_end(ap);
-}
-
-void uiPupmenuError(bContext *C, char *str, ...)
-{
- va_list ap;
- char nfmt[256];
- char titlestr[256];
+ startx= info->mx;
+ starty= info->my-height+MENU_BUTTON_HEIGHT/2;
+
+ /* 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(item->type==MENU_ITEM_LEVEL) {
+ uiDefIconTextMenuBut(block, item->newlevel, NULL, 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_OPNAME_ENUM) {
+ but= uiDefIconTextMenuBut(block, menu_item_enum_opname_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_LEVEL_RNA_ENUM) {
+ but= uiDefIconTextMenuBut(block, menu_item_enum_rna_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->rnapoin= item->rnapoin;
+ but->func_arg1= item->propname;
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_BOOL) {
+ but= uiDefIconTextButO(block, BUTM, item->opname, head->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_boolean_set(uiButGetOperatorPtrRNA(but), item->propname, item->boolval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_ENUM) {
+ const char *name;
+ char bname[64];
- sprintf(titlestr, "Error %%i%d", ICON_ERROR);
+ name= ui_menu_enumpropname(item->opname, item->propname, item->enumval);
+ BLI_strncpy(bname, name, sizeof(bname));
+
+ but= uiDefIconTextButO(block, BUTM, item->opname, head->opcontext, item->icon, bname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_enum_set(uiButGetOperatorPtrRNA(but), item->propname, item->enumval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_FLOAT) {
+ but= uiDefIconTextButO(block, BUTM, item->opname, head->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_float_set(uiButGetOperatorPtrRNA(but), item->propname, item->fltval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME) {
+ uiDefIconTextButO(block, BUTM, item->opname, head->opcontext, item->icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_RNA_BOOL) {
+ PropertyRNA *prop= RNA_struct_find_property(&item->rnapoin, item->propname);
- sprintf(nfmt, "%s", str);
+ if(prop && RNA_property_type(&item->rnapoin, prop) == PROP_BOOLEAN) {
+ icon= (RNA_property_boolean_get(&item->rnapoin, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
+ uiDefIconTextButR(block, TOG, 0, icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &item->rnapoin, item->propname, 0, 0, 0, 0, 0, NULL);
+ }
+ else {
+ uiBlockSetButLock(block, 1, "");
+ uiDefIconTextBut(block, BUT, 0, ICON_BLANK1, item->propname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockClearButLock(block);
+ }
- va_start(ap, str);
- vconfirm(C, NULL, titlestr, nfmt, ap);
- va_end(ap);
-}
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_RNA_ENUM) {
+ PropertyRNA *prop= RNA_struct_find_property(&item->rnapoin, item->propname);
-void uiPupmenuReports(bContext *C, ReportList *reports)
-{
- Report *report;
- DynStr *ds;
- char *str;
+ if(prop && RNA_property_type(&item->rnapoin, prop) == PROP_ENUM) {
+ icon= (RNA_property_enum_get(&item->rnapoin, prop) == item->enumval)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
+ uiDefIconTextButR(block, ROW, 0, icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &item->rnapoin, item->propname, 0, 0, item->enumval, 0, 0, NULL);
+ }
+ else {
+ uiBlockSetButLock(block, 1, "");
+ uiDefIconTextBut(block, BUT, 0, ICON_BLANK1, item->propname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockClearButLock(block);
+ }
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type == MENU_ITEM_ITEM) {
+ 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;
+ }
+ else {
+ uiDefBut(block, SEPR, 0, "", x1, y1, width+16, MENU_SEPR_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+ y1 -= MENU_SEPR_HEIGHT;
+ }
+ }
- if(!reports || !reports->list.first)
- return;
- if(!CTX_wm_window(C))
- return;
+ if(info->popup) {
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_RET_1);
+ uiBlockSetDirection(block, UI_DOWN);
- ds= BLI_dynstr_new();
+ uiPopupBoundsBlock(block, 1);
+ }
+ else {
+ /* for a header menu we set the direction automatic */
+ if(!info->slideout) {
+ sa= CTX_wm_area(C);
+ ar= CTX_wm_region(C);
+
+ if(sa && sa->headertype==HEADERDOWN) {
+ if(ar && ar->regiontype == RGN_TYPE_HEADER) {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+ }
+ }
- for(report=reports->list.first; report; report=report->next) {
- if(report->type >= RPT_ERROR)
- BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message);
- else if(report->type >= RPT_WARNING)
- BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message);
+ uiTextBoundsBlock(block, 50);
}
- str= BLI_dynstr_get_cstring(ds);
- uiPupmenu(C, 0, NULL, NULL, str);
- MEM_freeN(str);
+ /* if menu slides out of other menu, override direction */
+ if(info->slideout)
+ uiBlockSetDirection(block, UI_RIGHT);
- BLI_dynstr_free(ds);
+ uiEndBlock(C, block);
+
+ return block;
}
-/* ******************* 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;
+uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
+{
+ uiPopupBlockHandle *handle;
+ uiMenuItem *head;
+ uiMenuInfo info;
- int type;
- int icon;
- char name[MAX_MENU_STR];
+ head= MEM_callocN(sizeof(uiMenuItem), "menu dummy");
+ head->opcontext= WM_OP_EXEC_REGION_WIN;
+
+ menu_func(C, head, arg);
- char *opname; /* static string */
- char *propname; /* static string */
+ memset(&info, 0, sizeof(info));
+ info.head= head;
+ info.slideout= (but && (but->block->flag & UI_BLOCK_LOOP));
- int retval;
- int opcontext;
- void (*eventfunc)(bContext *, void *, int);
- void *argv;
- void (*newlevel)(uiMenuItem *);
+ handle= ui_popup_block_create(C, butregion, but, NULL, ui_block_func_MENU_ITEM, &info);
- ListBase items;
-};
+ BLI_freelistN(&head->items);
+ MEM_freeN(head);
-typedef struct uiMenuInfo {
- uiMenuItem *head;
- int mx, my;
- int startx, starty;
-} uiMenuInfo;
+ return handle;
+}
+
+/*************************** Menu Creating API **************************/
/* internal add func */
static uiMenuItem *ui_menu_add_item(uiMenuItem *head, const char *name, int icon, int argval)
@@ -1859,22 +1961,6 @@ static uiMenuItem *ui_menu_add_item(uiMenuItem *head, const char *name, int icon
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)
{
@@ -1906,48 +1992,103 @@ void uiMenuItemO(uiMenuItem *head, char *name, int icon)
item->type = MENU_ITEM_OPNAME;
}
-/* Single operator item with property */
+/* 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->enumval= value;
item->type = MENU_ITEM_OPNAME_ENUM;
}
-/* Add all operator items with property */
+/* single operator item with property */
+void uiMenuItemFloatO(uiMenuItem *head, const char *name, char *opname, char *propname, float value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, 0, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->fltval= value;
+ item->type = MENU_ITEM_OPNAME_FLOAT;
+}
+
+/* single operator item with property */
+void uiMenuItemBooleanO(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->boolval= value;
+ item->type = MENU_ITEM_OPNAME_BOOL;
+}
+
+/* add all operator items with property */
void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname)
{
- wmOperatorType *ot;
+ wmOperatorType *ot= WM_operatortype_find(opname);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ if(!ot || !ot->srna)
+ return;
- ot= WM_operatortype_find(opname);
- if(ot) {
- PointerRNA *opptr= MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
- PropertyRNA *prop;
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop= RNA_struct_find_property(&ptr, propname);
+
+ if(prop && RNA_property_type(&ptr, prop) == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int totitem, i;
- WM_operator_properties_create(opptr, opname);
- prop= RNA_struct_find_property(opptr, propname);
+ RNA_property_enum_items(&ptr, prop, &item, &totitem);
- 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);
+ for (i=0; i<totitem; i++)
+ uiMenuItemEnumO(head, opname, propname, item[i].value);
}
}
+/* rna property toggle */
+void uiMenuItemBooleanR(uiMenuItem *head, PointerRNA *ptr, char *propname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->propname= propname; // static!
+ item->rnapoin= *ptr;
+ item->type = MENU_ITEM_RNA_BOOL;
+}
+
+void uiMenuItemEnumR(uiMenuItem *head, PointerRNA *ptr, char *propname, int value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->propname= propname; // static!
+ item->rnapoin= *ptr;
+ item->enumval= value;
+ item->type = MENU_ITEM_RNA_ENUM;
+}
+
+/* add all rna items with property */
+void uiMenuItemsEnumR(uiMenuItem *head, PointerRNA *ptr, char *propname)
+{
+ PropertyRNA *prop;
+
+ prop= RNA_struct_find_property(ptr, propname);
+
+ if(prop && RNA_property_type(ptr, prop) == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++)
+ uiMenuItemEnumR(head, ptr, propname, item[i].value);
+ }
+}
/* generic new menu level */
-void uiMenuLevel(uiMenuItem *head, const char *name, void (*newlevel)(uiMenuItem *))
+void uiMenuLevel(uiMenuItem *head, const char *name, uiMenuCreateFunc newlevel)
{
uiMenuItem *item= ui_menu_add_item(head, name, 0, 0);
@@ -1961,7 +2102,7 @@ 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;
+ item->type = MENU_ITEM_LEVEL_OPNAME_ENUM;
ot= WM_operatortype_find(opname);
if(ot)
BLI_strncpy(item->name, ot->name, MAX_MENU_STR);
@@ -1972,19 +2113,62 @@ void uiMenuLevelEnumO(uiMenuItem *head, char *opname, char *propname)
BLI_addtail(&head->items, item);
}
+/* make a new level from enum properties */
+void uiMenuLevelEnumR(uiMenuItem *head, PointerRNA *ptr, char *propname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+ PropertyRNA *prop;
+
+ item->type = MENU_ITEM_LEVEL_RNA_ENUM;
+ prop= RNA_struct_find_property(ptr, propname);
+ if(prop)
+ BLI_strncpy(item->name, RNA_property_ui_name(ptr, prop), MAX_MENU_STR);
+
+ item->rnapoin= *ptr;
+ item->propname= propname; // static!
+
+ BLI_addtail(&head->items, item);
+}
+
+/* separator */
+void uiMenuSeparator(uiMenuItem *head)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->type = MENU_ITEM_SEPARATOR;
+}
+
+/*************************** Popup Menu API **************************/
+
+/* only return handler, and set optional title */
+uiMenuItem *uiPupMenuBegin(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 the whole structure to work */
-void uiMenuEnd(bContext *C, uiMenuItem *head)
+void uiPupMenuEnd(bContext *C, uiMenuItem *head)
{
wmWindow *window= CTX_wm_window(C);
uiMenuInfo info;
- uiMenuBlockHandle *menu;
+ uiPopupBlockHandle *menu;
memset(&info, 0, sizeof(info));
+ info.popup= 1;
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= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_MENU_ITEM, &info);
menu->popup= 1;
UI_add_popup_handlers(&window->handlers, menu);
@@ -1994,239 +2178,163 @@ void uiMenuEnd(bContext *C, uiMenuItem *head)
MEM_freeN(head);
}
-/* *********** internal code for menu/toolbox system */
-
-const char *ui_menu_enumpropname(PointerRNA *opptr, const char *propname, int retval)
+/* 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)
{
- PropertyRNA *prop;
+ wmWindow *window= CTX_wm_window(C);
+ uiPupMenuInfo info;
+ uiPopupBlockHandle *menu;
- prop= RNA_struct_find_property(opptr, propname);
+ memset(&info, 0, sizeof(info));
+ info.mx= window->eventstate->x;
+ info.my= window->eventstate->y;
+ info.maxrow= maxrow;
+ info.instr= str;
- 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 "";
+ menu= ui_popup_block_create(C, NULL, 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;
}
-/* make a menu level from uiMenuItems */
-static uiBlock *menu_item_makemenu(bContext *C, uiMenuBlockHandle *handle, void *arg)
+
+/* this one only to be called with operatortype name option */
+void uiPupMenu(bContext *C, int maxrow, uiMenuHandleFunc func, void *arg, char *str, ...)
{
- 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;
+ wmWindow *window= CTX_wm_window(C);
+ uiPupMenuInfo info;
+ uiPopupBlockHandle *menu;
- 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;
+ info.mx= window->eventstate->x;
+ info.my= window->eventstate->y;
+ info.maxrow= maxrow;
+ info.instr= str;
+
+ menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PUPMENU, &info);
+ menu->popup= 1;
+
+ UI_add_popup_handlers(&window->handlers, menu);
+ WM_event_add_mousemove(C);
+
+ menu->popup_func= func;
+ menu->popup_arg= arg;
}
-/* make a menu level from enum properties */
-static uiBlock *menu_item_enum_menu(bContext *C, uiMenuBlockHandle *handle, void *arg)
+/* standard pupmenus */
+
+static void operator_cb(bContext *C, void *arg, int retval)
{
- 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;
+ const char *opname= arg;
- block= ui_block_func_MENU_ITEM(C, handle, &info);
- block->direction= UI_RIGHT;
-
- BLI_freelistN(&head->items);
- MEM_freeN(head);
-
- return block;
+ if(opname && retval > 0)
+ WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
}
-static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiMenuBlockHandle *handle, void *arg_info)
+static void vconfirm(bContext *C, char *opname, char *title, char *itemfmt, va_list ap)
{
- 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, item->icon, 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, item->icon, 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;
- }
+ char *s, buf[512];
+
+ s= buf;
+ if (title) s+= sprintf(s, "%s%%t|", title);
+ vsprintf(s, itemfmt, ap);
+
+ uiPupMenu(C, 0, operator_cb, opname, buf);
+}
+
+static void confirm(bContext *C, char *opname, char *title, char *itemfmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, itemfmt);
+ vconfirm(C, opname, title, itemfmt, ap);
+ va_end(ap);
+}
+
+void uiPupMenuOkee(bContext *C, char *opname, char *str, ...)
+{
+ va_list ap;
+ char titlestr[256];
+
+ sprintf(titlestr, "OK? %%i%d", ICON_HELP);
+
+ va_start(ap, str);
+ vconfirm(C, opname, titlestr, str, ap);
+ va_end(ap);
+}
+
+void uiPupMenuSaveOver(bContext *C, char *opname, char *filename, ...)
+{
+ size_t len= strlen(filename);
+
+ if(len==0)
+ return;
+
+ if(BLI_exists(filename)==0)
+ operator_cb(C, opname, 1);
+
+ if(filename[len-1]=='/' || filename[len-1]=='\\') {
+ uiPupMenuError(C, "Cannot overwrite a directory");
+ return;
}
-
- uiBoundsBlock(block, 1);
- uiEndBlock(C, block);
-
- return block;
+
+ confirm(C, opname, "Save over", filename);
}
+void uiPupMenuNotice(bContext *C, char *str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ vconfirm(C, NULL, NULL, str, ap);
+ va_end(ap);
+}
+
+void uiPupMenuError(bContext *C, char *str, ...)
+{
+ va_list ap;
+ char nfmt[256];
+ char titlestr[256];
+
+ sprintf(titlestr, "Error %%i%d", ICON_ERROR);
+
+ sprintf(nfmt, "%s", str);
+
+ va_start(ap, str);
+ vconfirm(C, NULL, titlestr, nfmt, ap);
+ va_end(ap);
+}
+
+void uiPupMenuReports(bContext *C, ReportList *reports)
+{
+ Report *report;
+ DynStr *ds;
+ char *str;
+
+ if(!reports || !reports->list.first)
+ return;
+ if(!CTX_wm_window(C))
+ return;
+
+ ds= BLI_dynstr_new();
+
+ for(report=reports->list.first; report; report=report->next) {
+ if(report->type >= RPT_ERROR)
+ BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message);
+ else if(report->type >= RPT_WARNING)
+ BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message);
+ }
+
+ str= BLI_dynstr_get_cstring(ds);
+ uiPupMenu(C, 0, NULL, NULL, str);
+ MEM_freeN(str);
+
+ BLI_dynstr_free(ds);
+}