Fix dropdown mouse capture behavior

This commit is contained in:
Trevor Slocum 2020-01-04 21:43:26 -08:00
parent a8fe476d77
commit 6d9b735867
4 changed files with 43 additions and 8 deletions

View File

@ -1,3 +1,6 @@
v0.2.2 (WIP)
- Fix dropdown mouse capture behavior
v0.2.1 (2020-01-01)
- Add initial mouse support (some widgets are unsupported)
- Add window size change handler

View File

@ -85,6 +85,9 @@ type Application struct {
// be forwarded).
mouseCapture func(event *EventMouse) *EventMouse
// A temporary capture function overriding the above.
tempMouseCapture func(event *EventMouse) *EventMouse
lastMouseX, lastMouseY int
lastMouseBtn tcell.ButtonMask
lastMouseTarget Primitive // nil if none
@ -124,7 +127,9 @@ func (a *Application) GetInputCapture() func(event *tcell.EventKey) *tcell.Event
// choose to forward that event (or a different one) by returning it or stop
// the event processing by returning nil.
func (a *Application) SetMouseCapture(capture func(event *EventMouse) *EventMouse) *Application {
a.Lock()
a.mouseCapture = capture
a.Unlock()
return a
}
@ -134,6 +139,22 @@ func (a *Application) GetMouseCapture() func(event *EventMouse) *EventMouse {
return a.mouseCapture
}
// SetTemporaryMouseCapture temporarily overrides the normal capture function.
// Calling this function from anywhere other than a widget may result in
// unexpected behavior.
func (a *Application) SetTemporaryMouseCapture(capture func(event *EventMouse) *EventMouse) *Application {
a.Lock()
a.tempMouseCapture = capture
a.Unlock()
return a
}
// GetTemporaryMouseCapture returns the function installed with
// SetTemporaryMouseCapture() or nil if no such function has been installed.
func (a *Application) GetTemporaryMouseCapture() func(event *EventMouse) *EventMouse {
return a.tempMouseCapture
}
// SetScreen allows you to provide your own tcell.Screen object. For most
// applications, this is not needed and you should be familiar with
// tcell.Screen when using this function.
@ -263,6 +284,7 @@ EventLoop:
p := a.focus
inputCapture := a.inputCapture
mouseCapture := a.mouseCapture
tempMouseCapture := a.tempMouseCapture
screen := a.screen
root := a.root
a.RUnlock()
@ -373,6 +395,13 @@ EventLoop:
event2 := NewEventMouse(event, ptarget, a, act)
// Intercept event.
if tempMouseCapture != nil {
event2 = tempMouseCapture(event2)
if event2 == nil {
a.draw()
continue // Don't forward event.
}
}
if mouseCapture != nil {
event2 = mouseCapture(event2)
if event2 == nil {

View File

@ -108,7 +108,7 @@ func main() {
app.SetMouseCapture(func(event *cview.EventMouse) *cview.EventMouse {
atX, atY := event.Position()
if event.Action()&cview.MouseClick != 0 && atY == screenHeight-1 {
if event.Action()&cview.MouseDown != 0 && atY == screenHeight-1 {
slideClicked := -1
for i, region := range slideRegions {
if atX >= region {

View File

@ -440,7 +440,7 @@ func (d *DropDown) openList(setFocus func(Primitive), app *Application) {
d.list.SetSelectedFunc(func(index int, mainText, secondaryText string, shortcut rune) {
// An option was selected. Close the list again.
d.currentOption = index
d.closeList(setFocus)
d.closeList(setFocus, app)
// Trigger "selected" event.
if d.selected != nil {
@ -461,14 +461,14 @@ func (d *DropDown) openList(setFocus func(Primitive), app *Application) {
d.evalPrefix()
} else if event.Key() == tcell.KeyEscape {
d.currentOption = optionBefore
d.closeList(setFocus)
d.closeList(setFocus, app)
} else {
d.prefix = ""
}
return event
})
if app != nil {
app.SetMouseCapture(func(event *EventMouse) *EventMouse {
app.SetTemporaryMouseCapture(func(event *EventMouse) *EventMouse {
if d.open {
// Forward the mouse event to the list.
atX, atY := event.Position()
@ -490,8 +490,7 @@ func (d *DropDown) openList(setFocus func(Primitive), app *Application) {
// Mouse not within the list.
if event.Action()&MouseDown != 0 {
// If a mouse button was pressed, cancel this capture.
app.SetMouseCapture(nil)
d.closeList(event.SetFocus)
d.closeList(event.SetFocus, app)
}
}
}
@ -501,7 +500,11 @@ func (d *DropDown) openList(setFocus func(Primitive), app *Application) {
setFocus(d.list)
}
func (d *DropDown) closeList(setFocus func(Primitive)) {
func (d *DropDown) closeList(setFocus func(Primitive), app *Application) {
if app != nil {
app.SetTemporaryMouseCapture(nil)
}
d.open = false
if d.list.HasFocus() {
setFocus(d)
@ -532,7 +535,7 @@ func (d *DropDown) MouseHandler() func(event *EventMouse) {
//d.open = !d.open
//event.SetFocus(d)
if d.open {
d.closeList(event.SetFocus)
d.closeList(event.SetFocus, event.Application())
} else {
d.openList(event.SetFocus, event.Application())
}