diff options
Diffstat (limited to 'internal')
-rw-r--r-- | internal/exporter/exporter.go | 56 | ||||
-rw-r--r-- | internal/picker/picker.go | 89 | ||||
-rw-r--r-- | internal/slider/slider.go | 22 | ||||
-rw-r--r-- | internal/tui/tui.go | 5 |
4 files changed, 167 insertions, 5 deletions
diff --git a/internal/exporter/exporter.go b/internal/exporter/exporter.go new file mode 100644 index 0000000..3ecf6ef --- /dev/null +++ b/internal/exporter/exporter.go @@ -0,0 +1,56 @@ +package exporter + +import ( + "fmt" + "strings" +) + +const ( + rgbFormat = iota + hexFormat + hslFormat + hwbFormat +) + +func Export(hex string, format int) string { + switch format { + case hexFormat: + return hex + case rgbFormat: + return toRgb(hex) + case hslFormat: + return "Not Implemented yet..." + case hwbFormat: + return "Not Implemented yet..." + default: + return "Unknown export format requested" + } +} + +func toRgb(hex string) string { + hex = strings.TrimPrefix(hex, "#") + r, g, b := HexToI(hex[:2]), HexToI(hex[2:4]), HexToI(hex[4:6]) + return fmt.Sprintf("rgb(%d, %d, %d)", r, g, b) +} + +func HexToI(s string) int { + lenS := len(s) - 1 + chars := "0123456789ABCDEF" + s = strings.ToUpper(s) + var ttl int = 0 + + for n := lenS; n >= 0; n-- { + done := false + for i := 0; i < len(chars); i++ { + if s[n] == chars[i] { + ttl += i * (n << 4) + done = true + break + } + } + if !done { // Still not done after checking all chars + return -1 + } + } + return ttl +} diff --git a/internal/picker/picker.go b/internal/picker/picker.go new file mode 100644 index 0000000..290e9f9 --- /dev/null +++ b/internal/picker/picker.go @@ -0,0 +1,89 @@ +package picker + +import ( + "github.com/ChausseBenjamin/golorpicker/internal/slider" + "github.com/charmbracelet/bubbles/list" + tea "github.com/charmbracelet/bubbletea" +) + +const ( + rgbTitle string = "RGB" +) + +// A picker is a list of sliders allowing the user to select a color +// It must therefore be capable of exporting a HEX value for previewing +// as well as a + +type RGBPicker struct { + sliders list.Model + r, g, b slider.Slider + loaded bool +} + +func NewRGB() *RGBPicker { + r := slider.New("R", 0, 255) + g := slider.New("G", 0, 255) + b := slider.New("B", 0, 255) + + sliders := list.New( + []list.Item{*r, *g, *b}, + list.NewDefaultDelegate(), + 80, 6, + ) + sliders.Title = rgbTitle + sliders.SetShowHelp(false) + sliders.SetShowFilter(false) + sliders.DisableQuitKeybindings() + + return &RGBPicker{ + sliders: sliders, + r: *r, + g: *g, + b: *b, + loaded: false, + } +} + +func (p RGBPicker) toHex() string { + const txt = "0123456789ABCDEF" + rgb := string([]byte{ + '#', + txt[(p.r.Val()>>4)&0x0F], + txt[p.r.Val()&0x0F], + txt[(p.g.Val()>>4)&0x0F], + txt[p.g.Val()&0x0F], + txt[(p.b.Val()>>4)&0x0F], + txt[p.b.Val()&0x0F], + }) + return rgb +} + +func (p RGBPicker) Init() tea.Cmd { + return nil +} + +func (p RGBPicker) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.WindowSizeMsg: + if p.sliders.Width() != msg.Width && !p.loaded { + p.sliders.SetWidth(msg.Width - 6) + p.loaded = true + } + case tea.KeyMsg: + key := msg.String() + for _, k := range slider.Keystrokes() { + if key == k { + m := p.sliders.Items()[p.sliders.Index()].(slider.Slider) + return m.Update(msg) + } + } + } + + var cmd tea.Cmd + p.sliders, cmd = p.sliders.Update(msg) + return p, cmd +} + +func (p RGBPicker) View() string { + return p.sliders.View() +} diff --git a/internal/slider/slider.go b/internal/slider/slider.go index 0c0a89e..e882a29 100644 --- a/internal/slider/slider.go +++ b/internal/slider/slider.go @@ -51,8 +51,13 @@ func (s Slider) Dec(val int) (tea.Model, tea.Cmd) { return s.Set(s.val - val) } -func (s Slider) View() string { - return s.bar.View() + fmt.Sprintf(" (%d)", s.val) +func (s Slider) Val() int { + return s.val +} + +func New(name string, v int, maxV int, opt ...progress.Option) *Slider { + opt = append(opt, progress.WithoutPercentage()) + return &Slider{name: name, max: maxV, val: v, options: opt} } func (s Slider) Animate(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -66,9 +71,8 @@ func (s Slider) Init() tea.Cmd { return s.bar.Init() } -func New(name string, v int, maxV int, opt ...progress.Option) *Slider { - opt = append(opt, progress.WithoutPercentage()) - return &Slider{name: name, max: maxV, val: v, options: opt} +func (s Slider) View() string { + return s.bar.View() + fmt.Sprintf(" (%d)", s.val) } func (s Slider) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -103,3 +107,11 @@ func (s Slider) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } // }}} +// Implement the list.Item interface {{{ + +func (s Slider) FilterValue() string { + // Sliders shouldn't be filtered + return "" +} + +// }}} diff --git a/internal/tui/tui.go b/internal/tui/tui.go new file mode 100644 index 0000000..3bbbc95 --- /dev/null +++ b/internal/tui/tui.go @@ -0,0 +1,5 @@ +package tui + +// TODO: Implement the TUI struct +// This will be the main thing containing all elements +type TUI struct{} |