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 }