Sensibly format rows with table name on the right.
[pstop.git] / screen / screen.go
1 // This file configures the screen, basically remembering the size
2 // and foreground and background colours.
3 package screen
4
5 import (
6         "fmt"
7         "log"
8         "os"
9
10         "github.com/nsf/termbox-go"
11
12         "github.com/sjmudd/pstop/lib"
13         "github.com/sjmudd/pstop/version"
14 )
15
16 // this just allows me to use stuff with it
17 type TermboxScreen struct {
18         width, height int
19         fg, bg        termbox.Attribute
20 }
21
22 // print the characters in bold (for headings) but don't print them outside the screen
23 func (s *TermboxScreen) BoldPrintAt(x int, y int, text string) {
24         offset := 0
25         for c := range text {
26                 if (x + offset) < s.width {
27                         termbox.SetCell(x+offset, y, rune(text[c]), s.fg|termbox.AttrBold, s.bg)
28                         offset++
29                 }
30         }
31         s.Flush()
32 }
33
34 // clear the screen
35 func (s *TermboxScreen) Clear() {
36         termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
37 }
38
39 // close the screen
40 func (s *TermboxScreen) Close() {
41         termbox.Close()
42 }
43
44 // display a help page
45 func (s *TermboxScreen) DisplayHelp() {
46         s.PrintAt(0, 0, lib.MyName()+" version "+version.Version()+" "+lib.Copyright())
47
48         s.PrintAt(0, 2, "Program to show the top I/O information by accessing information from the")
49         s.PrintAt(0, 3, "performance_schema schema. Ideas based on mysql-sys.")
50
51         s.PrintAt(0, 5, "Keys:")
52         s.PrintAt(0, 6, "- - reduce the poll interval by 1 second (minimum 1 second)")
53         s.PrintAt(0, 7, "+ - increase the poll interval by 1 second")
54         s.PrintAt(0, 8, "h/? - this help screen")
55         s.PrintAt(0, 9, "q - quit")
56         s.PrintAt(0, 10, "t - toggle between showing time since resetting statistics or since P_S data was collected")
57         s.PrintAt(0, 11, "z - reset statistics")
58         s.PrintAt(0, 12, "<tab> or <right arrow> - change display modes between: latency, ops, file I/O, lock and user modes")
59         s.PrintAt(0, 13, "<left arrow> - change display modes to the previous screen (see above)")
60         s.PrintAt(0, 15, "Press h to return to main screen")
61 }
62
63 // flush changes to screen
64 func (s *TermboxScreen) Flush() {
65         termbox.Flush()
66 }
67
68 // return the current height of the screen
69 func (s *TermboxScreen) Height() int {
70         return s.height
71 }
72
73 // reset the termbox to a clear screen
74 func (s *TermboxScreen) Initialise() {
75         err := termbox.Init()
76         if err != nil {
77                 fmt.Println("Could not start termbox for " + lib.MyName() + ". View ~/." + lib.MyName() + ".log for error messages.")
78                 log.Printf("Cannot start "+lib.MyName()+", termbox.Init() gave an error:\n%s\n", err)
79                 os.Exit(1)
80         }
81
82         s.Clear()
83         s.fg = termbox.ColorDefault
84         s.bg = termbox.ColorDefault
85
86         s.SetSize(termbox.Size())
87 }
88
89 // print the characters but don't print them outside the screen
90 func (s *TermboxScreen) PrintAt(x int, y int, text string) {
91         offset := 0
92         for c := range text {
93                 if (x + offset) < s.width {
94                         termbox.SetCell(x+offset, y, rune(text[c]), s.fg, s.bg)
95                         offset++
96                 }
97         }
98         s.Flush()
99 }
100
101 // Clear EOL
102 func (s *TermboxScreen) ClearLine(x int, y int) {
103         for i := x; i < s.width; i++ {
104                 termbox.SetCell(i, y, ' ', termbox.ColorDefault, termbox.ColorDefault)
105         }
106         s.Flush()
107 }
108
109 // set the screen size
110 func (s *TermboxScreen) SetSize(width, height int) {
111         // if we get bigger then clear out the bottom line
112         for x := 0; x < s.width; x++ {
113                 termbox.SetCell(x, s.height-1, ' ', s.fg, s.bg)
114         }
115         s.Flush()
116
117         s.width = width
118         s.height = height
119 }
120
121 // return the current (width, height) of the screen
122 func (s *TermboxScreen) Size() (int, int) {
123         return s.width, s.height
124 }
125
126 // create a channel for termbox.Events and run a poller to send
127 // these events to the channel.  Return the channel.
128 func (s TermboxScreen) TermBoxChan() chan termbox.Event {
129         termboxChan := make(chan termbox.Event)
130         go func() {
131                 for {
132                         termboxChan <- termbox.PollEvent()
133                 }
134         }()
135         return termboxChan
136 }