ncumbra 0.1.0 → 0.1.1

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.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env bash
2
+
3
+ sqlite3 tennis.sqlite <<!
4
+ .mode csv
5
+ .import atp_matches_2018.csv matches
6
+ !
7
+
8
+ sqlite3 tennis.sqlite <<!
9
+ DELETE from matches WHERE tourney_id = 'tourney_id';
10
+ !
11
+ sqlite3 tennis.sqlite <<!
12
+ select count(1) from matches;
13
+ !
@@ -0,0 +1,51 @@
1
+ CREATE TABLE matches(
2
+ "tourney_id" TEXT,
3
+ "tourney_name" TEXT,
4
+ "surface" TEXT,
5
+ "draw_size" TEXT,
6
+ "tourney_level" TEXT,
7
+ "tourney_date" TEXT,
8
+ "match_num" TEXT,
9
+ "winner_id" TEXT,
10
+ "winner_seed" TEXT,
11
+ "winner_entry" TEXT,
12
+ "winner_name" TEXT,
13
+ "winner_hand" TEXT,
14
+ "winner_ht" TEXT,
15
+ "winner_ioc" TEXT,
16
+ "winner_age" TEXT,
17
+ "winner_rank" TEXT,
18
+ "winner_rank_points" TEXT,
19
+ "loser_id" TEXT,
20
+ "loser_seed" TEXT,
21
+ "loser_entry" TEXT,
22
+ "loser_name" TEXT,
23
+ "loser_hand" TEXT,
24
+ "loser_ht" TEXT,
25
+ "loser_ioc" TEXT,
26
+ "loser_age" TEXT,
27
+ "loser_rank" TEXT,
28
+ "loser_rank_points" TEXT,
29
+ "score" TEXT,
30
+ "best_of" TEXT,
31
+ "round" TEXT,
32
+ "minutes" TEXT,
33
+ "w_ace" TEXT,
34
+ "w_df" TEXT,
35
+ "w_svpt" TEXT,
36
+ "w_1stIn" TEXT,
37
+ "w_1stWon" TEXT,
38
+ "w_2ndWon" TEXT,
39
+ "w_SvGms" TEXT,
40
+ "w_bpSaved" TEXT,
41
+ "w_bpFaced" TEXT,
42
+ "l_ace" TEXT,
43
+ "l_df" TEXT,
44
+ "l_svpt" TEXT,
45
+ "l_1stIn" TEXT,
46
+ "l_1stWon" TEXT,
47
+ "l_2ndWon" TEXT,
48
+ "l_SvGms" TEXT,
49
+ "l_bpSaved" TEXT,
50
+ "l_bpFaced" TEXT
51
+ );
data/examples/ex1.rb CHANGED
@@ -55,10 +55,12 @@ begin
55
55
  form.add_widget w
56
56
  }
57
57
  form.pack
58
+ form.repaint
58
59
  win.wrefresh
59
60
 
60
61
  y = x = 1
61
62
  while (ch = win.getkey) != 113
63
+ next if ch == -1
62
64
  #y, x = win.getbegyx(win.pointer)
63
65
  old_y, old_x = y, x
64
66
  case ch
data/examples/ex2.rb CHANGED
@@ -99,6 +99,7 @@ begin
99
99
 
100
100
  y = x = 1
101
101
  while (ch = win.getkey) != FFI::NCurses::KEY_CTRL_Q
102
+ next if ch == -1
102
103
  begin
103
104
  form.handle_key ch
104
105
  rescue => e
data/examples/ex5.rb CHANGED
@@ -72,7 +72,7 @@ begin
72
72
  form.add_widget box, lb
73
73
  form.add_widget tb
74
74
  form.pack
75
- form.select_first_field
75
+ form.repaint
76
76
  win.wrefresh
77
77
 
78
78
  y = x = 1
data/examples/exbox.rb CHANGED
@@ -45,7 +45,8 @@ begin
45
45
  # check with long lines
46
46
  catch(:close) do
47
47
  form = Form.new win
48
- box = Box.new row: 2,col: 2, height: 24, width: 80, title: "A box", justify: :left
48
+ #box = Box.new row: 2,col: 2, height: 24, width: 80, title: "A box", justify: :left
49
+ box = Box.new row: 1,col: 2, height: -3, width: 80, title: "A box", justify: :left
49
50
  win.printstring(3,1,"Just testing that listbox is correctly positioned")
50
51
  #lb = Listbox.new list: alist, row: 4, col: 2, width: 70, height: 18
51
52
  lb = Listbox.new list: alist
@@ -55,7 +56,7 @@ begin
55
56
  win.printstring(box.row+1,0,"XX")
56
57
  win.printstring(box.row+1,lb.col+lb.width,"XX")
57
58
  win.printstring(box.row+box.height,1,"This prints below the listbox")
58
- brow = box.row+box.height+3
59
+ brow = box.row+box.height+2
59
60
  tb = ToggleButton.new onvalue: "Border", offvalue: "No Border", row: brow, col: 10, value: true
60
61
  ab = Button.new text: "Processes" , row: brow, col: 30
61
62
  logb = Button.new text: "LogFile" , row: brow, col: 50
data/examples/exm1.rb CHANGED
@@ -39,7 +39,7 @@ def _alert_fields str
39
39
  add Field.new name:"name", default: "Rahul", width: 25, color_pair: CP_CYAN, attr: REVERSE
40
40
  add LabeledField.new label:"Age:", name:"age", text:"25", col: 15, color_pair: CP_CYAN, attr: REVERSE
41
41
  # unfortunately this exceeds since width only takes field into account not label
42
- add LabeledField.new label:"Address:", name:"address", width:50 , col: 15, color_pair: CP_CYAN, attr: REVERSE
42
+ add LabeledField.new label:"Address:", name:"address", width:50 , maxlen: 70, col: 15, color_pair: CP_CYAN, attr: REVERSE
43
43
  end
44
44
  mb.run
45
45
  end
@@ -92,7 +92,6 @@ begin
92
92
  b4.command do
93
93
  ret = confirm "Do you wish to go?"
94
94
  message_label.text = "You selected #{ret}"
95
- #message_label.touch
96
95
  end
97
96
  form.add_widget message_label, b1, b2, b3, b4
98
97
  form.pack
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby
2
+ # ----------------------------------------------------------------------------- #
3
+ # File: extab2.rb
4
+ # Description:
5
+ # Author: j kepler http://github.com/mare-imbrium/canis/
6
+ # Date: 2018-05-06 - 11:20
7
+ # License: MIT
8
+ # Last update: 2018-05-22 23:05
9
+ # ----------------------------------------------------------------------------- #
10
+ # extab2.rb Copyright (C) 2018 j kepler
11
+ require 'umbra'
12
+ require 'umbra/label'
13
+ require 'umbra/tabular'
14
+ require 'umbra/listbox'
15
+ require 'umbra/textbox'
16
+ require 'umbra/box'
17
+ require 'umbra/table'
18
+
19
+ def startup
20
+ require 'date'
21
+
22
+ $log = create_logger "v.log"
23
+ #$log.level = Logger::DEBUG
24
+ today = Date.today
25
+ $log.info "Started demo table on #{today}"
26
+ end
27
+ def statusline win, str, col = 0
28
+ win.printstring( FFI::NCurses.LINES-1, col, str, 5)
29
+ end
30
+ begin
31
+ include Umbra
32
+ init_curses
33
+ startup
34
+ win = Window.new
35
+ statusline(win, " "*(win.width-0), 0)
36
+ statusline(win, "Press C-q to quit #{win.height}:#{win.width}", 20)
37
+ title = Label.new( :text => "Demo of Table", :row => 0, :col => 0 , :width => FFI::NCurses.COLS-1,
38
+ :justify => :center, :color_pair => 0)
39
+
40
+ form = Form.new win
41
+ form.add_widget title
42
+
43
+ box = Box.new row: 2, col: 0, width: 15, height: 7
44
+ =begin
45
+ t = Tabular.new(['a', 'b'], [1, 2], [3, 4], [5,6])
46
+ lb = Listbox.new list: t.render
47
+ =end
48
+ #table = Table.new(['a', 'b'], [1, 2], [3, 4], [5,6])
49
+ table = Table.new(columns: ['a', 'b'], data: [[1, 2], [3, 4], [5,6]])
50
+ box.fill table
51
+ box1 = Box.new row: box.row + box.height + 0, col: box.col, width: box.width, height: 7
52
+ table1 = Table.new columns: ['a', 'b']
53
+ table1 << [8, 6]
54
+ table1 << [1, 2]
55
+ table1 << [3, 4]
56
+ table1 << [4, 6]
57
+ table1 << [2, 6]
58
+ table1.y = '| '
59
+ table1.x = '+-'
60
+ #lb1 = Listbox.new list: t.render
61
+ #table1.render
62
+ box1.fill table1
63
+
64
+ #file = File.expand_path("examples/tasks.csv", __FILE__)
65
+ file = File.expand_path("examples/tasks.csv")
66
+ lines = File.open(file,'r').readlines
67
+ heads = %w[ id sta type prio title ]
68
+ t = Table.new do |t|
69
+ t.headings = heads
70
+ t.y = ' '
71
+ lines.each { |e| t.add_row e.chomp.split '|' }
72
+ end
73
+ t.tabular.use_separator = false
74
+ # testing out coloring different rows in different colors depending on status
75
+ def t.color_of_row index, state
76
+ arr = super
77
+ if index == 0 ## header
78
+ arr = @header_color_pair || [ CP_MAGENTA, REVERSE ]
79
+ elsif data[index-1][1] == "clo"
80
+ arr = [ CP_BLUE, NORMAL ]
81
+ elsif self.data[index-1][1] == "ope"
82
+ arr = [ CP_YELLOW, BOLD ]
83
+ end
84
+ arr
85
+ end
86
+ #t.column_width 4, 15 ## checking truncate of long data
87
+
88
+ #t.render
89
+ box2 = Box.new title: "tasks.csv", row: box.row , col: box.col + box.width+1, width: FFI::NCurses.COLS-box.width-1, height: FFI::NCurses.LINES-1-box.row
90
+ #lb2 = Listbox.new list: t
91
+
92
+ table2 = t
93
+ #box2.fill table2
94
+
95
+ r = `ls -l`
96
+ res = r.split("\n")
97
+
98
+ table3 = Table.new do
99
+ self.headings = 'User', 'Size', 'Mon', 'Date', 'Time', 'File'
100
+ self.header_color_pair = [ CP_CYAN, REVERSE ]
101
+ res.each { |e|
102
+ cols = e.split
103
+ next if cols.count < 6
104
+ cols = cols[3..-1]
105
+ cols = cols[0..5] if cols.count > 6
106
+ add_row cols
107
+ }
108
+ column_width 1, 10
109
+ #column_width 5, 10 ## testing truncate
110
+ column_align 1, :right
111
+ column_align 3, :right
112
+ end
113
+
114
+ # testing out coloring different columns in different color
115
+ ## NOTE that as we scroll the colors will change for a column
116
+ ## We don't know which columns have come in since scrolling will cut off some columns.
117
+ ## We need to access pcol to find out which the starting column is, so which know which columns
118
+ ## we actually have.
119
+ def table3.print_row(win, row, col, str, index, state)
120
+ f = str.split('|')
121
+ attrib = NORMAL
122
+ attrib = BOLD if index == 0
123
+ attrib = REVERSE if state == :HIGHLIGHTED
124
+ f.each_with_index {|c, ix|
125
+ win.printstring(row, col, c, ix+1, attrib)
126
+ col += c.length+1
127
+ }
128
+
129
+ end
130
+ #table3.render
131
+ #t.y = '| '
132
+ #t.x = '+-'
133
+ #tb = Textbox.new list: t.render
134
+ box2.add table2, table3
135
+
136
+ form.add_widget box, table
137
+ form.add_widget box1, table1
138
+ form.add_widget box2, table2, table3
139
+
140
+
141
+ form.pack
142
+ form.repaint
143
+ win.wrefresh
144
+
145
+ y = x = 1
146
+ main_loop(form) do |ch|
147
+ statusline(win, "Pressed #{ch} on ", 70)
148
+ form.handle_key ch
149
+ win.wrefresh
150
+ end
151
+ =begin
152
+ while (ch = win.getkey) != FFI::NCurses::KEY_CTRL_Q
153
+ next if ch == -1
154
+ form.handle_key ch
155
+ #statusline(win, "Pressed #{ch} on ", 70)
156
+ win.wrefresh
157
+ end
158
+ =end
159
+
160
+ rescue Object => e
161
+ @window.destroy if @window
162
+ FFI::NCurses.endwin
163
+ puts e
164
+ puts e.backtrace.join("\n")
165
+ ensure
166
+ @window.destroy if @window
167
+ $log.close if $log
168
+ FFI::NCurses.endwin
169
+ puts
170
+ end
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env ruby
2
+ # ----------------------------------------------------------------------------- #
3
+ # File: extab3.rb
4
+ # Description: Example of using a Table with an sqlite3 resultset.
5
+ # Author: j kepler http://github.com/mare-imbrium/umbra/
6
+ # Date: 2018-05-11
7
+ # License: MIT
8
+ # Last update: 2018-05-23 08:34
9
+ # ----------------------------------------------------------------------------- #
10
+ # extab3.rb Copyright (C) 2018 j kepler
11
+ require 'umbra'
12
+ require 'umbra/label'
13
+ require 'umbra/tabular'
14
+ require 'umbra/box'
15
+ require 'umbra/table'
16
+ require 'sqlite3'
17
+
18
+ def startup
19
+ require 'logger'
20
+ require 'date'
21
+
22
+ path = File.join(ENV["LOGDIR"] || "./" ,"v.log")
23
+ file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
24
+ $log = Logger.new(path)
25
+ $log.level = Logger::DEBUG
26
+ today = Date.today
27
+ $log.info "Started demo table #{$0} on #{today}"
28
+ $log.info "RETURN is #{curses::KEY_RETURN} "
29
+ $log.info "ENTER is #{curses::KEY_ENTER} "
30
+ path = File.dirname(__FILE__)
31
+ $log.info "PATH: #{path}"
32
+ FFI::NCurses.init_pair(10, FFI::NCurses::BLACK, FFI::NCurses::GREEN) # statusline
33
+ @file = "#{path}/data/tennis.sqlite"
34
+ @db = SQLite3::Database.new(@file)
35
+ @tablename = "matches"
36
+ $ncurses_timeout = -1
37
+ end
38
+ def ORIGstatusline win, str, col = 0
39
+ win.printstring( FFI::NCurses.LINES-1, col, str, 10)
40
+ end
41
+ def oldstatusline win, str, column = 1
42
+ # LINES-2 prints on second last line so that box can be seen
43
+ win.printstring( FFI::NCurses.LINES-1, 0, " "*(win.width), 6, REVERSE)
44
+ # printing fields in two alternating colors so easier to see
45
+ str.split("|").each_with_index {|s,ix|
46
+ _color = 6
47
+ _color = 5 if ix%2==0
48
+ win.printstring( FFI::NCurses.LINES-1, column, s, _color, REVERSE)
49
+ column += s.length+1
50
+ }
51
+ end
52
+ def statusline win, str, column = 1
53
+ @status.text = str
54
+ end # }}}
55
+ def fetch_data db, sql # {{{
56
+ $log.debug "SQL: #{sql} "
57
+ columns, *rows = db.execute2(sql)
58
+ content = rows
59
+ return nil if content.nil? or content[0].nil?
60
+ datatypes = content[0].types #if @datatypes.nil?
61
+ return content, columns, datatypes
62
+ end # }}}
63
+ def view_details(table)
64
+ id = table.current_id
65
+
66
+ res = %x{ sqlite3 #{@file} -line "select * from #{@tablename} where rowid = '#{id}'"}
67
+ if res and !res.empty?
68
+ res = res.split("\n")
69
+ view res
70
+ else
71
+ alert("No row for #{id} in #{@tablename}")
72
+ end
73
+ end
74
+ def get_full_row_as_hash(table)
75
+ id = table.current_id
76
+ data, columns, datatypes = fetch_data(@db, "select * from #{@tablename} where rowid = '#{id}'")
77
+ hash = columns.zip(data.first).to_h
78
+ #$log.debug " HASH == #{hash}"
79
+ return hash
80
+ end
81
+ def filter_popup lb # {{{
82
+ ## present user with a popup allowing him to select range of rating title, range of year, status etc
83
+ ## for querying.
84
+ #rowdata = fetch_data(@db, "select title, actors, director, imdbrating, language, genre , metascore, imdbvotes from #{@tablename} WHERE rowid = #{id}")
85
+ data = []
86
+ _columns = ["tourney_name", "winner_name", "loser_name", "surface", "Year >", "Year <", "round", "level", "best_of"]
87
+ _columns.each {|c| data << "" }
88
+ _datatypes = ["text","text","text","char(10)","char(4)","char(4)","char(5)", "char(1)", "char(1)"]
89
+ ret, array = generic_edit "Filter", _columns, data, _datatypes
90
+ if ret == 0
91
+ # okay pressed
92
+ ## query database on values entered TODO
93
+ _filter_table(lb, _columns, array)
94
+ end
95
+ end # }}}
96
+ def _filter_table(lb, columns, fields)
97
+ cols = []
98
+ bind_vars = []
99
+ sql = "#{@query}"
100
+ fields.each_with_index { |f, ix|
101
+ next if f.text == ""
102
+ c = columns[ix].downcase
103
+ if c == "round"
104
+ cols << " round = ? "
105
+ bind_vars << "#{f.text}"
106
+ elsif c == "year >"
107
+ cols << " tourney_date >= ? "
108
+ bind_vars << "#{f.text}"
109
+ elsif c == "year <"
110
+ cols << " tourney_date <= ? "
111
+ bind_vars << "#{f.text}"
112
+ elsif c == "level"
113
+ cols << " tourney_level = ? "
114
+ bind_vars << "#{f.text}"
115
+ elsif c == "best_of"
116
+ cols << " best_of = ? "
117
+ bind_vars << "#{f.text}"
118
+ else
119
+ cols << columns[ix] + " LIKE ? "
120
+ bind_vars << "%#{f.text}%"
121
+ end
122
+ }
123
+ if !cols.empty?
124
+ sql += " WHERE " + cols.join(" AND ")
125
+ end
126
+ $log.debug " SQL: #{sql} "
127
+ $log.debug " ibv: #{bind_vars.join ', '} "
128
+ alist = @db.execute( sql, bind_vars)
129
+ if alist #and !alist.empty?
130
+ #lb.list = alist ## results in error, FIXME
131
+ lb.data = alist
132
+ else
133
+ #alert "No rows returned. Check your query"
134
+ end
135
+ end
136
+ ## generic edit messagebox
137
+ ## @param array of column labels
138
+ ## @param array of data to edit, or blank
139
+ ## @param array of sqlite3 datatypes (real int text char(9) date)
140
+ ## @return offset of button pressed and array of LabeledFields
141
+ ## 0 = ok, 1 = cancel.
142
+ ## Use element.text() to get edited value of each element of array
143
+ def generic_edit _title, _columns, data, _datatypes
144
+ require 'umbra/messagebox'
145
+ require 'umbra/labeledfield'
146
+
147
+ array = [] # array of labeledfield we will create, and return
148
+ mb = MessageBox.new title: _title, width: 80 do
149
+ data.each_with_index do |r, ix|
150
+ dt = _datatypes[ix]
151
+ _w, _ml = calc_width_from_datatype( dt )
152
+ $log.debug " MESSAGE_BOX::: #{_columns[ix]} ==> #{_datatypes[ix]} "
153
+
154
+ x = LabeledField.new label: _columns[ix], name: _columns[ix], text: r, col: 20, width: _w, maxlen: _ml, color_pair: CP_CYAN, attr: REVERSE
155
+
156
+ $log.debug " MESSAGE_BOX::: after create #{_columns[ix]} ==> #{_datatypes[ix]} "
157
+ array << x
158
+ add x
159
+ $log.debug " MESSAGE_BOX::: after add #{_columns[ix]} ==> #{_datatypes[ix]} "
160
+ end
161
+ end
162
+ ret = mb.run
163
+ return ret, array
164
+ end
165
+ ## Given an sqlite3 datatype, returns width and maximum length.
166
+ ## Used in messageboxes.
167
+ def calc_width_from_datatype dt
168
+ if dt == "text"
169
+ _w = 50
170
+ _ml = 100
171
+ elsif dt == "date"
172
+ _w = 12
173
+ _ml = 20
174
+ elsif dt == "real"
175
+ _w = 10
176
+ _ml = 10
177
+ elsif dt == "int"
178
+ _w = 8
179
+ _ml = 8
180
+ elsif dt.index("char")
181
+ a = dt.match(/(\d+)/)
182
+ _w = a.captures().first.to_i
183
+ _ml = _w
184
+ else
185
+ _w = _ml = 30
186
+ end
187
+ return _w, _ml
188
+ end
189
+ begin
190
+ include Umbra
191
+ init_curses
192
+ startup
193
+ win = Window.new
194
+ # by making this is label with -1 as row, it will recalc and redraw when window height is changed.
195
+ @status = Label .new( text: "Press C-q to quit", row: -1, col: 0, width: -1 )
196
+ def @status.print_label(win, row, col, format, value, _color, _attr)
197
+ column = col
198
+ win.printstring( row, 0, " "*(win.width), 6, REVERSE)
199
+ value.split("|").each_with_index {|s,ix|
200
+ _color = 6
201
+ _color = 5 if ix%2==0
202
+ win.printstring( row, column, s, _color, REVERSE)
203
+ column += s.length+1
204
+ }
205
+ end
206
+ #statusline(win, " "*(win.width-0), 0)
207
+ #statusline(win, "Press C-q to quit #{win.height}:#{win.width}", 20)
208
+ #title = Label.new( :text => "Tennis Query", :row => 0, :col => 0 , :width => FFI::NCurses.COLS-1,
209
+ title = Label.new( :text => "Tennis Query", :row => 0, :col => 0 , :width => -1,
210
+ :justify => :center, :color_pair => 0, :attr => REVERSE)
211
+
212
+ #win.title "Tennis Query", 3, REVERSE
213
+ form = Form.new win
214
+ form.add_widget title, @status
215
+
216
+ ## -1 here suggests that this widget should extend till the end, less one.
217
+ ## This is not absolute, it is relative to row or col.
218
+ box = Box.new row: 1, col: 0, width: -1, height: -2
219
+ #box = Box.new row: 1, col: 0, width: -1, height: FFI::NCurses.LINES-2
220
+ #form.position_below(box, label)
221
+ #box.below(title)
222
+ #box.expand_right(0).expand_down(-1)
223
+ #box.expand_down(-1)
224
+ @query = "SELECT rowid, tourney_id, tourney_name, tourney_date, winner_name, loser_name, score, round FROM matches "
225
+ @order_by = "ORDER BY tourney_date, tourney_name, match_num"
226
+ data, columns, datatypes = fetch_data(@db, "#{@query} #{@order_by}")
227
+
228
+ table = Table.new(columns: columns, data: data) do |tt|
229
+ tt.column_hidden(0, true)
230
+ tt.column_hidden(1, true)
231
+ tt.column_width(6, 24)
232
+ end
233
+ #table.column_hide(0)
234
+ #table.column_hide(1)
235
+ #table.column_width(6, 24)
236
+ box.title = "#{table.row_count} rows"
237
+ box.fill table
238
+ tabular = table.tabular
239
+ # this is one way of hiding a column if we don't want to use the hide option.
240
+ # But we have to supply formatstring, and take care of separator and headings too.
241
+ #def tabular.convert_value_to_text row, format_string, index
242
+ #"%-5.5s |%-10.10s |%-12.12s |%-12.12s |%-27.27s |%-27.27s |%-24.24s |%-5.5s" % row
243
+ #"%-12.12s |%-12.12s |%-27.27s |%-27.27s |%-24.24s |%-5.5s" % row[2..-1]
244
+ #end
245
+ #def table._format_value line, index, state
246
+ #end
247
+ def table.color_of_data_row index, state, data_index
248
+ arr = _format_color index, state
249
+ if index == 0 ## header
250
+ arr = @header_color_pair || [ CP_MAGENTA, REVERSE ]
251
+ elsif data[data_index][-1] == "SF"
252
+ arr = [ CP_WHITE, BOLD | arr[1] ]
253
+ elsif data[data_index][-1] == "F"
254
+ arr = [ CP_YELLOW, BOLD | arr[1]]
255
+ end
256
+
257
+ arr
258
+ end
259
+ table.bind_event(:CHANGED) { |obj| box.title = "#{obj.row_count} rows"; }
260
+ table.bind_event(:PRESS) { |obj| alert( " Pressed on #{obj.current_index} :: #{obj.curpos} ") }
261
+ table.command do |ix|
262
+ #rowid = table.current_id
263
+ data = table.current_row_as_array
264
+ if data
265
+ #t_id = data[1]
266
+ #t_name = data[2]
267
+ hash = table.current_row_as_hash
268
+ score = hash['score']
269
+ h1 = get_full_row_as_hash(table)
270
+ surface = h1['surface']
271
+ draw = h1['draw_size']
272
+ level = h1['tourney_level']
273
+ #statusline(win, "#{rowid} | #{t_id} | #{t_name} ")
274
+ statusline(win, data[0..4].join("| ") + " | #{score} | #{surface} | #{draw} | #{level} " )
275
+ end
276
+ end
277
+ table.bind_key( 'v', 'view details') { view_details(table) }
278
+ table.bind_key( ?\C-s, 'filter popup') { filter_popup(table) }
279
+
280
+
281
+ form.add_widget box, table
282
+
283
+
284
+ form.pack
285
+ form.repaint
286
+ form.select_first_field
287
+ win.wrefresh
288
+
289
+ y = x = 1
290
+ while (ch = win.getkey) != FFI::NCurses::KEY_CTRL_Q
291
+ next if ch == -1
292
+ form.handle_key ch
293
+ #statusline(win, "Pressed #{ch} on ", 70)
294
+ win.wrefresh
295
+ end
296
+
297
+ rescue Object => e
298
+ @window.destroy if @window
299
+ FFI::NCurses.endwin
300
+ puts e
301
+ puts e.backtrace.join("\n")
302
+ ensure
303
+ @window.destroy if @window
304
+ FFI::NCurses.endwin
305
+ puts
306
+ end