Blender  V2.59
interface_layout.c
Go to the documentation of this file.
00001 /*
00002  * $Id: interface_layout.c 39186 2011-08-08 14:50:10Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * Contributor(s): Blender Foundation 2009.
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00030 #include <limits.h>
00031 #include <math.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <assert.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_screen_types.h"
00039 #include "DNA_armature_types.h"
00040 #include "DNA_userdef_types.h"
00041 
00042 #include "BLI_listbase.h"
00043 #include "BLI_string.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "BKE_context.h"
00047 #include "BKE_global.h"
00048 #include "BKE_idprop.h"
00049 #include "BKE_screen.h"
00050 
00051 #include "RNA_access.h"
00052 
00053 #include "UI_interface.h"
00054 
00055 
00056 #include "WM_api.h"
00057 #include "WM_types.h"
00058 
00059 #include "interface_intern.h"
00060 
00061 /************************ Structs and Defines *************************/
00062 
00063 #define RNA_NO_INDEX    -1
00064 #define RNA_ENUM_VALUE  -2
00065 
00066 #define EM_SEPR_X               6
00067 #define EM_SEPR_Y               6
00068 
00069 /* uiLayoutRoot */
00070 
00071 typedef struct uiLayoutRoot {
00072         struct uiLayoutRoot *next, *prev;
00073 
00074         int type;
00075         int opcontext;
00076 
00077         int emw, emh;
00078 
00079         uiMenuHandleFunc handlefunc;
00080         void *argv;
00081 
00082         uiStyle *style;
00083         uiBlock *block;
00084         uiLayout *layout;
00085 } uiLayoutRoot;
00086 
00087 /* Item */
00088 
00089 typedef enum uiItemType {
00090         ITEM_BUTTON,
00091 
00092         ITEM_LAYOUT_ROW,
00093         ITEM_LAYOUT_COLUMN,
00094         ITEM_LAYOUT_COLUMN_FLOW,
00095         ITEM_LAYOUT_ROW_FLOW,
00096         ITEM_LAYOUT_BOX,
00097         ITEM_LAYOUT_ABSOLUTE,
00098         ITEM_LAYOUT_SPLIT,
00099         ITEM_LAYOUT_OVERLAP,
00100 
00101         ITEM_LAYOUT_ROOT
00102 #if 0
00103         TEMPLATE_COLUMN_FLOW,
00104         TEMPLATE_SPLIT,
00105         TEMPLATE_BOX,
00106 
00107         TEMPLATE_HEADER,
00108         TEMPLATE_HEADER_ID
00109 #endif
00110 } uiItemType;
00111 
00112 typedef struct uiItem {
00113         void *next, *prev;
00114         uiItemType type;
00115         int flag;
00116 } uiItem;
00117 
00118 typedef struct uiButtonItem {
00119         uiItem item;
00120         uiBut *but;
00121 } uiButtonItem;
00122 
00123 struct uiLayout {
00124         uiItem item;
00125 
00126         uiLayoutRoot *root;
00127         bContextStore *context;
00128         ListBase items;
00129 
00130         int x, y, w, h;
00131         float scale[2];
00132         short space;
00133         char align;
00134         char active;
00135         char enabled;
00136         char redalert;
00137         char keepaspect;
00138         char alignment;
00139 };
00140 
00141 typedef struct uiLayoutItemFlow {
00142         uiLayout litem;
00143         int number;
00144         int totcol;
00145 } uiLayoutItemFlow;
00146 
00147 typedef struct uiLayoutItemBx {
00148         uiLayout litem;
00149         uiBut *roundbox;
00150 } uiLayoutItemBx;
00151 
00152 typedef struct uiLayoutItemSplit {
00153         uiLayout litem;
00154         float percentage;
00155 } uiLayoutItemSplit;
00156 
00157 typedef struct uiLayoutItemRoot {
00158         uiLayout litem;
00159 } uiLayoutItemRoot;
00160 
00161 /************************** Item ***************************/
00162 
00163 static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_NAME_STR])
00164 {
00165         int len= strlen(name);
00166 
00167         if(len != 0 && len+1 < UI_MAX_NAME_STR) {
00168                 BLI_strncpy(namestr, name, UI_MAX_NAME_STR);
00169                 namestr[len]= ':';
00170                 namestr[len+1]= '\0';
00171                 return namestr;
00172         }
00173 
00174         return name;
00175 }
00176 
00177 static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
00178 {
00179         /* available == 0 is unlimited */
00180         if(available == 0)
00181                 return item;
00182         
00183         if(offset)
00184                 *offset= 0;
00185         
00186         if(all > available) {
00187                 /* contents is bigger than available space */
00188                 if(last)
00189                         return available-pos;
00190                 else
00191                         return (item*available)/all;
00192         }
00193         else {
00194                 /* contents is smaller or equal to available space */
00195                 if(alignment == UI_LAYOUT_ALIGN_EXPAND) {
00196                         if(last)
00197                                 return available-pos;
00198                         else
00199                                 return (item*available)/all;
00200                 }
00201                 else
00202                         return item;
00203         }
00204 }
00205 
00206 /* variable button size in which direction? */
00207 #define UI_ITEM_VARY_X  1
00208 #define UI_ITEM_VARY_Y  2
00209 
00210 static int ui_layout_vary_direction(uiLayout *layout)
00211 {
00212         return (layout->root->type == UI_LAYOUT_HEADER || layout->alignment != UI_LAYOUT_ALIGN_EXPAND)? UI_ITEM_VARY_X: UI_ITEM_VARY_Y;
00213 }
00214 
00215 /* estimated size of text + icon */
00216 static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, int compact)
00217 {
00218         int variable = ui_layout_vary_direction(layout) == UI_ITEM_VARY_X;
00219 
00220         if(icon && !name[0])
00221                 return UI_UNIT_X; /* icon only */
00222         else if(icon)
00223                 return (variable)? UI_GetStringWidth(name) + (compact? 5: 10) + UI_UNIT_X: 10*UI_UNIT_X; /* icon + text */
00224         else
00225                 return (variable)? UI_GetStringWidth(name) + (compact? 5: 10) + UI_UNIT_X: 10*UI_UNIT_X; /* text only */
00226 }
00227 
00228 static void ui_item_size(uiItem *item, int *r_w, int *r_h)
00229 {
00230         if(item->type == ITEM_BUTTON) {
00231                 uiButtonItem *bitem= (uiButtonItem*)item;
00232 
00233                 if(r_w) *r_w= bitem->but->x2 - bitem->but->x1;
00234                 if(r_h) *r_h= bitem->but->y2 - bitem->but->y1;
00235         }
00236         else {
00237                 uiLayout *litem= (uiLayout*)item;
00238 
00239                 if(r_w) *r_w= litem->w;
00240                 if(r_h) *r_h= litem->h;
00241         }
00242 }
00243 
00244 static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
00245 {
00246         if(item->type == ITEM_BUTTON) {
00247                 uiButtonItem *bitem= (uiButtonItem*)item;
00248 
00249                 if(r_x) *r_x= bitem->but->x1;
00250                 if(r_y) *r_y= bitem->but->y1;
00251         }
00252         else {
00253                 if(r_x) *r_x= 0;
00254                 if(r_y) *r_y= 0;
00255         }
00256 }
00257 
00258 static void ui_item_position(uiItem *item, int x, int y, int w, int h)
00259 {
00260         if(item->type == ITEM_BUTTON) {
00261                 uiButtonItem *bitem= (uiButtonItem*)item;
00262 
00263                 bitem->but->x1= x;
00264                 bitem->but->y1= y;
00265                 bitem->but->x2= x+w;
00266                 bitem->but->y2= y+h;
00267                 
00268                 ui_check_but(bitem->but); /* for strlen */
00269         }
00270         else {
00271                 uiLayout *litem= (uiLayout*)item;
00272 
00273                 litem->x= x;
00274                 litem->y= y+h;
00275                 litem->w= w;
00276                 litem->h= h;
00277         }
00278 }
00279 
00280 /******************** Special RNA Items *********************/
00281 
00282 static int ui_layout_local_dir(uiLayout *layout)
00283 {
00284         switch(layout->item.type) {
00285                 case ITEM_LAYOUT_ROW:
00286                 case ITEM_LAYOUT_ROOT:
00287                 case ITEM_LAYOUT_OVERLAP:
00288                         return UI_LAYOUT_HORIZONTAL;
00289                 case ITEM_LAYOUT_COLUMN:
00290                 case ITEM_LAYOUT_COLUMN_FLOW:
00291                 case ITEM_LAYOUT_SPLIT:
00292                 case ITEM_LAYOUT_ABSOLUTE:
00293                 case ITEM_LAYOUT_BOX:
00294                 default:
00295                         return UI_LAYOUT_VERTICAL;
00296         }
00297 }
00298 
00299 static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, int align)
00300 {
00301         uiLayout *sub;
00302 
00303         if(ui_layout_local_dir(test) == UI_LAYOUT_HORIZONTAL)
00304                 sub= uiLayoutRow(layout, align);
00305         else
00306                 sub= uiLayoutColumn(layout, align);
00307         
00308         sub->space= 0;
00309         return sub;
00310 }
00311 
00312 static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
00313 {
00314         wmWindow *win= CTX_wm_window(C);
00315         uiBut *but= arg_but, *cbut;
00316         PointerRNA *ptr= &but->rnapoin;
00317         PropertyRNA *prop= but->rnaprop;
00318         int i, index= GET_INT_FROM_POINTER(arg_index);
00319         int shift= win->eventstate->shift;
00320         int len= RNA_property_array_length(ptr, prop);
00321 
00322         if(!shift) {
00323                 RNA_property_boolean_set_index(ptr, prop, index, 1);
00324 
00325                 for(i=0; i<len; i++)
00326                         if(i != index)
00327                                 RNA_property_boolean_set_index(ptr, prop, i, 0);
00328 
00329                 RNA_property_update(C, ptr, prop);
00330 
00331                 for(cbut=but->block->buttons.first; cbut; cbut=cbut->next)
00332                         ui_check_but(cbut);
00333         }
00334 }
00335 
00336 /* create buttons for an item with an RNA array */
00337 static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int h, int expand, int slider, int toggle, int icon_only)
00338 {
00339         uiStyle *style= layout->root->style;
00340         uiBut *but;
00341         PropertyType type;
00342         PropertySubType subtype;
00343         uiLayout *sub;
00344         int a, b;
00345 
00346         /* retrieve type and subtype */
00347         type= RNA_property_type(prop);
00348         subtype= RNA_property_subtype(prop);
00349 
00350         sub= ui_item_local_sublayout(layout, layout, 1);
00351         uiBlockSetCurLayout(block, sub);
00352 
00353         /* create label */
00354         if(name[0])
00355                 uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
00356 
00357         /* create buttons */
00358         if(type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
00359                 /* special check for layer layout */
00360                 int butw, buth, unit;
00361                 int cols= (len >= 20)? 2: 1;
00362                 int colbuts= len/(2*cols);
00363                 int layer_used= 0;
00364 
00365                 uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, 0));
00366 
00367                 unit= UI_UNIT_X*0.75;
00368                 butw= unit;
00369                 buth= unit;
00370                 
00371                 if(ptr->type == &RNA_Armature) {
00372                         bArmature *arm= (bArmature *)ptr->data;
00373                         layer_used= arm->layer_used;
00374                 }
00375 
00376                 for(b=0; b<cols; b++) {
00377                         uiBlockBeginAlign(block);
00378 
00379                         for(a=0; a<colbuts; a++) {
00380                                 if(layer_used & (1<<(a+b*colbuts))) icon= ICON_LAYER_USED;
00381                                 else icon= ICON_BLANK1;
00382                                         
00383                                 but= uiDefAutoButR(block, ptr, prop, a+b*colbuts, "", icon, x + butw*a, y+buth, butw, buth);
00384                                 if(subtype == PROP_LAYER_MEMBER)
00385                                         uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(a+b*colbuts));
00386                         }
00387                         for(a=0; a<colbuts; a++) {
00388                                 if(layer_used & (1<<(a+len/2+b*colbuts))) icon= ICON_LAYER_USED;
00389                                 else icon= ICON_BLANK1;
00390                                 
00391                                 but= uiDefAutoButR(block, ptr, prop, a+len/2+b*colbuts, "", icon, x + butw*a, y, butw, buth);
00392                                 if(subtype == PROP_LAYER_MEMBER)
00393                                         uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(a+len/2+b*colbuts));
00394                         }
00395                         uiBlockEndAlign(block);
00396 
00397                         x += colbuts*butw + style->buttonspacex;
00398                 }
00399         }
00400         else if(subtype == PROP_MATRIX) {
00401                 int totdim, dim_size[3];        /* 3 == RNA_MAX_ARRAY_DIMENSION */
00402                 int row, col;
00403 
00404                 uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, 1));
00405 
00406                 totdim= RNA_property_array_dimension(ptr, prop, dim_size);
00407                 if (totdim != 2) return;        /* only 2D matrices supported in UI so far */
00408                 
00409                 w /= dim_size[0];
00410                 h /= dim_size[1];
00411 
00412                 for(a=0; a<len; a++) {
00413                         col= a % dim_size[0];
00414                         row= a / dim_size[0];
00415                         
00416                         but= uiDefAutoButR(block, ptr, prop, a, "", ICON_NONE, x + w*col, y+(dim_size[1]*UI_UNIT_Y)-(row*UI_UNIT_Y), w, UI_UNIT_Y);
00417                         if(slider && but->type==NUM)
00418                                 but->type= NUMSLI;
00419                 }
00420         }
00421         else if(subtype == PROP_DIRECTION) {
00422                 uiDefButR_prop(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X*3, UI_UNIT_Y*3, ptr, prop, 0, 0, 0, -1, -1, NULL);
00423         }
00424         else {
00425                 if(ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand)
00426                         uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
00427 
00428                 if(!ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) || expand) {
00429                         /* layout for known array subtypes */
00430                         char str[3];
00431 
00432                         for(a=0; a<len; a++) {
00433                                 str[0]= RNA_property_array_item_char(prop, a);
00434 
00435                                 if(str[0]) {
00436                                         if (icon_only) {
00437                                                 str[0] = '\0';
00438                                         }
00439                                         else if(type == PROP_BOOLEAN) {
00440                                                 str[1]= '\0';
00441                                         }
00442                                         else {
00443                                                 str[1]= ':';
00444                                                 str[2]= '\0';
00445                                         }
00446                                 }
00447 
00448                                 but= uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, w, UI_UNIT_Y);
00449                                 if(slider && but->type==NUM)
00450                                         but->type= NUMSLI;
00451                                 if(toggle && but->type==OPTION)
00452                                         but->type= TOG;
00453                         }
00454                 }
00455         }
00456 
00457         uiBlockSetCurLayout(block, layout);
00458 }
00459 
00460 static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const char *uiname, int h, int icon_only)
00461 {
00462         uiBut *but;
00463         EnumPropertyItem *item;
00464         const char *name;
00465         int a, totitem, itemw, icon, value, free;
00466 
00467         RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
00468 
00469         uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
00470         for(a=0; a<totitem; a++) {
00471                 if(!item[a].identifier[0])
00472                         continue;
00473 
00474                 name= (!uiname || uiname[0])? item[a].name: "";
00475                 icon= item[a].icon;
00476                 value= item[a].value;
00477                 itemw= ui_text_icon_width(block->curlayout, name, icon, 0);
00478 
00479                 if(icon && name[0] && !icon_only)
00480                         but= uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
00481                 else if(icon)
00482                         but= uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
00483                 else
00484                         but= uiDefButR_prop(block, ROW, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
00485 
00486                 if(ui_layout_local_dir(layout) != UI_LAYOUT_HORIZONTAL)
00487                         but->flag |= UI_TEXT_LEFT;
00488         }
00489         uiBlockSetCurLayout(block, layout);
00490 
00491         if(free)
00492                 MEM_freeN(item);
00493 }
00494 
00495 /* callback for keymap item change button */
00496 static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_v))
00497 {
00498         uiBut *but= but_v;
00499 
00500         RNA_boolean_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) != 0);
00501         RNA_boolean_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) != 0);
00502         RNA_boolean_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) != 0);
00503         RNA_boolean_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) != 0);
00504 }
00505 
00506 /* create label + button for RNA property */
00507 static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h, int flag)
00508 {
00509         uiLayout *sub;
00510         uiBut *but=NULL;
00511         PropertyType type;
00512         PropertySubType subtype;
00513         int labelw;
00514 
00515         sub= uiLayoutRow(layout, 0);
00516         uiBlockSetCurLayout(block, sub);
00517 
00518         if(name[0]) {
00519                 /* XXX UI_GetStringWidth is not accurate
00520                 labelw= UI_GetStringWidth(name);
00521                 CLAMP(labelw, w/4, 3*w/4);*/
00522                 labelw= w/3;
00523                 uiDefBut(block, LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
00524                 w= w-labelw;
00525         }
00526 
00527         type= RNA_property_type(prop);
00528         subtype= RNA_property_subtype(prop);
00529 
00530         if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
00531                 uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
00532                 uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
00533 
00534                 /* BUTTONS_OT_file_browse calls uiFileBrowseContextProperty */
00535                 but= uiDefIconButO(block, BUT, subtype==PROP_DIRPATH ?
00536                                        "BUTTONS_OT_directory_browse" :
00537                                        "BUTTONS_OT_file_browse",
00538                                    WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
00539         }
00540         else if(flag & UI_ITEM_R_EVENT) {
00541                 uiDefButR_prop(block, KEYEVT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
00542         }
00543         else if(flag & UI_ITEM_R_FULL_EVENT) {
00544                 if(RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
00545                         char buf[128];
00546 
00547                         WM_keymap_item_to_string(ptr->data, buf, sizeof(buf));
00548 
00549                         but= uiDefButR_prop(block, HOTKEYEVT, 0, buf, x, y, w, h, ptr, prop, 0, 0, 0, -1, -1, NULL);
00550                         uiButSetFunc(but, ui_keymap_but_cb, but, NULL);
00551                         if (flag & UI_ITEM_R_IMMEDIATE)
00552                                 uiButSetFlag(but, UI_BUT_IMMEDIATE);
00553                 }
00554         }
00555         else
00556                 but= uiDefAutoButR(block, ptr, prop, index, (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY))? NULL: "", icon, x, y, w, h);
00557 
00558         uiBlockSetCurLayout(block, layout);
00559         return but;
00560 }
00561 
00562 void uiFileBrowseContextProperty(const bContext *C, PointerRNA *ptr, PropertyRNA **prop)
00563 {
00564         ARegion *ar= CTX_wm_region(C);
00565         uiBlock *block;
00566         uiBut *but, *prevbut;
00567 
00568         memset(ptr, 0, sizeof(*ptr));
00569         *prop= NULL;
00570 
00571         if(!ar)
00572                 return;
00573 
00574         for(block=ar->uiblocks.first; block; block=block->next) {
00575                 for(but=block->buttons.first; but; but= but->next) {
00576                         prevbut= but->prev;
00577 
00578                         /* find the button before the active one */
00579                         if((but->flag & UI_BUT_LAST_ACTIVE) && prevbut && prevbut->rnapoin.data) {
00580                                 if(RNA_property_type(prevbut->rnaprop) == PROP_STRING) {
00581                                         *ptr= prevbut->rnapoin;
00582                                         *prop= prevbut->rnaprop;
00583                                         return;
00584                                 }
00585                         }
00586                 }
00587         }
00588 }
00589 
00590 /********************* Button Items *************************/
00591 
00592 /* disabled item */
00593 static void ui_item_disabled(uiLayout *layout, const char *name)
00594 {
00595         uiBlock *block= layout->root->block;
00596         uiBut *but;
00597         int w;
00598 
00599         uiBlockSetCurLayout(block, layout);
00600 
00601         if(!name)
00602                 name= "";
00603 
00604         w= ui_text_icon_width(layout, name, 0, 0);
00605 
00606         but= uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
00607         but->flag |= UI_BUT_DISABLED;
00608         but->lock = 1;
00609         but->lockstr = "";
00610 }
00611 
00612 /* operator items */
00613 PointerRNA uiItemFullO(uiLayout *layout, const char *opname, const char *name, int icon, IDProperty *properties, int context, int flag)
00614 {
00615         uiBlock *block= layout->root->block;
00616         wmOperatorType *ot= WM_operatortype_find(opname, 1);
00617         uiBut *but;
00618         int w;
00619 
00620         if(!ot) {
00621                 ui_item_disabled(layout, opname);
00622                 RNA_warning("uiItemFullO: unknown operator '%s'\n", opname);
00623                 return PointerRNA_NULL;
00624         }
00625 
00626         if(!name)
00627                 name= ot->name;
00628         if(layout->root->type == UI_LAYOUT_MENU && !icon)
00629                 icon= ICON_BLANK1;
00630 
00631         /* create button */
00632         uiBlockSetCurLayout(block, layout);
00633 
00634         w= ui_text_icon_width(layout, name, icon, 0);
00635 
00636         if (flag & UI_ITEM_R_NO_BG)
00637                 uiBlockSetEmboss(block, UI_EMBOSSN);
00638 
00639         if(icon && name[0])
00640                 but= uiDefIconTextButO(block, BUT, ot->idname, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
00641         else if(icon)
00642                 but= uiDefIconButO(block, BUT, ot->idname, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
00643         else
00644                 but= uiDefButO(block, BUT, ot->idname, context, name, 0, 0, w, UI_UNIT_Y, NULL);
00645 
00646         assert(but->optype != NULL);
00647 
00648         /* text alignment for toolbar buttons */
00649         if((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon)
00650                 but->flag |= UI_TEXT_LEFT;
00651 
00652         if (flag & UI_ITEM_R_NO_BG)
00653                 uiBlockSetEmboss(block, UI_EMBOSS);
00654 
00655         if(layout->redalert)
00656                 uiButSetFlag(but, UI_BUT_REDALERT);
00657 
00658         /* assign properties */
00659         if(properties || (flag & UI_ITEM_O_RETURN_PROPS)) {
00660                 PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
00661 
00662                 if(properties) {
00663                         opptr->data= properties;
00664                 }
00665                 else {
00666                         IDPropertyTemplate val = {0};
00667                         opptr->data= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
00668                 }
00669 
00670                 return *opptr;
00671         }
00672 
00673         return PointerRNA_NULL;
00674 }
00675 
00676 static const char *ui_menu_enumpropname(uiLayout *layout, const char *opname, const char *propname, int retval)
00677 {
00678         wmOperatorType *ot= WM_operatortype_find(opname, 0);
00679         PointerRNA ptr;
00680         PropertyRNA *prop;
00681 
00682         if(!ot || !ot->srna)
00683                 return "";
00684 
00685         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
00686         prop= RNA_struct_find_property(&ptr, propname);
00687 
00688         if(prop) {
00689                 EnumPropertyItem *item;
00690                 int totitem, free;
00691                 const char *name;
00692 
00693                 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
00694                 if(RNA_enum_name(item, retval, &name)) {
00695                         if(free) MEM_freeN(item);
00696                         return name;
00697                 }
00698                 
00699                 if(free)
00700                         MEM_freeN(item);
00701         }
00702 
00703         return "";
00704 }
00705 
00706 void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int icon, const char *propname, int value)
00707 {
00708         PointerRNA ptr;
00709 
00710         WM_operator_properties_create(&ptr, opname);
00711         RNA_enum_set(&ptr, propname, value);
00712 
00713         if(!name)
00714                 name= ui_menu_enumpropname(layout, opname, propname, value);
00715 
00716         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00717 }
00718 
00719 void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, int context, int flag)
00720 {
00721         wmOperatorType *ot= WM_operatortype_find(opname, 1);
00722         PointerRNA ptr;
00723         PropertyRNA *prop;
00724         uiBut *bt;
00725         uiBlock *block= layout->root->block;
00726 
00727         if(!ot || !ot->srna) {
00728                 ui_item_disabled(layout, opname);
00729                 RNA_warning("uiItemsFullEnumO: %s '%s'\n", ot ? "unknown operator" : "operator missing srna", opname);
00730                 return;
00731         }
00732 
00733         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
00734         prop= RNA_struct_find_property(&ptr, propname);
00735 
00736         /* don't let bad properties slip through */
00737         BLI_assert((prop == NULL) || (RNA_property_type(prop) == PROP_ENUM));
00738 
00739         if(prop && RNA_property_type(prop) == PROP_ENUM) {
00740                 EnumPropertyItem *item;
00741                 int totitem, i, free;
00742                 uiLayout *split= uiLayoutSplit(layout, 0, 0);
00743                 uiLayout *column= uiLayoutColumn(split, 0);
00744 
00745                 RNA_property_enum_items(block->evil_C, &ptr, prop, &item, &totitem, &free);
00746 
00747                 for(i=0; i<totitem; i++) {
00748                         if(item[i].identifier[0]) {
00749                                 if(properties) {
00750                                         PointerRNA tptr;
00751 
00752                                         WM_operator_properties_create(&tptr, opname);
00753                                         if(tptr.data) {
00754                                                 IDP_FreeProperty(tptr.data);
00755                                                 MEM_freeN(tptr.data);
00756                                         }
00757                                         tptr.data= IDP_CopyProperty(properties);
00758                                         RNA_enum_set(&tptr, propname, item[i].value);
00759 
00760                                         uiItemFullO(column, opname, item[i].name, item[i].icon, tptr.data, context, flag);
00761                                 }
00762                                 else
00763                                         uiItemEnumO(column, opname, item[i].name, item[i].icon, propname, item[i].value);
00764                         }
00765                         else {
00766                                 if(item[i].name) {
00767                                         if(i != 0) {
00768                                                 column= uiLayoutColumn(split, 0);
00769                                                 /* inconsistent, but menus with labels do not look good flipped */
00770                                                 block->flag |= UI_BLOCK_NO_FLIP;
00771                                         }
00772 
00773                                         uiItemL(column, item[i].name, ICON_NONE);
00774                                         bt= block->buttons.last;
00775                                         bt->flag= UI_TEXT_LEFT;
00776                                 }
00777                                 else /* XXX bug here, collums draw bottom item badly */
00778                                         uiItemS(column);
00779                         }
00780                 }
00781 
00782                 if(free)
00783                         MEM_freeN(item);
00784         }
00785 }
00786 
00787 void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname)
00788 {
00789         uiItemsFullEnumO(layout, opname, propname, NULL, layout->root->opcontext, 0);
00790 }
00791 
00792 /* for use in cases where we have */
00793 void uiItemEnumO_value(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
00794 {
00795         PointerRNA ptr;
00796 
00797         /* for getting the enum */
00798         PropertyRNA *prop;
00799 
00800         WM_operator_properties_create(&ptr, opname);
00801 
00802         /* enum lookup */
00803         if((prop= RNA_struct_find_property(&ptr, propname))) {
00804                 /* pass */
00805         }
00806         else {
00807                 RNA_warning("uiItemEnumO_value: %s.%s not found.\n", RNA_struct_identifier(ptr.type), propname);
00808                 return;
00809         }
00810 
00811         RNA_property_enum_set(&ptr, prop, value);
00812 
00813         /* same as uiItemEnumO */
00814         if(!name)
00815                 name= ui_menu_enumpropname(layout, opname, propname, value);
00816 
00817         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00818 }
00819 
00820 void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value_str)
00821 {
00822         PointerRNA ptr;
00823         
00824         /* for getting the enum */
00825         PropertyRNA *prop;
00826         EnumPropertyItem *item;
00827         int value, free;
00828 
00829         WM_operator_properties_create(&ptr, opname);
00830         
00831         /* enum lookup */
00832         if((prop= RNA_struct_find_property(&ptr, propname))) {
00833                 RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
00834                 if(item==NULL || RNA_enum_value_from_id(item, value_str, &value)==0) {
00835                         if(free) MEM_freeN(item);
00836                         RNA_warning("uiItemEnumO_string: %s.%s, enum %s not found.\n", RNA_struct_identifier(ptr.type), propname, value_str);
00837                         return;
00838                 }
00839 
00840                 if(free)
00841                         MEM_freeN(item);
00842         }
00843         else {
00844                 RNA_warning("uiItemEnumO_string: %s.%s not found.\n", RNA_struct_identifier(ptr.type), propname);
00845                 return;
00846         }
00847         
00848         RNA_property_enum_set(&ptr, prop, value);
00849         
00850         /* same as uiItemEnumO */
00851         if(!name)
00852                 name= ui_menu_enumpropname(layout, opname, propname, value);
00853 
00854         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00855 }
00856 
00857 void uiItemBooleanO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
00858 {
00859         PointerRNA ptr;
00860 
00861         WM_operator_properties_create(&ptr, opname);
00862         RNA_boolean_set(&ptr, propname, value);
00863 
00864         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00865 }
00866 
00867 void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
00868 {
00869         PointerRNA ptr;
00870 
00871         WM_operator_properties_create(&ptr, opname);
00872         RNA_int_set(&ptr, propname, value);
00873 
00874         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00875 }
00876 
00877 void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, float value)
00878 {
00879         PointerRNA ptr;
00880 
00881         WM_operator_properties_create(&ptr, opname);
00882         RNA_float_set(&ptr, propname, value);
00883 
00884         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00885 }
00886 
00887 void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value)
00888 {
00889         PointerRNA ptr;
00890 
00891         WM_operator_properties_create(&ptr, opname);
00892         RNA_string_set(&ptr, propname, value);
00893 
00894         uiItemFullO(layout, opname, name, icon, ptr.data, layout->root->opcontext, 0);
00895 }
00896 
00897 void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
00898 {
00899         uiItemFullO(layout, opname, name, icon, NULL, layout->root->opcontext, 0);
00900 }
00901 
00902 /* RNA property items */
00903 
00904 static void ui_item_rna_size(uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int icon_only, int *r_w, int *r_h)
00905 {
00906         PropertyType type;
00907         PropertySubType subtype;
00908         int len, w, h;
00909 
00910         /* arbitrary extended width by type */
00911         type= RNA_property_type(prop);
00912         subtype= RNA_property_subtype(prop);
00913         len= RNA_property_array_length(ptr, prop);
00914 
00915         if(ELEM3(type, PROP_STRING, PROP_POINTER, PROP_ENUM) && !name[0] && !icon_only)
00916                 name= "non-empty text";
00917         else if(type == PROP_BOOLEAN && !name[0] && !icon_only)
00918                 icon= ICON_DOT;
00919 
00920         w= ui_text_icon_width(layout, name, icon, 0);
00921         h= UI_UNIT_Y;
00922 
00923         /* increase height for arrays */
00924         if(index == RNA_NO_INDEX && len > 0) {
00925                 if(!name[0] && icon == ICON_NONE)
00926                         h= 0;
00927 
00928                 if(ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER))
00929                         h += 2*UI_UNIT_Y;
00930                 else if(subtype == PROP_MATRIX)
00931                         h += ceil(sqrt(len))*UI_UNIT_Y;
00932                 else
00933                         h += len*UI_UNIT_Y;
00934         }
00935         else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
00936                 if(type == PROP_BOOLEAN && name[0])
00937                         w += UI_UNIT_X/5;
00938                 else if(type == PROP_ENUM)
00939                         w += UI_UNIT_X/4;
00940                 else if(type == PROP_FLOAT || type == PROP_INT)
00941                         w += UI_UNIT_X*3;
00942         }
00943 
00944         *r_w= w;
00945         *r_h= h;
00946 }
00947 
00948 void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon)
00949 {
00950         uiBlock *block= layout->root->block;
00951         uiBut *but;
00952         PropertyType type;
00953         char namestr[UI_MAX_NAME_STR];
00954         int len, w, h, slider, toggle, expand, icon_only, no_bg;
00955 
00956         uiBlockSetCurLayout(block, layout);
00957 
00958         /* retrieve info */
00959         type= RNA_property_type(prop);
00960         len= RNA_property_array_length(ptr, prop);
00961 
00962         /* set name and icon */
00963         if(!name)
00964                 name= RNA_property_ui_name(prop);
00965         if(icon == ICON_NONE)
00966                 icon= RNA_property_ui_icon(prop);
00967         
00968         if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER))
00969                 name= ui_item_name_add_colon(name, namestr);
00970         else if(type == PROP_BOOLEAN && len && index == RNA_NO_INDEX)
00971                 name= ui_item_name_add_colon(name, namestr);
00972         else if(type == PROP_ENUM && index != RNA_ENUM_VALUE)
00973                 name= ui_item_name_add_colon(name, namestr);
00974 
00975         if(layout->root->type == UI_LAYOUT_MENU) {
00976                 if(type == PROP_BOOLEAN)
00977                         icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
00978                 else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
00979                         int enum_value= RNA_property_enum_get(ptr, prop);
00980                         if(RNA_property_flag(prop) & PROP_ENUM_FLAG) {
00981                                 icon= (enum_value & value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
00982                         }
00983                         else {
00984                                 icon= (enum_value == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
00985                         }
00986                 }
00987         }
00988 
00989         slider= (flag & UI_ITEM_R_SLIDER);
00990         toggle= (flag & UI_ITEM_R_TOGGLE);
00991         expand= (flag & UI_ITEM_R_EXPAND);
00992         icon_only= (flag & UI_ITEM_R_ICON_ONLY);
00993         no_bg= (flag & UI_ITEM_R_NO_BG);
00994 
00995         /* get size */
00996         ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, &w, &h);
00997 
00998         if (no_bg)
00999                 uiBlockSetEmboss(block, UI_EMBOSSN);
01000         
01001         /* array property */
01002         if(index == RNA_NO_INDEX && len > 0)
01003                 ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand, slider, toggle, icon_only);
01004         /* enum item */
01005         else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) {
01006                 const char *identifier= RNA_property_identifier(prop);
01007 
01008                 if(icon && name[0] && !icon_only)
01009                         uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
01010                 else if(icon)
01011                         uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL);
01012                 else
01013                         uiDefButR_prop(block, ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
01014         }
01015         /* expanded enum */
01016         else if(type == PROP_ENUM && (expand || RNA_property_flag(prop) & PROP_ENUM_FLAG))
01017                 ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only);
01018         /* property with separate label */
01019         else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
01020                 but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h, flag);
01021                 ui_but_add_search(but, ptr, prop, NULL, NULL);
01022                 
01023                 if(layout->redalert)
01024                         uiButSetFlag(but, UI_BUT_REDALERT);
01025         }
01026         /* single button */
01027         else {
01028                 but= uiDefAutoButR(block, ptr, prop, index, name, icon, 0, 0, w, h);
01029 
01030                 if(slider && but->type==NUM)
01031                         but->type= NUMSLI;
01032 
01033                 if(toggle && but->type==OPTION)
01034                         but->type= TOG;
01035                 
01036                 if(layout->redalert)
01037                         uiButSetFlag(but, UI_BUT_REDALERT);
01038         }
01039         
01040         if (no_bg)
01041                 uiBlockSetEmboss(block, UI_EMBOSS);
01042 }
01043 
01044 void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
01045 {
01046         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01047 
01048         if(!prop) {
01049                 ui_item_disabled(layout, propname);
01050                 RNA_warning("uiItemR: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01051                 return;
01052         }
01053 
01054         uiItemFullR(layout, ptr, prop, RNA_NO_INDEX, 0, flag, name, icon);
01055 }
01056 
01057 void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value)
01058 {
01059         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01060 
01061         if(!prop || RNA_property_type(prop) != PROP_ENUM) {
01062                 ui_item_disabled(layout, propname);
01063                 RNA_warning("uiItemEnumR: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01064                 return;
01065         }
01066 
01067         uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
01068 }
01069 
01070 void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon)
01071 {
01072         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01073         EnumPropertyItem *item;
01074         int ivalue, a, free;
01075 
01076         if(!prop || RNA_property_type(prop) != PROP_ENUM) {
01077                 ui_item_disabled(layout, propname);
01078                 RNA_warning("uiItemEnumR_string: enum property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01079                 return;
01080         }
01081 
01082         RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
01083 
01084         if(!RNA_enum_value_from_id(item, value, &ivalue)) {
01085                 if(free) MEM_freeN(item);
01086                 ui_item_disabled(layout, propname);
01087                 RNA_warning("uiItemEnumR: enum property value not found: %s\n", value);
01088                 return;
01089         }
01090 
01091         for(a=0; item[a].identifier; a++) {
01092                 if(item[a].value == ivalue) {
01093                         uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, name ? name : item[a].name, icon ? icon : item[a].icon);
01094                         break;
01095                 }
01096         }
01097 
01098         if(free)
01099                 MEM_freeN(item);
01100 }
01101 
01102 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname)
01103 {
01104         PropertyRNA *prop;
01105         uiBlock *block= layout->root->block;
01106         uiBut *bt;
01107 
01108         prop= RNA_struct_find_property(ptr, propname);
01109 
01110         if(!prop) {
01111                 ui_item_disabled(layout, propname);
01112                 RNA_warning("uiItemsEnumR: enum property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01113                 return;
01114         }
01115 
01116         if(RNA_property_type(prop) != PROP_ENUM) {
01117                 RNA_warning("uiItemsEnumR: not an enum property: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01118                 return;
01119         }
01120         else {
01121                 EnumPropertyItem *item;
01122                 int totitem, i, free;
01123                 uiLayout *split= uiLayoutSplit(layout, 0, 0);
01124                 uiLayout *column= uiLayoutColumn(split, 0);
01125 
01126                 RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
01127 
01128                 for(i=0; i<totitem; i++) {
01129                         if(item[i].identifier[0]) {
01130                                 uiItemEnumR(column, item[i].name, ICON_NONE, ptr, propname, item[i].value);
01131                         }
01132                         else {
01133                                 if(item[i].name) {
01134                                         if(i != 0) {
01135                                                 column= uiLayoutColumn(split, 0);
01136                                                 /* inconsistent, but menus with labels do not look good flipped */
01137                                                 block->flag |= UI_BLOCK_NO_FLIP;
01138                                         }
01139 
01140                                         uiItemL(column, item[i].name, ICON_NONE);
01141                                         bt= block->buttons.last;
01142                                         bt->flag= UI_TEXT_LEFT;
01143                                 }
01144                                 else
01145                                         uiItemS(column);
01146                         }
01147                 }
01148 
01149                 if(free)
01150                         MEM_freeN(item);
01151         }
01152 }
01153 
01154 /* Pointer RNA button with search */
01155 
01156 typedef struct CollItemSearch {
01157         struct CollItemSearch *next, *prev;
01158         char *name;
01159         int index;
01160         int iconid;
01161 } CollItemSearch;
01162 
01163 static int sort_search_items_list(void *a, void *b)
01164 {
01165         CollItemSearch *cis1 = (CollItemSearch *)a;
01166         CollItemSearch *cis2 = (CollItemSearch *)b;
01167         
01168         if (BLI_strcasecmp(cis1->name, cis2->name)>0)
01169                 return 1;
01170         else
01171                 return 0;
01172 }
01173 
01174 static void rna_search_cb(const struct bContext *C, void *arg_but, const char *str, uiSearchItems *items)
01175 {
01176         uiBut *but= arg_but;
01177         char *name;
01178         int i=0, iconid=0, flag= RNA_property_flag(but->rnaprop);
01179         ListBase *items_list= MEM_callocN(sizeof(ListBase), "items_list");
01180         CollItemSearch *cis;
01181         const int skip_filter= !but->changed;
01182 
01183         /* build a temporary list of relevant items first */
01184         RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
01185                 if(flag & PROP_ID_SELF_CHECK)
01186                         if(itemptr.data == but->rnapoin.id.data)
01187                                 continue;
01188 
01189                 /* use filter */
01190                 if(RNA_property_type(but->rnaprop)==PROP_POINTER) {
01191                         if(RNA_property_pointer_poll(&but->rnapoin, but->rnaprop, &itemptr)==0)
01192                                 continue;
01193                 }
01194 
01195                 if(itemptr.type && RNA_struct_is_ID(itemptr.type)) {
01196                         ID *id= itemptr.data;
01197                         char name_ui[32];
01198 
01199 #if 0           /* this name is used for a string comparison and can't be modified, TODO */
01200                         name_uiprefix_id(name_ui, id);
01201 #else
01202                         strcpy(name_ui, id->name+2);
01203 #endif
01204                         name= BLI_strdup(name_ui);
01205                         iconid= ui_id_icon_get((bContext*)C, id, 1);
01206                 }
01207                 else {
01208                         name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
01209                         iconid = 0;
01210                 }
01211 
01212                 if(name) {
01213                         if(skip_filter || BLI_strcasestr(name, str)) {
01214                                 cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
01215                                 cis->name = MEM_dupallocN(name);
01216                                 cis->index = i;
01217                                 cis->iconid = iconid;
01218                                 BLI_addtail(items_list, cis);
01219                         }
01220                         MEM_freeN(name);
01221                 }                       
01222 
01223                 i++;
01224         }
01225         RNA_PROP_END;
01226         
01227         BLI_sortlist(items_list, sort_search_items_list);
01228         
01229         /* add search items from temporary list */
01230         for (cis=items_list->first; cis; cis=cis->next) {
01231                 if (!uiSearchItemAdd(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
01232                         break;
01233                 }
01234         }
01235 
01236         for (cis=items_list->first; cis; cis=cis->next) {
01237                 MEM_freeN(cis->name);
01238         }
01239         BLI_freelistN(items_list);
01240         MEM_freeN(items_list);
01241 }
01242 
01243 static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
01244 {
01245         StructRNA *srna;
01246 
01247         /* look for collection property in Main */
01248         RNA_main_pointer_create(G.main, ptr);
01249 
01250         *prop= NULL;
01251 
01252         RNA_STRUCT_BEGIN(ptr, iprop) {
01253                 /* if it's a collection and has same pointer type, we've got it */
01254                 if(RNA_property_type(iprop) == PROP_COLLECTION) {
01255                         srna= RNA_property_pointer_type(ptr, iprop);
01256 
01257                         if(ptype == srna) {
01258                                 *prop= iprop;
01259                                 break;
01260                         }
01261                 }
01262         }
01263         RNA_STRUCT_END;
01264 }
01265 
01266 void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
01267 {
01268         StructRNA *ptype;
01269         PointerRNA sptr;
01270 
01271         /* for ID's we do automatic lookup */
01272         if(!searchprop) {
01273                 if(RNA_property_type(prop) == PROP_POINTER) {
01274                         ptype= RNA_property_pointer_type(ptr, prop);
01275                         search_id_collection(ptype, &sptr, &searchprop);
01276                         searchptr= &sptr;
01277                 }
01278         }
01279 
01280         /* turn button into search button */
01281         if(searchprop) {
01282                 but->type= SEARCH_MENU;
01283                 but->hardmax= MAX2(but->hardmax, 256);
01284                 but->rnasearchpoin= *searchptr;
01285                 but->rnasearchprop= searchprop;
01286                 but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
01287 
01288                 uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
01289         }
01290 }
01291 
01292 void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
01293 {
01294         PropertyRNA *prop, *searchprop;
01295         PropertyType type;
01296         uiBut *but;
01297         uiBlock *block;
01298         StructRNA *icontype;
01299         int w, h;
01300         
01301         /* validate arguments */
01302         prop= RNA_struct_find_property(ptr, propname);
01303 
01304         if(!prop) {
01305                 RNA_warning("uiItemPointerR: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01306                 return;
01307         }
01308         
01309         type= RNA_property_type(prop);
01310         if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
01311                 RNA_warning("uiItemPointerR: property %s must be a pointer or string.\n", propname);
01312                 return;
01313         }
01314 
01315         searchprop= RNA_struct_find_property(searchptr, searchpropname);
01316 
01317 
01318         if(!searchprop) {
01319                 RNA_warning("uiItemPointerR: search collection property not found: %s.%s\n", RNA_struct_identifier(ptr->type), searchpropname);
01320                 return;
01321         }
01322         else if (RNA_property_type(searchprop) != PROP_COLLECTION) {
01323                 RNA_warning("uiItemPointerR: search collection property is not a collection type: %s.%s\n", RNA_struct_identifier(ptr->type), searchpropname);
01324                 return;
01325         }
01326 
01327         /* get icon & name */
01328         if(icon==ICON_NONE) {
01329                 if(type == PROP_POINTER)
01330                         icontype= RNA_property_pointer_type(ptr, prop);
01331                 else
01332                         icontype= RNA_property_pointer_type(searchptr, searchprop);
01333 
01334                 icon= RNA_struct_ui_icon(icontype);
01335         }
01336         if(!name)
01337                 name= RNA_property_ui_name(prop);
01338 
01339         /* create button */
01340         block= uiLayoutGetBlock(layout);
01341 
01342         ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, &w, &h);
01343         but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0);
01344 
01345         ui_but_add_search(but, ptr, prop, searchptr, searchprop);
01346 }
01347 
01348 /* menu item */
01349 static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
01350 {
01351         MenuType *mt= (MenuType*)arg_mt;
01352         Menu menu = {0};
01353 
01354         menu.type= mt;
01355         menu.layout= layout;
01356         mt->draw(C, &menu);
01357 }
01358 
01359 static void ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN)
01360 {
01361         uiBlock *block= layout->root->block;
01362         uiBut *but;
01363         int w, h;
01364 
01365         uiBlockSetCurLayout(block, layout);
01366 
01367         if(layout->root->type == UI_LAYOUT_HEADER)
01368                 uiBlockSetEmboss(block, UI_EMBOSS);
01369 
01370         if(!name)
01371                 name= "";
01372         if(layout->root->type == UI_LAYOUT_MENU && !icon)
01373                 icon= ICON_BLANK1;
01374 
01375         w= ui_text_icon_width(layout, name, icon, 1);
01376         h= UI_UNIT_Y;
01377 
01378         if(layout->root->type == UI_LAYOUT_HEADER) /* ugly .. */
01379                 w -= 10;
01380 
01381         if(name[0] && icon)
01382                 but= uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, "");
01383         else if(icon)
01384                 but= uiDefIconMenuBut(block, func, arg, icon, 0, 0, w, h, "");
01385         else
01386                 but= uiDefMenuBut(block, func, arg, name, 0, 0, w, h, "");
01387 
01388         if(argN) { /* ugly .. */
01389                 but->poin= (char*)but;
01390                 but->func_argN= argN;
01391         }
01392 
01393         if(layout->root->type == UI_LAYOUT_HEADER)
01394                 uiBlockSetEmboss(block, UI_EMBOSS);
01395         else if(layout->root->type == UI_LAYOUT_PANEL) {
01396                 but->type= MENU;
01397                 but->flag |= UI_TEXT_LEFT;
01398         }
01399 }
01400 
01401 void uiItemM(uiLayout *layout, bContext *UNUSED(C), const char *menuname, const char *name, int icon)
01402 {
01403         MenuType *mt;
01404 
01405         mt= WM_menutype_find(menuname, FALSE);
01406 
01407         if(mt==NULL) {
01408                 RNA_warning("uiItemM: not found %s\n", menuname);
01409                 return;
01410         }
01411 
01412         if(!name)
01413                 name= mt->label;
01414         if(layout->root->type == UI_LAYOUT_MENU && !icon)
01415                 icon= ICON_BLANK1;
01416 
01417         ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL);
01418 }
01419 
01420 /* label item */
01421 static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
01422 {
01423         uiBlock *block= layout->root->block;
01424         uiBut *but;
01425         int w;
01426 
01427         uiBlockSetCurLayout(block, layout);
01428 
01429         if(!name)
01430                 name= "";
01431         if(layout->root->type == UI_LAYOUT_MENU && !icon)
01432                 icon= ICON_BLANK1;
01433 
01434         w= ui_text_icon_width(layout, name, icon, 0);
01435 
01436         if(icon && name[0])
01437                 but= uiDefIconTextBut(block, LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
01438         else if(icon)
01439                 but= uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
01440         else
01441                 but= uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
01442         
01443         return but;
01444 }
01445 
01446 void uiItemL(uiLayout *layout, const char *name, int icon)
01447 {
01448         uiItemL_(layout, name, icon);
01449 }
01450 
01451 void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
01452 {
01453         uiBut *but= uiItemL_(layout, name, icon);
01454 
01455         if(ptr && ptr->type)
01456                 if(RNA_struct_is_ID(ptr->type))
01457                         uiButSetDragID(but, ptr->id.data);
01458 }
01459 
01460 
01461 /* value item */
01462 void uiItemV(uiLayout *layout, const char *name, int icon, int argval)
01463 {
01464         /* label */
01465         uiBlock *block= layout->root->block;
01466         float *retvalue= (block->handle)? &block->handle->retvalue: NULL;
01467         int w;
01468 
01469         uiBlockSetCurLayout(block, layout);
01470 
01471         if(!name)
01472                 name= "";
01473         if(layout->root->type == UI_LAYOUT_MENU && !icon)
01474                 icon= ICON_BLANK1;
01475 
01476         w= ui_text_icon_width(layout, name, icon, 0);
01477 
01478         if(icon && name[0])
01479                 uiDefIconTextButF(block, BUTM, 0, icon, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
01480         else if(icon)
01481                 uiDefIconButF(block, BUTM, 0, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
01482         else
01483                 uiDefButF(block, BUTM, 0, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, argval, "");
01484 }
01485 
01486 /* separator item */
01487 void uiItemS(uiLayout *layout)
01488 {
01489         uiBlock *block= layout->root->block;
01490 
01491         uiBlockSetCurLayout(block, layout);
01492         uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
01493 }
01494 
01495 /* level items */
01496 void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg)
01497 {
01498         if(!func)
01499                 return;
01500 
01501         ui_item_menu(layout, name, icon, func, arg, NULL);
01502 }
01503 
01504 typedef struct MenuItemLevel {
01505         int opcontext;
01506         /* dont use pointers to the strings because python can dynamically
01507          * allocate strings and free before the menu draws, see [#27304] */
01508         char opname[OP_MAX_TYPENAME];
01509         char propname[MAX_IDPROP_NAME];
01510         PointerRNA rnapoin;
01511 } MenuItemLevel;
01512 
01513 static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
01514 {
01515         MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
01516 
01517         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
01518         uiItemsEnumO(layout, lvl->opname, lvl->propname);
01519 }
01520 
01521 void uiItemMenuEnumO(uiLayout *layout, const char *opname, const char *propname, const char *name, int icon)
01522 {
01523         wmOperatorType *ot= WM_operatortype_find(opname, 1);
01524         MenuItemLevel *lvl;
01525 
01526         if(!ot) {
01527                 ui_item_disabled(layout, opname);
01528                 RNA_warning("uiItemMenuEnumO: unknown operator '%s'\n", opname);
01529                 return;
01530         }
01531         if(!ot->srna) {
01532                 ui_item_disabled(layout, opname);
01533                 RNA_warning("uiItemMenuEnumO: operator missing srna '%s'\n", opname);
01534                 return;
01535         }
01536 
01537         if(!name)
01538                 name= ot->name;
01539         if(layout->root->type == UI_LAYOUT_MENU && !icon)
01540                 icon= ICON_BLANK1;
01541 
01542         lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
01543         BLI_strncpy(lvl->opname, opname, sizeof(lvl->opname));
01544         BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
01545         lvl->opcontext= layout->root->opcontext;
01546 
01547         ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl);
01548 }
01549 
01550 static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
01551 {
01552         MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
01553 
01554         uiLayoutSetOperatorContext(layout, lvl->opcontext);
01555         uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
01556 }
01557 
01558 void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
01559 {
01560         MenuItemLevel *lvl;
01561         PropertyRNA *prop;
01562 
01563         prop= RNA_struct_find_property(ptr, propname);
01564         if(!prop) {
01565                 ui_item_disabled(layout, propname);
01566                 RNA_warning("uiItemMenuEnumR: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
01567                 return;
01568         }
01569 
01570         if(!name)
01571                 name= RNA_property_ui_name(prop);
01572         if(layout->root->type == UI_LAYOUT_MENU && !icon)
01573                 icon= ICON_BLANK1;
01574 
01575         lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
01576         lvl->rnapoin= *ptr;
01577         BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
01578         lvl->opcontext= layout->root->opcontext;
01579 
01580         ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl);
01581 }
01582 
01583 /**************************** Layout Items ***************************/
01584 
01585 /* single-row layout */
01586 static void ui_litem_estimate_row(uiLayout *litem)
01587 {
01588         uiItem *item;
01589         int itemw, itemh;
01590 
01591         litem->w= 0;
01592         litem->h= 0;
01593 
01594         for(item=litem->items.first; item; item=item->next) {
01595                 ui_item_size(item, &itemw, &itemh);
01596 
01597                 litem->w += itemw;
01598                 litem->h= MAX2(itemh, litem->h);
01599 
01600                 if(item->next)
01601                         litem->w += litem->space;
01602         }
01603 }
01604 
01605 static int ui_litem_min_width(int itemw)
01606 {
01607         return MIN2(2*UI_UNIT_X, itemw);
01608 }
01609 
01610 static void ui_litem_layout_row(uiLayout *litem)
01611 {
01612         uiItem *item;
01613         int x, y, w, tot, totw, neww, itemw, minw, itemh, offset;
01614         int fixedw, freew, fixedx, freex, flag= 0, lastw= 0;
01615 
01616         /* x= litem->x; */ /* UNUSED */
01617         y= litem->y;
01618         w= litem->w;
01619         totw= 0;
01620         tot= 0;
01621 
01622         for(item=litem->items.first; item; item=item->next) {
01623                 ui_item_size(item, &itemw, &itemh);
01624                 totw += itemw;
01625                 tot++;
01626         }
01627 
01628         if(totw == 0)
01629                 return;
01630         
01631         if(w != 0)
01632                 w -= (tot-1)*litem->space;
01633         fixedw= 0;
01634 
01635         /* keep clamping items to fixed minimum size until all are done */
01636         do {
01637                 freew= 0;
01638                 x= 0;
01639                 flag= 0;
01640 
01641                 for(item=litem->items.first; item; item=item->next) {
01642                         if(item->flag)
01643                                 continue;
01644 
01645                         ui_item_size(item, &itemw, &itemh);
01646                         minw= ui_litem_min_width(itemw);
01647 
01648                         if(w - lastw > 0)
01649                                 neww= ui_item_fit(itemw, x, totw, w-lastw, !item->next, litem->alignment, NULL);
01650                         else
01651                                 neww= 0; /* no space left, all will need clamping to minimum size */
01652 
01653                         x += neww;
01654 
01655                         if((neww < minw || itemw == minw) && w != 0) {
01656                                 /* fixed size */
01657                                 item->flag= 1;
01658                                 fixedw += minw;
01659                                 flag= 1;
01660                                 totw -= itemw;
01661                         }
01662                         else {
01663                                 /* keep free size */
01664                                 item->flag= 0;
01665                                 freew += itemw;
01666                         }
01667                 }
01668 
01669                 lastw= fixedw;
01670         } while(flag);
01671 
01672         freex= 0;
01673         fixedx= 0;
01674         x= litem->x;
01675 
01676         for(item=litem->items.first; item; item=item->next) {
01677                 ui_item_size(item, &itemw, &itemh);
01678                 minw= ui_litem_min_width(itemw);
01679 
01680                 if(item->flag) {
01681                         /* fixed minimum size items */
01682                         itemw= ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL);
01683                         fixedx += itemw;
01684                 }
01685                 else {
01686                         /* free size item */
01687                         itemw= ui_item_fit(itemw, freex, freew, w-fixedw, !item->next, litem->alignment, NULL);
01688                         freex += itemw;
01689                 }
01690 
01691                 /* align right/center */
01692                 offset= 0;
01693                 if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
01694                         if(freew > 0 && freew < w-fixedw)
01695                                 offset= (w - fixedw) - freew;
01696                 }
01697                 else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
01698                         if(freew > 0 && freew < w-fixedw)
01699                                 offset= ((w - fixedw) - freew)/2;
01700                 }
01701 
01702                 /* position item */
01703                 ui_item_position(item, x+offset, y-itemh, itemw, itemh);
01704 
01705                 x += itemw;
01706                 if(item->next)
01707                         x += litem->space;
01708         }
01709 
01710         litem->w= x - litem->x;
01711         litem->h= litem->y - y;
01712         litem->x= x;
01713         litem->y= y;
01714 }
01715 
01716 /* single-column layout */
01717 static void ui_litem_estimate_column(uiLayout *litem)
01718 {
01719         uiItem *item;
01720         int itemw, itemh;
01721 
01722         litem->w= 0;
01723         litem->h= 0;
01724 
01725         for(item=litem->items.first; item; item=item->next) {
01726                 ui_item_size(item, &itemw, &itemh);
01727 
01728                 litem->w= MAX2(litem->w, itemw);
01729                 litem->h += itemh;
01730 
01731                 if(item->next)
01732                         litem->h += litem->space;
01733         }
01734 }
01735 
01736 static void ui_litem_layout_column(uiLayout *litem)
01737 {
01738         uiItem *item;
01739         int itemh, x, y;
01740 
01741         x= litem->x;
01742         y= litem->y;
01743 
01744         for(item=litem->items.first; item; item=item->next) {
01745                 ui_item_size(item, NULL, &itemh);
01746 
01747                 y -= itemh;
01748                 ui_item_position(item, x, y, litem->w, itemh);
01749 
01750                 if(item->next)
01751                         y -= litem->space;
01752         }
01753 
01754         litem->h= litem->y - y;
01755         litem->x= x;
01756         litem->y= y;
01757 }
01758 
01759 /* root layout */
01760 static void ui_litem_estimate_root(uiLayout *UNUSED(litem))
01761 {
01762         /* nothing to do */
01763 }
01764 
01765 static void ui_litem_layout_root(uiLayout *litem)
01766 {
01767         if(litem->root->type == UI_LAYOUT_HEADER)
01768                 ui_litem_layout_row(litem);
01769         else
01770                 ui_litem_layout_column(litem);
01771 }
01772 
01773 /* box layout */
01774 static void ui_litem_estimate_box(uiLayout *litem)
01775 {
01776         uiStyle *style= litem->root->style;
01777 
01778         ui_litem_estimate_column(litem);
01779         litem->w += 2*style->boxspace;
01780         litem->h += style->boxspace;
01781 }
01782 
01783 static void ui_litem_layout_box(uiLayout *litem)
01784 {
01785         uiLayoutItemBx *box= (uiLayoutItemBx*)litem;
01786         uiStyle *style= litem->root->style;
01787         uiBut *but;
01788         int w, h;
01789 
01790         w= litem->w;
01791         h= litem->h;
01792 
01793         litem->x += style->boxspace;
01794 
01795         if(w != 0) litem->w -= 2*style->boxspace;
01796         if(h != 0) litem->h -= 2*style->boxspace;
01797 
01798         ui_litem_layout_column(litem);
01799 
01800         litem->x -= style->boxspace;
01801         litem->y -= style->boxspace;
01802 
01803         if(w != 0) litem->w += 2*style->boxspace;
01804         if(h != 0) litem->h += style->boxspace;
01805 
01806         /* roundbox around the sublayout */
01807         but= box->roundbox;
01808         but->x1= litem->x;
01809         but->y1= litem->y;
01810         but->x2= litem->x+litem->w;
01811         but->y2= litem->y+litem->h;
01812 }
01813 
01814 /* multi-column layout, automatically flowing to the next */
01815 static void ui_litem_estimate_column_flow(uiLayout *litem)
01816 {
01817         uiStyle *style= litem->root->style;
01818         uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
01819         uiItem *item;
01820         int col, x, y, emh, emy, miny, itemw, itemh, maxw=0;
01821         int toth, totitem;
01822 
01823         /* compute max needed width and total height */
01824         toth= 0;
01825         totitem= 0;
01826         for(item=litem->items.first; item; item=item->next) {
01827                 ui_item_size(item, &itemw, &itemh);
01828                 maxw= MAX2(maxw, itemw);
01829                 toth += itemh;
01830                 totitem++;
01831         }
01832 
01833         if(flow->number <= 0) {
01834                 /* auto compute number of columns, not very good */
01835                 if(maxw == 0) {
01836                         flow->totcol= 1;
01837                         return;
01838                 }
01839 
01840                 flow->totcol= MAX2(litem->root->emw/maxw, 1);
01841                 flow->totcol= MIN2(flow->totcol, totitem);
01842         }
01843         else
01844                 flow->totcol= flow->number;
01845 
01846         /* compute sizes */
01847         x= 0;
01848         y= 0;
01849         emy= 0;
01850         miny= 0;
01851 
01852         maxw= 0;
01853         emh= toth/flow->totcol;
01854 
01855         /* create column per column */
01856         col= 0;
01857         for(item=litem->items.first; item; item=item->next) {
01858                 ui_item_size(item, &itemw, &itemh);
01859 
01860                 y -= itemh + style->buttonspacey;
01861                 miny= MIN2(miny, y);
01862                 emy -= itemh;
01863                 maxw= MAX2(itemw, maxw);
01864 
01865                 /* decide to go to next one */
01866                 if(col < flow->totcol-1 && emy <= -emh) {
01867                         x += maxw + litem->space;
01868                         maxw= 0;
01869                         y= 0;
01870                         col++;
01871                 }
01872         }
01873 
01874         litem->w= x;
01875         litem->h= litem->y - miny;
01876 }
01877 
01878 static void ui_litem_layout_column_flow(uiLayout *litem)
01879 {
01880         uiStyle *style= litem->root->style;
01881         uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem;
01882         uiItem *item;
01883         int col, x, y, w, emh, emy, miny, itemw, itemh;
01884         int toth, totitem, offset;
01885 
01886         /* compute max needed width and total height */
01887         toth= 0;
01888         totitem= 0;
01889         for(item=litem->items.first; item; item=item->next) {
01890                 ui_item_size(item, &itemw, &itemh);
01891                 toth += itemh;
01892                 totitem++;
01893         }
01894 
01895         /* compute sizes */
01896         x= litem->x;
01897         y= litem->y;
01898         emy= 0;
01899         miny= 0;
01900 
01901         w= litem->w - (flow->totcol-1)*style->columnspace;
01902         emh= toth/flow->totcol;
01903 
01904         /* create column per column */
01905         col= 0;
01906         for(item=litem->items.first; item; item=item->next) {
01907                 ui_item_size(item, NULL, &itemh);
01908                 itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, col == flow->totcol-1, litem->alignment, &offset);
01909         
01910                 y -= itemh;
01911                 emy -= itemh;
01912                 ui_item_position(item, x+offset, y, itemw, itemh);
01913                 y -= style->buttonspacey;
01914                 miny= MIN2(miny, y);
01915 
01916                 /* decide to go to next one */
01917                 if(col < flow->totcol-1 && emy <= -emh) {
01918                         x += itemw + style->columnspace;
01919                         y= litem->y;
01920                         col++;
01921                 }
01922         }
01923 
01924         litem->h= litem->y - miny;
01925         litem->x= x;
01926         litem->y= miny;
01927 }
01928 
01929 /* free layout */
01930 static void ui_litem_estimate_absolute(uiLayout *litem)
01931 {
01932         uiItem *item;
01933         int itemx, itemy, itemw, itemh, minx, miny;
01934 
01935         minx= 1e6;
01936         miny= 1e6;
01937         litem->w= 0;
01938         litem->h= 0;
01939 
01940         for(item=litem->items.first; item; item=item->next) {
01941                 ui_item_offset(item, &itemx, &itemy);
01942                 ui_item_size(item, &itemw, &itemh);
01943 
01944                 minx= MIN2(minx, itemx);
01945                 miny= MIN2(miny, itemy);
01946 
01947                 litem->w= MAX2(litem->w, itemx+itemw);
01948                 litem->h= MAX2(litem->h, itemy+itemh);
01949         }
01950 
01951         litem->w -= minx;
01952         litem->h -= miny;
01953 }
01954 
01955 static void ui_litem_layout_absolute(uiLayout *litem)
01956 {
01957         uiItem *item;
01958         float scalex=1.0f, scaley=1.0f;
01959         int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
01960 
01961         minx= 1e6;
01962         miny= 1e6;
01963         totw= 0;
01964         toth= 0;
01965 
01966         for(item=litem->items.first; item; item=item->next) {
01967                 ui_item_offset(item, &itemx, &itemy);
01968                 ui_item_size(item, &itemw, &itemh);
01969 
01970                 minx= MIN2(minx, itemx);
01971                 miny= MIN2(miny, itemy);
01972 
01973                 totw= MAX2(totw, itemx+itemw);
01974                 toth= MAX2(toth, itemy+itemh);
01975         }
01976 
01977         totw -= minx;
01978         toth -= miny;
01979 
01980         if(litem->w && totw > 0)
01981                 scalex= (float)litem->w/(float)totw;
01982         if(litem->h && toth > 0)
01983                 scaley= (float)litem->h/(float)toth;
01984         
01985         x= litem->x;
01986         y= litem->y - scaley*toth;
01987 
01988         for(item=litem->items.first; item; item=item->next) {
01989                 ui_item_offset(item, &itemx, &itemy);
01990                 ui_item_size(item, &itemw, &itemh);
01991 
01992                 if(scalex != 1.0f) {
01993                         newx= (itemx - minx)*scalex;
01994                         itemw= (itemx - minx + itemw)*scalex - newx;
01995                         itemx= minx + newx;
01996                 }
01997 
01998                 if(scaley != 1.0f) {
01999                         newy= (itemy - miny)*scaley;
02000                         itemh= (itemy - miny + itemh)*scaley - newy;
02001                         itemy= miny + newy;
02002                 }
02003 
02004                 ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
02005         }
02006 
02007         litem->w= scalex*totw;
02008         litem->h= litem->y - y;
02009         litem->x= x + litem->w;
02010         litem->y= y;
02011 }
02012 
02013 /* split layout */
02014 static void ui_litem_estimate_split(uiLayout *litem)
02015 {
02016         ui_litem_estimate_row(litem);
02017 }
02018 
02019 static void ui_litem_layout_split(uiLayout *litem)
02020 {
02021         uiLayoutItemSplit *split= (uiLayoutItemSplit*)litem;
02022         uiItem *item;
02023         float percentage;
02024         const int tot= BLI_countlist(&litem->items);
02025         int itemh, x, y, w, colw=0;
02026 
02027         if(tot == 0)
02028                 return;
02029 
02030         x= litem->x;
02031         y= litem->y;
02032 
02033         percentage= (split->percentage == 0.0f)? 1.0f/(float)tot: split->percentage;
02034         
02035         w= (litem->w - (tot-1)*litem->space);
02036         colw= w*percentage;
02037         colw= MAX2(colw, 0);
02038 
02039         for(item=litem->items.first; item; item=item->next) {
02040                 ui_item_size(item, NULL, &itemh);
02041 
02042                 ui_item_position(item, x, y-itemh, colw, itemh);
02043                 x += colw;
02044 
02045                 if(item->next) {
02046                         colw= (w - (int)(w*percentage))/(tot-1);
02047                         colw= MAX2(colw, 0);
02048 
02049                         x += litem->space;
02050                 }
02051         }
02052 
02053         litem->w= x - litem->x;
02054         litem->h= litem->y - y;
02055         litem->x= x;
02056         litem->y= y;
02057 }
02058 
02059 /* overlap layout */
02060 static void ui_litem_estimate_overlap(uiLayout *litem)
02061 {
02062         uiItem *item;
02063         int itemw, itemh;
02064 
02065         litem->w= 0;
02066         litem->h= 0;
02067 
02068         for(item=litem->items.first; item; item=item->next) {
02069                 ui_item_size(item, &itemw, &itemh);
02070 
02071                 litem->w= MAX2(itemw, litem->w);
02072                 litem->h= MAX2(itemh, litem->h);
02073         }
02074 }
02075 
02076 static void ui_litem_layout_overlap(uiLayout *litem)
02077 {
02078         uiItem *item;
02079         int itemw, itemh, x, y;
02080 
02081         x= litem->x;
02082         y= litem->y;
02083 
02084         for(item=litem->items.first; item; item=item->next) {
02085                 ui_item_size(item, &itemw, &itemh);
02086                 ui_item_position(item, x, y-itemh, litem->w, itemh);
02087 
02088                 litem->h= MAX2(litem->h, itemh);
02089         }
02090 
02091         litem->x= x;
02092         litem->y= y - litem->h;
02093 }
02094 
02095 /* layout create functions */
02096 uiLayout *uiLayoutRow(uiLayout *layout, int align)
02097 {
02098         uiLayout *litem;
02099 
02100         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
02101         litem->item.type= ITEM_LAYOUT_ROW;
02102         litem->root= layout->root;
02103         litem->align= align;
02104         litem->active= 1;
02105         litem->enabled= 1;
02106         litem->context= layout->context;
02107         litem->space= (align)? 0: layout->root->style->buttonspacex;
02108         litem->w = layout->w;
02109         BLI_addtail(&layout->items, litem);
02110 
02111         uiBlockSetCurLayout(layout->root->block, litem);
02112 
02113         return litem;
02114 }
02115 
02116 uiLayout *uiLayoutColumn(uiLayout *layout, int align)
02117 {
02118         uiLayout *litem;
02119 
02120         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
02121         litem->item.type= ITEM_LAYOUT_COLUMN;
02122         litem->root= layout->root;
02123         litem->align= align;
02124         litem->active= 1;
02125         litem->enabled= 1;
02126         litem->context= layout->context;
02127         litem->space= (litem->align)? 0: layout->root->style->buttonspacey;
02128         litem->w = layout->w;
02129         BLI_addtail(&layout->items, litem);
02130 
02131         uiBlockSetCurLayout(layout->root->block, litem);
02132 
02133         return litem;
02134 }
02135 
02136 uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
02137 {
02138         uiLayoutItemFlow *flow;
02139 
02140         flow= MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
02141         flow->litem.item.type= ITEM_LAYOUT_COLUMN_FLOW;
02142         flow->litem.root= layout->root;
02143         flow->litem.align= align;
02144         flow->litem.active= 1;
02145         flow->litem.enabled= 1;
02146         flow->litem.context= layout->context;
02147         flow->litem.space= (flow->litem.align)? 0: layout->root->style->columnspace;
02148         flow->litem.w = layout->w;
02149         flow->number= number;
02150         BLI_addtail(&layout->items, flow);
02151 
02152         uiBlockSetCurLayout(layout->root->block, &flow->litem);
02153 
02154         return &flow->litem;
02155 }
02156 
02157 static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
02158 {
02159         uiLayoutItemBx *box;
02160 
02161         box= MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
02162         box->litem.item.type= ITEM_LAYOUT_BOX;
02163         box->litem.root= layout->root;
02164         box->litem.active= 1;
02165         box->litem.enabled= 1;
02166         box->litem.context= layout->context;
02167         box->litem.space= layout->root->style->columnspace;
02168         box->litem.w = layout->w;
02169         BLI_addtail(&layout->items, box);
02170 
02171         uiBlockSetCurLayout(layout->root->block, &box->litem);
02172 
02173         box->roundbox= uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
02174 
02175         return box;
02176 }
02177 
02178 uiLayout *uiLayoutBox(uiLayout *layout)
02179 {
02180         return (uiLayout*)ui_layout_box(layout, ROUNDBOX);
02181 }
02182 
02183 uiLayout *uiLayoutListBox(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, PropertyRNA *actprop)
02184 {
02185         uiLayoutItemBx *box= ui_layout_box(layout, LISTBOX);
02186         uiBut *but= box->roundbox;
02187 
02188         but->rnasearchpoin= *ptr;
02189         but->rnasearchprop= prop;
02190         but->rnapoin= *actptr;
02191         but->rnaprop= actprop;
02192 
02193         return (uiLayout*)box;
02194 }
02195 
02196 uiLayout *uiLayoutAbsolute(uiLayout *layout, int align)
02197 {
02198         uiLayout *litem;
02199 
02200         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
02201         litem->item.type= ITEM_LAYOUT_ABSOLUTE;
02202         litem->root= layout->root;
02203         litem->align= align;
02204         litem->active= 1;
02205         litem->enabled= 1;
02206         litem->context= layout->context;
02207         BLI_addtail(&layout->items, litem);
02208 
02209         uiBlockSetCurLayout(layout->root->block, litem);
02210 
02211         return litem;
02212 }
02213 
02214 uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout)
02215 {
02216         uiBlock *block;
02217 
02218         block= uiLayoutGetBlock(layout);
02219         uiLayoutAbsolute(layout, 0);
02220 
02221         return block;
02222 }
02223 
02224 uiLayout *uiLayoutOverlap(uiLayout *layout)
02225 {
02226         uiLayout *litem;
02227 
02228         litem= MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
02229         litem->item.type= ITEM_LAYOUT_OVERLAP;
02230         litem->root= layout->root;
02231         litem->active= 1;
02232         litem->enabled= 1;
02233         litem->context= layout->context;
02234         BLI_addtail(&layout->items, litem);
02235 
02236         uiBlockSetCurLayout(layout->root->block, litem);
02237 
02238         return litem;
02239 }
02240 
02241 uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align)
02242 {
02243         uiLayoutItemSplit *split;
02244 
02245         split= MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
02246         split->litem.item.type= ITEM_LAYOUT_SPLIT;
02247         split->litem.root= layout->root;
02248         split->litem.align= align;
02249         split->litem.active= 1;
02250         split->litem.enabled= 1;
02251         split->litem.context= layout->context;
02252         split->litem.space= layout->root->style->columnspace;
02253         split->litem.w= layout->w;
02254         split->percentage= percentage;
02255         BLI_addtail(&layout->items, split);
02256 
02257         uiBlockSetCurLayout(layout->root->block, &split->litem);
02258 
02259         return &split->litem;
02260 }
02261 
02262 void uiLayoutSetActive(uiLayout *layout, int active)
02263 {
02264         layout->active= active;
02265 }
02266 
02267 void uiLayoutSetEnabled(uiLayout *layout, int enabled)
02268 {
02269         layout->enabled= enabled;
02270 }
02271 
02272 void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
02273 {
02274         layout->redalert= redalert;
02275 }
02276 
02277 void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
02278 {
02279         layout->keepaspect= keepaspect;
02280 }
02281 
02282 void uiLayoutSetAlignment(uiLayout *layout, int alignment)
02283 {
02284         layout->alignment= alignment;
02285 }
02286 
02287 void uiLayoutSetScaleX(uiLayout *layout, float scale)
02288 {
02289         layout->scale[0]= scale;
02290 }
02291 
02292 void uiLayoutSetScaleY(uiLayout *layout, float scale)
02293 {
02294         layout->scale[1]= scale;
02295 }
02296 
02297 int uiLayoutGetActive(uiLayout *layout)
02298 {
02299         return layout->active;
02300 }
02301 
02302 int uiLayoutGetEnabled(uiLayout *layout)
02303 {
02304         return layout->enabled;
02305 }
02306 
02307 int uiLayoutGetRedAlert(uiLayout *layout)
02308 {
02309         return layout->redalert;
02310 }
02311 
02312 int uiLayoutGetKeepAspect(uiLayout *layout)
02313 {
02314         return layout->keepaspect;
02315 }
02316 
02317 int uiLayoutGetAlignment(uiLayout *layout)
02318 {
02319         return layout->alignment;
02320 }
02321 
02322 int uiLayoutGetWidth(uiLayout *layout)
02323 {
02324         return layout->w;
02325 }
02326 
02327 float uiLayoutGetScaleX(uiLayout *layout)
02328 {
02329         return layout->scale[0];
02330 }
02331 
02332 float uiLayoutGetScaleY(uiLayout *layout)
02333 {
02334         return layout->scale[0];
02335 }
02336 
02337 /********************** Layout *******************/
02338 
02339 static void ui_item_scale(uiLayout *litem, float scale[2])
02340 {
02341         uiItem *item;
02342         int x, y, w, h;
02343 
02344         for(item=litem->items.last; item; item=item->prev) {
02345                 ui_item_size(item, &w, &h);
02346                 ui_item_offset(item, &x, &y);
02347 
02348                 if(scale[0] != 0.0f) {
02349                         x *= scale[0];
02350                         w *= scale[0];
02351                 }
02352 
02353                 if(scale[1] != 0.0f) {
02354                         y *= scale[1];
02355                         h *= scale[1];
02356                 }
02357 
02358                 ui_item_position(item, x, y, w, h);
02359         }
02360 }
02361 
02362 static void ui_item_estimate(uiItem *item)
02363 {
02364         uiItem *subitem;
02365 
02366         if(item->type != ITEM_BUTTON) {
02367                 uiLayout *litem= (uiLayout*)item;
02368 
02369                 for(subitem=litem->items.first; subitem; subitem=subitem->next)
02370                         ui_item_estimate(subitem);
02371 
02372                 if(litem->items.first == NULL)
02373                         return;
02374 
02375                 if(litem->scale[0] != 0.0f || litem->scale[1] != 0.0f)
02376                         ui_item_scale(litem, litem->scale);
02377 
02378                 switch(litem->item.type) {
02379                         case ITEM_LAYOUT_COLUMN:
02380                                 ui_litem_estimate_column(litem);
02381                                 break;
02382                         case ITEM_LAYOUT_COLUMN_FLOW:
02383                                 ui_litem_estimate_column_flow(litem);
02384                                 break;
02385                         case ITEM_LAYOUT_ROW:
02386                                 ui_litem_estimate_row(litem);
02387                                 break;
02388                         case ITEM_LAYOUT_BOX:
02389                                 ui_litem_estimate_box(litem);
02390                                 break;
02391                         case ITEM_LAYOUT_ROOT:
02392                                 ui_litem_estimate_root(litem);
02393                                 break;
02394                         case ITEM_LAYOUT_ABSOLUTE:
02395                                 ui_litem_estimate_absolute(litem);
02396                                 break;
02397                         case ITEM_LAYOUT_SPLIT:
02398                                 ui_litem_estimate_split(litem);
02399                                 break;
02400                         case ITEM_LAYOUT_OVERLAP:
02401                                 ui_litem_estimate_overlap(litem);
02402                                 break;
02403                         default:
02404                                 break;
02405                 }
02406         }
02407 }
02408 
02409 static void ui_item_align(uiLayout *litem, int nr)
02410 {
02411         uiItem *item;
02412         uiButtonItem *bitem;
02413         uiLayoutItemBx *box;
02414 
02415         for(item=litem->items.last; item; item=item->prev) {
02416                 if(item->type == ITEM_BUTTON) {
02417                         bitem= (uiButtonItem*)item;
02418                         if(ui_but_can_align(bitem->but))
02419                                 if(!bitem->but->alignnr)
02420                                         bitem->but->alignnr= nr;
02421                 }
02422                 else if(item->type == ITEM_LAYOUT_ABSOLUTE);
02423                 else if(item->type == ITEM_LAYOUT_OVERLAP);
02424                 else if(item->type == ITEM_LAYOUT_BOX) {
02425                         box= (uiLayoutItemBx*)item;
02426                         box->roundbox->alignnr= nr;
02427                         BLI_remlink(&litem->root->block->buttons, box->roundbox);
02428                         BLI_addhead(&litem->root->block->buttons, box->roundbox);
02429                 }
02430                 else
02431                         ui_item_align((uiLayout*)item, nr);
02432         }
02433 }
02434 
02435 static void ui_item_flag(uiLayout *litem, int flag)
02436 {
02437         uiItem *item;
02438         uiButtonItem *bitem;
02439 
02440         for(item=litem->items.last; item; item=item->prev) {
02441                 if(item->type == ITEM_BUTTON) {
02442                         bitem= (uiButtonItem*)item;
02443                         bitem->but->flag |= flag;
02444                 }
02445                 else
02446                         ui_item_flag((uiLayout*)item, flag);
02447         }
02448 }
02449 
02450 static void ui_item_layout(uiItem *item)
02451 {
02452         uiItem *subitem;
02453 
02454         if(item->type != ITEM_BUTTON) {
02455                 uiLayout *litem= (uiLayout*)item;
02456 
02457                 if(litem->items.first == NULL)
02458                         return;
02459 
02460                 if(litem->align)
02461                         ui_item_align(litem, ++litem->root->block->alignnr);
02462                 if(!litem->active)
02463                         ui_item_flag(litem, UI_BUT_INACTIVE);
02464                 if(!litem->enabled)
02465                         ui_item_flag(litem, UI_BUT_DISABLED);
02466 
02467                 switch(litem->item.type) {
02468                         case ITEM_LAYOUT_COLUMN:
02469                                 ui_litem_layout_column(litem);
02470                                 break;
02471                         case ITEM_LAYOUT_COLUMN_FLOW:
02472                                 ui_litem_layout_column_flow(litem);
02473                                 break;
02474                         case ITEM_LAYOUT_ROW:
02475                                 ui_litem_layout_row(litem);
02476                                 break;
02477                         case ITEM_LAYOUT_BOX:
02478                                 ui_litem_layout_box(litem);
02479                                 break;
02480                         case ITEM_LAYOUT_ROOT:
02481                                 ui_litem_layout_root(litem);
02482                                 break;
02483                         case ITEM_LAYOUT_ABSOLUTE:
02484                                 ui_litem_layout_absolute(litem);
02485                                 break;
02486                         case ITEM_LAYOUT_SPLIT:
02487                                 ui_litem_layout_split(litem);
02488                                 break;
02489                         case ITEM_LAYOUT_OVERLAP:
02490                                 ui_litem_layout_overlap(litem);
02491                                 break;
02492                         default:
02493                                 break;
02494                 }
02495 
02496                 for(subitem=litem->items.first; subitem; subitem=subitem->next)
02497                         ui_item_layout(subitem);
02498         }
02499 }
02500 
02501 static void ui_layout_end(uiBlock *block, uiLayout *layout, int *x, int *y)
02502 {
02503         if(layout->root->handlefunc)
02504                 uiBlockSetButmFunc(block, layout->root->handlefunc, layout->root->argv);
02505 
02506         ui_item_estimate(&layout->item);
02507         ui_item_layout(&layout->item);
02508 
02509         if(x) *x= layout->x;
02510         if(y) *y= layout->y;
02511 }
02512 
02513 static void ui_layout_free(uiLayout *layout)
02514 {
02515         uiItem *item, *next;
02516 
02517         for(item=layout->items.first; item; item=next) {
02518                 next= item->next;
02519 
02520                 if(item->type == ITEM_BUTTON)
02521                         MEM_freeN(item);
02522                 else
02523                         ui_layout_free((uiLayout*)item);
02524         }
02525 
02526         MEM_freeN(layout);
02527 }
02528 
02529 uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, uiStyle *style)
02530 {
02531         uiLayout *layout;
02532         uiLayoutRoot *root;
02533 
02534         root= MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
02535         root->type= type;
02536         root->style= style;
02537         root->block= block;
02538         root->opcontext= WM_OP_INVOKE_REGION_WIN;
02539 
02540         layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
02541         layout->item.type= ITEM_LAYOUT_ROOT;
02542 
02543         layout->x= x;
02544         layout->y= y;
02545         layout->root= root;
02546         layout->space= style->templatespace;
02547         layout->active= 1;
02548         layout->enabled= 1;
02549         layout->context= NULL;
02550 
02551         if(type == UI_LAYOUT_MENU)
02552                 layout->space= 0;
02553 
02554         if(dir == UI_LAYOUT_HORIZONTAL) {
02555                 layout->h= size;
02556                 layout->root->emh= em*UI_UNIT_Y;
02557         }
02558         else {
02559                 layout->w= size;
02560                 layout->root->emw= em*UI_UNIT_X;
02561         }
02562 
02563         block->curlayout= layout;
02564         root->layout= layout;
02565         BLI_addtail(&block->layouts, root);
02566         
02567         return layout;
02568 }
02569 
02570 uiBlock *uiLayoutGetBlock(uiLayout *layout)
02571 {
02572         return layout->root->block;
02573 }
02574 
02575 int uiLayoutGetOperatorContext(uiLayout *layout)
02576 {
02577         return layout->root->opcontext;
02578 }
02579 
02580 
02581 void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
02582 {
02583         block->curlayout= layout;
02584 }
02585 
02586 void ui_layout_add_but(uiLayout *layout, uiBut *but)
02587 {
02588         uiButtonItem *bitem;
02589         
02590         bitem= MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
02591         bitem->item.type= ITEM_BUTTON;
02592         bitem->but= but;
02593         BLI_addtail(&layout->items, bitem);
02594 
02595         if(layout->context) {
02596                 but->context= layout->context;
02597                 but->context->used= 1;
02598         }
02599 }
02600 
02601 void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
02602 {
02603         layout->root->opcontext= opcontext;
02604 }
02605 
02606 void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
02607 {
02608         layout->root->handlefunc= handlefunc;
02609         layout->root->argv= argv;
02610 }
02611 
02612 void uiBlockLayoutResolve(uiBlock *block, int *x, int *y)
02613 {
02614         uiLayoutRoot *root;
02615 
02616         if(x) *x= 0;
02617         if(y) *y= 0;
02618 
02619         block->curlayout= NULL;
02620 
02621         for(root=block->layouts.first; root; root=root->next) {
02622                 /* NULL in advance so we don't interfere when adding button */
02623                 ui_layout_end(block, root->layout, x, y);
02624                 ui_layout_free(root->layout);
02625         }
02626 
02627         BLI_freelistN(&block->layouts);
02628 
02629         /* XXX silly trick, interface_templates.c doesn't get linked
02630          * because it's not used by other files in this module? */
02631         {
02632                 UI_template_fix_linking();
02633         }
02634 }
02635 
02636 void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr)
02637 {
02638         uiBlock *block= layout->root->block;
02639         layout->context= CTX_store_add(&block->contexts, name, ptr);
02640 }
02641 
02642 
02643 /* introspect funcs */
02644 #include "BLI_dynstr.h"
02645 
02646 static void ui_intro_button(DynStr *ds, uiButtonItem *bitem)
02647 {
02648         uiBut *but = bitem->but;
02649         BLI_dynstr_appendf(ds, "'type':%d, ", but->type); /* see ~ UI_interface.h:200 */
02650         BLI_dynstr_appendf(ds, "'draw_string':'''%s''', ", but->drawstr);
02651         BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : ""); // not exactly needed, rna has this
02652 
02653         if(but->optype) {
02654                 char *opstr = WM_operator_pystring(but->block->evil_C, but->optype, but->opptr, 0);
02655                 BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
02656                 MEM_freeN(opstr);
02657         }
02658 
02659         if(but->rnaprop) {
02660                 BLI_dynstr_appendf(ds, "'rna':'%s.%s[%d]', ", RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop), but->rnaindex);
02661         }
02662 
02663 }
02664 
02665 static void ui_intro_items(DynStr *ds, ListBase *lb)
02666 {
02667         uiItem *item;
02668 
02669         BLI_dynstr_append(ds, "[");
02670 
02671         for(item=lb->first; item; item=item->next) {
02672 
02673                 BLI_dynstr_append(ds, "{");
02674 
02675                 /* could also use the INT but this is nicer*/
02676                 switch(item->type) {
02677                 case ITEM_BUTTON:                       BLI_dynstr_append(ds, "'type':'BUTTON', ");break;
02678                 case ITEM_LAYOUT_ROW:           BLI_dynstr_append(ds, "'type':'ROW', "); break;
02679                 case ITEM_LAYOUT_COLUMN:        BLI_dynstr_append(ds, "'type':'COLUMN', "); break;
02680                 case ITEM_LAYOUT_COLUMN_FLOW:BLI_dynstr_append(ds, "'type':'COLUMN_FLOW', "); break;
02681                 case ITEM_LAYOUT_ROW_FLOW:      BLI_dynstr_append(ds, "'type':'ROW_FLOW', "); break;
02682                 case ITEM_LAYOUT_BOX:           BLI_dynstr_append(ds, "'type':'BOX', "); break;
02683                 case ITEM_LAYOUT_ABSOLUTE:      BLI_dynstr_append(ds, "'type':'ABSOLUTE', "); break;
02684                 case ITEM_LAYOUT_SPLIT:         BLI_dynstr_append(ds, "'type':'SPLIT', "); break;
02685                 case ITEM_LAYOUT_OVERLAP:       BLI_dynstr_append(ds, "'type':'OVERLAP', "); break;
02686                 case ITEM_LAYOUT_ROOT:          BLI_dynstr_append(ds, "'type':'ROOT', "); break;
02687                 default:                                        BLI_dynstr_append(ds, "'type':'UNKNOWN', "); break;
02688                 }
02689 
02690                 switch(item->type) {
02691                 case ITEM_BUTTON:
02692                         ui_intro_button(ds, (uiButtonItem *)item);
02693                         break;
02694                 default:
02695                         BLI_dynstr_append(ds, "'items':");
02696                         ui_intro_items(ds, &((uiLayout*)item)->items);
02697                         break;
02698                 }
02699 
02700                 BLI_dynstr_append(ds, "}");
02701 
02702                 if(item != lb->last)
02703                         BLI_dynstr_append(ds, ", ");
02704         }
02705         BLI_dynstr_append(ds, "], ");
02706 }
02707 
02708 static void ui_intro_uiLayout(DynStr *ds, uiLayout *layout)
02709 {
02710         ui_intro_items(ds, &layout->items);
02711 }
02712 
02713 static char *str = NULL; // XXX, constant re-freeing, far from ideal.
02714 const char *uiLayoutIntrospect(uiLayout *layout)
02715 {
02716         DynStr *ds= BLI_dynstr_new();
02717 
02718         if(str)
02719                 MEM_freeN(str);
02720 
02721         ui_intro_uiLayout(ds, layout);
02722 
02723         str = BLI_dynstr_get_cstring(ds);
02724         BLI_dynstr_free(ds);
02725 
02726         return str;
02727 }
02728 
02729 /* this function does not initialize the layout, functions can be called on the layout before and after */
02730 void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,int (*check_prop)(struct PropertyRNA *), const char label_align, const short flag)
02731 {
02732         if(!op->properties) {
02733                 IDPropertyTemplate val = {0};
02734                 op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
02735         }
02736 
02737         if(flag & UI_LAYOUT_OP_SHOW_TITLE) {
02738                 uiItemL(layout, op->type->name, ICON_NONE);
02739         }
02740 
02741         /* poll() on this operator may still fail, at the moment there is no nice feedback when this happens
02742          * just fails silently */
02743         if(!WM_operator_repeat_check(C, op)) {
02744                 uiBlockSetButLock(uiLayoutGetBlock(layout), TRUE, "Operator cannot redo");
02745                 uiItemL(layout, "* Redo Unsupported *", ICON_NONE); // XXX, could give some nicer feedback or not show redo panel at all?
02746         }
02747 
02748         /* menu */
02749         if(op->type->flag & OPTYPE_PRESET) {
02750                 /* XXX, no simple way to get WM_MT_operator_presets.bl_label from python! Label remains the same always! */
02751                 PointerRNA op_ptr;
02752                 uiLayout *row;
02753 
02754                 row= uiLayoutRow(layout, TRUE);
02755                 uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE);
02756 
02757                 WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add");
02758                 RNA_string_set(&op_ptr, "operator", op->type->idname);
02759                 op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
02760 
02761                 WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add");
02762                 RNA_string_set(&op_ptr, "operator", op->type->idname);
02763                 RNA_boolean_set(&op_ptr, "remove_active", 1);
02764                 op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
02765         }
02766 
02767         if(op->type->ui) {
02768                 op->layout= layout;
02769                 op->type->ui((bContext*)C, op);
02770                 op->layout= NULL;
02771 
02772                 /* UI_LAYOUT_OP_SHOW_EMPTY ignored */
02773         }
02774         else {
02775                 wmWindowManager *wm= CTX_wm_manager(C);
02776                 PointerRNA ptr;
02777                 int empty;
02778 
02779                 RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
02780 
02781                 /* main draw call */
02782                 empty= uiDefAutoButsRNA(layout, &ptr, check_prop, label_align) == 0;
02783 
02784                 if(empty && (flag & UI_LAYOUT_OP_SHOW_EMPTY)) {
02785                         uiItemL(layout, "No Properties.", ICON_NONE);
02786                 }
02787         }
02788         
02789         /* set various special settings for buttons */
02790         {
02791                 uiBut *but;
02792                 
02793                 for(but= uiLayoutGetBlock(layout)->buttons.first; but; but= but->next) {
02794                         /* no undo for buttons for operator redo panels */
02795                         uiButClearFlag(but, UI_BUT_UNDO);
02796                         
02797                         /* if button is operator's default property, and a text-field, enable focus for it
02798                          *      - this is used for allowing operators with popups to rename stuff with fewer clicks
02799                          */
02800                         if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
02801                                 uiButSetFocusOnEnter(CTX_wm_window(C), but);
02802                         }
02803                 }
02804         }
02805 }