From f128e8508c7d157f19163bbaf42f925b09b3b102 Mon Sep 17 00:00:00 2001 From: Jakub Sobon Date: Mon, 7 May 2018 18:48:52 +0100 Subject: [PATCH] Container's border now supports a title. Fixes #22. Fixes #19. --- container/draw.go | 7 ++- container/draw_test.go | 140 +++++++++++++++++++++++++++++++++++++++++ container/options.go | 32 +++++++++- 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/container/draw.go b/container/draw.go index bb711de..91f1e6b 100644 --- a/container/draw.go +++ b/container/draw.go @@ -75,7 +75,12 @@ func drawBorder(c *Container) error { cOpts = append(cOpts, cell.FgColor(c.opts.inherited.borderColor)) } - if err := draw.Border(cvs, ar, draw.BorderLineStyle(c.opts.border), draw.BorderCellOpts(cOpts...)); err != nil { + if err := draw.Border(cvs, ar, + draw.BorderLineStyle(c.opts.border), + draw.BorderTitle(c.opts.borderTitle, draw.OverrunModeThreeDot, cOpts...), + draw.BorderTitleAlign(c.opts.borderTitleHAlign), + draw.BorderCellOpts(cOpts...), + ); err != nil { return err } return cvs.Apply(c.term) diff --git a/container/draw_test.go b/container/draw_test.go index bb56d7d..8a57813 100644 --- a/container/draw_test.go +++ b/container/draw_test.go @@ -18,6 +18,7 @@ import ( "image" "testing" + "github.com/mum4k/termdash/align" "github.com/mum4k/termdash/canvas/testcanvas" "github.com/mum4k/termdash/cell" "github.com/mum4k/termdash/draw" @@ -62,6 +63,145 @@ func TestDrawWidget(t *testing.T) { return ft }, }, + { + desc: "draws widget with container border and title aligned on the left", + termSize: image.Point{9, 5}, + container: func(ft *faketerm.Terminal) *Container { + return New( + ft, + Border(draw.LineStyleLight), + BorderTitle("ab"), + BorderTitleAlignLeft(), + PlaceWidget(fakewidget.New(widgetapi.Options{})), + ) + }, + want: func(size image.Point) *faketerm.Terminal { + ft := faketerm.MustNew(size) + cvs := testcanvas.MustNew(ft.Area()) + // Container border. + testdraw.MustBorder( + cvs, + cvs.Area(), + draw.BorderCellOpts(cell.FgColor(cell.ColorYellow)), + draw.BorderTitle( + "ab", + draw.OverrunModeThreeDot, + cell.FgColor(cell.ColorYellow), + ), + ) + + // Fake widget border. + testdraw.MustBorder(cvs, image.Rect(1, 1, 8, 4)) + testdraw.MustText(cvs, "(7,3)", image.Point{2, 2}) + testcanvas.MustApply(cvs, ft) + return ft + }, + }, + { + desc: "draws widget with container border and title aligned in the center", + termSize: image.Point{9, 5}, + container: func(ft *faketerm.Terminal) *Container { + return New( + ft, + Border(draw.LineStyleLight), + BorderTitle("ab"), + BorderTitleAlignCenter(), + PlaceWidget(fakewidget.New(widgetapi.Options{})), + ) + }, + want: func(size image.Point) *faketerm.Terminal { + ft := faketerm.MustNew(size) + cvs := testcanvas.MustNew(ft.Area()) + // Container border. + testdraw.MustBorder( + cvs, + cvs.Area(), + draw.BorderCellOpts(cell.FgColor(cell.ColorYellow)), + draw.BorderTitle( + "ab", + draw.OverrunModeThreeDot, + cell.FgColor(cell.ColorYellow), + ), + draw.BorderTitleAlign(align.HorizontalCenter), + ) + + // Fake widget border. + testdraw.MustBorder(cvs, image.Rect(1, 1, 8, 4)) + testdraw.MustText(cvs, "(7,3)", image.Point{2, 2}) + testcanvas.MustApply(cvs, ft) + return ft + }, + }, + { + desc: "draws widget with container border and title aligned on the right", + termSize: image.Point{9, 5}, + container: func(ft *faketerm.Terminal) *Container { + return New( + ft, + Border(draw.LineStyleLight), + BorderTitle("ab"), + BorderTitleAlignRight(), + PlaceWidget(fakewidget.New(widgetapi.Options{})), + ) + }, + want: func(size image.Point) *faketerm.Terminal { + ft := faketerm.MustNew(size) + cvs := testcanvas.MustNew(ft.Area()) + // Container border. + testdraw.MustBorder( + cvs, + cvs.Area(), + draw.BorderCellOpts(cell.FgColor(cell.ColorYellow)), + draw.BorderTitle( + "ab", + draw.OverrunModeThreeDot, + cell.FgColor(cell.ColorYellow), + ), + draw.BorderTitleAlign(align.HorizontalRight), + ) + + // Fake widget border. + testdraw.MustBorder(cvs, image.Rect(1, 1, 8, 4)) + testdraw.MustText(cvs, "(7,3)", image.Point{2, 2}) + testcanvas.MustApply(cvs, ft) + return ft + }, + }, + { + desc: "draws widget with container border and title that is trimmed", + termSize: image.Point{9, 5}, + container: func(ft *faketerm.Terminal) *Container { + return New( + ft, + Border(draw.LineStyleLight), + BorderTitle("abcdefgh"), + BorderTitleAlignRight(), + PlaceWidget(fakewidget.New(widgetapi.Options{})), + ) + }, + want: func(size image.Point) *faketerm.Terminal { + ft := faketerm.MustNew(size) + cvs := testcanvas.MustNew(ft.Area()) + // Container border. + testdraw.MustBorder( + cvs, + cvs.Area(), + draw.BorderCellOpts(cell.FgColor(cell.ColorYellow)), + draw.BorderTitle( + "abcdefgh", + draw.OverrunModeThreeDot, + cell.FgColor(cell.ColorYellow), + ), + draw.BorderTitleAlign(align.HorizontalRight), + ) + + // Fake widget border. + testdraw.MustBorder(cvs, image.Rect(1, 1, 8, 4)) + testdraw.MustText(cvs, "(7,3)", image.Point{2, 2}) + testcanvas.MustApply(cvs, ft) + return ft + }, + }, { desc: "draws widget without container border", termSize: image.Point{9, 5}, diff --git a/container/options.go b/container/options.go index b3ec44c..b7ae8da 100644 --- a/container/options.go +++ b/container/options.go @@ -54,7 +54,9 @@ type options struct { vAlign align.Vertical // border is the border around the container. - border draw.LineStyle + border draw.LineStyle + borderTitle string + borderTitleHAlign align.Horizontal } // inherited contains options that are inherited by child containers. @@ -184,6 +186,34 @@ func Border(ls draw.LineStyle) Option { }) } +// BorderTitle sets a text title within the border. +func BorderTitle(title string) Option { + return option(func(c *Container) { + c.opts.borderTitle = title + }) +} + +// BorderTitleAlignLeft aligns the border title on the left. +func BorderTitleAlignLeft() Option { + return option(func(c *Container) { + c.opts.borderTitleHAlign = align.HorizontalLeft + }) +} + +// BorderTitleAlignCenter aligns the border title in the center. +func BorderTitleAlignCenter() Option { + return option(func(c *Container) { + c.opts.borderTitleHAlign = align.HorizontalCenter + }) +} + +// BorderTitleAlignRight aligns the border title on the right. +func BorderTitleAlignRight() Option { + return option(func(c *Container) { + c.opts.borderTitleHAlign = align.HorizontalRight + }) +} + // BorderColor sets the color of the border around the container. // This option is inherited to sub containers created by container splits. func BorderColor(color cell.Color) Option {