circular profile button
This commit is contained in:
parent
7a4673ab3d
commit
5a8a14f63d
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/container"
|
||||
|
||||
"git.martyn.berlin/martyn/fyne-widgets/pkg/profilebtn"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := app.New()
|
||||
w := a.NewWindow("ProfileBtn")
|
||||
b := profilebtn.NewProfileBtn()
|
||||
i, s, err := image.Decode(bytes.NewReader(resourceProfilepicdoesnotexistJpg.StaticContent))
|
||||
fmt.Println(s)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(i.Bounds())
|
||||
b.SetProfileImage(i)
|
||||
b.OutlineWidth = 5
|
||||
w.SetContent(container.NewBorder(nil, nil, nil, nil, b))
|
||||
w.Resize(fyne.NewSize(640, 480))
|
||||
w.ShowAndRun()
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 442 KiB |
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,27 @@
|
|||
package profilebtn
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type circle struct {
|
||||
p image.Point
|
||||
r int
|
||||
}
|
||||
|
||||
func (c *circle) ColorModel() color.Model {
|
||||
return color.AlphaModel
|
||||
}
|
||||
|
||||
func (c *circle) Bounds() image.Rectangle {
|
||||
return image.Rect(c.p.X-c.r, c.p.Y-c.r, c.p.X+c.r, c.p.Y+c.r)
|
||||
}
|
||||
|
||||
func (c *circle) At(x, y int) color.Color {
|
||||
xx, yy, rr := float64(x-c.p.X)+0.5, float64(y-c.p.Y)+0.5, float64(c.r)
|
||||
if xx*xx+yy*yy < rr*rr {
|
||||
return color.Alpha{255}
|
||||
}
|
||||
return color.Alpha{0}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package profilebtn
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type profileBtn struct {
|
||||
widget.BaseWidget
|
||||
|
||||
OutlineWidth int
|
||||
OutlineColor color.Color
|
||||
|
||||
profileImage image.Image
|
||||
}
|
||||
|
||||
func (b *profileBtn) Resize(s fyne.Size) {
|
||||
b.BaseWidget.Resize(s)
|
||||
}
|
||||
|
||||
func (b *profileBtn) CreateRenderer() fyne.WidgetRenderer {
|
||||
return NewProfileBtnRenderer(b)
|
||||
}
|
||||
|
||||
func NewProfileBtnRenderer(b *profileBtn) *profileBtnRenderer {
|
||||
r := &profileBtnRenderer{
|
||||
canvas.NewRasterFromImage(image.NewRGBA(image.Rect(0, 0, 10, 10))),
|
||||
canvas.NewCircle(b.OutlineColor),
|
||||
b,
|
||||
}
|
||||
b.ExtendBaseWidget(b)
|
||||
return r
|
||||
}
|
||||
|
||||
func NewProfileBtn() *profileBtn {
|
||||
w := &profileBtn{}
|
||||
w.ExtendBaseWidget(w)
|
||||
w.OutlineWidth = 0
|
||||
w.OutlineColor = color.White
|
||||
return w
|
||||
}
|
||||
|
||||
func (b *profileBtn) SetProfileResource(r fyne.Resource) {
|
||||
b.profileImage = canvas.NewImageFromResource(r).Image
|
||||
}
|
||||
|
||||
func (b *profileBtn) SetProfileImage(i image.Image) {
|
||||
b.profileImage = i
|
||||
}
|
||||
|
||||
type profileBtnRenderer struct {
|
||||
rast *canvas.Raster
|
||||
background *canvas.Circle
|
||||
w *profileBtn
|
||||
}
|
||||
|
||||
func min(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
func minf(x, y float32) float32 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) Render(w, h int) image.Image {
|
||||
i := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
if r.w.profileImage != nil {
|
||||
src := r.w.profileImage
|
||||
b := src.Bounds().Size()
|
||||
dst := image.NewRGBA(image.Rect(0, 0, b.X, b.Y))
|
||||
draw.DrawMask(dst, dst.Bounds(), src, image.ZP, &circle{image.Point{b.X / 2, b.Y / 2}, (min(b.Y, b.Y) / 2) - r.w.OutlineWidth}, image.ZP, draw.Over)
|
||||
return dst
|
||||
} else {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) MinSize() fyne.Size {
|
||||
return fyne.NewSize(theme.Padding()*4, theme.Padding()*4)
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) Layout(size fyne.Size) {
|
||||
r.background.Resize(size)
|
||||
squareSize := fyne.NewSize(minf(size.Width, size.Height), minf(size.Width, size.Height))
|
||||
r.rast.Resize(squareSize)
|
||||
if squareSize.Width < size.Width {
|
||||
r.rast.Move(fyne.NewPos((size.Width-squareSize.Width)/2, 0))
|
||||
} else if squareSize.Height < size.Height {
|
||||
r.rast.Move(fyne.NewPos(0, (size.Height-squareSize.Height)/2))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) ApplyTheme() {
|
||||
r.Refresh()
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) BackgprofileColor() color.Color {
|
||||
return theme.ButtonColor()
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) Refresh() {
|
||||
r.rast = canvas.NewRaster(r.Render)
|
||||
r.Layout(r.w.Size())
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) Destroy() {
|
||||
}
|
||||
|
||||
func (r *profileBtnRenderer) Objects() []fyne.CanvasObject {
|
||||
r.Refresh()
|
||||
return []fyne.CanvasObject{r.background, r.rast}
|
||||
}
|
Loading…
Reference in New Issue