This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
tomo-old/elements/fun/clock.go

112 lines
3.2 KiB
Go
Raw Normal View History

2023-01-12 17:52:21 -07:00
package fun
import "time"
import "math"
import "image"
import "git.tebibyte.media/sashakoshka/tomo/theme"
2023-02-08 13:12:18 -07:00
import "git.tebibyte.media/sashakoshka/tomo/config"
2023-01-12 17:52:21 -07:00
import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
2023-01-17 15:13:01 -07:00
// AnalogClock can display the time of day in an analog format.
2023-01-12 17:52:21 -07:00
type AnalogClock struct {
*core.Core
core core.CoreControl
time time.Time
2023-02-08 13:12:18 -07:00
config config.Wrapped
theme theme.Wrapped
2023-01-12 17:52:21 -07:00
}
2023-01-17 15:13:01 -07:00
// NewAnalogClock creates a new analog clock that displays the specified time.
2023-01-12 17:52:21 -07:00
func NewAnalogClock (newTime time.Time) (element *AnalogClock) {
element = &AnalogClock { }
2023-02-08 13:12:18 -07:00
element.theme.Case = theme.C("fun", "clock")
element.Core, element.core = core.NewCore(element.draw)
2023-01-12 17:52:21 -07:00
element.core.SetMinimumSize(64, 64)
return
}
2023-01-17 15:13:01 -07:00
// SetTime changes the time that the clock displays.
2023-01-12 17:52:21 -07:00
func (element *AnalogClock) SetTime (newTime time.Time) {
if newTime == element.time { return }
element.time = newTime
2023-02-08 13:12:18 -07:00
element.redo()
}
// SetTheme sets the element's theme.
func (element *AnalogClock) SetTheme (new theme.Theme) {
if new == element.theme.Theme { return }
element.theme.Theme = new
element.redo()
}
// SetConfig sets the element's configuration.
func (element *AnalogClock) SetConfig (new config.Config) {
if new == element.config.Config { return }
element.config.Config = new
element.redo()
}
func (element *AnalogClock) redo () {
2023-01-12 17:52:21 -07:00
if element.core.HasImage() {
element.draw()
2023-01-19 22:42:57 -07:00
element.core.DamageAll()
2023-01-12 17:52:21 -07:00
}
}
func (element *AnalogClock) draw () {
bounds := element.Bounds()
2023-01-12 17:52:21 -07:00
2023-02-08 13:12:18 -07:00
state := theme.PatternState { }
pattern := element.theme.Pattern(theme.PatternSunken, state)
inset := element.theme.Inset(theme.PatternSunken)
2023-02-14 00:14:52 -07:00
artist.FillRectangle(element.core, pattern, bounds)
bounds = inset.Apply(bounds)
2023-02-08 13:12:18 -07:00
foreground := element.theme.Pattern(theme.PatternForeground, state)
accent := element.theme.Pattern(theme.PatternAccent, state)
2023-01-12 17:52:21 -07:00
for hour := 0; hour < 12; hour ++ {
element.radialLine (
foreground,
2023-01-12 17:52:21 -07:00
0.8, 0.9, float64(hour) / 6 * math.Pi)
}
2023-01-13 11:55:20 -07:00
second := float64(element.time.Second())
minute := float64(element.time.Minute()) + second / 60
hour := float64(element.time.Hour()) + minute / 60
element.radialLine(foreground, 0, 0.5, (hour - 3) / 6 * math.Pi)
element.radialLine(foreground, 0, 0.7, (minute - 15) / 30 * math.Pi)
element.radialLine(accent, 0, 0.7, (second - 15) / 30 * math.Pi)
2023-01-12 17:52:21 -07:00
}
2023-01-19 22:42:57 -07:00
// FlexibleHeightFor constrains the clock's minimum size to a 1:1 aspect ratio.
func (element *AnalogClock) FlexibleHeightFor (width int) (height int) {
2023-01-17 12:47:07 -07:00
return width
}
2023-02-08 13:12:18 -07:00
// OnFlexibleHeightChange sets a function to be called when the parameters
2023-01-19 22:42:57 -07:00
// affecting the clock's flexible height change.
func (element *AnalogClock) OnFlexibleHeightChange (func ()) { }
2023-01-12 17:52:21 -07:00
func (element *AnalogClock) radialLine (
source artist.Pattern,
2023-01-12 17:52:21 -07:00
inner float64,
outer float64,
radian float64,
) {
bounds := element.Bounds()
2023-01-12 17:52:21 -07:00
width := float64(bounds.Dx()) / 2
height := float64(bounds.Dy()) / 2
2023-01-31 16:39:17 -07:00
min := element.Bounds().Min.Add(image.Pt (
2023-01-12 17:52:21 -07:00
int(math.Cos(radian) * inner * width + width),
2023-01-31 16:39:17 -07:00
int(math.Sin(radian) * inner * height + height)))
max := element.Bounds().Min.Add(image.Pt (
2023-01-12 17:52:21 -07:00
int(math.Cos(radian) * outer * width + width),
2023-01-31 16:39:17 -07:00
int(math.Sin(radian) * outer * height + height)))
2023-02-14 00:14:52 -07:00
artist.Line(element.core, source, 1, min, max)
2023-01-12 17:52:21 -07:00
}