added palette support for all the components, adjusted light theme colors

This commit is contained in:
sqshq 2019-03-23 20:16:59 -04:00
parent 55b26999db
commit d77dd1e524
13 changed files with 86 additions and 55 deletions

View File

@ -6,6 +6,7 @@ import (
"github.com/sqshq/sampler/asset" "github.com/sqshq/sampler/asset"
"github.com/sqshq/sampler/component" "github.com/sqshq/sampler/component"
"github.com/sqshq/sampler/config" "github.com/sqshq/sampler/config"
"github.com/sqshq/sampler/console"
"github.com/sqshq/sampler/data" "github.com/sqshq/sampler/data"
"image" "image"
) )
@ -19,11 +20,12 @@ type AsciiBox struct {
style ui.Style style ui.Style
render *fl.AsciiRender render *fl.AsciiRender
options *fl.RenderOptions options *fl.RenderOptions
palette console.Palette
} }
const asciiFontExtension = ".flf" const asciiFontExtension = ".flf"
func NewAsciiBox(c config.AsciiBoxConfig) *AsciiBox { func NewAsciiBox(c config.AsciiBoxConfig, palette console.Palette) *AsciiBox {
options := fl.NewRenderOptions() options := fl.NewRenderOptions()
options.FontName = string(*c.Font) options.FontName = string(*c.Font)
@ -36,12 +38,18 @@ func NewAsciiBox(c config.AsciiBoxConfig) *AsciiBox {
render := fl.NewAsciiRender() render := fl.NewAsciiRender()
_ = render.LoadBindataFont(fontStr, options.FontName) _ = render.LoadBindataFont(fontStr, options.FontName)
color := c.Color
if color == nil {
color = &palette.BaseColor
}
box := AsciiBox{ box := AsciiBox{
Block: component.NewBlock(c.Title, true), Block: component.NewBlock(c.Title, true, palette),
Consumer: data.NewConsumer(), Consumer: data.NewConsumer(),
style: ui.NewStyle(*c.Color), style: ui.NewStyle(*color),
render: render, render: render,
options: options, options: options,
palette: palette,
} }
go func() { go func() {

View File

@ -25,6 +25,7 @@ type BarChart struct {
scale int scale int
maxValue float64 maxValue float64
count int64 count int64
palette console.Palette
} }
type Bar struct { type Bar struct {
@ -34,14 +35,15 @@ type Bar struct {
delta float64 delta float64
} }
func NewBarChart(c config.BarChartConfig) *BarChart { func NewBarChart(c config.BarChartConfig, palette console.Palette) *BarChart {
chart := BarChart{ chart := BarChart{
Block: component.NewBlock(c.Title, true), Block: component.NewBlock(c.Title, true, palette),
Consumer: data.NewConsumer(), Consumer: data.NewConsumer(),
bars: []Bar{}, bars: []Bar{},
scale: *c.Scale, scale: *c.Scale,
maxValue: -math.MaxFloat64, maxValue: -math.MaxFloat64,
palette: palette,
} }
for _, i := range c.Items { for _, i := range c.Items {
@ -119,7 +121,7 @@ func (b *BarChart) Draw(buffer *ui.Buffer) {
barWidth := int(math.Ceil(float64(b.Inner.Dx()-2*barIndent-len(b.bars)*barIndent) / float64(len(b.bars)))) barWidth := int(math.Ceil(float64(b.Inner.Dx()-2*barIndent-len(b.bars)*barIndent) / float64(len(b.bars))))
barXCoordinate := b.Inner.Min.X + barIndent barXCoordinate := b.Inner.Min.X + barIndent
labelStyle := ui.NewStyle(console.ColorWhite) labelStyle := ui.NewStyle(b.palette.BaseColor)
for _, bar := range b.bars { for _, bar := range b.bars {

View File

@ -1,12 +1,19 @@
package component package component
import ( import (
"fmt"
ui "github.com/gizak/termui/v3" ui "github.com/gizak/termui/v3"
"github.com/sqshq/sampler/console"
) )
func NewBlock(title string, border bool) *ui.Block { func NewBlock(title string, border bool, palette console.Palette) *ui.Block {
style := ui.Style{Fg: palette.BaseColor, Bg: ui.ColorClear}
block := ui.NewBlock() block := ui.NewBlock()
block.Title = title
block.Border = border block.Border = border
block.BorderStyle = style
block.TitleStyle = style
if len(title) > 0 {
block.Title = fmt.Sprintf(" %s ", title)
}
return block return block
} }

View File

@ -27,15 +27,17 @@ type Gauge struct {
curValue float64 curValue float64
color ui.Color color ui.Color
scale int scale int
palette console.Palette
} }
func NewGauge(c config.GaugeConfig) *Gauge { func NewGauge(c config.GaugeConfig, palette console.Palette) *Gauge {
gauge := Gauge{ gauge := Gauge{
Block: component.NewBlock(c.Title, true), Block: component.NewBlock(c.Title, true, palette),
Consumer: data.NewConsumer(), Consumer: data.NewConsumer(),
scale: *c.Scale, scale: *c.Scale,
color: *c.Color, color: *c.Color,
palette: palette,
} }
go func() { go func() {
@ -105,9 +107,9 @@ func (g *Gauge) Draw(buffer *ui.Buffer) {
labelYCoordinate := g.Inner.Min.Y + ((g.Inner.Dy() - 1) / 2) labelYCoordinate := g.Inner.Min.Y + ((g.Inner.Dy() - 1) / 2)
if labelYCoordinate < g.Inner.Max.Y { if labelYCoordinate < g.Inner.Max.Y {
for i, char := range label { for i, char := range label {
style := ui.NewStyle(console.ColorWhite) style := ui.NewStyle(g.palette.BaseColor)
if labelXCoordinate+i+1 <= g.Inner.Min.X+barWidth { if labelXCoordinate+i+1 <= g.Inner.Min.X+barWidth {
style = ui.NewStyle(console.ColorWhite, ui.ColorClear) style = ui.NewStyle(g.palette.BaseColor, ui.ColorClear)
} }
buffer.SetCell(ui.NewCell(char, style), image.Pt(labelXCoordinate+i, labelYCoordinate)) buffer.SetCell(ui.NewCell(char, style), image.Pt(labelXCoordinate+i, labelYCoordinate))
} }

View File

@ -8,11 +8,12 @@ import (
) )
type Menu struct { type Menu struct {
ui.Block *ui.Block
options []MenuOption options []MenuOption
component Component component Component
mode MenuMode mode MenuMode
option MenuOption option MenuOption
palette console.Palette
} }
type MenuMode rune type MenuMode rune
@ -37,14 +38,13 @@ const (
minimalMenuHeight = 8 minimalMenuHeight = 8
) )
func NewMenu() *Menu { func NewMenu(palette console.Palette) *Menu {
block := *ui.NewBlock()
block.Border = true
return &Menu{ return &Menu{
Block: block, Block: NewBlock("", true, palette),
options: []MenuOption{MenuOptionMove, MenuOptionResize, MenuOptionPinpoint, MenuOptionResume}, options: []MenuOption{MenuOptionMove, MenuOptionResize, MenuOptionPinpoint, MenuOptionResume},
mode: MenuModeIdle, mode: MenuModeIdle,
option: MenuOptionMove, option: MenuOptionMove,
palette: palette,
} }
} }
@ -102,7 +102,7 @@ func (m *Menu) Draw(buffer *ui.Buffer) {
} }
m.updateDimensions() m.updateDimensions()
buffer.Fill(ui.NewCell(' ', ui.NewStyle(ui.ColorBlack)), m.GetRect()) buffer.Fill(ui.NewCell(' ', ui.NewStyle(m.palette.ReverseColor)), m.GetRect())
if m.Dy() > minimalMenuHeight { if m.Dy() > minimalMenuHeight {
m.drawInnerBorder(buffer) m.drawInnerBorder(buffer)
@ -198,9 +198,8 @@ func (m *Menu) printAllDirectionsArrowSign(buffer *ui.Buffer, y int) {
func (m *Menu) renderOptions(buffer *ui.Buffer) { func (m *Menu) renderOptions(buffer *ui.Buffer) {
// TODO extract styles to console.Palette highlightedStyle := ui.NewStyle(m.palette.BaseColor, console.ColorOlive)
highlightedStyle := ui.NewStyle(console.ColorBlack, console.ColorOlive) regularStyle := ui.NewStyle(m.palette.BaseColor, m.palette.ReverseColor)
regularStyle := ui.NewStyle(console.ColorWhite, console.ColorBlack)
offset := 1 offset := 1
for _, option := range m.options { for _, option := range m.options {
@ -212,7 +211,7 @@ func (m *Menu) renderOptions(buffer *ui.Buffer) {
if option != MenuOptionPinpoint || m.component.Type == config.TypeRunChart { if option != MenuOptionPinpoint || m.component.Type == config.TypeRunChart {
offset += 2 offset += 2
point := getMiddlePoint(m.Block.Rectangle, string(option), offset-5) point := getMiddlePoint(m.Block.Rectangle, string(option), offset-6)
buffer.SetString(string(option), style, point) buffer.SetString(string(option), style, point)
} }
} }

View File

@ -2,7 +2,6 @@ package runchart
import ( import (
ui "github.com/gizak/termui/v3" ui "github.com/gizak/termui/v3"
"github.com/sqshq/sampler/console"
"image" "image"
"math" "math"
"time" "time"
@ -35,13 +34,13 @@ func (c *RunChart) newChartGrid() ChartGrid {
func (c *RunChart) renderAxes(buffer *ui.Buffer) { func (c *RunChart) renderAxes(buffer *ui.Buffer) {
// draw origin cell // draw origin cell
buffer.SetCell( buffer.SetCell(
ui.NewCell(ui.BOTTOM_LEFT, ui.NewStyle(console.ColorWhite)), ui.NewCell(ui.BOTTOM_LEFT, ui.NewStyle(c.palette.BaseColor)),
image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, c.Inner.Max.Y-xAxisLabelsHeight-1)) image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, c.Inner.Max.Y-xAxisLabelsHeight-1))
// draw x axis line // draw x axis line
for i := c.grid.minTimeWidth + 1; i < c.Inner.Dx(); i++ { for i := c.grid.minTimeWidth + 1; i < c.Inner.Dx(); i++ {
buffer.SetCell( buffer.SetCell(
ui.NewCell(ui.HORIZONTAL_DASH, ui.NewStyle(console.ColorWhite)), ui.NewCell(ui.HORIZONTAL_DASH, ui.NewStyle(c.palette.BaseColor)),
image.Pt(i+c.Inner.Min.X, c.Inner.Max.Y-xAxisLabelsHeight-1)) image.Pt(i+c.Inner.Min.X, c.Inner.Max.Y-xAxisLabelsHeight-1))
} }
@ -49,7 +48,7 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
for y := 0; y < c.Inner.Dy()-xAxisLabelsHeight-2; y = y + 2 { for y := 0; y < c.Inner.Dy()-xAxisLabelsHeight-2; y = y + 2 {
for x := 1; x <= c.grid.linesCount; x++ { for x := 1; x <= c.grid.linesCount; x++ {
buffer.SetCell( buffer.SetCell(
ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(console.ColorDarkGrey)), ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(c.palette.MediumColor)),
image.Pt(c.grid.maxTimeWidth-x*xAxisGridWidth, y+c.Inner.Min.Y+1)) image.Pt(c.grid.maxTimeWidth-x*xAxisGridWidth, y+c.Inner.Min.Y+1))
} }
} }
@ -57,7 +56,7 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
// draw y axis line // draw y axis line
for i := 0; i < c.Inner.Dy()-xAxisLabelsHeight-1; i++ { for i := 0; i < c.Inner.Dy()-xAxisLabelsHeight-1; i++ {
buffer.SetCell( buffer.SetCell(
ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(console.ColorWhite)), ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(c.palette.BaseColor)),
image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, i+c.Inner.Min.Y)) image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, i+c.Inner.Min.Y))
} }
@ -66,7 +65,7 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
labelTime := c.grid.timeRange.max.Add(time.Duration(-i) * c.timescale) labelTime := c.grid.timeRange.max.Add(time.Duration(-i) * c.timescale)
buffer.SetString( buffer.SetString(
labelTime.Format("15:04:05"), labelTime.Format("15:04:05"),
ui.NewStyle(console.ColorWhite), ui.NewStyle(c.palette.BaseColor),
image.Pt(c.grid.maxTimeWidth-xAxisLabelsWidth/2-i*(xAxisGridWidth), c.Inner.Max.Y-1)) image.Pt(c.grid.maxTimeWidth-xAxisLabelsWidth/2-i*(xAxisGridWidth), c.Inner.Max.Y-1))
} }
@ -78,13 +77,13 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
value := c.grid.valueExtrema.max - (valuePerY * float64(i) * (yAxisLabelsIndent + yAxisLabelsHeight)) value := c.grid.valueExtrema.max - (valuePerY * float64(i) * (yAxisLabelsIndent + yAxisLabelsHeight))
buffer.SetString( buffer.SetString(
formatValue(value, c.scale), formatValue(value, c.scale),
ui.NewStyle(console.ColorWhite), ui.NewStyle(c.palette.BaseColor),
image.Pt(c.Inner.Min.X, 1+c.Inner.Min.Y+i*(yAxisLabelsIndent+yAxisLabelsHeight))) image.Pt(c.Inner.Min.X, 1+c.Inner.Min.Y+i*(yAxisLabelsIndent+yAxisLabelsHeight)))
} }
} else { } else {
buffer.SetString( buffer.SetString(
formatValue(c.grid.valueExtrema.max, c.scale), formatValue(c.grid.valueExtrema.max, c.scale),
ui.NewStyle(console.ColorWhite), ui.NewStyle(c.palette.BaseColor),
image.Pt(c.Inner.Min.X, c.Inner.Min.Y+c.Inner.Dy()/2)) image.Pt(c.Inner.Min.X, c.Inner.Min.Y+c.Inner.Dy()/2))
} }
} }

View File

@ -3,7 +3,6 @@ package runchart
import ( import (
"fmt" "fmt"
ui "github.com/gizak/termui/v3" ui "github.com/gizak/termui/v3"
"github.com/sqshq/sampler/console"
"image" "image"
"math" "math"
) )
@ -55,7 +54,7 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
y := c.Inner.Min.Y + yAxisLegendIndent + row*height y := c.Inner.Min.Y + yAxisLegendIndent + row*height
titleStyle := ui.NewStyle(line.color) titleStyle := ui.NewStyle(line.color)
detailsStyle := ui.NewStyle(console.ColorWhite) detailsStyle := ui.NewStyle(c.palette.BaseColor)
buffer.SetString(string(ui.DOT), titleStyle, image.Pt(x-2, y)) buffer.SetString(string(ui.DOT), titleStyle, image.Pt(x-2, y))
buffer.SetString(line.label, titleStyle, image.Pt(x, y)) buffer.SetString(line.label, titleStyle, image.Pt(x, y))

View File

@ -51,6 +51,7 @@ type RunChart struct {
selection time.Time selection time.Time
scale int scale int
legend Legend legend Legend
palette console.Palette
} }
type TimePoint struct { type TimePoint struct {
@ -78,10 +79,10 @@ type ValueExtrema struct {
min float64 min float64
} }
func NewRunChart(c config.RunChartConfig) *RunChart { func NewRunChart(c config.RunChartConfig, palette console.Palette) *RunChart {
chart := RunChart{ chart := RunChart{
Block: component.NewBlock(c.Title, true), Block: component.NewBlock(c.Title, true, palette),
Consumer: data.NewConsumer(), Consumer: data.NewConsumer(),
lines: []TimeLine{}, lines: []TimeLine{},
timescale: calculateTimescale(*c.RefreshRateMs), timescale: calculateTimescale(*c.RefreshRateMs),
@ -89,6 +90,7 @@ func NewRunChart(c config.RunChartConfig) *RunChart {
scale: *c.Scale, scale: *c.Scale,
mode: ModeDefault, mode: ModeDefault,
legend: Legend{Enabled: c.Legend.Enabled, Details: c.Legend.Details}, legend: Legend{Enabled: c.Legend.Enabled, Details: c.Legend.Details},
palette: palette,
} }
for _, i := range c.Items { for _, i := range c.Items {

View File

@ -12,16 +12,16 @@ const (
) )
type StatusBar struct { type StatusBar struct {
ui.Block *ui.Block
keyBindings []string keyBindings []string
configFileName string configFileName string
} }
func NewStatusLine(configFileName string) *StatusBar { func NewStatusLine(configFileName string, palette console.Palette) *StatusBar {
block := *ui.NewBlock() block := *ui.NewBlock()
block.Border = false block.Border = false
return &StatusBar{ return &StatusBar{
Block: block, Block: NewBlock("", false, palette),
configFileName: configFileName, configFileName: configFileName,
keyBindings: []string{ keyBindings: []string{
"(Q) quit", "(Q) quit",

View File

@ -80,6 +80,6 @@ asciiboxes:
position: [[53, 17], [27, 5]] position: [[53, 17], [27, 5]]
value: date +%r value: date +%r
- title: UTC TIME - title: UTC TIME
position: [[53, 22], [27, 7]] position: [[53, 22], [27, 6]]
value: env TZ=UTC date +%r value: env TZ=UTC date +%r
font: 3d font: 3d

View File

@ -98,10 +98,6 @@ func (c *Config) setDefaultValues() {
font := console.AsciiFontFlat font := console.AsciiFontFlat
box.Font = &font box.Font = &font
} }
if box.Color == nil {
color := console.ColorWhite
box.Color = &color
}
c.AsciiBoxes[i] = box c.AsciiBoxes[i] = box
} }
} }
@ -139,12 +135,12 @@ func (c *Config) setDefaultLayout() {
func (c *Config) setDefaultColors() { func (c *Config) setDefaultColors() {
palette := console.GetPalette(*c.Theme) palette := console.GetPalette(*c.Theme)
colorsCount := len(palette.Colors) colorsCount := len(palette.ContentColors)
for _, ch := range c.RunCharts { for _, ch := range c.RunCharts {
for j, item := range ch.Items { for j, item := range ch.Items {
if item.Color == nil { if item.Color == nil {
item.Color = &palette.Colors[j%colorsCount] item.Color = &palette.ContentColors[j%colorsCount]
ch.Items[j] = item ch.Items[j] = item
} }
} }
@ -153,7 +149,7 @@ func (c *Config) setDefaultColors() {
for _, b := range c.BarCharts { for _, b := range c.BarCharts {
for j, item := range b.Items { for j, item := range b.Items {
if item.Color == nil { if item.Color == nil {
item.Color = &palette.Colors[j%colorsCount] item.Color = &palette.ContentColors[j%colorsCount]
b.Items[j] = item b.Items[j] = item
} }
} }
@ -161,7 +157,7 @@ func (c *Config) setDefaultColors() {
for i, g := range c.Gauges { for i, g := range c.Gauges {
if g.Color == nil { if g.Color == nil {
g.Color = &palette.Colors[i%colorsCount] g.Color = &palette.ContentColors[i%colorsCount]
c.Gauges[i] = g c.Gauges[i] = g
} }
} }

View File

@ -20,7 +20,10 @@ const (
ColorOrange ui.Color = 166 ColorOrange ui.Color = 166
ColorPurple ui.Color = 129 ColorPurple ui.Color = 129
ColorGreen ui.Color = 64 ColorGreen ui.Color = 64
ColorDarkRed ui.Color = 88
ColorBlueViolet ui.Color = 57
ColorDarkGrey ui.Color = 238 ColorDarkGrey ui.Color = 238
ColorLightGrey ui.Color = 254
ColorGrey ui.Color = 242 ColorGrey ui.Color = 242
ColorWhite ui.Color = 15 ColorWhite ui.Color = 15
ColorBlack ui.Color = 0 ColorBlack ui.Color = 0
@ -33,16 +36,28 @@ const (
) )
type Palette struct { type Palette struct {
Colors []ui.Color ContentColors []ui.Color
// TODO Menu colors, like Dark, Medium, Light etc BaseColor ui.Color
MediumColor ui.Color
ReverseColor ui.Color
} }
func GetPalette(theme Theme) Palette { func GetPalette(theme Theme) Palette {
switch theme { switch theme {
case ThemeDark: case ThemeDark:
return Palette{Colors: []ui.Color{ColorOlive, ColorDeepSkyBlue, ColorDeepPink, ColorWhite, ColorGrey, ColorGreen, ColorOrange, ColorCian, ColorPurple}} return Palette{
ContentColors: []ui.Color{ColorOlive, ColorDeepSkyBlue, ColorDeepPink, ColorWhite, ColorGrey, ColorGreen, ColorOrange, ColorCian, ColorPurple},
BaseColor: ColorWhite,
MediumColor: ColorDarkGrey,
ReverseColor: ColorBlack,
}
case ThemeLight: case ThemeLight:
return Palette{Colors: []ui.Color{ColorOlive, ColorDeepSkyBlue, ColorDeepPink, ColorWhite, ColorGrey, ColorGreen, ColorOrange, ColorCian, ColorPurple}} return Palette{
ContentColors: []ui.Color{ColorBlack, ColorDarkRed, ColorBlueViolet, ColorGrey, ColorGreen},
BaseColor: ColorBlack,
MediumColor: ColorLightGrey,
ReverseColor: ColorWhite,
}
default: default:
panic(fmt.Sprintf("Following theme is not supported: %v", theme)) panic(fmt.Sprintf("Following theme is not supported: %v", theme))
} }

12
main.go
View File

@ -38,28 +38,30 @@ func main() {
player := asset.NewAudioPlayer() player := asset.NewAudioPlayer()
defer player.Close() defer player.Close()
palette := console.GetPalette(*cfg.Theme)
width, height := ui.TerminalDimensions() width, height := ui.TerminalDimensions()
lout := layout.NewLayout(width, height, component.NewStatusLine(opt.ConfigFile), component.NewMenu())
lout := layout.NewLayout(width, height, component.NewStatusLine(opt.ConfigFile, palette), component.NewMenu(palette))
starter := &Starter{lout, player, opt} starter := &Starter{lout, player, opt}
for _, c := range cfg.RunCharts { for _, c := range cfg.RunCharts {
cpt := runchart.NewRunChart(c) cpt := runchart.NewRunChart(c, palette)
starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers) starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers)
} }
for _, c := range cfg.AsciiBoxes { for _, c := range cfg.AsciiBoxes {
cpt := asciibox.NewAsciiBox(c) cpt := asciibox.NewAsciiBox(c, palette)
starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers) starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)
} }
for _, c := range cfg.BarCharts { for _, c := range cfg.BarCharts {
cpt := barchart.NewBarChart(c) cpt := barchart.NewBarChart(c, palette)
starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers) starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers)
} }
for _, c := range cfg.Gauges { for _, c := range cfg.Gauges {
cpt := gauge.NewGauge(c) cpt := gauge.NewGauge(c, palette)
starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers) starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers)
} }