Class: Canis::Form
- Includes:
- EventHandler, Utils
- Defined in:
- lib/canis/core/widgets/rwidget.rb
Overview
Manages the controls/widgets on a screen. Manages traversal, rendering and events of all widgets that are associated with it via the add_widget
method.
Passes keys pressed by user to the current field. Any keys that are not handled by the current field, are handled by the form if the application has bound the key via bind_key
.
TODO: we don’t have an event for when form is entered and exited.
Instance Attribute Summary collapse
-
#active_index ⇒ Object
index of active widget.
- #attr ⇒ Object
-
#bgcolor ⇒ Object
returns form’s bgcolor, or global default.
-
#by_name ⇒ Object
readonly
hash containing widgets by name for retrieval Useful if one widget refers to second before second created.
-
#col ⇒ Object
cursor row and col.
-
#color ⇒ Object
returns forms color, or if not set then app default This is used by widget’s as the color to fallback on when no color is specified for them.
-
#layout_manager ⇒ Object
class that lays out objects (calculates row, col, width and height).
-
#menu_bar ⇒ Object
readonly
associated menubar.
-
#modified ⇒ Object
has the form been modified.
-
#name ⇒ Object
name given to form for debugging.
-
#navigation_policy ⇒ Object
this influences whether navigation will return to first component after last or not Default is :CYCLICAL which cycles between first and last.
-
#resize_required ⇒ Object
signify that the layout manager must calculate each widgets dimensions again since typically the window has been resized.
-
#row ⇒ Object
cursor row and col.
-
#widgets ⇒ Object
readonly
array of widgets.
-
#window ⇒ Object
related window used for printing.
Instance Method Summary collapse
-
#add_widget(widget) ⇒ Object
(also: #add)
Add given widget to widget list and returns an incremental id.
-
#addcol(num) ⇒ Object
move cursor by num columns.
-
#addrowcol(row, col) ⇒ Object
move cursor by given rows and columns, can be negative.
- #digit_argument(ch) ⇒ Object
-
#get_current_field ⇒ Widget?
(also: #current_widget)
Current field, nil if no focusable field.
-
#handle_key(ch) ⇒ Object
forms handle keys mainly traps tab and backtab to navigate between widgets.
-
#help_manager ⇒ Object
returns in instance of help_manager with which one may install help_text and call help.
-
#initialize(win, &block) ⇒ Form
constructor
A new instance of Form.
-
#map_keys ⇒ Object
These mappings will only trigger if the current field does not use them.
-
#on_enter(f) ⇒ Object
form calls on_enter of each object.
-
#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.
-
#process_key(keycode, object) ⇒ Object
e.g.
-
#remove_widget(widget) ⇒ Object
remove a widget (internal use).
-
#repaint ⇒ Object
form repaint,calls repaint on each widget which will repaint it only if it has been modified since last call.
-
#repaint_all_widgets ⇒ Object
this forces a repaint of all visible widgets and has been added for the case of overlapping windows, since a black rectangle is often left when a window is destroyed.
-
#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.
-
#select_first_field ⇒ Object
take focus to first focussable field we shoud not send to select_next.
-
#select_last_field ⇒ Object
take focus to last field on form.
-
#select_next_field ⇒ Object
put focus on next field will cycle by default, unless navigation policy not :CYCLICAL in which case returns :NO_NEXT_FIELD.
-
#select_prev_field ⇒ nil, :NO_PREV_FIELD
put focus on previous field will cycle by default, unless navigation policy not :CYCLICAL in which case returns :NO_PREV_FIELD.
-
#set_menu_bar(mb) ⇒ Object
set this menubar as the form’s menu bar.
-
#setpos(r = @row, c = @col) ⇒ Object
move cursor to where the fields row and col are private.
-
#setrowcol(r, c) ⇒ Object
Form New attempt at setting cursor using absolute coordinates Also, trying NOT to go up.
-
#to_s ⇒ Object
2010-02-07 14:50 to aid in debugging and comparing log files.
-
#universal_argument ⇒ Object
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.
-
#update_focusables ⇒ Object
sets a flag that focusables should be updated called whenever a widgets changes its focusable property.
-
#validate_field(f = ) ⇒ 0, -1
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.
Methods included from Utils
#ORIG_process_key, #ORIGbind_key, #ORIGkeycode_tos, #_process_key, #bind_composite_mapping, #bind_key, #bind_keys, #check_composite_mapping, #create_logger, #define_key, #define_prefix_command, #execute_mapping, #get_attrib, #get_color, #key, #key_tos, #print_key_bindings, #repeatm, #run_command, #shell_out, #shell_output, #suspend, #view, #xxxbind_composite_mapping
Methods included from EventHandler
#bind, #event?, #event_list, #fire_handler, #fire_property_change, #register_events
Constructor Details
#initialize(win, &block) ⇒ Form
Returns a new instance of Form.
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 1608 1609 1610 1611 1612 1613 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1572 def initialize win, &block @window = win # added 2014-05-01 - 20:43 so that a window can update its form, during overlapping forms. @window.form = self if win @widgets = [] @by_name = {} @active_index = -1 @row = @col = -1 @modified = false @resize_required = true @focusable = true # when widgets are added, add them here if focusable so traversal is easier. However, # if user changes this during the app, we need to update this somehow. FIXME @focusables = [] # added 2014-04-24 - 12:28 to make traversal easier @navigation_policy ||= :CYCLICAL # 2014-04-24 - 17:42 NO MORE ENTER LEAVE at FORM LEVEL #register_events([:ENTER, :LEAVE, :RESIZE]) register_events(:RESIZE) instance_eval &block if block_given? @_firsttime = true; # added on 2010-01-02 19:21 to prevent scrolling crash ! @name ||= "" # related to emacs kill ring concept for copy-paste $kill_ring ||= [] # 2010-03-09 22:42 so textarea and others can copy and paste emacs EMACS $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 $last_key = 0 # last key pressed @since 1.1.5 (not used yet) $current_key = 0 # curr key pressed @since 1.1.5 (so some containers can behave based on whether # user tabbed in, or backtabbed in (rmultisplit) # for storing error message $error_message ||= Variable.new "" # what kind of key-bindings do you want, :vim or :emacs $key_map_type ||= :vim ## :emacs or :vim, keys to be defined accordingly. TODO #bind_key(KEY_F1, 'help') { hm = help_manager(); hm.display_help } map_keys unless @keys_mapped end |
Instance Attribute Details
#active_index ⇒ Object
index of active widget
1548 1549 1550 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1548 def active_index @active_index end |
#attr ⇒ Object
1542 1543 1544 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1542 def attr @attr end |
#bgcolor ⇒ Object
returns form’s bgcolor, or global default.
2226 2227 2228 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2226 def bgcolor @bgcolor || $def_bg_color end |
#by_name ⇒ Object (readonly)
hash containing widgets by name for retrieval Useful if one widget refers to second before second created.
lb = @form.by_name["listb"]
1553 1554 1555 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1553 def by_name @by_name end |
#col ⇒ Object
cursor row and col
1538 1539 1540 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1538 def col @col end |
#color ⇒ Object
returns forms color, or if not set then app default This is used by widget’s as the color to fallback on when no color is specified for them. This way all widgets in a form can have one color.
2222 2223 2224 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2222 def color @color || $def_fg_color end |
#layout_manager ⇒ Object
class that lays out objects (calculates row, col, width and height)
1570 1571 1572 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1570 def layout_manager @layout_manager end |
#menu_bar ⇒ Object (readonly)
associated menubar
1556 1557 1558 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1556 def @menu_bar end |
#modified ⇒ Object
has the form been modified
1545 1546 1547 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1545 def modified @modified end |
#name ⇒ Object
name given to form for debugging
1564 1565 1566 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1564 def name @name end |
#navigation_policy ⇒ Object
this influences whether navigation will return to first component after last or not Default is :CYCLICAL which cycles between first and last. In some cases, where a form or container exists inside a form with buttons or tabs, you may not want cyclical traversal.
1561 1562 1563 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1561 def @navigation_policy end |
#resize_required ⇒ Object
signify that the layout manager must calculate each widgets dimensions again since typically the window has been resized.
1568 1569 1570 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1568 def resize_required @resize_required end |
#row ⇒ Object
cursor row and col
1538 1539 1540 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1538 def row @row end |
#widgets ⇒ Object (readonly)
array of widgets
1532 1533 1534 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1532 def @widgets end |
#window ⇒ Object
related window used for printing
1535 1536 1537 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1535 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. (internal use)
1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1637 def # this help to access widget by a name if .respond_to? :name and !.name.nil? @by_name[.name] = end @widgets << @focusable_modified = true return @widgets.length-1 end |
#addcol(num) ⇒ Object
move cursor by num columns. Form
1953 1954 1955 1956 1957 1958 1959 1960 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1953 def addcol num return if @col.nil? || @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 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
1964 1965 1966 1967 1968 1969 1970 1971 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1964 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 end |
#digit_argument(ch) ⇒ Object
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2032 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 |
#get_current_field ⇒ Widget? Also known as: current_widget
Returns current field, nil if no focusable field.
1723 1724 1725 1726 1727 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1723 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.
NOTE : please rescue exceptions when you use this in your main loop and alert() user
2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2112 def handle_key(ch) # 2014-08-19 - 21:10 moving to init, so that user may override or remove #map_keys unless @keys_mapped handled = :UNHANDLED # 2011-10-4 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 # emacs EMACS 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 $current_key = ch case ch when -1 return when 1000, 12 # NOTE this works if widgets cover entire screen like text areas and lists but not in # dialogs where there is blank space. only widgets are painted. # testing out 12 is C-l $log.debug " form REFRESH_ALL repaint_all HK #{ch} #{self}, #{@name} " return when FFI::NCurses::KEY_RESIZE # SIGWINCH # note that in windows that have dialogs or text painted on window such as title or # box, the clear call will clear it out. these are not redrawn. lines = Ncurses.LINES cols = Ncurses.COLS x = Ncurses.stdscr.getmaxy y = Ncurses.stdscr.getmaxx $log.debug " form RESIZE HK #{ch} #{self}, #{@name}, #{ch}, x #{x} y #{y} lines #{lines} , cols: #{cols} " #alert "SIGWINCH WE NEED TO RECALC AND REPAINT resize #{lines}, #{cols}: #{x}, #{y} " # next line may be causing flicker, can we do without. Ncurses.endwin @window.wrefresh @window.wclear if @layout_manager @layout_manager.do_layout # we need to redo statusline and others that layout ignores else @widgets.each { |e| e.repaint_all(true) } # trying out end ## added RESIZE on 2012-01-5 ## stuff that relies on last line such as statusline dock etc will need to be redrawn. fire_handler :RESIZE, self else field = get_current_field if $log.debug? keycode = keycode_tos(ch) $log.debug " form HK #{ch} #{self}, #{@name}, #{keycode}, field: giving to: #{field}, #{field.name} " if field end handled = :UNHANDLED handled = field.handle_key ch unless field.nil? # no field focussable $log.debug "handled inside Form #{ch} from #{field} got #{handled} " # some widgets like textarea and list handle up and down if handled == :UNHANDLED or handled == -1 or field.nil? case ch when KEY_TAB, ?\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 FFI::NCurses::KEY_BTAB, 481 ## backtab added 2008-12-14 18:41 ret = select_prev_field return ret if ret == :NO_PREV_FIELD when FFI::NCurses::KEY_UP ret = select_prev_field return ret if ret == :NO_PREV_FIELD when FFI::NCurses::KEY_DOWN ret = select_next_field return ret if ret == :NO_NEXT_FIELD else #$log.debug " before calling process_key in form #{ch} " if $log.debug? ret = process_key ch, self # seems we need to flushinp in case composite has pushed key $log.debug "FORM process_key #{ch} got ret #{ret} in #{self}, flushing input " # 2014-06-01 - 17:01 added flush, maybe at some point we could do it only if unhandled # in case some method wishes to actually push some keys Ncurses.flushinp return :UNHANDLED if ret == :UNHANDLED end elsif handled == :NO_NEXT_FIELD || handled == :NO_PREV_FIELD # 2011-10-4 return handled end end $log.debug " form before repaint #{self} , #{@name}, ret #{ret}" repaint $last_key = ch ret || 0 # 2011-10-17 end |
#help_manager ⇒ Object
returns in instance of help_manager with which one may install help_text and call help. user apps will only supply help_text, form would already have mapped F1 to help.
2215 2216 2217 2218 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2215 def help_manager require 'canis/core/util/helpmanager' @help_manager ||= Canis::HelpManager.new self end |
#map_keys ⇒ Object
These mappings will only trigger if the current field
does not use them.
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2065 def map_keys return if @keys_mapped bind_key(KEY_F1, 'help') { hm = help_manager(); hm.display_help } bind_keys([?\M-?,?\?], 'show field help') { #if get_current_field.help_text #textdialog(get_current_field.help_text, 'title' => 'Help Text', :bgcolor => 'green', :color => :white) #else print_key_bindings #end } bind_key(FFI::NCurses::KEY_F9, "Print keys", :print_key_bindings) # show bindings, tentative on F9 bind_key(?\M-:, 'show menu') { fld = get_current_field am = fld.action_manager() #fld.init_menu am.show_actions } @keys_mapped = true end |
#on_enter(f) ⇒ Object
form calls on_enter of each object. However, if a multicomponent calls on_enter of a widget, this code will not be triggered. The highlighted part
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1785 def on_enter f return if f.nil? || !f.focusable # added focusable, else label was firing 2010-09 f.state = :HIGHLIGHTED # If the widget has a color defined for focussed, set repaint # otherwise it will not be repainted unless user edits ! if f.highlight_bgcolor || f.highlight_color f.repaint_required true end f.modified false #f.set_modified false f.on_enter if f.respond_to? :on_enter # 2014-04-24 - 17:42 NO MORE ENTER LEAVE at FORM LEVEL #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
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1767 def on_leave f return if f.nil? || !f.focusable # added focusable, else label was firing f.state = :NORMAL # on leaving update text_variable if defined. Should happen on modified only # should this not be f.text_var ... f.buffer ? 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 # 2014-04-24 - 17:42 NO MORE ENTER LEAVE at FORM LEVEL #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
1988 1989 1990 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1988 def process_key keycode, object return _process_key keycode, object, @window end |
#remove_widget(widget) ⇒ Object
remove a widget (internal use)
1652 1653 1654 1655 1656 1657 1658 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1652 def if .respond_to? :name and !.name.nil? @by_name.delete(.name) end @focusable_modified = true @widgets.delete end |
#repaint ⇒ Object
form repaint,calls repaint on each widget which will repaint it only if it has been modified since last call. called after each keypress.
1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1678 def repaint $log.debug " form repaint:#{self}, #{@name} , r #{@row} c #{@col} " if $log.debug? if @resize_required && @layout_manager @layout_manager.form = self unless @layout_manager.form @layout_manager.do_layout @resize_required = false end @widgets.each do |f| next if f.visible == false # added 2008-12-09 12:17 #$log.debug "XXX: FORM CALLING REPAINT OF WIDGET #{f} IN LOOP" #raise "Row or col nil #{f.row} #{f.col} for #{f}, #{f.name} " if f.row.nil? || f.col.nil? f.repaint f._object_created = true # added 2010-09-16 13:02 now prop handlers can be fired end _update_focusables if @focusable_modified # this can bomb if someone sets row. We need a better way! if @row == -1 and @_firsttime == true select_first_field @_firsttime = false end setpos # XXX this creates a problem if window is a pad # although this does show cursor movement etc. ### @window.wrefresh #if @window.window_type == :WINDOW #$log.debug " formrepaint #{@name} calling window.wrefresh #{@window} " @window.wrefresh Ncurses::Panel.update_panels ## added 2010-11-05 00:30 to see if clears the stdscr problems #else #$log.warn " XXX formrepaint #{@name} no refresh called 2011-09-19 #{@window} " #end end |
#repaint_all_widgets ⇒ Object
this forces a repaint of all visible widgets and has been added for the case of overlapping windows, since a black rectangle is often left when a window is destroyed. This is internally triggered whenever a window is destroyed, and currently only for root window. NOTE: often the window itself or spaces between widgets also gets cleared, so basically the window itself may need recreating ? 2014-08-18 - 21:03
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2090 def $log.debug " REPAINT ALL in FORM called " @widgets.each do |w| next if w.visible == false next if w.class.to_s == "Canis::MenuBar" $log.debug " ---- REPAINT ALL #{w.name} " #w.repaint_required true w.repaint_all true w.repaint end $log.debug " REPAINT ALL in FORM complete " # place cursor on current_widget setpos 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
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1806 def select_field ix0 if ix0.is_a? Widget ix0 = @widgets.index(ix0) end return if @widgets.nil? or @widgets.empty? #$log.debug "inside select_field : #{ix0} ai #{@active_index}" f = @widgets[ix0] return if !f.focusable? if f.focusable? @active_index = ix0 @row, @col = f.rowcol #$log.debug " WMOVE insdie sele nxt field : ROW #{@row} COL #{@col} " on_enter f @window.wmove @row, @col # added RK FFI 2011-09-7 = setpos f.set_form_row # added 2011-10-5 so when embedded in another form it can get the cursor f.set_form_col # this can wreak havoc in containers, unless overridden # next line in field changes cursor position after setting form_col # resulting in a bug. 2011-11-25 # maybe it is in containers or tabbed panes and multi-containers # where previous objects col is still shown. we cannot do this after # setformcol #f.curpos = 0 # why was this, okay is it because of prev obj's cursor ? repaint @window.refresh else $log.debug "inside select field ENABLED FALSE : act #{@active_index} ix0 #{ix0}" end end |
#select_first_field ⇒ Object
take focus to first focussable field we shoud not send to select_next. have a separate method to avoid bugs. but check current_field, in case called from anotehr field TODO FIXME
1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1732 def select_first_field # this results in on_leave of last field being executed when form starts. #@active_index = -1 # FIXME HACK #select_next_field ix = @focusables.first return unless ix # no focussable field # if the user is on a field other than current then fire on_leave if @active_index.nil? || @active_index < 0 elsif @active_index != ix f = @widgets[@active_index] begin #$log.debug " select first field, calling on_leave of #{f} #{@active_index} " on_leave f rescue => err $log.error " Caught EXCEPTION select_first_field on_leave #{err}" Ncurses.beep #$error_message = "#{err}" $error_message.value = "#{err}" return end end select_field ix end |
#select_last_field ⇒ Object
take focus to last field on form
1758 1759 1760 1761 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1758 def select_last_field @active_index = nil select_prev_field end |
#select_next_field ⇒ Object
put focus on next field will cycle by default, unless navigation policy not :CYCLICAL in which case returns :NO_NEXT_FIELD. FIXME: in the beginning it comes in as -1 and does an on_leave of last field
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1860 def select_next_field return :UNHANDLED if @widgets.nil? || @widgets.empty? #$log.debug "insdie sele nxt field : #{@active_index} WL:#{@widgets.length}" if @active_index.nil? || @active_index == -1 # needs to be tested out A LOT # what is this silly hack for still here 2014-04-24 - 13:04 DELETE FIXME @active_index = -1 else f = @widgets[@active_index] begin on_leave f rescue FieldValidationException => err # added 2011-10-2 v1.3.1 so we can rollback $log.error "select_next_field: caught EXCEPTION #{err}" $error_message.value = "#{err}" raise err rescue => err $log.error "select_next_field: caught EXCEPTION #{err}" $log.error(err.backtrace.join("\n")) # $error_message = "#{err}" # changed 2010 $error_message.value = "#{err}" Ncurses.beep return 0 end end f = @widgets[@active_index] index = @focusables.index(f) # 2014-08-09 - 13:09 f may be status_line esp if ai is -1, so it is not found in focusables # why are we first checking widgets and then focusables. #index += 1 index = index ? index+1 : 0 f = @focusables[index] if f select_field f return 0 end # #$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 f = @focusables.first if f select_field f return 0 end end $log.debug "inside sele nxt field : NO NEXT #{@active_index} WL:#{@widgets.length}" return :NO_NEXT_FIELD end |
#select_prev_field ⇒ nil, :NO_PREV_FIELD
put focus on previous field will cycle by default, unless navigation policy not :CYCLICAL in which case returns :NO_PREV_FIELD.
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1913 def select_prev_field return :UNHANDLED 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.error " Caught EXCEPTION #{err}" Ncurses.beep # $error_message = "#{err}" # changed 2010 $error_message.value = "#{err}" return end end f = @widgets[@active_index] index = @focusables.index(f) if index > 0 index -= 1 f = @focusables[index] if f select_field f return end end ## 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 f = @focusables.last select_field @widgets.index(f) if f 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 ?
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1618 def mb @menu_bar = mb mb mb.toggle_key ||= Ncurses.KEY_F2 if !mb.toggle_key.nil? ch = mb.toggle_key bind_key(ch, 'Menu Bar') do |_form| if !@menu_bar.nil? @menu_bar.toggle @menu_bar.handle_keys end end end end |
#setpos(r = @row, c = @col) ⇒ Object
move cursor to where the fields row and col are private
1715 1716 1717 1718 1719 1720 1721 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1715 def setpos r=@row, c=@col #$log.debug "setpos : (#{self.name}) #{r} #{c} XXX" ## 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.
1976 1977 1978 1979 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1976 def setrowcol r, c @row = r unless r.nil? @col = c unless c.nil? end |
#to_s ⇒ Object
2010-02-07 14:50 to aid in debugging and comparing log files.
2210 |
# File 'lib/canis/core/widgets/rwidget.rb', line 2210 def to_s; @name || self; end |
#universal_argument ⇒ Object
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
1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1998 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 |
#update_focusables ⇒ Object
sets a flag that focusables should be updated called whenever a widgets changes its focusable property
1662 1663 1664 1665 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1662 def update_focusables $log.debug "XXX: inside update focusables" @focusable_modified = true end |
#validate_field(f = ) ⇒ 0, -1
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. # @param field object NOTE : catches exception and sets $error_message, check if -1
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 |
# File 'lib/canis/core/widgets/rwidget.rb', line 1843 def validate_field f=@widgets[@active_index] begin on_leave f rescue => err $log.error "form: validate_field caught EXCEPTION #{err}" $log.error(err.backtrace.join("\n")) # $error_message = "#{err}" # changed 2010 $error_message.value = "#{err}" Ncurses.beep return -1 end return 0 end |