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

Add a "SimpleWidget" or "StaticRenderer" so I can make canvas primitives interactive #709

Closed
andydotxyz opened this issue Feb 24, 2020 · 7 comments
Assignees

Comments

@andydotxyz
Copy link
Member

Is your feature request related to a problem? Please describe:

The amount of code required to make a simple widget is high, especially if I just want to wrap an existing CanvasObject.

Is it possible to construct a solution with the existing API?

Yes, but it's a lot of code.

Describe the solution you'd like to see:

Something like the following would allow me to make a tappable image:

type tappableImage struct {
    SimpleWidget
}

func (t *tappableImage) Tapped(_ *PointEvent) {
... etc 
}

func newTappableImage(img *canvas.Image) *tappableImage {
    ret := &tappableImage{}
    ret.SimpleWidget := widget.NewSimpleWidget(img) 
    return ret
}
@gooid
Copy link

gooid commented Aug 9, 2020

suggest:

index 9d021e03..ab37f920 100644
--- a/internal/painter/gl/draw.go
+++ b/internal/painter/gl/draw.go
@@ -153,5 +153,9 @@ func (p *glPainter) drawObject(o fyne.CanvasObject, pos fyne.Position, frame fyn
                p.drawGradient(obj, p.newGlRadialGradientTexture, pos, frame)
        case fyne.Widget:
                p.drawWidget(obj, pos, frame)
+       default:
+               if obj, ok := o.(interface{ superCanvas() fyne.CanvasObject }); ok {
+                       p.drawObject(obj.superCanvas(), pos, frame)
+               }
        }
 }

cmd/fyne_demo/main.go

// Package main loads a very basic Hello World graphical application.
package main

import (
	"fmt"

	"fyne.io/fyne"
	"fyne.io/fyne/app"
	"fyne.io/fyne/driver/desktop"
	"fyne.io/fyne/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("Hello")

	hello := widget.NewLabel("Hello Fyne!")
	w.SetContent(widget.NewVBox(
		hello,
		//widget.NewButton("Hi!", func() {
		NewCustomButton("Hi!", func() {
			hello.SetText("Welcome :)")
		}),
	))

	w.ShowAndRun()
}

type CustomButton struct {
	*widget.Button
}

func (button *CustomButton) superCanvas() fyne.CanvasObject {
	return button.Button
}

// MouseIn is called when a desktop pointer enters the widget
func (button *CustomButton) MouseIn(ev *desktop.MouseEvent) {
	fmt.Println("mouse in...", ev)
	button.Button.MouseIn(ev)
}

func NewCustomButton(text string, fn func()) *CustomButton {
	return &CustomButton{
		Button: widget.NewButton(text, fn),
	}
}

@andydotxyz
Copy link
Member Author

andydotxyz commented Aug 9, 2020

The example you posted above is already supported - in your constructor function call ExtendBaseWidget() - the docs are at https://developer.fyne.io/tutorial/extending-widgets @gooid

@toaster toaster self-assigned this Dec 2, 2020
@alkanna
Copy link

alkanna commented Dec 30, 2020

Hey @andydotxyz, I'm still looking for a solution to this. I'd simply like to create a custom image widget that I can regularly update. For the record, it would be a map tile that I would update based on the desired coordinates.
I tried to reimplement this by looking at how most internal widgets are currently implemented, by I hit a wall when trying to reimplement a renderer for my widget. It just feels like an insane amount of code just to get this working. I thought by extending BaseWidget I could get this in working order with minimal code addiitions, but it seems it's not possible yet, or I just can't see the obvious.

Anyone can help ?

@andydotxyz
Copy link
Member Author

I don't think that what you described required a custom widget @alkanna - if you have a canvas.Image that you want to update, just apply the changes to it and call Refresh().
What else were you looking to do?

@alkanna
Copy link

alkanna commented Dec 31, 2020

I was looking into being able to inject additional sprites onto that image and draw them over it as I see fit

@andydotxyz
Copy link
Member Author

Then perhaps container.NewMax(img1, img2, img3) so you can have 3 images on top of each other?
Or use a single Go image.Image and then draw it using canvas.NewImageFromImage?
Neither need custom widgets.

toaster added a commit to toaster/fyne that referenced this issue Mar 2, 2021
Making this public would address fyne-io#709.
@andydotxyz andydotxyz added this to the Aberlour (2.1) milestone May 24, 2021
@andydotxyz andydotxyz changed the title Add a "SimpleWidget" wrapper or similar so I can make canvas primitives interactive Add a "SimpleWidget" or "StaticRenderer" so I can make canvas primitives interactive May 24, 2021
@andydotxyz andydotxyz assigned andydotxyz and unassigned toaster May 24, 2021
andydotxyz added a commit to andydotxyz/fyne that referenced this issue Jun 6, 2021
Easiest usage is to return NewSimpleRenderer(myObj) from CreateRenderer

Fixes fyne-io#709
@andydotxyz
Copy link
Member Author

This is now on develop :)

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

4 participants