| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- package widget
- import (
- "image/color"
- "fyne.io/fyne/v2"
- "fyne.io/fyne/v2/canvas"
- "fyne.io/fyne/v2/theme"
- )
- var _ fyne.Widget = (*Shadow)(nil)
- // Shadow is a widget that renders a shadow.
- type Shadow struct {
- Base
- level ElevationLevel
- typ ShadowType
- }
- // ElevationLevel is the level of elevation of the shadow casting object.
- type ElevationLevel int
- // ElevationLevel constants inspired by:
- // https://storage.googleapis.com/spec-host/mio-staging%2Fmio-design%2F1584058305895%2Fassets%2F0B6xUSjjSulxceF9udnA4Sk5tdU0%2Fbaselineelevation-chart.png
- const (
- BaseLevel ElevationLevel = 0
- CardLevel ElevationLevel = 1
- ButtonLevel ElevationLevel = 2
- MenuLevel ElevationLevel = 4
- PopUpLevel ElevationLevel = 8
- SubmergedContentLevel ElevationLevel = 8
- DialogLevel ElevationLevel = 24
- )
- // ShadowType specifies the type of the shadow.
- type ShadowType int
- // ShadowType constants
- const (
- ShadowAround ShadowType = iota
- ShadowLeft
- ShadowRight
- ShadowBottom
- ShadowTop
- )
- // NewShadow create a new Shadow.
- func NewShadow(typ ShadowType, level ElevationLevel) *Shadow {
- s := &Shadow{typ: typ, level: level}
- s.ExtendBaseWidget(s)
- return s
- }
- // CreateRenderer returns a new renderer for the shadow.
- //
- // Implements: fyne.Widget
- func (s *Shadow) CreateRenderer() fyne.WidgetRenderer {
- r := &shadowRenderer{s: s}
- r.createShadows()
- return r
- }
- type shadowRenderer struct {
- BaseRenderer
- b, l, r, t *canvas.LinearGradient
- bl, br, tl, tr *canvas.RadialGradient
- minSize fyne.Size
- s *Shadow
- }
- func (r *shadowRenderer) Layout(size fyne.Size) {
- depth := float32(r.s.level)
- if r.tl != nil {
- r.tl.Resize(fyne.NewSize(depth, depth))
- r.tl.Move(fyne.NewPos(-depth, -depth))
- }
- if r.t != nil {
- r.t.Resize(fyne.NewSize(size.Width, depth))
- r.t.Move(fyne.NewPos(0, -depth))
- }
- if r.tr != nil {
- r.tr.Resize(fyne.NewSize(depth, depth))
- r.tr.Move(fyne.NewPos(size.Width, -depth))
- }
- if r.r != nil {
- r.r.Resize(fyne.NewSize(depth, size.Height))
- r.r.Move(fyne.NewPos(size.Width, 0))
- }
- if r.br != nil {
- r.br.Resize(fyne.NewSize(depth, depth))
- r.br.Move(fyne.NewPos(size.Width, size.Height))
- }
- if r.b != nil {
- r.b.Resize(fyne.NewSize(size.Width, depth))
- r.b.Move(fyne.NewPos(0, size.Height))
- }
- if r.bl != nil {
- r.bl.Resize(fyne.NewSize(depth, depth))
- r.bl.Move(fyne.NewPos(-depth, size.Height))
- }
- if r.l != nil {
- r.l.Resize(fyne.NewSize(depth, size.Height))
- r.l.Move(fyne.NewPos(-depth, 0))
- }
- }
- func (r *shadowRenderer) MinSize() fyne.Size {
- return r.minSize
- }
- func (r *shadowRenderer) Refresh() {
- r.refreshShadows()
- r.Layout(r.s.Size())
- canvas.Refresh(r.s)
- }
- func (r *shadowRenderer) createShadows() {
- switch r.s.typ {
- case ShadowLeft:
- r.l = canvas.NewHorizontalGradient(color.Transparent, theme.ShadowColor())
- r.SetObjects([]fyne.CanvasObject{r.l})
- case ShadowRight:
- r.r = canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent)
- r.SetObjects([]fyne.CanvasObject{r.r})
- case ShadowBottom:
- r.b = canvas.NewVerticalGradient(theme.ShadowColor(), color.Transparent)
- r.SetObjects([]fyne.CanvasObject{r.b})
- case ShadowTop:
- r.t = canvas.NewVerticalGradient(color.Transparent, theme.ShadowColor())
- r.SetObjects([]fyne.CanvasObject{r.t})
- case ShadowAround:
- r.tl = canvas.NewRadialGradient(theme.ShadowColor(), color.Transparent)
- r.tl.CenterOffsetX = 0.5
- r.tl.CenterOffsetY = 0.5
- r.t = canvas.NewVerticalGradient(color.Transparent, theme.ShadowColor())
- r.tr = canvas.NewRadialGradient(theme.ShadowColor(), color.Transparent)
- r.tr.CenterOffsetX = -0.5
- r.tr.CenterOffsetY = 0.5
- r.r = canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent)
- r.br = canvas.NewRadialGradient(theme.ShadowColor(), color.Transparent)
- r.br.CenterOffsetX = -0.5
- r.br.CenterOffsetY = -0.5
- r.b = canvas.NewVerticalGradient(theme.ShadowColor(), color.Transparent)
- r.bl = canvas.NewRadialGradient(theme.ShadowColor(), color.Transparent)
- r.bl.CenterOffsetX = 0.5
- r.bl.CenterOffsetY = -0.5
- r.l = canvas.NewHorizontalGradient(color.Transparent, theme.ShadowColor())
- r.SetObjects([]fyne.CanvasObject{r.tl, r.t, r.tr, r.r, r.br, r.b, r.bl, r.l})
- }
- }
- func (r *shadowRenderer) refreshShadows() {
- updateShadowEnd(r.l)
- updateShadowStart(r.r)
- updateShadowStart(r.b)
- updateShadowEnd(r.t)
- updateShadowRadial(r.tl)
- updateShadowRadial(r.tr)
- updateShadowRadial(r.bl)
- updateShadowRadial(r.br)
- }
- func updateShadowEnd(g *canvas.LinearGradient) {
- if g == nil {
- return
- }
- g.EndColor = theme.ShadowColor()
- g.Refresh()
- }
- func updateShadowRadial(g *canvas.RadialGradient) {
- if g == nil {
- return
- }
- g.StartColor = theme.ShadowColor()
- g.Refresh()
- }
- func updateShadowStart(g *canvas.LinearGradient) {
- if g == nil {
- return
- }
- g.StartColor = theme.ShadowColor()
- g.Refresh()
- }
|