~whereswaldon/gio-x

25f73222d1a5ab07a1b11a72a4fc904a1b239233 — Chris Waldon 3 years ago 4b959c1
feat: remove old RightClickArea and respond to active menus

Now the demo places a context area over each shadow and responds to the
active menu by recoloring the shadow. This demonstrates how to determine
which of multiple context areas are active.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
1 files changed, 26 insertions(+), 90 deletions(-)

M component/menudemo/main.go
M component/menudemo/main.go => component/menudemo/main.go +26 -90
@@ 11,8 11,6 @@ import (
	"os"

	"gioui.org/app"
	"gioui.org/f32"
	"gioui.org/io/pointer"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"


@@ 57,85 55,6 @@ type (
	D = layout.Dimensions
)

type RightClickArea struct {
	position f32.Point
	dims     D
	active   bool
}

func (r *RightClickArea) Layout(gtx C, w layout.Widget) D {
	pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops)
	pointer.PassOp{Pass: true}.Add(gtx.Ops)
	pointer.InputOp{
		Tag:   r,
		Grab:  false,
		Types: pointer.Press | pointer.Release,
	}.Add(gtx.Ops)
	for _, e := range gtx.Events(r) {
		e, ok := e.(pointer.Event)
		if !ok {
			continue
		}
		if r.active {
			// Check whether we should dismiss menu.
			if e.Buttons.Contain(pointer.ButtonPrimary) {
				clickPos := e.Position.Sub(r.position)
				if !clickPos.In(f32.Rectangle{Max: layout.FPt(r.dims.Size)}) {
					r.Dismiss()
				}
			}
		}
		if e.Buttons.Contain(pointer.ButtonSecondary) {
			r.active = true
			r.position = e.Position
		}
	}
	dims := D{Size: gtx.Constraints.Min}

	if !r.active {
		return dims
	}

	for _, e := range gtx.Events(&r.active) {
		e, ok := e.(pointer.Event)
		if !ok {
			continue
		}
		if e.Type == pointer.Release {
			r.Dismiss()
		}
	}

	defer op.Save(gtx.Ops).Load()
	macro := op.Record(gtx.Ops)
	r.dims = w(gtx)
	call := macro.Stop()

	if int(r.position.X)+r.dims.Size.X > gtx.Constraints.Max.X {
		r.position.X = float32(gtx.Constraints.Max.X - r.dims.Size.X)
	}
	if int(r.position.Y)+r.dims.Size.Y > gtx.Constraints.Max.Y {
		r.position.Y = float32(gtx.Constraints.Max.Y - r.dims.Size.Y)
	}
	macro2 := op.Record(gtx.Ops)
	op.Offset(r.position).Add(gtx.Ops)
	call.Add(gtx.Ops)
	pointer.PassOp{Pass: true}.Add(gtx.Ops)
	pointer.Rect(image.Rectangle{Max: r.dims.Size}).Add(gtx.Ops)
	pointer.InputOp{
		Tag:   &r.active,
		Grab:  false,
		Types: pointer.Release,
	}.Add(gtx.Ops)
	call2 := macro2.Stop()
	op.Defer(gtx.Ops, call2)
	return dims
}

func (r *RightClickArea) Dismiss() {
	r.active = false
}

func loop(w *app.Window) error {
	th := material.NewTheme(gofont.Collection())
	var (


@@ 166,7 85,7 @@ func loop(w *app.Window) error {
		},
	}
	var shadows layout.List
	var area RightClickArea
	var areas []component.ContextArea
	for {
		e := <-w.Events()
		switch e := e.(type) {


@@ 185,16 104,33 @@ func loop(w *app.Window) error {
			if c.Clicked() {
				log.Println("C")
			}
			area.Layout(gtx, func(gtx C) D {
				gtx.Constraints.Min = image.Point{}
				return component.Menu(th, &menu).Layout(gtx)
			})
			layout.N.Layout(gtx, func(gtx C) D {
				return shadows.Layout(gtx, 30, func(gtx C, index int) D {
					return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D {
						gtx.Constraints.Min = image.Point{X: gtx.Px(unit.Dp(30)), Y: gtx.Px(unit.Dp(30))}
						return component.Shadow(unit.Dp(8), unit.Dp(float32(index))).Layout(gtx)
					})
					if len(areas) < index+1 {
						areas = append(areas, component.ContextArea{})
					}
					active := areas[index].Active()
					return layout.Stack{}.Layout(gtx,
						layout.Expanded(func(gtx C) D {
							return areas[index].Layout(gtx, func(gtx C) D {
								gtx.Constraints.Min = image.Point{}
								return component.Menu(th, &menu).Layout(gtx)
							})
						}),
						layout.Stacked(func(gtx C) D {
							return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D {
								gtx.Constraints.Min = image.Point{X: gtx.Px(unit.Dp(30)), Y: gtx.Px(unit.Dp(30))}
								shadow := component.Shadow(unit.Dp(8), unit.Dp(float32(index)))
								if active {
									col := color.NRGBA{R: 255, A: 0x30}
									shadow.AmbientColor = col
									shadow.PenumbraColor = col
									shadow.UmbraColor = col
								}
								return shadow.Layout(gtx)
							})
						}),
					)
				})
			})
			e.Frame(gtx.Ops)