Class: RubyCurses::ScrollForm

Inherits:
Form
  • Object
show all
Defined in:
lib/rbcurse/rtabbedpane.rb,
lib/rbcurse/rscrollform.rb

Overview

An extension of Form that only displays and focuses on visible widgets

This is minimal, and is being expanded upon as a separate class in rscrollform.rb

Instance Attribute Summary collapse

Attributes inherited from Form

#active_index, #add_cols, #add_rows, #by_name, #col, #ext_col_offset, #ext_row_offset, #menu_bar, #modified, #navigation_policy, #padx, #pady, #parent_form, #row, #value, #widgets

Instance Method Summary collapse

Methods inherited from Form

#OLDbind_key, #addcol, #addrowcol, #digit_argument, #dump_data, #get_current_field, #on_enter, #on_leave, #process_key, #remove_widget, #select_field, #select_next_field, #select_prev_field, #set_menu_bar, #set_parent_buffer, #setpos, #to_s, #universal_argument, #validate_field

Methods included from Utils

#_process_key, #bind_key, #clean_string!, #get_color, #keycode_tos, #repeatm, #wrap_text

Methods included from EventHandler

#bind, #fire_handler, #fire_property_change

Constructor Details

#initialize(win, &block) ⇒ ScrollForm

Returns a new instance of ScrollForm.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rbcurse/rscrollform.rb', line 43

def initialize win, &block
  @target_window = win
  super
  @pminrow = @pmincol = 0
  @row_offset = @col_offset = 0
  @scroll_unit = 3
  @cols_panned = @rows_panned = 0
  @repaint_all = true

  # take display dimensions from window. It is safe to override immediately after form creation
  @display_h = win.height
  @display_w = win.width
  @display_h = (Ncurses.LINES - win.top - 2) if @display_h == 0
  @display_w = (Ncurses.COLS - win.left - 2) if @display_w == 0
  
  init_vars
end

Instance Attribute Details

#col_offsetObject

Returns the value of attribute col_offset.



37
38
39
# File 'lib/rbcurse/rscrollform.rb', line 37

def col_offset
  @col_offset
end

#cols_pannedObject (readonly)

Returns the value of attribute cols_panned.



42
43
44
# File 'lib/rbcurse/rscrollform.rb', line 42

def cols_panned
  @cols_panned
end

#display_hObject

ht of screen display



36
37
38
# File 'lib/rbcurse/rscrollform.rb', line 36

def display_h
  @display_h
end

#display_wObject

width of screen display



35
36
37
# File 'lib/rbcurse/rscrollform.rb', line 35

def display_w
  @display_w
end

#nameObject

Returns the value of attribute name.



41
42
43
# File 'lib/rbcurse/rscrollform.rb', line 41

def name
  @name
end

#orig_leftObject (readonly)

Returns the value of attribute orig_left.



39
40
41
# File 'lib/rbcurse/rscrollform.rb', line 39

def orig_left
  @orig_left
end

#orig_topObject (readonly)

Returns the value of attribute orig_top.



39
40
41
# File 'lib/rbcurse/rscrollform.rb', line 39

def orig_top
  @orig_top
end

#pmincolObject

advance / scroll columns



32
33
34
# File 'lib/rbcurse/rscrollform.rb', line 32

def pmincol
  @pmincol
end

#pminrowObject

advance / scroll rows (vertically)



34
35
36
# File 'lib/rbcurse/rscrollform.rb', line 34

def pminrow
  @pminrow
end

#row_offsetObject

Returns the value of attribute row_offset.



37
38
39
# File 'lib/rbcurse/rscrollform.rb', line 37

def row_offset
  @row_offset
end

#rows_pannedObject (readonly)

Returns the value of attribute rows_panned.



42
43
44
# File 'lib/rbcurse/rscrollform.rb', line 42

def rows_panned
  @rows_panned
end

#scroll_ctrObject

Returns the value of attribute scroll_ctr.



759
760
761
# File 'lib/rbcurse/rtabbedpane.rb', line 759

def scroll_ctr
  @scroll_ctr
end

#scroll_unitObject

by how much should be scroll



38
39
40
# File 'lib/rbcurse/rscrollform.rb', line 38

def scroll_unit
  @scroll_unit
end

#windowObject (readonly)

Returns the value of attribute window.



40
41
42
# File 'lib/rbcurse/rscrollform.rb', line 40

def window
  @window
end

Instance Method Details

#_print_more_columns_marker(tf) ⇒ Object

XXX needs to be called from repaint and print_border

Parameters:

  • should (boolean)

    marker be printed or not



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/rbcurse/rscrollform.rb', line 347

def _print_more_columns_marker tf
  tf = false
  if @pmincol + @display_w < @pad_w
    tf = true
  end
  marker = tf ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
  h = @display_h; w = @display_w
  r = @orig_top
  c = @orig_left
  @target_window.mvwaddch r+h, c+w-2, marker
  #
  # show if columns to left or not
  marker = @pmincol > 0 ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
  @target_window.mvwaddch r+h, c+1, marker
end

#_print_more_data_marker(tf) ⇒ Object

XXX needs to be called from repaint and print_border

Parameters:

  • should (boolean)

    marker be printed or not



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/rbcurse/rscrollform.rb', line 328

def _print_more_data_marker tf
  tf = false
  # the bottom marker meaning there's more data below
  if @pminrow + @display_h < @pad_h
    tf = true
  end
  marker = tf ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_VLINE
  h = @display_h; w = @display_w
  r = @orig_top
  c = @orig_left
  $log.debug " more data #{r+h-1}, #{c+w-1} : row #{r} h #{h} w #{w} col #{c} "
  @target_window.mvwaddch r+h-1, c+w-0, marker
  # the top marker to show that there is data above
  marker = @pminrow > 0 ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_VLINE
  @target_window.mvwaddch r+1, c+w-0, marker
end

#add_widget(w) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/rbcurse/rscrollform.rb', line 273

def add_widget w
  super
  $log.debug " inside add_widget #{w.name}  pad w #{@pad_w} #{w.col}, #{@pad_h}  "
  if w.col >= @pad_w
    @pad_w += 10 # XXX currently just a guess value, we need length and maybe some extra
    @window.wresize(@pad_h, @pad_w) if @pad
  end
  if w.row >= @pad_h
    @pad_h += 10 # XXX currently just a guess value, we need length and maybe some extra
    $log.debug " SCROLL add_widget ..."
    @window.wresize(@pad_h, @pad_w) if @pad
  end
end

#create_padObject



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rbcurse/rscrollform.rb', line 90

def create_pad
  raise "Pad already created" if @pad
  r = @top
  c = @left
  layout = { :height => @pad_h, :width => @pad_w, :top => r, :left => c } 
  @window = VER::Pad.create_with_layout(layout)
  
  @window.name = "Pad::ScrollPad" # 2010-02-02 20:01 
  @name = "Form::ScrollForm"
  @pad = @window
  return @window
end

#first_visible_component_indexindex, -1

returns index of first visible component. Currently using column index I am doing this for horizontal scrolling presently

Returns:

  • (index, -1)

    -1 if none visible, else index/offset



301
302
303
304
305
306
# File 'lib/rbcurse/rscrollform.rb', line 301

def first_visible_component_index
  @widgets.each_with_index do |w, ix|
    return ix if visible?(w) and focusable?(w)
  end
  return -1
end

#focusable?(w) ⇒ Boolean

Returns:

  • (Boolean)


322
323
324
# File 'lib/rbcurse/rscrollform.rb', line 322

def focusable?(w)
  w.focusable and visible?(w)
end

#handle_key(ch) ⇒ Object

ScrollForm handle key, scrolling



789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
# File 'lib/rbcurse/rtabbedpane.rb', line 789

def handle_key ch
  $log.debug " inside ScrollForm handlekey #{ch} "
  # do the scrolling thing here top left prow and pcol of pad to be done
  # # XXX TODO check whether we can scroll before incrementing esp cols_panned etc
  case ch
  when ?\M-l.getbyte(0)
    return false if !validate_scroll_col(@pmincol + @scroll_ctr)
    @pmincol += @scroll_ctr # some check is required or we'll crash
    @cols_panned -= @scroll_ctr
    $log.debug " handled ch M-l in ScrollForm"
    @window.modified = true
    return 0
  when ?\M-h.getbyte(0)
    return false if !validate_scroll_col(@pmincol - @scroll_ctr)
    @pmincol -= @scroll_ctr # some check is required or we'll crash
    @cols_panned += @scroll_ctr
    $log.debug " handled ch M-h in ScrollForm"
    @window.modified = true
    return 0
  when ?\M-n.getbyte(0)
    return false if !validate_scroll_row(@pminrow + @scroll_ctr)
    @pminrow += @scroll_ctr # some check is required or we'll crash
    @rows_panned -= @scroll_ctr
    @window.modified = true
    return 0
  when ?\M-p.getbyte(0)
    return false if !validate_scroll_row(@pminrow - @scroll_ctr)
    @pminrow -= @scroll_ctr # some check is required or we'll crash
    @rows_panned += @scroll_ctr
    @window.modified = true
    return 0
  end

  super
end

#init_varsObject



60
61
62
63
64
65
# File 'lib/rbcurse/rscrollform.rb', line 60

def init_vars
  bind_key(?\M-h, :scroll_left)
  bind_key(?\M-l, :scroll_right)
  bind_key(?\M-n, :scroll_down)
  bind_key(?\M-p, :scroll_up)
end

#last_visible_component_indexObject



307
308
309
310
311
312
313
# File 'lib/rbcurse/rscrollform.rb', line 307

def last_visible_component_index
  ret = -1
  @widgets.each_with_index do |w, ix|
    ret = ix if visible?(w) and focusable?(w)
  end
  return ret
end

#prefreshObject

refresh pad onto window I am now copying onto main window, else prefresh has funny effects



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rbcurse/rscrollform.rb', line 187

def prefresh
  ## reduce so we don't go off in top+h and top+w
  $log.debug "  start ret = @buttonpad.prefresh( #{@pminrow} , #{@pmincol} , #{@top} , #{@left} , top + #{@display_h} left + #{@display_w} ) "
  if @pminrow + @display_h > @orig_top + @pad_h
    $log.debug " if #{@pminrow} + #{@display_h} > #{@orig_top} +#{@pad_h} "
    $log.debug " ERROR 1 "
    #return -1
  end
  if @pmincol + @display_w > @orig_left + @pad_w
  $log.debug " if #{@pmincol} + #{@display_w} > #{@orig_left} +#{@pad_w} "
    $log.debug " ERROR 2 "
    return -1
  end
  # actually if there is a change in the screen, we may still need to allow update
  # but ensure that size does not exceed
  if @top + @display_h > @orig_top + @pad_h
  $log.debug " if #{@top} + #{@display_h} > #{@orig_top} +#{@pad_h} "
    $log.debug " ERROR 3 "
    return -1
  end
  if @left + @display_w > @orig_left + @pad_w
  $log.debug " if #{@left} + #{@display_w} > #{@orig_left} +#{@pad_w} "
    $log.debug " ERROR 4 "
    return -1
  end
  # maybe we should use copywin to copy onto @target_window
  $log.debug "   ret = @window.prefresh( #{@pminrow} , #{@pmincol} , #{@top} , #{@left} , #{@top} + #{@display_h}, #{@left} + #{@display_w} ) "
  omit = 0
  # this works but if want to avoid copying border
  #ret = @window.prefresh(@pminrow, @pmincol, @top+@row_offset, @left+@col_offset, @top + @display_h - @row_offset , @left + @display_w - @col_offset)
  #
  ## Haha , we are back to the old notorious copywin which has given mankind
  # so much grief that it should be removed in the next round of creation.
  ret = @window.copywin(@target_window.get_window, @pminrow, @pmincol, @top+@row_offset, @left+@col_offset, 
        @top + @display_h - @row_offset , @left + @display_w - @col_offset,  0)

  $log.debug " copywin ret = #{ret} "
end

print a border on the main window, just for kicks



159
160
161
162
163
# File 'lib/rbcurse/rscrollform.rb', line 159

def print_border
  $log.debug " SCROLL print_border ..."
  #@window.print_border_only(@top-@rows_panned, @left+@cols_panned, @display_h, @display_w, $datacolor)
  @target_window.print_border_only(@top, @left, @display_h, @display_w+1, $datacolor)
end


164
165
166
167
# File 'lib/rbcurse/rscrollform.rb', line 164

def print_footer
  footer = "Lines %d-%d (%d)  Cols %d-%d (%d) " % [ @pminrow, @pminrow + @display_h, @orig_top + @pad_h, @pmincol, @pmincol + @display_w, @orig_left + @pad_w ] 
  @target_window.printstring(@top +@display_h, @left + 3, footer, $datacolor)
end

#repaintObject

XXX what if we want a static area at bottom ? maybe we should rename targetwindow to window

and window to pad
super may need target window


172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rbcurse/rscrollform.rb', line 172

def repaint
  print_border if @repaint_all and @print_border_flag
  print_footer
  $log.debug " scrollForm repaint calling parent #{@row} #{@col}+ #{@cols_panned} #{@col_offset} "
  super
  prefresh
  _print_more_data_marker true
  _print_more_columns_marker true
  #$log.debug " @target_window.wmove #{@row+@rows_panned+@row_offset}, #{@col+@cols_panned+@col_offset}  "
  @target_window.wmove @row+@rows_panned+@row_offset, @col+@cols_panned+@col_offset
  @window.modified = false
  @repaint_all = false
end

#req_first_fieldObject



314
315
316
317
318
# File 'lib/rbcurse/rscrollform.rb', line 314

def req_first_field
  index = first_visible_component_index
  ret = select_field(index)
  return ret
end

#req_last_fieldObject



319
320
321
# File 'lib/rbcurse/rscrollform.rb', line 319

def req_last_field
  select_field(last_visible_component_index)
end

#scroll_downObject



132
133
134
135
136
137
138
139
140
# File 'lib/rbcurse/rscrollform.rb', line 132

def scroll_down
  s = @scroll_unit + $multiplier; $multiplier = 0
  return false if !validate_scroll_row(@pminrow + s)
  @pminrow += s # some check is required or we'll crash
  @rows_panned -= s
  @window.modified = true
  #@repaint_all = true
  return 0
end

#scroll_leftObject

validate fails once unit + mult > 1. Then it won’t go further unit should be one by default.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rbcurse/rscrollform.rb', line 117

def scroll_left
  s = @scroll_unit + $multiplier
  $log.debug " scroll_left #{s} m: #{$multiplier} "
  $multiplier = 0
  #return false if !validate_scroll_col(@pmincol - s)
  if !validate_scroll_col(@pmincol - s)
    @pmincol = 0
    @cols_panned  = 0 
  else
    @pmincol -= s # some check is required or we'll crash
    @cols_panned += s
  end
  @window.modified = true
  return 0
end

#scroll_rightObject



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rbcurse/rscrollform.rb', line 103

def scroll_right
  s = @scroll_unit + $multiplier
  $log.debug " scroll_right #{s} m: #{$multiplier} "
  $multiplier = 0
  return false if !validate_scroll_col(@pmincol + s)
  @pmincol += s # some check is required or we'll crash
  @cols_panned -= s
  $log.debug " handled ch M-l in ScrollForm"
  @window.modified = true
  return 0
end

#scroll_upObject



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rbcurse/rscrollform.rb', line 141

def scroll_up
  s = @scroll_unit + $multiplier; $multiplier = 0
  $log.debug " scroll_up #{s} "
  #return false if !validate_scroll_row(@pminrow - s)
  if !validate_scroll_row(@pminrow - s)
    @pminrow = 0
    @rows_panned = 0
    $log.debug " !valid #{@pminrow} "
  else
    @pminrow -= s # some check is required or we'll crash
    @rows_panned += s
    $log.debug " valid #{@pminrow} "
  end
  @window.modified = true
  #@repaint_all = true
  return 0
end

#set_layout(h, w, t, l) ⇒ Object



771
772
773
774
775
776
# File 'lib/rbcurse/rtabbedpane.rb', line 771

def set_layout(h, w, t, l)
  @pad_h = h
  @pad_w = w
  @top = @orig_top = t
  @left = @orig_left = l
end

#set_pad_dimensions(t, l, h, w) ⇒ Object

This is how we set size of pad and where it prints on screen This is all that’s needed after constructor.

Parameters:

  • t (Fixnum)

    top (row on screen to print pad on)

  • l (Fixnum)

    left (col on screen to print)

  • h (Fixnum)

    height (how many lines in Pad, usually more that screens actual height)

  • w (Fixnum)

    width (how many cols in Pad, often more than screens width)



77
78
79
80
81
82
83
# File 'lib/rbcurse/rscrollform.rb', line 77

def set_pad_dimensions(t, l, h, w )
  @pad_h = h
  @pad_w = w
  @top = @orig_top = t
  @left = @orig_left = l
  create_pad
end

#setrowcol(r, c) ⇒ Object

when tabbing through buttons, we need to account for all that panning/scrolling goin’ on



883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
# File 'lib/rbcurse/rtabbedpane.rb', line 883

def setrowcol r, c
  # aha ! here's where i can check whether the cursor is falling off the viewable area
  if c+@cols_panned < @orig_left
    # this essentially means this widget (button) is not in view, its off to the left
    $log.debug " setrowcol OVERRIDE #{c} #{@cols_panned} < #{@orig_left} "
    $log.debug " aborting settrow col for now"
    return
  end
  if c+@cols_panned > @orig_left + @display_w
    # this essentially means this button is not in view, its off to the right
    $log.debug " setrowcol OVERRIDE #{c} #{@cols_panned} > #{@orig_left} + #{@display_w} "
    $log.debug " aborting settrow col for now"
    return
  end
  super r+@rows_panned, c+@cols_panned
end

#should_print_border(flag = true) ⇒ Object



66
67
68
69
# File 'lib/rbcurse/rscrollform.rb', line 66

def should_print_border flag=true
  @print_border_flag = flag
  @row_offset = @col_offset = 1
end

#validate_scroll_col(mincol) ⇒ Object



235
236
237
238
239
240
241
242
243
# File 'lib/rbcurse/rscrollform.rb', line 235

def validate_scroll_col mincol
  return false if mincol < 0
  if mincol + @display_w > @orig_left + @pad_w
  $log.debug " if #{mincol} + #{@display_w} > #{@orig_left} +#{@pad_w} "
    $log.debug " ERROR 2 "
    return false
  end
  return true
end

#validate_scroll_row(minrow) ⇒ Object

need to refresh the form after repaint over



864
865
866
867
868
869
870
871
872
# File 'lib/rbcurse/rtabbedpane.rb', line 864

def validate_scroll_row minrow
   return false if minrow < 0
  if minrow + @display_h > @orig_top + @pad_h
    $log.debug " if #{minrow} + #{@display_h} > #{@orig_top} +#{@pad_h} "
    $log.debug " ERROR 1 "
    return false
  end
  return true
end

#visible?(component) ⇒ Boolean

Is a component visible, typically used to prevent traversal into the field

Returns:

  • (Boolean)


288
289
290
291
292
293
294
295
296
297
# File 'lib/rbcurse/rscrollform.rb', line 288

def visible? component
  r, c = component.rowcol
  return false if c+@cols_panned < @orig_left
  return false if c+@cols_panned > @orig_left + @display_w
  # XXX TODO for rows UNTESTED for rows
  return false if r + @rows_panned < @orig_top
  return false if r + @rows_panned > @orig_top + @display_h

  return true
end