1
0
mirror of https://github.com/rivo/tview.git synced 2025-04-26 13:49:06 +08:00

Added suspended mode to Application. (Swallows one key event, tcell issue pending.) Resolves #70

This commit is contained in:
Oliver 2018-03-13 08:16:09 +01:00
parent 7e4958256f
commit 11727c933b

View File

@ -1,6 +1,8 @@
package tview
import (
"fmt"
"os"
"sync"
"github.com/gdamore/tcell"
@ -38,6 +40,9 @@ type Application struct {
// An optional callback function which is invoked after the root primitive
// was drawn.
afterDraw func(screen tcell.Screen)
// If this value is true, the application has entered suspended mode.
suspended bool
}
// NewApplication creates and returns a new application.
@ -98,9 +103,12 @@ func (a *Application) Run() error {
// Start event loop.
for {
a.RLock()
a.Lock()
screen := a.screen
a.RUnlock()
if a.suspended {
a.suspended = false // Clear previous suspended flag.
}
a.Unlock()
if screen == nil {
break
}
@ -108,7 +116,17 @@ func (a *Application) Run() error {
// Wait for next event.
event := a.screen.PollEvent()
if event == nil {
break // The screen was finalized.
a.Lock()
if a.suspended {
// This screen was renewed due to suspended mode.
a.suspended = false
a.Unlock()
continue // Resume.
}
a.Unlock()
// The screen was finalized. Exit the loop.
break
}
switch event := event.(type) {
@ -162,6 +180,57 @@ func (a *Application) Stop() {
a.screen = nil
}
// Suspend temporarily suspends the application by exiting terminal UI mode and
// invoking the provided function "f". When "f" returns, terminal UI mode is
// entered again and the application resumes.
//
// A return value of true indicates that the application was suspended and "f"
// was called. If false is returned, the application was already suspended,
// terminal UI mode was not exited, and "f" was not called.
func (a *Application) Suspend(f func()) bool {
a.Lock()
if a.suspended || a.screen == nil {
// Application is already suspended.
a.Unlock()
return false
}
// Enter suspended mode.
a.suspended = true
a.Unlock()
a.Stop()
// Deal with panics during suspended mode. Exit the program.
defer func() {
if p := recover(); p != nil {
fmt.Println(p)
os.Exit(1)
}
}()
// Wait for "f" to return.
f()
// Make a new screen and redraw.
a.Lock()
var err error
a.screen, err = tcell.NewScreen()
if err != nil {
a.Unlock()
panic(err)
}
if err = a.screen.Init(); err != nil {
a.Unlock()
panic(err)
}
a.Unlock()
a.Draw()
// Continue application loop.
return true
}
// Draw refreshes the screen. It calls the Draw() function of the application's
// root primitive and then syncs the screen buffer.
func (a *Application) Draw() *Application {