~eliasnaur/gio

2 2

gio/cmd/gogio: boilerplate generator

Details
Message ID
<9955DB28-F277-4004-B4A2-5CF948C15E97@getmailspring.com>
DKIM signature
pass
Download raw message
Hi Elias, 

I've found myself tediously writing-out or copy-pasting Gio startup code
when creating experimental / throwaway apps. 

I wonder if it would be useful to include a boilerplate generator in the
`gogio` or simliar tool. This could be useful for people new to Gio and
who are unfamiliar with setting up the event loop, and for people who
are creating lots of small experiments. 

For example:

`gogio init git.sr.ht/~jackmordaunt/demo`

Would create a go module named "git.sr.ht/~jackmordaunt/demo", with a
sample app generated in `main.go`.

The sample app could look like: 

```go 
package main

import (
	"log"
	"os"

	"gioui.org/app"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/unit"
)

type (
	C = layout.Context
	D = layout.Dimensions
)

func main() {
	ui := UI{
		app.NewWindow(app.Title("demo"), app.Size(unit.Dp(800), unit.Dp(600))),
	}
	go func() {
		if err := ui.Loop(); err != nil {
			log.Printf("error: %v", err)
		}
		os.Exit(0)
	}()
	app.Main()
}

// UI contains all ui state.
type UI struct {
	*app.Window
}

// Loop starts the event loop.
func (ui *UI) Loop() error {
	var ops op.Ops
	for event := range ui.Window.Events() {
		switch event := event.(type) {
		case system.DestroyEvent:
			return event.Err
		case system.FrameEvent:
			gtx := layout.NewContext(&ops, event)
			ui.Update(gtx)
			ui.Layout(gtx)
			event.Frame(gtx.Ops)
		}
	}
	return nil
}

// Update performs event processing and state updates.
func (ui *UI) Update(gtx C) {}

// Layout renders the gui into the context.
func (ui *UI) Layout(gtx C) D {
	return D{}
}
```

To get started you can simply start writing your layout code and you're
good to go. 

Do you think such a command deserves to be in core gio? 

Thanks!
Details
Message ID
<CC8E82V6KEU8.1XRFOPC3CAGWN@testmac>
In-Reply-To
<9955DB28-F277-4004-B4A2-5CF948C15E97@getmailspring.com> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
On Sat Jun 19, 2021 at 23:37 CEST, Jack Mordaunt wrote:
> Hi Elias, 
>
> I've found myself tediously writing-out or copy-pasting Gio startup code
> when creating experimental / throwaway apps. 
>
> I wonder if it would be useful to include a boilerplate generator in the
> `gogio` or simliar tool. This could be useful for people new to Gio and
> who are unfamiliar with setting up the event loop, and for people who
> are creating lots of small experiments. 
>
> For example:
>
> `gogio init git.sr.ht/~jackmordaunt/demo`
>
> Would create a go module named "git.sr.ht/~jackmordaunt/demo", with a
> sample app generated in `main.go`.
>
> The sample app could look like: 
>
> ```go 
> package main
>
> import (
> 	"log"
> 	"os"
>
> 	"gioui.org/app"
> 	"gioui.org/io/system"
> 	"gioui.org/layout"
> 	"gioui.org/op"
> 	"gioui.org/unit"
> )
>
> type (
> 	C = layout.Context
> 	D = layout.Dimensions
> )
>
> func main() {
> 	ui := UI{
> 		app.NewWindow(app.Title("demo"), app.Size(unit.Dp(800), unit.Dp(600))),
> 	}
> 	go func() {
> 		if err := ui.Loop(); err != nil {
> 			log.Printf("error: %v", err)
> 		}
> 		os.Exit(0)
> 	}()
> 	app.Main()
> }
>
> // UI contains all ui state.
> type UI struct {
> 	*app.Window
> }
>
> // Loop starts the event loop.
> func (ui *UI) Loop() error {
> 	var ops op.Ops
> 	for event := range ui.Window.Events() {
> 		switch event := event.(type) {
> 		case system.DestroyEvent:
> 			return event.Err
> 		case system.FrameEvent:
> 			gtx := layout.NewContext(&ops, event)
> 			ui.Update(gtx)
> 			ui.Layout(gtx)
> 			event.Frame(gtx.Ops)
> 		}
> 	}
> 	return nil
> }
>
> // Update performs event processing and state updates.
> func (ui *UI) Update(gtx C) {}
>
> // Layout renders the gui into the context.
> func (ui *UI) Layout(gtx C) D {
> 	return D{}
> }
> ```
>
> To get started you can simply start writing your layout code and you're
> good to go. 
>
> Do you think such a command deserves to be in core gio? 
>

Sure! I'd simplify a bit and replace `UI` and its methods with just a
`layoutUI` method, and the module name argument to `gogio init` with a
default name.

Elias
Details
Message ID
<CANtNKfoBE--s57JQtwHuCv_5NbLw0=YXG7FBu+0sznjc5hM9fA@mail.gmail.com>
In-Reply-To
<CC8E82V6KEU8.1XRFOPC3CAGWN@testmac> (view parent)
DKIM signature
pass
Download raw message
Wouldn't it be more convenient to minimize the boilerplate, when possible?

For example:

```
func main() {
        var ui UI
        qapp.Layout(
                ui.Layout,
                app.Title("demo"),
                app.Size(unit.Dp(800), unit.Dp(600)),
        )
}

type UI struct {}

func (ui *UI) Layout(gtx layout.Context, th *material.Theme) layout.Dimensions {
        return material.H1(th, "hello").Layout(gtx)
}
```

This could eventually set up themes based on different system
preferences, switch based on dark mode etc.

+ Egon


On Sun, Jun 20, 2021 at 2:02 PM Elias Naur <mail@eliasnaur.com> wrote:
>
> On Sat Jun 19, 2021 at 23:37 CEST, Jack Mordaunt wrote:
> > Hi Elias,
> >
> > I've found myself tediously writing-out or copy-pasting Gio startup code
> > when creating experimental / throwaway apps.
> >
> > I wonder if it would be useful to include a boilerplate generator in the
> > `gogio` or simliar tool. This could be useful for people new to Gio and
> > who are unfamiliar with setting up the event loop, and for people who
> > are creating lots of small experiments.
> >
> > For example:
> >
> > `gogio init git.sr.ht/~jackmordaunt/demo`
> >
> > Would create a go module named "git.sr.ht/~jackmordaunt/demo", with a
> > sample app generated in `main.go`.
> >
> > The sample app could look like:
> >
> > ```go
> > package main
> >
> > import (
> >       "log"
> >       "os"
> >
> >       "gioui.org/app"
> >       "gioui.org/io/system"
> >       "gioui.org/layout"
> >       "gioui.org/op"
> >       "gioui.org/unit"
> > )
> >
> > type (
> >       C = layout.Context
> >       D = layout.Dimensions
> > )
> >
> > func main() {
> >       ui := UI{
> >               app.NewWindow(app.Title("demo"), app.Size(unit.Dp(800), unit.Dp(600))),
> >       }
> >       go func() {
> >               if err := ui.Loop(); err != nil {
> >                       log.Printf("error: %v", err)
> >               }
> >               os.Exit(0)
> >       }()
> >       app.Main()
> > }
> >
> > // UI contains all ui state.
> > type UI struct {
> >       *app.Window
> > }
> >
> > // Loop starts the event loop.
> > func (ui *UI) Loop() error {
> >       var ops op.Ops
> >       for event := range ui.Window.Events() {
> >               switch event := event.(type) {
> >               case system.DestroyEvent:
> >                       return event.Err
> >               case system.FrameEvent:
> >                       gtx := layout.NewContext(&ops, event)
> >                       ui.Update(gtx)
> >                       ui.Layout(gtx)
> >                       event.Frame(gtx.Ops)
> >               }
> >       }
> >       return nil
> > }
> >
> > // Update performs event processing and state updates.
> > func (ui *UI) Update(gtx C) {}
> >
> > // Layout renders the gui into the context.
> > func (ui *UI) Layout(gtx C) D {
> >       return D{}
> > }
> > ```
> >
> > To get started you can simply start writing your layout code and you're
> > good to go.
> >
> > Do you think such a command deserves to be in core gio?
> >
>
> Sure! I'd simplify a bit and replace `UI` and its methods with just a
> `layoutUI` method, and the module name argument to `gogio init` with a
> default name.
>
> Elias
Reply to thread Export thread (mbox)