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
|
||||
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
|
||||
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 {
|
||||
EventTmpl
|
||||
|
||||
scr tcell.Screen
|
||||
buf *ViewBuffer
|
||||
|
||||
@ -17,12 +19,6 @@ type Screen struct {
|
||||
|
||||
// Root is the root view which is currently shown on screen
|
||||
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) {
|
||||
@ -72,9 +68,10 @@ func (s *Screen) onKeyPressed(event *KeyEvent) {
|
||||
s.Redraw()
|
||||
}
|
||||
|
||||
func (s *Screen) onMouseClicked(event *MouseEvent) {
|
||||
if s.MouseClicked == nil || !s.MouseClicked(event) {
|
||||
go s.Root.OnMouseClicked(event)
|
||||
func (s *Screen) onMouseEvent(event *MouseEvent) {
|
||||
if s.MouseEvent == nil || !s.MouseEvent(event) {
|
||||
go s.Root.OnMouseEvent(event)
|
||||
// TODO redraw in same thread
|
||||
}
|
||||
if event.Button != MouseButtonNone {
|
||||
s.Redraw()
|
||||
@ -104,7 +101,7 @@ func (s *Screen) eventloop() {
|
||||
case *tcell.EventKey:
|
||||
s.onKeyPressed(event)
|
||||
case *tcell.EventMouse:
|
||||
s.onMouseClicked(convertMouseEvent(event))
|
||||
s.onMouseEvent(convertMouseEvent(event))
|
||||
default:
|
||||
s.StopWithError(fmt.Errorf("%#v", event))
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.tordarus.net/Tordarus/tui"
|
||||
@ -61,7 +62,7 @@ func TestScrollView(t *testing.T) {
|
||||
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[1].(*views.TextView).Text = fmt.Sprintf("mouse button: %d", event.Button)
|
||||
|
||||
@ -123,7 +124,7 @@ func TestMousePosition(t *testing.T) {
|
||||
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())
|
||||
return true
|
||||
}
|
||||
@ -217,20 +218,58 @@ func TestSeparatorLayout(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))
|
||||
|
||||
bottomView := views.NewConstrainView(nil, 10, 10)
|
||||
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.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.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.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.SetStyle(tui.StyleDefault.Background(tcell.ColorPurple))
|
||||
@ -253,6 +292,23 @@ func TestBorderLayout(t *testing.T) {
|
||||
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()
|
||||
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 {
|
||||
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 {
|
||||
|
@ -11,7 +11,7 @@ type BorderLayout struct {
|
||||
horizontalLayout *LayoutResult
|
||||
verticalLayout *LayoutResult
|
||||
|
||||
viewDimensions map[Slot]tui.Dimension
|
||||
ViewDimensions map[Slot]tui.Dimension
|
||||
}
|
||||
|
||||
var _ tui.Layout = &BorderLayout{}
|
||||
@ -19,7 +19,7 @@ var _ tui.Layout = &BorderLayout{}
|
||||
func NewBorderLayout() *BorderLayout {
|
||||
return &BorderLayout{
|
||||
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))
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
||||
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))
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
||||
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))
|
||||
}
|
||||
|
||||
@ -118,12 +118,12 @@ func (g *BorderLayout) Draw(buf *tui.ViewBuffer) {
|
||||
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))
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
@ -146,22 +146,22 @@ func (g *BorderLayout) OnKeyPressed(event *tui.KeyEvent) (consumed bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *BorderLayout) OnMouseClicked(event *tui.MouseEvent) (consumed bool) {
|
||||
for slot, dim := range g.viewDimensions {
|
||||
func (g *BorderLayout) OnMouseEvent(event *tui.MouseEvent) (consumed bool) {
|
||||
for slot, dim := range g.ViewDimensions {
|
||||
if event.Position.In(dim) {
|
||||
g.views[slot].OnMouseClicked(event)
|
||||
g.views[slot].OnMouseEvent(event)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Slot uint8
|
||||
type Slot string
|
||||
|
||||
const (
|
||||
Top Slot = iota
|
||||
Bottom
|
||||
Left
|
||||
Right
|
||||
Center
|
||||
Top Slot = "top"
|
||||
Bottom Slot = "bottom"
|
||||
Left Slot = "left"
|
||||
Right Slot = "right"
|
||||
Center Slot = "center"
|
||||
)
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"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 {
|
||||
tui.ViewTmpl
|
||||
views []tui.View
|
||||
@ -68,8 +68,8 @@ func (g *SeperatorLayout) RemoveView(v tui.View) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *SeperatorLayout) View(slot Slot) tui.View {
|
||||
return g.views[slot]
|
||||
func (g *SeperatorLayout) View(index int) tui.View {
|
||||
return g.views[index]
|
||||
}
|
||||
|
||||
func (g *SeperatorLayout) Draw(buf *tui.ViewBuffer) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package tui
|
||||
|
||||
type ViewTmpl struct {
|
||||
EventTmpl
|
||||
style *Style
|
||||
}
|
||||
|
||||
@ -14,14 +15,6 @@ func (v *ViewTmpl) Layout() (prefWidth, prefHeight int) {
|
||||
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) {
|
||||
v.style = &s
|
||||
}
|
||||
|
@ -29,6 +29,13 @@ func (v *WrapperTmpl) OnKeyPressed(event *KeyEvent) (consumed bool) {
|
||||
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) {
|
||||
v.ViewTmpl.SetStyle(s)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user