Class: RubyCurses::Form

Inherits:
Object
  • Object
show all
Includes:
EventHandler, Utils
Defined in:
lib/rbcurse/rwidget.rb

Overview

TODO: we don’t have an event for when form is entered and exited. Current ENTER and LEAVE are for when any widgt is entered, so a common event can be put for all widgets in one place.

Direct Known Subclasses

ScrollForm

Instance Attribute Summary collapse

Instance Method Summary collapse

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) ⇒ Form

attr_accessor :allow_alt_digits # catch Alt-1-9 as digit_argument



1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
# File 'lib/rbcurse/rwidget.rb', line 1024

def initialize win, &block
  @window = win
  @widgets = []
  @by_name = {}
  @active_index = -1
  @padx = @pady = 0
  @row = @col = -1
  @ext_row_offset = @ext_col_offset = 0 # 2010-02-07 20:18 
  @add_cols = @add_rows = 0 # 2010-01-26 20:28 
  @handler = {}
  @modified = false
  @focusable = true
  @navigation_policy ||= :CYCLICAL
  instance_eval &block if block_given?
  @firsttime = true # internal, don't touch
  ## I need some counter so a widget knows it has been panned and can send a correct
  ##+ cursor coordinate to system.
  @rows_panned = @cols_panned = 0 # how many rows were panned, typically at a higher level
  @firsttime = true; # added on 2010-01-02 19:21 to prevent scrolling crash ! 
  @name ||= ""
  $kill_ring ||= [] # 2010-03-09 22:42 so textarea and others can copy and paste
  $kill_ring_pointer = 0 # needs to be incremented with each append, moved with yank-pop
  $append_next_kill = false
  $kill_last_pop_size = 0 # size of last pop which has to be cleared

  #@allow_alt_digits = true ; # capture Alt-1-9 as digit_args. Set to false if you wish to map
                             # Alt-1-9 to buttons of tabs 
end

Instance Attribute Details

#active_indexObject

Returns the value of attribute active_index.



1007
1008
1009
# File 'lib/rbcurse/rwidget.rb', line 1007

def active_index
  @active_index
end

#add_colsObject

next 2 added since tabbedpanes offset needs to be accounted by form inside it.



1019
1020
1021
# File 'lib/rbcurse/rwidget.rb', line 1019

def add_cols
  @add_cols
end

#add_rowsObject

2010-01-26 20:23 additional columns due to being placed in some container



1020
1021
1022
# File 'lib/rbcurse/rwidget.rb', line 1020

def add_rows
  @add_rows
end

#by_nameObject (readonly)

hash containing widgets by name for retrieval



1008
1009
1010
# File 'lib/rbcurse/rwidget.rb', line 1008

def by_name
  @by_name
end

#colObject

Returns the value of attribute col.



1001
1002
1003
# File 'lib/rbcurse/rwidget.rb', line 1001

def col
  @col
end

#cols_pannedObject

how many cols the component is panning embedded widget by



1017
1018
1019
# File 'lib/rbcurse/rwidget.rb', line 1017

def cols_panned
  @cols_panned
end

#ext_col_offsetObject

2010-02-07 20:16 to get abs position for cursor



1022
1023
1024
# File 'lib/rbcurse/rwidget.rb', line 1022

def ext_col_offset
  @ext_col_offset
end

#ext_row_offsetObject

2010-02-07 20:16 to get abs position for cursor



1022
1023
1024
# File 'lib/rbcurse/rwidget.rb', line 1022

def ext_row_offset
  @ext_row_offset
end

Returns the value of attribute menu_bar.



1009
1010
1011
# File 'lib/rbcurse/rwidget.rb', line 1009

def menu_bar
  @menu_bar
end

#modifiedObject

Returns the value of attribute modified.



1006
1007
1008
# File 'lib/rbcurse/rwidget.rb', line 1006

def modified
  @modified
end

#nameObject

for debugging 2010-02-02 20:12



1021
1022
1023
# File 'lib/rbcurse/rwidget.rb', line 1021

def name
  @name
end

:CYCLICAL will cycle around. Needed to move to other tabs



1010
1011
1012
# File 'lib/rbcurse/rwidget.rb', line 1010

def navigation_policy
  @navigation_policy
end

#padxObject

attr_accessor :bgcolor



1004
1005
1006
# File 'lib/rbcurse/rwidget.rb', line 1004

def padx
  @padx
end

#padyObject

Returns the value of attribute pady.



1005
1006
1007
# File 'lib/rbcurse/rwidget.rb', line 1005

def pady
  @pady
end

#parent_formObject

i need some way to move the cursor by telling the main form what the coords are + perhaps this will work



1013
1014
1015
# File 'lib/rbcurse/rwidget.rb', line 1013

def parent_form
  @parent_form
end

#rowObject

Returns the value of attribute row.



1001
1002
1003
# File 'lib/rbcurse/rwidget.rb', line 1001

def row
  @row
end

#rows_pannedObject

how many rows the component is panning embedded widget by



1015
1016
1017
# File 'lib/rbcurse/rwidget.rb', line 1015

def rows_panned
  @rows_panned
end

#valueObject (readonly)

Returns the value of attribute value.



998
999
1000
# File 'lib/rbcurse/rwidget.rb', line 998

def value
  @value
end

#widgetsObject (readonly)

Returns the value of attribute widgets.



999
1000
1001
# File 'lib/rbcurse/rwidget.rb', line 999

def widgets
  @widgets
end

#windowObject

Returns the value of attribute window.



1000
1001
1002
# File 'lib/rbcurse/rwidget.rb', line 1000

def window
  @window
end

Instance Method Details

#add_widget(widget) ⇒ Object Also known as: add

Add given widget to widget list and returns an incremental id. Adding to widgets, results in it being painted, and focussed. removing a widget and adding can give the same ID’s, however at this point we are not really using ID. But need to use an incremental int in future.



1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
# File 'lib/rbcurse/rwidget.rb', line 1075

def add_widget widget
  # this help to access widget by a name
  if widget.respond_to? :name and !widget.name.nil?
    @by_name[widget.name] = widget
  end


  $log.debug " #{self} adding a widget #{@widgets.length} .. #{widget} "
  @widgets << widget
  # add form offsets to widget's external offsets - 2010-02-07 20:22 
  if widget.is_a? RubyCurses::Widget
    if @window # ext seems redundant
      widget.ext_col_offset += @window.left # just hope window aint undef!! XXX
      $log.debug " #{@name} add widget ( #{widget.name} ) ext_row #{widget.ext_row_offset} += #{@window.top} "
      widget.ext_row_offset += @window.top
    end
  end
  return @widgets.length-1
end

#addcol(num) ⇒ Object

move cursor by num columns. Form



1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
# File 'lib/rbcurse/rwidget.rb', line 1348

def addcol num
  return if @col.nil? or @col == -1
  @col += num
  @window.wmove @row, @col
  ## 2010-01-30 23:45 exchange calling parent with calling this forms setrow
  # since in tabbedpane with table i am not gietting this forms offset. 
    setrowcol nil, col
  # added on 2010-01-05 22:26 so component widgets like scrollpane can get the cursor
  #if !@parent_form.nil? and @parent_form != self #@form
    #$log.debug " #{@name} addcol calling parents setrowcol #{row}, #{col}: #{@parent_form}   "
    #@parent_form.setrowcol nil, col
  #end
end

#addrowcol(row, col) ⇒ Object

move cursor by given rows and columns, can be negative. 2010-01-30 23:47 FIXME, if this is called we should call setrowcol like in addcol



1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
# File 'lib/rbcurse/rwidget.rb', line 1364

def addrowcol row,col
  return if @col.nil? or @col == -1   # contradicts comment on top
  return if @row.nil? or @row == -1
  @col += col
  @row += row
  @window.wmove @row, @col
  # added on 2010-01-05 22:26 so component widgets like scrollpane can get the cursor
  if !@parent_form.nil? and @parent_form != @form
    $log.debug " #{@name} addrowcol calling parents setrowcol #{row}, #{col}  "
    @parent_form.setrowcol row, col
  end
end

#digit_argument(ch) ⇒ Object



1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
# File 'lib/rbcurse/rwidget.rb', line 1511

def digit_argument ch
  $multiplier = ch - ?\M-0.getbyte(0)
  $log.debug " inside UNIV MULT 0 #{$multiplier} "
  # See if user enters numerics. If so discard existing varaible and take only 
  #+ entered values
  _m = $multiplier
  while true
    ch = @window.getchar()
    case ch
    when -1
      next 
    when ?0.getbyte(0)..?9.getbyte(0)
      _m *= 10 ; _m += (ch-48)
      $multiplier = _m
      $log.debug " inside UNIV MULT 1 #{$multiplier} "
    when ?\M-0.getbyte(0)..?\M-9.getbyte(0)
      _m *= 10 ; _m += (ch-?\M-0.getbyte(0))
      $multiplier = _m
      $log.debug " inside UNIV MULT 2 #{$multiplier} "
    else
      $log.debug " inside UNIV MULT else got #{ch} "
      # here is some other key that is the function key to be repeated. we must honor this
      # and ensure it goes to the right widget
      return ch
      #return :UNHANDLED
    end
  end
  return 0
end

#dump_dataObject

test program to dump data onto log The problem I face is that since widget array contains everything that should be displayed I do not know what all the user wants - what are his data entry fields. A user could have disabled entry on some field after modification, so i can’t use focusable or editable as filters. I just dump everything? What’s more, currently getvalue has been used by paint to return what needs to be displayed - at least by label and button.



1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
# File 'lib/rbcurse/rwidget.rb', line 1616

def dump_data
  $log.debug " DUMPING DATA "
  @widgets.each do |w|
    # we need checkbox and radio button values
    #next if w.is_a? RubyCurses::Button or w.is_a? RubyCurses::Label 
    next if w.is_a? RubyCurses::Label 
    next if !w.is_a? RubyCurses::Widget
    if w.respond_to? :getvalue
      $log.debug " #{w.name} #{w.getvalue}"
    else
      $log.debug " #{w.name} DOES NOT RESPOND TO getvalue"
    end
  end
  $log.debug " END DUMPING DATA "
end

#focusable?(f) ⇒ Boolean

is a field focusable Added a method here, so forms can extend this to avoid focussing on off-screen components

Returns:

  • (Boolean)


1212
1213
1214
# File 'lib/rbcurse/rwidget.rb', line 1212

def focusable?(f)
  return f.focusable
end

#get_current_fieldObject



1172
1173
1174
1175
1176
# File 'lib/rbcurse/rwidget.rb', line 1172

def get_current_field
  select_next_field if @active_index == -1
  return nil if @active_index.nil?   # for forms that have no focusable field 2009-01-08 12:22 
  @widgets[@active_index]
end

#handle_key(ch) ⇒ Object

forms handle keys mainly traps tab and backtab to navigate between widgets. I know some widgets will want to use tab, e.g edit boxes for entering a tab

or for completion.


1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
# File 'lib/rbcurse/rwidget.rb', line 1544

def handle_key(ch)
      if ch ==  ?\C-u.getbyte(0)
        ret = universal_argument
        $log.debug "C-u FORM set MULT to #{$multiplier}, ret = #{ret}  "
        return 0 if ret == 0
        ch = ret # unhandled char
      elsif ch >= ?\M-1.getbyte(0) && ch <= ?\M-9.getbyte(0)
        if $catch_alt_digits
          ret = digit_argument ch
          $log.debug " FORM set MULT DA to #{$multiplier}, ret = #{ret}  "
          return 0 if ret == 0 # don't see this happening
          ch = ret # unhandled char
        end
      end

      case ch
      when -1
        return
      else
        keycode = keycode_tos(ch)
        $log.debug " form HK #{ch} #{self}, #{@name}, #{keycode}  "
        field =  get_current_field
        handled = :UNHANDLED 
        handled = field.handle_key ch unless field.nil? # no field focussable
        # some widgets like textarea and list handle up and down
        if handled == :UNHANDLED or handled == -1 or field.nil?
          case ch
          when 9, ?\M-\C-i.getbyte(0)  # tab and M-tab in case widget eats tab (such as Table)
            ret = select_next_field
            return ret if ret == :NO_NEXT_FIELD
            # alt-shift-tab  or backtab (in case Table eats backtab)
          when 353, 481 ## backtab added 2008-12-14 18:41 
            ret = select_prev_field
            return ret if ret == :NO_PREV_FIELD
          when KEY_UP
            select_prev_field
          when KEY_DOWN
            select_next_field
          #when ?\M-L.getbyte(0)
            ### trying out these for fuun and testing splitpane 2010-01-10 20:32 
            #$log.debug " field #{field.name} was #{field.width} "
            #field.width += 1
            #$log.debug " field #{field.name} now #{field.width} "
            #field.repaint_all
          #when ?\M-H.getbyte(0), ?\M-<.getbyte(0)
            #field.width -= 1
            #$log.debug " field #{field.name} now #{field.width} "
            #field.repaint_all
          #when ?\M-J.getbyte(0)
            #field.height += 1
          #when ?\M-K.getbyte(0)
            #field.height -= 1
          else
            ret = process_key ch, self
            $log.debug " process_key #{ch} got ret #{ret} in #{self} "
            return :UNHANDLED if ret == :UNHANDLED
          end
        end
      end
     $log.debug " form before repaint #{self} , #{@name}, ret #{ret}"
     repaint
     #return handled # TRYNG 2010-03-01 23:30 since TP returns NO_NEXT_FIELD sometimes
     #$multiplier = 0
end

#OLDbind_key(keycode, *args, &blk) ⇒ Object

1.9 if string passed then getbyte so user does not need to change much and less chance of error 2009-10-04 16:08



1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
# File 'lib/rbcurse/rwidget.rb', line 1420

def OLDbind_key keycode, *args, &blk
    @key_handler ||= {}
    case keycode
    when String
      $log.debug "FORM String called bind_key BIND #{keycode} #{keycode_tos(keycode)}  "
      keycode = keycode.getbyte(0) #if keycode.class==String ##    1.9 2009-10-05 19:40 
      @key_handler[keycode] = blk
    when Array
      # for starters lets try with 2 keys only
      a0 = keycode[0]
      a0 = keycode[0].getbyte(0) if keycode[0].class == String
      a1 = keycode[1]
      a1 = keycode[1].getbyte(0) if keycode[1].class == String
      @key_handler[a0] ||= OrderedHash.new
      @key_handler[a0][a1] = blk
    else
      @key_handler[keycode] = blk
    end
    @key_args ||= {}
    @key_args[keycode] = args
end

#OLDsetrowcol(r, c) ⇒ Object

added 2009-12-29 15:46 BUFFERED Set forms row and col, so that the cursor can be displayed at that point. Widgets should call this rather than touch row and col directly. This should percolate the row and col upwards to parent forms, after comparing to prevent infinite recursion. This is being done for embedded objects so that the cursor can be maintained correctly.



1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
# File 'lib/rbcurse/rwidget.rb', line 1385

def OLDsetrowcol r, c
  @row = r unless r.nil?
  @col = c unless c.nil?
       r +=  @add_rows unless r.nil? # 2010-01-26 20:31 
       c +=  @add_cols unless c.nil? # 2010-01-26 20:31 
       $log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self}  "
  if !@parent_form.nil? and @parent_form != self
    $log.debug " (#{@name}) calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self:  #{self}, #{self.class}  "
    r += @parent_form.window.top unless  r.nil?
    c += @parent_form.window.left unless c.nil?
    @parent_form.setrowcol r, c
  end
end

#on_enter(f) ⇒ Object



1202
1203
1204
1205
1206
1207
1208
1209
# File 'lib/rbcurse/rwidget.rb', line 1202

def on_enter f
  return if f.nil?
  f.state = :HIGHLIGHTED
  f.modified false
  #f.set_modified false
  f.on_enter if f.respond_to? :on_enter
  fire_handler :ENTER, f 
end

#on_leave(f) ⇒ Object

do not override form’s trigger, fired when any widget loses focus

This wont get called in editor components in tables, since  they are formless XXX


1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
# File 'lib/rbcurse/rwidget.rb', line 1188

def on_leave f
  return if f.nil?
  f.state = :NORMAL
  # on leaving update text_variable if defined. Should happen on modified only
  # should this not be f.text_var ... f.buffer ? XXX 2008-11-25 18:58 
  #f.text_variable.value = f.buffer if !f.text_variable.nil? # 2008-12-20 23:36 
  f.on_leave if f.respond_to? :on_leave
  fire_handler :LEAVE, f 
  ## to test XXX in combo boxes the box may not be editable by be modified by selection.
  if f.respond_to? :editable and f.modified?
    $log.debug " Form about to fire CHANGED for #{f} "
    f.fire_handler(:CHANGED, f) 
  end
end

#process_key(keycode, object) ⇒ Object

e.g. process_key ch, self returns UNHANDLED if no block for it after form handles basic keys, it gives unhandled key to current field, if current field returns unhandled, then it checks this map. Please update widget with any changes here. TODO: match regexes as in mapper



1447
1448
1449
# File 'lib/rbcurse/rwidget.rb', line 1447

def process_key keycode, object
  return _process_key keycode, object, @window
end

#remove_widget(widget) ⇒ Object

remove a widget

added 2008-12-09 12:18


1098
1099
1100
1101
1102
1103
1104
# File 'lib/rbcurse/rwidget.rb', line 1098

def remove_widget widget
  if widget.respond_to? :name and !widget.name.nil?
    $log.debug "removing from byname: #{widget.name} " 
    @by_name.delete(widget.name)
  end
  @widgets.delete widget
end

#repaintObject

form repaint to be called at some interval, such as after each keypress.



1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
# File 'lib/rbcurse/rwidget.rb', line 1107

def repaint
  $log.debug " form repaint:#{self}, #{@name} , r #{@row} c #{@col} "
  @widgets.each do |f|
    next if f.visible == false # added 2008-12-09 12:17 
    f.repaint
    # added 2009-10-29 20:11 for double buffered widgets
    # this should only happen if painting actually happened
    #$log.debug " #{self} form repaint parent_buffer (#{@parent_buffer}) if #{f.is_double_buffered?} : #{f.name} "
    pb = @parent_buffer #|| @window
    # is next line used 2010-02-05 00:04 its wiping off top in scrollpane in tabbedpane
    # RFED16 - the next line should never execute now, since no outer object is buffered
    #+ only those within containers are.
    # Drat - this line is happeing since components inside a TP are double_buffered
    #x f.buffer_to_screen(pb) if f.is_double_buffered? 
  end
  @window.clear_error # suddenly throwing up on a small pad 2010-03-02 15:22 TPNEW
  @window.print_status_message $status_message unless $status_message.nil?
  @window.print_error_message $error_message unless $error_message.nil?
  $error_message = $status_message = nil
  #  this can bomb if someone sets row. We need a better way!
  if @row == -1 and @firsttime == true
    #set_field_cursor 0
    #  this part caused an endless loop on 2010-01-02 19:20 when scrollpane scrolled up
   $log.debug "form repaint calling select field 0 SHOULD HAPPEN FIRST TIME ONLY"
    #select_field 0
    req_first_field
    @firsttime = false
  end
   setpos 
   # XXX this creates a problem if window is a pad
   # although this does show cursor movement etc.
   ### [email protected]
   if @window.window_type == :WINDOW
     $log.debug " formrepaint #{@name} calling window.wrefresh #{@window} "
     @window.wrefresh
   else
     # UGLY HACK TO MAKE TABBEDPANES WORK !!
     # If the form is based on a Pad, then it would come here to write the Pad onto the parent_buffer
     # However, I've obviated the need to handle anything here by adding a display_form after handle_key
     # in TP.
     #x if @parent_buffer!=nil
       #x $log.debug " formrep coming to set backing window part #{@window} , type:#{@window.window_type}, #{@parent_buffer}, #{@parent_buffer.window_type} "
       # XXX RFED19 do we need at all 2010-02-19 15:26 
       # this is required so that each key stroke registers on tabbedpane
       # for this to work both have to be pads
       #x @window.set_backing_window(@parent_buffer)
       #x @window.copy_pad_to_win
       #x @window.wrefresh #since the pads are writing onto window directly, i don't think we need  this
       #x $log.debug " DO I NEED TO DO SOMETHING HERE FOR TABBEDPANES now ? WARN ?? YES, else keystrokes won't be updated "
     #x end
   end
end

#req_first_fieldObject



1177
1178
1179
1180
# File 'lib/rbcurse/rwidget.rb', line 1177

def req_first_field
  @active_index = -1 # FIXME HACK
  select_next_field
end

#req_last_fieldObject



1181
1182
1183
1184
# File 'lib/rbcurse/rwidget.rb', line 1181

def req_last_field
  @active_index = nil 
  select_prev_field
end

#select_field(ix0) ⇒ Object

puts focus on the given field/widget index XXX if called externally will not run a on_leave of previous field



1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
# File 'lib/rbcurse/rwidget.rb', line 1218

def select_field ix0
  #return if @widgets.nil? or @widgets.empty? or !@widgets[ix0].focusable
  return if @widgets.nil? or @widgets.empty? or !focusable?(@widgets[ix0])
 #$log.debug "insdie select  field :  #{ix0} ai #{@active_index}" 
  f = @widgets[ix0]
  if focusable?(f)
    @active_index = ix0
    @row, @col = f.rowcol
   #$log.debug " WMOVE insdie sele nxt field : ROW #{@row} COL #{@col} " 
    @window.wmove @row, @col
    on_enter f
    f.curpos = 0
    repaint
    @window.refresh
  else
    $log.debug "insdie sele nxt field ENABLED FALSE :   act #{@active_index} ix0 #{ix0}" 
  end
end

#select_next_fieldObject Also known as: req_next_field

put focus on next field will cycle by default, unless navigation policy not :CYCLICAL in which case returns :NO_NEXT_FIELD.



1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
# File 'lib/rbcurse/rwidget.rb', line 1255

def select_next_field
  return if @widgets.nil? or @widgets.empty?
  $log.debug "insdie sele nxt field :  #{@active_index} WL:#{@widgets.length}" 
  if @active_index.nil?
    @active_index = -1 
  else
    f = @widgets[@active_index]
    begin
      on_leave f
    rescue => err
     $log.debug "select_next_field: caught EXCEPTION #{err}"
     $log.debug(err.backtrace.join("\n")) 
     $error_message = "#{err}"
     Ncurses.beep
     return
    end
  end
  index = @active_index + 1
  index.upto(@widgets.length-1) do |i|
    f = @widgets[i]
    $log.debug "insdie sele nxt field :  i #{i}  #{index} WL:#{@widgets.length}, field #{f}" 
    if focusable?(f)
      select_field i
      return
    end
  end
  #req_first_field
  #$log.debug "insdie sele nxt field FAILED:  #{@active_index} WL:#{@widgets.length}" 
  ## added on 2008-12-14 18:27 so we can skip to another form/tab
  if @navigation_policy == :CYCLICAL
    @active_index = nil
    # recursive call worked, but bombed if no focusable field!
    #select_next_field
    0.upto(index-1) do |i|
      f = @widgets[i]
      if focusable?(f)
        select_field i
        return
      end
    end
  end
  $log.debug "insdie sele nxt field : NO NEXT  #{@active_index} WL:#{@widgets.length}" 
  return :NO_NEXT_FIELD
end

#select_prev_fieldObject Also known as: req_prev_field

put focus on previous field will cycle by default, unless navigation policy not :CYCLICAL in which case returns :NO_PREV_FIELD.



1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
# File 'lib/rbcurse/rwidget.rb', line 1303

def select_prev_field
  return if @widgets.nil? or @widgets.empty?
  #$log.debug "insdie sele prev field :  #{@active_index} WL:#{@widgets.length}" 
  if @active_index.nil?
    @active_index = @widgets.length 
  else
    f = @widgets[@active_index]
    begin
      on_leave f
    rescue => err
     $log.debug " cauGHT EXCEPTION #{err}"
     Ncurses.beep
     return
    end
  end

  index = @active_index - 1
  (index).downto(0) do |i|
    f = @widgets[i]
    if focusable?(f)
      select_field i
      return
    end
  end
  # $log.debug "insdie sele prev field FAILED:  #{@active_index} WL:#{@widgets.length}" 
  ## added on 2008-12-14 18:27 so we can skip to another form/tab
  # 2009-01-08 12:24 no recursion, can be stack overflows if no focusable field
  if @navigation_policy == :CYCLICAL
    @active_index = nil # HACK !!!
    #select_prev_field
    total = @widgets.length-1
    total.downto(index-1) do |i|
      f = @widgets[i]
      if focusable?(f)
        select_field i
        return
      end
    end
  end
  return :NO_PREV_FIELD
end

#set_menu_bar(mb) ⇒ Object

set this menubar as the form’s menu bar. also bind the toggle_key for popping up. Should this not be at application level ?



1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
# File 'lib/rbcurse/rwidget.rb', line 1056

def set_menu_bar mb
  @menu_bar = mb
  add_widget mb
  mb.toggle_key ||= 27 # ESC
  if !mb.toggle_key.nil?
    ch = mb.toggle_key
    bind_key(ch) do |_form| 
      if !@menu_bar.nil?
        @menu_bar.toggle
        @menu_bar.handle_keys
      end
    end
  end
end

#set_parent_buffer(b) ⇒ Object

trying out for splitpane and others who have a sub-form



1633
1634
1635
# File 'lib/rbcurse/rwidget.rb', line 1633

def set_parent_buffer b
  @parent_buffer = b
end

#setpos(r = @row, c = @col) ⇒ Object

move cursor to where the fields row and col are private



1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
# File 'lib/rbcurse/rwidget.rb', line 1162

def setpos r=@row, c=@col
  # next 2 lines added, only do cursor if current field doesn't manage it.
  #curr = get_current_field
  #return if curr.manages_cursor
  $log.debug "setpos : (#{self}) #{r} #{c}"
  ## adding just in case things are going out of bounds of a parent and no cursor to be shown
  return if r.nil? or c.nil?  # added 2009-12-29 23:28 BUFFERED
  return if r<0 or c<0  # added 2010-01-02 18:49 stack too deep coming if goes above screen
  @window.wmove r,c
end

#setrowcol(r, c) ⇒ Object

Form New attempt at setting cursor using absolute coordinates Also, trying NOT to go up. let this pad or window print cursor.



1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
# File 'lib/rbcurse/rwidget.rb', line 1401

def setrowcol r, c
  @row = r unless r.nil?
  @col = c unless c.nil?
  r +=  @add_rows unless r.nil? # 2010-01-26 20:31 
  c +=  @add_cols unless c.nil? # 2010-01-26 20:31 
  $log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self}  "
  if !@parent_form.nil? and @parent_form != self
    $log.debug " (#{@name}) calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self:  #{self}, #{self.class}  "
    #r += @parent_form.window.top unless  r.nil?
    #c += @parent_form.window.left unless c.nil?
    @parent_form.setrowcol r, c
  end
end

#to_sObject

2010-02-07 14:50 to aid in debugging and comparing log files.



1637
# File 'lib/rbcurse/rwidget.rb', line 1637

def to_s; @name || self; end

#universal_argumentObject

end Defines how user can give numeric args to a command even in edit mode User either presses universal_argument (C-u) which generates a series of 4 16 64. Or he presses C-u and then types some numbers. Followed by the action. by system. ) implies only numeric args were obtained. This method updates $multiplier



1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
# File 'lib/rbcurse/rwidget.rb', line 1478

def universal_argument
  $multiplier = ( ($multiplier.nil? || $multiplier == 0) ? 4 : $multiplier *= 4)
      $log.debug " inside UNIV MULT0: #{$multiplier} "
  # See if user enters numerics. If so discard existing varaible and take only 
  #+ entered values
  _m = 0
  while true
    ch = @window.getchar()
    case ch
    when -1
      next 
    when ?0.getbyte(0)..?9.getbyte(0)
      _m *= 10 ; _m += (ch-48)
      $multiplier = _m
      $log.debug " inside UNIV MULT #{$multiplier} "
    when ?\C-u.getbyte(0)
      if _m == 0
        # user is incrementally hitting C-u
        $multiplier *= 4
      else
        # user is terminating some numbers so he can enter a numeric command next
        return 0
      end
    else
      $log.debug " inside UNIV MULT else got #{ch} "
      # here is some other key that is the function key to be repeated. we must honor this
      # and ensure it goes to the right widget
      return ch
      #return :UNHANDLED
    end
  end
  return 0
end

#validate_field(f = ) ⇒ Object

run validate_field on a field, usually whatevers current before transferring control We should try to automate this so developer does not have to remember to call it.



1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
# File 'lib/rbcurse/rwidget.rb', line 1240

def validate_field f=@widgets[@active_index]
  begin
    on_leave f
  rescue => err
    $log.debug "form: validate_field caught EXCEPTION #{err}"
    $log.debug(err.backtrace.join("\n")) 
    $error_message = "#{err}"
    Ncurses.beep
    return -1
  end
  return 0
end