From 0d284e1fb8b05ac4bbecc713dfab3daccffd0a06 Mon Sep 17 00:00:00 2001 From: Charles Eckman Date: Tue, 9 Jan 2018 13:21:24 -0800 Subject: [PATCH 1/6] Mostly revert "Make Box FillRect (so, style) its interior." This reverts commit 171ef323de3f6034667fb1dfd3084db532bdcd18. It has some calls to methods that don't yet exist- making Box's fill behavior optional. This allows it to be used for layout as well as styling. --- box.go | 3 - box_test.go | 241 ++++++++++++++++++++++---------------------- cjk_test.go | 6 +- entry_test.go | 24 ++--- scroll_area_test.go | 14 +-- table_test.go | 22 ++-- 6 files changed, 151 insertions(+), 159 deletions(-) diff --git a/box.go b/box.go index 5780dae..a9d5a07 100644 --- a/box.go +++ b/box.go @@ -126,11 +126,8 @@ func (b *Box) Draw(p *Painter) { p.DrawText(1, 0, b.title) }) }) - p.FillRect(1, 1, sz.X-2, sz.Y-2) p.Translate(1, 1) defer p.Restore() - } else { - p.FillRect(0, 0, sz.X, sz.Y) } var off image.Point diff --git a/box_test.go b/box_test.go index 12a04bd..bccabc8 100644 --- a/box_test.go +++ b/box_test.go @@ -20,9 +20,9 @@ var drawBoxTests = []struct { }, want: ` ┌────────┐ -│ │ -│ │ -│ │ +│........│ +│........│ +│........│ └────────┘ `, }, @@ -35,9 +35,9 @@ var drawBoxTests = []struct { }, want: ` ┌────────┐ -│test │ -│ │ -│ │ +│test....│ +│........│ +│........│ └────────┘ `, }, @@ -50,9 +50,9 @@ var drawBoxTests = []struct { }, want: ` ┌────────┐ -│testfoo │ -│ │ -│ │ +│testfoo.│ +│........│ +│........│ └────────┘ `, }, @@ -65,9 +65,9 @@ var drawBoxTests = []struct { }, want: ` ┌────────┐ -│ │ -│ │ -│ │ +│........│ +│........│ +│........│ └────────┘ `, }, @@ -80,9 +80,9 @@ var drawBoxTests = []struct { }, want: ` ┌────────┐ -│test │ -│ │ -│ │ +│test....│ +│........│ +│........│ └────────┘ `, }, @@ -95,9 +95,9 @@ var drawBoxTests = []struct { }, want: ` ┌────────┐ -│test │ -│ │ -│foo │ +│test....│ +│........│ +│foo.....│ └────────┘ `, }, @@ -114,9 +114,9 @@ var drawBoxTests = []struct { }, want: ` ┌──────────────────────────────┐ -│ ┌────┐ │ -│ │test│ │ -│ └────┘ │ +│............┌────┐............│ +│............│test│............│ +│............└────┘............│ └──────────────────────────────┘ `, }, @@ -138,12 +138,12 @@ var drawBoxTests = []struct { want: ` ┌──────────────────────────────┐ │┌─────────────┐┌─────────────┐│ -││test ││test ││ -││ ││ ││ -││ ││ ││ -││ ││ ││ -││ ││ ││ -││ ││ ││ +││test.........││test.........││ +││.............││.............││ +││.............││.............││ +││.............││.............││ +││.............││.............││ +││.............││.............││ │└─────────────┘└─────────────┘│ └──────────────────────────────┘ `, @@ -177,22 +177,22 @@ var drawBoxTests = []struct { ┌──────────────────────────────┐ │┌────────────────────────────┐│ ││┌────────────┐┌────────────┐││ -│││test ││test │││ -│││ ││ │││ -│││ ││ │││ -│││ ││ │││ -│││ ││ │││ -│││ ││ │││ +│││test........││test........│││ +│││............││............│││ +│││............││............│││ +│││............││............│││ +│││............││............│││ +│││............││............│││ ││└────────────┘└────────────┘││ │└────────────────────────────┘│ │┌────────────────────────────┐│ ││┌────────────┐┌────────────┐││ -│││test ││test │││ -│││ ││ │││ -│││ ││ │││ -│││ ││ │││ -│││ ││ │││ -│││ ││ │││ +│││test........││test........│││ +│││............││............│││ +│││............││............│││ +│││............││............│││ +│││............││............│││ +│││............││............│││ ││└────────────┘└────────────┘││ │└────────────────────────────┘│ └──────────────────────────────┘ @@ -228,26 +228,26 @@ var drawBoxTests = []struct { want: ` ┌──────────────────────────────┐ │┌────────────────────────────┐│ -││test ││ -││testing ││ -││foo ││ -││bar ││ +││test........................││ +││testing.....................││ +││foo.........................││ +││bar.........................││ │└────────────────────────────┘│ │┌────────────────────────────┐│ -││test ││ -││testing ││ -││foo ││ -││bar ││ -││ ││ -││ ││ +││test........................││ +││testing.....................││ +││foo.........................││ +││bar.........................││ +││............................││ +││............................││ │└────────────────────────────┘│ │┌────────────────────────────┐│ -││foo ││ -││ ││ -││ ││ -││ ││ -││ ││ -││ ││ +││foo.........................││ +││............................││ +││............................││ +││............................││ +││............................││ +││............................││ │└────────────────────────────┘│ └──────────────────────────────┘ `, @@ -262,9 +262,9 @@ var drawBoxTests = []struct { }, want: ` ┌Title───┐ -│test │ -│ │ -│ │ +│test....│ +│........│ +│........│ └────────┘ `, }, @@ -278,9 +278,9 @@ var drawBoxTests = []struct { }, want: ` ┌Very lon┐ -│test │ -│ │ -│ │ +│test....│ +│........│ +│........│ └────────┘ `, }, @@ -308,34 +308,26 @@ func TestBox_Draw(t *testing.T) { } var styleBoxTests = []struct { - test string - setup func() *Box - theme func() *Theme - wantContents string - wantColors string + test string + setup func() *Box + theme func() *Theme + wantColors string wantDecorations string }{ { test: "Red horizontal box", setup: func() *Box { b := NewHBox() - b.SetBorder(true) + b.SetFill(true) return b }, - theme: func() *Theme { + theme: func() *Theme{ t := NewTheme() t.SetStyle("box", Style{ Fg: Color(3), }) return t }, - wantContents: ` -┌────────┐ -│ │ -│ │ -│ │ -└────────┘ -`, wantColors: ` 3333333333 3333333333 @@ -352,6 +344,7 @@ var styleBoxTests = []struct { styled.SetStyleName("blue") box := NewVBox(unstyled, styled) box.SetBorder(true) + box.SetFill(true) return box }, theme: func() *Theme { @@ -390,10 +383,12 @@ var styleBoxTests = []struct { { test: "Styled box, labels inherit", setup: func() *Box { - return NewVBox( + b := NewVBox( NewLabel("label 1"), NewLabel("label 2"), ) + b.SetFill(true) + return b }, theme: func() *Theme { t := NewTheme() @@ -433,6 +428,7 @@ label 2 NewLabel("label 2"), ) r.SetBorder(true) + r.SetFill(true) return r }, theme: func() *Theme { @@ -477,9 +473,6 @@ func TestBox_Style(t *testing.T) { painter := NewPainter(surface, tt.theme()) painter.Repaint(tt.setup()) - if tt.wantContents != "" && surface.String() != tt.wantContents { - t.Errorf("wrong contents: got = \n%s\n\nwant = \n%s", surface.String(), tt.wantContents) - } if tt.wantColors != "" && surface.FgColors() != tt.wantColors { t.Errorf("wrong colors: got = \n%s\n\nwant = \n%s", surface.FgColors(), tt.wantColors) } @@ -490,6 +483,8 @@ func TestBox_Style(t *testing.T) { } } + + func TestBox_IsFocused(t *testing.T) { btn := NewButton("Test box focus") box := NewVBox(btn) @@ -516,14 +511,14 @@ var insertWidgetTests = []struct { index: 0, want: ` ┌──────────────────┐ -│Insertion │ -│ │ -│Test 0 │ -│ │ -│Test 1 │ -│ │ -│Test 2 │ -│ │ +│Insertion.........│ +│..................│ +│Test 0............│ +│..................│ +│Test 1............│ +│..................│ +│Test 2............│ +│..................│ └──────────────────┘ `, }, @@ -532,14 +527,14 @@ var insertWidgetTests = []struct { index: 1, want: ` ┌──────────────────┐ -│Test 0 │ -│ │ -│Insertion │ -│ │ -│Test 1 │ -│ │ -│Test 2 │ -│ │ +│Test 0............│ +│..................│ +│Insertion.........│ +│..................│ +│Test 1............│ +│..................│ +│Test 2............│ +│..................│ └──────────────────┘ `, }, @@ -548,14 +543,14 @@ var insertWidgetTests = []struct { index: 5, want: ` ┌──────────────────┐ -│Test 0 │ -│ │ -│ │ -│Test 1 │ -│ │ -│ │ -│Test 2 │ -│ │ +│Test 0............│ +│..................│ +│..................│ +│Test 1............│ +│..................│ +│..................│ +│Test 2............│ +│..................│ └──────────────────┘ `, }, @@ -564,14 +559,14 @@ var insertWidgetTests = []struct { index: 3, want: ` ┌──────────────────┐ -│Test 0 │ -│ │ -│Test 1 │ -│ │ -│Test 2 │ -│ │ -│Insertion │ -│ │ +│Test 0............│ +│..................│ +│Test 1............│ +│..................│ +│Test 2............│ +│..................│ +│Insertion.........│ +│..................│ └──────────────────┘ `, }, @@ -607,14 +602,14 @@ func TestBox_Insert(t *testing.T) { func TestBox_Prepend(t *testing.T) { want := ` ┌──────────────────┐ -│Prepend │ -│ │ -│Test 0 │ -│ │ -│Test 1 │ -│ │ -│Test 2 │ -│ │ +│Prepend...........│ +│..................│ +│Test 0............│ +│..................│ +│Test 1............│ +│..................│ +│Test 2............│ +│..................│ └──────────────────┘ ` surface := NewTestSurface(20, 10) @@ -641,10 +636,10 @@ func TestBox_Prepend(t *testing.T) { func TestBox_Remove(t *testing.T) { want := ` ┌──────────────────┐ -│Test 0 │ -│ │ -│Test 2 │ -│ │ +│Test 0............│ +│..................│ +│Test 2............│ +│..................│ └──────────────────┘ ` surface := NewTestSurface(20, 6) diff --git a/cjk_test.go b/cjk_test.go index d359311..1f306cb 100644 --- a/cjk_test.go +++ b/cjk_test.go @@ -48,8 +48,8 @@ var drawCJKTests = []struct { }, want: ` ┌标题────┐ -│测试 │ -│ │ +│测试....│ +│........│ └────────┘ `, }, @@ -65,7 +65,7 @@ var drawCJKTests = []struct { want: ` ┌────────┐ │テスト │ -│ │ +│........│ └────────┘ `, }, diff --git a/entry_test.go b/entry_test.go index 228dd65..75a8a40 100644 --- a/entry_test.go +++ b/entry_test.go @@ -171,8 +171,8 @@ var layoutEntryTests = []struct { want: ` ┌──────────────────┐ │ │ -│ │ -│ │ +│..................│ +│..................│ └──────────────────┘ `, }, @@ -198,8 +198,8 @@ var layoutEntryTests = []struct { want: ` ┌──────────────────┐ │456789foo456789bar│ -│ │ -│ │ +│..................│ +│..................│ └──────────────────┘ `, }, @@ -224,8 +224,8 @@ var layoutEntryTests = []struct { want: ` ┌──────────────────┐ │56789foo3456789bar│ -│ │ -│ │ +│..................│ +│..................│ └──────────────────┘ `, }, @@ -250,8 +250,8 @@ var layoutEntryTests = []struct { want: ` ┌──────────────────┐ │3456789foo56789bar│ -│ │ -│ │ +│..................│ +│..................│ └──────────────────┘ `, }, @@ -275,8 +275,8 @@ var layoutEntryTests = []struct { want: ` ┌──────────────────┐ │foo bar │ -│ │ -│ │ +│..................│ +│..................│ └──────────────────┘ `, }, @@ -299,8 +299,8 @@ var layoutEntryTests = []struct { want: ` ┌──────────────────┐ │foo bar │ -│ │ -│ │ +│..................│ +│..................│ └──────────────────┘ `, }, diff --git a/scroll_area_test.go b/scroll_area_test.go index 6e37a66..45b4492 100644 --- a/scroll_area_test.go +++ b/scroll_area_test.go @@ -161,8 +161,8 @@ var drawNestedScrollAreaTests = []struct { │└───────┘│ │┌───────┐│ ││└─────┘││ -││ ││ -││ ││ +││.......││ +││.......││ │└───────┘│ └─────────┘ `, @@ -194,11 +194,11 @@ var drawNestedScrollAreaTests = []struct { want: ` ┌──────────────────┐ │┌───────┐┌───────┐│ -││ ┌─││1234567││ -││ │┌││ ││ -││ ││││ ││ -││ │└││ ││ -││ └─││ ││ +││.....┌─││1234567││ +││.....│┌││.......││ +││.....││││.......││ +││.....│└││.......││ +││.....└─││.......││ │└───────┘└───────┘│ └──────────────────┘ `, diff --git a/table_test.go b/table_test.go index 16bf34d..6049069 100644 --- a/table_test.go +++ b/table_test.go @@ -33,11 +33,11 @@ var drawTableTests = []struct { ┌──────────────────────────────┐ │┌───────────┬──────────┐┌────┐│ ││ABC123 │test ││test││ -││ │ ││ ││ -│├───────────┼──────────┤│ ││ -││DEF456 │testing a ││ ││ -│├───────────┼──────────┤│ ││ -││GHI789 │foo ││ ││ +││ │ ││....││ +│├───────────┼──────────┤│....││ +││DEF456 │testing a ││....││ +│├───────────┼──────────┤│....││ +││GHI789 │foo ││....││ │└───────────┴──────────┘└────┘│ └──────────────────────────────┘ `, @@ -94,12 +94,12 @@ var drawTableTests = []struct { want: ` ┌──────────────────┐ │┌────────┬───────┐│ -││ │ ││ -││ │ ││ -││ │ ││ -││ │ ││ -││ │ ││ -││ │ ││ +││........│.......││ +││........│.......││ +││........│.......││ +││........│.......││ +││........│.......││ +││........│.......││ │└────────┴───────┘│ └──────────────────┘ `, From 642a1b3b4ee52122f3040f46fb41461a2fdccd2c Mon Sep 17 00:00:00 2001 From: Charles Eckman Date: Tue, 9 Jan 2018 13:23:25 -0800 Subject: [PATCH 2/6] add SetFill --- box.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/box.go b/box.go index a9d5a07..5f0c181 100644 --- a/box.go +++ b/box.go @@ -25,6 +25,7 @@ type Box struct { children []Widget border bool + fill bool title string alignment Alignment @@ -86,6 +87,11 @@ func (b *Box) SetBorder(enabled bool) { b.border = enabled } +// SetFill sets whether or not the box should be filled cells of its style. +func (b *Box) SetFill(enabled bool) { + b.fill = enabled +} + // SetTitle sets the title of the box. func (b *Box) SetTitle(title string) { b.title = title @@ -121,13 +127,16 @@ func (b *Box) Draw(p *Painter) { p.WithStyle(style+".border", func(p *Painter) { p.DrawRect(0, 0, sz.X, sz.Y) }) - p.WithStyle(style, func(p *Painter) { - p.WithMask(image.Rect(0, 0, sz.X-1, 1), func(p *Painter) { - p.DrawText(1, 0, b.title) - }) + p.WithMask(image.Rect(0, 0, sz.X-1, 1), func(p *Painter) { + p.DrawText(1, 0, b.title) }) + if b.fill { + p.FillRect(1, 1, sz.X-2, sz.Y-2) + } p.Translate(1, 1) defer p.Restore() + } else if b.fill { + p.FillRect(0, 0, sz.X, sz.Y) } var off image.Point From be490b55d9b0a14e4b3b9a014f909fb7d86f8ca8 Mon Sep 17 00:00:00 2001 From: Charles Eckman Date: Tue, 9 Jan 2018 13:27:35 -0800 Subject: [PATCH 3/6] fix up tests for optional-fill behavior --- box_test.go | 4 ++++ cjk_test.go | 2 +- scroll_area_test.go | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/box_test.go b/box_test.go index bccabc8..70ae1b6 100644 --- a/box_test.go +++ b/box_test.go @@ -311,6 +311,7 @@ var styleBoxTests = []struct { test string setup func() *Box theme func() *Theme + wantContents string wantColors string wantDecorations string }{ @@ -473,6 +474,9 @@ func TestBox_Style(t *testing.T) { painter := NewPainter(surface, tt.theme()) painter.Repaint(tt.setup()) + if tt.wantContents != "" && surface.String() != tt.wantContents { + t.Errorf("wrong contents: got = \n%s\n\nwant = \n%s", surface.String(), tt.wantContents) + } if tt.wantColors != "" && surface.FgColors() != tt.wantColors { t.Errorf("wrong colors: got = \n%s\n\nwant = \n%s", surface.FgColors(), tt.wantColors) } diff --git a/cjk_test.go b/cjk_test.go index 1f306cb..f90f857 100644 --- a/cjk_test.go +++ b/cjk_test.go @@ -81,7 +81,7 @@ var drawCJKTests = []struct { want: ` ┌────────┐ │これはテ│ -│ │ +│........│ └────────┘ `, }, diff --git a/scroll_area_test.go b/scroll_area_test.go index 45b4492..d6be126 100644 --- a/scroll_area_test.go +++ b/scroll_area_test.go @@ -24,8 +24,8 @@ var drawScrollAreaTests = []struct { return a }, want: ` -foo ...... -bar ...... +foo....... +bar....... test...... `, }, @@ -42,8 +42,8 @@ test...... return a }, want: ` -foo ...... -bar ...... +foo....... +bar....... `, }, { @@ -60,7 +60,7 @@ bar ...... return a }, want: ` -bar ...... +bar....... test...... `, }, From 6b2926b08e114608fad09dfecfac401a60959e2e Mon Sep 17 00:00:00 2001 From: Charles Eckman Date: Tue, 9 Jan 2018 13:28:58 -0800 Subject: [PATCH 4/6] fix up tests for optional-fill behavior --- box_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/box_test.go b/box_test.go index 70ae1b6..f01dfc0 100644 --- a/box_test.go +++ b/box_test.go @@ -308,11 +308,11 @@ func TestBox_Draw(t *testing.T) { } var styleBoxTests = []struct { - test string - setup func() *Box - theme func() *Theme - wantContents string - wantColors string + test string + setup func() *Box + theme func() *Theme + wantContents string + wantColors string wantDecorations string }{ { @@ -322,7 +322,7 @@ var styleBoxTests = []struct { b.SetFill(true) return b }, - theme: func() *Theme{ + theme: func() *Theme { t := NewTheme() t.SetStyle("box", Style{ Fg: Color(3), @@ -419,6 +419,46 @@ label 2 2222222222 2222222222 2222222222 +`, + }, + + { + test: "no fill, labels inherit", + setup: func() *Box { + b := NewVBox( + NewLabel("label 1"), + NewLabel("label 2"), + ) + return b + }, + theme: func() *Theme { + t := NewTheme() + t.SetStyle("box", Style{ + Fg: Color(3), + Bold: DecorationOn, + }) + return t + }, + wantContents: ` +label 1... +.......... +.......... +label 2... +.......... +`, + wantColors: ` +3333333... +.......... +.......... +3333333... +.......... +`, + wantDecorations: ` +2222222... +.......... +.......... +2222222... +.......... `, }, { @@ -487,8 +527,6 @@ func TestBox_Style(t *testing.T) { } } - - func TestBox_IsFocused(t *testing.T) { btn := NewButton("Test box focus") box := NewVBox(btn) From 4f960defc0017d447ef1956f2b6e19e4131aa663 Mon Sep 17 00:00:00 2001 From: Charles Eckman Date: Sat, 13 Jan 2018 14:31:28 -0800 Subject: [PATCH 5/6] Add an example of how word-wrapping requires two layout cycles. --- label_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/label_test.go b/label_test.go index 6d91aa7..28a4026 100644 --- a/label_test.go +++ b/label_test.go @@ -1,6 +1,7 @@ package tui import ( + "fmt" "image" "testing" ) @@ -120,3 +121,45 @@ func TestLabel_Draw(t *testing.T) { } } } + +func ExampleWordWrap() { + s := NewTestSurface(15, 7) + painter := NewPainter(s, NewTheme()) + + center := func(w Widget) Widget { + return NewVBox(NewSpacer(), NewHBox(NewSpacer(), w, NewSpacer()), NewSpacer()) + } + + thanks := NewLabel("Thanks for using tui-go!") + thanks.SetWordWrap(true) + thanksBox := NewVBox(thanks) + thanksBox.SetBorder(true) + thanksBox.SetFill(true) + + root := center(thanksBox) + + // First painting: cuts off text + painter.Repaint(root) + fmt.Print(s.String()) + + // Second painting: wraps appropriately + painter.Repaint(root) + fmt.Print(s.String()) + + // Output: + // ............... + // ............... + // ┌─────────────┐ + // │Thanks for │ + // └─────────────┘ + // ............... + // ............... + // + // ............... + // ............... + // ┌─────────────┐ + // │Thanks for │ + // │using tui-go!│ + // └─────────────┘ + // ............... +} From 7992c8b56c8aff0884d435f54b2f359666c69ba2 Mon Sep 17 00:00:00 2001 From: Charles Eckman Date: Sat, 13 Jan 2018 14:59:15 -0800 Subject: [PATCH 6/6] Rename example per go vet --- label_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/label_test.go b/label_test.go index 28a4026..ec41333 100644 --- a/label_test.go +++ b/label_test.go @@ -122,7 +122,7 @@ func TestLabel_Draw(t *testing.T) { } } -func ExampleWordWrap() { +func ExampleLabel_SetWordWrap() { s := NewTestSurface(15, 7) painter := NewPainter(s, NewTheme())