Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maybe change Event to be an interface instead of struct? #4

Closed
peterhellberg opened this issue May 7, 2019 · 15 comments
Closed

Maybe change Event to be an interface instead of struct? #4

peterhellberg opened this issue May 7, 2019 · 15 comments

Comments

@peterhellberg
Copy link

peterhellberg commented May 7, 2019

I'm thinking something along these lines:

type Event interface {
	Name() string
	Args() interface{}
}

This would look like this when in use:

package main

import (
	"image"
	"image/draw"

	"github.com/peterhellberg/gfx"
	"github.com/peterhellberg/gui"
)

func main() {
	gui.Run(loop)
}

func loop() {
	win, err := gui.New(gui.Title("gui-xor"), gui.Size(512, 512))
	if err != nil {
		return
	}

	win.Draw() <- func(dst draw.Image) image.Rectangle {
		r := dst.Bounds()

		gfx.EachPixel(r, func(x, y int) {
			c := uint8(x ^ y)

			dst.Set(x, y, gfx.ColorNRGBA(c, c%192, c, 255))
		})

		return r
	}

	for event := range win.Events() {
		switch event.Name() {
		case gui.EventClose, gui.EventKeyboardUp:
			close(win.Draw())
		default:
			gfx.Log("Event: %+v", event)
		}
	}
}

gui-xor

I will experiment a bit more, but so far I've reduced the code in this project to a single file (in order to help with the experimentation)

@faiface
Copy link
Owner

faiface commented May 7, 2019

Thanks a lot for thinking about this!

There is one more benefit to the original string events that you don't cover here and that's this:

switch {
case event.Matches("kb/down/left"):
    // ...
case event.Matches("kb/down/right"):
    // ...
}

Matching directly on the values of the event, like specific keys. We don't necessarily need to address it, but it would be nice.

@peterhellberg
Copy link
Author

peterhellberg commented May 7, 2019

Handling the args can be done in a second switch; for example if you want to do something when the letter q is typed on the keyboard:

switch event.Name() {
case gui.EventKeyboardChar:
	switch event.Args().(rune) {
	case 'q':
		win.Close()
	}
}

And in a case for gui.EventKeyboardDown you could have a switch like:

switch event.Args().(string) {
case "up":
	gfx.Log("↑")
case "down":
	gfx.Log("↓")
case "left":
	gfx.Log("←")
case "right":
	gfx.Log("→")
}

@faiface
Copy link
Owner

faiface commented May 7, 2019

Yeah, I know, but that requires another switch, you know. It's quite nicer to have to all in a single switch.

@faiface
Copy link
Owner

faiface commented May 7, 2019

Btw, what do you think about something as straightforward as this?

type Event interface{}

type EventResize struct {
    Bounds image.Rectangle
}

type EventKbDown struct {
    Key string
}

type EventMoMove struct {
    Point image.Point
}

// more event types

@faiface
Copy link
Owner

faiface commented May 7, 2019

And perhaps adding a String() method to the Event interface, so that events are nicely printable for debugging.

@peterhellberg
Copy link
Author

Then you would be back to using a concrete type for each event instead of an interface that could be implemented by someone else.

@faiface
Copy link
Owner

faiface commented May 7, 2019

Yeah, but an event is just data, right? I'm not sure a single type of event needs multiple implementations. And adding more types of events would be easy, just add a new event type.

@faiface
Copy link
Owner

faiface commented May 7, 2019

Perhaps I'm missing some of your points :D

@peterhellberg
Copy link
Author

peterhellberg commented May 7, 2019

I'll continue experimenting to see what I come up with :)

Thank you for creating this project, it is very close to exactly what I've wanted when displaying my github.com/peterhellberg/gfx experiments.

@faiface
Copy link
Owner

faiface commented May 7, 2019

Thanks! I appreciate that a lot. I also appreciate your feedback and suggestions.

@faiface
Copy link
Owner

faiface commented May 8, 2019

Have you figured something out? I think I'll try the structs, see how it goes.

@peterhellberg
Copy link
Author

Not much, other than deciding to rename the Args field to Data :)

// Event includes its name and data.
type Event interface {
	Name() string
	Data() interface{}
}

I've started to think a bit about how/if it would make sense to being able to trigger custom events (on a timer, when receiving data over the network, etc.) Will probably not have that much time tonight though.

@faiface
Copy link
Owner

faiface commented May 8, 2019

With concurrent GUI, you can solve that kind of thing simply with channels :). You make a long running thing send a value over a channel and you select on that channel alonside selecting on the events channel.

@faiface
Copy link
Owner

faiface commented May 9, 2019

I decided to give concrete event types a try.

@peterhellberg
Copy link
Author

Ok :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants