This commit is contained in:
Melody Becker 2025-02-03 08:22:01 +01:00
commit 185c84742a
No known key found for this signature in database
7 changed files with 254 additions and 0 deletions

7
constants.go Normal file
View file

@ -0,0 +1,7 @@
package main
import "image/color"
var (
ColorRed = color.NRGBA{R: 0xff, G: 0x0, B: 0x0, A: 255}
)

18
go.mod Normal file
View file

@ -0,0 +1,18 @@
module git.mstar.dev/mstar/timer
go 1.23.5
require (
gioui.org v0.8.0 // indirect
gioui.org/shader v1.0.8 // indirect
git.mstar.dev/mstar/goutils v1.6.1 // indirect
github.com/go-text/typesetting v0.2.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/rs/zerolog v1.33.0 // indirect
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect
golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
)

33
go.sum Normal file
View file

@ -0,0 +1,33 @@
gioui.org v0.8.0 h1:QV5p5JvsmSmGiIXVYOKn6d9YDliTfjtLlVf5J+BZ9Pg=
gioui.org v0.8.0/go.mod h1:vEMmpxMOd/iwJhXvGVIzWEbxMWhnMQ9aByOGQdlQ8rc=
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
gioui.org/shader v1.0.8 h1:6ks0o/A+b0ne7RzEqRZK5f4Gboz2CfG+mVliciy6+qA=
gioui.org/shader v1.0.8/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
git.mstar.dev/mstar/goutils v1.6.1 h1:2yr9GYN8CJByZsJRu1pZ6WBp51Nn+3zJq49ky54xYDk=
git.mstar.dev/mstar/goutils v1.6.1/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w=
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37 h1:SOSg7+sueresE4IbmmGM60GmlIys+zNX63d6/J4CMtU=
golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=

33
main.go Normal file
View file

@ -0,0 +1,33 @@
package main
import (
"os"
"time"
"gioui.org/app"
"github.com/rs/zerolog/log"
)
var t time.Time
func main() {
window := new(app.Window)
var err error
t, err = time.Parse(time.RFC3339, "2025-01-31T22:50:00Z")
if err != nil {
log.Fatal().Err(err).Send()
}
go func() {
// window.Option(func(m unit.Metric, c *app.Config) {
// c.Size = image.Pt(500, 150)
// c.MaxSize = image.Pt(500, 150)
// c.MinSize = image.Pt(500, 150)
// })
err := run(window, &StateEnterTime{})
if err != nil {
log.Fatal().Err(err).Msg("Failed to run main window")
}
os.Exit(0)
}()
app.Main()
}

62
window.go Normal file
View file

@ -0,0 +1,62 @@
package main
import (
"image/color"
"os"
"time"
"gioui.org/app"
"gioui.org/widget/material"
)
type GlobalState struct {
Window *app.Window
Theme *material.Theme
state WindowState
}
func ticker(window *app.Window) {
t := time.NewTicker(time.Second)
for range t.C {
window.Invalidate()
}
}
func run(window *app.Window, initialState WindowState) error {
state := GlobalState{}
theme := material.NewTheme()
theme.Bg = color.NRGBA{A: 0xff}
state.Theme = theme
state.Window = window
state.state = initialState
for {
e := window.Event()
newState := state.state.Run(&state, e)
if newState.NextState != nil {
state.state = newState.NextState
}
if newState.ExitCode != nil {
os.Exit(*newState.ExitCode)
}
// log.Debug().Any("size", e.Size).Msg("Redrawing")
// // This graphics context is used for managing the rendering state.
// gtx := app.NewContext(&ops, e)
// paint.FillShape(gtx.Ops, theme.Bg, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op())
// //
// // // Define an large label with an appropriate text:
// log.Debug().Dur("d", t.Sub(e.Now)).Time("t", t).Send()
// title := material.H1(theme, e.Now.Sub(t).Round(time.Second).String())
// //
// // // Change the color of the label.
// maroon := color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 255}
// title.Color = maroon
// //
// // // 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.
// e.Frame(&ops)
}
}

81
windowEnterTime.go Normal file
View file

@ -0,0 +1,81 @@
package main
import (
"gioui.org/app"
"gioui.org/io/event"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/widget"
"gioui.org/widget/material"
"git.mstar.dev/mstar/goutils/other"
"github.com/rs/zerolog/log"
)
type StateEnterTime struct {
initialSetupDone bool
editor *widget.Editor
inputField *material.EditorStyle
ops op.Ops
}
func (s *StateEnterTime) initialSetup(globalState *GlobalState) {
s.editor = &widget.Editor{
SingleLine: true,
Submit: true,
Filter: "01234567890TZ+-:",
}
field := material.Editor(globalState.Theme, s.editor, "timestamp")
s.inputField = &field
s.initialSetupDone = true
}
func (s *StateEnterTime) Run(globalState *GlobalState, event event.Event) 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 EmptyEvent()
default:
log.Debug().Any("event", event).Type("type", event).Msg("Unknown event")
return NewState{}
}
}
func (s *StateEnterTime) handleFrameEvent(
globalState *GlobalState,
frameEvent *app.FrameEvent,
) NewState {
gtx := app.NewContext(&s.ops, *frameEvent)
for ev, ok := s.editor.Update(gtx); ok; ev, ok = s.editor.Update(gtx) {
log.Debug().Any("Editor event", ev).Send()
}
label := material.H3(globalState.Theme, "Enter timestamp")
hint := material.Subtitle1(
globalState.Theme,
"Format: <YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>(Z|+<TZ>)",
)
list := layout.List{Axis: layout.Vertical}
list.Layout(gtx, 3, func(gtx layout.Context, index int) layout.Dimensions {
switch index {
case 0:
return label.Layout(gtx)
case 1:
return hint.Layout(gtx)
case 2:
return s.inputField.Layout(gtx)
default:
return hint.Layout(gtx)
}
})
frameEvent.Frame(&s.ops)
return NewState{}
}
func (s *StateEnterTime) handleQuitEvent() NewState {
return NewState{ExitCode: other.IntoPointer(0)}
}

20
windowState.go Normal file
View file

@ -0,0 +1,20 @@
package main
import (
"gioui.org/io/event"
)
type WindowState interface {
Run(globalState *GlobalState, event event.Event) NewState
}
type NewState struct {
// If null, keep current state
NextState WindowState
Error error
ExitCode *int
}
func EmptyEvent() NewState {
return NewState{}
}