github.com/Seikaijyu/gio@v0.0.1/widget/enum.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package widget
     4  
     5  import (
     6  	"github.com/Seikaijyu/gio/gesture"
     7  	"github.com/Seikaijyu/gio/io/key"
     8  	"github.com/Seikaijyu/gio/io/pointer"
     9  	"github.com/Seikaijyu/gio/io/semantic"
    10  	"github.com/Seikaijyu/gio/layout"
    11  	"github.com/Seikaijyu/gio/op"
    12  	"github.com/Seikaijyu/gio/op/clip"
    13  )
    14  
    15  type Enum struct {
    16  	Value    string
    17  	hovered  string
    18  	hovering bool
    19  
    20  	focus   string
    21  	focused bool
    22  
    23  	keys []*enumKey
    24  }
    25  
    26  type enumKey struct {
    27  	key   string
    28  	click gesture.Click
    29  	tag   struct{}
    30  }
    31  
    32  func (e *Enum) index(k string) *enumKey {
    33  	for _, v := range e.keys {
    34  		if v.key == k {
    35  			return v
    36  		}
    37  	}
    38  	return nil
    39  }
    40  
    41  // Update the state and report whether Value has changed by user interaction.
    42  func (e *Enum) Update(gtx layout.Context) bool {
    43  	if gtx.Queue == nil {
    44  		e.focused = false
    45  	}
    46  	e.hovering = false
    47  	changed := false
    48  	for _, state := range e.keys {
    49  		for _, ev := range state.click.Update(gtx) {
    50  			switch ev.Kind {
    51  			case gesture.KindPress:
    52  				if ev.Source == pointer.Mouse {
    53  					key.FocusOp{Tag: &state.tag}.Add(gtx.Ops)
    54  				}
    55  			case gesture.KindClick:
    56  				if state.key != e.Value {
    57  					e.Value = state.key
    58  					changed = true
    59  				}
    60  			}
    61  		}
    62  		for _, ev := range gtx.Events(&state.tag) {
    63  			switch ev := ev.(type) {
    64  			case key.FocusEvent:
    65  				if ev.Focus {
    66  					e.focused = true
    67  					e.focus = state.key
    68  				} else if state.key == e.focus {
    69  					e.focused = false
    70  				}
    71  			case key.Event:
    72  				if !e.focused || ev.State != key.Release {
    73  					break
    74  				}
    75  				if ev.Name != key.NameReturn && ev.Name != key.NameSpace {
    76  					break
    77  				}
    78  				if state.key != e.Value {
    79  					e.Value = state.key
    80  					changed = true
    81  				}
    82  			}
    83  		}
    84  		if state.click.Hovered() {
    85  			e.hovered = state.key
    86  			e.hovering = true
    87  		}
    88  	}
    89  
    90  	return changed
    91  }
    92  
    93  // Hovered returns the key that is highlighted, or false if none are.
    94  func (e *Enum) Hovered() (string, bool) {
    95  	return e.hovered, e.hovering
    96  }
    97  
    98  // Focused 方法会返回当前聚焦的键,如果没有键被聚焦,那么返回 false。
    99  func (e *Enum) Focused() (string, bool) {
   100  	return e.focus, e.focused
   101  }
   102  
   103  // Layout adds the event handler for the key k.
   104  func (e *Enum) Layout(gtx layout.Context, k string, content layout.Widget) layout.Dimensions {
   105  	e.Update(gtx)
   106  	m := op.Record(gtx.Ops)
   107  	dims := content(gtx)
   108  	c := m.Stop()
   109  	defer clip.Rect{Max: dims.Size}.Push(gtx.Ops).Pop()
   110  
   111  	state := e.index(k)
   112  	if state == nil {
   113  		state = &enumKey{
   114  			key: k,
   115  		}
   116  		e.keys = append(e.keys, state)
   117  	}
   118  	clk := &state.click
   119  	clk.Add(gtx.Ops)
   120  	enabled := gtx.Queue != nil
   121  	if enabled {
   122  		key.InputOp{Tag: &state.tag, Keys: "⏎|Space"}.Add(gtx.Ops)
   123  	}
   124  	semantic.SelectedOp(k == e.Value).Add(gtx.Ops)
   125  	semantic.EnabledOp(enabled).Add(gtx.Ops)
   126  	c.Add(gtx.Ops)
   127  
   128  	return dims
   129  }