4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * Contributor(s): Blender Foundation 2009.
22 * ***** END GPL LICENSE BLOCK *****
30 #include "MEM_guardedalloc.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_userdef_types.h"
36 #include "DNA_windowmanager_types.h"
38 #include "BLI_listbase.h"
39 #include "BLI_string.h"
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_idprop.h"
44 #include "BKE_library.h"
45 #include "BKE_screen.h"
46 #include "BKE_utildefines.h"
48 #include "RNA_access.h"
50 #include "UI_interface.h"
51 #include "UI_resources.h"
52 #include "UI_view2d.h"
56 #include "ED_screen.h"
61 #include "interface_intern.h"
63 /************************ Structs and Defines *************************/
65 #define RNA_NO_INDEX -1
66 #define RNA_ENUM_VALUE -2
73 typedef struct uiLayoutRoot {
74 struct uiLayoutRoot *next, *prev;
81 uiMenuHandleFunc handlefunc;
91 typedef enum uiItemType {
96 ITEM_LAYOUT_COLUMN_FLOW,
104 TEMPLATE_COLUMN_FLOW,
113 typedef struct uiItem {
119 typedef struct uiButtonItem {
128 bContextStore *context;
142 typedef struct uiLayoutItemFlow {
148 typedef struct uiLayoutItemBx {
153 typedef struct uiLayoutItemSplt {
158 typedef struct uiLayoutItemRoot {
162 /************************** Item ***************************/
164 static char *ui_item_name_add_colon(char *name, char namestr[UI_MAX_NAME_STR])
166 int len= strlen(name);
168 if(len != 0 && len+1 < UI_MAX_NAME_STR) {
169 BLI_strncpy(namestr, name, UI_MAX_NAME_STR);
171 namestr[len+1]= '\0';
178 static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
180 /* available == 0 is unlimited */
187 if(all > available) {
188 /* contents is bigger than available space */
190 return available-pos;
192 return (item*available)/all;
195 /* contents is smaller or equal to available space */
196 if(alignment == UI_LAYOUT_ALIGN_EXPAND) {
198 return available-pos;
200 return (item*available)/all;
207 /* variable button size in which direction? */
208 #define UI_ITEM_VARY_X 1
209 #define UI_ITEM_VARY_Y 2
211 static int ui_layout_vary_direction(uiLayout *layout)
213 return (layout->root->type == UI_LAYOUT_HEADER || layout->alignment != UI_LAYOUT_ALIGN_EXPAND)? UI_ITEM_VARY_X: UI_ITEM_VARY_Y;
216 /* estimated size of text + icon */
217 static int ui_text_icon_width(uiLayout *layout, char *name, int icon)
219 int variable = ui_layout_vary_direction(layout) == UI_ITEM_VARY_X;
221 if(icon && strcmp(name, "") == 0)
222 return UI_UNIT_X; /* icon only */
224 return (variable)? UI_GetStringWidth(name) + 4 + UI_UNIT_X: 10*UI_UNIT_X; /* icon + text */
226 return (variable)? UI_GetStringWidth(name) + 4 + UI_UNIT_X: 10*UI_UNIT_X; /* text only */
229 static void ui_item_size(uiItem *item, int *r_w, int *r_h)
231 if(item->type == ITEM_BUTTON) {
232 uiButtonItem *bitem= (uiButtonItem*)item;
234 if(r_w) *r_w= bitem->but->x2 - bitem->but->x1;
235 if(r_h) *r_h= bitem->but->y2 - bitem->but->y1;
238 uiLayout *litem= (uiLayout*)item;
240 if(r_w) *r_w= litem->w;
241 if(r_h) *r_h= litem->h;
245 static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
247 if(item->type == ITEM_BUTTON) {
248 uiButtonItem *bitem= (uiButtonItem*)item;
250 if(r_x) *r_x= bitem->but->x1;
251 if(r_y) *r_y= bitem->but->y1;
259 static void ui_item_position(uiItem *item, int x, int y, int w, int h)
261 if(item->type == ITEM_BUTTON) {
262 uiButtonItem *bitem= (uiButtonItem*)item;
269 ui_check_but(bitem->but); /* for strlen */
272 uiLayout *litem= (uiLayout*)item;
281 /******************** Special RNA Items *********************/
283 static int ui_layout_local_dir(uiLayout *layout)
285 switch(layout->item.type) {
286 case ITEM_LAYOUT_ROW:
287 case ITEM_LAYOUT_ROOT:
288 return UI_LAYOUT_HORIZONTAL;
289 case ITEM_LAYOUT_COLUMN:
290 case ITEM_LAYOUT_COLUMN_FLOW:
291 case ITEM_LAYOUT_SPLIT:
292 case ITEM_LAYOUT_FREE:
293 case ITEM_LAYOUT_BOX:
295 return UI_LAYOUT_VERTICAL;
299 static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int align)
303 if(ui_layout_local_dir(test) == UI_LAYOUT_HORIZONTAL)
304 sub= uiLayoutRow(layout, align);
306 sub= uiLayoutColumn(layout, align);
312 /* create buttons for an item with an RNA array */
313 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, int slider)
315 uiStyle *style= layout->root->style;
318 PropertySubType subtype;
322 /* retrieve type and subtype */
323 type= RNA_property_type(prop);
324 subtype= RNA_property_subtype(prop);
326 sub= ui_item_local_sublayout(layout, layout, 1);
327 uiBlockSetCurLayout(block, sub);
330 if(strcmp(name, "") != 0)
331 uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
334 if(type == PROP_BOOLEAN && len == 20) {
335 /* special check for layer layout */
336 int butw, buth, unit;
338 uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
340 unit= UI_UNIT_X*0.75;
344 uiBlockBeginAlign(block);
346 uiDefAutoButR(block, ptr, prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
348 uiDefAutoButR(block, ptr, prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
349 uiBlockEndAlign(block);
351 x += 5*butw + style->buttonspacex;
353 uiBlockBeginAlign(block);
355 uiDefAutoButR(block, ptr, prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
357 uiDefAutoButR(block, ptr, prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
358 uiBlockEndAlign(block);
360 else if(subtype == PROP_MATRIX) {
364 uiBlockSetCurLayout(block, uiLayoutFree(layout, 1));
366 len= ceil(sqrt(len));
372 for(a=0; a<len; a++) {
376 but= uiDefAutoButR(block, ptr, prop, a, "", 0, x + w*col, y+(row-a-1)*UI_UNIT_Y, w, UI_UNIT_Y);
377 if(slider && but->type==NUM)
381 else if(len <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
382 if(subtype == PROP_COLOR)
383 uiDefAutoButR(block, ptr, prop, -1, "", 0, 0, 0, w, UI_UNIT_Y);
385 if(subtype != PROP_COLOR || expand) {
386 /* layout for known array subtypes */
387 static char vectoritem[4]= {'X', 'Y', 'Z', 'W'};
388 static char quatitem[4]= {'W', 'X', 'Y', 'Z'};
389 static char coloritem[4]= {'R', 'G', 'B', 'A'};
392 for(a=0; a<len; a++) {
393 if(len == 4 && subtype == PROP_ROTATION)
395 else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
396 str[0]= vectoritem[a];
398 str[0]= coloritem[a];
400 if(type == PROP_BOOLEAN) {
408 but= uiDefAutoButR(block, ptr, prop, a, str, 0, 0, 0, w, UI_UNIT_Y);
409 if(slider && but->type==NUM)
413 else if(subtype == PROP_COLOR && len == 4) {
414 but= uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, w, UI_UNIT_Y);
415 if(slider && but->type==NUM)
420 for(a=0; a<len; a++) {
421 but= uiDefAutoButR(block, ptr, prop, a, "", 0, 0, 0, w, UI_UNIT_Y);
422 if(slider && but->type==NUM)
427 uiBlockSetCurLayout(block, layout);
430 static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, char *uiname, int x, int y, int w, int h)
432 EnumPropertyItem *item;
433 const char *identifier;
435 int a, totitem, itemw, icon, value, free;
437 identifier= RNA_property_identifier(prop);
438 RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
440 uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
441 for(a=0; a<totitem; a++) {
442 if(!item[a].identifier[0])
445 name= (!uiname || uiname[0])? (char*)item[a].name: "";
447 value= item[a].value;
448 itemw= ui_text_icon_width(block->curlayout, name, icon);
450 if(icon && strcmp(name, "") != 0)
451 uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
453 uiDefIconButR(block, ROW, 0, icon, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
455 uiDefButR(block, ROW, 0, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
457 uiBlockSetCurLayout(block, layout);
463 /* create label + button for RNA property */
464 static uiBut *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)
468 PropertySubType subtype;
471 sub= uiLayoutRow(layout, 0);
472 uiBlockSetCurLayout(block, sub);
474 if(strcmp(name, "") != 0) {
475 /* XXX UI_GetStringWidth is not accurate
476 labelw= UI_GetStringWidth(name);
477 CLAMP(labelw, w/4, 3*w/4);*/
479 uiDefBut(block, LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
483 subtype= RNA_property_subtype(prop);
485 if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
486 uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
487 uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
488 but= 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 */
491 but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
493 uiBlockSetCurLayout(block, layout);
497 /********************* Button Items *************************/
500 static void ui_item_disabled(uiLayout *layout, char *name)
502 uiBlock *block= layout->root->block;
506 uiBlockSetCurLayout(block, layout);
511 w= ui_text_icon_width(layout, name, 0);
513 but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
514 but->flag |= UI_BUT_DISABLED;
520 void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
522 uiBlock *block= layout->root->block;
523 wmOperatorType *ot= WM_operatortype_find(idname, 0);
528 ui_item_disabled(layout, idname);
534 if(layout->root->type == UI_LAYOUT_MENU && !icon)
538 uiBlockSetCurLayout(block, layout);
540 w= ui_text_icon_width(layout, name, icon);
542 if(icon && strcmp(name, "") != 0)
543 but= uiDefIconTextButO(block, BUT, ot->idname, context, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
545 but= uiDefIconButO(block, BUT, ot->idname, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
547 but= uiDefButO(block, BUT, ot->idname, context, (char*)name, 0, 0, w, UI_UNIT_Y, NULL);
549 /* assign properties */
551 PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
552 opptr->data= properties;
556 static char *ui_menu_enumpropname(uiLayout *layout, char *opname, char *propname, int retval)
558 wmOperatorType *ot= WM_operatortype_find(opname, 0);
565 RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
566 prop= RNA_struct_find_property(&ptr, propname);
569 EnumPropertyItem *item;
573 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
574 if(RNA_enum_name(item, retval, &name)) {
575 if(free) MEM_freeN(item);
586 void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
590 WM_operator_properties_create(&ptr, opname);
591 RNA_enum_set(&ptr, propname, value);
594 name= ui_menu_enumpropname(layout, opname, propname, value);
596 uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
599 void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
601 wmOperatorType *ot= WM_operatortype_find(opname, 0);
605 if(!ot || !ot->srna) {
606 ui_item_disabled(layout, opname);
610 RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
611 prop= RNA_struct_find_property(&ptr, propname);
613 if(prop && RNA_property_type(prop) == PROP_ENUM) {
614 EnumPropertyItem *item;
615 int totitem, i, free;
617 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
619 for(i=0; i<totitem; i++)
620 if(item[i].identifier[0])
621 uiItemEnumO(layout, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
630 /* for use in cases where we have */
631 void uiItemEnumO_string(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value_str)
635 /* for getting the enum */
637 EnumPropertyItem *item;
640 WM_operator_properties_create(&ptr, opname);
643 if((prop= RNA_struct_find_property(&ptr, propname))) {
644 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
645 if(RNA_enum_value_from_id(item, value_str, &value)==0) {
646 if(free) MEM_freeN(item);
647 printf("uiItemEnumO_string: %s.%s, enum %s not found.\n", RNA_struct_identifier(ptr.type), propname, value_str);
655 printf("uiItemEnumO_string: %s.%s not found.\n", RNA_struct_identifier(ptr.type), propname);
659 RNA_property_enum_set(&ptr, prop, value);
661 /* same as uiItemEnumO */
663 name= ui_menu_enumpropname(layout, opname, propname, value);
665 uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
668 void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
672 WM_operator_properties_create(&ptr, opname);
673 RNA_boolean_set(&ptr, propname, value);
675 uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
678 void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
682 WM_operator_properties_create(&ptr, opname);
683 RNA_int_set(&ptr, propname, value);
685 uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
688 void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
692 WM_operator_properties_create(&ptr, opname);
693 RNA_float_set(&ptr, propname, value);
695 uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
698 void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
702 WM_operator_properties_create(&ptr, opname);
703 RNA_string_set(&ptr, propname, value);
705 uiItemFullO(layout, name, icon, opname, ptr.data, layout->root->opcontext);
708 void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
710 uiItemFullO(layout, name, icon, opname, NULL, layout->root->opcontext);
713 /* RNA property items */
715 static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA *prop, int index, int *r_w, int *r_h)
718 PropertySubType subtype;
721 /* arbitrary extended width by type */
722 type= RNA_property_type(prop);
723 subtype= RNA_property_subtype(prop);
724 len= RNA_property_array_length(prop);
726 if(ELEM(type, PROP_STRING, PROP_POINTER) && strcmp(name, "") == 0)
729 w= ui_text_icon_width(layout, name, icon);
732 /* increase height for arrays */
733 if(index == RNA_NO_INDEX && len > 0) {
734 if(strcmp(name, "") == 0 && icon == 0)
737 if(type == PROP_BOOLEAN && len == 20)
739 else if(subtype == PROP_MATRIX)
740 h += ceil(sqrt(len))*UI_UNIT_Y;
744 else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
745 if(type == PROP_BOOLEAN && strcmp(name, "") != 0)
747 else if(type == PROP_ENUM)
755 void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int expand, int slider, int toggle)
757 uiBlock *block= layout->root->block;
760 char namestr[UI_MAX_NAME_STR];
763 if(!ptr->data || !prop)
766 uiBlockSetCurLayout(block, layout);
769 type= RNA_property_type(prop);
770 len= RNA_property_array_length(prop);
772 /* set name and icon */
774 name= (char*)RNA_property_ui_name(prop);
776 icon= RNA_property_ui_icon(prop);
778 if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER))
779 name= ui_item_name_add_colon(name, namestr);
780 else if(type == PROP_BOOLEAN && len)
781 name= ui_item_name_add_colon(name, namestr);
782 else if(type == PROP_ENUM && index != RNA_ENUM_VALUE)
783 name= ui_item_name_add_colon(name, namestr);
785 if(layout->root->type == UI_LAYOUT_MENU) {
786 if(type == PROP_BOOLEAN)
787 icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
788 else if(type == PROP_ENUM && index == RNA_ENUM_VALUE)
789 icon= (RNA_property_enum_get(ptr, prop) == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
793 ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
796 if(index == RNA_NO_INDEX && len > 0)
797 ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand, slider);
799 else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
800 char *identifier= (char*)RNA_property_identifier(prop);
802 if(icon && strcmp(name, "") != 0)
803 uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
805 uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
807 uiDefButR(block, ROW, 0, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
810 else if(type == PROP_ENUM && expand)
811 ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h);
812 /* property with separate label */
813 else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
814 but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
815 ui_but_add_search(but, ptr, prop, NULL, NULL);
819 but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
821 if(slider && but->type==NUM)
824 if(toggle && but->type==OPTION)
829 void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand, int slider, int toggle)
833 if(!ptr->data || !propname)
836 prop= RNA_struct_find_property(ptr, propname);
839 ui_item_disabled(layout, propname);
840 printf("uiItemR: property not found: %s\n", propname);
844 uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, 0, expand, slider, toggle);
847 void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value)
851 if(!ptr->data || !propname)
854 prop= RNA_struct_find_property(ptr, propname);
856 if(!prop || RNA_property_type(prop) != PROP_ENUM) {
857 ui_item_disabled(layout, propname);
858 printf("uiItemEnumR: enum property not found: %s\n", propname);
862 uiItemFullR(layout, name, icon, ptr, prop, RNA_ENUM_VALUE, value, 0, 0, 0);
865 void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, char *value)
868 EnumPropertyItem *item;
871 if(!ptr->data || !propname)
874 prop= RNA_struct_find_property(ptr, propname);
876 if(!prop || RNA_property_type(prop) != PROP_ENUM) {
877 ui_item_disabled(layout, propname);
878 printf("uiItemEnumR: enum property not found: %s\n", propname);
882 RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
884 if(!RNA_enum_value_from_id(item, value, &ivalue)) {
885 if(free) MEM_freeN(item);
886 ui_item_disabled(layout, propname);
887 printf("uiItemEnumR: enum property value not found: %s\n", value);
891 for(a=0; item[a].identifier; a++) {
892 if(item[a].value == ivalue) {
893 uiItemFullR(layout, (char*)item[a].name, item[a].icon, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, 0, 0);
902 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
906 prop= RNA_struct_find_property(ptr, propname);
909 ui_item_disabled(layout, propname);
913 if(RNA_property_type(prop) == PROP_ENUM) {
914 EnumPropertyItem *item;
915 int totitem, i, free;
917 RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
919 for(i=0; i<totitem; i++)
920 if(item[i].identifier[0])
921 uiItemEnumR(layout, (char*)item[i].name, 0, ptr, propname, item[i].value);
930 /* Pointer RNA button with search */
932 static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
934 Scene *scene= CTX_data_scene(C);
940 RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
942 if(RNA_struct_is_ID(itemptr.type))
943 iconid= ui_id_icon_get(scene, itemptr.data);
945 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
948 if(BLI_strcasestr(name, str)) {
949 if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) {
963 static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
967 /* look for collection property in Main */
968 RNA_main_pointer_create(G.main, ptr);
972 RNA_STRUCT_BEGIN(ptr, iprop) {
973 /* if it's a collection and has same pointer type, we've got it */
974 if(RNA_property_type(iprop) == PROP_COLLECTION) {
975 srna= RNA_property_pointer_type(ptr, iprop);
986 void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
991 /* for ID's we do automatic lookup */
993 if(RNA_property_type(prop) == PROP_POINTER) {
994 ptype= RNA_property_pointer_type(ptr, prop);
995 search_id_collection(ptype, &sptr, &searchprop);
1000 /* turn button into search button */
1002 but->type= SEARCH_MENU;
1003 but->hardmax= MAX2(but->hardmax, 256);
1004 but->rnasearchpoin= *searchptr;
1005 but->rnasearchprop= searchprop;
1006 but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
1008 uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
1012 void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname)
1014 PropertyRNA *prop, *searchprop;
1018 StructRNA *icontype;
1021 /* validate arguments */
1022 if(!ptr->data || !searchptr->data)
1025 prop= RNA_struct_find_property(ptr, propname);
1028 printf("uiItemPointerR: property not found: %s\n", propname);
1032 type= RNA_property_type(prop);
1033 if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
1034 printf("uiItemPointerR: property %s must be a pointer or string.\n", propname);
1038 searchprop= RNA_struct_find_property(searchptr, searchpropname);
1040 if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) {
1041 printf("uiItemPointerR: search collection property not found: %s\n", searchpropname);
1045 /* get icon & name */
1047 if(type == PROP_POINTER)
1048 icontype= RNA_property_pointer_type(ptr, prop);
1050 icontype= RNA_property_pointer_type(searchptr, searchprop);
1052 icon= RNA_struct_ui_icon(icontype);
1055 name= (char*)RNA_property_ui_name(prop);
1058 block= uiLayoutGetBlock(layout);
1060 ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
1061 but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
1063 ui_but_add_search(but, ptr, prop, searchptr, searchprop);
1067 static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
1069 MenuType *mt= (MenuType*)arg_mt;
1073 menu.layout= layout;
1077 static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN)
1079 uiBlock *block= layout->root->block;
1083 uiBlockSetCurLayout(block, layout);
1085 if(layout->root->type == UI_LAYOUT_HEADER)
1086 uiBlockSetEmboss(block, UI_EMBOSS);
1090 if(layout->root->type == UI_LAYOUT_MENU && !icon)
1093 w= ui_text_icon_width(layout, name, icon);
1096 if(layout->root->type == UI_LAYOUT_HEADER) /* ugly .. */
1100 but= uiDefIconTextMenuBut(block, func, arg, icon, (char*)name, 0, 0, w, h, "");
1102 but= uiDefMenuBut(block, func, arg, (char*)name, 0, 0, w, h, "");
1104 if(argN) { /* ugly .. */
1105 but->poin= (char*)but;
1106 but->func_argN= argN;
1109 if(layout->root->type == UI_LAYOUT_HEADER)
1110 uiBlockSetEmboss(block, UI_EMBOSS);
1111 else if(layout->root->type == UI_LAYOUT_PANEL)
1115 void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname)
1117 ARegion *ar= CTX_wm_region(C);
1123 for(mt=ar->type->menutypes.first; mt; mt=mt->next) {
1124 if(strcmp(menuname, mt->idname) == 0) {
1127 if(layout->root->type == UI_LAYOUT_MENU && !icon)
1129 ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL);
1134 printf("uiItemM: not found %s\n", menuname);
1138 void uiItemL(uiLayout *layout, char *name, int icon)
1140 uiBlock *block= layout->root->block;
1144 uiBlockSetCurLayout(block, layout);
1148 if(layout->root->type == UI_LAYOUT_MENU && !icon)
1151 w= ui_text_icon_width(layout, name, icon);
1153 if(icon && strcmp(name, "") != 0)
1154 but= uiDefIconTextBut(block, LABEL, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1156 but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1158 but= uiDefBut(block, LABEL, 0, (char*)name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1162 void uiItemV(uiLayout *layout, char *name, int icon, int argval)
1165 uiBlock *block= layout->root->block;
1166 float *retvalue= (block->handle)? &block->handle->retvalue: NULL;
1169 uiBlockSetCurLayout(block, layout);
1173 if(layout->root->type == UI_LAYOUT_MENU && !icon)
1176 w= ui_text_icon_width(layout, name, icon);
1178 if(icon && strcmp(name, "") != 0)
1179 uiDefIconTextButF(block, BUTM, 0, icon, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1181 uiDefIconButF(block, BUTM, 0, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1183 uiDefButF(block, BUTM, 0, (char*)name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
1186 /* separator item */
1187 void uiItemS(uiLayout *layout)
1189 uiBlock *block= layout->root->block;
1191 uiBlockSetCurLayout(block, layout);
1192 uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
1196 void uiItemMenuF(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
1201 ui_item_menu(layout, name, icon, func, NULL, NULL);
1204 typedef struct MenuItemLevel {
1211 static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
1213 MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
1215 uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
1216 uiItemsEnumO(layout, lvl->opname, lvl->propname);
1219 void uiItemMenuEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname)
1221 wmOperatorType *ot= WM_operatortype_find(opname, 0);
1224 if(!ot || !ot->srna) {
1225 ui_item_disabled(layout, opname);
1231 if(layout->root->type == UI_LAYOUT_MENU && !icon)
1234 lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
1235 lvl->opname= opname;
1236 lvl->propname= propname;
1237 lvl->opcontext= layout->root->opcontext;
1239 ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl);
1242 static void menu_item_enum_rna_menu(bContext *C, uiLayout *layout, void *arg)
1244 MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
1246 uiLayoutSetOperatorContext(layout, lvl->opcontext);
1247 uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
1250 void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname)
1255 prop= RNA_struct_find_property(ptr, propname);
1257 ui_item_disabled(layout, propname);
1262 name= (char*)RNA_property_ui_name(prop);
1263 if(layout->root->type == UI_LAYOUT_MENU && !icon)
1266 lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
1268 lvl->propname= propname;
1269 lvl->opcontext= layout->root->opcontext;
1271 ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl);
1274 /**************************** Layout Items ***************************/
1276 /* single-row layout */
1277 static void ui_litem_estimate_row(uiLayout *litem)
1285 for(item=litem->items.first; item; item=item->next) {
1286 ui_item_size(item, &itemw, &itemh);
1289 litem->h= MAX2(itemh, litem->h);
1292 litem->w += litem->space;
1296 static int ui_litem_min_width(int itemw)
1298 return MIN2(2*UI_UNIT_X, itemw);
1301 static void ui_litem_layout_row(uiLayout *litem)
1304 int x, y, w, tot, totw, neww, itemw, minw, itemh, offset;
1305 int fixedw, freew, fixedx, freex, flag= 0, lastw= 0;
1313 for(item=litem->items.first; item; item=item->next) {
1314 ui_item_size(item, &itemw, &itemh);
1323 w -= (tot-1)*litem->space;
1326 /* keep clamping items to fixed minimum size until all are done */
1332 for(item=litem->items.first; item; item=item->next) {
1336 ui_item_size(item, &itemw, &itemh);
1337 minw= ui_litem_min_width(itemw);
1340 neww= ui_item_fit(itemw, x, totw, w-lastw, !item->next, litem->alignment, NULL);
1342 neww= 0; /* no space left, all will need clamping to minimum size */
1346 if((neww < minw || itemw == minw) && w != 0) {
1354 /* keep free size */
1367 for(item=litem->items.first; item; item=item->next) {
1368 ui_item_size(item, &itemw, &itemh);
1369 minw= ui_litem_min_width(itemw);
1372 /* fixed minimum size items */
1373 itemw= ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL);
1377 /* free size item */
1378 itemw= ui_item_fit(itemw, freex, freew, w-fixedw, !item->next, litem->alignment, NULL);
1382 /* align right/center */
1384 if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
1385 if(fixedw == 0 && freew < w-fixedw)
1386 offset= (w - fixedw) - freew;
1388 else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
1389 if(fixedw == 0 && freew < w-fixedw)
1390 offset= ((w - fixedw) - freew)/2;
1394 ui_item_position(item, x+offset, y-itemh, itemw, itemh);
1401 litem->w= x - litem->x;
1402 litem->h= litem->y - y;
1407 /* single-column layout */
1408 static void ui_litem_estimate_column(uiLayout *litem)
1416 for(item=litem->items.first; item; item=item->next) {
1417 ui_item_size(item, &itemw, &itemh);
1419 litem->w= MAX2(litem->w, itemw);
1423 litem->h += litem->space;
1427 static void ui_litem_layout_column(uiLayout *litem)
1435 for(item=litem->items.first; item; item=item->next) {
1436 ui_item_size(item, NULL, &itemh);
1439 ui_item_position(item, x, y, litem->w, itemh);
1445 litem->h= litem->y - y;
1451 static void ui_litem_estimate_root(uiLayout *litem)
1456 static void ui_litem_layout_root(uiLayout *litem)
1458 if(litem->root->type == UI_LAYOUT_HEADER)
1459 ui_litem_layout_row(litem);
1461 ui_litem_layout_column(litem);
1465 static void ui_litem_estimate_box(uiLayout *litem)
1467 uiStyle *style= litem->root->style;
1469 ui_litem_estimate_column(litem);
1470 litem->w += 2*style->boxspace;
1471 litem->h += style->boxspace;
1474 static void ui_litem_layout_box(uiLayout *litem)
1476 uiLayoutItemBx *box= (uiLayoutItemBx*)litem;
1477 uiStyle *style= litem->root->style;
1484 litem->x += style->boxspace;
1486 if(w != 0) litem->w -= 2*style->boxspace;
1487 if(h != 0) litem->h -= 2*style->boxspace;
1489 ui_litem_layout_column(litem);
1491 litem->x -= style->boxspace;
1492 litem->y -= style->boxspace;
1494 if(w != 0) litem->w += 2*style->boxspace;
1495 if(h != 0) litem->h += style->boxspace;
1497 /* roundbox around the sublayout */
1501 but->x2= litem->x+litem->w;
1502 but->y2= litem->y+litem->h;
1505 /* multi-column layout, automatically flowing to the next */
1506 static void ui_litem_estimate_column_flow(uiLayout *litem)
1508 uiStyle *style= litem->root->style;
1509 uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
1511 int col, x, y, emh, emy, miny, itemw, itemh, maxw=0;
1514 /* compute max needed width and total height */
1517 for(item=litem->items.first; item; item=item->next) {
1518 ui_item_size(item, &itemw, &itemh);
1519 maxw= MAX2(maxw, itemw);
1524 if(flow->number <= 0) {
1525 /* auto compute number of columns, not very good */
1531 flow->totcol= MAX2(litem->root->emw/maxw, 1);
1532 flow->totcol= MIN2(flow->totcol, totitem);
1535 flow->totcol= flow->number;
1544 emh= toth/flow->totcol;
1546 /* create column per column */
1548 for(item=litem->items.first; item; item=item->next) {
1549 ui_item_size(item, &itemw, &itemh);
1551 y -= itemh + style->buttonspacey;
1552 miny= MIN2(miny, y);
1554 maxw= MAX2(itemw, maxw);
1556 /* decide to go to next one */
1557 if(col < flow->totcol-1 && emy <= -emh) {
1558 x += maxw + litem->space;
1566 litem->h= litem->y - miny;
1569 static void ui_litem_layout_column_flow(uiLayout *litem)
1571 uiStyle *style= litem->root->style;
1572 uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
1574 int col, x, y, w, emh, emy, miny, itemw, itemh;
1575 int toth, totitem, offset;
1577 /* compute max needed width and total height */
1580 for(item=litem->items.first; item; item=item->next) {
1581 ui_item_size(item, &itemw, &itemh);
1592 w= litem->w - (flow->totcol-1)*style->columnspace;
1593 emh= toth/flow->totcol;
1595 /* create column per column */
1597 for(item=litem->items.first; item; item=item->next) {
1598 ui_item_size(item, NULL, &itemh);
1599 itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, col == flow->totcol-1, litem->alignment, &offset);
1603 ui_item_position(item, x+offset, y, itemw, itemh);
1604 y -= style->buttonspacey;
1605 miny= MIN2(miny, y);
1607 /* decide to go to next one */
1608 if(col < flow->totcol-1 && emy <= -emh) {
1609 x += itemw + style->columnspace;
1615 litem->h= litem->y - miny;
1621 static void ui_litem_estimate_free(uiLayout *litem)
1624 int itemx, itemy, itemw, itemh, minx, miny;
1631 for(item=litem->items.first; item; item=item->next) {
1632 ui_item_offset(item, &itemx, &itemy);
1633 ui_item_size(item, &itemw, &itemh);
1635 minx= MIN2(minx, itemx);
1636 miny= MIN2(miny, itemy);
1638 litem->w= MAX2(litem->w, itemx+itemw);
1639 litem->h= MAX2(litem->h, itemy+itemh);
1646 static void ui_litem_layout_free(uiLayout *litem)
1649 float scalex=1.0f, scaley=1.0f;
1650 int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
1657 for(item=litem->items.first; item; item=item->next) {
1658 ui_item_offset(item, &itemx, &itemy);
1659 ui_item_size(item, &itemw, &itemh);
1661 minx= MIN2(minx, itemx);
1662 miny= MIN2(miny, itemy);
1664 totw= MAX2(totw, itemx+itemw);
1665 toth= MAX2(toth, itemy+itemh);
1671 if(litem->w && totw > 0)
1672 scalex= (float)litem->w/(float)totw;
1673 if(litem->h && toth > 0)
1674 scaley= (float)litem->h/(float)toth;
1677 y= litem->y - scaley*toth;
1679 for(item=litem->items.first; item; item=item->next) {
1680 ui_item_offset(item, &itemx, &itemy);
1681 ui_item_size(item, &itemw, &itemh);
1683 if(scalex != 1.0f) {
1684 newx= (itemx - minx)*scalex;
1685 itemw= (itemx - minx + itemw)*scalex - newx;
1689 if(scaley != 1.0f) {
1690 newy= (itemy - miny)*scaley;
1691 itemh= (itemy - miny + itemh)*scaley - newy;
1695 ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
1698 litem->w= scalex*totw;
1699 litem->h= litem->y - y;
1700 litem->x= x + litem->w;
1705 static void ui_litem_estimate_split(uiLayout *litem)
1707 ui_litem_estimate_row(litem);
1710 static void ui_litem_layout_split(uiLayout *litem)
1712 uiLayoutItemSplt *split= (uiLayoutItemSplt*)litem;
1715 int itemh, x, y, w, tot=0, colw=0;
1720 for(item=litem->items.first; item; item=item->next)
1726 percentage= (split->percentage == 0.0f)? 1.0f/(float)tot: split->percentage;
1728 w= (litem->w - (tot-1)*litem->space);
1730 colw= MAX2(colw, 0);
1732 for(item=litem->items.first; item; item=item->next) {
1733 ui_item_size(item, NULL, &itemh);
1735 ui_item_position(item, x, y-itemh, colw, itemh);
1739 colw= (w - (int)(w*percentage))/(tot-1);
1740 colw= MAX2(colw, 0);
1746 litem->w= x - litem->x;
1747 litem->h= litem->y - y;
1752 /* layout create functions */
1753 uiLayout *uiLayoutRow(uiLayout *layout, int align)
1757 litem= MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
1758 litem->item.type= ITEM_LAYOUT_ROW;
1759 litem->root= layout->root;
1760 litem->align= align;
1763 litem->context= layout->context;
1764 litem->space= (align)? 0: layout->root->style->buttonspacex;
1765 BLI_addtail(&layout->items, litem);
1767 uiBlockSetCurLayout(layout->root->block, litem);
1772 uiLayout *uiLayoutColumn(uiLayout *layout, int align)
1776 litem= MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
1777 litem->item.type= ITEM_LAYOUT_COLUMN;
1778 litem->root= layout->root;
1779 litem->align= align;
1782 litem->context= layout->context;
1783 litem->space= (litem->align)? 0: layout->root->style->buttonspacey;
1784 BLI_addtail(&layout->items, litem);
1786 uiBlockSetCurLayout(layout->root->block, litem);
1791 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
1793 uiLayoutItemFlow *flow;
1795 flow= MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
1796 flow->litem.item.type= ITEM_LAYOUT_COLUMN_FLOW;
1797 flow->litem.root= layout->root;
1798 flow->litem.align= align;
1799 flow->litem.active= 1;
1800 flow->litem.enabled= 1;
1801 flow->litem.context= layout->context;
1802 flow->litem.space= (flow->litem.align)? 0: layout->root->style->columnspace;
1803 flow->number= number;
1804 BLI_addtail(&layout->items, flow);
1806 uiBlockSetCurLayout(layout->root->block, &flow->litem);
1808 return &flow->litem;
1811 uiLayout *uiLayoutBox(uiLayout *layout)
1813 uiLayoutItemBx *box;
1815 box= MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
1816 box->litem.item.type= ITEM_LAYOUT_BOX;
1817 box->litem.root= layout->root;
1818 box->litem.active= 1;
1819 box->litem.enabled= 1;
1820 box->litem.context= layout->context;
1821 box->litem.space= layout->root->style->columnspace;
1822 BLI_addtail(&layout->items, box);
1824 uiBlockSetCurLayout(layout->root->block, &box->litem);
1826 box->roundbox= uiDefBut(layout->root->block, ROUNDBOX, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
1831 uiLayout *uiLayoutFree(uiLayout *layout, int align)
1835 litem= MEM_callocN(sizeof(uiLayout), "uiLayoutFree");
1836 litem->item.type= ITEM_LAYOUT_FREE;
1837 litem->root= layout->root;
1838 litem->align= align;
1841 litem->context= layout->context;
1842 BLI_addtail(&layout->items, litem);
1844 uiBlockSetCurLayout(layout->root->block, litem);
1849 uiBlock *uiLayoutFreeBlock(uiLayout *layout)
1853 block= uiLayoutGetBlock(layout);
1854 uiLayoutFree(layout, 0);
1859 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage)
1861 uiLayoutItemSplt *split;
1863 split= MEM_callocN(sizeof(uiLayoutItemSplt), "uiLayoutItemSplt");
1864 split->litem.item.type= ITEM_LAYOUT_SPLIT;
1865 split->litem.root= layout->root;
1866 split->litem.active= 1;
1867 split->litem.enabled= 1;
1868 split->litem.context= layout->context;
1869 split->litem.space= layout->root->style->columnspace;
1870 split->percentage= percentage;
1871 BLI_addtail(&layout->items, split);
1873 uiBlockSetCurLayout(layout->root->block, &split->litem);
1875 return &split->litem;
1878 void uiLayoutSetActive(uiLayout *layout, int active)
1880 layout->active= active;
1883 void uiLayoutSetEnabled(uiLayout *layout, int enabled)
1885 layout->enabled= enabled;
1888 void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
1890 layout->redalert= redalert;
1893 void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
1895 layout->keepaspect= keepaspect;
1898 void uiLayoutSetAlignment(uiLayout *layout, int alignment)
1900 layout->alignment= alignment;
1903 void uiLayoutSetScaleX(uiLayout *layout, float scale)
1905 layout->scale[0]= scale;
1908 void uiLayoutSetScaleY(uiLayout *layout, float scale)
1910 layout->scale[1]= scale;
1913 int uiLayoutGetActive(uiLayout *layout)
1915 return layout->active;
1918 int uiLayoutGetEnabled(uiLayout *layout)
1920 return layout->enabled;
1923 int uiLayoutGetRedAlert(uiLayout *layout)
1925 return layout->redalert;
1928 int uiLayoutGetKeepAspect(uiLayout *layout)
1930 return layout->keepaspect;
1933 int uiLayoutGetAlignment(uiLayout *layout)
1935 return layout->alignment;
1938 float uiLayoutGetScaleX(uiLayout *layout)
1940 return layout->scale[0];
1943 float uiLayoutGetScaleY(uiLayout *layout)
1945 return layout->scale[0];
1948 /********************** Layout *******************/
1950 static void ui_item_scale(uiLayout *litem, float scale[2])
1955 for(item=litem->items.last; item; item=item->prev) {
1956 ui_item_size(item, &w, &h);
1957 ui_item_offset(item, &x, &y);
1959 if(scale[0] != 0.0f) {
1964 if(scale[1] != 0.0f) {
1969 ui_item_position(item, x, y, w, h);
1973 static void ui_item_estimate(uiItem *item)
1977 if(item->type != ITEM_BUTTON) {
1978 uiLayout *litem= (uiLayout*)item;
1980 for(subitem=litem->items.first; subitem; subitem=subitem->next)
1981 ui_item_estimate(subitem);
1983 if(litem->items.first == NULL)
1986 if(litem->scale[0] != 0.0f || litem->scale[1] != 0.0f)
1987 ui_item_scale(litem, litem->scale);
1989 switch(litem->item.type) {
1990 case ITEM_LAYOUT_COLUMN:
1991 ui_litem_estimate_column(litem);
1993 case ITEM_LAYOUT_COLUMN_FLOW:
1994 ui_litem_estimate_column_flow(litem);
1996 case ITEM_LAYOUT_ROW:
1997 ui_litem_estimate_row(litem);
1999 case ITEM_LAYOUT_BOX:
2000 ui_litem_estimate_box(litem);
2002 case ITEM_LAYOUT_ROOT:
2003 ui_litem_estimate_root(litem);
2005 case ITEM_LAYOUT_FREE:
2006 ui_litem_estimate_free(litem);
2008 case ITEM_LAYOUT_SPLIT:
2009 ui_litem_estimate_split(litem);
2017 static void ui_item_align(uiLayout *litem, int nr)
2020 uiButtonItem *bitem;
2021 uiLayoutItemBx *box;
2023 for(item=litem->items.last; item; item=item->prev) {
2024 if(item->type == ITEM_BUTTON) {
2025 bitem= (uiButtonItem*)item;
2026 if(ui_but_can_align(bitem->but))
2027 if(!bitem->but->alignnr)
2028 bitem->but->alignnr= nr;
2030 else if(item->type == ITEM_LAYOUT_FREE);
2031 else if(item->type == ITEM_LAYOUT_BOX) {
2032 box= (uiLayoutItemBx*)item;
2033 box->roundbox->alignnr= nr;
2034 BLI_remlink(&litem->root->block->buttons, box->roundbox);
2035 BLI_addhead(&litem->root->block->buttons, box->roundbox);
2038 ui_item_align((uiLayout*)item, nr);
2042 static void ui_item_flag(uiLayout *litem, int flag)
2045 uiButtonItem *bitem;
2047 for(item=litem->items.last; item; item=item->prev) {
2048 if(item->type == ITEM_BUTTON) {
2049 bitem= (uiButtonItem*)item;
2050 bitem->but->flag |= flag;
2053 ui_item_flag((uiLayout*)item, flag);
2057 static void ui_item_layout(uiItem *item)
2061 if(item->type != ITEM_BUTTON) {
2062 uiLayout *litem= (uiLayout*)item;
2064 if(litem->items.first == NULL)
2068 ui_item_align(litem, ++litem->root->block->alignnr);
2070 ui_item_flag(litem, UI_BUT_INACTIVE);
2072 ui_item_flag(litem, UI_BUT_DISABLED);
2074 switch(litem->item.type) {
2075 case ITEM_LAYOUT_COLUMN:
2076 ui_litem_layout_column(litem);
2078 case ITEM_LAYOUT_COLUMN_FLOW:
2079 ui_litem_layout_column_flow(litem);
2081 case ITEM_LAYOUT_ROW:
2082 ui_litem_layout_row(litem);
2084 case ITEM_LAYOUT_BOX:
2085 ui_litem_layout_box(litem);
2087 case ITEM_LAYOUT_ROOT:
2088 ui_litem_layout_root(litem);
2090 case ITEM_LAYOUT_FREE:
2091 ui_litem_layout_free(litem);
2093 case ITEM_LAYOUT_SPLIT:
2094 ui_litem_layout_split(litem);
2100 for(subitem=litem->items.first; subitem; subitem=subitem->next)
2101 ui_item_layout(subitem);
2105 static void ui_layout_items(const bContext *C, uiBlock *block, uiLayout *layout)
2107 ui_item_estimate(&layout->item);
2108 ui_item_layout(&layout->item);
2111 static void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
2113 if(layout->root->handlefunc)
2114 uiBlockSetButmFunc(block, layout->root->handlefunc, layout->root->argv);
2116 ui_layout_items(C, block, layout);
2118 if(x) *x= layout->x;
2119 if(y) *y= layout->y;
2122 static void ui_layout_free(uiLayout *layout)
2124 uiItem *item, *next;
2126 for(item=layout->items.first; item; item=next) {
2129 if(item->type == ITEM_BUTTON)
2132 ui_layout_free((uiLayout*)item);
2138 uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, uiStyle *style)
2143 root= MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
2147 root->opcontext= WM_OP_INVOKE_REGION_WIN;
2149 layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
2150 layout->item.type= ITEM_LAYOUT_ROOT;
2155 layout->space= style->templatespace;
2158 layout->context= NULL;
2160 if(type == UI_LAYOUT_MENU)
2163 if(dir == UI_LAYOUT_HORIZONTAL) {
2165 layout->root->emh= em*UI_UNIT_Y;
2169 layout->root->emw= em*UI_UNIT_X;
2172 block->curlayout= layout;
2173 root->layout= layout;
2174 BLI_addtail(&block->layouts, root);
2179 uiBlock *uiLayoutGetBlock(uiLayout *layout)
2181 return layout->root->block;
2184 int uiLayoutGetOperatorContext(uiLayout *layout)
2186 return layout->root->opcontext;
2190 void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
2192 block->curlayout= layout;
2195 void ui_layout_add_but(uiLayout *layout, uiBut *but)
2197 uiButtonItem *bitem;
2199 bitem= MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
2200 bitem->item.type= ITEM_BUTTON;
2202 BLI_addtail(&layout->items, bitem);
2204 if(layout->context) {
2205 but->context= layout->context;
2206 but->context->used= 1;
2210 void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
2212 layout->root->opcontext= opcontext;
2215 void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
2217 layout->root->handlefunc= handlefunc;
2218 layout->root->argv= argv;
2221 void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y)
2228 block->curlayout= NULL;
2230 for(root=block->layouts.first; root; root=root->next) {
2231 /* NULL in advance so we don't interfere when adding button */
2232 ui_layout_end(C, block, root->layout, x, y);
2233 ui_layout_free(root->layout);
2236 BLI_freelistN(&block->layouts);
2238 /* XXX silly trick, interface_templates.c doesn't get linked
2239 * because it's not used by other files in this module? */
2241 void ui_template_fix_linking();
2242 ui_template_fix_linking();
2246 void uiLayoutSetContextPointer(uiLayout *layout, char *name, PointerRNA *ptr)
2248 uiBlock *block= layout->root->block;
2249 layout->context= CTX_store_add(&block->contexts, name, ptr);