fstui 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +2 -0
- data/lib/fstui/datascreen.rb +39 -0
- data/lib/fstui/fieldscreen.rb +195 -0
- data/lib/fstui/infolist.rb +118 -0
- data/lib/fstui/inputbox.rb +22 -0
- data/lib/fstui/menu.rb +53 -0
- data/lib/fstui/messagebox.rb +25 -0
- data/lib/fstui/screen.rb +153 -0
- data/lib/fstui/version.rb +3 -0
- data/lib/fstui.rb +10 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c70d3bdbca2796d540ec5518bccfcdcb01cea95b4ccb844780affe7aaf38ddf7
|
|
4
|
+
data.tar.gz: 97c8de10fa9948830b068c801b4fc580610e694f33517c588f121f5e72474897
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0efb84d357330c920760c40cfd66f9ddafcb893ee20098ffa8e255ac1cb5f98cf47267e59b05bd9aa9c2736e92f441c772ad47e0d7af7e03d63f20faa848246f
|
|
7
|
+
data.tar.gz: 84c669222f21fc903d2c279824ae3ca1f67131be94ddfdff6b8f39459d573372ed72a0e74fb74e1f8789de23dfc779b074a11980b5dbf53dd2aa54dcca0068b8
|
data/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class DataScreen
|
|
3
|
+
attr_accessor :title, :subtitle, :data
|
|
4
|
+
|
|
5
|
+
def initialize(screen, title, subtitle, data)
|
|
6
|
+
@screen = screen
|
|
7
|
+
@title = title
|
|
8
|
+
@subtitle = subtitle
|
|
9
|
+
@data = data
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get_response(options: nil)
|
|
13
|
+
loop do
|
|
14
|
+
@win = Window.new(@data.lines.length+3, stdscr.maxx, 5, 0)
|
|
15
|
+
@win.addstr @title.center(@win.maxx)
|
|
16
|
+
@win.addstr @subtitle.center(@win.maxx) + "\n"
|
|
17
|
+
|
|
18
|
+
# figure out which line is the longest and center it
|
|
19
|
+
longest_line = 0
|
|
20
|
+
@data.each_line do |line|
|
|
21
|
+
longest_line = line.length if line.length > longest_line
|
|
22
|
+
end
|
|
23
|
+
padding = " " * (@win.maxx / 2 - longest_line / 2)
|
|
24
|
+
|
|
25
|
+
# draw the data block, with the longest line centered and all others left justified with it
|
|
26
|
+
@data.each_line do |line|
|
|
27
|
+
@win.addstr "#{padding}#{line.strip}\n"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@win.noutrefresh
|
|
31
|
+
selection = @screen.inputbar.get_selection(options: options)
|
|
32
|
+
@win.clear
|
|
33
|
+
@win.noutrefresh
|
|
34
|
+
@win.close
|
|
35
|
+
return selection
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class FieldScreen
|
|
3
|
+
attr_accessor :title, :subtitle, :fields
|
|
4
|
+
|
|
5
|
+
def initialize(screen, title, subtitle, fields)
|
|
6
|
+
@screen = screen
|
|
7
|
+
@title = title
|
|
8
|
+
@subtitle = subtitle
|
|
9
|
+
@fields = fields
|
|
10
|
+
@field_rows = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def clear_fields
|
|
14
|
+
@fields.each do |field|
|
|
15
|
+
field.value = nil
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_response(options: nil)
|
|
20
|
+
loop do
|
|
21
|
+
@win = Window.new(stdscr.maxy-4, stdscr.maxx, 2, 0)
|
|
22
|
+
@win.addstr @title.center(@win.maxx)
|
|
23
|
+
@win.addstr @subtitle.center(@win.maxx) + "\n"
|
|
24
|
+
|
|
25
|
+
# draw the fields on the form
|
|
26
|
+
@fields.each_index do |idx|
|
|
27
|
+
field = @fields[idx]
|
|
28
|
+
# keep track of which row each field starts on, for later edits
|
|
29
|
+
@field_rows[idx] = @win.cury
|
|
30
|
+
@win.addstr " #{idx+1} - #{field.display_name}: "
|
|
31
|
+
@win.attron Curses::A_UNDERLINE
|
|
32
|
+
@win.addstr "#{field.value}"
|
|
33
|
+
@win.attroff Curses::A_UNDERLINE
|
|
34
|
+
@win.addstr "\n\n"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@screen.inputbar.instructions = "#=Enter Data ENTER=Submit Form A=Abort"
|
|
38
|
+
@win.noutrefresh
|
|
39
|
+
selection = @screen.inputbar.get_selection(options: options)
|
|
40
|
+
case selection
|
|
41
|
+
when "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
|
42
|
+
edit_field selection.to_i-1
|
|
43
|
+
when :enter
|
|
44
|
+
# check that all required fields have data
|
|
45
|
+
field_errors = 0
|
|
46
|
+
@fields.each_index do |idx|
|
|
47
|
+
field = @fields[idx]
|
|
48
|
+
next unless field.is_required?
|
|
49
|
+
next unless field.value == "" or field.value == nil
|
|
50
|
+
field_row = 3+idx*2
|
|
51
|
+
|
|
52
|
+
@win.setpos field_row, 0
|
|
53
|
+
@win.addstr " #{idx+1} X #{field.display_name}: "
|
|
54
|
+
@win.standout
|
|
55
|
+
@win.addstr " "
|
|
56
|
+
@win.standend
|
|
57
|
+
@win.clrtoeol
|
|
58
|
+
@win.setpos field_row, 8+field.display_name.length
|
|
59
|
+
field_errors += 1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if(field_errors == 0) then
|
|
63
|
+
# everything looks good, end here and return the collected data
|
|
64
|
+
@win.clear
|
|
65
|
+
@win.noutrefresh
|
|
66
|
+
@win.close
|
|
67
|
+
@screen.inputbar.instructions = ""
|
|
68
|
+
return @fields
|
|
69
|
+
else
|
|
70
|
+
# TODO: consider blink or something, this isn't very obvious
|
|
71
|
+
@screen.inputbar.instructions = "Missing data in required field!"
|
|
72
|
+
@win.noutrefresh
|
|
73
|
+
@screen.redraw
|
|
74
|
+
doupdate
|
|
75
|
+
sleep 3
|
|
76
|
+
end
|
|
77
|
+
when 'A', 'a'
|
|
78
|
+
@win.clear
|
|
79
|
+
@win.noutrefresh
|
|
80
|
+
@win.close
|
|
81
|
+
@screen.inputbar.instructions = ""
|
|
82
|
+
return nil
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def edit_field(field_nbr)
|
|
88
|
+
field = @fields[field_nbr]
|
|
89
|
+
value = ""
|
|
90
|
+
value = field.value if field.value
|
|
91
|
+
insert_pos = value.length
|
|
92
|
+
@win.setpos @field_rows[field_nbr], 0
|
|
93
|
+
@win.addstr " #{field_nbr+1} - #{field.display_name}: "
|
|
94
|
+
@win.standout
|
|
95
|
+
# TODO: fix the hardcoded 33-long fields :)
|
|
96
|
+
@win.addstr value.ljust(33)
|
|
97
|
+
@win.clrtoeol
|
|
98
|
+
@win.setpos @field_rows[field_nbr], 8+field.display_name.length + value.length
|
|
99
|
+
noecho
|
|
100
|
+
@win.refresh
|
|
101
|
+
@win.keypad(true)
|
|
102
|
+
loop do
|
|
103
|
+
char = @win.getch
|
|
104
|
+
case char
|
|
105
|
+
when 10, 13, "\n", "\r"
|
|
106
|
+
break
|
|
107
|
+
when 8, KEY_BACKSPACE, "\b", 127
|
|
108
|
+
next unless insert_pos > 0
|
|
109
|
+
row = @win.cury
|
|
110
|
+
col = @win.curx
|
|
111
|
+
if(insert_pos == 1) then
|
|
112
|
+
value = ""
|
|
113
|
+
insert_pos = 0
|
|
114
|
+
else
|
|
115
|
+
value = value[0..insert_pos-2] + value[insert_pos..-1]
|
|
116
|
+
insert_pos -= 1
|
|
117
|
+
end
|
|
118
|
+
if(col==0) then
|
|
119
|
+
@win.setpos(row-1, @win.maxx-1)
|
|
120
|
+
@win.addstr value[insert_pos..-1] + ' '
|
|
121
|
+
@win.setpos(row-1, @win.maxx-1)
|
|
122
|
+
else
|
|
123
|
+
@win.setpos(row, col-1)
|
|
124
|
+
@win.addstr value[insert_pos..-1] + ' '
|
|
125
|
+
@win.setpos(row, col-1)
|
|
126
|
+
end
|
|
127
|
+
when KEY_DC # delete
|
|
128
|
+
next unless insert_pos < value.length
|
|
129
|
+
value = value[0..insert_pos-1] + value[insert_pos+1..-1]
|
|
130
|
+
row = @win.cury
|
|
131
|
+
col = @win.curx
|
|
132
|
+
@win.addstr value[insert_pos..-1] + ' '
|
|
133
|
+
@win.setpos(row, col)
|
|
134
|
+
when KEY_LEFT
|
|
135
|
+
next unless insert_pos > 0
|
|
136
|
+
row = @win.cury
|
|
137
|
+
col = @win.curx
|
|
138
|
+
if(col == 0) then
|
|
139
|
+
@win.setpos(row-1, @win.maxx-1)
|
|
140
|
+
else
|
|
141
|
+
@win.setpos(row, col-1)
|
|
142
|
+
end
|
|
143
|
+
insert_pos -= 1
|
|
144
|
+
when KEY_RIGHT
|
|
145
|
+
next unless insert_pos < value.length
|
|
146
|
+
row = @win.cury
|
|
147
|
+
col = @win.curx
|
|
148
|
+
if(col == @win.maxx-1) then
|
|
149
|
+
@win.setpos(row+1, 0)
|
|
150
|
+
else
|
|
151
|
+
@win.setpos(row, col+1)
|
|
152
|
+
end
|
|
153
|
+
insert_pos += 1
|
|
154
|
+
when KEY_DOWN, KEY_UP
|
|
155
|
+
else
|
|
156
|
+
value.insert(insert_pos, char)
|
|
157
|
+
insert_pos += 1
|
|
158
|
+
if(insert_pos == value.length) then
|
|
159
|
+
# adding chars at the end, easy
|
|
160
|
+
@win.addch char
|
|
161
|
+
else
|
|
162
|
+
# adding chars in the middle, need to redraw the rest of the field
|
|
163
|
+
row = @win.cury
|
|
164
|
+
col = @win.curx
|
|
165
|
+
@win.addstr value[insert_pos-1..-1]
|
|
166
|
+
@win.setpos(row, col+1)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
@win.keypad(false)
|
|
171
|
+
echo
|
|
172
|
+
@win.standend
|
|
173
|
+
|
|
174
|
+
@fields[field_nbr].value = value
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
class Field
|
|
179
|
+
attr_accessor :name, :required, :value
|
|
180
|
+
def initialize(name:, required: true)
|
|
181
|
+
@name = name
|
|
182
|
+
@required = required
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def display_name
|
|
186
|
+
disp_name = @name
|
|
187
|
+
disp_name += " (opt)" unless @required
|
|
188
|
+
disp_name
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def is_required?
|
|
192
|
+
@required
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class InfoList
|
|
3
|
+
attr_accessor :infoline, :left_heading, :right_heading
|
|
4
|
+
|
|
5
|
+
def initialize(screen, infoline, lines_per_item)
|
|
6
|
+
@infoline = infoline
|
|
7
|
+
@lines_per_item = lines_per_item
|
|
8
|
+
@items = Array.new
|
|
9
|
+
@screen = screen
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def add_item(item)
|
|
13
|
+
@items.push item
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def <<(item)
|
|
17
|
+
@items.push item
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def clear_items
|
|
21
|
+
@items = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def get_response(extra_options: [])
|
|
25
|
+
page = 1
|
|
26
|
+
loop do
|
|
27
|
+
@win = Window.new(stdscr.maxy - 5, stdscr.maxx, 2, 0)
|
|
28
|
+
@win.addstr @infoline
|
|
29
|
+
@win.setpos 2, 0
|
|
30
|
+
@win.attron A_REVERSE
|
|
31
|
+
@win.addstr " "*5 + @left_heading + " " * (stdscr.maxx - 5 - 5 - @left_heading.length - @right_heading.length) + @right_heading + " "*5
|
|
32
|
+
@win.attroff A_REVERSE
|
|
33
|
+
|
|
34
|
+
items_per_page = (@win.maxy - 6) / (@lines_per_item + 1)
|
|
35
|
+
total_pages = @items.length / items_per_page
|
|
36
|
+
start_item = items_per_page * (page-1)
|
|
37
|
+
|
|
38
|
+
idx = start_item + 1
|
|
39
|
+
@items[start_item..start_item + items_per_page].each do |item|
|
|
40
|
+
# figure out which line has the longest right-hand side so we know how much to trim the left so it doesn't interfere
|
|
41
|
+
longest_rhs = 0
|
|
42
|
+
item.rows.each do |row|
|
|
43
|
+
longest_rhs = row.rhs.length if row.rhs.length > longest_rhs
|
|
44
|
+
end
|
|
45
|
+
lhs = truncate(item.rows[0].lhs, stdscr.maxx - 6 - longest_rhs - 3)
|
|
46
|
+
@win.addstr " #{idx}. #{lhs}" + " "*(stdscr.maxx - 5 - 1 - idx.to_s.length - lhs.length - item.rows[0].rhs.length) + "#{item.rows[0].rhs}\n"
|
|
47
|
+
if(item.rows.length > 1)
|
|
48
|
+
item.rows[1..-1].each do |row|
|
|
49
|
+
lhs = truncate(row.lhs, stdscr.maxx - 9 - longest_rhs - 3)
|
|
50
|
+
@win.addstr " #{lhs}" + " "*(stdscr.maxx - 7 - 2 - lhs.length - row.rhs.length) + "#{row.rhs}\n"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
@win.addstr "\n"
|
|
54
|
+
idx += 1
|
|
55
|
+
end
|
|
56
|
+
morepages = page < total_pages ? "More on Next Screen" : "End of List"
|
|
57
|
+
@win.addstr "\n** #{@items.length} Items UNSORTED - Page #{page} of #{total_pages} - #{morepages} **"
|
|
58
|
+
|
|
59
|
+
@win.noutrefresh
|
|
60
|
+
old_instructions = @screen.inputbar.instructions
|
|
61
|
+
instructions = []
|
|
62
|
+
extra_options.each do |key, desc|
|
|
63
|
+
instructions << "#{key}=#{desc}"
|
|
64
|
+
end
|
|
65
|
+
instructions.push "B=Back" if page > 1
|
|
66
|
+
instructions.push "<Enter>=Next Screen" if page < total_pages
|
|
67
|
+
@screen.inputbar.instructions = instructions.join(", ")
|
|
68
|
+
selection = @screen.inputbar.get_string
|
|
69
|
+
@screen.inputbar.instructions = old_instructions
|
|
70
|
+
@win.clear
|
|
71
|
+
@win.noutrefresh
|
|
72
|
+
@win.close
|
|
73
|
+
|
|
74
|
+
if(selection == "" and page < total_pages)
|
|
75
|
+
page += 1
|
|
76
|
+
elsif(selection == "b" or selection == "B" and page > 1)
|
|
77
|
+
page -= 1
|
|
78
|
+
elsif(extra_options.keys.include?(selection.upcase) or extra_options.keys.include?(selection.downcase))
|
|
79
|
+
return selection
|
|
80
|
+
else
|
|
81
|
+
return @items[selection.to_i - 1].key if selection.to_i > 0 and selection.to_i < @items.length + 1
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def truncate(str, len)
|
|
89
|
+
return str if str.length <= len
|
|
90
|
+
"#{str[0..len-3]}..."
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
class InfoItem
|
|
95
|
+
attr_accessor :key, :rows
|
|
96
|
+
|
|
97
|
+
def initialize(key:, rows:)
|
|
98
|
+
@key = key
|
|
99
|
+
@rows = rows
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class InfoRow
|
|
104
|
+
attr_accessor :lhs, :rhs
|
|
105
|
+
|
|
106
|
+
def initialize(lhs:, rhs:)
|
|
107
|
+
@lhs = lhs
|
|
108
|
+
@rhs = rhs
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def [](idx)
|
|
112
|
+
return @lhs if idx == 0
|
|
113
|
+
return @rhs if idx == 1
|
|
114
|
+
|
|
115
|
+
nil
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class InputBox
|
|
3
|
+
attr_accessor :title
|
|
4
|
+
def initialize(screen, title, subtitle)
|
|
5
|
+
@title = title
|
|
6
|
+
@subtitle = subtitle
|
|
7
|
+
@screen = screen
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get_entry
|
|
11
|
+
@win = Window.new(5, stdscr.maxx, stdscr.maxy / 2 - 3, 0)
|
|
12
|
+
@win.addstr @title.center(@win.maxx)
|
|
13
|
+
@win.addstr @subtitle.center(@win.maxx) + "\n"
|
|
14
|
+
|
|
15
|
+
@win.refresh
|
|
16
|
+
@screen.redraw
|
|
17
|
+
selection = @screen.inputbar.get_string
|
|
18
|
+
@win.close
|
|
19
|
+
selection
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/fstui/menu.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class Menu
|
|
3
|
+
attr_accessor :title
|
|
4
|
+
def initialize(screen, title, subtitle)
|
|
5
|
+
@title = title
|
|
6
|
+
@subtitle = subtitle
|
|
7
|
+
@items = Array.new
|
|
8
|
+
@screen = screen
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def add_item(key, desc)
|
|
12
|
+
@items.push MenuItem.new(key, desc)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get_response
|
|
16
|
+
loop do
|
|
17
|
+
@win = Window.new(@items.length + 4, stdscr.maxx, 5, 0)
|
|
18
|
+
@win.clear
|
|
19
|
+
@win.addstr @title.center(@win.maxx)
|
|
20
|
+
@win.addstr @subtitle.center(@win.maxx) + "\n"
|
|
21
|
+
|
|
22
|
+
# figure out which item is the longest and center it
|
|
23
|
+
longest_item = 0
|
|
24
|
+
@items.each do |item|
|
|
25
|
+
longest_item = item.desc.length if item.desc.length > longest_item
|
|
26
|
+
end
|
|
27
|
+
padding = " " * (@win.maxx / 2 - longest_item / 2)
|
|
28
|
+
|
|
29
|
+
# draw the menu, with the longest item centered and all others left justified with it
|
|
30
|
+
@items.each_index do |idx|
|
|
31
|
+
menu_text = "#{padding}#{idx + 1}. #{@items[idx].desc}\n"
|
|
32
|
+
@win.addstr menu_text
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@win.noutrefresh
|
|
36
|
+
selection = @screen.inputbar.get_selection
|
|
37
|
+
@win.clear
|
|
38
|
+
@win.noutrefresh
|
|
39
|
+
@win.close
|
|
40
|
+
return @items[selection.to_i - 1].key if(("0".."9").include?(selection) and selection.to_i <= @items.length)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class MenuItem
|
|
45
|
+
attr_accessor :key, :desc
|
|
46
|
+
|
|
47
|
+
def initialize(key, desc)
|
|
48
|
+
@key = key
|
|
49
|
+
@desc = desc
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class MessageBox
|
|
3
|
+
attr_accessor :title
|
|
4
|
+
def initialize(screen, title, subtitle)
|
|
5
|
+
@title = title
|
|
6
|
+
@subtitle = subtitle
|
|
7
|
+
@screen = screen
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def show
|
|
11
|
+
@win = Window.new(5, stdscr.maxx, stdscr.maxy / 2 - 3, 0)
|
|
12
|
+
@win.addstr @title.center(@win.maxx)
|
|
13
|
+
@win.addstr @subtitle.center(@win.maxx) + "\n"
|
|
14
|
+
@win.refresh
|
|
15
|
+
@screen.inputbar.hide
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def hide
|
|
19
|
+
@win.clear
|
|
20
|
+
@win.refresh
|
|
21
|
+
@win.close
|
|
22
|
+
@screen.redraw
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/fstui/screen.rb
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
module FSTui
|
|
2
|
+
class Screen
|
|
3
|
+
attr_accessor :titlebar, :inputbar
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
init_screen
|
|
7
|
+
start_color
|
|
8
|
+
crmode
|
|
9
|
+
|
|
10
|
+
@titlebar = TitleBar.new(self)
|
|
11
|
+
@inputbar = InputBar.new(self)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def destroy
|
|
15
|
+
close_screen
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def redraw
|
|
19
|
+
@titlebar.redraw
|
|
20
|
+
@inputbar.redraw
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def new_menu(title, subtitle = "Please select one of the options below.")
|
|
24
|
+
Menu.new(self, title, subtitle)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def new_inputbox(title, subtitle = "Please enter your selection below.")
|
|
28
|
+
InputBox.new(self, title, subtitle)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def new_messagebox(title, subtitle = "")
|
|
32
|
+
MessageBox.new(self, title, subtitle)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def pop_messagebox(title, subtitle = "", timeout = 3)
|
|
36
|
+
msg = MessageBox.new(self, title, subtitle)
|
|
37
|
+
msg.show
|
|
38
|
+
sleep timeout
|
|
39
|
+
msg.hide
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def new_infolist(infoline, lines_per_item)
|
|
43
|
+
InfoList.new(self, infoline, lines_per_item)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def new_datascreen(title, subtitle = "", data)
|
|
47
|
+
DataScreen.new(self, title, subtitle, data)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def new_fieldscreen(title, subtitle = "", fields)
|
|
51
|
+
FieldScreen.new(self, title, subtitle, fields)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class TitleBar
|
|
56
|
+
def initialize(screen, pad_chars = 2)
|
|
57
|
+
@win = Window.new(1, stdscr.maxx, 0, 0)
|
|
58
|
+
@win.attrset A_REVERSE
|
|
59
|
+
@win.noutrefresh
|
|
60
|
+
@left = @center = @right = ""
|
|
61
|
+
@pad_chars = pad_chars
|
|
62
|
+
redraw
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def center=(center)
|
|
66
|
+
@center = center
|
|
67
|
+
redraw
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def left=(left)
|
|
71
|
+
@left = left
|
|
72
|
+
redraw
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def right=(right)
|
|
76
|
+
@right = right
|
|
77
|
+
redraw
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def redraw
|
|
81
|
+
@win.clear
|
|
82
|
+
@win.addstr (" " * @pad_chars) + @left + @center.center(@win.maxx - (@left.length + @pad_chars) - (@right.length + @pad_chars)) + @right + (" " * @pad_chars)
|
|
83
|
+
@win.noutrefresh
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class InputBar
|
|
88
|
+
attr_accessor :prompt, :instructions
|
|
89
|
+
|
|
90
|
+
def initialize(screen, prompt = " Enter your selection(s) and press <Enter> : ", instructions = "")
|
|
91
|
+
@prompt = prompt
|
|
92
|
+
@instructions = instructions
|
|
93
|
+
window_setup
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def window_setup
|
|
97
|
+
# TODO: this could use a lot of simplification
|
|
98
|
+
@promptwin = Window.new(1, @prompt.length, stdscr.maxy - 2, 0)
|
|
99
|
+
@promptwin.attrset A_REVERSE
|
|
100
|
+
@entrywin = Window.new(1, stdscr.maxx - @prompt.length, stdscr.maxy - 2, @prompt.length + 1)
|
|
101
|
+
@instructionwin = Window.new(1, stdscr.maxx, stdscr.maxy-1, 0)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def prompt=(prompt)
|
|
105
|
+
@prompt = prompt
|
|
106
|
+
destroy
|
|
107
|
+
window_setup
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def destroy
|
|
111
|
+
@promptwin.close
|
|
112
|
+
@entrywin.close
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def redraw
|
|
116
|
+
@promptwin.clear
|
|
117
|
+
@promptwin.addstr @prompt
|
|
118
|
+
@promptwin.noutrefresh
|
|
119
|
+
@instructionwin.clear
|
|
120
|
+
@instructionwin.addstr @instructions
|
|
121
|
+
@instructionwin.noutrefresh
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def hide
|
|
125
|
+
@promptwin.clear
|
|
126
|
+
@promptwin.noutrefresh
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def get_selection(options: nil)
|
|
130
|
+
while(true) do
|
|
131
|
+
@entrywin.setpos 0, 0
|
|
132
|
+
redraw
|
|
133
|
+
# getch will doupdate() for us as well
|
|
134
|
+
entry = @entrywin.getch
|
|
135
|
+
@entrywin.clear
|
|
136
|
+
@entrywin.noutrefresh
|
|
137
|
+
entry = :enter if entry == 10 or entry == 13
|
|
138
|
+
break if options == nil or options.include? entry
|
|
139
|
+
end
|
|
140
|
+
entry
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def get_string
|
|
144
|
+
@entrywin.setpos 0, 0
|
|
145
|
+
redraw
|
|
146
|
+
# getstr will doupdate() for us as well
|
|
147
|
+
entry = @entrywin.getstr
|
|
148
|
+
@entrywin.clear
|
|
149
|
+
@entrywin.noutrefresh
|
|
150
|
+
entry
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
data/lib/fstui.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fstui
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.5
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- sarahemm
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: curses
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.2'
|
|
19
|
+
- - ">="
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 1.2.0
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - "~>"
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '1.2'
|
|
29
|
+
- - ">="
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: 1.2.0
|
|
32
|
+
description: Full screen text UI library
|
|
33
|
+
email: github@sen.cx
|
|
34
|
+
executables: []
|
|
35
|
+
extensions: []
|
|
36
|
+
extra_rdoc_files: []
|
|
37
|
+
files:
|
|
38
|
+
- README.md
|
|
39
|
+
- lib/fstui.rb
|
|
40
|
+
- lib/fstui/datascreen.rb
|
|
41
|
+
- lib/fstui/fieldscreen.rb
|
|
42
|
+
- lib/fstui/infolist.rb
|
|
43
|
+
- lib/fstui/inputbox.rb
|
|
44
|
+
- lib/fstui/menu.rb
|
|
45
|
+
- lib/fstui/messagebox.rb
|
|
46
|
+
- lib/fstui/screen.rb
|
|
47
|
+
- lib/fstui/version.rb
|
|
48
|
+
homepage: http://github.com/sarahemm/ruby-fstui
|
|
49
|
+
licenses:
|
|
50
|
+
- MIT
|
|
51
|
+
metadata: {}
|
|
52
|
+
rdoc_options: []
|
|
53
|
+
require_paths:
|
|
54
|
+
- lib
|
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '0'
|
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '0'
|
|
65
|
+
requirements: []
|
|
66
|
+
rubygems_version: 4.0.21
|
|
67
|
+
specification_version: 4
|
|
68
|
+
summary: Full Screen TUI library
|
|
69
|
+
test_files: []
|