diff --git a/checkbox.go b/checkbox.go index 76f8e59..282d8a9 100644 --- a/checkbox.go +++ b/checkbox.go @@ -135,6 +135,24 @@ func (c *CheckBox) GetMessage() string { return c.message } +// SetAttributes sets the given attributes on the check box. +func (c *CheckBox) SetAttributes(attributes ...FormItemAttribute) { + allAttributes := newFormItemAttributes() + for _, attribute := range attributes { + attribute.apply(allAttributes) + } + + allAttributes.setLabelWidth(&c.labelWidth) + allAttributes.setBackgroundColor(&c.backgroundColor) + allAttributes.setLabelColor(&c.labelColor) + allAttributes.setLabelColorFocused(&c.labelColorFocused) + allAttributes.setFieldTextColor(&c.fieldTextColor) + allAttributes.setFieldTextColorFocused(&c.fieldTextColorFocused) + allAttributes.setFieldBackgroundColor(&c.fieldBackgroundColor) + allAttributes.setFieldBackgroundColorFocused(&c.fieldBackgroundColorFocused) + allAttributes.setFinishedFunc(&c.finished) +} + // SetLabelWidth sets the screen width of the label. A value of 0 will cause the // primitive to use the width of the label string. func (c *CheckBox) SetLabelWidth(width int) *CheckBox { @@ -145,6 +163,12 @@ func (c *CheckBox) SetLabelWidth(width int) *CheckBox { return c } +// SetBackgroundColor sets the background color. +func (c *CheckBox) SetBackgroundColor(color tcell.Color) *CheckBox { + c.Box.SetBackgroundColor(color) + return c +} + // SetLabelColor sets the color of the label. func (c *CheckBox) SetLabelColor(color tcell.Color) *CheckBox { c.Lock() @@ -199,22 +223,6 @@ func (c *CheckBox) SetFieldTextColorFocused(color tcell.Color) *CheckBox { return c } -// SetFormAttributes sets attributes shared by all form items. -func (c *CheckBox) SetFormAttributes(labelWidth int, bgColor, labelColor, labelColorFocused, fieldTextColor, fieldTextColorFocused, fieldBgColor, fieldBgColorFocused tcell.Color) FormItem { - c.Lock() - defer c.Unlock() - - c.labelWidth = labelWidth - c.backgroundColor = bgColor - c.labelColor = labelColor - c.labelColorFocused = labelColorFocused - c.fieldTextColor = fieldTextColor - c.fieldTextColorFocused = fieldTextColorFocused - c.fieldBackgroundColor = fieldBgColor - c.fieldBackgroundColorFocused = fieldBgColorFocused - return c -} - // GetFieldHeight returns the height of the field. func (c *CheckBox) GetFieldHeight() int { return 1 @@ -259,7 +267,7 @@ func (c *CheckBox) SetDoneFunc(handler func(key tcell.Key)) *CheckBox { } // SetFinishedFunc sets a callback invoked when the user leaves this form item. -func (c *CheckBox) SetFinishedFunc(handler func(key tcell.Key)) FormItem { +func (c *CheckBox) SetFinishedFunc(handler func(key tcell.Key)) *CheckBox { c.Lock() defer c.Unlock() diff --git a/dropdown.go b/dropdown.go index bd18599..9fc5fe6 100644 --- a/dropdown.go +++ b/dropdown.go @@ -266,6 +266,24 @@ func (d *DropDown) GetLabel() string { return d.label } +// SetAttributes sets the given attributes on the drop down. +func (d *DropDown) SetAttributes(attributes ...FormItemAttribute) { + allAttributes := newFormItemAttributes() + for _, attribute := range attributes { + attribute.apply(allAttributes) + } + + allAttributes.setLabelWidth(&d.labelWidth) + allAttributes.setBackgroundColor(&d.backgroundColor) + allAttributes.setLabelColor(&d.labelColor) + allAttributes.setLabelColorFocused(&d.labelColorFocused) + allAttributes.setFieldTextColor(&d.fieldTextColor) + allAttributes.setFieldTextColorFocused(&d.fieldTextColorFocused) + allAttributes.setFieldBackgroundColor(&d.fieldBackgroundColor) + allAttributes.setFieldBackgroundColorFocused(&d.fieldBackgroundColorFocused) + allAttributes.setFinishedFunc(&d.finished) +} + // SetLabelWidth sets the screen width of the label. A value of 0 will cause the // primitive to use the width of the label string. func (d *DropDown) SetLabelWidth(width int) *DropDown { @@ -276,6 +294,12 @@ func (d *DropDown) SetLabelWidth(width int) *DropDown { return d } +// SetBackgroundColor sets the background color. +func (d *DropDown) SetBackgroundColor(color tcell.Color) *DropDown { + d.Box.SetBackgroundColor(color) + return d +} + // SetLabelColor sets the color of the label. func (d *DropDown) SetLabelColor(color tcell.Color) *DropDown { d.Lock() @@ -377,22 +401,6 @@ func (d *DropDown) SetPrefixTextColor(color tcell.Color) *DropDown { return d } -// SetFormAttributes sets attributes shared by all form items. -func (d *DropDown) SetFormAttributes(labelWidth int, bgColor, labelColor, labelColorFocused, fieldTextColor, fieldTextColorFocused, fieldBgColor, fieldBgColorFocused tcell.Color) FormItem { - d.Lock() - defer d.Unlock() - - d.labelWidth = labelWidth - d.backgroundColor = bgColor - d.labelColor = labelColor - d.labelColorFocused = labelColorFocused - d.fieldTextColor = fieldTextColor - d.fieldTextColorFocused = fieldTextColorFocused - d.fieldBackgroundColor = fieldBgColor - d.fieldBackgroundColorFocused = fieldBgColorFocused - return d -} - // SetFieldWidth sets the screen width of the options area. A value of 0 means // extend to as long as the longest option text. func (d *DropDown) SetFieldWidth(width int) *DropDown { @@ -514,7 +522,7 @@ func (d *DropDown) SetDoneFunc(handler func(key tcell.Key)) *DropDown { } // SetFinishedFunc sets a callback invoked when the user leaves this form item. -func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) FormItem { +func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) *DropDown { d.Lock() defer d.Unlock() diff --git a/form.go b/form.go index 806171a..f8b1ceb 100644 --- a/form.go +++ b/form.go @@ -11,6 +11,149 @@ import ( // horizontal layouts. var DefaultFormFieldWidth = 10 +// FormItemAttribute represents a form attribute. +type FormItemAttribute interface { + apply(attributes *formItemAttributes) +} + +// formItemAttributes is a set of attribute setters to be applied. +type formItemAttributes struct { + setLabelWidth func(width *int) + setBackgroundColor func(color *tcell.Color) + setLabelColor func(color *tcell.Color) + setLabelColorFocused func(color *tcell.Color) + setFieldTextColor func(color *tcell.Color) + setFieldTextColorFocused func(color *tcell.Color) + setFieldBackgroundColor func(color *tcell.Color) + setFieldBackgroundColorFocused func(color *tcell.Color) + setFinishedFunc func(handler *func(key tcell.Key)) +} + +func newFormItemAttributes() *formItemAttributes { + return &formItemAttributes{ + setLabelWidth: func(_ *int) {}, + setBackgroundColor: func(_ *tcell.Color) {}, + setLabelColor: func(_ *tcell.Color) {}, + setLabelColorFocused: func(_ *tcell.Color) {}, + setFieldTextColor: func(_ *tcell.Color) {}, + setFieldTextColorFocused: func(_ *tcell.Color) {}, + setFieldBackgroundColor: func(_ *tcell.Color) {}, + setFieldBackgroundColorFocused: func(_ *tcell.Color) {}, + setFinishedFunc: func(_ *func(key tcell.Key)) {}, + } +} + +// funcFormItemAttribute holds the attribute setter. +type funcFormItemAttribute struct { + f func(*formItemAttributes) +} + +// apply invokes the attribute setter. +func (fdo *funcFormItemAttribute) apply(do *formItemAttributes) { + fdo.f(do) +} + +// newFuncAttribute creates a new funcFormItemAttribute. +func newFuncAttribute(f func(*formItemAttributes)) *funcFormItemAttribute { + return &funcFormItemAttribute{ + f: f, + } +} + +// WithLabelWidth creates a form item attribute promise with the given value to be set. +// When applied, sets the screen width of the label. A value of 0 will cause the +// primitive to use the width of the label string. +func WithLabelWidth(labelWidth int) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setLabelWidth = func(width *int) { + *width = labelWidth + } + }) +} + +// WithBackgroundColor creates a form item attribute promise with the given value to be set. +// When applied, sets the background color. +func WithBackgroundColor(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setBackgroundColor = func(backgroundColor *tcell.Color) { + *backgroundColor = color + } + }) +} + +// WithLabelColor creates a form item attribute promise with the given value to be set. +// When applied, sets the color of the label. +func WithLabelColor(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setLabelColor = func(labelColor *tcell.Color) { + *labelColor = color + } + }) +} + +// WithLabelColorFocused creates a form item attribute promise with the given value to be set. +// When applied, sets the color of the label when focused. +func WithLabelColorFocused(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setLabelColorFocused = func(labelColorFocused *tcell.Color) { + *labelColorFocused = color + } + }) +} + +// WithFieldTextColor creates a form item attribute promise with the given value to be set. +// When applied, sets the text color of the input area. +func WithFieldTextColor(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setFieldTextColor = func(fieldTextColor *tcell.Color) { + *fieldTextColor = color + } + }) +} + +// WithFieldTextColorFocused creates a form item attribute promise with the given value to be set. +// When applied, sets the text color of the input area when focused. +func WithFieldTextColorFocused(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setFieldTextColorFocused = func(fieldTextColorFocused *tcell.Color) { + *fieldTextColorFocused = color + } + }) +} + +// WithFieldBackgroundColor creates a form item attribute promise with the given value to be set. +// When applied, sets the background color of the input area. +func WithFieldBackgroundColor(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setFieldBackgroundColor = func(fieldBackgroundColor *tcell.Color) { + *fieldBackgroundColor = color + } + }) +} + +// WithFieldBackgroundColorFocused creates a form item attribute promise with the given value to be set. +// When applied, sets the background color of the input area when focused. +func WithFieldBackgroundColorFocused(color tcell.Color) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setFieldBackgroundColorFocused = func(fieldBackgroundColorFocused *tcell.Color) { + *fieldBackgroundColorFocused = color + } + }) +} + +// WithFieldBackgroundColorFocused creates a form item attribute promise with the given value to be set. +// When applied, sets the handler function for when the user finished +// entering data into the item. The handler may receive events for the +// Enter key (we're done), the Escape key (cancel input), the Tab key (move to +// next field), and the Backtab key (move to previous field). +func WithFinishedFunc(handler func(key tcell.Key)) FormItemAttribute { + return newFuncAttribute(func(o *formItemAttributes) { + o.setFinishedFunc = func(finishedFunc *func(key tcell.Key)) { + *finishedFunc = handler + } + }) +} + // FormItem is the interface all form items must implement to be able to be // included in a form. type FormItem interface { @@ -19,8 +162,8 @@ type FormItem interface { // GetLabel returns the item's label text. GetLabel() string - // SetFormAttributes sets a number of item attributes at once. - SetFormAttributes(labelWidth int, bgColor, labelColor, labelColorFocused, fieldTextColor, fieldTextColorFocused, fieldBgColor, fieldBgColorFocused tcell.Color) FormItem + // SetAttributes sets the given attributes on the form item. + SetAttributes(attributes ...FormItemAttribute) // GetFieldWidth returns the width of the form item's field (the area which // is manipulated by the user) in number of screen cells. A value of 0 @@ -30,12 +173,6 @@ type FormItem interface { // GetFieldHeight returns the height of the form item. GetFieldHeight() int - - // SetFinishedFunc sets the handler function for when the user finished - // entering data into the item. The handler may receive events for the - // Enter key (we're done), the Escape key (cancel input), the Tab key (move to - // next field), and the Backtab key (move to previous field). - SetFinishedFunc(handler func(key tcell.Key)) FormItem } // Form allows you to combine multiple one-line form elements into a vertical @@ -619,16 +756,16 @@ func (f *Form) Draw(screen tcell.Screen) { if x+itemWidth >= rightLimit { itemWidth = rightLimit - x } - item.SetFormAttributes( - labelWidth, - f.backgroundColor, - f.labelColor, - f.labelColorFocused, - f.fieldTextColor, - f.fieldTextColorFocused, - f.fieldBackgroundColor, - f.fieldBackgroundColorFocused, - ) + + item.SetAttributes( + WithLabelWidth(labelWidth), + WithBackgroundColor(f.backgroundColor), + WithLabelColor(f.labelColor), + WithLabelColorFocused(f.labelColorFocused), + WithFieldTextColor(f.fieldTextColor), + WithFieldTextColorFocused(f.fieldTextColorFocused), + WithFieldBackgroundColor(f.fieldBackgroundColor), + WithFieldBackgroundColorFocused(f.fieldBackgroundColorFocused)) // Save position. positions[index].x = x @@ -812,7 +949,7 @@ func (f *Form) Focus(delegate func(p Primitive)) { if f.focusedElement < len(f.items) { // We're selecting an item. item := f.items[f.focusedElement] - item.SetFinishedFunc(handler) + item.SetAttributes(WithFinishedFunc(handler)) f.Unlock() delegate(item) } else { diff --git a/inputfield.go b/inputfield.go index 1763298..9c72529 100644 --- a/inputfield.go +++ b/inputfield.go @@ -198,6 +198,24 @@ func (i *InputField) GetLabel() string { return i.label } +// SetAttributes sets the given attributes on the input field. +func (i *InputField) SetAttributes(attributes ...FormItemAttribute) { + allAttributes := newFormItemAttributes() + for _, attribute := range attributes { + attribute.apply(allAttributes) + } + + allAttributes.setLabelWidth(&i.labelWidth) + allAttributes.setBackgroundColor(&i.backgroundColor) + allAttributes.setLabelColor(&i.labelColor) + allAttributes.setLabelColorFocused(&i.labelColorFocused) + allAttributes.setFieldTextColor(&i.fieldTextColor) + allAttributes.setFieldTextColorFocused(&i.fieldTextColorFocused) + allAttributes.setFieldBackgroundColor(&i.fieldBackgroundColor) + allAttributes.setFieldBackgroundColorFocused(&i.fieldBackgroundColorFocused) + allAttributes.setFinishedFunc(&i.finished) +} + // SetLabelWidth sets the screen width of the label. A value of 0 will cause the // primitive to use the width of the label string. func (i *InputField) SetLabelWidth(width int) *InputField { @@ -208,6 +226,12 @@ func (i *InputField) SetLabelWidth(width int) *InputField { return i } +// SetBackgroundColor sets the background color. +func (i *InputField) SetBackgroundColor(color tcell.Color) *InputField { + i.Box.SetBackgroundColor(color) + return i +} + // SetPlaceholder sets the text to be displayed when the input text is empty. func (i *InputField) SetPlaceholder(text string) *InputField { i.Lock() @@ -352,22 +376,6 @@ func (i *InputField) ResetFieldNote() *InputField { return i } -// SetFormAttributes sets attributes shared by all form items. -func (i *InputField) SetFormAttributes(labelWidth int, bgColor, labelColor, labelColorFocused, fieldTextColor, fieldTextColorFocused, fieldBgColor, fieldBgColorFocused tcell.Color) FormItem { - i.Lock() - defer i.Unlock() - - i.labelWidth = labelWidth - i.backgroundColor = bgColor - i.labelColor = labelColor - i.labelColorFocused = labelColorFocused - i.fieldTextColor = fieldTextColor - i.fieldTextColorFocused = fieldTextColorFocused - i.fieldBackgroundColor = fieldBgColor - i.fieldBackgroundColorFocused = fieldBgColorFocused - return i -} - // SetFieldWidth sets the screen width of the input area. A value of 0 means // extend as much as possible. func (i *InputField) SetFieldWidth(width int) *InputField { @@ -549,7 +557,7 @@ func (i *InputField) SetDoneFunc(handler func(key tcell.Key)) *InputField { } // SetFinishedFunc sets a callback invoked when the user leaves this form item. -func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) FormItem { +func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) *InputField { i.Lock() defer i.Unlock()