From 19b71a7cec961e5d88cca9da614d50ec396aa9c3 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 3 Jun 2024 03:48:13 -0400 Subject: [PATCH] Add aluminum style --- internal/registrar/registrar_unix.go | 16 +- internal/theme/style/aluminum/default.go | 19 ++ internal/theme/style/aluminum/style.go | 305 +++++++++++++++++++++++ 3 files changed, 335 insertions(+), 5 deletions(-) create mode 100644 internal/theme/style/aluminum/default.go create mode 100644 internal/theme/style/aluminum/style.go diff --git a/internal/registrar/registrar_unix.go b/internal/registrar/registrar_unix.go index 4c7380c..caea02c 100644 --- a/internal/registrar/registrar_unix.go +++ b/internal/registrar/registrar_unix.go @@ -5,12 +5,22 @@ import "os" import "log" import "git.tebibyte.media/tomo/backend/x" import "git.tebibyte.media/tomo/tomo" +import dataTheme "git.tebibyte.media/tomo/nasin/internal/theme" import "git.tebibyte.media/tomo/nasin/internal/theme/icons/xdg" import "git.tebibyte.media/tomo/nasin/internal/theme/icons/fallback" import "git.tebibyte.media/tomo/nasin/internal/theme/style/fallback" +import "git.tebibyte.media/tomo/nasin/internal/theme/style/aluminum" func Init () error { - theme := fallbackStyle.New() + var theme *dataTheme.Theme + // TODO eventually get rid of this when we make a file format for + // storing visual styles + if os.Getenv("TOMO_USE_ALUMINUM_STYLE") != "" { + theme = aluminumStyle.New() + } else { + theme = fallbackStyle.New() + } + theme.IconTheme = fallbackIcons.New() iconThemeName := os.Getenv("TOMO_XDG_ICON_THEME") if iconThemeName != "" { @@ -21,10 +31,6 @@ func Init () error { log.Printf("nasin: could not load icon theme '%s': %v", iconThemeName, err) } } - - if theme.IconTheme == nil { - theme.IconTheme = fallbackIcons.New() - } tomo.SetTheme(theme) tomo.Register(1, x.New) diff --git a/internal/theme/style/aluminum/default.go b/internal/theme/style/aluminum/default.go new file mode 100644 index 0000000..c59cdef --- /dev/null +++ b/internal/theme/style/aluminum/default.go @@ -0,0 +1,19 @@ +package aluminumStyle + +import "image/color" +import "git.tebibyte.media/tomo/tomo" +import dataTheme "git.tebibyte.media/tomo/nasin/internal/theme" + +// New returns Aluminum, a futuristic, bluish-white style. +func New () *dataTheme.Theme { + return &dataTheme.Theme { + Colors: map[tomo.Color] color.Color { + tomo.ColorBackground: colorBackground, + tomo.ColorForeground: colorForeground, + tomo.ColorRaised: colorCarved, + tomo.ColorSunken: colorCarved, + tomo.ColorAccent: colorFocus, + }, + Rules: rules, + } +} diff --git a/internal/theme/style/aluminum/style.go b/internal/theme/style/aluminum/style.go new file mode 100644 index 0000000..59aa809 --- /dev/null +++ b/internal/theme/style/aluminum/style.go @@ -0,0 +1,305 @@ +package aluminumStyle + +import "image/color" +import "git.tebibyte.media/tomo/tomo" +import "golang.org/x/image/font/basicfont" +import dataTheme "git.tebibyte.media/tomo/nasin/internal/theme" + +func hex (color uint32) (c color.RGBA) { + c.A = uint8(color) + c.B = uint8(color >> 8) + c.G = uint8(color >> 16) + c.R = uint8(color >> 24) + return +} + +func border (top, right, bottom, left uint32, width ...int) tomo.Border { + return tomo.Border { + Width: tomo.I(width...), + Color: [4]color.Color { + hex(top), hex(right), + hex(bottom), hex(left), + }, + } +} + +var colorDot = hex(0x7391c080) +var colorFocus = hex(0x5f8bc4FF) +var colorHighlight = hex(0x5f8bc4FF) +var colorBackground = hex(0xd6d6d6FF) +var colorForeground = color.Black +var colorOutline = color.Black +var colorGutter = hex(0xbfc6d1FF) +var colorGutterHovered = hex(0xc5cbd6FF) +var colorCarved = hex(0xe9eaeaFF) +var colorCarvedPressed = hex(0xe3e4e4FF) +var colorCarvedFocused = hex(0xe4e6e8FF) +var colorCarvedHovered = hex(0xf1f3f5FF) + +var outline = tomo.Border { + Width: tomo.I(1), + Color: [4]color.Color { + colorOutline, + colorOutline, + colorOutline, + colorOutline, + }, +} + +var borderEngraved = border(0xc3c3c5FF, 0xe3e3e3FF, 0xe9e9e9ff, 0xc2c2c2ff, 1) +var borderGap = border(0x697c7cFF, 0x566767FF, 0x566767ff, 0x697c7cff, 1) +var borderLifted = border(0xf9fafcFF, 0xc2c8d3FF, 0xa4afc0ff, 0xf5f6f8ff, 1) +var borderFocused = border(0x5f8bc4FF, 0x5f8bc4FF, 0x5f8bc4ff, 0x5f8bc4ff, 1) +var borderInnerShadow = border(0xa4afc0FF, 0xa4afc0FF, 0xa4afc0ff, 0xa4afc0ff, 1, 0, 0, 1) +var borderOuterShadow = border(0xa4afc0FF, 0xa4afc0FF, 0xa4afc0ff, 0xa4afc0ff, 0, 1, 1, 0) + +var rules = []dataTheme.Rule { + // *.*[*] + dataTheme.Rule { + Default: dataTheme.AS ( + dataTheme.AttrFace { Face: basicfont.Face7x13 }, + dataTheme.AttrTextColor { Color: tomo.ColorForeground }, + dataTheme.AttrDotColor { Color: colorDot }, + dataTheme.AttrGap { X: 8, Y: 8 }, + ), + }, + + // *.Button[*] + dataTheme.Rule { + Role: tomo.R("", "Button", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderLifted, + }, + dataTheme.AttrPadding(tomo.I(4, 8)), + dataTheme.AttrColor { Color: tomo.ColorRaised }, + ), + Pressed: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderInnerShadow, + }, + dataTheme.AttrPadding(tomo.I(5, 8, 4, 9)), + dataTheme.AttrColor { Color: colorCarvedPressed }, + ), + Focused: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderFocused, + borderLifted, + }, + dataTheme.AttrPadding(tomo.I(4, 8)), + dataTheme.AttrColor { Color: colorCarvedFocused }, + ), + Hovered: dataTheme.AS ( + dataTheme.AttrColor { Color: colorCarvedHovered }, + ), + }, + + // *.TextInput[*] + dataTheme.Rule { + Role: tomo.R("", "TextInput", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderInnerShadow, + }, + dataTheme.AttrColor { Color: tomo.ColorSunken }, + dataTheme.AttrPadding(tomo.I(5, 4, 4, 5)), + ), + Focused: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderFocused, + borderInnerShadow, + }, + ), + }, + + // *.TextView[*] + dataTheme.Rule { + Role: tomo.R("", "TextView", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderInnerShadow, + }, + dataTheme.AttrColor { Color: tomo.ColorSunken }, + dataTheme.AttrPadding(tomo.I(8)), + ), + }, + + // *.NumberInput[*] + dataTheme.Rule { + Role: tomo.R("", "NumberInput", ""), + Default: dataTheme.AS ( + dataTheme.AttrGap { }, + ), + }, + + // *.Container[sunken] + dataTheme.Rule { + Role: tomo.R("", "Container", "sunken"), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderInnerShadow, + }, + dataTheme.AttrColor { Color: tomo.ColorSunken }, + dataTheme.AttrPadding(tomo.I(8)), + ), + }, + + // *.Container[outer] + dataTheme.Rule { + Role: tomo.R("", "Container", "outer"), + Default: dataTheme.AS ( + dataTheme.AttrColor { Color: tomo.ColorBackground }, + dataTheme.AttrPadding(tomo.I(8)), + ), + }, + + // *.Container[menu] + dataTheme.Rule { + Role: tomo.R("", "Container", "menu"), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderGap, + borderLifted, + }, + dataTheme.AttrColor { Color: tomo.ColorBackground }, + dataTheme.AttrGap { }, + ), + }, + + // *.Heading[*] + dataTheme.Rule { + Role: tomo.R("", "Heading", ""), + Default: dataTheme.AS ( + dataTheme.AttrAlign { X: tomo.AlignMiddle, Y: tomo.AlignMiddle }, + ), + }, + + // *.Separator[*] + dataTheme.Rule { + Role: tomo.R("", "Separator", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + }, + ), + }, + + // *.Slider[*] + dataTheme.Rule { + Role: tomo.R("", "Slider", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderInnerShadow, + }, + dataTheme.AttrColor { Color: colorGutter }, + ), + Focused: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderFocused, + borderInnerShadow, + }, + ), + Hovered: dataTheme.AS ( + dataTheme.AttrColor { Color: colorGutterHovered }, + ), + }, + + // *.Slider[horizontal] + dataTheme.Rule { + Role: tomo.R("", "Slider", "horizontal"), + Default: dataTheme.AS(dataTheme.AttrMinimumSize { X: 48 }), + }, + + // *.Slider[vertical] + dataTheme.Rule { + Role: tomo.R("", "Slider", "vertical"), + Default: dataTheme.AS(dataTheme.AttrMinimumSize { Y: 48 }), + }, + + // *.SliderHandle[*] + dataTheme.Rule { + Role: tomo.R("", "SliderHandle", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderOuterShadow, + borderGap, + borderLifted, + }, + dataTheme.AttrColor { Color: tomo.ColorRaised }, + dataTheme.AttrMinimumSize { X: 12, Y: 12, }, + ), + }, + + // *.Checkbox[*] + dataTheme.Rule { + Role: tomo.R("", "Checkbox", ""), + Default: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderGap, + borderInnerShadow, + }, + dataTheme.AttrColor { Color: tomo.ColorSunken }, + dataTheme.AttrPadding(tomo.I(0, 1, 1, 0)), + dataTheme.AttrMinimumSize { X: 19, Y: 19 }, + ), + Focused: dataTheme.AS ( + dataTheme.AttrBorder { + borderEngraved, + borderFocused, + borderInnerShadow, + }, + dataTheme.AttrPadding(tomo.I(0)), + ), + }, + + // *.LabelCheckbox[*] + dataTheme.Rule { + Role: tomo.R("", "LabelCheckbox", ""), + Default: dataTheme.AS ( + dataTheme.AttrGap { X: 8, Y: 8 }, + ), + }, + + // *.MenuItem[*] + dataTheme.Rule { + Role: tomo.R("", "MenuItem", ""), + Default: dataTheme.AS ( + dataTheme.AttrPadding(tomo.I(4)), + dataTheme.AttrGap { X: 4, Y: 4 }, + dataTheme.AttrColor { Color: color.Transparent }, + ), + Hovered: dataTheme.AS ( + dataTheme.AttrColor { Color: colorDot }, + ), + Focused: dataTheme.AS ( + dataTheme.AttrColor { Color: colorDot }, + ), + }, + + // *.File[*] + dataTheme.Rule { + Role: tomo.R("", "File", ""), + Default: dataTheme.AS ( + dataTheme.AttrColor { Color: color.Transparent }, + ), + Focused: dataTheme.AS ( + dataTheme.AttrColor { Color: colorDot }, + ), + }, +}