Compare commits
2 commits
f503732f38
...
1964b0202b
Author | SHA1 | Date | |
---|---|---|---|
1964b0202b | |||
08904c484a |
4 changed files with 165 additions and 31 deletions
35
examples/floatingControlsContainer/main.go
Normal file
35
examples/floatingControlsContainer/main.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/app"
|
||||||
|
"fyne.io/fyne/v2/canvas"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"git.martyn.berlin/martyn/fyne-widgets/pkg/layouts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := app.New()
|
||||||
|
w := a.NewWindow("FloatingButtons")
|
||||||
|
|
||||||
|
background := canvas.NewRectangle(color.RGBA{255, 0, 0, 128})
|
||||||
|
|
||||||
|
layout := layouts.NewFloatingControlsLayout()
|
||||||
|
layout.FloatingControlsLocation = layouts.FloatingControlsCenter
|
||||||
|
button := widget.NewButton("X", func() {
|
||||||
|
fmt.Println("button clicked")
|
||||||
|
layout.FloatingControlsLocation = layout.FloatingControlsLocation + 1
|
||||||
|
if layout.FloatingControlsLocation > 4 {
|
||||||
|
layout.FloatingControlsLocation = 0
|
||||||
|
}
|
||||||
|
w.SetContent(w.Content())
|
||||||
|
})
|
||||||
|
|
||||||
|
w.SetContent(container.New(&layout, background, button))
|
||||||
|
w.Resize(fyne.NewSize(100, 100))
|
||||||
|
w.ShowAndRun()
|
||||||
|
}
|
|
@ -24,6 +24,10 @@ func main() {
|
||||||
level.Set(data / 100)
|
level.Set(data / 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.SetContent(container.New(layout.NewVBoxLayout(), levelPB, progress, slider))
|
vLevelPB := vumeter.NewVUMeterWithData(level)
|
||||||
|
vLevelPB.VUMeterDirection = vumeter.VUMeterVertical
|
||||||
|
vLevelPB.TextFormatter = func() string { return " " }
|
||||||
|
contain := container.New(layout.NewVBoxLayout(), levelPB, progress, slider)
|
||||||
|
w.SetContent(container.New(layout.NewHBoxLayout(), contain, vLevelPB))
|
||||||
w.ShowAndRun()
|
w.ShowAndRun()
|
||||||
}
|
}
|
||||||
|
|
59
pkg/layouts/floatingControlsContainer.go
Normal file
59
pkg/layouts/floatingControlsContainer.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package layouts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FloatingControlsLocationEnum uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
FloatingControlsTopLeft = iota
|
||||||
|
FloatingControlsTopRight
|
||||||
|
FloatingControlsBottomLeft
|
||||||
|
FloatingControlsBottomRight
|
||||||
|
FloatingControlsCenter
|
||||||
|
)
|
||||||
|
|
||||||
|
type floatingControlsLayout struct {
|
||||||
|
FloatingControlsLocation FloatingControlsLocationEnum
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloatingControlsLayout creates a new floatingControlsLayout instance
|
||||||
|
// This layout contains exactly TWO items, one background item (first) and one
|
||||||
|
// floating container that floats according to FloatingControlsLocation
|
||||||
|
func NewFloatingControlsLayout() floatingControlsLayout {
|
||||||
|
return floatingControlsLayout{FloatingControlsTopRight}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *floatingControlsLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
||||||
|
if len(objects) > 1 {
|
||||||
|
return objects[0].MinSize()
|
||||||
|
}
|
||||||
|
return fyne.NewSize(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *floatingControlsLayout) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
|
||||||
|
if len(objects) == 2 {
|
||||||
|
o := objects[0]
|
||||||
|
size := containerSize
|
||||||
|
o.Resize(size)
|
||||||
|
o.Move(fyne.NewPos(0, 0))
|
||||||
|
|
||||||
|
o = objects[1]
|
||||||
|
size = o.MinSize()
|
||||||
|
o.Resize(size)
|
||||||
|
switch d.FloatingControlsLocation {
|
||||||
|
case FloatingControlsTopLeft:
|
||||||
|
o.Move(fyne.NewPos(0, 0))
|
||||||
|
case FloatingControlsTopRight:
|
||||||
|
o.Move(fyne.NewPos(containerSize.Width-size.Width, 0))
|
||||||
|
case FloatingControlsBottomLeft:
|
||||||
|
o.Move(fyne.NewPos(0, containerSize.Height-size.Height))
|
||||||
|
case FloatingControlsBottomRight:
|
||||||
|
o.Move(fyne.NewPos(containerSize.Width-size.Width, containerSize.Height-size.Height))
|
||||||
|
case FloatingControlsCenter:
|
||||||
|
o.Move(fyne.NewPos((containerSize.Width/2)-(size.Width/2), (containerSize.Height/2)-(size.Height/2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,47 +54,74 @@ func (v *vuRenderer) updateBars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
size := v.meter.Size()
|
size := v.meter.Size()
|
||||||
greenWidth := 0.0
|
var ratioSize float64
|
||||||
amberWidth := 0.0
|
if v.meter.VUMeterDirection == VUMeterHorizontal {
|
||||||
redWidth := 0.0
|
ratioSize = float64(size.Width)
|
||||||
|
} else {
|
||||||
|
ratioSize = float64(size.Height)
|
||||||
|
}
|
||||||
|
|
||||||
|
greenSize := 0.0
|
||||||
|
amberSize := 0.0
|
||||||
|
redSize := 0.0
|
||||||
if ratio > (v.meter.OptimumValueMin / 100) {
|
if ratio > (v.meter.OptimumValueMin / 100) {
|
||||||
if ratio > (v.meter.OptimumValueMax / 100) {
|
if ratio > (v.meter.OptimumValueMax / 100) {
|
||||||
greenWidth = float64(size.Width) * v.meter.OptimumValueMin / 100
|
greenSize = ratioSize * v.meter.OptimumValueMin / 100
|
||||||
amberWidth = float64(size.Width) * v.meter.OptimumValueMax / 100
|
amberSize = ratioSize * v.meter.OptimumValueMax / 100
|
||||||
redWidth = float64(size.Width) * ratio
|
redSize = ratioSize * ratio
|
||||||
} else {
|
} else {
|
||||||
greenWidth = float64(size.Width) * v.meter.OptimumValueMin / 100
|
greenSize = ratioSize * v.meter.OptimumValueMin / 100
|
||||||
amberWidth = float64(size.Width) * ratio
|
amberSize = ratioSize * ratio
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
greenWidth = float64(size.Width) * ratio
|
greenSize = ratioSize * ratio
|
||||||
}
|
}
|
||||||
redWidth = redWidth - amberWidth
|
redSize = redSize - amberSize
|
||||||
if redWidth < 0 {
|
if redSize < 0 {
|
||||||
redWidth = 0
|
redSize = 0
|
||||||
}
|
}
|
||||||
amberWidth = amberWidth - greenWidth
|
amberSize = amberSize - greenSize
|
||||||
if amberWidth < 0 {
|
if amberSize < 0 {
|
||||||
amberWidth = 0
|
amberSize = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
lowalphaGreenWidth := float64(size.Width) * v.meter.OptimumValueMin / 100
|
lowalphaGreenSize := ratioSize * v.meter.OptimumValueMin / 100
|
||||||
lowalphaAmberWidth := float64(size.Width) * v.meter.OptimumValueMax / 100
|
lowalphaAmberSize := ratioSize * v.meter.OptimumValueMax / 100
|
||||||
lowalphaRedWidth := float64(size.Width)
|
lowalphaRedSize := ratioSize
|
||||||
lowalphaRedWidth = lowalphaRedWidth - lowalphaAmberWidth
|
lowalphaRedSize = lowalphaRedSize - lowalphaAmberSize
|
||||||
lowalphaAmberWidth = lowalphaAmberWidth - lowalphaGreenWidth
|
lowalphaAmberSize = lowalphaAmberSize - lowalphaGreenSize
|
||||||
|
|
||||||
v.lowalphaGreen.Resize(fyne.NewSize(float32(lowalphaGreenWidth), size.Height))
|
if v.meter.VUMeterDirection == VUMeterHorizontal {
|
||||||
v.lowalphaAmber.Resize(fyne.NewSize(float32(lowalphaAmberWidth), size.Height))
|
v.lowalphaGreen.Move(fyne.NewPos(0, 0))
|
||||||
v.lowalphaAmber.Move(fyne.NewPos(float32(lowalphaGreenWidth), 0))
|
v.lowalphaGreen.Resize(fyne.NewSize(float32(lowalphaGreenSize), size.Height))
|
||||||
v.lowalphaRed.Resize(fyne.NewSize(float32(lowalphaRedWidth), size.Height))
|
v.lowalphaAmber.Resize(fyne.NewSize(float32(lowalphaAmberSize), size.Height))
|
||||||
v.lowalphaRed.Move(fyne.NewPos(float32(lowalphaAmberWidth+lowalphaGreenWidth), 0))
|
v.lowalphaAmber.Move(fyne.NewPos(float32(lowalphaGreenSize), 0))
|
||||||
|
v.lowalphaRed.Resize(fyne.NewSize(float32(lowalphaRedSize), size.Height))
|
||||||
|
v.lowalphaRed.Move(fyne.NewPos(float32(lowalphaAmberSize+lowalphaGreenSize), 0))
|
||||||
|
} else {
|
||||||
|
v.lowalphaGreen.Move(fyne.NewPos(0, size.Height-float32(lowalphaGreenSize)))
|
||||||
|
v.lowalphaGreen.Resize(fyne.NewSize(size.Width, float32(lowalphaGreenSize)))
|
||||||
|
v.lowalphaAmber.Resize(fyne.NewSize(size.Width, float32(lowalphaAmberSize)))
|
||||||
|
v.lowalphaAmber.Move(fyne.NewPos(0, size.Height-float32(lowalphaGreenSize+lowalphaAmberSize)))
|
||||||
|
v.lowalphaRed.Resize(fyne.NewSize(size.Width, float32(lowalphaRedSize)))
|
||||||
|
v.lowalphaRed.Move(fyne.NewPos(0, size.Height-float32(lowalphaGreenSize+lowalphaAmberSize+lowalphaRedSize)))
|
||||||
|
}
|
||||||
|
|
||||||
v.bar.Resize(fyne.NewSize(float32(greenWidth), size.Height))
|
if v.meter.VUMeterDirection == VUMeterHorizontal {
|
||||||
v.optimumBar.Resize(fyne.NewSize(float32(amberWidth), size.Height))
|
v.bar.Move(fyne.NewPos(0, 0))
|
||||||
v.optimumBar.Move(fyne.NewPos(float32(greenWidth), 0))
|
v.bar.Resize(fyne.NewSize(float32(greenSize), size.Height))
|
||||||
v.peakBar.Resize(fyne.NewSize(float32(redWidth), size.Height))
|
v.optimumBar.Resize(fyne.NewSize(float32(amberSize), size.Height))
|
||||||
v.peakBar.Move(fyne.NewPos(float32(greenWidth+amberWidth), 0))
|
v.optimumBar.Move(fyne.NewPos(float32(greenSize), 0))
|
||||||
|
v.peakBar.Resize(fyne.NewSize(float32(redSize), size.Height))
|
||||||
|
v.peakBar.Move(fyne.NewPos(float32(greenSize+amberSize), 0))
|
||||||
|
} else {
|
||||||
|
v.bar.Resize(fyne.NewSize(size.Width, float32(greenSize)))
|
||||||
|
v.bar.Move(fyne.NewPos(0, size.Height-float32(greenSize)))
|
||||||
|
v.optimumBar.Resize(fyne.NewSize(size.Width, float32(amberSize)))
|
||||||
|
v.optimumBar.Move(fyne.NewPos(0, size.Height-float32(greenSize+amberSize)))
|
||||||
|
v.peakBar.Resize(fyne.NewSize(size.Width, float32(redSize)))
|
||||||
|
v.peakBar.Move(fyne.NewPos(0, size.Height-float32(greenSize+amberSize+redSize)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout the components of the widget
|
// Layout the components of the widget
|
||||||
|
@ -128,12 +155,20 @@ func (v *vuRenderer) Objects() []fyne.CanvasObject {
|
||||||
func (v *vuRenderer) Destroy() {
|
func (v *vuRenderer) Destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VUMeterDirectionEnum uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
VUMeterVertical = iota
|
||||||
|
VUMeterHorizontal
|
||||||
|
)
|
||||||
|
|
||||||
// vuMeter widget is a kind of custom progressbar but has "zones" of different color for peaking.
|
// vuMeter widget is a kind of custom progressbar but has "zones" of different color for peaking.
|
||||||
type vuMeter struct {
|
type vuMeter struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
TextFormatter func() string
|
TextFormatter func() string
|
||||||
Value, Min, Max,
|
Value, Min, Max,
|
||||||
OptimumValueMin, OptimumValueMax float64
|
OptimumValueMin, OptimumValueMax float64
|
||||||
|
VUMeterDirection VUMeterDirectionEnum
|
||||||
|
|
||||||
binder basicBinder
|
binder basicBinder
|
||||||
}
|
}
|
||||||
|
@ -214,6 +249,7 @@ func NewVUMeter(value float64) *vuMeter {
|
||||||
meter.OptimumValueMin = 75
|
meter.OptimumValueMin = 75
|
||||||
meter.OptimumValueMax = 85
|
meter.OptimumValueMax = 85
|
||||||
meter.ExtendBaseWidget(meter)
|
meter.ExtendBaseWidget(meter)
|
||||||
|
meter.VUMeterDirection = VUMeterHorizontal
|
||||||
return meter
|
return meter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue