| @@ -861,7 +861,7 @@ void build_columndemo(int parent) { | |||||
| } | } | ||||
| } | } | ||||
| void fill_wrap_box(int box) { | |||||
| void fill_wrap_row_box(int box) { | |||||
| const int M = 5; | const int M = 5; | ||||
| const int S = 100; | const int S = 100; | ||||
| const int T = 50; | const int T = 50; | ||||
| @@ -877,7 +877,7 @@ void fill_wrap_box(int box) { | |||||
| demorect(box, "Layout( UI_TOP )", hue, 0, UI_TOP, width, T, M, M, M, M); | demorect(box, "Layout( UI_TOP )", hue, 0, UI_TOP, width, T, M, M, M, M); | ||||
| } break; | } break; | ||||
| case 1: { | case 1: { | ||||
| demorect(box, "Layout( UI_VCENTER )", hue, 0, UI_VCENTER, width, T/2, M, 0, M, 0); | |||||
| demorect(box, "Layout( UI_VCENTER )", hue, 0, UI_VCENTER, width, T/2, M, M, M, M); | |||||
| } break; | } break; | ||||
| case 2: { | case 2: { | ||||
| demorect(box, "Layout( UI_VFILL )", hue, 0, UI_VFILL, width, T, M, M, M, M); | demorect(box, "Layout( UI_VFILL )", hue, 0, UI_VFILL, width, T, M, M, M, M); | ||||
| @@ -890,11 +890,40 @@ void fill_wrap_box(int box) { | |||||
| } | } | ||||
| void fill_wrap_column_box(int box) { | |||||
| const int M = 5; | |||||
| const int S = 100; | |||||
| const int T = 50; | |||||
| srand(303); | |||||
| for (int i = 0; i < 20; ++i) { | |||||
| float hue = (float)(rand()%360)/360.0f; | |||||
| int height = 10 + (rand()%5)*10; | |||||
| switch(rand()%4) { | |||||
| default: break; | |||||
| case 0: { | |||||
| demorect(box, "Layout( UI_LEFT )", hue, 0, UI_LEFT, T, height, M, M, M, M); | |||||
| } break; | |||||
| case 1: { | |||||
| demorect(box, "Layout( UI_HCENTER )", hue, 0, UI_HCENTER, T/2, height, M, M, M, M); | |||||
| } break; | |||||
| case 2: { | |||||
| demorect(box, "Layout( UI_HFILL )", hue, 0, UI_HFILL, T, height, M, M, M, M); | |||||
| } break; | |||||
| case 3: { | |||||
| demorect(box, "Layout( UI_RIGHT )", hue, 0, UI_RIGHT, T/2, height, M, M, M, M); | |||||
| } break; | |||||
| } | |||||
| } | |||||
| } | |||||
| void build_wrapdemo(int parent) { | void build_wrapdemo(int parent) { | ||||
| int col = uiItem(); | int col = uiItem(); | ||||
| uiAppend(parent, col); | uiAppend(parent, col); | ||||
| uiSetBox(col, UI_COLUMN); | uiSetBox(col, UI_COLUMN); | ||||
| uiSetLayout(col, UI_HFILL|UI_TOP); | |||||
| uiSetLayout(col, UI_FILL); | |||||
| const int M = 5; | const int M = 5; | ||||
| const int S = 100; | const int S = 100; | ||||
| @@ -902,16 +931,19 @@ void build_wrapdemo(int parent) { | |||||
| int box; | int box; | ||||
| box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_START )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_START, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_START )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_START, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | ||||
| fill_wrap_box(box); | |||||
| fill_wrap_row_box(box); | |||||
| box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_MIDDLE )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_MIDDLE )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | ||||
| fill_wrap_box(box); | |||||
| fill_wrap_row_box(box); | |||||
| box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_END )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_END, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_END )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_END, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | ||||
| fill_wrap_box(box); | |||||
| fill_wrap_row_box(box); | |||||
| box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_JUSTIFY )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_JUSTIFY, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_JUSTIFY )\nLayout( UI_HFILL | UI_TOP )", 0.6f, UI_ROW | UI_WRAP | UI_JUSTIFY, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); | ||||
| fill_wrap_box(box); | |||||
| fill_wrap_row_box(box); | |||||
| box = demorect(col, "Box( UI_COLUMN | UI_WRAP | UI_START )\nLayout( UI_LEFT | UI_VFILL )", 0.6f, UI_COLUMN | UI_WRAP | UI_START, UI_LEFT | UI_VFILL, 0, 0, M, M, M, M); | |||||
| fill_wrap_column_box(box); | |||||
| } | } | ||||
| @@ -648,7 +648,9 @@ OUI_EXPORT short uiGetMarginDown(int item); | |||||
| // extra item flags | // extra item flags | ||||
| enum { | enum { | ||||
| // bit 0-2 | // bit 0-2 | ||||
| UI_ITEM_BOX_MASK = 0x00001F, | |||||
| UI_ITEM_BOX_MODEL_MASK = 0x000007, | |||||
| // bit 0-4 | |||||
| UI_ITEM_BOX_MASK = 0x00001F, | |||||
| // bit 5-8 | // bit 5-8 | ||||
| UI_ITEM_LAYOUT_MASK = 0x0001E0, | UI_ITEM_LAYOUT_MASK = 0x0001E0, | ||||
| // bit 9-18 | // bit 9-18 | ||||
| @@ -1123,25 +1125,35 @@ static void uiComputeSize(int item, int dim) { | |||||
| kid = uiNextSibling(kid); | kid = uiNextSibling(kid); | ||||
| } | } | ||||
| if (pitem->size[dim]) { | |||||
| if (pitem->size[dim]) | |||||
| return; | return; | ||||
| } else if(pitem->flags & UI_FLEX) { | |||||
| if (pitem->flags & UI_WRAP) { | |||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiComputeStackedSize(pitem, dim); | |||||
| else | |||||
| uiComputeWrappedSize(pitem, dim); | |||||
| } else { | |||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiComputeStackedSize(pitem, dim); | |||||
| else | |||||
| uiComputeImposedSize(pitem, dim); | |||||
| } | |||||
| } else { | |||||
| switch(pitem->flags & UI_ITEM_BOX_MODEL_MASK) { | |||||
| case UI_COLUMN|UI_WRAP: { | |||||
| // flex model | |||||
| if (dim) // direction | |||||
| uiComputeStackedSize(pitem, 1); | |||||
| else | |||||
| uiComputeImposedSize(pitem, 0); | |||||
| } break; | |||||
| case UI_ROW|UI_WRAP: { | |||||
| // flex model | |||||
| if (!dim) // direction | |||||
| uiComputeStackedSize(pitem, 0); | |||||
| else | |||||
| uiComputeWrappedSize(pitem, 1); | |||||
| } break; | |||||
| case UI_COLUMN: | |||||
| case UI_ROW: { | |||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiComputeStackedSize(pitem, dim); | |||||
| else | |||||
| uiComputeImposedSize(pitem, dim); | |||||
| } break; | |||||
| default: { | |||||
| // layout model | // layout model | ||||
| uiComputeImposedSize(pitem, dim); | uiComputeImposedSize(pitem, dim); | ||||
| } break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1171,7 +1183,7 @@ UI_INLINE void uiArrangeStacked(UIitem *pitem, int dim, bool wrap) { | |||||
| } else { | } else { | ||||
| extend += pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | extend += pkid->margins[dim] + pkid->size[dim] + pkid->margins[wdim]; | ||||
| } | } | ||||
| if (wrap && (extend > space) && (total>1)) { | |||||
| if (wrap && (extend > space) && total) { | |||||
| end_kid = kid; | end_kid = kid; | ||||
| // add marker for subsequent queries | // add marker for subsequent queries | ||||
| pkid->flags |= UI_ITEM_NEWLINE; | pkid->flags |= UI_ITEM_NEWLINE; | ||||
| @@ -1253,7 +1265,7 @@ UI_INLINE void uiArrangeImposedRange(UIitem *pitem, int dim, | |||||
| switch(flags & UI_HFILL) { | switch(flags & UI_HFILL) { | ||||
| default: break; | default: break; | ||||
| case UI_HCENTER: { | case UI_HCENTER: { | ||||
| pkid->margins[dim] += (space-pkid->size[dim])/2; | |||||
| pkid->margins[dim] += (space-pkid->size[dim])/2 - pkid->margins[wdim]; | |||||
| } break; | } break; | ||||
| case UI_RIGHT: { | case UI_RIGHT: { | ||||
| pkid->margins[dim] = space-pkid->size[dim]-pkid->margins[wdim]; | pkid->margins[dim] = space-pkid->size[dim]-pkid->margins[wdim]; | ||||
| @@ -1273,7 +1285,7 @@ UI_INLINE void uiArrangeImposed(UIitem *pitem, int dim) { | |||||
| } | } | ||||
| // superimpose all items according to their alignment | // superimpose all items according to their alignment | ||||
| UI_INLINE void uiArrangeWrappedImposed(UIitem *pitem, int dim) { | |||||
| UI_INLINE short uiArrangeWrappedImposed(UIitem *pitem, int dim) { | |||||
| int wdim = dim+2; | int wdim = dim+2; | ||||
| short offset = pitem->margins[dim]; | short offset = pitem->margins[dim]; | ||||
| @@ -1299,28 +1311,43 @@ UI_INLINE void uiArrangeWrappedImposed(UIitem *pitem, int dim) { | |||||
| } | } | ||||
| uiArrangeImposedRange(pitem, dim, start_kid, -1, offset, need_size); | uiArrangeImposedRange(pitem, dim, start_kid, -1, offset, need_size); | ||||
| offset += need_size; | |||||
| return offset; | |||||
| } | } | ||||
| static void uiArrange(int item, int dim) { | static void uiArrange(int item, int dim) { | ||||
| UIitem *pitem = uiItemPtr(item); | UIitem *pitem = uiItemPtr(item); | ||||
| if(pitem->flags & UI_FLEX) { | |||||
| if (pitem->flags & UI_WRAP) { | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) { // direction | |||||
| uiArrangeStacked(pitem, dim, true); | |||||
| } else { | |||||
| uiArrangeWrappedImposed(pitem, dim); | |||||
| } | |||||
| switch(pitem->flags & UI_ITEM_BOX_MODEL_MASK) { | |||||
| case UI_COLUMN|UI_WRAP: { | |||||
| // flex model, wrapping | |||||
| if (dim) { // direction | |||||
| uiArrangeStacked(pitem, 1, true); | |||||
| // this retroactive resize will not effect parent widths | |||||
| short offset = uiArrangeWrappedImposed(pitem, 0); | |||||
| pitem->size[0] = offset - pitem->margins[0]; | |||||
| } | |||||
| } break; | |||||
| case UI_ROW|UI_WRAP: { | |||||
| // flex model, wrapping | |||||
| if (!dim) { // direction | |||||
| uiArrangeStacked(pitem, 0, true); | |||||
| } else { | } else { | ||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiArrangeStacked(pitem, dim, false); | |||||
| else | |||||
| uiArrangeImposed(pitem, dim); | |||||
| uiArrangeWrappedImposed(pitem, 1); | |||||
| } | } | ||||
| } else { | |||||
| } break; | |||||
| case UI_COLUMN: | |||||
| case UI_ROW: { | |||||
| // flex model | |||||
| if ((pitem->flags & 1) == (unsigned int)dim) // direction | |||||
| uiArrangeStacked(pitem, dim, false); | |||||
| else | |||||
| uiArrangeImposed(pitem, dim); | |||||
| } break; | |||||
| default: { | |||||
| // layout model | // layout model | ||||
| uiArrangeImposed(pitem, dim); | uiArrangeImposed(pitem, dim); | ||||
| } break; | |||||
| } | } | ||||
| int kid = uiFirstChild(item); | int kid = uiFirstChild(item); | ||||
| @@ -1330,19 +1357,21 @@ static void uiArrange(int item, int dim) { | |||||
| } | } | ||||
| } | } | ||||
| static void uiNestedLayout(int item, int dim) { | |||||
| uiComputeSize(item,dim); | |||||
| uiArrange(item,dim); | |||||
| // vertical layout: | |||||
| // compute horizontal: superimposed width of all child items (assume single row) | |||||
| // arrange horizontal: arrange all items imposed in-place | |||||
| // compute vertical: set size to 0 | |||||
| // arrange vertical: stack and wrap, vertically and horizontally | |||||
| uiComputeSize(item,1-dim); | |||||
| uiArrange(item,1-dim); | |||||
| } | |||||
| void uiLayout() { | void uiLayout() { | ||||
| assert(ui_context); | assert(ui_context); | ||||
| if (!ui_context->count) return; | if (!ui_context->count) return; | ||||
| uiNestedLayout(0,0); | |||||
| uiComputeSize(0,0); | |||||
| uiArrange(0,0); | |||||
| uiComputeSize(0,1); | |||||
| uiArrange(0,1); | |||||
| uiValidateStateItems(); | uiValidateStateItems(); | ||||
| // drawing routines may require this to be set already | // drawing routines may require this to be set already | ||||