diff --git a/cmd/hello/main.go b/cmd/hello/main.go index 42c0cc9540..c68da2d698 100644 --- a/cmd/hello/main.go +++ b/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() } diff --git a/dialog/color_picker.go b/dialog/color_picker.go index 52ec621429..fed3bfee99 100644 --- a/dialog/color_picker.go +++ b/dialog/color_picker.go @@ -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, @@ -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 @@ -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() { diff --git a/internal/app/focus_manager_test.go b/internal/app/focus_manager_test.go index 6bf961db9c..b0a4d70fe7 100644 --- a/internal/app/focus_manager_test.go +++ b/internal/app/focus_manager_test.go @@ -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() { @@ -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{} diff --git a/internal/widget/simple_renderer.go b/internal/widget/simple_renderer.go new file mode 100644 index 0000000000..532d5435ea --- /dev/null +++ b/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() +} diff --git a/widget/entry_password.go b/widget/entry_password.go index acf80a5c3b..e57f78299d 100644 --- a/widget/entry_password.go +++ b/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" @@ -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, } } @@ -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() diff --git a/widget/entry_validation.go b/widget/entry_validation.go index a548e46342..1fe504101b 100644 --- a/widget/entry_validation.go +++ b/widget/entry_validation.go @@ -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 } @@ -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() diff --git a/widget/form.go b/widget/form.go index f6c99c4879..7160f2765b 100644 --- a/widget/form.go +++ b/widget/form.go @@ -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" ) @@ -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 diff --git a/widget/separator.go b/widget/separator.go index 8fab81ef5f..47e2516793 100644 --- a/widget/separator.go +++ b/widget/separator.go @@ -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, } } @@ -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) diff --git a/widget/widget.go b/widget/widget.go index a0ce655a8b..2cacddc056 100644 --- a/widget/widget.go +++ b/widget/widget.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/internal/cache" + internalWidget "fyne.io/fyne/v2/internal/widget" ) // BaseWidget provides a helper that handles basic widget behaviours. @@ -198,25 +199,4 @@ func (w *DisableableWidget) Disabled() bool { return w.disabled } -type simpleRenderer struct { - content *fyne.Container -} - -func (s *simpleRenderer) Destroy() { -} - -func (s *simpleRenderer) Layout(size fyne.Size) { - s.content.Resize(size) -} - -func (s *simpleRenderer) MinSize() fyne.Size { - return s.content.MinSize() -} - -func (s *simpleRenderer) Objects() []fyne.CanvasObject { - return []fyne.CanvasObject{s.content} -} - -func (s *simpleRenderer) Refresh() { - s.content.Refresh() -} +type SimpleRenderer = internalWidget.SimpleRenderer diff --git a/widget/widget_test.go b/widget/widget_test.go index 602bd9ca74..affbc009a6 100644 --- a/widget/widget_test.go +++ b/widget/widget_test.go @@ -5,6 +5,7 @@ import ( "time" "fyne.io/fyne/v2" + internalWidget "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -23,7 +24,7 @@ func (m *myWidget) Refresh() { func (m *myWidget) CreateRenderer() fyne.WidgetRenderer { m.ExtendBaseWidget(m) - return &simpleRenderer{&fyne.Container{}} + return internalWidget.NewSimpleRenderer(&fyne.Container{}) } func TestApplyThemeCalled(t *testing.T) {