iconbutton.go raw

   1  package gel
   2  
   3  import (
   4  	"image"
   5  	
   6  	"github.com/p9c/gio/f32"
   7  	"github.com/p9c/gio/io/pointer"
   8  	l "github.com/p9c/gio/layout"
   9  	"github.com/p9c/gio/op/clip"
  10  	"github.com/p9c/gio/unit"
  11  	"golang.org/x/exp/shiny/materialdesign/icons"
  12  	
  13  	"github.com/p9c/gel/f32color"
  14  )
  15  
  16  type IconButton struct {
  17  	*Window
  18  	background string
  19  	// Color is the icon color.
  20  	color string
  21  	icon  *Icon
  22  	// Size is the icon size.
  23  	size    unit.Value
  24  	inset   *Inset
  25  	button  *Clickable
  26  	corners int
  27  }
  28  
  29  // IconButton creates an icon with a circular *optional non-round corners* background and an icon placed in the centre
  30  func (w *Window) IconButton(button *Clickable) *IconButton {
  31  	return &IconButton{
  32  		Window:     w,
  33  		background: "Primary",
  34  		color:      "DocBg",
  35  		size:       w.TextSize,
  36  		inset:      w.Inset(0.33, nil),
  37  		button:     button,
  38  		icon:       w.Icon().Src(&icons.AlertError),
  39  	}
  40  }
  41  
  42  // Corners sets the corners that will be circular
  43  func (b *IconButton) Corners(corners int) *IconButton {
  44  	b.corners = corners
  45  	return b
  46  }
  47  
  48  // Background sets the color of the circular background
  49  func (b *IconButton) Background(color string) *IconButton {
  50  	b.background = color
  51  	return b
  52  }
  53  
  54  // Color sets the color of the icon
  55  func (b *IconButton) Color(color string) *IconButton {
  56  	b.color = color
  57  	return b
  58  }
  59  
  60  // Icon sets the icon to display
  61  func (b *IconButton) Icon(ic *Icon) *IconButton {
  62  	b.icon = ic
  63  	return b
  64  }
  65  
  66  // Scale changes the size of the icon as a ratio of the base font size
  67  func (b *IconButton) Scale(scale float32) *IconButton {
  68  	b.size = b.Theme.TextSize.Scale(scale * 0.72)
  69  	return b
  70  }
  71  
  72  // ButtonInset sets the size of inset that goes in between the button background
  73  // and the icon
  74  func (b *IconButton) ButtonInset(inset float32) *IconButton {
  75  	b.inset = b.Inset(inset, b.button.Fn)
  76  	return b
  77  }
  78  
  79  // SetClick sets the function to run on click
  80  func (b *IconButton) SetClick(fn func()) *IconButton {
  81  	b.button.SetClick(fn)
  82  	return b
  83  }
  84  
  85  // SetPress sets the function to run on press
  86  func (b *IconButton) SetPress(fn func()) *IconButton {
  87  	b.button.SetPress(fn)
  88  	return b
  89  }
  90  
  91  // SetCancel sets the function to run on cancel (click but release outside)
  92  func (b *IconButton) SetCancel(fn func()) *IconButton {
  93  	b.button.SetCancel(fn)
  94  	return b
  95  }
  96  
  97  // Fn renders the icon button
  98  func (b *IconButton) Fn(gtx l.Context) l.Dimensions {
  99  	return b.Stack().Expanded(
 100  		func(gtx l.Context) l.Dimensions {
 101  			sizex, sizey := gtx.Constraints.Min.X, gtx.Constraints.Min.Y
 102  			sizexf, sizeyf := float32(sizex), float32(sizey)
 103  			rr := (sizexf + sizeyf) * .25
 104  			clip.RRect{
 105  				Rect: f32.Rectangle{Max: f32.Point{X: sizexf, Y: sizeyf}},
 106  				NE:   ifDir(rr, b.corners&NE),
 107  				NW:   ifDir(rr, b.corners&NW),
 108  				SE:   ifDir(rr, b.corners&SE),
 109  				SW:   ifDir(rr, b.corners&SW),
 110  			}.Add(gtx.Ops)
 111  			background := b.Theme.Colors.GetNRGBAFromName(b.background)
 112  			if gtx.Queue == nil {
 113  				background = f32color.MulAlpha(background, 150)
 114  			}
 115  			var dims l.Dimensions
 116  			if b.background != "" {
 117  				dims = Fill(gtx, background)
 118  			}
 119  			for _, c := range b.button.History() {
 120  				drawInk(gtx, c)
 121  			}
 122  			return dims
 123  		},
 124  	).Stacked(
 125  		b.inset.Embed(b.icon.Fn).Fn,
 126  	).Expanded(
 127  		func(gtx l.Context) l.Dimensions {
 128  			pointer.Ellipse(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops)
 129  			return b.button.Fn(gtx)
 130  		},
 131  	).Fn(gtx)
 132  }
 133