MouseEvent handling refactored
This commit is contained in:
parent
b1ad5ab081
commit
b6b6668d0e
26
events.go
26
events.go
@ -6,7 +6,29 @@ type Events interface {
|
|||||||
// If OnKeyPressed returns true, the event will not be passed onto child views
|
// If OnKeyPressed returns true, the event will not be passed onto child views
|
||||||
OnKeyPressed(event *KeyEvent) (consumed bool)
|
OnKeyPressed(event *KeyEvent) (consumed bool)
|
||||||
|
|
||||||
// OnMouseClicked is called every time a mouse button was pressed on the view.
|
// OnMouseEvent is called every time the mouse was used in any way.
|
||||||
|
// That includes mouse movement, button presses and scroll wheel usage
|
||||||
// If OnMouseClicked returns true, the event will not be passed onto child views
|
// If OnMouseClicked returns true, the event will not be passed onto child views
|
||||||
OnMouseClicked(event *MouseEvent) (consumed bool)
|
OnMouseEvent(event *MouseEvent) (consumed bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventTmpl struct {
|
||||||
|
KeyPressed func(event *KeyEvent) (consumed bool)
|
||||||
|
MouseEvent func(event *MouseEvent) (consumed bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Events = &EventTmpl{}
|
||||||
|
|
||||||
|
func (e *EventTmpl) OnKeyPressed(event *KeyEvent) (consumed bool) {
|
||||||
|
if e.KeyPressed == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return e.KeyPressed(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EventTmpl) OnMouseEvent(event *MouseEvent) (consumed bool) {
|
||||||
|
if e.MouseEvent == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return e.MouseEvent(event)
|
||||||
}
|
}
|
||||||
|
17
screen.go
17
screen.go
@ -9,6 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Screen struct {
|
type Screen struct {
|
||||||
|
EventTmpl
|
||||||
|
|
||||||
scr tcell.Screen
|
scr tcell.Screen
|
||||||
buf *ViewBuffer
|
buf *ViewBuffer
|
||||||
|
|
||||||
@ -17,12 +19,6 @@ type Screen struct {
|
|||||||
|
|
||||||
// Root is the root view which is currently shown on screen
|
// Root is the root view which is currently shown on screen
|
||||||
Root View
|
Root View
|
||||||
|
|
||||||
// KeyPressed is called every time a key or key-combination is pressed.
|
|
||||||
KeyPressed func(event *KeyEvent) (consumed bool)
|
|
||||||
|
|
||||||
// MouseClicked is called every time a mouse button was pressed.
|
|
||||||
MouseClicked func(event *MouseEvent) (consumed bool)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScreen(root View) (*Screen, error) {
|
func NewScreen(root View) (*Screen, error) {
|
||||||
@ -72,9 +68,10 @@ func (s *Screen) onKeyPressed(event *KeyEvent) {
|
|||||||
s.Redraw()
|
s.Redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Screen) onMouseClicked(event *MouseEvent) {
|
func (s *Screen) onMouseEvent(event *MouseEvent) {
|
||||||
if s.MouseClicked == nil || !s.MouseClicked(event) {
|
if s.MouseEvent == nil || !s.MouseEvent(event) {
|
||||||
go s.Root.OnMouseClicked(event)
|
go s.Root.OnMouseEvent(event)
|
||||||
|
// TODO redraw in same thread
|
||||||
}
|
}
|
||||||
if event.Button != MouseButtonNone {
|
if event.Button != MouseButtonNone {
|
||||||
s.Redraw()
|
s.Redraw()
|
||||||
@ -104,7 +101,7 @@ func (s *Screen) eventloop() {
|
|||||||
case *tcell.EventKey:
|
case *tcell.EventKey:
|
||||||
s.onKeyPressed(event)
|
s.onKeyPressed(event)
|
||||||
case *tcell.EventMouse:
|
case *tcell.EventMouse:
|
||||||
s.onMouseClicked(convertMouseEvent(event))
|
s.onMouseEvent(convertMouseEvent(event))
|
||||||
default:
|
default:
|
||||||
s.StopWithError(fmt.Errorf("%#v", event))
|
s.StopWithError(fmt.Errorf("%#v", event))
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.tordarus.net/Tordarus/tui"
|
"git.tordarus.net/Tordarus/tui"
|
||||||
@ -61,7 +62,7 @@ func TestScrollView(t *testing.T) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.MouseClicked = func(event *tui.MouseEvent) (consumed bool) {
|
screen.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
//textViews[0].(*views.TextView).Text = fmt.Sprintf("mouse position: %d | %d", event.X, event.Y)
|
//textViews[0].(*views.TextView).Text = fmt.Sprintf("mouse position: %d | %d", event.X, event.Y)
|
||||||
//textViews[1].(*views.TextView).Text = fmt.Sprintf("mouse button: %d", event.Button)
|
//textViews[1].(*views.TextView).Text = fmt.Sprintf("mouse button: %d", event.Button)
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ func TestMousePosition(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.MouseClicked = func(event *tui.MouseEvent) (consumed bool) {
|
screen.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
textView.Text = fmt.Sprintf("position: %s", event.Position.String())
|
textView.Text = fmt.Sprintf("position: %s", event.Position.String())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -217,20 +218,58 @@ func TestSeparatorLayout(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBorderLayout(t *testing.T) {
|
func TestBorderLayout(t *testing.T) {
|
||||||
topView := views.NewConstrainView(nil, 10, 10)
|
textView := views.NewTextView("")
|
||||||
|
textView.SetStyle(tui.StyleDefault.Background(tcell.ColorBlue))
|
||||||
|
textView.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
|
if event.Button == tui.MouseButtonLeft {
|
||||||
|
textView.SetStyle(tui.StyleDefault.Background(tcell.ColorRed))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
topView := views.NewConstrainView(textView, -1, -1)
|
||||||
topView.SetStyle(tui.StyleDefault.Background(tcell.ColorBlue))
|
topView.SetStyle(tui.StyleDefault.Background(tcell.ColorBlue))
|
||||||
|
|
||||||
bottomView := views.NewConstrainView(nil, 10, 10)
|
bottomView := views.NewConstrainView(nil, 10, 10)
|
||||||
bottomView.SetStyle(tui.StyleDefault.Background(tcell.ColorRed))
|
bottomView.SetStyle(tui.StyleDefault.Background(tcell.ColorRed))
|
||||||
|
bottomView.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
|
if event.Button == tui.MouseButtonLeft {
|
||||||
|
bottomView.SetStyle(tui.StyleDefault.Background(tcell.ColorBlue))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
leftView := views.NewConstrainView(nil, 10, 10)
|
leftView := views.NewConstrainView(nil, 10, 10)
|
||||||
leftView.SetStyle(tui.StyleDefault.Background(tcell.ColorYellow))
|
leftView.SetStyle(tui.StyleDefault.Background(tcell.ColorYellow))
|
||||||
|
leftView.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
|
if event.Button == tui.MouseButtonLeft {
|
||||||
|
leftView.SetStyle(tui.StyleDefault.Background(tcell.ColorGreen))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
rightView := views.NewConstrainView(nil, 10, 10)
|
rightView := views.NewConstrainView(nil, 10, 10)
|
||||||
rightView.SetStyle(tui.StyleDefault.Background(tcell.ColorGreen))
|
rightView.SetStyle(tui.StyleDefault.Background(tcell.ColorGreen))
|
||||||
|
rightView.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
|
if event.Button == tui.MouseButtonLeft {
|
||||||
|
rightView.SetStyle(tui.StyleDefault.Background(tcell.ColorYellow))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
centerView := views.NewConstrainView(nil, 10, 10)
|
centerView := views.NewConstrainView(nil, 10, 10)
|
||||||
centerView.SetStyle(tui.StyleDefault.Background(tcell.ColorPurple))
|
centerView.SetStyle(tui.StyleDefault.Background(tcell.ColorPurple))
|
||||||
|
centerView.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
|
if event.Button == tui.MouseButtonLeft {
|
||||||
|
centerView.SetStyle(tui.StyleDefault.Background(tcell.ColorOrange))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
borderLayout := views.NewBorderLayout()
|
borderLayout := views.NewBorderLayout()
|
||||||
borderLayout.SetStyle(tui.StyleDefault.Background(tcell.ColorPurple))
|
borderLayout.SetStyle(tui.StyleDefault.Background(tcell.ColorPurple))
|
||||||
@ -253,6 +292,23 @@ func TestBorderLayout(t *testing.T) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
screen.MouseEvent = func(event *tui.MouseEvent) (consumed bool) {
|
||||||
|
if event.Button == tui.MouseButtonLeft {
|
||||||
|
b := new(strings.Builder)
|
||||||
|
b.WriteString(textView.Text)
|
||||||
|
|
||||||
|
for slot, dim := range borderLayout.ViewDimensions {
|
||||||
|
if event.Position.In(dim) {
|
||||||
|
b.WriteString(fmt.Sprintf("%s: %s\n", slot, dim))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.Text = b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
err = screen.Start()
|
err = screen.Start()
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
2
types.go
2
types.go
@ -23,7 +23,7 @@ func P(x, y int) Point {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Point) In(d Dimension) bool {
|
func (p Point) In(d Dimension) bool {
|
||||||
return p.X >= d.X && p.X < d.X+d.Width && p.Y >= d.Y && p.Y < d.Y+d.Height
|
return p.X > d.X && p.X < d.X+d.Width && p.Y > d.Y && p.Y < d.Y+d.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Point) String() string {
|
func (p Point) String() string {
|
||||||
|
@ -11,7 +11,7 @@ type BorderLayout struct {
|
|||||||
horizontalLayout *LayoutResult
|
horizontalLayout *LayoutResult
|
||||||
verticalLayout *LayoutResult
|
verticalLayout *LayoutResult
|
||||||
|
|
||||||
viewDimensions map[Slot]tui.Dimension
|
ViewDimensions map[Slot]tui.Dimension
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ tui.Layout = &BorderLayout{}
|
var _ tui.Layout = &BorderLayout{}
|
||||||
@ -19,7 +19,7 @@ var _ tui.Layout = &BorderLayout{}
|
|||||||
func NewBorderLayout() *BorderLayout {
|
func NewBorderLayout() *BorderLayout {
|
||||||
return &BorderLayout{
|
return &BorderLayout{
|
||||||
views: map[Slot]tui.View{},
|
views: map[Slot]tui.View{},
|
||||||
viewDimensions: map[Slot]tui.Dimension{},
|
ViewDimensions: map[Slot]tui.Dimension{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
|||||||
topHeight = int(float64(buf.Height()) * float64(topHeight) / float64(verticalLayout.Sum.Height))
|
topHeight = int(float64(buf.Height()) * float64(topHeight) / float64(verticalLayout.Sum.Height))
|
||||||
}
|
}
|
||||||
|
|
||||||
g.viewDimensions[Top] = tui.D(0, 0, buf.Width(), topHeight)
|
g.ViewDimensions[Top] = tui.D(0, 0, buf.Width(), topHeight)
|
||||||
view.Draw(buf.Sub(0, 0, buf.Width(), topHeight))
|
view.Draw(buf.Sub(0, 0, buf.Width(), topHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
|||||||
bottomHeight = int(float64(buf.Height()) * float64(bottomHeight) / float64(verticalLayout.Sum.Height))
|
bottomHeight = int(float64(buf.Height()) * float64(bottomHeight) / float64(verticalLayout.Sum.Height))
|
||||||
}
|
}
|
||||||
|
|
||||||
g.viewDimensions[Bottom] = tui.D(0, buf.Height()-bottomHeight, buf.Width(), bottomHeight)
|
g.ViewDimensions[Bottom] = tui.D(0, buf.Height()-bottomHeight, buf.Width(), bottomHeight)
|
||||||
view.Draw(buf.Sub(0, buf.Height()-bottomHeight, buf.Width(), bottomHeight))
|
view.Draw(buf.Sub(0, buf.Height()-bottomHeight, buf.Width(), bottomHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
|||||||
leftWidth = int(float64(buf.Width()) * float64(leftWidth) / float64(horizontalLayout.Sum.Width))
|
leftWidth = int(float64(buf.Width()) * float64(leftWidth) / float64(horizontalLayout.Sum.Width))
|
||||||
}
|
}
|
||||||
|
|
||||||
g.viewDimensions[Left] = tui.D(0, topHeight, leftWidth, buf.Height()-topHeight-bottomHeight)
|
g.ViewDimensions[Left] = tui.D(0, topHeight, leftWidth, buf.Height()-topHeight-bottomHeight)
|
||||||
view.Draw(buf.Sub(0, topHeight, leftWidth, buf.Height()-topHeight-bottomHeight))
|
view.Draw(buf.Sub(0, topHeight, leftWidth, buf.Height()-topHeight-bottomHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,12 +118,12 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
|||||||
rightWidth = int(float64(buf.Width()) * float64(rightWidth) / float64(horizontalLayout.Sum.Width))
|
rightWidth = int(float64(buf.Width()) * float64(rightWidth) / float64(horizontalLayout.Sum.Width))
|
||||||
}
|
}
|
||||||
|
|
||||||
g.viewDimensions[Right] = tui.D(buf.Width()-rightWidth, topHeight, rightWidth, buf.Height()-topHeight-bottomHeight)
|
g.ViewDimensions[Right] = tui.D(buf.Width()-rightWidth, topHeight, rightWidth, buf.Height()-topHeight-bottomHeight)
|
||||||
view.Draw(buf.Sub(buf.Width()-rightWidth, topHeight, rightWidth, buf.Height()-topHeight-bottomHeight))
|
view.Draw(buf.Sub(buf.Width()-rightWidth, topHeight, rightWidth, buf.Height()-topHeight-bottomHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
if view, ok := g.views[Center]; ok {
|
if view, ok := g.views[Center]; ok {
|
||||||
g.viewDimensions[Center] = tui.D(leftWidth, topHeight, buf.Width()-leftWidth-rightWidth, buf.Height()-topHeight-bottomHeight)
|
g.ViewDimensions[Center] = tui.D(leftWidth, topHeight, buf.Width()-leftWidth-rightWidth, buf.Height()-topHeight-bottomHeight)
|
||||||
view.Draw(buf.Sub(leftWidth, topHeight, buf.Width()-leftWidth-rightWidth, buf.Height()-topHeight-bottomHeight))
|
view.Draw(buf.Sub(leftWidth, topHeight, buf.Width()-leftWidth-rightWidth, buf.Height()-topHeight-bottomHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,22 +146,22 @@ func (g *BorderLayout) OnKeyPressed(event *tui.KeyEvent) (consumed bool) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *BorderLayout) OnMouseClicked(event *tui.MouseEvent) (consumed bool) {
|
func (g *BorderLayout) OnMouseEvent(event *tui.MouseEvent) (consumed bool) {
|
||||||
for slot, dim := range g.viewDimensions {
|
for slot, dim := range g.ViewDimensions {
|
||||||
if event.Position.In(dim) {
|
if event.Position.In(dim) {
|
||||||
g.views[slot].OnMouseClicked(event)
|
g.views[slot].OnMouseEvent(event)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type Slot uint8
|
type Slot string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Top Slot = iota
|
Top Slot = "top"
|
||||||
Bottom
|
Bottom Slot = "bottom"
|
||||||
Left
|
Left Slot = "left"
|
||||||
Right
|
Right Slot = "right"
|
||||||
Center
|
Center Slot = "center"
|
||||||
)
|
)
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"git.tordarus.net/Tordarus/tui"
|
"git.tordarus.net/Tordarus/tui"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SeperatorLayout ia a tui.Layout which separates
|
// SeperatorLayout ia a tui.Layout which separates its view into gravity-based portions
|
||||||
type SeperatorLayout struct {
|
type SeperatorLayout struct {
|
||||||
tui.ViewTmpl
|
tui.ViewTmpl
|
||||||
views []tui.View
|
views []tui.View
|
||||||
@ -68,8 +68,8 @@ func (g *SeperatorLayout) RemoveView(v tui.View) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *SeperatorLayout) View(slot Slot) tui.View {
|
func (g *SeperatorLayout) View(index int) tui.View {
|
||||||
return g.views[slot]
|
return g.views[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *SeperatorLayout) Draw(buf *tui.ViewBuffer) {
|
func (g *SeperatorLayout) Draw(buf *tui.ViewBuffer) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package tui
|
package tui
|
||||||
|
|
||||||
type ViewTmpl struct {
|
type ViewTmpl struct {
|
||||||
|
EventTmpl
|
||||||
style *Style
|
style *Style
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,14 +15,6 @@ func (v *ViewTmpl) Layout() (prefWidth, prefHeight int) {
|
|||||||
return -1, -1
|
return -1, -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ViewTmpl) OnKeyPressed(event *KeyEvent) (consumed bool) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ViewTmpl) OnMouseClicked(event *MouseEvent) (consumed bool) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ViewTmpl) SetStyle(s Style) {
|
func (v *ViewTmpl) SetStyle(s Style) {
|
||||||
v.style = &s
|
v.style = &s
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,13 @@ func (v *WrapperTmpl) OnKeyPressed(event *KeyEvent) (consumed bool) {
|
|||||||
return v.ViewTmpl.OnKeyPressed(event)
|
return v.ViewTmpl.OnKeyPressed(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *WrapperTmpl) OnMouseEvent(event *MouseEvent) (consumed bool) {
|
||||||
|
if v.view != nil {
|
||||||
|
return v.view.OnMouseEvent(event)
|
||||||
|
}
|
||||||
|
return v.ViewTmpl.OnMouseEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *WrapperTmpl) SetStyle(s Style) {
|
func (v *WrapperTmpl) SetStyle(s Style) {
|
||||||
v.ViewTmpl.SetStyle(s)
|
v.ViewTmpl.SetStyle(s)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user