tomo/theme/theme.go

110 lines
3.3 KiB
Go
Raw Normal View History

2023-08-08 01:49:11 +00:00
package theme
import "fmt"
2023-08-08 01:49:11 +00:00
import "git.tebibyte.media/tomo/tomo"
2023-08-12 04:56:13 +00:00
import "git.tebibyte.media/tomo/tomo/data"
2023-08-08 01:57:50 +00:00
import "git.tebibyte.media/tomo/tomo/event"
2023-08-24 20:30:10 +00:00
import "git.tebibyte.media/tomo/tomo/canvas"
2023-08-08 01:49:11 +00:00
// Role describes the role of an object.
type Role struct {
// Package is an optional namespace field. If specified, it should be
// the package name or module name the object is from.
Package string
2023-08-24 20:30:10 +00:00
2023-08-08 01:49:11 +00:00
// Object specifies what type of object it is. For example:
2023-08-08 01:51:05 +00:00
// - TextInput
// - Table
// - Label
// - Dial
// This should correspond directly to the type name of the object.
2023-08-08 01:49:11 +00:00
Object string
2023-08-24 20:30:10 +00:00
2023-08-10 21:49:22 +00:00
// Variant is an optional field to be used when an object has one or
// more soft variants under one type. For example, an object "Slider"
// may have variations "horizontal" and "vertical".
Variant string
2023-08-08 01:49:11 +00:00
}
// String satisfies the fmt.Stringer interface.
// It follows the format of:
// Package.Object[Variant]
func (r Role) String () string {
return fmt.Sprintf("%s.%s[%s]", r.Package, r.Object, r.Variant)
}
2023-08-08 07:00:41 +00:00
// R is shorthand for creating a Role structure.
2023-08-10 21:49:22 +00:00
func R (pack, object, variant string) Role {
return Role { Package: pack, Object: object, Variant: variant }
2023-08-24 20:30:10 +00:00
}
2023-08-08 07:00:41 +00:00
2023-08-09 16:08:17 +00:00
// Color represents a color ID.
2023-08-09 19:13:19 +00:00
type Color int; const (
2023-08-09 16:08:17 +00:00
ColorBackground Color = iota
ColorForeground
ColorRaised
ColorSunken
ColorAccent
2023-08-09 19:13:19 +00:00
)
// String satisfies the fmt.Stringer interface.
func (c Color) String () string {
switch c {
case ColorBackground: return "background"
case ColorForeground: return "foreground"
case ColorRaised: return "raised"
case ColorSunken: return "sunken"
case ColorAccent: return "accent"
default: return "unknown"
}
}
2023-08-09 19:13:19 +00:00
// RGBA satisfies the color.Color interface.
func (id Color) RGBA () (r, g, b, a uint32) {
if current == nil { return }
return current.RGBA(id)
2023-08-09 16:08:17 +00:00
}
2023-08-08 01:49:11 +00:00
// Theme is an object that can apply a visual style to different objects.
type Theme interface {
// A word on textures:
//
// Because textures can be linked to some resource that is outside of
// the control of Go's garbage collector, methods of Theme must not
// allocate new copies of a texture each time they are called. It is
// fine to lazily load textures and save them for later use, but the
// same texture must never be allocated multiple times as this could
// cause a memory leak.
//
// As such, textures returned by these methods must be protected.
2023-08-08 01:49:11 +00:00
// Apply applies the theme to the given object, according to the given
// role. This may register event listeners with the given object;
// closing the returned cookie must remove them.
2023-08-08 01:49:11 +00:00
Apply (tomo.Object, Role) event.Cookie
2023-08-24 20:30:10 +00:00
2023-08-09 19:13:19 +00:00
// RGBA returns the RGBA values of the corresponding color ID.
RGBA (Color) (r, g, b, a uint32)
2023-08-24 20:30:10 +00:00
// Icon returns a texture of the corresponding icon ID.
2023-08-24 20:30:10 +00:00
Icon (Icon, IconSize) canvas.Texture
// MimeIcon returns an icon corresponding to a MIME type.
2023-08-24 20:30:10 +00:00
MimeIcon (data.Mime, IconSize) canvas.Texture
2023-08-08 01:49:11 +00:00
}
var current Theme
// SetTheme sets the theme.
func SetTheme (theme Theme) {
current = theme
}
// Apply applies the current theme to the given object, according to the given
// role. This may register event listeners with the given object; closing the
// returned cookie will remove them.
func Apply (object tomo.Object, role Role) event.Cookie {
2023-08-09 16:08:17 +00:00
if current == nil { return event.NoCookie { } }
2023-08-08 01:49:11 +00:00
return current.Apply(object, role)
}