mirror of https://github.com/mum4k/termdash.git
Button can be drawn without horizontal padding around its text.
This commit is contained in:
parent
ce3adfb084
commit
73644716a5
|
@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- the `button` widget allows users to specify multiple trigger keys.
|
||||
- the `button` widget can now be drawn without the shadow and the pressing the
|
||||
animation.
|
||||
- the `button` widget can now be drawn without horizontal padding around its
|
||||
text.
|
||||
|
||||
## [0.13.0] - 17-Nov-2020
|
||||
|
||||
|
|
|
@ -143,7 +143,8 @@ func (b *Button) Draw(cvs *canvas.Canvas, meta *widgetapi.Meta) error {
|
|||
return err
|
||||
}
|
||||
|
||||
textAr := image.Rect(buttonAr.Min.X+1, buttonAr.Min.Y, buttonAr.Dx()-1, buttonAr.Max.Y)
|
||||
pad := b.opts.textHorizontalPadding
|
||||
textAr := image.Rect(buttonAr.Min.X+pad, buttonAr.Min.Y, buttonAr.Dx()-pad, buttonAr.Max.Y)
|
||||
start, err := alignfor.Text(textAr, b.text, align.HorizontalCenter, align.VerticalMiddle)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -223,7 +224,7 @@ func (b *Button) shadowWidth() int {
|
|||
func (b *Button) Options() widgetapi.Options {
|
||||
// No need to lock, as the height and width get fixed when New is called.
|
||||
|
||||
width := b.opts.width + b.shadowWidth()
|
||||
width := b.opts.width + b.shadowWidth() + 2*b.opts.textHorizontalPadding
|
||||
height := b.opts.height + b.shadowWidth()
|
||||
return widgetapi.Options{
|
||||
MinimumSize: image.Point{width, height},
|
||||
|
|
|
@ -115,6 +115,15 @@ func TestButton(t *testing.T) {
|
|||
canvas: image.Rect(0, 0, 1, 1),
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
desc: "New fails with negative textHorizontalPadding",
|
||||
callback: &callbackTracker{},
|
||||
opts: []Option{
|
||||
TextHorizontalPadding(-1),
|
||||
},
|
||||
canvas: image.Rect(0, 0, 1, 1),
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
desc: "draw fails on canvas too small",
|
||||
callback: &callbackTracker{},
|
||||
|
@ -934,11 +943,25 @@ func TestOptions(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
desc: "custom width specified",
|
||||
desc: "custom width specified with default padding",
|
||||
text: "hello",
|
||||
opts: []Option{
|
||||
Width(10),
|
||||
},
|
||||
want: widgetapi.Options{
|
||||
MinimumSize: image.Point{13, 4},
|
||||
MaximumSize: image.Point{13, 4},
|
||||
WantKeyboard: widgetapi.KeyScopeNone,
|
||||
WantMouse: widgetapi.MouseScopeGlobal,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "custom width specified with custom padding",
|
||||
text: "hello",
|
||||
opts: []Option{
|
||||
Width(10),
|
||||
TextHorizontalPadding(0),
|
||||
},
|
||||
want: widgetapi.Options{
|
||||
MinimumSize: image.Point{11, 4},
|
||||
MaximumSize: image.Point{11, 4},
|
||||
|
@ -946,7 +969,21 @@ func TestOptions(t *testing.T) {
|
|||
WantMouse: widgetapi.MouseScopeGlobal,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
desc: "without shadow or padding",
|
||||
text: "hello",
|
||||
opts: []Option{
|
||||
Width(10),
|
||||
TextHorizontalPadding(0),
|
||||
DisableShadow(),
|
||||
},
|
||||
want: widgetapi.Options{
|
||||
MinimumSize: image.Point{10, 3},
|
||||
MaximumSize: image.Point{10, 3},
|
||||
WantKeyboard: widgetapi.KeyScopeNone,
|
||||
WantMouse: widgetapi.MouseScopeGlobal,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "doesn't want keyboard by default",
|
||||
text: "hello",
|
||||
|
|
|
@ -60,6 +60,7 @@ func main() {
|
|||
button.GlobalKeys('s', 'S'),
|
||||
button.DisableShadow(),
|
||||
button.Height(1),
|
||||
button.TextHorizontalPadding(0),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -75,6 +76,7 @@ func main() {
|
|||
button.GlobalKeys('c', 'C'),
|
||||
button.DisableShadow(),
|
||||
button.Height(1),
|
||||
button.TextHorizontalPadding(0),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -42,19 +42,23 @@ func (o option) set(opts *options) {
|
|||
|
||||
// options holds the provided options.
|
||||
type options struct {
|
||||
fillColor cell.Color
|
||||
textColor cell.Color
|
||||
shadowColor cell.Color
|
||||
disableShadow bool
|
||||
height int
|
||||
width int
|
||||
keys map[keyboard.Key]bool
|
||||
keyScope widgetapi.KeyScope
|
||||
keyUpDelay time.Duration
|
||||
fillColor cell.Color
|
||||
textColor cell.Color
|
||||
textHorizontalPadding int
|
||||
shadowColor cell.Color
|
||||
disableShadow bool
|
||||
height int
|
||||
width int
|
||||
keys map[keyboard.Key]bool
|
||||
keyScope widgetapi.KeyScope
|
||||
keyUpDelay time.Duration
|
||||
}
|
||||
|
||||
// validate validates the provided options.
|
||||
func (o *options) validate() error {
|
||||
if min := 0; o.textHorizontalPadding < min {
|
||||
return fmt.Errorf("invalid textHorizontalPadding %d, must be %d <= textHorizontalPadding", o.textHorizontalPadding, min)
|
||||
}
|
||||
if min := 1; o.height < min {
|
||||
return fmt.Errorf("invalid height %d, must be %d <= height", o.height, min)
|
||||
}
|
||||
|
@ -76,13 +80,14 @@ type keyScope struct {
|
|||
// newOptions returns options with the default values set.
|
||||
func newOptions(text string) *options {
|
||||
return &options{
|
||||
fillColor: cell.ColorNumber(117),
|
||||
textColor: cell.ColorBlack,
|
||||
shadowColor: cell.ColorNumber(240),
|
||||
height: DefaultHeight,
|
||||
width: widthFor(text),
|
||||
keyUpDelay: DefaultKeyUpDelay,
|
||||
keys: map[keyboard.Key]bool{},
|
||||
fillColor: cell.ColorNumber(117),
|
||||
textColor: cell.ColorBlack,
|
||||
textHorizontalPadding: DefaultTextHorizontalPadding,
|
||||
shadowColor: cell.ColorNumber(240),
|
||||
height: DefaultHeight,
|
||||
width: widthFor(text),
|
||||
keyUpDelay: DefaultKeyUpDelay,
|
||||
keys: map[keyboard.Key]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +127,8 @@ func Height(cells int) Option {
|
|||
// Width sets the width of the button in cells.
|
||||
// Must be a positive non-zero integer.
|
||||
// Defaults to the auto-width based on the length of the text label.
|
||||
// Not all the width may be available to the text if TextHorizontalPadding is
|
||||
// set to a non-zero integer.
|
||||
func Width(cells int) Option {
|
||||
return option(func(opts *options) {
|
||||
opts.width = cells
|
||||
|
@ -211,7 +218,18 @@ func DisableShadow() Option {
|
|||
})
|
||||
}
|
||||
|
||||
// DefaultTextHorizontalPadding is the default value for the HorizontalPadding option.
|
||||
const DefaultTextHorizontalPadding = 1
|
||||
|
||||
// TextHorizontalPadding sets padding on the left and right side of the
|
||||
// button's text as the amount of cells.
|
||||
func TextHorizontalPadding(p int) Option {
|
||||
return option(func(opts *options) {
|
||||
opts.textHorizontalPadding = p
|
||||
})
|
||||
}
|
||||
|
||||
// widthFor returns the required width for the specified text.
|
||||
func widthFor(text string) int {
|
||||
return runewidth.StringWidth(text) + 2 // One empty cell at each side.
|
||||
return runewidth.StringWidth(text)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue