From 4aa60fe8e705023e5b4475e7d3916a297f1b259a Mon Sep 17 00:00:00 2001 From: nijynot Date: Mon, 6 May 2019 21:42:24 +0200 Subject: [PATCH] Refactor fixed container feature to `SplitFixed()` which takes one arg --- container/container.go | 4 ++-- container/grid/grid_test.go | 4 ++-- container/options.go | 21 +++++++--------- internal/area/area.go | 44 +++++++++++++++++++++------------- internal/area/area_test.go | 4 ++-- widgets/textinput/textinput.go | 2 +- 6 files changed, 44 insertions(+), 35 deletions(-) diff --git a/container/container.go b/container/container.go index 4f59677..0d065c8 100644 --- a/container/container.go +++ b/container/container.go @@ -172,9 +172,9 @@ func (c *Container) split() (image.Rectangle, image.Rectangle, error) { return image.ZR, image.ZR, err } if c.opts.split == splitTypeVertical { - return area.VSplit(ar, c.opts.splitPercent) + return area.VSplit(ar, c.opts.splitPercent, c.opts.splitFixed) } - return area.HSplit(ar, c.opts.splitPercent, c.opts.topHeight, c.opts.bottomHeight) + return area.HSplit(ar, c.opts.splitPercent, c.opts.splitFixed) } // createFirst creates and returns the first sub container of this container. diff --git a/container/grid/grid_test.go b/container/grid/grid_test.go index 01f6b29..85ca390 100644 --- a/container/grid/grid_test.go +++ b/container/grid/grid_test.go @@ -127,7 +127,7 @@ func mirror() *fakewidget.Mirror { // mustHSplit splits the area or panics. func mustHSplit(ar image.Rectangle, heightPerc int) (top image.Rectangle, bottom image.Rectangle) { - t, b, err := area.HSplit(ar, heightPerc) + t, b, err := area.HSplit(ar, heightPerc, -1) if err != nil { panic(err) } @@ -136,7 +136,7 @@ func mustHSplit(ar image.Rectangle, heightPerc int) (top image.Rectangle, bottom // mustVSplit splits the area or panics. func mustVSplit(ar image.Rectangle, widthPerc int) (left image.Rectangle, right image.Rectangle) { - l, r, err := area.VSplit(ar, widthPerc) + l, r, err := area.VSplit(ar, widthPerc, -1) if err != nil { panic(err) } diff --git a/container/options.go b/container/options.go index 476d1f7..49793ec 100644 --- a/container/options.go +++ b/container/options.go @@ -77,8 +77,7 @@ type options struct { // split identifies how is this container split. split splitType splitPercent int - topHeight int - bottomHeight int + splitFixed int // widget is the widget in the container. // A container can have either two sub containers (left and right) or a @@ -169,8 +168,7 @@ func newOptions(parent *options) *options { hAlign: align.HorizontalCenter, vAlign: align.VerticalMiddle, splitPercent: DefaultSplitPercent, - topHeight: -1, - bottomHeight: -1, + splitFixed: -1, } if parent != nil { opts.inherited = parent.inherited @@ -220,16 +218,15 @@ func SplitPercent(p int) SplitOption { }) } -// FixHeight sets the heights of the top and the bottom containers. -// If an argument is equal to -1, then the height will be set automatically, -// i.e. will fill the rest of the space that is available. -func FixHeight(th int, bh int) SplitOption { +// SplitFixed sets the heights of the top and the bottom containers. +// The first container will be fixed and the second one will fill the rest of the space. +// Allows values greater or equal to zero. +func SplitFixed(cells int) SplitOption { return splitOption(func(opts *options) error { - if th < -1 || bh < -1 { - return fmt.Errorf("invalid fixed height %d or %d, must be in range %d <= th, bh", th, bh, -1) + if cells < 0 { + return fmt.Errorf("invalid fixed value %d, must be in range %d <= cells", cells, 0) } - opts.topHeight = th - opts.bottomHeight = bh + opts.splitFixed = cells return nil }) } diff --git a/internal/area/area.go b/internal/area/area.go index b080366..4c6c2bd 100644 --- a/internal/area/area.go +++ b/internal/area/area.go @@ -42,22 +42,21 @@ func FromSize(size image.Point) (image.Rectangle, error) { // specified percentage of its width. The percentage must be in the range // 0 <= heightPerc <= 100. // Can return zero size areas. -func HSplit(area image.Rectangle, heightPerc int, topHeight int, bottomHeight int) (top image.Rectangle, bottom image.Rectangle, err error) { +// +// The fixed value must by in the range -1 <= heightFixed. +// If fixed value is -1 (default value), heightPerc is used instead. +func HSplit(area image.Rectangle, heightPerc int, heightFixed int) (top image.Rectangle, bottom image.Rectangle, err error) { if min, max := 0, 100; heightPerc < min || heightPerc > max { return image.ZR, image.ZR, fmt.Errorf("invalid heightPerc %d, must be in range %d <= heightPerc <= %d", heightPerc, min, max) } - if topHeight < -1 || bottomHeight < -1 { - return image.ZR, image.ZR, fmt.Errorf("invalid fixed height %d or %d, must be in range %d <= topHeight, bottomHeight", topHeight, bottomHeight, -1) + if heightFixed < -1 { + return image.ZR, image.ZR, fmt.Errorf("invalid heightFixed %d, must be in range %d <= heightFixed", heightFixed, -1) } - if topHeight >= 0 && bottomHeight >= 0 { - top = image.Rect(area.Min.X, area.Min.Y, area.Max.X, area.Min.Y+topHeight) - bottom = image.Rect(area.Min.X, area.Min.Y+topHeight, area.Max.X, area.Min.Y+topHeight+bottomHeight) - } else if topHeight >= 0 { - top = image.Rect(area.Min.X, area.Min.Y, area.Max.X, area.Min.Y+topHeight) - bottom = image.Rect(area.Min.X, area.Min.Y+topHeight, area.Max.X, area.Max.Y) - } else if bottomHeight >= 0 { - top = image.Rect(area.Min.X, area.Min.Y, area.Max.X, area.Max.Y-bottomHeight) - bottom = image.Rect(area.Min.X, area.Max.Y-bottomHeight, area.Max.X, area.Max.Y) + + // Prioritize `SplitFixed()` over `SplitPercent()`. + if heightFixed >= 0 { + top = image.Rect(area.Min.X, area.Min.Y, area.Max.X, area.Min.Y+heightFixed) + bottom = image.Rect(area.Min.X, area.Min.Y+heightFixed, area.Max.X, area.Max.Y) } else { height := area.Dy() * heightPerc / 100 top = image.Rect(area.Min.X, area.Min.Y, area.Max.X, area.Min.Y+height) @@ -76,16 +75,29 @@ func HSplit(area image.Rectangle, heightPerc int, topHeight int, bottomHeight in // specified percentage of its width. The percentage must be in the range // 0 <= widthPerc <= 100. // Can return zero size areas. -func VSplit(area image.Rectangle, widthPerc int) (left image.Rectangle, right image.Rectangle, err error) { +// +// The fixed value must by in the range -1 <= heightFixed. +// If fixed value is -1 (default value), heightPerc is used instead. +func VSplit(area image.Rectangle, widthPerc int, widthFixed int) (left image.Rectangle, right image.Rectangle, err error) { if min, max := 0, 100; widthPerc < min || widthPerc > max { return image.ZR, image.ZR, fmt.Errorf("invalid widthPerc %d, must be in range %d <= widthPerc <= %d", widthPerc, min, max) } - width := area.Dx() * widthPerc / 100 - left = image.Rect(area.Min.X, area.Min.Y, area.Min.X+width, area.Max.Y) + if widthFixed < -1 { + return image.ZR, image.ZR, fmt.Errorf("invalid widthFixed %d, must be in range %d <= widthFixed", widthFixed, -1) + } + + // Prioritize `SplitFixed()` over `SplitPercent()`. + if widthFixed >= 0 { + left = image.Rect(area.Min.X, area.Min.Y, area.Min.X+widthFixed, area.Max.Y) + right = image.Rect(area.Min.X+widthFixed, area.Min.Y, area.Max.X, area.Max.Y) + } else { + width := area.Dx() * widthPerc / 100 + left = image.Rect(area.Min.X, area.Min.Y, area.Min.X+width, area.Max.Y) + right = image.Rect(area.Min.X+width, area.Min.Y, area.Max.X, area.Max.Y) + } if left.Dx() == 0 { left = image.ZR } - right = image.Rect(area.Min.X+width, area.Min.Y, area.Max.X, area.Max.Y) if right.Dx() == 0 { right = image.ZR } diff --git a/internal/area/area_test.go b/internal/area/area_test.go index 4acd496..54dba59 100644 --- a/internal/area/area_test.go +++ b/internal/area/area_test.go @@ -184,7 +184,7 @@ func TestHSplit(t *testing.T) { for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { - gotTop, gotBot, err := HSplit(tc.area, tc.heightPerc) + gotTop, gotBot, err := HSplit(tc.area, tc.heightPerc, -1) if (err != nil) != tc.wantErr { t.Errorf("VSplit => unexpected error:%v, wantErr:%v", err, tc.wantErr) } @@ -265,7 +265,7 @@ func TestVSplit(t *testing.T) { for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { - gotLeft, gotRight, err := VSplit(tc.area, tc.widthPerc) + gotLeft, gotRight, err := VSplit(tc.area, tc.widthPerc, -1) if (err != nil) != tc.wantErr { t.Errorf("VSplit => unexpected error:%v, wantErr:%v", err, tc.wantErr) } diff --git a/widgets/textinput/textinput.go b/widgets/textinput/textinput.go index cc2de60..d58343c 100644 --- a/widgets/textinput/textinput.go +++ b/widgets/textinput/textinput.go @@ -330,7 +330,7 @@ func split(cvsAr image.Rectangle, label string, widthPerc *int) (labelAr, textAr switch { case widthPerc != nil: splitP := 100 - *widthPerc - labelAr, textAr, err := area.VSplit(cvsAr, splitP) + labelAr, textAr, err := area.VSplit(cvsAr, splitP, -1) if err != nil { return image.ZR, image.ZR, err }