2023-01-12 17:52:21 -07:00
|
|
|
package fun
|
|
|
|
|
|
|
|
import "time"
|
|
|
|
import "math"
|
|
|
|
import "image"
|
2023-02-26 20:20:17 -07:00
|
|
|
import "image/color"
|
2023-03-30 23:06:29 -06:00
|
|
|
import "git.tebibyte.media/sashakoshka/tomo"
|
2023-04-15 16:24:16 -06:00
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
2023-02-26 20:20:17 -07:00
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/artist/shapes"
|
2023-03-30 23:06:29 -06:00
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
2023-01-12 17:52:21 -07:00
|
|
|
|
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 {
|
2023-04-15 16:24:16 -06:00
|
|
|
entity tomo.Entity
|
|
|
|
time time.Time
|
2023-02-08 13:12:18 -07:00
|
|
|
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-03-30 23:06:29 -06:00
|
|
|
element.theme.Case = tomo.C("tomo", "clock")
|
2023-04-15 16:24:16 -06:00
|
|
|
element.entity = tomo.NewEntity(element)
|
2023-04-15 16:30:22 -06:00
|
|
|
element.entity.SetMinimumSize(64, 64)
|
2023-01-12 17:52:21 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-04-15 16:24:16 -06:00
|
|
|
// Entity returns this element's entity.
|
|
|
|
func (element *AnalogClock) Entity () tomo.Entity {
|
|
|
|
return element.entity
|
2023-01-12 17:52:21 -07:00
|
|
|
}
|
|
|
|
|
2023-04-15 16:24:16 -06:00
|
|
|
// Draw causes the element to draw to the specified destination canvas.
|
|
|
|
func (element *AnalogClock) Draw (destination canvas.Canvas) {
|
2023-04-15 16:30:22 -06:00
|
|
|
bounds := element.entity.Bounds()
|
2023-01-12 17:52:21 -07:00
|
|
|
|
2023-03-30 23:06:29 -06:00
|
|
|
state := tomo.State { }
|
|
|
|
pattern := element.theme.Pattern(tomo.PatternSunken, state)
|
|
|
|
padding := element.theme.Padding(tomo.PatternSunken)
|
2023-04-15 16:30:22 -06:00
|
|
|
pattern.Draw(destination, bounds)
|
2023-01-28 23:49:01 -07:00
|
|
|
|
2023-02-26 20:20:17 -07:00
|
|
|
bounds = padding.Apply(bounds)
|
2023-01-28 23:49:01 -07:00
|
|
|
|
2023-03-30 23:06:29 -06:00
|
|
|
foreground := element.theme.Color(tomo.ColorForeground, state)
|
|
|
|
accent := element.theme.Color(tomo.ColorAccent, state)
|
2023-01-12 17:52:21 -07:00
|
|
|
|
|
|
|
for hour := 0; hour < 12; hour ++ {
|
|
|
|
element.radialLine (
|
2023-04-15 16:30:22 -06:00
|
|
|
destination,
|
2023-01-28 23:49:01 -07:00
|
|
|
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
|
|
|
|
|
2023-04-15 16:24:16 -06:00
|
|
|
element.radialLine(destination, foreground, 0, 0.5, (hour - 3) / 6 * math.Pi)
|
|
|
|
element.radialLine(destination, foreground, 0, 0.7, (minute - 15) / 30 * math.Pi)
|
|
|
|
element.radialLine(destination, accent, 0, 0.7, (second - 15) / 30 * math.Pi)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetTime changes the time that the clock displays.
|
|
|
|
func (element *AnalogClock) SetTime (newTime time.Time) {
|
|
|
|
if newTime == element.time { return }
|
|
|
|
element.time = newTime
|
|
|
|
element.entity.Invalidate()
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetTheme sets the element's theme.
|
|
|
|
func (element *AnalogClock) SetTheme (new tomo.Theme) {
|
|
|
|
if new == element.theme.Theme { return }
|
|
|
|
element.theme.Theme = new
|
|
|
|
element.entity.Invalidate()
|
2023-01-12 17:52:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (element *AnalogClock) radialLine (
|
2023-04-15 16:24:16 -06:00
|
|
|
destination canvas.Canvas,
|
2023-02-26 20:20:17 -07:00
|
|
|
source color.RGBA,
|
2023-01-12 17:52:21 -07:00
|
|
|
inner float64,
|
|
|
|
outer float64,
|
|
|
|
radian float64,
|
|
|
|
) {
|
2023-04-15 16:24:16 -06:00
|
|
|
bounds := element.entity.Bounds()
|
2023-01-12 17:52:21 -07:00
|
|
|
width := float64(bounds.Dx()) / 2
|
|
|
|
height := float64(bounds.Dy()) / 2
|
2023-04-15 16:24:16 -06:00
|
|
|
min := 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)))
|
2023-04-15 16:24:16 -06:00
|
|
|
max := 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-04-15 16:30:22 -06:00
|
|
|
shapes.ColorLine(destination, source, 1, min, max)
|
2023-01-12 17:52:21 -07:00
|
|
|
}
|