ncumbra 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/umbra/textbox.rb CHANGED
@@ -4,26 +4,21 @@
4
4
  # Author: j kepler http://github.com/mare-imbrium/canis/
5
5
  # Date: 2018-03-24 - 12:39
6
6
  # License: MIT
7
- # Last update: 2018-04-20 12:58
7
+ # Last update: 2018-05-10 11:06
8
8
  # ----------------------------------------------------------------------------- #
9
9
  # textbox.rb Copyright (C) 2012-2018 j kepler
10
10
  ## TODO -----------------------------------
11
11
  # improve the object sent when row change or cursor movement
12
- #
12
+ ## 2018-05-08 - extend Multiline
13
13
  #
14
14
  # ----------------------------------------
15
15
  ## CHANGELOG
16
16
  #
17
17
  # ----------------------------------------
18
- require 'umbra/widget'
18
+ require 'umbra/multiline'
19
19
  module Umbra
20
- class Textbox < Widget
21
- attr_reader :list # list containing data
20
+ class Textbox < Multiline
22
21
  attr_accessor :file_name # filename passed in for reading
23
- attr_accessor :selection_key # key used to select a row
24
- attr_accessor :selected_index # row selected, may change to plural
25
- attr_accessor :selected_color_pair # row selected color_pair
26
- attr_accessor :selected_attr # row selected color_pair
27
22
  #attr_accessor :cursor # position of cursor in line ??
28
23
  =begin
29
24
  attr_accessor :selected_mark # row selected character
@@ -32,55 +27,18 @@ class Textbox < Widget
32
27
  =end
33
28
 
34
29
  def initialize config={}, &block
35
- @focusable = false # will only be set true if data is set
36
- @editable = false
37
- @pstart = 0 # which row does printing start from
38
- @current_index = 0 # index of row on which cursor is
39
- @selected_index = nil # index of row selected
40
- @selection_key = 0 # presently no selection. Actually 0 is Ctrl-Space.
41
30
  @highlight_attr = FFI::NCurses::A_BOLD
42
- @to_print_border = false
43
31
  @row_offset = 0
44
32
  @col_offset = 0
45
- @pcol = 0
46
33
  @curpos = 0 # current cursor position in buffer (NOT screen/window/field)
47
- =begin
48
-
49
- @selected_color_pair = CP_RED
50
- @selected_attr = REVERSE
51
- @selected_mark = 'x' # row selected character
52
- @unselected_mark = ' ' # row unselected character (usually blank)
53
- @current_mark = '>' # row current character (default is >)
54
- =end
55
- register_events([:ENTER_ROW, :LEAVE_ROW, :CURSOR_MOVE]) #
34
+ #register_events([:ENTER_ROW, :LEAVE_ROW, :CURSOR_MOVE]) #
35
+ register_events([:CURSOR_MOVE]) #
56
36
  super
57
37
 
58
- map_keys
59
- # internal width and height
60
- @repaint_required = true
61
38
  end
62
- def _calculate_dimensions
63
- @int_width = @width
64
- @int_height = @height # used here only
65
- @scroll_lines ||= @int_height/2 # fix these to be perhaps half and one of ht
66
- @page_lines = @int_height
67
- @calculate_dimensions = true
68
- end
69
- # set list of data to be displayed.
39
+ # set list of data to be displayed from filename. {{{
70
40
  # NOTE this can be called again and again, so we need to take care of change in size of data
71
41
  # as well as things like current_index and selected_index or indices.
72
- def list=(alist)
73
- if !alist or alist.size == 0
74
- self.focusable=(false)
75
- else
76
- self.focusable=(true)
77
- end
78
- @list = alist
79
- @repaint_required = true
80
- @pstart = @current_index = 0
81
- @selected_index = nil
82
- @focusable = true # too late since form is not rechecking its array
83
- end
84
42
  def file_name=(fp)
85
43
  raise "File #{fp} not readable" unless File.readable? fp
86
44
  return Dir.new(fp).entries if File.directory? fp
@@ -106,126 +64,28 @@ class Textbox < Widget
106
64
  self.list = content
107
65
  raise "list not set" unless @list
108
66
 
109
- end
110
-
111
- def repaint
112
- _calculate_dimensions unless @calculate_dimensions
113
- return unless @repaint_required
114
- return unless @list
115
- win = @graphic
116
- r,c = @row, @col
117
- _attr = @attr || NORMAL
118
- _color = @color_pair || CP_WHITE
119
- #_bordercolor = @border_color_pair || CP_BLUE
120
- rowpos = 1
121
- coffset = 0
122
- #width = win.width-1
123
- width = @width
124
- files = @list
125
-
126
- #ht = win.height-2
127
- ht = @height
128
- cur = @current_index
129
- st = pstart = @pstart # previous start
130
- pend = pstart + ht -1 #- previous end
131
- if cur > pend
132
- st = (cur -ht) + 1 #+
133
- elsif cur < pstart
134
- st = cur
135
- end
136
- $log.debug "LISTBOX: cur = #{cur} st = #{st} pstart = #{pstart} pend = #{pend} listsize = #{@list.size} "
137
- hl = cur
138
- y = 0
139
- ctr = 0
140
- filler = " "*(width)
141
- files.each_with_index {|f, y|
142
- next if y < st
143
- colr = CP_WHITE # white on bg -1
144
- mark = @unselected_mark
145
- if y == hl
146
- attr = @highlight_attr #FFI::NCurses::A_REVERSE
147
- mark = @current_mark
148
- rowpos = ctr
149
- else
150
- attr = FFI::NCurses::A_NORMAL
151
- end
152
- if y == @selected_index
153
- colr = @selected_color_pair
154
- attr = @selected_attr
155
- mark = @selected_mark
156
- end
157
- #ff = "#{mark} #{f}"
158
- ff = f
159
- if ff
160
- if ff.size > width
161
- #ff = ff[0...width]
162
- # pcol can be greater than width then we get null
163
- if @pcol < ff.size
164
- ff = ff[@pcol..@pcol+width-1]
165
- else
166
- ff = ""
167
- end
168
- else
169
- if @pcol < ff.size
170
- ff = ff[@pcol..-1]
171
- else
172
- ff = ""
173
- end
174
- end
175
- end
176
- ff = "" unless ff
177
-
178
- win.printstring(ctr + r, coffset+c, filler, colr )
179
- win.printstring(ctr + r, coffset+c, ff, colr, attr)
180
- ctr += 1
181
- @pstart = st
182
- break if ctr >= ht #-
183
- }
184
- ## if counter < ht then we need to clear the rest in case there was data earlier {{{
185
- if ctr < ht
186
- while ctr < ht
187
- win.printstring(ctr + r, coffset+c, filler, _color )
188
- ctr += 1
189
- end
190
- end # }}}
191
- @row_offset = rowpos
192
- #@col_offset = coffset # this way form can pick it up XXX can't override it like this
193
- @repaint_required = false
194
- end
195
-
196
- def getvalue
197
- @list
198
- end
67
+ end # }}}
199
68
 
200
- # ensure text has been passed or action
201
- def getvalue_for_paint
202
- raise
203
- ret = getvalue
204
- #@text_offset = @surround_chars[0].length
205
- #@surround_chars[0] + ret + @surround_chars[1]
69
+ # returns current row
70
+ def current_row
71
+ @list[@current_index]
206
72
  end
207
73
 
208
74
 
209
- def map_keys
210
- return if @keys_mapped
211
- bind_keys([?k,FFI::NCurses::KEY_UP], "Up") { cursor_up }
212
- bind_keys([?j,FFI::NCurses::KEY_DOWN], "Down") { cursor_down }
213
- bind_keys([?l,FFI::NCurses::KEY_RIGHT], "Right") { cursor_forward }
214
- bind_keys([?h,FFI::NCurses::KEY_LEFT], "Left") { cursor_backward }
215
- bind_key(?g, 'goto_start') { goto_start }
216
- bind_key(?G, 'goto_end') { goto_end }
217
- bind_key(FFI::NCurses::KEY_CTRL_A, 'cursor_home') { cursor_home }
218
- bind_key(FFI::NCurses::KEY_CTRL_E, 'cursor_end') { cursor_end }
219
- bind_key(FFI::NCurses::KEY_CTRL_F, 'page_forward') { page_forward }
220
- bind_key(32, 'page_forward') { page_forward }
221
- bind_key(FFI::NCurses::KEY_CTRL_B, 'page_backward'){ page_backward }
222
- bind_key(FFI::NCurses::KEY_CTRL_U, 'scroll_up') { scroll_up }
223
- bind_key(FFI::NCurses::KEY_CTRL_D, 'scroll_down') { scroll_down }
224
- @keys_mapped = true
225
- end
226
-
227
- # listbox key handling
75
+ ## textbox key handling
76
+ ## Textbox varies from multiline in that it fires a cursor_move event whrease the parent
77
+ ## fires a cursor_move event which is mostly used for testing out
228
78
  def handle_key ch
79
+ begin
80
+ ret = super
81
+ return ret
82
+ ensure
83
+ if @repaint_required
84
+ fire_handler(:CURSOR_MOVE, [@col_offset, @current_index, @curpos, @pcol, ch ]) # 2018-03-25 - improve this
85
+ end
86
+ end
87
+ end
88
+ def OLDhandle_key ch # {{{
229
89
  return :UNHANDLED unless @list
230
90
  # save old positions so we know movement has happened
231
91
  old_current_index = @current_index
@@ -233,18 +93,8 @@ class Textbox < Widget
233
93
  old_col_offset = @col_offset
234
94
 
235
95
  begin
236
- case ch
237
- when @selection_key
238
- @repaint_required = true
239
- if @selected_index == @current_index
240
- @selected_index = nil
241
- else
242
- @selected_index = @current_index
243
- end
244
- else
245
96
  ret = super
246
97
  return ret
247
- end
248
98
  ensure
249
99
  @current_index = 0 if @current_index < 0
250
100
  @current_index = @list.size-1 if @current_index >= @list.size
@@ -253,30 +103,25 @@ class Textbox < Widget
253
103
  if @current_index != old_current_index
254
104
  on_leave_row old_current_index
255
105
  on_enter_row @current_index
256
- #fire_handler(:CHANGE_ROW, [old_current_index, @current_index, ch ]) # 2018-03-26 - improve this
257
106
  end
258
107
  @repaint_required = true
259
108
  fire_handler(:CURSOR_MOVE, [@col_offset, @current_index, @curpos, @pcol, ch ]) # 2018-03-25 - improve this
260
109
  end
261
110
  end
262
- end
263
- # advance col_offset (where cursor will be displayed on screen)
111
+ end # }}}
112
+ # advance col_offset (where cursor will be displayed on screen) {{{
264
113
  # @param [Integer] advance by n (can be negative or positive)
265
114
  # @return -1 if cannot advance
266
- private def add_col_offset num
115
+ private def OLDadd_col_offset num
267
116
  x = @col_offset + num
268
117
  return -1 if x < 0
269
118
  return -1 if x > @int_width
270
119
  # is it a problem that i am directly changing col_offset ??? XXX
271
120
  @col_offset += num
272
121
  end
273
- # returns current row
274
- def current_row
275
- @list[@current_index]
276
- end
277
122
 
278
123
  # move cursor forward one character, called with KEY_RIGHT action.
279
- def cursor_forward
124
+ def OLDcursor_forward
280
125
  blen = current_row().size-1
281
126
  if @curpos < blen
282
127
  if add_col_offset(1)==-1 # go forward if you can, else scroll
@@ -286,7 +131,7 @@ class Textbox < Widget
286
131
  @curpos += 1
287
132
  end
288
133
  end
289
- def cursor_backward
134
+ def OLDcursor_backward
290
135
 
291
136
  if @col_offset > 0
292
137
  @curpos -= 1
@@ -302,14 +147,14 @@ class Textbox < Widget
302
147
  end
303
148
  end
304
149
  # position cursor at start of field
305
- def cursor_home
150
+ def OLDcursor_home
306
151
  @curpos = 0
307
152
  @pcol = 0
308
153
  set_col_offset 0
309
154
  end
310
155
  # goto end of line.
311
156
  # This should be consistent with moving the cursor to the end of the row with right arrow
312
- def cursor_end
157
+ def OLDcursor_end
313
158
  blen = current_row().length
314
159
  if blen < @int_width
315
160
  set_col_offset blen # just after the last character
@@ -322,31 +167,19 @@ class Textbox < Widget
322
167
  # regardless of pcol (panning)
323
168
  end
324
169
  # go to start of file (first line)
325
- def goto_start
170
+ def OLDgoto_start
326
171
  @current_index = 0
327
172
  @pcol = @curpos = 0
328
173
  set_col_offset 0
329
174
  end
330
175
  # go to end of file (last line)
331
- def goto_end
176
+ def OLDgoto_end
332
177
  @current_index = @list.size-1
333
178
  end
334
- def scroll_down
335
- @current_index += @scroll_lines
336
- end
337
- def scroll_up
338
- @current_index -= @scroll_lines
339
- end
340
- def page_backward
341
- @current_index -= @page_lines
342
- end
343
- def page_forward
344
- @current_index += @page_lines
345
- end
346
179
  # sets the visual cursor on the window at correct place
347
180
  # NOTE be careful of curpos - pcol being less than 0
348
181
  # @param [Integer] position in data on the line
349
- private def set_col_offset x=@curpos
182
+ private def OLD_set_col_offset x=@curpos
350
183
  @curpos = x || 0 # NOTE we set the index of cursor here - WHY TWO THINGS ??? XXX
351
184
  #return -1 if x < 0
352
185
  #return -1 if x > @width
@@ -359,29 +192,9 @@ class Textbox < Widget
359
192
  @col_offset = @int_width if @col_offset > @int_width
360
193
  return
361
194
  end
362
- def cursor_up
363
- @current_index -= 1
364
- end
365
- # go to next row
366
- def cursor_down
367
- @current_index += 1
368
- end
369
- def on_enter
370
- super
371
- return unless @list
372
- on_enter_row @current_index
373
- end
374
- def on_leave
375
- super
376
- on_leave_row @current_index
377
- end
378
- # called when object leaves a row and when object is exited.
379
- def on_leave_row index
380
- fire_handler(:LEAVE_ROW, [index]) # 2018-03-26 - improve this
381
- end
382
195
  # called whenever a row entered.
383
196
  # Call when object entered, also.
384
- def on_enter_row index
197
+ def OLD_on_enter_row index
385
198
  #fire_handler(:ENTER_ROW, [old_current_index, @current_index, ch ]) # 2018-03-26 - improve this
386
199
  fire_handler(:ENTER_ROW, [@current_index]) # 2018-03-26 - improve this
387
200
  # if cursor ahead of blen then fix it
@@ -396,7 +209,7 @@ class Textbox < Widget
396
209
  end
397
210
  end
398
211
  @col_offset = 0 if @col_offset < 0
399
- end
212
+ end # }}}
400
213
  ## border {{{
401
214
  private def print_border row, col, height, width, color, att=FFI::NCurses::A_NORMAL
402
215
  raise
@@ -6,7 +6,7 @@ require 'umbra/button'
6
6
  # Author: j kepler http://github.com/mare-imbrium/umbra/
7
7
  # Date: 2018-03-17 - 22:50
8
8
  # License: MIT
9
- # Last update: 2018-04-07 23:08
9
+ # Last update: 2018-05-14 14:35
10
10
  # ----------------------------------------------------------------------------- #
11
11
  # togglebutton.rb Copyright (C) 2012-2018 j kepler
12
12
  #
@@ -50,14 +50,12 @@ class ToggleButton < Button
50
50
  # boolean, which value to use currently, onvalue or offvalue
51
51
  attr_accessor :value
52
52
  # characters to use for surround, array, default square brackets
53
- attr_accessor :surround_chars
53
+ attr_property :surround_chars
54
54
  # 2018-04-02 - removing variable
55
55
  #attr_accessor :variable # value linked to this variable which is a boolean
56
56
  # background to use when selected, if not set then default
57
57
  # 2018-04-02 - unused so commenting off. color_pair is not used here or in checkbox
58
- #attr_accessor :selected_bgcolor
59
- #attr_accessor :selected_color
60
- attr_accessor :selected_color_pair
58
+ attr_property :selected_color_pair
61
59
 
62
60
  def initialize config={}, &block
63
61
  super
data/lib/umbra/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Umbra
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/umbra/widget.rb CHANGED
@@ -3,10 +3,39 @@
3
3
  # extend this, if it wants to be repainted or wants focus. Otherwise.
4
4
  # form will be unaware of it.
5
5
  # 2018-03-08 -
6
- #require 'umbra/form' # for EventHandler !!!
6
+
7
7
  require 'umbra/eventhandler' # for register_events and fire_handler etc
8
8
  require 'umbra/keymappinghandler' # for bind_key and process_key
9
9
 
10
+ class Module # {{{
11
+
12
+ def attr_property(*symbols)
13
+ symbols.each { |sym|
14
+ class_eval %{
15
+ def #{sym}=(val)
16
+ oldvalue = @#{sym}
17
+ newvalue = val
18
+ if @_object_created.nil?
19
+ @#{sym} = newvalue
20
+ end
21
+ # return(self) if oldvalue.nil? || @_object_created.nil?
22
+ return(self) if @_object_created.nil?
23
+
24
+ if oldvalue != newvalue
25
+ begin
26
+ fire_property_change("#{sym}", oldvalue, newvalue)
27
+ @#{sym} = newvalue
28
+ rescue PropertyVetoException
29
+ $log.warn "PropertyVetoException for #{sym}:" + oldvalue.to_s + "-> "+ newvalue.to_s
30
+ end
31
+ end # oldvalue !=
32
+ self
33
+ end # def
34
+ attr_reader sym
35
+ }
36
+ }
37
+ end # def
38
+ end # module }}}
10
39
  module Umbra
11
40
  class FieldValidationException < RuntimeError
12
41
  end
@@ -14,27 +43,29 @@ class Widget
14
43
  include EventHandler
15
44
  include KeyMappingHandler
16
45
  # common interface for text related to a field, label, textview, button etc
17
- attr_accessor :text, :width, :height
46
+ attr_property :text
47
+ attr_property :width, :height ## FIXME this won't trigger repaint or property !!!
18
48
 
19
49
  # foreground and background colors when focussed. Currently used with buttons and field
20
50
  # Form checks and repaints on entry if these are set.
21
- attr_accessor :highlight_color_pair
22
- attr_accessor :highlight_attr
51
+ attr_property :highlight_color_pair
52
+ attr_property :highlight_attr
23
53
 
24
54
  # NOTE: 2018-03-04 - user will have to call repaint_required if he changes color or coordinates.
25
- attr_accessor :row, :col # location of object
55
+ attr_accessor :col # location of object
56
+ attr_writer :row # location of object
26
57
  #attr_writer :color, :bgcolor # normal foreground and background 2018-03-08 - now color_pair
27
58
  # moved to a method which calculates color 2011-11-12
28
- attr_accessor :color_pair # instead of colors give just color_pair
29
- attr_accessor :attr # attribute bold, normal, reverse
59
+ attr_property :color_pair # instead of colors give just color_pair
60
+ attr_property :attr # attribute bold, normal, reverse
30
61
  attr_accessor :name # name to refr to or recall object by_name
31
62
  attr_accessor :curpos # cursor position inside object - column, not row.
32
- attr_reader :config # can be used for popping user objects too
63
+ attr_reader :config # can be used for popping user objects too. NOTE unused
33
64
  #attr_accessor :form # made accessor 2008-11-27 22:32 so menu can set
34
65
  attr_accessor :graphic # window which should be set by form when adding 2018-03-19
35
66
  attr_accessor :state # normal, selected, highlighted
36
67
  attr_reader :row_offset, :col_offset # where should the cursor be placed to start with
37
- attr_accessor :visible # boolean # 2008-12-09 11:29
68
+ attr_property :visible # boolean # 2008-12-09 11:29
38
69
  # if changing focusable property of a field after form creation, you may need to call
39
70
  # pack again, or atl east update_focusables
40
71
  attr_reader :focusable # boolean can this get focus # 2018-03-21 - 23:13
@@ -104,7 +135,7 @@ class Widget
104
135
  #alias :modified :set_modified
105
136
 
106
137
  # triggered whenever a widget is entered.
107
- # TODO should we not fix cursor at this point ?
138
+ # NOTE should we not fix cursor at this point (on_enter) ?
108
139
  def on_enter
109
140
  @state = :HIGHLIGHTED # duplicating since often these are inside containers
110
141
  @focussed = true
@@ -126,7 +157,7 @@ class Widget
126
157
  # row and col is where a widget starts. offsets usually take into account borders.
127
158
  # the offsets typically are where the cursor should be positioned inside, upon on_enter.
128
159
  def rowcol
129
- return @row+@row_offset, @col+@col_offset
160
+ return self.row+@row_offset, self.col+@col_offset
130
161
  end
131
162
  ## return the value of the widget.
132
163
  def getvalue
@@ -144,12 +175,13 @@ class Widget
144
175
  r,c = rowcol
145
176
  $log.debug("widget repaint : r:#{r} c:#{c} col:#{@color_pair}" )
146
177
  value = getvalue_for_paint
147
- len = @width || value.length
178
+ len = self.width || value.length
148
179
  acolor = @color_pair
149
180
  @graphic.printstring r, c, "%-*s" % [len, value], acolor, attr()
150
181
  end
151
182
 
152
183
  def destroy
184
+ raise "what is this dong here still SHOULD Not be CALLED"
153
185
  $log.debug "DESTROY : widget #{@name} "
154
186
  panel = @window.panel
155
187
  Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
@@ -186,10 +218,13 @@ class Widget
186
218
  # is the entire widget to be repainted including things like borders and titles
187
219
  # earlier took a default of true, now must be explicit. Perhaps, not used currently.
188
220
  def repaint_all(tf)
221
+ # NOTE NOT USED
222
+ raise " not used repaint all"
189
223
  @repaint_all = tf
190
224
  @repaint_required = tf
191
225
  end
192
226
  # shortcut for users to indicate that a widget should be redrawn since some property has been changed.
227
+ # Now that I have created attr_property this may not be needed
193
228
  def touch
194
229
  @repaint_required = true
195
230
  end
@@ -210,10 +245,34 @@ class Widget
210
245
  @_form = aform
211
246
  end
212
247
  def focusable=(bool)
213
- $log.debug " inside focusable= with #{bool} "
248
+ #$log.debug " inside focusable= with #{bool} "
214
249
  @focusable = bool
215
250
  @_form.update_focusables if @_form
216
251
  end
252
+
253
+ ## TODO maybe check for decimal between 0 and 1 which will be percentage of width
254
+ def width
255
+ return nil unless @width ## this is required otherwise checking for nil will fail
256
+ if @width < 0
257
+ return ( FFI::NCurses.COLS + @width ) - self.col + 1
258
+ #return ( FFI::NCurses.COLS + @width ) #- self.col + 1
259
+ end
260
+ @width
261
+ end
262
+ def height
263
+ return nil unless @height
264
+ if @height < 0
265
+ return ((FFI::NCurses.LINES + @height) - self.row) + 1
266
+ #return (FFI::NCurses.LINES + @height)
267
+ end
268
+ @height
269
+ end
270
+ def row
271
+ if @row < 0
272
+ return FFI::NCurses.LINES + @row
273
+ end
274
+ @row
275
+ end
217
276
  #
218
277
  ## ADD HERE WIDGET
219
278
  end #
data/lib/umbra/window.rb CHANGED
@@ -1,22 +1,35 @@
1
1
  require 'ffi-ncurses'
2
2
  require 'ffi-ncurses/widechars'
3
3
 
4
+ ## NOTE: conflict between KEY_RESIZE and wtimeout or halfdelay.
5
+ ## Setting a timeout or delay allows an application to respond to updates without a keypress,
6
+ ## such as continuous updates.
7
+ ## However, this means that KEY_RESIZE will not work unless a key is pressed.
8
+ ## If resizing is important, then caller may set $ncurses_timeout to -1.
9
+
10
+
11
+
12
+
4
13
  module Umbra
5
14
 
6
- # attribute constants, use them to specify an attrib for a widget or window.
7
- BOLD = FFI::NCurses::A_BOLD
8
- REVERSE = FFI::NCurses::A_REVERSE
9
- UNDERLINE = FFI::NCurses::A_UNDERLINE
10
- NORMAL = FFI::NCurses::A_NORMAL
11
-
12
- # color constants, use these when creating a color
13
- COLOR_BLACK = FFI::NCurses::BLACK
14
- COLOR_WHITE = FFI::NCurses::WHITE
15
- COLOR_BLUE = FFI::NCurses::BLUE
16
- COLOR_RED = FFI::NCurses::RED
17
- COLOR_GREEN = FFI::NCurses::GREEN
18
- COLOR_CYAN = FFI::NCurses::CYAN
19
- COLOR_MAGENTA = FFI::NCurses::MAGENTA
15
+ ## attribute constants, use them to specify an attrib for a widget or window.
16
+ BOLD = FFI::NCurses::A_BOLD
17
+ REVERSE = FFI::NCurses::A_REVERSE
18
+ UNDERLINE = FFI::NCurses::A_UNDERLINE
19
+ NORMAL = FFI::NCurses::A_NORMAL
20
+
21
+ ## color constants, use these when creating a color
22
+ COLOR_BLACK = FFI::NCurses::BLACK
23
+ COLOR_WHITE = FFI::NCurses::WHITE
24
+ COLOR_BLUE = FFI::NCurses::BLUE
25
+ COLOR_RED = FFI::NCurses::RED
26
+ COLOR_GREEN = FFI::NCurses::GREEN
27
+ COLOR_CYAN = FFI::NCurses::CYAN
28
+ COLOR_MAGENTA = FFI::NCurses::MAGENTA
29
+
30
+ ## key constants
31
+ KEY_ENTER = 13 ## FFI::NCurses::KEY_ENTER is 343 ???
32
+ KEY_RETURN = 10 ## already defined by ffi
20
33
 
21
34
  # Initialize ncurses before any program.
22
35
  # Reduce the value of $ncurses_timeout if you want a quicker response to Escape keys or continuous updates.
@@ -125,6 +138,19 @@ module Umbra
125
138
  return @pointer
126
139
  end
127
140
 
141
+ ## create a window and return window, or yield window to block
142
+ def self.create h=0, w=0, top=0, left=0
143
+ win = Window.new h, w, top, left
144
+ return win unless block_given?
145
+
146
+ begin
147
+ yield win
148
+ ensure
149
+ win.destroy
150
+ end
151
+
152
+ end
153
+
128
154
  # print string at x, y coordinates. replace this with the original one below
129
155
  # @deprecated
130
156
  def printstr(str, x=0,y=0)
@@ -253,18 +279,36 @@ module Umbra
253
279
  end # }}}
254
280
  # make a box around the window. Just a wrapper
255
281
  def box
282
+ @box = true
256
283
  FFI::NCurses.box(@pointer, 0, 0)
257
284
  end
258
- # print a centered title on top of window
285
+ # Print a centered title on top of window.
286
+ # NOTE : the string is not stored, so it can be overwritten.
259
287
  # This should be called after box, or else box will erase the title
260
288
  # @param str [String] title to print
261
289
  # @param color [Integer] color_pair
262
290
  # @param att [Integer] attribute constant
263
291
  def title str, color=0, att=BOLD
292
+ ## save so we can repaint if required
293
+ @title_data = [str, color, att]
264
294
  strl = str.length
265
295
  col = (@width - strl)/2
266
296
  printstring(0,col, str, color, att)
267
297
  end
268
298
 
299
+ ## repaints windows objects like title and box.
300
+ ## To be called from form on pressing redraw, and SIGWINCH
301
+ def repaint
302
+ curses.wclear(@pointer)
303
+ if @box
304
+ self.box
305
+ end
306
+ if @title_data
307
+ str, color, att = @title_data
308
+ self.title str, color, att
309
+ end
310
+ end
311
+
312
+
269
313
  end # window
270
314
  end # module