package timer import ( "image" "sync" "time" "gioui.org/app" "gioui.org/io/event" "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" "gioui.org/text" "gioui.org/widget/material" "git.mstar.dev/mstar/timer/shared" "github.com/rs/zerolog/log" ) type StateCountdown struct { initialSetupDone bool TargetTime time.Time ops op.Ops } func (s *StateCountdown) Run(globalState *shared.GlobalState, event event.Event) shared.NewState { if !s.initialSetupDone { s.initialSetup(globalState) } switch event := event.(type) { case app.FrameEvent: return s.handleFrameEvent(globalState, &event) case app.DestroyEvent: return s.handleQuitEvent() case app.WaylandViewEvent, app.X11ViewEvent: return shared.EmptyEvent() default: log.Debug().Any("event", event).Type("type", event).Msg("Unknown event") return shared.NewState{} } } func (s *StateCountdown) Exit(globalState *shared.GlobalState, wg *sync.WaitGroup) { wg.Done() } func (s *StateCountdown) initialSetup(globalState *shared.GlobalState) { s.initialSetupDone = true go func(window *app.Window) { t := time.NewTicker(time.Second) for range t.C { window.Invalidate() } }(globalState.Window) } func (s *StateCountdown) handleQuitEvent() shared.NewState { return shared.NewState{ExitCode: shared.ErrExitOk} } func (s *StateCountdown) handleFrameEvent( globalState *shared.GlobalState, frameEvent *app.FrameEvent, ) shared.NewState { gtx := app.NewContext(&s.ops, *frameEvent) paint.FillShape( gtx.Ops, globalState.Theme.Bg, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op(), ) diff := frameEvent.Now.Sub(s.TargetTime) diff *= -1 title := material.H1( globalState.Theme, diff.Round(time.Second).String(), ) // // // // // Change the color of the label. title.Color = shared.TextColor // // // // // Change the position of the label. title.Alignment = text.Middle // // // Draw the label to the graphics context. title.Layout(gtx) // // Pass the drawing operations to the GPU. frameEvent.Frame(&s.ops) return shared.NewState{} }