mko
mko

Reputation: 185

How to extend fyne BaseWidget - go gives error "type *SimpleCard has no field or method super"

I'm trying to extend fyne widget to have a simple clickable content with background. I searched fyne widgets to find an example that could be used as a starter and found something similar in List/ListItem.

I basically copied the list item code and adapted it a little bit. It does look similar to the simpler example on fyne documentation. But for some unknown reason go gives me an error and I don't know what the cause is or how I can fix it:

custom_widget/simple_card.go:80:24: c.card.super undefined (type *SimpleCard has no field or method super)

Here is the code of the module (custom_widget/simple_card.go):

package custom_widget

import (
    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/theme"
    "fyne.io/fyne/v2/widget"
    "log"
)

// Declare conformity with interfaces.
var _ fyne.Widget = (*SimpleCard)(nil)
var _ fyne.Tappable = (*SimpleCard)(nil)

type SimpleCard struct {
    widget.BaseWidget

    onTapped   func()
    background *canvas.Rectangle
    content    fyne.CanvasObject
    selected   bool
}

func NewSimpleCard(content fyne.CanvasObject, tapped func()) *SimpleCard {
    card := &SimpleCard{onTapped: tapped, content: content}
    card.ExtendBaseWidget(card)
    return card
}

// CreateRenderer is a private method to Fyne which links this custom_widget to its renderer.
func (c *SimpleCard) CreateRenderer() fyne.WidgetRenderer {
    c.ExtendBaseWidget(c)

    c.background = canvas.NewRectangle(theme.SelectionColor())
    c.background.Hide()

    objects := []fyne.CanvasObject{c.background, c.content}

    // NewBaseRenderer and BaseRenderer are copied from
    // https://github.com/fyne-io/fyne/blob/master/internal/widget/base_renderer.go
    // because the functionality is marked internal in fyne !?
    return &SimpleCardRenderer{NewBaseRenderer(objects), c}
}

func (c *SimpleCard) Tapped(_ *fyne.PointEvent) {
    log.Println("I have been tapped")
    if c.onTapped != nil {
        c.selected = true
        c.Refresh()
        c.onTapped()
    }
}

// Declare conformity with the WidgetRenderer interface.
var _ fyne.WidgetRenderer = (*SimpleCardRenderer)(nil)

type SimpleCardRenderer struct {
    BaseRenderer

    card *SimpleCard
}

// MinSize calculates the minimum size of a SimpleCardRenderer.
// This is based on the size of the status indicator and the size of the child object.
func (c *SimpleCardRenderer) MinSize() fyne.Size {
    return c.card.content.MinSize()
}

// Layout the components of the SimpleCardRenderer custom_widget.
func (c *SimpleCardRenderer) Layout(size fyne.Size) {
    c.card.background.Resize(size)
    c.card.content.Resize(size)
}

func (c *SimpleCardRenderer) Refresh() {
    if c.card.selected {
        c.card.background.FillColor = theme.SelectionColor()
        c.card.background.Show()
    } else {
        c.card.background.Hide()
    }
    c.card.background.Refresh()
    canvas.Refresh(c.card.super()) // compiler error !
}

Upvotes: 1

Views: 303

Answers (1)

andy.xyz
andy.xyz

Reputation: 3265

Remove all of the renderer type you created and in the CreateRenderer just return widget.NewSimpleRenderer(container .NewMax(c.background, c.content)). It is simpler than you think.

Copying code out of the main widgets is often not the best way as we have shortcuts and/or must support more functionality than your own widgets.

Upvotes: 1

Related Questions