This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/editors/interface/interface_layout.c
Brecht Van Lommel b4d46e5ded UI: Layout Engine
* Buttons are now created first, and after that the layout is computed.
  This means the layout engine now works at button level, and makes it
  easier to write templates. Otherwise you had to store all info and
  create the buttons later.
* Added interface_templates.c as a separate file to put templates in.
  These can contain regular buttons, and can be put in a Free layout,
  which means you can specify manual coordinates, but still get nested
  correct inside other layouts.

* API was changed to allow better nesting. Previously items were added
  in the last added layout specifier, i.e. one level up in the layout
  hierarchy. This doesn't work well in always, so now when creating things
  like rows or columns it always returns a layout which you have to add
  the items in. All py scripts were updated to follow this.

* Computing the layout now goes in two passes, first estimating the
  required width/height of all nested layouts, and then in the second
  pass using the results of that to decide on the actual locations.

* Enum and array buttons now follow the direction of the layout, i.e.
  they are vertical or horizontal depending if they are in a column or row.
* Color properties now get a color picker, and only get the additional
  RGB sliders with Expand=True.
* File/directory string properties now get a button next to them for
  opening the file browse, though this is not implemented yet.
* Layout items can now be aligned, set align=True when creating a column,
  row, etc.
* Buttons now get a minimum width of one icon (avoids squashing icon
  buttons).

* Moved some more space variables into Style.
2009-05-15 11:19:59 +00:00

1709 lines
39 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contributor(s): Blender Foundation 2009.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "BIF_gl.h"
#include "ED_util.h"
#include "ED_types.h"
#include "ED_screen.h"
#include "WM_api.h"
#include "WM_types.h"
#include "interface_intern.h"
/************************ Structs and Defines *************************/
#define RNA_NO_INDEX -1
#define RNA_ENUM_VALUE -2
#define EM_SEPR_X 6
#define EM_SEPR_Y 6
/* uiLayoutCommon */
typedef struct uiLayoutCommon {
int type;
int opcontext;
int emw, emh;
uiMenuHandleFunc handlefunc;
void *argv;
uiStyle *style;
uiBlock *block;
} uiLayoutCommon;
/* Item */
typedef enum uiItemType {
ITEM_BUTTON,
ITEM_LAYOUT_ROW,
ITEM_LAYOUT_COLUMN,
ITEM_LAYOUT_COLUMN_FLOW,
ITEM_LAYOUT_ROW_FLOW,
ITEM_LAYOUT_BOX,
ITEM_LAYOUT_FREE,
ITEM_LAYOUT_SPLIT,
ITEM_LAYOUT_ROOT
#if 0
TEMPLATE_COLUMN_FLOW,
TEMPLATE_SPLIT,
TEMPLATE_BOX,
TEMPLATE_HEADER,
TEMPLATE_HEADER_ID
#endif
} uiItemType;
typedef struct uiItem {
void *next, *prev;
uiItemType type;
} uiItem;
typedef struct uiButtonItem {
uiItem item;
uiBut *but;
} uiButtonItem;
struct uiLayout {
uiItem item;
uiLayoutCommon *common;
ListBase items;
int x, y, w, h;
int space;
int align;
};
typedef struct uiLayoutItemFlow {
uiLayout litem;
int number;
int totcol;
} uiLayoutItemFlow;
typedef struct uiLayoutItemSplt {
uiLayout litem;
int number;
int lr;
} uiLayoutItemSplt;
typedef struct uiLayoutItemBx {
uiLayout litem;
} uiLayoutItemBx;
typedef struct uiLayoutItemRoot {
uiLayout litem;
} uiLayoutItemRoot;
/************************** Item ***************************/
static char *ui_item_name_add_colon(char *name, char namestr[UI_MAX_NAME_STR])
{
int len= strlen(name);
if(len != 0 && len+1 < UI_MAX_NAME_STR) {
BLI_strncpy(namestr, name, UI_MAX_NAME_STR);
namestr[len]= ':';
namestr[len+1]= '\0';
return namestr;
}
return name;
}
#define UI_FIT_EXPAND 1
static int ui_item_fit(int item, int pos, int all, int available, int spacing, int last, int flag)
{
/* available == 0 is unlimited */
if(available != 0 && all > available-spacing) {
/* contents is bigger than available space */
if(last)
return available-pos;
else
return (item*(available-spacing))/all;
}
else {
/* contents is smaller or equal to available space */
if(available != 0 && (flag & UI_FIT_EXPAND)) {
if(last)
return available-pos;
else
return (item*(available-spacing))/all;
}
else
return item;
}
}
/* variable button size in which direction? */
#define UI_ITEM_VARY_X 1
#define UI_ITEM_VARY_Y 2
static int ui_layout_vary_direction(uiLayout *layout)
{
return (layout->common->type == UI_LAYOUT_HEADER)? UI_ITEM_VARY_X: UI_ITEM_VARY_Y;
}
/* estimated size of text + icon */
static int ui_text_icon_width(uiLayout *layout, char *name, int icon)
{
int variable = ui_layout_vary_direction(layout) == UI_ITEM_VARY_X;
if(icon && strcmp(name, "") == 0)
return UI_UNIT_X; /* icon only */
else if(icon)
return (variable)? UI_GetStringWidth(name) + UI_UNIT_X: 10*UI_UNIT_X; /* icon + text */
else
return (variable)? UI_GetStringWidth(name) + UI_UNIT_X: 10*UI_UNIT_X; /* text only */
}
static void ui_item_size(uiItem *item, int *r_w, int *r_h)
{
if(item->type == ITEM_BUTTON) {
uiButtonItem *bitem= (uiButtonItem*)item;
if(r_w) *r_w= bitem->but->x2 - bitem->but->x1;
if(r_h) *r_h= bitem->but->y2 - bitem->but->y1;
}
else {
uiLayout *litem= (uiLayout*)item;
if(r_w) *r_w= litem->w;
if(r_h) *r_h= litem->h;
}
}
static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
{
if(item->type == ITEM_BUTTON) {
uiButtonItem *bitem= (uiButtonItem*)item;
if(r_x) *r_x= bitem->but->x1;
if(r_y) *r_y= bitem->but->y1;
}
else {
if(r_x) *r_x= 0;
if(r_y) *r_y= 0;
}
}
static void ui_item_position(uiItem *item, int x, int y, int w, int h)
{
if(item->type == ITEM_BUTTON) {
uiButtonItem *bitem= (uiButtonItem*)item;
bitem->but->x1= x;
bitem->but->y1= y;
bitem->but->x2= x+w;
bitem->but->y2= y+h;
}
else {
uiLayout *litem= (uiLayout*)item;
litem->x= x;
litem->y= y+h;
litem->w= w;
litem->h= h;
}
}
/******************** Special RNA Items *********************/
static int ui_layout_local_dir(uiLayout *layout)
{
switch(layout->item.type) {
case ITEM_LAYOUT_ROW:
case ITEM_LAYOUT_ROOT:
return UI_LAYOUT_HORIZONTAL;
case ITEM_LAYOUT_COLUMN:
case ITEM_LAYOUT_COLUMN_FLOW:
case ITEM_LAYOUT_SPLIT:
case ITEM_LAYOUT_FREE:
case ITEM_LAYOUT_BOX:
default:
return UI_LAYOUT_VERTICAL;
}
}
static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int align)
{
uiLayout *sub;
if(ui_layout_local_dir(test) == UI_LAYOUT_HORIZONTAL)
sub= uiLayoutRow(layout, align);
else
sub= uiLayoutColumn(layout, align);
sub->space= 0;
return sub;
}
/* create buttons for an item with an RNA array */
static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int h, int expand)
{
uiStyle *style= layout->common->style;
PropertyType type;
PropertySubType subtype;
uiLayout *sub;
int a;
/* retrieve type and subtype */
type= RNA_property_type(prop);
subtype= RNA_property_subtype(prop);
sub= ui_item_local_sublayout(layout, layout, 0);
uiBlockSetCurLayout(block, sub);
/* create label */
if(strcmp(name, "") != 0)
uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* create buttons */
if(type == PROP_BOOLEAN && len == 20) {
/* special check for layer layout */
int butw, buth, unit;
uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
unit= UI_UNIT_X*0.75;
butw= unit;
buth= unit;
uiBlockBeginAlign(block);
for(a=0; a<5; a++)
uiDefAutoButR(block, ptr, prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
for(a=0; a<5; a++)
uiDefAutoButR(block, ptr, prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
uiBlockEndAlign(block);
x += 5*butw + style->buttonspacex;
uiBlockBeginAlign(block);
for(a=0; a<5; a++)
uiDefAutoButR(block, ptr, prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
for(a=0; a<5; a++)
uiDefAutoButR(block, ptr, prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
uiBlockEndAlign(block);
}
else if(subtype == PROP_MATRIX) {
/* matrix layout */
int row, col;
uiBlockSetCurLayout(block, uiLayoutFree(layout, 1));
len= ceil(sqrt(len));
h /= len;
w /= len;
// XXX test
for(a=0; a<len; a++) {
col= a%len;
row= a/len;
uiDefAutoButR(block, ptr, prop, a, "", 0, x + w*col, y+(row-a-1)*UI_UNIT_Y, w, UI_UNIT_Y);
}
}
else if(len <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, sub, 1));
if(subtype == PROP_COLOR)
uiDefAutoButR(block, ptr, prop, -1, "", 0, 0, 0, w, UI_UNIT_Y);
if(subtype != PROP_COLOR || expand) {
/* layout for known array subtypes */
static char vectoritem[4]= {'X', 'Y', 'Z', 'W'};
static char quatitem[4]= {'W', 'X', 'Y', 'Z'};
static char coloritem[4]= {'R', 'G', 'B', 'A'};
char str[3];
for(a=0; a<len; a++) {
if(len == 4 && subtype == PROP_ROTATION)
str[0]= quatitem[a];
else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
str[0]= vectoritem[a];
else
str[0]= coloritem[a];
if(type == PROP_BOOLEAN) {
str[1]= '\0';
}
else {
str[1]= ':';
str[2]= '\0';
}
uiDefAutoButR(block, ptr, prop, a, str, 0, 0, 0, w, UI_UNIT_Y);
}
}
else if(subtype == PROP_COLOR && len == 4)
uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, w, UI_UNIT_Y);
}
else {
/* default array layout */
uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, sub, 1));
for(a=0; a<len; a++)
uiDefAutoButR(block, ptr, prop, a, "", 0, 0, 0, w, UI_UNIT_Y);
}
uiBlockSetCurLayout(block, layout);
}
static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int x, int y, int w, int h)
{
const EnumPropertyItem *item;
int a, totitem, itemw;
const char *propname;
propname= RNA_property_identifier(prop);
RNA_property_enum_items(ptr, prop, &item, &totitem);
uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
for(a=0; a<totitem; a++) {
itemw= ui_text_icon_width(block->curlayout, (char*)item[a].name, 0);
uiDefButR(block, ROW, 0, NULL, 0, 0, itemw, h, ptr, propname, -1, 0, item[a].value, -1, -1, NULL);
}
uiBlockSetCurLayout(block, layout);
}
/* create label + button for RNA property */
static void ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h)
{
uiLayout *sub;
PropertySubType subtype;
sub= uiLayoutRow(layout, 0);
uiBlockSetCurLayout(block, sub);
if(strcmp(name, "") != 0) {
w= w/2;
uiDefBut(block, LABEL, 0, name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
}
subtype= RNA_property_subtype(prop);
if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */
}
else
uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
uiBlockSetCurLayout(block, layout);
}
/********************* Button Items *************************/
/* disabled item */
static void ui_item_disabled(uiLayout *layout, char *name)
{
uiBlock *block= layout->common->block;
uiBut *but;
int w;
uiBlockSetCurLayout(block, layout);
if(!name)
name= "";
w= ui_text_icon_width(layout, name, 0);
but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
but->flag |= UI_BUT_DISABLED;
but->lock = 1;
but->lockstr = "";
}
/* operator items */
void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
{
uiBlock *block= layout->common->block;
wmOperatorType *ot= WM_operatortype_find(idname);
uiBut *but;
int w;
if(!ot) {
ui_item_disabled(layout, idname);
return;
}
if(!name)
name= ot->name;
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
/* create button */
uiBlockSetCurLayout(block, layout);
w= ui_text_icon_width(layout, name, icon);
if(icon && strcmp(name, "") != 0)
but= uiDefIconTextButO(block, BUT, ot->idname, context, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
else if(icon)
but= uiDefIconButO(block, BUT, ot->idname, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
else
but= uiDefButO(block, BUT, ot->idname, context, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
/* assign properties */
if(properties) {
PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
opptr->data= properties;
}
}
static char *ui_menu_enumpropname(char *opname, char *propname, int retval)
{
wmOperatorType *ot= WM_operatortype_find(opname);
PointerRNA ptr;
PropertyRNA *prop;
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 (char*)item[i].name;
}
}
return "";
}
void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
{
PointerRNA ptr;
WM_operator_properties_create(&ptr, opname);
RNA_enum_set(&ptr, propname, value);
if(!name)
name= ui_menu_enumpropname(opname, propname, value);
uiItemFullO(layout, name, icon, opname, ptr.data, layout->common->opcontext);
}
void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
{
wmOperatorType *ot= WM_operatortype_find(opname);
PointerRNA ptr;
PropertyRNA *prop;
if(!ot || !ot->srna) {
ui_item_disabled(layout, opname);
return;
}
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
prop= RNA_struct_find_property(&ptr, propname);
if(prop && RNA_property_type(prop) == PROP_ENUM) {
const EnumPropertyItem *item;
int totitem, i;
RNA_property_enum_items(&ptr, prop, &item, &totitem);
for(i=0; i<totitem; i++)
uiItemEnumO(layout, NULL, 0, opname, propname, item[i].value);
}
}
void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
{
PointerRNA ptr;
WM_operator_properties_create(&ptr, opname);
RNA_boolean_set(&ptr, propname, value);
uiItemFullO(layout, name, icon, opname, ptr.data, layout->common->opcontext);
}
void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
{
PointerRNA ptr;
WM_operator_properties_create(&ptr, opname);
RNA_int_set(&ptr, propname, value);
uiItemFullO(layout, name, icon, opname, ptr.data, layout->common->opcontext);
}
void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
{
PointerRNA ptr;
WM_operator_properties_create(&ptr, opname);
RNA_float_set(&ptr, propname, value);
uiItemFullO(layout, name, icon, opname, ptr.data, layout->common->opcontext);
}
void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
{
PointerRNA ptr;
WM_operator_properties_create(&ptr, opname);
RNA_string_set(&ptr, propname, value);
uiItemFullO(layout, name, icon, opname, ptr.data, layout->common->opcontext);
}
void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
{
uiItemFullO(layout, name, icon, opname, NULL, layout->common->opcontext);
}
/* RNA property items */
static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA *prop, int index, int *r_w, int *r_h)
{
PropertyType type;
PropertySubType subtype;
int len, w, h;
w= ui_text_icon_width(layout, name, icon);
h= UI_UNIT_Y;
/* arbitrary extended width by type */
type= RNA_property_type(prop);
subtype= RNA_property_subtype(prop);
len= RNA_property_array_length(prop);
if(type == PROP_STRING)
w += 10*UI_UNIT_X;
/* increase height for arrays */
if(index == RNA_NO_INDEX && len > 0) {
if(strcmp(name, "") == 0 && icon == 0)
h= 0;
if(type == PROP_BOOLEAN && len == 20)
h += 2*UI_UNIT_Y;
else if(subtype == PROP_MATRIX)
h += ceil(sqrt(len))*UI_UNIT_Y;
else
h += len*UI_UNIT_Y;
}
else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
if(type == PROP_BOOLEAN && strcmp(name, "") != 0)
w += UI_UNIT_X;
}
*r_w= w;
*r_h= h;
}
void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int expand)
{
uiBlock *block= layout->common->block;
PropertyType type;
char namestr[UI_MAX_NAME_STR];
int len, w, h;
if(!ptr->data || !prop)
return;
uiBlockSetCurLayout(block, layout);
/* retrieve info */
type= RNA_property_type(prop);
len= RNA_property_array_length(prop);
/* set name and icon */
if(!name)
name= (char*)RNA_property_ui_name(prop);
if(ELEM5(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_ENUM, PROP_POINTER))
name= ui_item_name_add_colon(name, namestr);
if(type == PROP_BOOLEAN && len)
name= ui_item_name_add_colon(name, namestr);
if(layout->common->type == UI_LAYOUT_MENU) {
if(type == PROP_BOOLEAN)
icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
else if(type == PROP_ENUM && index == RNA_ENUM_VALUE)
icon= (RNA_property_enum_get(ptr, prop) == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
}
/* get size */
ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
/* array property */
if(index == RNA_NO_INDEX && len > 0)
ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand);
/* enum item */
else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
char *identifier= (char*)RNA_property_identifier(prop);
if(icon && strcmp(name, "") != 0)
uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
else if(icon)
uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
else
uiDefButR(block, ROW, 0, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
}
/* expanded enum */
else if(type == PROP_ENUM && expand)
ui_item_enum_row(layout, block, ptr, prop, 0, 0, w, h);
/* property with separate label */
else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER)
ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
/* single button */
else
uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
}
void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand)
{
PropertyRNA *prop;
if(!ptr->data || !propname)
return;
prop= RNA_struct_find_property(ptr, propname);
if(!prop) {
ui_item_disabled(layout, propname);
printf("uiItemR: property not found: %s\n", propname);
return;
}
uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, 0, expand);
}
void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value)
{
PropertyRNA *prop;
if(!ptr->data || !propname)
return;
prop= RNA_struct_find_property(ptr, propname);
if(!prop) {
ui_item_disabled(layout, propname);
printf("uiItemEnumR: property not found: %s\n", propname);
return;
}
uiItemFullR(layout, name, icon, ptr, prop, RNA_ENUM_VALUE, value, 0);
}
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
{
PropertyRNA *prop;
prop= RNA_struct_find_property(ptr, propname);
if(!prop) {
ui_item_disabled(layout, propname);
return;
}
if(RNA_property_type(prop) == PROP_ENUM) {
const EnumPropertyItem *item;
int totitem, i;
RNA_property_enum_items(ptr, prop, &item, &totitem);
for(i=0; i<totitem; i++)
uiItemEnumR(layout, (char*)item[i].name, 0, ptr, propname, item[i].value);
}
}
/* menu item */
static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
{
MenuType *mt= (MenuType*)arg_mt;
Menu menu = {0};
menu.type= mt;
menu.layout= layout;
mt->draw(C, &menu);
}
static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN)
{
uiBlock *block= layout->common->block;
uiBut *but;
int w, h;
uiBlockSetCurLayout(block, layout);
if(layout->common->type == UI_LAYOUT_HEADER)
uiBlockSetEmboss(block, UI_EMBOSSP);
if(!name)
name= "";
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
w= ui_text_icon_width(layout, name, icon);
h= UI_UNIT_Y;
if(layout->common->type == UI_LAYOUT_HEADER) /* ugly .. */
w -= 3;
if(icon)
but= uiDefIconTextMenuBut(block, func, arg, icon, (char*)name, 0, 0, w, h, "");
else
but= uiDefMenuBut(block, func, arg, (char*)name, 0, 0, w, h, "");
if(argN) { /* ugly .. */
but->poin= (char*)but;
but->func_argN= argN;
}
if(layout->common->type == UI_LAYOUT_HEADER)
uiBlockSetEmboss(block, UI_EMBOSS);
}
void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname)
{
ARegion *ar= CTX_wm_region(C);
MenuType *mt;
if(!menuname)
return;
for(mt=ar->type->menutypes.first; mt; mt=mt->next) {
if(strcmp(menuname, mt->idname) == 0) {
if(!name)
name= mt->label;
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL);
break;
}
}
}
/* label item */
void uiItemL(uiLayout *layout, char *name, int icon)
{
uiBlock *block= layout->common->block;
uiBut *but;
int w;
uiBlockSetCurLayout(block, layout);
if(!name)
name= "";
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
w= ui_text_icon_width(layout, name, icon);
if(icon && strcmp(name, "") != 0)
but= uiDefIconTextBut(block, LABEL, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
else if(icon)
but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
else
but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
/* value item */
void uiItemV(uiLayout *layout, char *name, int icon, int argval)
{
/* label */
uiBlock *block= layout->common->block;
float *retvalue= (block->handle)? &block->handle->retvalue: NULL;
int w;
uiBlockSetCurLayout(block, layout);
if(!name)
name= "";
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
w= ui_text_icon_width(layout, name, icon);
if(icon && strcmp(name, "") != 0)
uiDefIconTextButF(block, BUTM, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
else if(icon)
uiDefIconButF(block, BUTM, 0, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
else
uiDefButF(block, BUTM, 0, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
}
/* separator item */
void uiItemS(uiLayout *layout)
{
uiBlock *block= layout->common->block;
uiBlockSetCurLayout(block, layout);
uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
}
/* level items */
void uiItemMenuF(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
{
if(!func)
return;
ui_item_menu(layout, name, icon, func, NULL, NULL);
}
typedef struct MenuItemLevel {
int opcontext;
char *opname;
char *propname;
PointerRNA rnapoin;
} MenuItemLevel;
static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
{
MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
uiLayoutContext(layout, WM_OP_EXEC_REGION_WIN);
uiItemsEnumO(layout, lvl->opname, lvl->propname);
}
void uiItemMenuEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname)
{
wmOperatorType *ot= WM_operatortype_find(opname);
MenuItemLevel *lvl;
if(!ot || !ot->srna) {
ui_item_disabled(layout, opname);
return;
}
if(!name)
name= ot->name;
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
lvl->opname= opname;
lvl->propname= propname;
lvl->opcontext= layout->common->opcontext;
ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl);
}
static void menu_item_enum_rna_menu(bContext *C, uiLayout *layout, void *arg)
{
MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
uiLayoutContext(layout, lvl->opcontext);
uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
}
void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname)
{
MenuItemLevel *lvl;
PropertyRNA *prop;
prop= RNA_struct_find_property(ptr, propname);
if(!prop) {
ui_item_disabled(layout, propname);
return;
}
if(!name)
name= (char*)RNA_property_ui_name(prop);
if(layout->common->type == UI_LAYOUT_MENU && !icon)
icon= ICON_BLANK1;
lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
lvl->rnapoin= *ptr;
lvl->propname= propname;
lvl->opcontext= layout->common->opcontext;
ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl);
}
/**************************** Layout Items ***************************/
/* single-row layout */
static void ui_litem_estimate_row(uiLayout *litem)
{
uiItem *item;
int itemw, itemh;
litem->w= 0;
litem->h= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
litem->w += itemw;
litem->h= MAX2(itemh, litem->h);
if(item->next)
litem->w += litem->space;
}
}
static void ui_litem_layout_row(uiLayout *litem)
{
uiItem *item;
int neww, itemw, itemh, x, y, w, tot= 0, totw= 0, extra=0, available=0;
x= litem->x;
y= litem->y;
w= litem->w;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
totw += itemw;
tot++;
}
if(totw == 0)
return;
/* two step to enforce minimum button with .. could be better */
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
itemw= ui_item_fit(itemw, x-litem->x, totw, w, (tot-1)*litem->space, !item->next, UI_FIT_EXPAND);
x += itemw;
if(itemw < UI_UNIT_X)
extra += UI_UNIT_X - itemw;
else
available += itemw - UI_UNIT_X;
if(item->next)
x += litem->space;
}
x= litem->x;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
neww= ui_item_fit(itemw, x-litem->x, totw, w, (tot-1)*litem->space, !item->next, UI_FIT_EXPAND);
if(neww < UI_UNIT_X) {
if(item->next)
itemw= UI_UNIT_X;
else
itemw= litem->w - (x-litem->x);
}
else
itemw= ui_item_fit(itemw, x-litem->x, totw, w-extra, (tot-1)*litem->space, !item->next, UI_FIT_EXPAND);
ui_item_position(item, x, y-itemh, itemw, itemh);
x += itemw;
if(item->next)
x += litem->space;
}
litem->w= x - litem->x;
litem->h= litem->y - y;
litem->x= x;
litem->y= y;
}
/* single-column layout */
static void ui_litem_estimate_column(uiLayout *litem)
{
uiItem *item;
int itemw, itemh;
litem->w= 0;
litem->h= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
litem->w= MAX2(litem->w, itemw);
litem->h += itemh;
if(item->next)
litem->h += litem->space;
}
}
static void ui_litem_layout_column(uiLayout *litem)
{
uiItem *item;
int itemh, x, y;
x= litem->x;
y= litem->y;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, NULL, &itemh);
y -= itemh;
ui_item_position(item, x, y, litem->w, itemh);
if(item->next)
y -= litem->space;
}
litem->h= litem->y - y;
litem->x= x;
litem->y= y;
}
/* root layout */
static void ui_litem_estimate_root(uiLayout *litem)
{
/* nothing to do */
}
static void ui_litem_layout_root(uiLayout *litem)
{
if(litem->common->type == UI_LAYOUT_HEADER)
ui_litem_layout_row(litem);
else
ui_litem_layout_column(litem);
}
/* box layout */
static void ui_litem_estimate_box(uiLayout *litem)
{
uiStyle *style= litem->common->style;
ui_litem_estimate_column(litem);
litem->w += 2*style->boxspace;
litem->h += 2*style->boxspace;
}
static void ui_litem_layout_box(uiLayout *litem)
{
uiStyle *style= litem->common->style;
int w, h;
w= litem->w;
h= litem->h;
litem->x += style->boxspace;
litem->y -= style->boxspace;
if(w != 0) litem->w -= 2*style->boxspace;
if(h != 0) litem->h -= 2*style->boxspace;
ui_litem_layout_column(litem);
litem->x -= style->boxspace;
litem->y -= style->boxspace;
if(w != 0) litem->w += 2*style->boxspace;
if(h != 0) litem->h += 2*style->boxspace;
/* roundbox around the sublayout */
uiDefBut(litem->common->block, ROUNDBOX, 0, "", litem->x, litem->y, litem->w, litem->h, NULL, 7.0, 0.0, 3, 20, "");
}
/* multi-column layout, automatically flowing to the next */
static void ui_litem_estimate_column_flow(uiLayout *litem)
{
uiStyle *style= litem->common->style;
uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
uiItem *item;
int col, x, y, emh, emy, miny, itemw, itemh, maxw=0;
int toth, totitem;
/* compute max needed width and total height */
toth= 0;
totitem= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
maxw= MAX2(maxw, itemw);
toth += itemh;
totitem++;
}
if(flow->number <= 0) {
/* auto compute number of columns, not very good */
if(maxw == 0) {
flow->totcol= 1;
return;
}
flow->totcol= MAX2(litem->common->emw/maxw, 1);
flow->totcol= MIN2(flow->totcol, totitem);
}
else
flow->totcol= flow->number;
/* compute sizes */
x= 0;
y= 0;
emy= 0;
miny= 0;
maxw= 0;
emh= toth/flow->totcol;
/* create column per column */
col= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
y -= itemh + style->buttonspacey;
miny= MIN2(miny, y);
emy -= itemh;
maxw= MAX2(itemw, maxw);
/* decide to go to next one */
if(col < flow->totcol-1 && emy <= -emh) {
x += maxw + litem->space;
maxw= 0;
y= 0;
col++;
}
}
litem->h= litem->y - miny;
}
static void ui_litem_layout_column_flow(uiLayout *litem)
{
uiStyle *style= litem->common->style;
uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
uiItem *item;
int col, x, y, w, emh, emy, miny, itemw, itemh;
int toth, totitem;
/* compute max needed width and total height */
toth= 0;
totitem= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
toth += itemh;
totitem++;
}
/* compute sizes */
x= litem->x;
y= litem->y;
emy= 0;
miny= 0;
w= litem->w;
emh= toth/flow->totcol;
/* create column per column */
col= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, NULL, &itemh);
itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, (flow->totcol-1)*style->columnspace, col == flow->totcol-1, UI_FIT_EXPAND);
y -= itemh;
emy -= itemh;
ui_item_position(item, x, y, itemw, itemh);
y -= style->buttonspacey;
miny= MIN2(miny, y);
/* decide to go to next one */
if(col < flow->totcol-1 && emy <= -emh) {
x += itemw + style->columnspace;
y= litem->y;
col++;
}
}
litem->h= litem->y - miny;
litem->x= x;
litem->y= miny;
}
/* free layout */
static void ui_litem_estimate_free(uiLayout *litem)
{
uiItem *item;
int itemx, itemy, itemw, itemh, minx, miny;
minx= 1e6;
miny= 1e6;
litem->w= 0;
litem->h= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
minx= MIN2(minx, itemx);
miny= MIN2(miny, itemy);
litem->w= MAX2(litem->w, itemx+itemw);
litem->h= MAX2(litem->h, itemy+itemh);
}
litem->w -= minx;
litem->h -= miny;
}
static void ui_litem_layout_free(uiLayout *litem)
{
uiItem *item;
float scalex=1.0f, scaley=1.0f;
int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
minx= 1e6;
miny= 1e6;
totw= 0;
toth= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
minx= MIN2(minx, itemx);
miny= MIN2(miny, itemy);
totw= MAX2(totw, itemx+itemw);
toth= MAX2(toth, itemy+itemh);
}
totw -= minx;
toth -= miny;
if(litem->w && totw > litem->w)
scalex= (float)litem->w/(float)totw;
if(litem->h && toth > litem->h)
scaley= (float)litem->h/(float)toth;
x= litem->x;
y= litem->y - scalex*toth;
for(item=litem->items.first; item; item=item->next) {
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
if(scalex != 1.0f) {
newx= itemx*scalex;
itemw= (itemx + itemw)*scalex - newx;
itemx= newx;
}
if(scaley != 1.0f) {
newy= itemy*scaley;
itemh= (itemy + itemh)*scaley - newy;
itemy= newy;
}
ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
}
litem->w= scalex*totw;
litem->h= litem->y - y;
litem->x= x + litem->w;
litem->y= y;
}
/* split layout */
static void ui_litem_estimate_split(uiLayout *litem)
{
ui_litem_estimate_row(litem);
}
static void ui_litem_layout_split(uiLayout *litem)
{
uiItem *item;
int itemh, x, y, w, tot=0, colw=0;
x= litem->x;
y= litem->y;
w= litem->w;
for(item=litem->items.first; item; item=item->next)
tot++;
if(tot == 0)
return;
colw= (litem->w - (tot-1)*litem->space)/tot;
colw= MAX2(colw, 0);
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, NULL, &itemh);
ui_item_position(item, x, y-itemh, colw, itemh);
x += colw;
if(item->next)
x += litem->space;
}
litem->w= x - litem->x;
litem->h= litem->y - y;
litem->x= x;
litem->y= y;
}
/* layout create functions */
uiLayout *uiLayoutRow(uiLayout *layout, int align)
{
uiLayout *litem;
litem= MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
litem->item.type= ITEM_LAYOUT_ROW;
litem->common= layout->common;
litem->align= align;
litem->space= (align)? 0: layout->common->style->buttonspacex;
BLI_addtail(&layout->items, litem);
return litem;
}
uiLayout *uiLayoutColumn(uiLayout *layout, int align)
{
uiLayout *litem;
litem= MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
litem->item.type= ITEM_LAYOUT_COLUMN;
litem->common= layout->common;
litem->align= align;
litem->space= (litem->align)? 0: layout->common->style->buttonspacey;
BLI_addtail(&layout->items, litem);
return litem;
}
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
{
uiLayoutItemFlow *flow;
flow= MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
flow->litem.item.type= ITEM_LAYOUT_COLUMN_FLOW;
flow->litem.common= layout->common;
flow->litem.align= align;
flow->litem.space= (flow->litem.align)? 0: layout->common->style->columnspace;
flow->number= number;
BLI_addtail(&layout->items, flow);
return &flow->litem;
}
uiLayout *uiLayoutBox(uiLayout *layout)
{
uiLayoutItemBx *box;
box= MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
box->litem.item.type= ITEM_LAYOUT_BOX;
box->litem.common= layout->common;
box->litem.space= layout->common->style->columnspace;
BLI_addtail(&layout->items, box);
return &box->litem;
}
uiLayout *uiLayoutFree(uiLayout *layout, int align)
{
uiLayout *litem;
litem= MEM_callocN(sizeof(uiLayout), "uiLayoutFree");
litem->item.type= ITEM_LAYOUT_FREE;
litem->common= layout->common;
litem->align= align;
BLI_addtail(&layout->items, litem);
return litem;
}
uiLayout *uiLayoutSplit(uiLayout *layout)
{
uiLayout *litem;
litem= uiLayoutRow(layout, 0);
litem->item.type = ITEM_LAYOUT_SPLIT;
litem->common= layout->common;
litem->space= layout->common->style->columnspace;
return litem;
}
/********************** Layout *******************/
static void ui_item_estimate(uiItem *item)
{
uiItem *subitem;
if(item->type != ITEM_BUTTON) {
uiLayout *litem= (uiLayout*)item;
for(subitem=litem->items.first; subitem; subitem=subitem->next)
ui_item_estimate(subitem);
switch(litem->item.type) {
case ITEM_LAYOUT_COLUMN:
ui_litem_estimate_column(litem);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_estimate_column_flow(litem);
break;
case ITEM_LAYOUT_ROW:
ui_litem_estimate_row(litem);
break;
case ITEM_LAYOUT_BOX:
ui_litem_estimate_box(litem);
break;
case ITEM_LAYOUT_ROOT:
ui_litem_estimate_root(litem);
break;
case ITEM_LAYOUT_FREE:
ui_litem_estimate_free(litem);
break;
case ITEM_LAYOUT_SPLIT:
ui_litem_estimate_split(litem);
break;
default:
break;
}
}
}
static void ui_item_align(uiLayout *litem, int nr)
{
uiItem *item;
for(item=litem->items.first; item; item=item->next) {
if(item->type == ITEM_BUTTON)
((uiButtonItem*)item)->but->alignnr= nr;
else
ui_item_align((uiLayout*)item, nr);
}
}
static void ui_item_layout(uiItem *item, int align)
{
uiItem *subitem;
if(item->type != ITEM_BUTTON) {
uiLayout *litem= (uiLayout*)item;
if(litem->align && !align)
ui_item_align(litem, ++litem->common->block->alignnr);
switch(litem->item.type) {
case ITEM_LAYOUT_COLUMN:
ui_litem_layout_column(litem);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_layout_column_flow(litem);
break;
case ITEM_LAYOUT_ROW:
ui_litem_layout_row(litem);
break;
case ITEM_LAYOUT_BOX:
ui_litem_layout_box(litem);
break;
case ITEM_LAYOUT_ROOT:
ui_litem_layout_root(litem);
break;
case ITEM_LAYOUT_FREE:
ui_litem_layout_free(litem);
break;
case ITEM_LAYOUT_SPLIT:
ui_litem_layout_split(litem);
break;
default:
break;
}
for(subitem=litem->items.first; subitem; subitem=subitem->next)
ui_item_layout(subitem, litem->align || align);
}
}
static void ui_layout_items(const bContext *C, uiBlock *block, uiLayout *layout)
{
ui_item_estimate(&layout->item);
ui_item_layout(&layout->item, 0);
}
static void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
{
if(layout->common->handlefunc)
uiBlockSetButmFunc(block, layout->common->handlefunc, layout->common->argv);
ui_layout_items(C, block, layout);
if(x) *x= layout->x;
if(y) *y= layout->y;
}
static void ui_layout_free(uiLayout *layout)
{
uiItem *item, *next;
for(item=layout->items.first; item; item=next) {
next= item->next;
if(item->type == ITEM_BUTTON)
MEM_freeN(item);
else
ui_layout_free((uiLayout*)item);
}
MEM_freeN(layout);
}
uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, uiStyle *style)
{
uiLayout *layout;
uiLayoutCommon *common;
if(!block->layout) {
common= MEM_callocN(sizeof(uiLayoutCommon), "uiLayoutCommon");
common->type= type;
common->style= style;
common->block= block;
common->opcontext= WM_OP_INVOKE_REGION_WIN;
layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
layout->item.type= ITEM_LAYOUT_ROOT;
layout->x= x;
layout->y= y;
layout->common= common;
layout->space= style->templatespace;
if(type == UI_LAYOUT_MENU)
layout->space= 0;
if(dir == UI_LAYOUT_HORIZONTAL) {
layout->h= size;
layout->common->emh= em*UI_UNIT_Y;
}
else {
layout->w= size;
layout->common->emw= em*UI_UNIT_X;
}
block->curlayout= layout;
block->layout= layout;
}
return block->layout;
}
uiBlock *uiLayoutBlock(uiLayout *layout)
{
return layout->common->block;
}
void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
{
block->curlayout= layout;
}
void ui_layout_add_but(uiLayout *layout, uiBut *but)
{
uiButtonItem *bitem;
bitem= MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
bitem->item.type= ITEM_BUTTON;
bitem->but= but;
BLI_addtail(&layout->items, bitem);
}
void uiLayoutContext(uiLayout *layout, int opcontext)
{
layout->common->opcontext= opcontext;
}
void uiLayoutFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
{
layout->common->handlefunc= handlefunc;
layout->common->argv= argv;
}
void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y)
{
uiLayout *layout= block->layout;
if(layout) {
/* NULL in advance so we don't interfere when adding button */
block->layout= NULL;
block->curlayout= NULL;
ui_layout_end(C, block, layout, x, y);
MEM_freeN(layout->common);
ui_layout_free(layout);
}
else {
if(x) *x= 0;
if(y) *y= 0;
}
/* XXX silly trick, interface_templates.c doesn't get linked
* because it's not used by other files in this module? */
{
void ui_template_fix_linking();
ui_template_fix_linking();
}
}
float uiBlockAspect(uiBlock *block)
{
return block->aspect; /* temporary */
}