mirror of https://github.com/mum4k/termdash.git
314 lines
7.9 KiB
Go
314 lines
7.9 KiB
Go
package container
|
|
|
|
// options.go defines container options.
|
|
|
|
import (
|
|
"github.com/mum4k/termdash/draw"
|
|
"github.com/mum4k/termdash/widget"
|
|
)
|
|
|
|
// applyOptions applies the options to the container.
|
|
func applyOptions(c *Container, opts ...Option) {
|
|
for _, opt := range opts {
|
|
opt.set(c)
|
|
}
|
|
}
|
|
|
|
// Option is used to provide options to a container.
|
|
type Option interface {
|
|
// set sets the provided option.
|
|
set(*Container)
|
|
}
|
|
|
|
// options stores the options provided to the container.
|
|
type options struct {
|
|
// split identifies how is this container split.
|
|
split splitType
|
|
|
|
// widget is the widget in the container.
|
|
// A container can have either two sub containers (left and right) or a
|
|
// widget. But not both.
|
|
widget widget.Widget
|
|
|
|
// Alignment of the widget if present.
|
|
hAlign hAlignType
|
|
vAlign vAlignType
|
|
|
|
// border is the border around the container.
|
|
border draw.LineStyle
|
|
}
|
|
|
|
// option implements Option.
|
|
type option func(*Container)
|
|
|
|
// set implements Option.set.
|
|
func (o option) set(c *Container) {
|
|
o(c)
|
|
}
|
|
|
|
// SplitVertical splits the container along the vertical axis into two sub
|
|
// containers. The use of this option removes any widget placed at this
|
|
// container, containers with sub containers cannot contain widgets.
|
|
func SplitVertical(l LeftOption, r RightOption) Option {
|
|
return option(func(c *Container) {
|
|
c.opts.split = splitTypeVertical
|
|
c.opts.widget = nil
|
|
applyOptions(c.createFirst(), l.lOpts()...)
|
|
applyOptions(c.createSecond(), r.rOpts()...)
|
|
})
|
|
}
|
|
|
|
// SplitHorizontal splits the container along the horizontal axis into two sub
|
|
// containers. The use of this option removes any widget placed at this
|
|
// container, containers with sub containers cannot contain widgets.
|
|
func SplitHorizontal(t TopOption, b BottomOption) Option {
|
|
return option(func(c *Container) {
|
|
c.opts.split = splitTypeHorizontal
|
|
c.opts.widget = nil
|
|
applyOptions(c.createFirst(), t.tOpts()...)
|
|
applyOptions(c.createSecond(), b.bOpts()...)
|
|
})
|
|
}
|
|
|
|
// PlaceWidget places the provided widget into the container.
|
|
// The use of this option removes any sub containers. Containers with sub
|
|
// containers cannot have widgets.
|
|
func PlaceWidget(w widget.Widget) Option {
|
|
return option(func(c *Container) {
|
|
c.opts.widget = w
|
|
c.first = nil
|
|
c.second = nil
|
|
})
|
|
}
|
|
|
|
// HorizontalAlignLeft aligns the placed widget on the left of the
|
|
// container along the horizontal axis. Has no effect if the container contains
|
|
// no widget. This is the default horizontal alignment if no other is specified.
|
|
func HorizontalAlignLeft() Option {
|
|
return option(func(c *Container) {
|
|
c.opts.hAlign = hAlignTypeLeft
|
|
})
|
|
}
|
|
|
|
// HorizontalAlignCenter aligns the placed widget in the center of the
|
|
// container along the horizontal axis. Has no effect if the container contains
|
|
// no widget.
|
|
func HorizontalAlignCenter() Option {
|
|
return option(func(c *Container) {
|
|
c.opts.hAlign = hAlignTypeCenter
|
|
})
|
|
}
|
|
|
|
// HorizontalAlignRight aligns the placed widget on the right of the
|
|
// container along the horizontal axis. Has no effect if the container contains
|
|
// no widget.
|
|
func HorizontalAlignRight() Option {
|
|
return option(func(c *Container) {
|
|
c.opts.hAlign = hAlignTypeRight
|
|
})
|
|
}
|
|
|
|
// VerticalAlignTop aligns the placed widget on the top of the
|
|
// container along the vertical axis. Has no effect if the container contains
|
|
// no widget. This is the default vertical alignment if no other is specified.
|
|
func VerticalAlignTop() Option {
|
|
return option(func(c *Container) {
|
|
c.opts.vAlign = vAlignTypeTop
|
|
})
|
|
}
|
|
|
|
// VerticalAlignMiddle aligns the placed widget in the middle of the
|
|
// container along the vertical axis. Has no effect if the container contains
|
|
// no widget.
|
|
func VerticalAlignMiddle() Option {
|
|
return option(func(c *Container) {
|
|
c.opts.vAlign = vAlignTypeMiddle
|
|
})
|
|
}
|
|
|
|
// VerticalAlignBottom aligns the placed widget at the bottom of the
|
|
// container along the vertical axis. Has no effect if the container contains
|
|
// no widget.
|
|
func VerticalAlignBottom() Option {
|
|
return option(func(c *Container) {
|
|
c.opts.vAlign = vAlignTypeBottom
|
|
})
|
|
}
|
|
|
|
// Border configures the container to have a border of the specified style.
|
|
func Border(ls draw.LineStyle) Option {
|
|
return option(func(c *Container) {
|
|
c.opts.border = ls
|
|
})
|
|
}
|
|
|
|
// splitType identifies how a container is split.
|
|
type splitType int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (st splitType) String() string {
|
|
if n, ok := splitTypeNames[st]; ok {
|
|
return n
|
|
}
|
|
return "splitTypeUnknown"
|
|
}
|
|
|
|
// splitTypeNames maps splitType values to human readable names.
|
|
var splitTypeNames = map[splitType]string{
|
|
splitTypeVertical: "splitTypeVertical",
|
|
splitTypeHorizontal: "splitTypeHorizontal",
|
|
}
|
|
|
|
const (
|
|
splitTypeVertical splitType = iota
|
|
splitTypeHorizontal
|
|
)
|
|
|
|
// hAlignType indicates the horizontal alignment of the widget in the container.
|
|
type hAlignType int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (hat hAlignType) String() string {
|
|
if n, ok := hAlignTypeNames[hat]; ok {
|
|
return n
|
|
}
|
|
return "hAlignTypeUnknown"
|
|
}
|
|
|
|
// hAlignTypeNames maps hAlignType values to human readable names.
|
|
var hAlignTypeNames = map[hAlignType]string{
|
|
hAlignTypeLeft: "hAlignTypeLeft",
|
|
hAlignTypeCenter: "hAlignTypeCenter",
|
|
hAlignTypeRight: "hAlignTypeRight",
|
|
}
|
|
|
|
const (
|
|
hAlignTypeLeft hAlignType = iota
|
|
hAlignTypeCenter
|
|
hAlignTypeRight
|
|
)
|
|
|
|
// vAlignType represents
|
|
type vAlignType int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (vat vAlignType) String() string {
|
|
if n, ok := vAlignTypeNames[vat]; ok {
|
|
return n
|
|
}
|
|
return "vAlignTypeUnknown"
|
|
}
|
|
|
|
// vAlignTypeNames maps vAlignType values to human readable names.
|
|
var vAlignTypeNames = map[vAlignType]string{
|
|
vAlignTypeTop: "vAlignTypeTop",
|
|
vAlignTypeMiddle: "vAlignTypeMiddle",
|
|
vAlignTypeBottom: "vAlignTypeBottom",
|
|
}
|
|
|
|
const (
|
|
vAlignTypeTop vAlignType = iota
|
|
vAlignTypeMiddle
|
|
vAlignTypeBottom
|
|
)
|
|
|
|
// LeftOption is used to provide options to the left sub container after a
|
|
// vertical split of the parent.
|
|
type LeftOption interface {
|
|
// lOpts returns the options.
|
|
lOpts() []Option
|
|
}
|
|
|
|
// leftOption implements LeftOption.
|
|
type leftOption func() []Option
|
|
|
|
// lOpts implements LeftOption.lOpts.
|
|
func (lo leftOption) lOpts() []Option {
|
|
if lo == nil {
|
|
return nil
|
|
}
|
|
return lo()
|
|
}
|
|
|
|
// Left applies options to the left sub container after a vertical split of the parent.
|
|
func Left(opts ...Option) LeftOption {
|
|
return leftOption(func() []Option {
|
|
return opts
|
|
})
|
|
}
|
|
|
|
// RightOption is used to provide options to the right sub container after a
|
|
// vertical split of the parent.
|
|
type RightOption interface {
|
|
// rOpts returns the options.
|
|
rOpts() []Option
|
|
}
|
|
|
|
// rightOption implements RightOption.
|
|
type rightOption func() []Option
|
|
|
|
// rOpts implements RightOption.rOpts.
|
|
func (lo rightOption) rOpts() []Option {
|
|
if lo == nil {
|
|
return nil
|
|
}
|
|
return lo()
|
|
}
|
|
|
|
// Right applies options to the right sub container after a vertical split of the parent.
|
|
func Right(opts ...Option) RightOption {
|
|
return rightOption(func() []Option {
|
|
return opts
|
|
})
|
|
}
|
|
|
|
// TopOption is used to provide options to the top sub container after a
|
|
// horizontal split of the parent.
|
|
type TopOption interface {
|
|
// tOpts returns the options.
|
|
tOpts() []Option
|
|
}
|
|
|
|
// topOption implements TopOption.
|
|
type topOption func() []Option
|
|
|
|
// tOpts implements TopOption.tOpts.
|
|
func (lo topOption) tOpts() []Option {
|
|
if lo == nil {
|
|
return nil
|
|
}
|
|
return lo()
|
|
}
|
|
|
|
// Top applies options to the top sub container after a horizontal split of the parent.
|
|
func Top(opts ...Option) TopOption {
|
|
return topOption(func() []Option {
|
|
return opts
|
|
})
|
|
}
|
|
|
|
// BottomOption is used to provide options to the bottom sub container after a
|
|
// horizontal split of the parent.
|
|
type BottomOption interface {
|
|
// bOpts returns the options.
|
|
bOpts() []Option
|
|
}
|
|
|
|
// bottomOption implements BottomOption.
|
|
type bottomOption func() []Option
|
|
|
|
// bOpts implements BottomOption.bOpts.
|
|
func (lo bottomOption) bOpts() []Option {
|
|
if lo == nil {
|
|
return nil
|
|
}
|
|
return lo()
|
|
}
|
|
|
|
// Bottom applies options to the bottom sub container after a horizontal split of the parent.
|
|
func Bottom(opts ...Option) BottomOption {
|
|
return bottomOption(func() []Option {
|
|
return opts
|
|
})
|
|
}
|