Merge branch 'add-synchronization-channels' of https://github.com/3cb/tview into 3cb-add-synchronization-channels

pull/177/head
Oliver 6 years ago
commit d830c42f6b

@ -46,11 +46,20 @@ type Application struct {
// Halts the event loop during suspended mode.
suspendMutex sync.Mutex
// Used to send screen events from separate goroutine to main event loop
events chan tcell.Event
// Used to send primitive updates from separate goroutines to the main event loop
updates chan func()
}
// NewApplication creates and returns a new application.
func NewApplication() *Application {
return &Application{}
return &Application{
events: make(chan tcell.Event, 100),
updates: make(chan func(), 100),
}
}
// SetInputCapture sets a function which captures all key events before they are
@ -136,7 +145,8 @@ func (a *Application) Run() error {
a.Unlock()
a.Draw()
// Start event loop.
// Separate loop to wait for screen events
go func() {
for {
// Do not poll events during suspend mode
a.suspendMutex.Lock()
@ -145,15 +155,25 @@ func (a *Application) Run() error {
a.RUnlock()
if screen == nil {
a.suspendMutex.Unlock()
// send signal to stop main event loop
a.QueueEvent(nil)
break
}
// Wait for next event.
event := a.screen.PollEvent()
a.QueueEvent(screen.PollEvent())
a.suspendMutex.Unlock()
}
}()
// Start event loop.
loop:
for {
select {
case event := <-a.events:
if event == nil {
// The screen was finalized. Exit the loop.
break
break loop
}
switch event := event.(type) {
@ -166,7 +186,7 @@ func (a *Application) Run() error {
if a.inputCapture != nil {
event = a.inputCapture(event)
if event == nil {
break // Don't forward event.
break loop // Don't forward event.
}
}
@ -191,6 +211,12 @@ func (a *Application) Run() error {
screen.Clear()
a.Draw()
}
case updater := <-a.updates:
updater()
a.Draw()
}
}
return nil
@ -404,3 +430,15 @@ func (a *Application) GetFocus() Primitive {
defer a.RUnlock()
return a.focus
}
// QueueUpdate is used to synchronize changes to primitives by carrying an update function from separate goroutine to the Application event loop via channel
func (a *Application) QueueUpdate(f func()) *Application {
a.updates <- f
return a
}
// QueueEvent takes an Event instance and sends it to the Application event loop via channel
func (a *Application) QueueEvent(e tcell.Event) *Application {
a.events <- e
return a
}

Loading…
Cancel
Save