2023-01-12 17:52:21 -07:00
|
|
|
package fun
|
|
|
|
|
|
|
|
import "time"
|
|
|
|
import "math"
|
|
|
|
import "image"
|
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
|
|
|
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-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 { }
|
|
|
|
element.Core, element.core = core.NewCore(element)
|
|
|
|
element.core.SetMinimumSize(64, 64)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-01-17 15:13:01 -07:00
|
|
|
// Resize changes the size of the clock.
|
2023-01-15 22:31:57 -07:00
|
|
|
func (element *AnalogClock) Resize (width, height int) {
|
|
|
|
element.core.AllocateCanvas(width, height)
|
|
|
|
element.draw()
|
2023-01-12 17:52:21 -07:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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.core.Bounds()
|
|
|
|
|
2023-01-14 19:01:00 -07:00
|
|
|
artist.FillRectangle (
|
2023-01-12 17:52:21 -07:00
|
|
|
element.core,
|
2023-01-14 19:01:00 -07:00
|
|
|
theme.SunkenPattern(),
|
2023-01-12 17:52:21 -07:00
|
|
|
bounds)
|
|
|
|
|
|
|
|
for hour := 0; hour < 12; hour ++ {
|
|
|
|
element.radialLine (
|
2023-01-14 19:01:00 -07:00
|
|
|
theme.ForegroundPattern(true),
|
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-01-12 17:52:21 -07:00
|
|
|
element.radialLine (
|
2023-01-14 19:01:00 -07:00
|
|
|
theme.ForegroundPattern(true),
|
2023-01-13 11:55:20 -07:00
|
|
|
0, 0.5, (hour - 3) / 6 * math.Pi)
|
2023-01-12 17:52:21 -07:00
|
|
|
element.radialLine (
|
2023-01-14 19:01:00 -07:00
|
|
|
theme.ForegroundPattern(true),
|
2023-01-13 11:55:20 -07:00
|
|
|
0, 0.7, (minute - 15) / 30 * math.Pi)
|
2023-01-12 17:52:21 -07:00
|
|
|
element.radialLine (
|
2023-01-14 19:01:00 -07:00
|
|
|
theme.AccentPattern(),
|
2023-01-13 11:55:20 -07:00
|
|
|
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-01-19 22:42:57 -07:00
|
|
|
// OnFlexibleHeightChange sets a function to be calle dwhen the parameters
|
|
|
|
// affecting the clock's flexible height change.
|
|
|
|
func (element *AnalogClock) OnFlexibleHeightChange (func ()) { }
|
|
|
|
|
2023-01-12 17:52:21 -07:00
|
|
|
func (element *AnalogClock) radialLine (
|
2023-01-13 23:54:57 -07:00
|
|
|
source artist.Pattern,
|
2023-01-12 17:52:21 -07:00
|
|
|
inner float64,
|
|
|
|
outer float64,
|
|
|
|
radian float64,
|
|
|
|
) {
|
|
|
|
bounds := element.core.Bounds()
|
|
|
|
width := float64(bounds.Dx()) / 2
|
|
|
|
height := float64(bounds.Dy()) / 2
|
|
|
|
min := image.Pt (
|
|
|
|
int(math.Cos(radian) * inner * width + width),
|
|
|
|
int(math.Sin(radian) * inner * height + height))
|
|
|
|
max := image.Pt (
|
|
|
|
int(math.Cos(radian) * outer * width + width),
|
|
|
|
int(math.Sin(radian) * outer * height + height))
|
|
|
|
// println(min.String(), max.String())
|
|
|
|
artist.Line(element.core, source, 1, min, max)
|
|
|
|
}
|