Some changes in tui.
This commit is contained in:
parent
b33d5f036c
commit
9e9eb70cd2
15
tui/channel_all.go
Normal file
15
tui/channel_all.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
func (t *TUI) launchAllChannels() error {
|
||||||
|
var err error
|
||||||
|
err = t.launchErrorsChannel()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.errorsChannel <- t.launchInputChannel()
|
||||||
|
t.errorsChannel <- t.launchInputChannel()
|
||||||
|
t.errorsChannel <- t.launchMessageChannel()
|
||||||
|
t.errorsChannel <- t.launchSignalsChannel()
|
||||||
|
t.errorsChannel <- t.launchStateChannel()
|
||||||
|
return nil
|
||||||
|
}
|
17
tui/channel_errors.go
Normal file
17
tui/channel_errors.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import "git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
|
||||||
|
func (t *TUI) launchErrorsChannel() error {
|
||||||
|
if t.errorsChannel == nil {
|
||||||
|
return errors.WrapErr("t.errors", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for err := range t.errorsChannel {
|
||||||
|
if err != nil {
|
||||||
|
t.createNotification(err.Error(), CONST_ERROR_N_TITLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
71
tui/channel_input.go
Normal file
71
tui/channel_input.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *TUI) launchInputChannel() error {
|
||||||
|
if t.inputChannel == nil {
|
||||||
|
return errors.WrapErr("t.inputChannel", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for r := range t.inputChannel {
|
||||||
|
log.Printf("Read rune: %#v from t.input\n", r)
|
||||||
|
selWidget := t.selectedWidget
|
||||||
|
// Enter
|
||||||
|
if r == 13 {
|
||||||
|
log.Printf("Debug: selWidget: %#v ; selWidget.Input: %#v", selWidget, selWidget.Input)
|
||||||
|
if selWidget != nil && selWidget.Input != nil {
|
||||||
|
t.errorsChannel <- selWidget.Handler(t, selWidget.Data)
|
||||||
|
buf := selWidget.Clear()
|
||||||
|
t.writeMu.Lock()
|
||||||
|
err := t.write(buf)
|
||||||
|
t.writeMu.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
t.errorsChannel <- errors.WrapErr("t.write", err)
|
||||||
|
}
|
||||||
|
if selWidget.Next != nil {
|
||||||
|
log.Printf("Seeing that widget.Next is not nil")
|
||||||
|
t.errorsChannel <- t.addWidget(*selWidget.Next)
|
||||||
|
t.errorsChannel <- t.drawSelectedWidget()
|
||||||
|
} else {
|
||||||
|
t.readInputState <- false
|
||||||
|
}
|
||||||
|
if selWidget.Finale != nil {
|
||||||
|
log.Printf("Seeing that widget.Finale is not nil")
|
||||||
|
t.errorsChannel <- selWidget.Finale(t, selWidget.FinaleData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if r == 127 {
|
||||||
|
log.Printf("seeing r = 127")
|
||||||
|
sliceLen := len(*selWidget.Input)
|
||||||
|
log.Printf("sliceLen = %d\n", sliceLen)
|
||||||
|
if sliceLen > 0 {
|
||||||
|
log.Printf("sliceLen > 0")
|
||||||
|
*selWidget.Input = (*selWidget.Input)[:sliceLen-1]
|
||||||
|
t.writeMu.Lock()
|
||||||
|
t.errorsChannel <- t.moveCursor(t.cursorPosRow, t.cursorPosCol-1)
|
||||||
|
t.errorsChannel <- t.writeRune(' ')
|
||||||
|
t.errorsChannel <- t.moveCursor(t.cursorPosRow, t.cursorPosCol-1)
|
||||||
|
t.writeMu.Unlock()
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if selWidget != nil && selWidget.Input != nil {
|
||||||
|
log.Printf("t.input: append %#v to widget input\n", r)
|
||||||
|
*selWidget.Input = append(*selWidget.Input, r)
|
||||||
|
log.Printf("t.input: trying to write %#v", r)
|
||||||
|
t.writeMu.Lock()
|
||||||
|
err := t.writeRune(r)
|
||||||
|
t.writeMu.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
t.errorsChannel <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
37
tui/channel_message.go
Normal file
37
tui/channel_message.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.qowevisa.me/Qowevisa/gotell/communication"
|
||||||
|
"git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Basically every X_channel.go file launches some sort of channel
|
||||||
|
|
||||||
|
func (t *TUI) launchMessageChannel() error {
|
||||||
|
if t.messageChannel == nil {
|
||||||
|
return errors.WrapErr("t.messageChannel", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for message := range t.messageChannel {
|
||||||
|
t.createNotification(string(message), "Message!")
|
||||||
|
msg, err := communication.Decode(message)
|
||||||
|
t.errorsChannel <- err
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch msg.Type {
|
||||||
|
case communication.SERVER_COMMAND:
|
||||||
|
t.handleServerCommands(msg.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TUI) handleServerCommands(data []byte) {
|
||||||
|
if len(data) == 1 {
|
||||||
|
if data[0] == communication.NICKNAME {
|
||||||
|
t.SendMessageToServer("Nickname", 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
tui/channel_signals.go
Normal file
24
tui/channel_signals.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *TUI) launchSignalsChannel() error {
|
||||||
|
if t.osSignals == nil {
|
||||||
|
return errors.WrapErr("t.osSignals", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for sig := range t.osSignals {
|
||||||
|
log.Printf("Receive OS.signal: %#v\n", sig)
|
||||||
|
switch sig {
|
||||||
|
case syscall.SIGWINCH:
|
||||||
|
t.errorsChannel <- t.redraw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
21
tui/channel_state.go
Normal file
21
tui/channel_state.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import "git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
|
||||||
|
func (t *TUI) launchStateChannel() error {
|
||||||
|
if t.stateChannel == nil {
|
||||||
|
return errors.WrapErr("t.stateChannel", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for state := range t.stateChannel {
|
||||||
|
t.writeMu.Lock()
|
||||||
|
oldRow, oldCol := t.getCursorPos()
|
||||||
|
t.errorsChannel <- t.moveCursor(t.height, len(footerStart)+1)
|
||||||
|
t._clearLine()
|
||||||
|
t.errorsChannel <- t.write(state)
|
||||||
|
t.errorsChannel <- t.moveCursor(oldRow, oldCol)
|
||||||
|
t.writeMu.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -5,6 +5,10 @@ const (
|
||||||
MY_SIGNAL_MESSAGE
|
MY_SIGNAL_MESSAGE
|
||||||
MY_SIGNAL_CONNECT
|
MY_SIGNAL_CONNECT
|
||||||
MY_SIGNAL_CLOSE
|
MY_SIGNAL_CLOSE
|
||||||
|
MY_SIGNAL_MOVE_CURSOR_UP
|
||||||
|
MY_SIGNAL_MOVE_CURSOR_DOWN
|
||||||
|
MY_SIGNAL_MOVE_CURSOR_LEFT
|
||||||
|
MY_SIGNAL_MOVE_CURSOR_RIGHT
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,8 +26,8 @@ const (
|
||||||
footerStart = "State: "
|
footerStart = "State: "
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *cursorPosConfigValue) isGeneral() bool {
|
func (c cursorPosConfigValue) isGeneral() bool {
|
||||||
switch *c {
|
switch c {
|
||||||
case cursorPosGeneralCenter:
|
case cursorPosGeneralCenter:
|
||||||
return true
|
return true
|
||||||
case cursorPosGeneralLeft:
|
case cursorPosGeneralLeft:
|
||||||
|
@ -40,8 +44,8 @@ const (
|
||||||
widgetPosGeneralRightCenter widgetPosConfigValue = -3
|
widgetPosGeneralRightCenter widgetPosConfigValue = -3
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *widgetPosConfigValue) isGeneral() bool {
|
func (w widgetPosConfigValue) isGeneral() bool {
|
||||||
switch *w {
|
switch w {
|
||||||
case widgetPosGeneralCenter:
|
case widgetPosGeneralCenter:
|
||||||
return true
|
return true
|
||||||
case widgetPosGeneralLeftCenter:
|
case widgetPosGeneralLeftCenter:
|
||||||
|
|
|
@ -15,7 +15,7 @@ func (t *TUI) launchReadingMessagesFromConnection(ctx context.Context, wg *sync.
|
||||||
defer wg.Done() // Mark this goroutine as done when it exits
|
defer wg.Done() // Mark this goroutine as done when it exits
|
||||||
|
|
||||||
if t.messageChannel == nil {
|
if t.messageChannel == nil {
|
||||||
t.errors <- errors.WrapErr("t.messageChannel", errors.NOT_INIT)
|
t.errorsChannel <- errors.WrapErr("t.messageChannel", errors.NOT_INIT)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf := make([]byte, CONST_MESSAGE_LEN)
|
buf := make([]byte, CONST_MESSAGE_LEN)
|
||||||
|
@ -27,7 +27,7 @@ func (t *TUI) launchReadingMessagesFromConnection(ctx context.Context, wg *sync.
|
||||||
timeoutDuration := 5 * time.Second
|
timeoutDuration := 5 * time.Second
|
||||||
err := t.tlsConnection.SetReadDeadline(time.Now().Add(timeoutDuration))
|
err := t.tlsConnection.SetReadDeadline(time.Now().Add(timeoutDuration))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.errors <- errors.WrapErr("SetReadDeadline", err)
|
t.errorsChannel <- errors.WrapErr("SetReadDeadline", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err := t.tlsConnection.Read(buf)
|
n, err := t.tlsConnection.Read(buf)
|
||||||
|
@ -36,7 +36,7 @@ func (t *TUI) launchReadingMessagesFromConnection(ctx context.Context, wg *sync.
|
||||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.errors <- errors.WrapErr("t.tlsConnection.Read", err)
|
t.errorsChannel <- errors.WrapErr("t.tlsConnection.Read", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
16
tui/types.go
16
tui/types.go
|
@ -60,6 +60,15 @@ type notifier struct {
|
||||||
Buf string
|
Buf string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dialog struct {
|
||||||
|
Row int
|
||||||
|
Col int
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
Buf string
|
||||||
|
Catcher RuneCatcher
|
||||||
|
}
|
||||||
|
|
||||||
type widgetDraw struct {
|
type widgetDraw struct {
|
||||||
Buf string
|
Buf string
|
||||||
Row int
|
Row int
|
||||||
|
@ -89,6 +98,8 @@ type closeData struct {
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RuneCatcher func(runes chan (rune)) error
|
||||||
|
|
||||||
type TUI struct {
|
type TUI struct {
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
|
@ -97,11 +108,12 @@ type TUI struct {
|
||||||
writeMu sync.Mutex
|
writeMu sync.Mutex
|
||||||
sizeMutex sync.Mutex
|
sizeMutex sync.Mutex
|
||||||
oldState *term.State
|
oldState *term.State
|
||||||
input chan (rune)
|
inputChannel chan (rune)
|
||||||
|
inputCatcher RuneCatcher
|
||||||
printRunes chan (rune)
|
printRunes chan (rune)
|
||||||
mySignals chan (mySignal)
|
mySignals chan (mySignal)
|
||||||
osSignals chan (os.Signal)
|
osSignals chan (os.Signal)
|
||||||
errors chan (error)
|
errorsChannel chan (error)
|
||||||
readInputState chan (bool)
|
readInputState chan (bool)
|
||||||
readEnterState chan (bool)
|
readEnterState chan (bool)
|
||||||
stateChannel chan (string)
|
stateChannel chan (string)
|
||||||
|
|
159
tui/ui.go
159
tui/ui.go
|
@ -17,10 +17,10 @@ import (
|
||||||
|
|
||||||
func (t *TUI) init() error {
|
func (t *TUI) init() error {
|
||||||
var err error
|
var err error
|
||||||
t.input = make(chan rune, 32)
|
t.inputChannel = make(chan rune, 32)
|
||||||
t.printRunes = make(chan rune, 32)
|
t.printRunes = make(chan rune, 32)
|
||||||
t.widgets = make([]*widget, 8)
|
t.widgets = make([]*widget, 8)
|
||||||
t.errors = make(chan error, 4)
|
t.errorsChannel = make(chan error, 4)
|
||||||
t.mySignals = make(chan mySignal, 1)
|
t.mySignals = make(chan mySignal, 1)
|
||||||
t.osSignals = make(chan os.Signal, 1)
|
t.osSignals = make(chan os.Signal, 1)
|
||||||
t.writer = bufio.NewWriter(os.Stdout)
|
t.writer = bufio.NewWriter(os.Stdout)
|
||||||
|
@ -46,6 +46,10 @@ func (t *TUI) init() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WrapErr("t.readRoutines", err)
|
return errors.WrapErr("t.readRoutines", err)
|
||||||
}
|
}
|
||||||
|
err = t.launchAllChannels()
|
||||||
|
if err != nil {
|
||||||
|
return errors.WrapErr("t.launchAllChannels", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +68,7 @@ func (t *TUI) Run() error {
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if t.mySignals == nil {
|
if t.mySignals == nil {
|
||||||
return errors.WrapErr("t.signals", errors.NOT_INIT)
|
return errors.WrapErr("t.mySignals", errors.NOT_INIT)
|
||||||
}
|
}
|
||||||
err = t.Draw()
|
err = t.Draw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -73,8 +77,8 @@ func (t *TUI) Run() error {
|
||||||
for mySignal := range t.mySignals {
|
for mySignal := range t.mySignals {
|
||||||
log.Printf("Receive signal: %#v\n", mySignal)
|
log.Printf("Receive signal: %#v\n", mySignal)
|
||||||
if mySignal.Type == MY_SIGNAL_EXIT {
|
if mySignal.Type == MY_SIGNAL_EXIT {
|
||||||
t.errors <- t.clearScreen()
|
t.errorsChannel <- t.clearScreen()
|
||||||
t.errors <- t.moveCursor(0, 0)
|
t.errorsChannel <- t.moveCursor(0, 0)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch mySignal.Type {
|
switch mySignal.Type {
|
||||||
|
@ -108,43 +112,23 @@ func (t *TUI) Run() error {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.errors <- errors.WrapErr("t.addWidget", err)
|
t.errorsChannel <- errors.WrapErr("t.addWidget", err)
|
||||||
}
|
}
|
||||||
err = t.drawSelectedWidget()
|
err = t.drawSelectedWidget()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.errors <- errors.WrapErr("t.drawSelectedWidget", err)
|
t.errorsChannel <- errors.WrapErr("t.drawSelectedWidget", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case MY_SIGNAL_MESSAGE:
|
case MY_SIGNAL_MESSAGE:
|
||||||
if t.isConnected {
|
if t.isConnected {
|
||||||
var msg []rune
|
t.SendMessageToServer("Message", 20)
|
||||||
h, d := SendMessageToConnectionEasy(&msg)
|
|
||||||
err := t.addWidget(widgetConfig{
|
|
||||||
Input: &msg,
|
|
||||||
Title: "Message",
|
|
||||||
MinWidth: 20,
|
|
||||||
HasBorder: true,
|
|
||||||
WidgetPosConfig: widgetPosGeneralCenter,
|
|
||||||
CursorPosConfig: cursorPosGeneralCenter,
|
|
||||||
DataHandler: h,
|
|
||||||
Data: d,
|
|
||||||
Next: nil,
|
|
||||||
Finale: nil,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.errors <- errors.WrapErr("t.addWidget", err)
|
|
||||||
}
|
|
||||||
err = t.drawSelectedWidget()
|
|
||||||
if err != nil {
|
|
||||||
t.errors <- errors.WrapErr("t.drawSelectedWidget", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case MY_SIGNAL_CLOSE:
|
case MY_SIGNAL_CLOSE:
|
||||||
if t.isConnected {
|
if t.isConnected {
|
||||||
CloseConnection(t.tlsConnCloseData.wg, t.tlsConnCloseData.cancel)
|
CloseConnection(t.tlsConnCloseData.wg, t.tlsConnCloseData.cancel)
|
||||||
t.isConnected = false
|
t.isConnected = false
|
||||||
t.errors <- t.tlsConnection.Close()
|
t.errorsChannel <- t.tlsConnection.Close()
|
||||||
t.stateChannel <- "Disconnected"
|
t.stateChannel <- "Disconnected"
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -157,23 +141,13 @@ func (t *TUI) Run() error {
|
||||||
func (t *TUI) createNotification(text, title string) {
|
func (t *TUI) createNotification(text, title string) {
|
||||||
notifier, err := createNotification(text, title)
|
notifier, err := createNotification(text, title)
|
||||||
t.selectedNotifier = ¬ifier
|
t.selectedNotifier = ¬ifier
|
||||||
t.errors <- err
|
t.errorsChannel <- err
|
||||||
t.errors <- t.write(notifier.Buf)
|
t.errorsChannel <- t.write(notifier.Buf)
|
||||||
t.readEnterState <- true
|
t.readEnterState <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TUI) setRoutines() error {
|
func (t *TUI) setRoutines() error {
|
||||||
if t.errors == nil {
|
if t.inputChannel == nil {
|
||||||
return errors.WrapErr("t.errors", errors.NOT_INIT)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for err := range t.errors {
|
|
||||||
if err != nil {
|
|
||||||
t.createNotification(err.Error(), CONST_ERROR_N_TITLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if t.input == nil {
|
|
||||||
return errors.WrapErr("t.input", errors.NOT_INIT)
|
return errors.WrapErr("t.input", errors.NOT_INIT)
|
||||||
}
|
}
|
||||||
if t.oldState == nil {
|
if t.oldState == nil {
|
||||||
|
@ -191,22 +165,6 @@ func (t *TUI) setRoutines() error {
|
||||||
if t.messageChannel == nil {
|
if t.messageChannel == nil {
|
||||||
return errors.WrapErr("t.messageChannel", errors.NOT_INIT)
|
return errors.WrapErr("t.messageChannel", errors.NOT_INIT)
|
||||||
}
|
}
|
||||||
go func() {
|
|
||||||
for message := range t.messageChannel {
|
|
||||||
t.createNotification(string(message), "Message!")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
for state := range t.stateChannel {
|
|
||||||
t.writeMu.Lock()
|
|
||||||
oldRow, oldCol := t.getCursorPos()
|
|
||||||
t.errors <- t.moveCursor(t.height, len(footerStart)+1)
|
|
||||||
t._clearLine()
|
|
||||||
t.errors <- t.write(state)
|
|
||||||
t.errors <- t.moveCursor(oldRow, oldCol)
|
|
||||||
t.writeMu.Unlock()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
var readInputMu sync.Mutex
|
var readInputMu sync.Mutex
|
||||||
var readEnterdMu sync.Mutex
|
var readEnterdMu sync.Mutex
|
||||||
readInput := false
|
readInput := false
|
||||||
|
@ -239,7 +197,7 @@ func (t *TUI) setRoutines() error {
|
||||||
if r == 13 {
|
if r == 13 {
|
||||||
readEnter = false
|
readEnter = false
|
||||||
if t.selectedNotifier != nil {
|
if t.selectedNotifier != nil {
|
||||||
t.errors <- t.write(t.selectedNotifier.Clear())
|
t.errorsChannel <- t.write(t.selectedNotifier.Clear())
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -298,101 +256,26 @@ func (t *TUI) setRoutines() error {
|
||||||
} else {
|
} else {
|
||||||
if readInput {
|
if readInput {
|
||||||
log.Printf("Send %c | %d to t.input", r, r)
|
log.Printf("Send %c | %d to t.input", r, r)
|
||||||
t.input <- r
|
t.inputChannel <- r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readInputMu.Lock()
|
readInputMu.Lock()
|
||||||
if readInput {
|
if readInput {
|
||||||
switch r {
|
switch r {
|
||||||
case 13:
|
case 13:
|
||||||
t.input <- r
|
t.inputChannel <- r
|
||||||
case 127:
|
case 127:
|
||||||
t.input <- r
|
t.inputChannel <- r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readInputMu.Unlock()
|
readInputMu.Unlock()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
//
|
//
|
||||||
if t.osSignals == nil {
|
|
||||||
return errors.WrapErr("t.osSignals", errors.NOT_INIT)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for sig := range t.osSignals {
|
|
||||||
log.Printf("Receive OS.signal: %#v\n", sig)
|
|
||||||
switch sig {
|
|
||||||
case syscall.SIGWINCH:
|
|
||||||
t.errors <- t.redraw()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if t.input == nil {
|
|
||||||
return errors.WrapErr("t.input", errors.NOT_INIT)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for r := range t.input {
|
|
||||||
log.Printf("Read rune: %#v from t.input\n", r)
|
|
||||||
selWidget := t.selectedWidget
|
|
||||||
// Enter
|
|
||||||
if r == 13 {
|
|
||||||
log.Printf("Debug: selWidget: %#v ; selWidget.Input: %#v", selWidget, selWidget.Input)
|
|
||||||
if selWidget != nil && selWidget.Input != nil {
|
|
||||||
t.errors <- selWidget.Handler(t, selWidget.Data)
|
|
||||||
buf := selWidget.Clear()
|
|
||||||
t.writeMu.Lock()
|
|
||||||
err := t.write(buf)
|
|
||||||
t.writeMu.Unlock()
|
|
||||||
if err != nil {
|
|
||||||
t.errors <- errors.WrapErr("t.write", err)
|
|
||||||
}
|
|
||||||
if selWidget.Next != nil {
|
|
||||||
log.Printf("Seeing that widget.Next is not nil")
|
|
||||||
t.errors <- t.addWidget(*selWidget.Next)
|
|
||||||
t.errors <- t.drawSelectedWidget()
|
|
||||||
} else {
|
|
||||||
t.readInputState <- false
|
|
||||||
}
|
|
||||||
if selWidget.Finale != nil {
|
|
||||||
log.Printf("Seeing that widget.Finale is not nil")
|
|
||||||
t.errors <- selWidget.Finale(t, selWidget.FinaleData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
} else if r == 127 {
|
|
||||||
log.Printf("seeing r = 127")
|
|
||||||
sliceLen := len(*selWidget.Input)
|
|
||||||
log.Printf("sliceLen = %d\n", sliceLen)
|
|
||||||
if sliceLen > 0 {
|
|
||||||
log.Printf("sliceLen > 0")
|
|
||||||
*selWidget.Input = (*selWidget.Input)[:sliceLen-1]
|
|
||||||
t.writeMu.Lock()
|
|
||||||
t.errors <- t.moveCursor(t.cursorPosRow, t.cursorPosCol-1)
|
|
||||||
t.errors <- t.writeRune(' ')
|
|
||||||
t.errors <- t.moveCursor(t.cursorPosRow, t.cursorPosCol-1)
|
|
||||||
t.writeMu.Unlock()
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if selWidget != nil && selWidget.Input != nil {
|
|
||||||
log.Printf("t.input: append %#v to widget input\n", r)
|
|
||||||
*selWidget.Input = append(*selWidget.Input, r)
|
|
||||||
log.Printf("t.input: trying to write %#v", r)
|
|
||||||
t.writeMu.Lock()
|
|
||||||
err := t.writeRune(r)
|
|
||||||
t.writeMu.Unlock()
|
|
||||||
if err != nil {
|
|
||||||
t.errors <- err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TUI) readRoutines() error {
|
func (t *TUI) readRoutines() error {
|
||||||
if t.input == nil {
|
|
||||||
return errors.WrapErr("t.input", errors.NOT_INIT)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +340,7 @@ func (t *TUI) getCursorPos() (int, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TUI) _clearLine() {
|
func (t *TUI) _clearLine() {
|
||||||
t.errors <- t.write("\033[0K")
|
t.errorsChannel <- t.write("\033[0K")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TUI) moveCursor(row, col int) error {
|
func (t *TUI) moveCursor(row, col int) error {
|
||||||
|
|
27
tui/util.go
Normal file
27
tui/util.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import "git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
|
||||||
|
func (t *TUI) SendMessageToServer(title string, minW int) {
|
||||||
|
var msg []rune
|
||||||
|
h, d := SendMessageToConnectionEasy(&msg)
|
||||||
|
err := t.addWidget(widgetConfig{
|
||||||
|
Input: &msg,
|
||||||
|
Title: title,
|
||||||
|
MinWidth: minW,
|
||||||
|
HasBorder: true,
|
||||||
|
WidgetPosConfig: widgetPosGeneralCenter,
|
||||||
|
CursorPosConfig: cursorPosGeneralCenter,
|
||||||
|
DataHandler: h,
|
||||||
|
Data: d,
|
||||||
|
Next: nil,
|
||||||
|
Finale: nil,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.errorsChannel <- errors.WrapErr("t.addWidget", err)
|
||||||
|
}
|
||||||
|
err = t.drawSelectedWidget()
|
||||||
|
if err != nil {
|
||||||
|
t.errorsChannel <- errors.WrapErr("t.drawSelectedWidget", err)
|
||||||
|
}
|
||||||
|
}
|
125
tui/widget_dialog.go
Normal file
125
tui/widget_dialog.go
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.qowevisa.me/Qowevisa/gotell/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createDialog(message, title string) (dialog, error) {
|
||||||
|
var buf string
|
||||||
|
width, height := UI.getSizes()
|
||||||
|
if width == 0 {
|
||||||
|
return dialog{}, errors.WrapErr("width", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
if height == 0 {
|
||||||
|
return dialog{}, errors.WrapErr("height", errors.NOT_INIT)
|
||||||
|
}
|
||||||
|
maxWidth := width / 3
|
||||||
|
maxHeight := 5
|
||||||
|
errMsgLen := len(message)
|
||||||
|
innerPart := maxWidth - 2
|
||||||
|
if errMsgLen <= innerPart {
|
||||||
|
maxWidth = errMsgLen + 2
|
||||||
|
} else {
|
||||||
|
for {
|
||||||
|
if errMsgLen <= innerPart {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
maxHeight++
|
||||||
|
errMsgLen -= innerPart
|
||||||
|
}
|
||||||
|
}
|
||||||
|
innerPart = maxWidth - 2
|
||||||
|
col := (width - maxWidth) / 2
|
||||||
|
row := (height - maxHeight) / 2
|
||||||
|
startCol := col
|
||||||
|
startRow := row
|
||||||
|
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
buf += strings.Repeat("-", maxWidth)
|
||||||
|
|
||||||
|
row++
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
buf += centerText(maxWidth, title)
|
||||||
|
|
||||||
|
row++
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
buf += strings.Repeat("-", maxWidth)
|
||||||
|
|
||||||
|
startI := 0
|
||||||
|
endI := innerPart
|
||||||
|
for i := 3; i < maxHeight-1; i++ {
|
||||||
|
var tmp string
|
||||||
|
if endI > len(message) {
|
||||||
|
tmp = message[startI:]
|
||||||
|
} else {
|
||||||
|
tmp = message[startI:endI]
|
||||||
|
}
|
||||||
|
row++
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
var spaces string
|
||||||
|
if innerPart > len(tmp) {
|
||||||
|
spaces = strings.Repeat(" ", innerPart-len(tmp))
|
||||||
|
}
|
||||||
|
buf += fmt.Sprintf("|%s%s|", tmp, spaces)
|
||||||
|
startI += innerPart
|
||||||
|
endI += innerPart
|
||||||
|
}
|
||||||
|
|
||||||
|
row++
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
buf += strings.Repeat("-", maxWidth)
|
||||||
|
|
||||||
|
row++
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
buf += centerText(maxWidth, "YES | NO")
|
||||||
|
|
||||||
|
row++
|
||||||
|
buf += getBufForMovingCursorTo(row, col)
|
||||||
|
buf += strings.Repeat("-", maxWidth)
|
||||||
|
return dialog{
|
||||||
|
Row: startRow,
|
||||||
|
Col: startCol,
|
||||||
|
Width: maxWidth,
|
||||||
|
Height: row - startRow + 1,
|
||||||
|
Buf: buf,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
_int_CatcherNone = iota
|
||||||
|
_int_Catcher1Arrow
|
||||||
|
_int_Catcher2Arrow
|
||||||
|
_int_CatcherArrow
|
||||||
|
)
|
||||||
|
|
||||||
|
func dialogRuneCatcher(t *TUI, runes chan (rune)) error {
|
||||||
|
state := _int_CatcherNone
|
||||||
|
for r := range runes {
|
||||||
|
if r == 27 && state == _int_CatcherNone {
|
||||||
|
state = _int_Catcher1Arrow
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if r == 91 && state == _int_Catcher1Arrow {
|
||||||
|
state = _int_Catcher2Arrow
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if state == _int_Catcher2Arrow {
|
||||||
|
switch r {
|
||||||
|
case 65:
|
||||||
|
t.mySignals <- mySignal{Type: MY_SIGNAL_MOVE_CURSOR_UP}
|
||||||
|
case 66:
|
||||||
|
t.mySignals <- mySignal{Type: MY_SIGNAL_MOVE_CURSOR_DOWN}
|
||||||
|
case 67:
|
||||||
|
t.mySignals <- mySignal{Type: MY_SIGNAL_MOVE_CURSOR_RIGHT}
|
||||||
|
case 68:
|
||||||
|
t.mySignals <- mySignal{Type: MY_SIGNAL_MOVE_CURSOR_LEFT}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user