gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/widget/example_test.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package widget_test 4 5 import ( 6 "fmt" 7 "image" 8 "io" 9 "strings" 10 11 "gioui.org/f32" 12 "gioui.org/io/event" 13 "gioui.org/io/input" 14 "gioui.org/io/pointer" 15 "gioui.org/io/transfer" 16 "gioui.org/layout" 17 "gioui.org/op" 18 "gioui.org/op/clip" 19 "gioui.org/widget" 20 ) 21 22 func ExampleClickable_passthrough() { 23 // When laying out clickable widgets on top of each other, 24 // pointer events can be passed down for the underlying 25 // widgets to pick them up. 26 var button1, button2 widget.Clickable 27 var r input.Router 28 gtx := layout.Context{ 29 Ops: new(op.Ops), 30 Constraints: layout.Exact(image.Pt(100, 100)), 31 Source: r.Source(), 32 } 33 34 // widget lays out two buttons on top of each other. 35 widget := func() { 36 content := func(gtx layout.Context) layout.Dimensions { return layout.Dimensions{Size: gtx.Constraints.Min} } 37 button1.Layout(gtx, content) 38 // button2 completely covers button1, but pass-through allows pointer 39 // events to pass through to button1. 40 defer pointer.PassOp{}.Push(gtx.Ops).Pop() 41 button2.Layout(gtx, content) 42 } 43 44 // The first layout and call to Frame declare the Clickable handlers 45 // to the input router, so the following pointer events are propagated. 46 widget() 47 r.Frame(gtx.Ops) 48 // Simulate one click on the buttons by sending a Press and Release event. 49 r.Queue( 50 pointer.Event{ 51 Source: pointer.Mouse, 52 Buttons: pointer.ButtonPrimary, 53 Kind: pointer.Press, 54 Position: f32.Pt(50, 50), 55 }, 56 pointer.Event{ 57 Source: pointer.Mouse, 58 Buttons: pointer.ButtonPrimary, 59 Kind: pointer.Release, 60 Position: f32.Pt(50, 50), 61 }, 62 ) 63 64 if button1.Clicked(gtx) { 65 fmt.Println("button1 clicked!") 66 } 67 if button2.Clicked(gtx) { 68 fmt.Println("button2 clicked!") 69 } 70 71 // Output: 72 // button1 clicked! 73 // button2 clicked! 74 } 75 76 func ExampleDraggable_Layout() { 77 var r input.Router 78 gtx := layout.Context{ 79 Ops: new(op.Ops), 80 Constraints: layout.Exact(image.Pt(100, 100)), 81 Source: r.Source(), 82 } 83 // mime is the type used to match drag and drop operations. 84 // It could be left empty in this example. 85 const mime = "MyMime" 86 drag := &widget.Draggable{Type: mime} 87 var drop int 88 // widget lays out the drag and drop handlers and processes 89 // the transfer events. 90 widget := func() { 91 // Setup the draggable widget. 92 w := func(gtx layout.Context) layout.Dimensions { 93 sz := image.Pt(10, 10) // drag area 94 return layout.Dimensions{Size: sz} 95 } 96 drag.Layout(gtx, w, w) 97 // drag must respond with an Offer event when requested. 98 // Use the drag method for this. 99 if m, ok := drag.Update(gtx); ok { 100 drag.Offer(gtx, m, io.NopCloser(strings.NewReader("hello world"))) 101 } 102 103 // Setup the area for drops. 104 ds := clip.Rect{ 105 Min: image.Pt(20, 20), 106 Max: image.Pt(40, 40), 107 }.Push(gtx.Ops) 108 event.Op(gtx.Ops, &drop) 109 ds.Pop() 110 111 // Check for the received data. 112 for { 113 ev, ok := gtx.Event(transfer.TargetFilter{Target: &drop, Type: mime}) 114 if !ok { 115 break 116 } 117 switch e := ev.(type) { 118 case transfer.DataEvent: 119 data := e.Open() 120 defer data.Close() 121 content, _ := io.ReadAll(data) 122 fmt.Println(string(content)) 123 } 124 } 125 } 126 // Register and lay out the widget. 127 widget() 128 r.Frame(gtx.Ops) 129 130 // Send drag and drop gesture events. 131 r.Queue( 132 pointer.Event{ 133 Kind: pointer.Press, 134 Position: f32.Pt(5, 5), // in the drag area 135 }, 136 pointer.Event{ 137 Kind: pointer.Move, 138 Position: f32.Pt(5, 5), // in the drop area 139 }, 140 pointer.Event{ 141 Kind: pointer.Release, 142 Position: f32.Pt(30, 30), // in the drop area 143 }, 144 ) 145 // Let the widget process the events. 146 widget() 147 r.Frame(gtx.Ops) 148 149 // Process the transfer.DataEvent. 150 widget() 151 152 // Output: 153 // hello world 154 }