Apply relevant msglist styles in order

Allow styles to be layered over a base style. The list of styles to
apply is layered over the base style in order, such that if the layer
does not differ from the base it is not used. The order that these
styles are applied in is, from first to last:

msglist_default
msglist_unread
msglist_read    (exclusive with unread, so technically the same level)
msglist_flagged
msglist_deleted
msglist_marked

So, msglist_marked style dominates.

This fixes an issue where the msglist_deleted style was not being applied.
This commit is contained in:
Chris Vittal 2020-10-27 14:56:44 -04:00 committed by Reto Brunner
parent 743683a0c1
commit f9bba3d17d
4 changed files with 90 additions and 17 deletions

View file

@ -699,3 +699,12 @@ func (uiConfig UIConfig) GetStyle(so StyleObject) tcell.Style {
func (uiConfig UIConfig) GetStyleSelected(so StyleObject) tcell.Style { func (uiConfig UIConfig) GetStyleSelected(so StyleObject) tcell.Style {
return uiConfig.style.Selected(so) return uiConfig.style.Selected(so)
} }
func (uiConfig UIConfig) GetComposedStyle(base StyleObject,
styles []StyleObject) tcell.Style {
return uiConfig.style.Compose(base, styles)
}
func (uiConfig UIConfig) GetComposedStyleSelected(base StyleObject, styles []StyleObject) tcell.Style {
return uiConfig.style.ComposeSelected(base, styles)
}

View file

@ -31,9 +31,9 @@ const (
STYLE_MSGLIST_DEFAULT STYLE_MSGLIST_DEFAULT
STYLE_MSGLIST_UNREAD STYLE_MSGLIST_UNREAD
STYLE_MSGLIST_READ STYLE_MSGLIST_READ
STYLE_MSGLIST_FLAGGED
STYLE_MSGLIST_DELETED STYLE_MSGLIST_DELETED
STYLE_MSGLIST_MARKED STYLE_MSGLIST_MARKED
STYLE_MSGLIST_FLAGGED
STYLE_DIRLIST_DEFAULT STYLE_DIRLIST_DEFAULT
@ -67,9 +67,9 @@ var StyleNames = map[string]StyleObject{
"msglist_default": STYLE_MSGLIST_DEFAULT, "msglist_default": STYLE_MSGLIST_DEFAULT,
"msglist_unread": STYLE_MSGLIST_UNREAD, "msglist_unread": STYLE_MSGLIST_UNREAD,
"msglist_read": STYLE_MSGLIST_READ, "msglist_read": STYLE_MSGLIST_READ,
"msglist_flagged": STYLE_MSGLIST_FLAGGED,
"msglist_deleted": STYLE_MSGLIST_DELETED, "msglist_deleted": STYLE_MSGLIST_DELETED,
"msglist_marked": STYLE_MSGLIST_MARKED, "msglist_marked": STYLE_MSGLIST_MARKED,
"msglist_flagged": STYLE_MSGLIST_FLAGGED,
"dirlist_default": STYLE_DIRLIST_DEFAULT, "dirlist_default": STYLE_DIRLIST_DEFAULT,
@ -180,6 +180,31 @@ func (s *Style) Set(attr, val string) error {
return nil return nil
} }
func (s Style) composeWith(styles []*Style) Style {
newStyle := s
for _, st := range styles {
if st.Fg != s.Fg {
newStyle.Fg = st.Fg
}
if st.Bg != s.Bg {
newStyle.Bg = st.Bg
}
if st.Bold != s.Bold {
newStyle.Bold = st.Bold
}
if st.Blink != s.Blink {
newStyle.Blink = st.Blink
}
if st.Underline != s.Underline {
newStyle.Underline = st.Underline
}
if st.Reverse != s.Reverse {
newStyle.Reverse = st.Reverse
}
}
return newStyle
}
type StyleSet struct { type StyleSet struct {
objects map[StyleObject]*Style objects map[StyleObject]*Style
selected map[StyleObject]*Style selected map[StyleObject]*Style
@ -213,6 +238,27 @@ func (ss StyleSet) Selected(so StyleObject) tcell.Style {
return ss.selected[so].Get() return ss.selected[so].Get()
} }
func (ss StyleSet) Compose(so StyleObject, sos []StyleObject) tcell.Style {
base := *ss.objects[so]
styles := make([]*Style, len(sos))
for i, so := range sos {
styles[i] = ss.objects[so]
}
return base.composeWith(styles).Get()
}
func (ss StyleSet) ComposeSelected(so StyleObject,
sos []StyleObject) tcell.Style {
base := *ss.selected[so]
styles := make([]*Style, len(sos))
for i, so := range sos {
styles[i] = ss.selected[so]
}
return base.composeWith(styles).Get()
}
func findStyleSet(stylesetName string, stylesetsDir []string) (string, error) { func findStyleSet(stylesetName string, stylesetsDir []string) (string, error) {
for _, dir := range stylesetsDir { for _, dir := range stylesetsDir {
stylesetPath, err := homedir.Expand(path.Join(dir, stylesetName)) stylesetPath, err := homedir.Expand(path.Join(dir, stylesetName))

View file

@ -107,12 +107,12 @@ styling.
: Unread messages in a message list. : Unread messages in a message list.
| msglist_read | msglist_read
: Read messages in a message list. : Read messages in a message list.
| msglist_flagged
: The messages with the flagged flag.
| msglist_deleted | msglist_deleted
: The messages marked as deleted. : The messages marked as deleted.
| msglist_marked | msglist_marked
: The messages with the marked flag. : The messages with the marked flag.
| msglist_flagged
: The messages with the flagged flag.
| dirlist_default | dirlist_default
: The default style for directories in the directory list. : The default style for directories in the directory list.
| completion_default | completion_default
@ -175,6 +175,23 @@ If we specify the global style selected modifer using fnmatch as below:
This toggles the reverse switch for selected version of all the style objects. This toggles the reverse switch for selected version of all the style objects.
## Layered styles
Some styles, (currently only the `msglist\*` ones) are applied in layers. If
a style differs from the base (in this case `msglist_default`) then that style
applies, unless overridden by a higher layer. The order that `msglist` styles
are applied in is, from first to last:
```
msglist_default
msglist_unread
msglist_read
msglist_flagged
msglist_deleted
msglist_marked
```
So, the marked style will override all other msglist styles.
## Colors ## Colors
The color values are set using the values accepted by the tcell library. The color values are set using the values accepted by the tcell library.
The values can be one of the following. The values can be one of the following.

View file

@ -108,12 +108,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
config.UI_CONTEXT_SUBJECT: msg.Envelope.Subject, config.UI_CONTEXT_SUBJECT: msg.Envelope.Subject,
}) })
so := config.STYLE_MSGLIST_DEFAULT msg_styles := []config.StyleObject{}
// deleted message
if _, ok := store.Deleted[msg.Uid]; ok {
so = config.STYLE_MSGLIST_DELETED
}
// unread message // unread message
seen := false seen := false
flagged := false flagged := false
@ -127,25 +122,31 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
} }
if seen { if seen {
so = config.STYLE_MSGLIST_READ msg_styles = append(msg_styles, config.STYLE_MSGLIST_READ)
} else { } else {
so = config.STYLE_MSGLIST_UNREAD msg_styles = append(msg_styles, config.STYLE_MSGLIST_UNREAD)
} }
if flagged { if flagged {
so = config.STYLE_MSGLIST_FLAGGED msg_styles = append(msg_styles, config.STYLE_MSGLIST_FLAGGED)
}
// deleted message
if _, ok := store.Deleted[msg.Uid]; ok {
msg_styles = append(msg_styles, config.STYLE_MSGLIST_DELETED)
} }
// marked message // marked message
if store.IsMarked(msg.Uid) { if store.IsMarked(msg.Uid) {
so = config.STYLE_MSGLIST_MARKED msg_styles = append(msg_styles, config.STYLE_MSGLIST_MARKED)
} }
style := uiConfig.GetStyle(so) var style tcell.Style
// current row // current row
if row == ml.store.SelectedIndex()-ml.scroll { if row == ml.store.SelectedIndex()-ml.scroll {
style = uiConfig.GetStyleSelected(so) style = uiConfig.GetComposedStyleSelected(config.STYLE_MSGLIST_DEFAULT, msg_styles)
} else {
style = uiConfig.GetComposedStyle(config.STYLE_MSGLIST_DEFAULT, msg_styles)
} }
ctx.Fill(0, row, ctx.Width(), 1, ' ', style) ctx.Fill(0, row, ctx.Width(), 1, ' ', style)