aluminum/theme.go

242 lines
5.7 KiB
Go

package aluminum
import "image"
import "image/color"
import "git.tebibyte.media/tomo/tomo"
import "golang.org/x/image/font/basicfont"
import "git.tebibyte.media/tomo/tomo/data"
import "git.tebibyte.media/tomo/tomo/theme"
import "git.tebibyte.media/tomo/tomo/input"
import "git.tebibyte.media/tomo/tomo/event"
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 engravedBorder = border(0xc3c3c5FF, 0xe3e3e3FF, 0xe9e9e9ff, 0xc2c2c2ff, 1)
var gapBorder = border(0x697c7cFF, 0x566767FF, 0x566767ff, 0x697c7cff, 1)
var focusedBorder = border(0x5f8bc4FF, 0x5f8bc4FF, 0x5f8bc4ff, 0x5f8bc4ff, 1)
var buttonBorder = border(0xf9fafcFF, 0xc2c8d3FF, 0xa4afc0ff, 0xf5f6f8ff, 1)
var sunkenShadow = border(0xa4afc0FF, 0xa4afc0FF, 0xa4afc0ff, 0xa4afc0ff, 1, 0, 0, 1)
var outerShadow = border(0xa4afc0FF, 0xa4afc0FF, 0xa4afc0ff, 0xa4afc0ff, 0, 1, 1, 0)
var buttonColor = hex(0xe9eaeaFF)
var buttonColorPressed = hex(0xe3e4e4FF)
var buttonColorFocused = hex(0xe4e6e8FF)
var buttonColorHovered = hex(0xf1f3f5FF)
var dotColor = hex(0xa4b1c6FF)
var inputColor = hex(0xe3e4e4FF)
var textColor = hex(0x000000FF)
var backgroundColor = hex(0xd6d6d6FF)
var gutterColor = hex(0xbfc6d1FF)
var gutterColorHovered = hex(0xc5cbd6FF)
type Theme struct { }
func (this *Theme) RGBA (id theme.Color) (r, g, b, a uint32) {
switch id {
case theme.ColorBackground: return backgroundColor .RGBA()
case theme.ColorForeground: return textColor .RGBA()
case theme.ColorRaised: return buttonColor .RGBA()
case theme.ColorSunken: return inputColor .RGBA()
case theme.ColorAccent: return hex(0x5f8bc4FF) .RGBA()
default: return color.Transparent.RGBA()
}
}
func (this *Theme) Apply (object tomo.Object, role theme.Role) event.Cookie {
box := object.GetBox()
box.SetColor(backgroundColor)
if textBox, ok := box.(tomo.TextBox); ok {
textBox.SetDotColor(dotColor)
textBox.SetTextColor(textColor)
textBox.SetFace(basicfont.Face7x13)
}
if containerBox, ok := box.(tomo.ContainerBox); ok {
containerBox.SetGap(image.Pt(8, 8))
}
switch role.Object {
case "Button":
pressed := false
hovered := false
updateStyle := func () {
border := []tomo.Border {
engravedBorder,
gapBorder,
buttonBorder,
}
padding := tomo.I(4, 8)
box.SetColor(buttonColor)
if box.Focused() {
box.SetColor(buttonColorFocused)
border[1] = focusedBorder
}
if pressed {
box.SetColor(buttonColorPressed)
padding = tomo.I(5, 8, 4, 9)
border[2] = sunkenShadow
} else if hovered {
box.SetColor(buttonColorHovered)
}
box.SetBorder(border...)
box.SetPadding(padding)
}
updateStyle()
return event.MultiCookie (
box.OnMouseDown(func (button input.Button) {
if button != input.ButtonLeft { return }
pressed = true
updateStyle()
}),
box.OnMouseUp(func (button input.Button) {
if button != input.ButtonLeft { return }
pressed = false
updateStyle()
}),
box.OnFocusEnter(updateStyle),
box.OnFocusLeave(updateStyle),
box.OnMouseEnter(func () {
hovered = true
updateStyle()
}),
box.OnMouseLeave(func () {
hovered = false
updateStyle()
}))
case "TextInput", "NumberInput":
box.SetPadding(tomo.I(5, 4, 4, 5))
updateStyle := func () {
border := []tomo.Border {
engravedBorder,
gapBorder,
sunkenShadow,
}
box.SetColor(inputColor)
if box.Focused() {
border[1] = focusedBorder
}
box.SetBorder(border...)
}
updateStyle()
return event.MultiCookie (
box.OnFocusEnter(updateStyle),
box.OnFocusLeave(updateStyle))
case "Container":
if role.Variant == "outer" {
box.SetPadding(tomo.I(8))
}
case "Heading":
if textBox, ok := box.(tomo.TextBox); ok {
textBox.SetAlign(tomo.AlignMiddle, tomo.AlignMiddle)
}
case "Separator":
box.SetBorder(engravedBorder)
case "Slider":
pressed := false
hovered := false
if role.Variant == "vertical" {
box.SetMinimumSize(image.Pt(0, 48))
} else {
box.SetMinimumSize(image.Pt(48, 0))
}
updateStyle := func () {
border := []tomo.Border {
engravedBorder,
gapBorder,
sunkenShadow,
}
box.SetColor(gutterColor)
if box.Focused() {
border[1] = focusedBorder
}
if hovered && !pressed {
box.SetColor(gutterColorHovered)
}
box.SetBorder(border...)
}
updateStyle()
return event.MultiCookie (
box.OnFocusEnter(updateStyle),
box.OnFocusLeave(updateStyle),
box.OnMouseDown(func (button input.Button) {
pressed = true
updateStyle()
}),
box.OnMouseUp(func (button input.Button) {
pressed = false
updateStyle()
}),
box.OnMouseEnter(func () {
hovered = true
updateStyle()
}),
box.OnMouseLeave(func () {
hovered = false
updateStyle()
}))
case "SliderHandle":
box.SetMinimumSize(image.Pt(12, 12))
border := []tomo.Border {
outerShadow,
gapBorder,
buttonBorder,
}
box.SetBorder(border...)
box.SetColor(buttonColor)
}
return event.MultiCookie()
}
func (this *Theme) Icon (theme.Icon, theme.IconSize) tomo.Texture {
this.ensure()
// TODO
return nil
}
func (this *Theme) MimeIcon (data.Mime, theme.IconSize) tomo.Texture {
this.ensure()
// TODO
return nil
}
func (this *Theme) ApplicationIcon (theme.ApplicationIcon, theme.IconSize) tomo.Texture {
this.ensure()
// TODO
return nil
}
func (this *Theme) ensure () {
// TODO
}