From 1ff687ca2b0821c2cacc1fa725abb3302d2af9da Mon Sep 17 00:00:00 2001 From: Kalyan Sriram Date: Mon, 27 Jul 2020 01:03:55 -0700 Subject: Implement style configuration. Introduce the ability to configure stylesets, allowing customization of aerc's look (color scheme, font weight, etc). Default styleset is installed to /path/to/aerc/stylesets/default. --- lib/ui/borders.go | 13 +++++++++---- lib/ui/stack.go | 10 +++++++--- lib/ui/tab.go | 11 ++++++----- lib/ui/text.go | 42 ++++++------------------------------------ lib/ui/textinput.go | 32 ++++++++++++++++++++------------ 5 files changed, 48 insertions(+), 60 deletions(-) (limited to 'lib') diff --git a/lib/ui/borders.go b/lib/ui/borders.go index 7a75759..99d6880 100644 --- a/lib/ui/borders.go +++ b/lib/ui/borders.go @@ -2,6 +2,8 @@ package ui import ( "github.com/gdamore/tcell" + + "git.sr.ht/~sircmpwn/aerc/config" ) const ( @@ -16,12 +18,15 @@ type Bordered struct { borders uint content Drawable onInvalidate func(d Drawable) + uiConfig config.UIConfig } -func NewBordered(content Drawable, borders uint) *Bordered { +func NewBordered( + content Drawable, borders uint, uiConfig config.UIConfig) *Bordered { b := &Bordered{ - borders: borders, - content: content, + borders: borders, + content: content, + uiConfig: uiConfig, } content.OnInvalidate(b.contentInvalidated) return b @@ -44,7 +49,7 @@ func (bordered *Bordered) Draw(ctx *Context) { y := 0 width := ctx.Width() height := ctx.Height() - style := tcell.StyleDefault.Reverse(true) + style := bordered.uiConfig.GetStyle(config.STYLE_BORDER) if bordered.borders&BORDER_LEFT != 0 { ctx.Fill(0, 0, 1, ctx.Height(), ' ', style) x += 1 diff --git a/lib/ui/stack.go b/lib/ui/stack.go index 690a869..c9004a0 100644 --- a/lib/ui/stack.go +++ b/lib/ui/stack.go @@ -3,16 +3,19 @@ package ui import ( "fmt" + "git.sr.ht/~sircmpwn/aerc/config" + "github.com/gdamore/tcell" ) type Stack struct { children []Drawable onInvalidate []func(d Drawable) + uiConfig config.UIConfig } -func NewStack() *Stack { - return &Stack{} +func NewStack(uiConfig config.UIConfig) *Stack { + return &Stack{uiConfig: uiConfig} } func (stack *Stack) Children() []Drawable { @@ -33,7 +36,8 @@ func (stack *Stack) Draw(ctx *Context) { if len(stack.children) > 0 { stack.Peek().Draw(ctx) } else { - ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) + ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', + stack.uiConfig.GetStyle(config.STYLE_STACK)) } } diff --git a/lib/ui/tab.go b/lib/ui/tab.go index 4b99e4b..cd5f448 100644 --- a/lib/ui/tab.go +++ b/lib/ui/tab.go @@ -283,9 +283,9 @@ func (tabs *Tabs) removeHistory(index int) { func (strip *TabStrip) Draw(ctx *Context) { x := 0 for i, tab := range strip.Tabs { - style := tcell.StyleDefault.Reverse(true) + style := strip.uiConfig.GetStyle(config.STYLE_TAB) if strip.Selected == i { - style = tcell.StyleDefault + style = strip.uiConfig.GetStyleSelected(config.STYLE_TAB) } tabWidth := 32 if ctx.Width()-x < tabWidth { @@ -301,8 +301,8 @@ func (strip *TabStrip) Draw(ctx *Context) { break } } - style := tcell.StyleDefault.Reverse(true) - ctx.Fill(x, 0, ctx.Width()-x, 1, ' ', style) + ctx.Fill(x, 0, ctx.Width()-x, 1, ' ', + strip.uiConfig.GetStyle(config.STYLE_TAB)) } func (strip *TabStrip) Invalidate() { @@ -386,7 +386,8 @@ func (content *TabContent) Draw(ctx *Context) { if content.Selected >= len(content.Tabs) { width := ctx.Width() height := ctx.Height() - ctx.Fill(0, 0, width, height, ' ', tcell.StyleDefault) + ctx.Fill(0, 0, width, height, ' ', + content.uiConfig.GetStyle(config.STYLE_TAB)) } tab := content.Tabs[content.Selected] diff --git a/lib/ui/text.go b/lib/ui/text.go index 2b82598..455c2eb 100644 --- a/lib/ui/text.go +++ b/lib/ui/text.go @@ -15,17 +15,13 @@ type Text struct { Invalidatable text string strategy uint - fg tcell.Color - bg tcell.Color - bold bool - reverse bool + style tcell.Style } -func NewText(text string) *Text { +func NewText(text string, style tcell.Style) *Text { return &Text{ - bg: tcell.ColorDefault, - fg: tcell.ColorDefault, - text: text, + text: text, + style: style, } } @@ -41,25 +37,6 @@ func (t *Text) Strategy(strategy uint) *Text { return t } -func (t *Text) Bold(bold bool) *Text { - t.bold = bold - t.Invalidate() - return t -} - -func (t *Text) Color(fg tcell.Color, bg tcell.Color) *Text { - t.fg = fg - t.bg = bg - t.Invalidate() - return t -} - -func (t *Text) Reverse(reverse bool) *Text { - t.reverse = reverse - t.Invalidate() - return t -} - func (t *Text) Draw(ctx *Context) { size := runewidth.StringWidth(t.text) x := 0 @@ -69,15 +46,8 @@ func (t *Text) Draw(ctx *Context) { if t.strategy == TEXT_RIGHT { x = ctx.Width() - size } - style := tcell.StyleDefault.Background(t.bg).Foreground(t.fg) - if t.bold { - style = style.Bold(true) - } - if t.reverse { - style = style.Reverse(true) - } - ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', style) - ctx.Printf(x, 0, style, "%s", t.text) + ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', t.style) + ctx.Printf(x, 0, t.style, "%s", t.text) } func (t *Text) Invalidate() { diff --git a/lib/ui/textinput.go b/lib/ui/textinput.go index f6b0c72..2445065 100644 --- a/lib/ui/textinput.go +++ b/lib/ui/textinput.go @@ -6,6 +6,8 @@ import ( "github.com/gdamore/tcell" "github.com/mattn/go-runewidth" + + "git.sr.ht/~sircmpwn/aerc/config" ) // TODO: Attach history providers @@ -27,16 +29,18 @@ type TextInput struct { completeIndex int completeDelay time.Duration completeDebouncer *time.Timer + uiConfig config.UIConfig } // Creates a new TextInput. TextInputs will render a "textbox" in the entire // context they're given, and process keypresses to build a string from user // input. -func NewTextInput(text string) *TextInput { +func NewTextInput(text string, ui config.UIConfig) *TextInput { return &TextInput{ - cells: -1, - text: []rune(text), - index: len([]rune(text)), + cells: -1, + text: []rune(text), + index: len([]rune(text)), + uiConfig: ui, } } @@ -87,16 +91,18 @@ func (ti *TextInput) Draw(ctx *Context) { ti.ensureScroll() } ti.ctx = ctx // gross - ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) + + defaultStyle := ti.uiConfig.GetStyle(config.STYLE_DEFAULT) + ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', defaultStyle) text := ti.text[scroll:] sindex := ti.index - scroll if ti.password { - x := ctx.Printf(0, 0, tcell.StyleDefault, "%s", ti.prompt) + x := ctx.Printf(0, 0, defaultStyle, "%s", ti.prompt) cells := runewidth.StringWidth(string(text)) - ctx.Fill(x, 0, cells, 1, '*', tcell.StyleDefault) + ctx.Fill(x, 0, cells, 1, '*', defaultStyle) } else { - ctx.Printf(0, 0, tcell.StyleDefault, "%s%s", ti.prompt, string(text)) + ctx.Printf(0, 0, defaultStyle, "%s%s", ti.prompt, string(text)) } cells := runewidth.StringWidth(string(text[:sindex]) + ti.prompt) if ti.focus { @@ -126,6 +132,7 @@ func (ti *TextInput) drawPopover(ctx *Context) { ti.Set(stem + ti.StringRight()) ti.Invalidate() }, + uiConfig: ti.uiConfig, } width := maxLen(ti.completions) + 3 height := len(ti.completions) @@ -353,6 +360,7 @@ type completions struct { onSelect func(int) onExec func() onStem func(string) + uiConfig config.UIConfig } func maxLen(ss []string) int { @@ -367,10 +375,10 @@ func maxLen(ss []string) int { } func (c *completions) Draw(ctx *Context) { - bg := tcell.StyleDefault - sel := tcell.StyleDefault.Reverse(true) - gutter := tcell.StyleDefault - pill := tcell.StyleDefault.Reverse(true) + bg := c.uiConfig.GetStyle(config.STYLE_COMPLETION_DEFAULT) + gutter := c.uiConfig.GetStyle(config.STYLE_COMPLETION_GUTTER) + pill := c.uiConfig.GetStyle(config.STYLE_COMPLETION_PILL) + sel := c.uiConfig.GetStyleSelected(config.STYLE_COMPLETION_DEFAULT) ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', bg) -- cgit 1.4.1-2-gfad0