From 9ed9acaf9a5a64a3471b4eca6a9e91bb8f0bc23e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 3 Jun 2009 00:04:48 +0000 Subject: UI: * Implemented scale_x/scale_y for layouts. * Implemented left/right/center/expand alignment for row layouts. --- source/blender/editors/include/UI_interface.h | 13 +- .../blender/editors/interface/interface_layout.c | 172 +++++++++++++++------ source/blender/makesrna/intern/rna_ui.c | 26 +++- 3 files changed, 157 insertions(+), 54 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index e66c4ef827b..45f26ecdcab 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -556,9 +556,10 @@ uiBut *uiDefMenuTogR(uiBlock *block, struct PointerRNA *ptr, char *propname, cha #define UI_UNIT_X 20 #define UI_UNIT_Y 20 -#define UI_LAYOUT_ALIGN_LEFT 0 -#define UI_LAYOUT_ALIGN_CENTER 1 -#define UI_LAYOUT_ALIGN_RIGHT 2 +#define UI_LAYOUT_ALIGN_EXPAND 0 +#define UI_LAYOUT_ALIGN_LEFT 1 +#define UI_LAYOUT_ALIGN_CENTER 2 +#define UI_LAYOUT_ALIGN_RIGHT 3 uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, struct uiStyle *style); void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout); @@ -575,14 +576,16 @@ void uiLayoutSetEnabled(uiLayout *layout, int enabled); void uiLayoutSetRedAlert(uiLayout *layout, int redalert); void uiLayoutSetAlignment(uiLayout *layout, int alignment); void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect); -void uiLayoutSetScale(uiLayout *layout, float scale); +void uiLayoutSetScaleX(uiLayout *layout, float scale); +void uiLayoutSetScaleY(uiLayout *layout, float scale); int uiLayoutGetActive(uiLayout *layout); int uiLayoutGetEnabled(uiLayout *layout); int uiLayoutGetRedAlert(uiLayout *layout); int uiLayoutGetAlignment(uiLayout *layout); int uiLayoutGetKeepAspect(uiLayout *layout); -float uiLayoutGetScale(uiLayout *layout); +float uiLayoutGetScaleX(uiLayout *layout); +float uiLayoutGetScaleY(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, int align); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 2e123c28339..bb2be0da874 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -115,6 +115,7 @@ typedef enum uiItemType { typedef struct uiItem { void *next, *prev; uiItemType type; + int flag; } uiItem; typedef struct uiButtonItem { @@ -130,7 +131,7 @@ struct uiLayout { ListBase items; int x, y, w, h; - float scale; + float scale[2]; short space; char align; char active; @@ -177,26 +178,29 @@ static char *ui_item_name_add_colon(char *name, char namestr[UI_MAX_NAME_STR]) return name; } -#define UI_FIT_EXPAND 1 - -static int ui_item_fit(int item, int pos, int all, int available, int spacing, int last, int flag) +static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset) { /* available == 0 is unlimited */ - - if(available != 0 && all > available-spacing) { + if(available == 0) + return item; + + if(offset) + *offset= 0; + + if(all > available) { /* contents is bigger than available space */ if(last) return available-pos; else - return (item*(available-spacing))/all; + return (item*available)/all; } else { /* contents is smaller or equal to available space */ - if(available != 0 && (flag & UI_FIT_EXPAND)) { + if(alignment == UI_LAYOUT_ALIGN_EXPAND) { if(last) return available-pos; else - return (item*(available-spacing))/all; + return (item*available)/all; } else return item; @@ -655,9 +659,6 @@ static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA subtype= RNA_property_subtype(prop); len= RNA_property_array_length(prop); - if(ELEM(type, PROP_STRING, PROP_ENUM)) - w += 10*UI_UNIT_X; - /* increase height for arrays */ if(index == RNA_NO_INDEX && len > 0) { if(strcmp(name, "") == 0 && icon == 0) @@ -1033,14 +1034,22 @@ static void ui_litem_estimate_row(uiLayout *litem) } } +static int ui_litem_min_width(int itemw) +{ + return MIN2(UI_UNIT_X, itemw); +} + static void ui_litem_layout_row(uiLayout *litem) { uiItem *item; - int neww, itemw, itemh, x, y, w, tot= 0, totw= 0, extra=0, available=0; + int x, y, w, tot, totw, neww, itemw, minw, itemh, offset; + int fixedw, freew, fixedx, freex, flag= 0, lastw= 0; x= litem->x; y= litem->y; w= litem->w; + totw= 0; + tot= 0; for(item=litem->items.first; item; item=item->next) { ui_item_size(item, &itemw, &itemh); @@ -1051,40 +1060,81 @@ static void ui_litem_layout_row(uiLayout *litem) if(totw == 0) return; - /* two step to enforce minimum button with .. could be better */ - for(item=litem->items.first; item; item=item->next) { - ui_item_size(item, &itemw, &itemh); + if(w != 0) + w -= (tot-1)*litem->space; + fixedw= 0; - itemw= ui_item_fit(itemw, x-litem->x, totw, w, (tot-1)*litem->space, !item->next, UI_FIT_EXPAND); - x += itemw; + /* keep clamping items to fixed minimum size until all are done */ + do { + freew= 0; + x= 0; + flag= 0; - if(itemw < UI_UNIT_X) - extra += UI_UNIT_X - itemw; - else - available += itemw - UI_UNIT_X; + for(item=litem->items.first; item; item=item->next) { + if(item->flag) + continue; - if(item->next) - x += litem->space; - } + ui_item_size(item, &itemw, &itemh); + minw= ui_litem_min_width(itemw); + + if(w - lastw > 0) + neww= ui_item_fit(itemw, x, totw, w-lastw, !item->next, litem->alignment, NULL); + else + neww= 0; /* no space left, all will need clamping to minimum size */ + x += neww; + + if(neww < minw && w != 0) { + /* fixed size */ + item->flag= 1; + fixedw += minw; + flag= 1; + totw -= itemw; + } + else { + /* keep free size */ + item->flag= 0; + freew += itemw; + } + } + + lastw= fixedw; + } while(flag); + + freex= 0; + fixedx= 0; x= litem->x; for(item=litem->items.first; item; item=item->next) { ui_item_size(item, &itemw, &itemh); + minw= ui_litem_min_width(itemw); - neww= ui_item_fit(itemw, x-litem->x, totw, w, (tot-1)*litem->space, !item->next, UI_FIT_EXPAND); - if(neww < UI_UNIT_X) { - if(item->next) - itemw= UI_UNIT_X; - else - itemw= litem->w - (x-litem->x); + if(item->flag) { + /* fixed minimum size items */ + itemw= ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL); + fixedx += itemw; + } + else { + /* free size item */ + itemw= ui_item_fit(itemw, freex, freew, w-fixedw, !item->next, litem->alignment, NULL); + freex += itemw; } - else - itemw= ui_item_fit(itemw, x-litem->x, totw, w-extra, (tot-1)*litem->space, !item->next, UI_FIT_EXPAND); - ui_item_position(item, x, y-itemh, itemw, itemh); - x += itemw; + /* align right/center */ + offset= 0; + if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) { + if(fixedw == 0 && freew < w-fixedw) + offset= (w - fixedw) - freew; + } + else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) { + if(fixedw == 0 && freew < w-fixedw) + offset= ((w - fixedw) - freew)/2; + } + + /* position item */ + ui_item_position(item, x+offset, y-itemh, itemw, itemh); + x += itemw; if(item->next) x += litem->space; } @@ -1263,7 +1313,7 @@ static void ui_litem_layout_column_flow(uiLayout *litem) uiLayoutItemFlow *flow= (uiLayoutItemFlow*)litem; uiItem *item; int col, x, y, w, emh, emy, miny, itemw, itemh; - int toth, totitem; + int toth, totitem, offset; /* compute max needed width and total height */ toth= 0; @@ -1280,18 +1330,18 @@ static void ui_litem_layout_column_flow(uiLayout *litem) emy= 0; miny= 0; - w= litem->w; + w= litem->w - (flow->totcol-1)*style->columnspace; emh= toth/flow->totcol; /* create column per column */ col= 0; for(item=litem->items.first; item; item=item->next) { ui_item_size(item, NULL, &itemh); - itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, (flow->totcol-1)*style->columnspace, col == flow->totcol-1, UI_FIT_EXPAND); + itemw= ui_item_fit(1, x-litem->x, flow->totcol, w, col == flow->totcol-1, litem->alignment, &offset); y -= itemh; emy -= itemh; - ui_item_position(item, x, y, itemw, itemh); + ui_item_position(item, x+offset, y, itemw, itemh); y -= style->buttonspacey; miny= MIN2(miny, y); @@ -1578,9 +1628,14 @@ void uiLayoutSetAlignment(uiLayout *layout, int alignment) layout->alignment= alignment; } -void uiLayoutSetScale(uiLayout *layout, float scale) +void uiLayoutSetScaleX(uiLayout *layout, float scale) { - layout->scale= scale; + layout->scale[0]= scale; +} + +void uiLayoutSetScaleY(uiLayout *layout, float scale) +{ + layout->scale[1]= scale; } int uiLayoutGetActive(uiLayout *layout) @@ -1608,13 +1663,41 @@ int uiLayoutGetAlignment(uiLayout *layout) return layout->alignment; } -float uiLayoutGetScale(uiLayout *layout) +float uiLayoutGetScaleX(uiLayout *layout) { - return layout->scale; + return layout->scale[0]; +} + +float uiLayoutGetScaleY(uiLayout *layout) +{ + return layout->scale[0]; } /********************** Layout *******************/ +static void ui_item_scale(uiLayout *litem, float scale[2]) +{ + uiItem *item; + int x, y, w, h; + + for(item=litem->items.last; item; item=item->prev) { + ui_item_size(item, &w, &h); + ui_item_offset(item, &x, &y); + + if(scale[0] != 0.0f) { + x *= scale[0]; + w *= scale[0]; + } + + if(scale[1] != 0.0f) { + y *= scale[1]; + h *= scale[1]; + } + + ui_item_position(item, x, y, w, h); + } +} + static void ui_item_estimate(uiItem *item) { uiItem *subitem; @@ -1628,6 +1711,9 @@ static void ui_item_estimate(uiItem *item) if(litem->items.first == NULL) return; + if(litem->scale[0] != 0.0f || litem->scale[1] != 0.0f) + ui_item_scale(litem, litem->scale); + switch(litem->item.type) { case ITEM_LAYOUT_COLUMN: ui_litem_estimate_column(litem); diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 7ca0c586d47..796817e1018 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -458,14 +458,24 @@ static void rna_UILayout_alignment_set(struct PointerRNA *ptr, int value) return uiLayoutSetAlignment(ptr->data, value); } -static float rna_UILayout_scale_get(struct PointerRNA *ptr) +static float rna_UILayout_scale_x_get(struct PointerRNA *ptr) { - return uiLayoutGetScale(ptr->data); + return uiLayoutGetScaleX(ptr->data); } -static void rna_UILayout_scale_set(struct PointerRNA *ptr, float value) +static void rna_UILayout_scale_x_set(struct PointerRNA *ptr, float value) { - return uiLayoutSetScale(ptr->data, value); + return uiLayoutSetScaleX(ptr->data, value); +} + +static float rna_UILayout_scale_y_get(struct PointerRNA *ptr) +{ + return uiLayoutGetScaleY(ptr->data); +} + +static void rna_UILayout_scale_y_set(struct PointerRNA *ptr, float value) +{ + return uiLayoutSetScaleY(ptr->data, value); } #else @@ -476,6 +486,7 @@ static void rna_def_ui_layout(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem alignment_items[] = { + {UI_LAYOUT_ALIGN_EXPAND, "EXPAND", "Expand", ""}, {UI_LAYOUT_ALIGN_LEFT, "LEFT", "Left", ""}, {UI_LAYOUT_ALIGN_CENTER, "CENTER", "Center", ""}, {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", "RIght", ""}, @@ -501,8 +512,11 @@ static void rna_def_ui_layout(BlenderRNA *brna) prop= RNA_def_property(srna, "keep_aspect", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_UILayout_keep_aspect_get", "rna_UILayout_keep_aspect_set"); - prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_UNSIGNED); - RNA_def_property_float_funcs(prop, "rna_UILayout_scale_get", "rna_UILayout_scale_set", NULL); + prop= RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED); + RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL); + + prop= RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED); + RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL); RNA_api_ui_layout(srna); } -- cgit v1.2.3