Skip to content

Commit

Permalink
New async size and pos to reduce code duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacalz committed Jan 6, 2024
1 parent 9830d0e commit c2ab3af
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 66 deletions.
37 changes: 12 additions & 25 deletions canvas/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,18 @@
package canvas // import "fyne.io/fyne/v2/canvas"

import (
"math"
"sync"
"sync/atomic"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/internal/async"
)

type baseObject struct {
size atomic.Uint64 // The current size of the canvas object
position atomic.Uint64 // The current position of the object
Hidden bool // Is this object currently hidden
size async.Size // The current size of the canvas object
position async.Position // The current position of the object
Hidden bool // Is this object currently hidden

min atomic.Uint64 // The minimum size this object can be
min async.Size // The minimum size this object can be

propertyLock sync.RWMutex
}
Expand All @@ -36,31 +35,31 @@ func (o *baseObject) Hide() {
// MinSize returns the specified minimum size, if set, or {1, 1} otherwise.
func (o *baseObject) MinSize() fyne.Size {
min := o.min.Load()
if min == 0 {
if min.IsZero() {
return fyne.Size{Width: 1, Height: 1}
}

return fyne.NewSize(twoFloat32FromUint64(min))
return min
}

// Move the object to a new position, relative to its parent.
func (o *baseObject) Move(pos fyne.Position) {
o.position.Store(uint64fromTwoFloat32(pos.X, pos.Y))
o.position.Store(pos)
}

// Position gets the current position of this canvas object, relative to its parent.
func (o *baseObject) Position() fyne.Position {
return fyne.NewPos(twoFloat32FromUint64(o.position.Load()))
return o.position.Load()
}

// Resize sets a new size for the canvas object.
func (o *baseObject) Resize(size fyne.Size) {
o.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
o.size.Store(size)
}

// SetMinSize specifies the smallest size this object should be.
func (o *baseObject) SetMinSize(size fyne.Size) {
o.min.Store(uint64fromTwoFloat32(size.Width, size.Height))
o.min.Store(size)
}

// Show will set this object to be visible.
Expand All @@ -73,7 +72,7 @@ func (o *baseObject) Show() {

// Size returns the current size of this canvas object.
func (o *baseObject) Size() fyne.Size {
return fyne.NewSize(twoFloat32FromUint64(o.size.Load()))
return o.size.Load()
}

// Visible returns true if this object is visible, false otherwise.
Expand All @@ -83,15 +82,3 @@ func (o *baseObject) Visible() bool {

return !o.Hidden
}

func uint64fromTwoFloat32(a, b float32) uint64 {
x := uint64(math.Float32bits(a))
y := uint64(math.Float32bits(b))
return (y << 32) | x
}

func twoFloat32FromUint64(combined uint64) (float32, float32) {
x := uint32(combined & 0x00000000FFFFFFFF)
y := uint32(combined & 0xFFFFFFFF00000000 >> 32)
return math.Float32frombits(x), math.Float32frombits(y)
}
52 changes: 52 additions & 0 deletions internal/async/vector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package async

import (
"math"
"sync/atomic"

"fyne.io/fyne/v2"
)

// Position is an atomic version of fyne.Position.
// Loads and stores are guaranteed to happen using a single atomic operation.
type Position struct {
pos atomic.Uint64
}

// Load performs an atomic load on the fyne.Position value.
func (p *Position) Load() fyne.Position {
return fyne.NewPos(twoFloat32FromUint64(p.pos.Load()))
}

// Store performs an atomic store on the fyne.Position value.
func (p *Position) Store(pos fyne.Position) {
p.pos.Store(uint64fromTwoFloat32(pos.X, pos.Y))
}

// Size is an atomic version of fyne.Size.
// Loads and stores are guaranteed to happen using a single atomic operation.
type Size struct {
size atomic.Uint64
}

// Load performs an atomic load on the fyne.Size value.
func (s *Size) Load() fyne.Size {
return fyne.NewSize(twoFloat32FromUint64(s.size.Load()))
}

// Store performs an atomic store on the fyne.Size value.
func (s *Size) Store(size fyne.Size) {
s.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
}

func uint64fromTwoFloat32(a, b float32) uint64 {
x := uint64(math.Float32bits(a))
y := uint64(math.Float32bits(b))
return (y << 32) | x
}

func twoFloat32FromUint64(combined uint64) (float32, float32) {
x := uint32(combined & 0x00000000FFFFFFFF)
y := uint32(combined & 0xFFFFFFFF00000000 >> 32)
return math.Float32frombits(x), math.Float32frombits(y)
}
26 changes: 7 additions & 19 deletions internal/widget/base.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package widget

import (
"math"
"sync/atomic"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/internal/async"
"fyne.io/fyne/v2/internal/cache"
)

// Base provides a helper that handles basic widget behaviours.
type Base struct {
hidden atomic.Bool
position atomic.Uint64
size atomic.Uint64
position async.Position
size async.Size
impl atomic.Pointer[fyne.Widget]
}

Expand All @@ -29,7 +29,7 @@ func (w *Base) ExtendBaseWidget(wid fyne.Widget) {

// Size gets the current size of this widget.
func (w *Base) Size() fyne.Size {
return fyne.NewSize(twoFloat32FromUint64(w.size.Load()))
return w.size.Load()
}

// Resize sets a new size for a widget.
Expand All @@ -39,7 +39,7 @@ func (w *Base) Resize(size fyne.Size) {
return
}

w.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
w.size.Store(size)

impl := w.super()
if impl == nil {
Expand All @@ -50,13 +50,13 @@ func (w *Base) Resize(size fyne.Size) {

// Position gets the current position of this widget, relative to its parent.
func (w *Base) Position() fyne.Position {
return fyne.NewPos(twoFloat32FromUint64(w.position.Load()))
return w.position.Load()
}

// Move the widget to a new position, relative to its parent.
// Note this should not be used if the widget is being managed by a Layout within a Container.
func (w *Base) Move(pos fyne.Position) {
w.position.Store(uint64fromTwoFloat32(pos.X, pos.Y))
w.position.Store(pos)

Repaint(w.super())
}
Expand Down Expand Up @@ -142,15 +142,3 @@ func Repaint(obj fyne.CanvasObject) {
}
}
}

func uint64fromTwoFloat32(a, b float32) uint64 {
x := uint64(math.Float32bits(a))
y := uint64(math.Float32bits(b))
return (y << 32) | x
}

func twoFloat32FromUint64(combined uint64) (float32, float32) {
x := uint32(combined & 0x00000000FFFFFFFF)
y := uint32(combined & 0xFFFFFFFF00000000 >> 32)
return math.Float32frombits(x), math.Float32frombits(y)
}
2 changes: 1 addition & 1 deletion widget/richtext.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (t *RichText) Resize(size fyne.Size) {
return
}

t.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
t.size.Store(size)

t.propertyLock.RLock()
segments := t.Segments
Expand Down
4 changes: 2 additions & 2 deletions widget/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func (t *Tree) Resize(size fyne.Size) {
return
}

t.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
t.size.Store(size)

t.Refresh() // trigger a redraw
}
Expand Down Expand Up @@ -590,7 +590,7 @@ func (c *treeContent) Resize(size fyne.Size) {
return
}

c.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
c.size.Store(size)

c.Refresh() // trigger a redraw
}
Expand Down
26 changes: 7 additions & 19 deletions widget/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
package widget // import "fyne.io/fyne/v2/widget"

import (
"math"
"sync"
"sync/atomic"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/internal/async"
"fyne.io/fyne/v2/internal/cache"
internalWidget "fyne.io/fyne/v2/internal/widget"
)

// BaseWidget provides a helper that handles basic widget behaviours.
type BaseWidget struct {
size atomic.Uint64
position atomic.Uint64
size async.Size
position async.Position
Hidden bool

impl atomic.Pointer[fyne.Widget]
Expand All @@ -34,7 +34,7 @@ func (w *BaseWidget) ExtendBaseWidget(wid fyne.Widget) {

// Size gets the current size of this widget.
func (w *BaseWidget) Size() fyne.Size {
return fyne.NewSize(twoFloat32FromUint64(w.size.Load()))
return w.size.Load()
}

// Resize sets a new size for a widget.
Expand All @@ -44,7 +44,7 @@ func (w *BaseWidget) Resize(size fyne.Size) {
return
}

w.size.Store(uint64fromTwoFloat32(size.Width, size.Height))
w.size.Store(size)

impl := w.super()
if impl == nil {
Expand All @@ -55,13 +55,13 @@ func (w *BaseWidget) Resize(size fyne.Size) {

// Position gets the current position of this widget, relative to its parent.
func (w *BaseWidget) Position() fyne.Position {
return fyne.NewPos(twoFloat32FromUint64(w.position.Load()))
return w.position.Load()
}

// Move the widget to a new position, relative to its parent.
// Note this should not be used if the widget is being managed by a Layout within a Container.
func (w *BaseWidget) Move(pos fyne.Position) {
w.position.Store(uint64fromTwoFloat32(pos.X, pos.Y))
w.position.Store(pos)
internalWidget.Repaint(w.super())
}

Expand Down Expand Up @@ -196,15 +196,3 @@ func (w *DisableableWidget) Disabled() bool {
func NewSimpleRenderer(object fyne.CanvasObject) fyne.WidgetRenderer {
return internalWidget.NewSimpleRenderer(object)
}

func uint64fromTwoFloat32(a, b float32) uint64 {
x := uint64(math.Float32bits(a))
y := uint64(math.Float32bits(b))
return (y << 32) | x
}

func twoFloat32FromUint64(combined uint64) (float32, float32) {
x := uint32(combined & 0x00000000FFFFFFFF)
y := uint32(combined & 0xFFFFFFFF00000000 >> 32)
return math.Float32frombits(x), math.Float32frombits(y)
}

0 comments on commit c2ab3af

Please sign in to comment.