113 lines
2.2 KiB
Go
113 lines
2.2 KiB
Go
package display
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"image/color"
|
|
|
|
"git.dvdt.dev/david/bitcoin-ticker-pi/fonts"
|
|
rgbmatrix "git.dvdt.dev/david/bitcoin-ticker-pi/go-rpi-rgb-led-matrix"
|
|
)
|
|
|
|
type Alignment uint8
|
|
|
|
const (
|
|
Left Alignment = iota
|
|
Center
|
|
Right
|
|
)
|
|
|
|
var (
|
|
ErrUnsupportedSlotHeight = errors.New("unsupported slot height")
|
|
)
|
|
|
|
type Segment struct {
|
|
Text string
|
|
Color color.RGBA
|
|
bitmap [][]color.RGBA
|
|
}
|
|
|
|
func (s *Segment) Draw(canvas *rgbmatrix.Canvas, x, y int) {
|
|
for i, row := range s.bitmap {
|
|
drawRow(canvas, row, x, y+i)
|
|
}
|
|
}
|
|
|
|
func drawRow(canvas *rgbmatrix.Canvas, row []color.RGBA, x, y int) {
|
|
for i := 0; i < len(row); i++ {
|
|
canvas.Set(x+i, y, color.Black)
|
|
canvas.Set(x+i, y, row[i])
|
|
}
|
|
}
|
|
|
|
type Slot struct {
|
|
alignment Alignment
|
|
segmentLimit int
|
|
segmentHeight int
|
|
segmentWidth int
|
|
x, xoffset, y int
|
|
text []Segment
|
|
}
|
|
|
|
func NewSlot(alignment Alignment, limit, height, width, x, y int) *Slot {
|
|
return &Slot{
|
|
alignment: alignment,
|
|
segmentLimit: limit,
|
|
segmentHeight: height,
|
|
segmentWidth: width,
|
|
x: x,
|
|
y: y,
|
|
text: []Segment{},
|
|
}
|
|
}
|
|
|
|
func (s *Slot) Update(text []Segment) error {
|
|
if len(text) > s.segmentLimit {
|
|
text = text[:s.segmentLimit-3]
|
|
text = append(text, []Segment{
|
|
{Text: ".", Color: fonts.White},
|
|
{Text: ".", Color: fonts.White},
|
|
{Text: ".", Color: fonts.White},
|
|
}...)
|
|
}
|
|
|
|
// Default to left alignment.
|
|
s.xoffset = 0
|
|
if s.alignment == Center {
|
|
s.xoffset = ((s.segmentLimit * s.segmentWidth) - (len(text) * s.segmentWidth)) / 2
|
|
}
|
|
if s.alignment == Right {
|
|
s.xoffset = (s.segmentLimit * s.segmentWidth) - (len(text) * s.segmentWidth)
|
|
}
|
|
|
|
var font fonts.Font
|
|
switch s.segmentHeight {
|
|
case 5:
|
|
font = fonts.Face5x4
|
|
case 7:
|
|
font = fonts.Face7x5
|
|
case 9:
|
|
font = fonts.Face9x6
|
|
case 13:
|
|
font = fonts.Face13x8
|
|
default:
|
|
return fmt.Errorf("%w: %d", ErrUnsupportedSlotHeight, s.segmentHeight)
|
|
}
|
|
|
|
for i, t := range text {
|
|
c, err := font.ToColor(t.Text, t.Color)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
text[i].bitmap = c
|
|
}
|
|
s.text = text
|
|
return nil
|
|
}
|
|
|
|
func (s *Slot) Draw(canvas *rgbmatrix.Canvas) {
|
|
for i, segment := range s.text {
|
|
segment.Draw(canvas, s.x+(i*s.segmentWidth)+s.xoffset, s.y)
|
|
}
|
|
}
|