mirror of https://github.com/mum4k/termdash.git
Container options for focus group support.
This commit is contained in:
parent
ec92395f6d
commit
fe482ab6e6
|
@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- ability to configure keyboard keys that move focus to the next or the
|
||||
previous container.
|
||||
- containers can request to be skipped when focus is moved using keyboard keys.
|
||||
- containers can register into separate focus groups and specific keyboard keys
|
||||
can be configured to move the focus within each focus group.
|
||||
- widgets can now request keyboard events exclusively when focused.
|
||||
- ability to configure keyboard keys that move focus to the next or the
|
||||
previous container.
|
||||
|
|
|
@ -136,6 +136,8 @@ type options struct {
|
|||
// keyFocusSkip asserts whether this container should be skipped when focus
|
||||
// is being moved using either of KeyFocusNext or KeyFocusPrevious.
|
||||
keyFocusSkip bool
|
||||
// keyFocusGroup is the focus group this container belongs to.
|
||||
keyFocusGroup int
|
||||
}
|
||||
|
||||
// margin stores the configured margin for the container.
|
||||
|
@ -194,6 +196,10 @@ type inherited struct {
|
|||
focusedColor cell.Color
|
||||
}
|
||||
|
||||
// focusGroups maps focus group numbers that have the same key assigned.
|
||||
// The value is always true for all keys.
|
||||
type focusGroups map[int]bool
|
||||
|
||||
// globalOptions are options that can only have a single value across the
|
||||
// entire tree of containers.
|
||||
// Regardless of which container they get set on, the new value will take
|
||||
|
@ -203,6 +209,12 @@ type globalOptions struct {
|
|||
keyFocusNext *keyboard.Key
|
||||
// keyFocusPrevious when set is the key that moves the focus to the previous container.
|
||||
keyFocusPrevious *keyboard.Key
|
||||
// keysFocusGroupNext maps keyboard keys that move to the next container
|
||||
// within a focus group to the focus groups they should work on.
|
||||
keysFocusGroupsNext map[keyboard.Key]focusGroups
|
||||
// keysFocusGroupPrevious maps keyboard keys that move to the previous
|
||||
// container within a focus group to the focus groups they should work on.
|
||||
keysFocusGroupsPrevious map[keyboard.Key]focusGroups
|
||||
}
|
||||
|
||||
// newOptions returns a new options instance with the default values.
|
||||
|
@ -210,7 +222,10 @@ type globalOptions struct {
|
|||
// options are for a container with no parent (the root).
|
||||
func newOptions(parent *options) *options {
|
||||
opts := &options{
|
||||
global: &globalOptions{},
|
||||
global: &globalOptions{
|
||||
keysFocusGroupsNext: map[keyboard.Key]focusGroups{},
|
||||
keysFocusGroupsPrevious: map[keyboard.Key]focusGroups{},
|
||||
},
|
||||
inherited: inherited{
|
||||
focusedColor: cell.ColorYellow,
|
||||
},
|
||||
|
@ -889,3 +904,98 @@ func KeyFocusSkip() Option {
|
|||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// KeyFocusGroup assigns this container to a focus group of the specified
|
||||
// number.
|
||||
//
|
||||
// See either of (KeysFocusGroupNext, KeysFocusGroupPrevious) for a description
|
||||
// of focus groups.
|
||||
//
|
||||
// If not specified, the container becomes part of the default focus group
|
||||
// zero.
|
||||
func KeyFocusGroup(group int) Option {
|
||||
return option(func(c *Container) error {
|
||||
if min := 0; group < min {
|
||||
return fmt.Errorf("invalid group %d, must be 0 <= group", group)
|
||||
}
|
||||
c.opts.keyFocusGroup = group
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// KeysFocusGroupNext configures keys that move the keyboard focus to the next
|
||||
// container within a focus group.
|
||||
//
|
||||
// Containers are assigned to focus groups using the KeyFocusGroup option.
|
||||
// The group parameter indicates which group are these keys attached to.
|
||||
//
|
||||
// A key configured using KeysFocusGroupNext only moves focus if the container
|
||||
// that is currently focused is part of the same focus group as the group
|
||||
// parameter in this call. The keyboard focus only gets moved to the next
|
||||
// container in the same focus group, other containers are ignored.
|
||||
//
|
||||
// The order in which the containers in the group are visited is the same as
|
||||
// with the KeyFocusNext option.
|
||||
//
|
||||
// This option is global and applies to all created containers.
|
||||
// Pressing either of (KeyFocusNext, KeyFocusPrevious) still moves the focus to
|
||||
// any container regardless of its focus group.
|
||||
func KeyFocusGroupNext(group int, keys []keyboard.Key) Option {
|
||||
return option(func(c *Container) error {
|
||||
if min := 0; group < min {
|
||||
return fmt.Errorf("invalid group %d, must be 0 <= group", group)
|
||||
}
|
||||
for _, k := range keys {
|
||||
if g := c.opts.global.keysFocusGroupsPrevious[k]; len(g) > 0 {
|
||||
return fmt.Errorf("key %q is already assigned as a KeyFocusGroupPrevious for focus groups %v", k, g)
|
||||
}
|
||||
|
||||
fg, ok := c.opts.global.keysFocusGroupsNext[k]
|
||||
if !ok {
|
||||
fg = focusGroups{}
|
||||
c.opts.global.keysFocusGroupsNext[k] = fg
|
||||
}
|
||||
fg[group] = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// KeysFocusGroupPrevious configures keys that move the keyboard focus to the
|
||||
// previous container within a focus group.
|
||||
//
|
||||
// Containers are assigned to focus groups using the KeyFocusGroup option.
|
||||
// The group parameter indicates which group are these keys attached to.
|
||||
//
|
||||
// A key configured using KeysFocusGroupPrevious only moves focus if the
|
||||
// container that is currently focused is part of the same focus group as the
|
||||
// group parameter in this call. The keyboard focus only gets moved to the
|
||||
// previous container in the same focus group, other containers are ignored.
|
||||
//
|
||||
// The order in which the containers in the group are visited is the same as
|
||||
// with the KeyFocusPrevious option.
|
||||
//
|
||||
// This option is global and applies to all created containers.
|
||||
// Pressing either of (KeyFocusNext, KeyFocusPrevious) still moves the focus to
|
||||
// any container regardless of its focus group.
|
||||
func KeyFocusGroupPrevious(group int, keys []keyboard.Key) Option {
|
||||
return option(func(c *Container) error {
|
||||
if min := 0; group < min {
|
||||
return fmt.Errorf("invalid group %d, must be 0 <= group", group)
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
if g := c.opts.global.keysFocusGroupsNext[k]; len(g) > 0 {
|
||||
return fmt.Errorf("key %q is already assigned as a KeyFocusGroupNext for focus groups %v", k, g)
|
||||
}
|
||||
|
||||
fg, ok := c.opts.global.keysFocusGroupsPrevious[k]
|
||||
if !ok {
|
||||
fg = focusGroups{}
|
||||
c.opts.global.keysFocusGroupsPrevious[k] = fg
|
||||
}
|
||||
fg[group] = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue