ncumbra 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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