Skip to content

Commit

Permalink
Add a new SimpleRenderer to handle simple cases.
Browse files Browse the repository at this point in the history
Easiest usage is to return NewSimpleRenderer(myObj) from CreateRenderer

Fixes fyne-io#709
  • Loading branch information
andydotxyz committed Jun 6, 2021
1 parent e3a830d commit 64aba40
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 102 deletions.
76 changes: 62 additions & 14 deletions cmd/hello/main.go
@@ -1,23 +1,71 @@
// Package main loads a very basic Hello World graphical application.
package main

import (
"fmt"
"image/color"
"math/rand"
"time"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"fyne.io/fyne/v2/theme"
)

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

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

w.ShowAndRun()
myApp := app.New()
myWindow := myApp.NewWindow("Lines")

c := container.NewWithoutLayout()
lps := canvas.NewText("- lps", color.White)
sig := canvas.NewRectangle(theme.BackgroundColor())
myWindow.SetContent(container.NewBorder(lps, nil, nil, nil, container.NewMax(sig, c)))
myWindow.Resize(fyne.NewSize(400, 400))
myWindow.SetPadded(false)

drawn := 0
r := uint8(0)
g := uint8(0)
go func() {
pos := fyne.NewPos(0, 0)
for {
newPos := fyne.NewPos(float32(rand.Intn(400)), float32(rand.Intn(400)))

line := canvas.NewLine(color.NRGBA{R: r, G: g, B: 250, A: 255})
g++
if g >= 255 {
g = 0
}
if g%10 == 0 {
r++
if r >= 255 {
r = 0
}
}
line.Position1 = pos
line.Position2 = newPos

c.Objects = append(c.Objects, line)
if len(c.Objects) > 1024 {
c.Objects = c.Objects[1:1025]
}
pos = newPos

canvas.Refresh(sig)
drawn++
time.Sleep(time.Millisecond / 8)
}
}()

go func() {
for {
time.Sleep(time.Second)
lps.Text = fmt.Sprintf("%d lps", drawn)
lps.Refresh()
drawn = 0
}
}()

myWindow.ShowAndRun()
}
16 changes: 3 additions & 13 deletions dialog/color_picker.go
Expand Up @@ -192,7 +192,7 @@ func (p *colorAdvancedPicker) CreateRenderer() fyne.WidgetRenderer {
))

r := &colorPickerRenderer{
BaseRenderer: internalwidget.NewBaseRenderer([]fyne.CanvasObject{contents}),
SimpleRenderer: internalwidget.NewSimpleRenderer(contents),
picker: p,
redChannel: redChannel,
greenChannel: greenChannel,
Expand Down Expand Up @@ -253,7 +253,7 @@ func (p *colorAdvancedPicker) updateRGBA(r, g, b, a int) bool {
var _ fyne.WidgetRenderer = (*colorPickerRenderer)(nil)

type colorPickerRenderer struct {
internalwidget.BaseRenderer
*internalwidget.SimpleRenderer
picker *colorAdvancedPicker
redChannel *colorChannel
greenChannel *colorChannel
Expand All @@ -268,19 +268,9 @@ type colorPickerRenderer struct {
contents fyne.CanvasObject
}

func (r *colorPickerRenderer) Layout(size fyne.Size) {
r.contents.Move(fyne.NewPos(0, 0))
r.contents.Resize(size)
}

func (r *colorPickerRenderer) MinSize() fyne.Size {
return r.contents.MinSize()
}

func (r *colorPickerRenderer) Refresh() {
r.updateObjects()
r.Layout(r.picker.Size())
canvas.Refresh(r.picker)
r.SimpleRenderer.Refresh()
}

func (r *colorPickerRenderer) updateObjects() {
Expand Down
24 changes: 4 additions & 20 deletions internal/app/focus_manager_test.go
Expand Up @@ -151,12 +151,12 @@ var _ fyne.Disableable = (*focusable)(nil)

type focusable struct {
widget.DisableableWidget
children []fyne.CanvasObject
focused bool
child fyne.CanvasObject
focused bool
}

func (f *focusable) CreateRenderer() fyne.WidgetRenderer {
return &focusableRenderer{BaseRenderer: internalWidget.NewBaseRenderer(f.children)}
return internalWidget.NewSimpleRenderer(f.child)
}

func (f *focusable) FocusGained() {
Expand All @@ -176,27 +176,11 @@ func (f *focusable) TypedRune(_ rune) {
func (f *focusable) TypedKey(_ *fyne.KeyEvent) {
}

var _ fyne.WidgetRenderer = (*focusableRenderer)(nil)

type focusableRenderer struct {
internalWidget.BaseRenderer
}

func (f focusableRenderer) Layout(_ fyne.Size) {
}

func (f focusableRenderer) MinSize() fyne.Size {
return fyne.NewSize(0, 0)
}

func (f focusableRenderer) Refresh() {
}

func setupFocusManager(t *testing.T) (m *app.FocusManager, entry1, hidden, visibleInsideHidden, entry2, disabled, entry3 *focusable) {
entry1 = &focusable{}
visibleInsideHidden = &focusable{}
hidden = &focusable{
children: []fyne.CanvasObject{visibleInsideHidden},
child: visibleInsideHidden,
}
hidden.Hide()
entry2 = &focusable{}
Expand Down
64 changes: 64 additions & 0 deletions internal/widget/simple_renderer.go
@@ -0,0 +1,64 @@
package widget

import "fyne.io/fyne/v2"

var _ fyne.WidgetRenderer = (*SimpleRenderer)(nil)

// SimpleRenderer is a basic renderer that satisfies widget.Renderer interface by wrapping
// a single fyne.CanvasObject.
//
// Since: 2.1
type SimpleRenderer struct {
object fyne.CanvasObject
}

// NewSimpleRenderer creates a new BaseRenderer.
//
// Since: 2.1
func NewSimpleRenderer(object fyne.CanvasObject) *SimpleRenderer {
return &SimpleRenderer{object}
}

// Destroy does nothing in the base implementation.
//
// Implements: fyne.WidgetRenderer
//
// Since: 2.1
func (r *SimpleRenderer) Destroy() {
}

// Layout updates the contained object to be the requested size.
//
// Implements: fyne.WidgetRenderer
//
// Since: 2.1
func (r *SimpleRenderer) Layout(s fyne.Size) {
r.object.Resize(s)
}

// MinSize returns the smallest size that this render can use, returned from the underlying object.
//
// Implements: fyne.WidgetRenderer
//
// Since: 2.1
func (r *SimpleRenderer) MinSize() fyne.Size {
return r.object.MinSize()
}

// Objects returns the objects that should be rendered.
//
// Implements: fyne.WidgetRenderer
//
// Since: 2.1
func (r *SimpleRenderer) Objects() []fyne.CanvasObject {
return []fyne.CanvasObject{r.object}
}

// Refresh requests the underlying object to redraw.
//
// Implements: fyne.WidgetRenderer
//
// Since: 2.1
func (r *SimpleRenderer) Refresh() {
r.object.Refresh()
}
19 changes: 5 additions & 14 deletions widget/entry_password.go
@@ -1,8 +1,6 @@
package widget

import (
"image/color"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/driver/desktop"
Expand All @@ -26,15 +24,16 @@ func newPasswordRevealer(e *Entry) *passwordRevealer {
icon: canvas.NewImageFromResource(theme.VisibilityOffIcon()),
entry: e,
}
pr.icon.SetMinSize(fyne.NewSize(theme.IconInlineSize(), theme.IconInlineSize()))
pr.ExtendBaseWidget(pr)
return pr
}

func (r *passwordRevealer) CreateRenderer() fyne.WidgetRenderer {
return &passwordRevealerRenderer{
BaseRenderer: widget.NewBaseRenderer([]fyne.CanvasObject{r.icon}),
icon: r.icon,
entry: r.entry,
SimpleRenderer: widget.NewSimpleRenderer(r.icon),
icon: r.icon,
entry: r.entry,
}
}

Expand All @@ -52,24 +51,16 @@ func (r *passwordRevealer) Tapped(*fyne.PointEvent) {
var _ fyne.WidgetRenderer = (*passwordRevealerRenderer)(nil)

type passwordRevealerRenderer struct {
widget.BaseRenderer
*widget.SimpleRenderer
entry *Entry
icon *canvas.Image
}

func (r *passwordRevealerRenderer) BackgroundColor() color.Color {
return color.Transparent
}

func (r *passwordRevealerRenderer) Layout(size fyne.Size) {
r.icon.Resize(fyne.NewSize(theme.IconInlineSize(), theme.IconInlineSize()))
r.icon.Move(fyne.NewPos((size.Width-theme.IconInlineSize())/2, (size.Height-theme.IconInlineSize())/2))
}

func (r *passwordRevealerRenderer) MinSize() fyne.Size {
return fyne.NewSize(theme.IconInlineSize(), theme.IconInlineSize())
}

func (r *passwordRevealerRenderer) Refresh() {
r.entry.propertyLock.RLock()
defer r.entry.propertyLock.RUnlock()
Expand Down
13 changes: 5 additions & 8 deletions widget/entry_validation.go
Expand Up @@ -68,17 +68,18 @@ func newValidationStatus(e *Entry) *validationStatus {
func (r *validationStatus) CreateRenderer() fyne.WidgetRenderer {
icon := &canvas.Image{}
icon.Hide()
icon.SetMinSize(fyne.NewSize(theme.IconInlineSize(), theme.IconInlineSize()))
return &validationStatusRenderer{
BaseRenderer: widget.NewBaseRenderer([]fyne.CanvasObject{icon}),
icon: icon,
entry: r.entry,
SimpleRenderer: widget.NewSimpleRenderer(icon),
icon: icon,
entry: r.entry,
}
}

var _ fyne.WidgetRenderer = (*validationStatusRenderer)(nil)

type validationStatusRenderer struct {
widget.BaseRenderer
*widget.SimpleRenderer
entry *Entry
icon *canvas.Image
}
Expand All @@ -88,10 +89,6 @@ func (r *validationStatusRenderer) Layout(size fyne.Size) {
r.icon.Move(fyne.NewPos((size.Width-theme.IconInlineSize())/2, (size.Height-theme.IconInlineSize())/2))
}

func (r *validationStatusRenderer) MinSize() fyne.Size {
return fyne.NewSize(theme.IconInlineSize(), theme.IconInlineSize())
}

func (r *validationStatusRenderer) Refresh() {
r.entry.propertyLock.RLock()
defer r.entry.propertyLock.RUnlock()
Expand Down
3 changes: 2 additions & 1 deletion widget/form.go
Expand Up @@ -6,6 +6,7 @@ import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/internal/cache"
internalWidget "fyne.io/fyne/v2/internal/widget"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
)
Expand Down Expand Up @@ -261,7 +262,7 @@ func (f *Form) CreateRenderer() fyne.WidgetRenderer {
}
f.itemGrid = fyne.NewContainerWithLayout(layout.NewFormLayout(), objects...)

renderer := &simpleRenderer{content: fyne.NewContainerWithLayout(layout.NewVBoxLayout(), f.itemGrid, f.buttonBox)}
renderer := internalWidget.NewSimpleRenderer(fyne.NewContainerWithLayout(layout.NewVBoxLayout(), f.itemGrid, f.buttonBox))
f.updateButtons() // will set correct visibility on the submit/cancel btns
f.checkValidation(nil) // will trigger a validation check for correct initial validation status
return renderer
Expand Down
13 changes: 4 additions & 9 deletions widget/separator.go
Expand Up @@ -31,11 +31,10 @@ func NewSeparator() *Separator {
func (s *Separator) CreateRenderer() fyne.WidgetRenderer {
s.ExtendBaseWidget(s)
bar := canvas.NewRectangle(theme.DisabledColor())
objects := []fyne.CanvasObject{bar}
return &separatorRenderer{
BaseRenderer: widget.NewBaseRenderer(objects),
bar: bar,
d: s,
SimpleRenderer: widget.NewSimpleRenderer(bar),
bar: bar,
d: s,
}
}

Expand All @@ -51,15 +50,11 @@ func (s *Separator) MinSize() fyne.Size {
var _ fyne.WidgetRenderer = (*separatorRenderer)(nil)

type separatorRenderer struct {
widget.BaseRenderer
*widget.SimpleRenderer
bar *canvas.Rectangle
d *Separator
}

func (r *separatorRenderer) Layout(size fyne.Size) {
r.bar.Resize(size)
}

func (r *separatorRenderer) MinSize() fyne.Size {
t := theme.SeparatorThicknessSize()
return fyne.NewSize(t, t)
Expand Down

0 comments on commit 64aba40

Please sign in to comment.