| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package gui
- import (
- "github.com/g3n/engine/math32"
- "github.com/g3n/engine/texture"
- "github.com/g3n/engine/window"
- )
- type ImageButton struct {
- *Panel // Embedded Panel
- label *Label // Label panel
- iconLabel bool // True if icon
- image *Image // pointer to button image (may be nil)
- styles *ImageButtonStyles // pointer to current button styles
- mouseOver bool // true if mouse is over button
- pressed bool // true if button is pressed
- stateImages [ButtonDisabled+1]*texture.Texture2D // array of images for each button state
- }
- type ButtonState int
- const (
- ButtonNormal ButtonState = iota
- ButtonOver
- //ButtonFocus
- ButtonPressed
- ButtonDisabled
- )
- // ImageButton style
- type ImageButtonStyle struct {
- Border BorderSizes
- Paddings BorderSizes
- BorderColor math32.Color4
- BgColor math32.Color4
- FgColor math32.Color
- }
- // All ImageButton styles
- type ImageButtonStyles struct {
- Normal ImageButtonStyle
- Over ImageButtonStyle
- Focus ImageButtonStyle
- Pressed ImageButtonStyle
- Disabled ImageButtonStyle
- }
- // NewImageButton creates and returns a pointer to a new ImageButton widget
- // with the specified image.
- func NewImageButton(normalImgPath string) (*ImageButton, error) {
- b := new(ImageButton)
- b.styles = &StyleDefault.ImageButton
- tex, err := texture.NewTexture2DFromImage(normalImgPath)
- if err != nil {
- return nil, err
- }
- b.stateImages[ButtonNormal] = tex
- b.image = NewImageFromTex(tex)
- // Initializes the button panel
- b.Panel = NewPanel(0, 0)
- b.Panel.SetContentSize(b.image.Width(), b.image.Height())
- b.Panel.SetBorders(5, 5, 5, 5)
- b.Panel.Add(b.image)
- // Subscribe to panel events
- b.Panel.Subscribe(OnKeyDown, b.onKey)
- b.Panel.Subscribe(OnKeyUp, b.onKey)
- b.Panel.Subscribe(OnMouseUp, b.onMouse)
- b.Panel.Subscribe(OnMouseDown, b.onMouse)
- b.Panel.Subscribe(OnCursor, b.onCursor)
- b.Panel.Subscribe(OnCursorEnter, b.onCursor)
- b.Panel.Subscribe(OnCursorLeave, b.onCursor)
- b.Panel.Subscribe(OnEnable, func(name string, ev interface{}) { b.update() })
- b.Panel.Subscribe(OnResize, func(name string, ev interface{}) { b.recalc() })
- b.recalc()
- b.update()
- return b, nil
- }
- // SetText sets the text of the label
- func (b *ImageButton) SetText(text string) {
- if b.iconLabel && b.label != nil {
- b.Panel.Remove(b.label)
- b.label.Dispose()
- b.label = nil
- }
- b.iconLabel = false
- if b.label == nil {
- // Create label
- b.label = NewLabel(text)
- b.Panel.Add(b.label)
- } else {
- b.label.SetText(text)
- }
- b.recalc()
- }
- // SetIcon sets the icon
- func (b *ImageButton) SetIcon(icode int) {
- if b.iconLabel == false && b.label != nil {
- b.Panel.Remove(b.label)
- b.label.Dispose()
- b.label = nil
- }
- b.iconLabel = true
- if b.label == nil {
- // Create icon
- b.label = NewIconLabel(string(icode))
- b.Panel.Add(b.label)
- } else {
- b.label.SetText(string(icode))
- }
- b.recalc()
- }
- // SetFontSize sets the font size of the label/icon
- func (b *ImageButton) SetFontSize(size float64) {
- if b.label != nil {
- b.label.SetFontSize(size)
- b.recalc()
- }
- }
- // SetImage sets the button left image from the specified filename
- // If there is currently a selected icon, it is removed
- func (b *ImageButton) SetImage(state ButtonState, imgfile string) error {
- tex, err := texture.NewTexture2DFromImage(imgfile)
- if err != nil {
- return err
- }
- if b.stateImages[state] != nil {
- b.stateImages[state].Dispose()
- }
- b.stateImages[state] = tex
- b.update()
- return nil
- }
- // Dispose releases resources used by this widget
- func (b *ImageButton) Dispose() {
- b.Panel.Dispose()
- for _, tex := range b.stateImages {
- if tex != nil {
- tex.Dispose()
- }
- }
- }
- // SetStyles set the button styles overriding the default style
- func (b *ImageButton) SetStyles(bs *ImageButtonStyles) {
- b.styles = bs
- b.update()
- }
- // onCursor process subscribed cursor events
- func (b *ImageButton) onCursor(evname string, ev interface{}) {
- switch evname {
- case OnCursorEnter:
- b.mouseOver = true
- b.update()
- case OnCursorLeave:
- b.pressed = false
- b.mouseOver = false
- b.update()
- }
- b.root.StopPropagation(StopAll)
- }
- // onMouseEvent process subscribed mouse events
- func (b *ImageButton) onMouse(evname string, ev interface{}) {
- switch evname {
- case OnMouseDown:
- b.root.SetKeyFocus(b)
- b.pressed = true
- b.update()
- b.Dispatch(OnClick, nil)
- case OnMouseUp:
- b.pressed = false
- b.update()
- default:
- return
- }
- b.root.StopPropagation(StopAll)
- }
- // onKey processes subscribed key events
- func (b *ImageButton) onKey(evname string, ev interface{}) {
- kev := ev.(*window.KeyEvent)
- if evname == OnKeyDown && kev.Keycode == window.KeyEnter {
- b.pressed = true
- b.update()
- b.Dispatch(OnClick, nil)
- b.root.StopPropagation(Stop3D)
- return
- }
- if evname == OnKeyUp && kev.Keycode == window.KeyEnter {
- b.pressed = false
- b.update()
- b.root.StopPropagation(Stop3D)
- return
- }
- return
- }
- // update updates the button visual state
- func (b *ImageButton) update() {
- if !b.Enabled() {
- if b.stateImages[ButtonDisabled] != nil {
- b.image.SetTexture(b.stateImages[ButtonDisabled])
- }
- b.applyStyle(&b.styles.Disabled)
- return
- }
- if b.pressed {
- if b.stateImages[ButtonPressed] != nil {
- b.image.SetTexture(b.stateImages[ButtonPressed])
- }
- b.applyStyle(&b.styles.Pressed)
- return
- }
- if b.mouseOver {
- if b.stateImages[ButtonOver] != nil {
- b.image.SetTexture(b.stateImages[ButtonOver])
- }
- b.applyStyle(&b.styles.Over)
- return
- }
- b.image.SetTexture(b.stateImages[ButtonNormal])
- b.applyStyle(&b.styles.Normal)
- }
- // applyStyle applies the specified button style
- func (b *ImageButton) applyStyle(bs *ImageButtonStyle) {
- b.SetBordersColor4(&bs.BorderColor)
- b.SetBordersFrom(&bs.Border)
- b.SetPaddingsFrom(&bs.Paddings)
- b.SetColor4(&bs.BgColor)
- if b.label != nil {
- b.label.SetColor(&bs.FgColor)
- }
- }
- // recalc recalculates all dimensions and position from inside out
- func (b *ImageButton) recalc() {
- // Only need to recal if there's a label preset
- if b.label != nil {
- width := b.Panel.ContentWidth()
- height := b.Panel.ContentHeight()
- x := (width - b.label.Width()) / 2
- y := (height - b.label.Height()) / 2
- b.label.SetPosition(x, y)
- }
- }
|