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  }