canis 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,194 @@
1
+ require 'canis/core/widgets/rwidget'
2
+ #include Ncurses # FFI 2011-09-8
3
+ include Canis
4
+ module Canis
5
+ #
6
+ # This paints labels for various keys at the bottom of the screen, in 2 rows.
7
+ # This is based on alpines last 2 rows. Modes are supported so that the
8
+ # labels change as you enter a widget.
9
+ # For an example, see dbdemo.rb or rfe.rb
10
+ # NOTE: applications using 'App' use a shortcut "dock" to create this.
11
+ #
12
+ # The most minimal keylabel to print one label in first row, and none in second is:
13
+ # [["F1", "Help"], nil]
14
+ # To print 2 labels, one over the other:
15
+ # [["F1", "Help"], ["F10", "Quit"]]
16
+ #
17
+ class KeyLabelPrinter < Widget
18
+ attr_reader :key_labels
19
+ # the current mode (labels are based on mode, changing the mode, changes the labels
20
+ # displayed)
21
+ dsl_property :mode
22
+ # set the color of the labels, overriding the defaults
23
+ dsl_accessor :footer_color_pair
24
+ # set the color of the mnemonic, overriding the defaults
25
+ dsl_accessor :footer_mnemonic_color_pair
26
+ #attr_accessor :row_relative # lets only advertise this when we've tested it out
27
+
28
+ def initialize form, key_labels, config={}, &block
29
+
30
+ @name = "dock"
31
+ case key_labels
32
+ when Hash
33
+ raise "KeyLabelPrinter: KeyLabels cannot be a hash, Array of key labels required. Perhaps you did not pass labels"
34
+ when Array
35
+ else
36
+ raise "KeyLabelPrinter: Array of key labels required. Perhaps you did not pass labels"
37
+ end
38
+ super form, config, &block
39
+ @mode ||= :normal
40
+ #@key_labels = key_labels
41
+ @key_hash = {}
42
+ @key_hash[@mode] = key_labels
43
+ @editable = false
44
+ @focusable = false
45
+ unless @row
46
+ @row_relative = -2
47
+ @row = Ncurses.LINES + @row_relative
48
+ end
49
+ @col ||= 0
50
+ # if negativ row passed we store as relative to bottom, so we can maintain that.
51
+ if @row < 0
52
+ @row_relative = @row
53
+ @row = Ncurses.LINES - @row
54
+ else
55
+ @row_relative = (Ncurses.LINES - @row) * -1
56
+ end
57
+ @cols ||= Ncurses.COLS-1
58
+ @repaint_required = true
59
+ @footer_color_pair ||= $bottomcolor
60
+ @footer_mnemonic_color_pair ||= $reversecolor #2
61
+ end
62
+ def key_labels mode=@mode
63
+ @key_hash[mode]
64
+ end
65
+ # returns the keys as printed. these may or may not help
66
+ # in validation depedign on what you passed as zeroth index
67
+ def get_current_keys
68
+ a = []
69
+ @key_hash[@mode].each do |arr|
70
+ a << arr[0] unless arr.nil?
71
+ end
72
+ return a
73
+ end
74
+ def getvalue
75
+ @key_hash
76
+ end
77
+ def set_key_labels _key_labels, mode=:normal
78
+ @key_hash[mode] = _key_labels
79
+ end
80
+
81
+ ##
82
+ # XXX need to move wrapping etc up and done once.
83
+ def repaint
84
+ return unless @repaint_required
85
+ r,c = rowcol
86
+ # this should only happen if there's a change in window
87
+ if @row_relative
88
+ @row = Ncurses.LINES+@row_relative
89
+ end
90
+ arr = key_labels()
91
+ print_key_labels(arr, mode=@mode)
92
+ @repaint_required = false
93
+ end
94
+ # ?? does not use mode, i think key_labels is unused. a hash is now used 2011-10-11 XXX FIXME
95
+ # WARNING, i have not tested this after changing it.
96
+ def append_key_label key, label, mode=@mode
97
+ #@key_labels << [key, label] if !@key_labels.include? [key, label]
98
+ @key_hash[mode] << [key, label] if !@key_hash[mode].include? [key, label]
99
+ @repaint_required = true
100
+ end
101
+ def print_key_labels(arr = key_labels(), mode=@mode)
102
+ #return if !@show_key_labels # XXX
103
+ @win ||= @form.window
104
+ #$log.debug "XXX: PKL #{arr.length}, #{arr}"
105
+ @padding = @cols / (arr.length/2)
106
+ posx = 0
107
+ even = []
108
+ odd = []
109
+ arr.each_index { |i|
110
+ if i % 2 == 0
111
+ #arr[i+1] = ['',''] if arr[i+1].nil?
112
+ nextarr = arr[i+1] || ['', '']
113
+ keyw = [arr[i][0].length, nextarr[0].length].max
114
+ labelw = [arr[i][1].length, nextarr[1].length].max
115
+
116
+ even << [ sprintf("%*s", keyw, arr[i][0]), sprintf("%-*s", labelw, arr[i][1]) ]
117
+ odd << [ sprintf("%*s", keyw, nextarr[0]), sprintf("%-*s", labelw, nextarr[1]) ]
118
+ #$log.debug("loop even: #{even.inspect}")
119
+ else
120
+ end
121
+ }
122
+ #$log.debug("even: #{even.inspect}")
123
+ #$log.debug("odd : #{odd.inspect}")
124
+ #posy = @barrow-1
125
+ posy = @row
126
+ print_key_labels_row(posy, posx, even)
127
+ posy = @row+1
128
+ print_key_labels_row(posy, posx, odd)
129
+ # uncommented next line after ffi-ncurses else not showing till key press FFI 2011-09-17
130
+ @win.wrefresh # needed else secod row not shown after askchoice XXX
131
+ end
132
+ def print_key_labels_row(posy, posx, arr)
133
+ # FIXME: this logic of padding needs to take into account
134
+ # width of window
135
+ padding = 8
136
+ padding = 4 if arr.length > 5
137
+ padding = 2 if arr.length > 7
138
+ padding = 0 if arr.length > 9
139
+ #padding = @padding # XXX 2008-11-13 23:01
140
+ my_form_win = @win
141
+ @win.printstring(posy,0, "%-*s" % [@cols," "], @footer_color_pair, @attr)
142
+ arr.each do |kl|
143
+ key = kl[0]
144
+ lab = kl[1]
145
+ if key !="" # don't print that white blank space for fillers
146
+ color_pair= @footer_mnemonic_color_pair # $reversecolor #2
147
+ x = posx + (key.length - key.strip.length)
148
+ my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
149
+ my_form_win.mvprintw(posy, x, "%s" % kl[0].strip );
150
+ my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
151
+ end
152
+ color_pair=@footer_color_pair
153
+ posx = posx + kl[0].length
154
+ my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
155
+
156
+ #lab = sprintf(" %s %*s" , kl[1], padding, " ");
157
+ lab = sprintf(" %s %s" , kl[1], " "*padding);
158
+ my_form_win.mvprintw(posy, posx, lab)
159
+ my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
160
+ posx = posx + lab.length
161
+ end
162
+ end
163
+ ##
164
+ # updates existing label with a new one.
165
+ # @return true if updated, else false
166
+ # @example update "C-x", "C-x", "Disable"
167
+ def update_application_key_label(display_code, new_display_code, text)
168
+ @repaint_required = true
169
+ labels = key_labels()
170
+ raise "labels are nil !!!" unless labels
171
+ labels.each_index do |ix|
172
+ lab = labels[ix]
173
+ next if lab.nil?
174
+ if lab[0] == display_code
175
+ labels[ix] = [new_display_code , text]
176
+ $log.debug("updated #{labels[ix]}")
177
+ return true
178
+ end
179
+ end
180
+ return false
181
+ end
182
+ alias :update :update_application_key_label
183
+ ##
184
+ # inserts an application label at given index
185
+ # to add the key, use create_datakeys to add bindings
186
+ # remember to call restore_application_key_labels after updating/inserting
187
+ def insert_application_key_label(index, display_code, text)
188
+ @repaint_required = true
189
+ labels = key_labels()
190
+ labels.insert(index, [display_code , text] )
191
+ end
192
+ # ADD HERE KEYLABEL
193
+ end
194
+ end
@@ -0,0 +1,326 @@
1
+ #!/usr/bin/env ruby
2
+ # ----------------------------------------------------------------------------- #
3
+ # File: listbox.rb
4
+ # Description: A list box based on textpad
5
+ # Author: jkepler http://github.com/mare-imbrium/canis/
6
+ # Date: 2014-04-06 - 19:37
7
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
8
+ # Last update: 2014-07-07 00:36
9
+ # ----------------------------------------------------------------------------- #
10
+ # listbox.rb Copyright (C) 2012-2014 kepler
11
+
12
+ require 'canis'
13
+ require 'forwardable'
14
+ require 'canis/core/include/listselectionmodel'
15
+ ##
16
+ # A listbox based on textpad.
17
+ # Contains a scrollable array of Strings. The list is selectable too.
18
+ # In place editing is not provided, however editing in a separate box
19
+ # has been implemented in various examples.
20
+ # Essentially, the listbox only adds selection to the textpad.
21
+ # TODO
22
+ # ----
23
+ # [ ] focussed_color - this could be part of textpad too. row under cursor
24
+ # [ ] rlist has menu actions that can use prompt menu or popup ?
25
+ # [ ] nothing has been done about show_selector -- consider whether to knock off
26
+ #
27
+ #
28
+ # CHANGES
29
+ # -------
30
+ # - removed Array operations to Textpad, some renaming 2014-04-10 - 20:50
31
+ #
32
+ #
33
+ module Canis
34
+
35
+ ##
36
+ # A scrollable, selectable array of strings.
37
+ # Delegates display to ListRenderer
38
+ # Delegates selection to Defaultlistselection (/include/listselectionmodel.rb)
39
+ # Due to extending Defaultlistselection, methods are not visible here.
40
+ # Selection methods are (the first three are what programmers will use the most):
41
+ #
42
+ # - `selected_values` : returns values selecteda (multiple selection)
43
+ # - `selected_value` : returns value of row selected (single selection)
44
+ # - `selected_rows` : same as selected_indices, indices of selected items
45
+ #
46
+ # - `toggle_row_selection` : toggles current row, called by key $row_selector
47
+ # - `select` : select given or current row
48
+ # - `unselect` : unselects given or current row
49
+ # - `is_row_selected?` : determine if given row is selected
50
+ # - `is_selection_empty?` : has anything been selected
51
+ # - `clear_selection` : clear selection
52
+ # - `select_all` : select all rows
53
+ #
54
+ # Listbox also fires a ListSelectionEvent whose type can be:
55
+ #
56
+ # - :INSERT , a row or rows added to selection
57
+ # - :DELETE , a row or rows removed from selection
58
+ # - :CLEAR , all selection cleared
59
+ #
60
+ # == Examples
61
+ #
62
+ # mylist = %w[john tim matz shougo _why sean aaron]
63
+ # l = Listbox.new @form, :row => 5, :col => 4, :height => 10, :width => 20, :list => mylist
64
+ #
65
+ # Inside a Flow:
66
+ #
67
+ # lb = listbox :list => mylist, :title => 'Contacts', :width_pc => 50, :selection_mode => :single
68
+ #
69
+ class Listbox < TextPad
70
+
71
+ extend Forwardable
72
+
73
+ # boolean, should a selector character be shown on the left of data for selected rows.
74
+ dsl_property :show_selector
75
+ # should textpads content_cols also add left_margin ? XXX
76
+ # how much space to leave on left, currently 0, was used with selector character once
77
+ dsl_property :left_margin
78
+
79
+ # justify text to :left :right or :center (renderer to take care of this).
80
+ dsl_accessor :justify
81
+
82
+ # should focussed line be shown in a different way, currently BOLD, default true
83
+ dsl_accessor :should_show_focus
84
+
85
+ def initialize form = nil, config={}, &block
86
+
87
+ @left_margin = 0
88
+ @should_show_focus = true
89
+
90
+ register_events([:LEAVE_ROW, :LIST_SELECTION_EVENT])
91
+ self.extend DefaultListSelection
92
+ super
93
+ # textpad takes care of enter_row and press
94
+ #@_events.push(*[:LEAVE_ROW, :LIST_SELECTION_EVENT])
95
+ bind_key(?f, 'next row starting with char'){ set_selection_for_char(nil) }
96
+
97
+ # if user has not specified a selection model, install default
98
+ unless @selection_mode == :none
99
+ unless @list_selection_model
100
+ create_default_selection_model
101
+ end
102
+ end
103
+ # if user has not specified a renderer, install default
104
+ unless @renderer
105
+ create_default_renderer
106
+ end
107
+ end
108
+ # create a default renderer since user has not specified
109
+ # Widgets inheriting this with a differernt rendering such as tree
110
+ # can overrider this.
111
+ def create_default_renderer
112
+ r = ListRenderer.new self
113
+ renderer(r)
114
+ end
115
+ def renderer *val
116
+ if val.empty?
117
+ return @renderer
118
+ end
119
+ @renderer = val[0]
120
+ end
121
+ # create a default selection model
122
+ # Widgets inheriting this may override this
123
+ def create_default_selection_model
124
+ list_selection_model(Canis::DefaultListSelectionModel.new self)
125
+ end
126
+
127
+
128
+ # http://www.opensource.apple.com/source/gcc/gcc-5483/libjava/javax/swing/table/DefaultTableColumnModel.java
129
+ #
130
+ # clear the list completely of data, including selections
131
+ def clear
132
+ @selected_indices.clear
133
+ super
134
+ end
135
+ alias :remove_all :clear
136
+
137
+ # This is called whenever user leaves a row
138
+ # Fires handler for leave_row
139
+ def on_leave_row arow
140
+ # leave this out, since we are not painting on exit of widget 2014-07-02 - 17:51
141
+ #if @should_show_focus
142
+ #fire_row_changed arow
143
+ #end
144
+ fire_handler :LEAVE_ROW, self
145
+ end
146
+ # This is called whenever user enters a row
147
+ def on_enter_row arow
148
+ super
149
+ # TODO check if user wants focus to be showed
150
+ ## this results in the row being entered and left being evaluated and repainted
151
+ # which means that the focussed row can be bolded. The renderer's +render+ method will be triggered
152
+ if @should_show_focus
153
+ fire_row_changed @oldindex
154
+ fire_row_changed arow
155
+ end
156
+ end
157
+ #def on_leave
158
+ #super
159
+ #on_leave_row @current_index if @current_index
160
+ #end
161
+ # get a char ensure it is a char or number
162
+ # In this state, it could accept control and other chars.
163
+ private
164
+ def _ask_a_char
165
+ ch = @graphic.getch
166
+ #message "achar is #{ch}"
167
+ if ch < 26 || ch > 255
168
+ @graphic.ungetch ch
169
+ return :UNHANDLED
170
+ end
171
+ return ch.chr
172
+ end
173
+ public
174
+ # sets the selection to the next row starting with char
175
+ # Trying to return unhandled is having no effect right now. if only we could pop it into a
176
+ # stack or unget it.
177
+ def set_selection_for_char char=nil
178
+ char = _ask_a_char unless char
179
+ return :UNHANDLED if char == :UNHANDLED
180
+ #alert "got #{char}"
181
+ @oldrow = @current_index
182
+ @last_regex = /^#{char}/i
183
+ ix = next_regex @last_regex
184
+ return unless ix
185
+ @current_index = ix[0]
186
+ #alert "curr ind #{@current_index} "
187
+ @search_found_ix = @current_index
188
+ @curpos = ix[1]
189
+ ensure_visible
190
+ return @current_index
191
+ end
192
+ # Find the next row that contains given string
193
+ # @return row and col offset of match, or nil
194
+ # @param String to find
195
+ def next_regex str
196
+ first = nil
197
+ ## content can be string or Chunkline, so we had to write <tt>index</tt> for this.
198
+ ## =~ does not give an error, but it does not work.
199
+ @list.each_with_index do |line, ix|
200
+ col = line =~ /#{str}/
201
+ if col
202
+ first ||= [ ix, col ]
203
+ if ix > @current_index
204
+ return [ix, col]
205
+ end
206
+ end
207
+ end
208
+ return first
209
+ end
210
+
211
+ end # class listbox
212
+
213
+
214
+ ## Takes care of rendering the list.
215
+ # In the case of a List we take care of selected indices.
216
+ # Also, focussed row is shown in bold, although we can make that optional and configurable
217
+ # A user wanting a different rendering of listboxes may either extend this class
218
+ # or completely replace it and set it as the renderer.
219
+ class ListRenderer < AbstractTextPadRenderer
220
+ # text to be placed in the left margin. This requires that a left margin be set in the source
221
+ # object.
222
+ attr_accessor :left_margin_text
223
+ attr_accessor :row_focussed_attr
224
+
225
+ def initialize source
226
+ @source = source
227
+ # internal width based on both borders - earlier internal_width which we need
228
+ @int_w = 3
229
+ # 3 leaves a blank black in popuplists as in testlistbox.rb F4
230
+ # setting it as 2 means that in some cases, the next line first character
231
+ # gets overwritten with traversal
232
+ #@int_w = 2
233
+ end
234
+ # This is called prior to render_all, and may not be called when a single row is rendered
235
+ # as in fire_row_changed
236
+ def pre_render
237
+ super
238
+ @selected_indices = @source.selected_indices
239
+ @left_margin = @source.left_margin
240
+ @bg = @source.bgcolor
241
+ @fg = @source.color
242
+ @attr = NORMAL
243
+ @row_focussed_attr ||= $row_focussed_attr
244
+ end
245
+
246
+ #
247
+ # @param pad for calling print methods on
248
+ # @param lineno the line number on the pad to print on
249
+ # @param text data to print
250
+ #--
251
+ # NOTE: in some cases like testlistbox.rb if a line is updated then the newly printed
252
+ # value may not overwrite the entire line, addstr seems to only write the text no more
253
+ # Fixed with +clear_row+
254
+ #++
255
+ def render pad, lineno, text
256
+ sele = false
257
+ =begin
258
+ bg = @source.bgcolor
259
+ fg = @source.color
260
+ att = NORMAL
261
+ cp = get_color($datacolor, fg, bg)
262
+ =end
263
+ bg = @bg || @source.bgcolor
264
+ fg = @fg || @source.color
265
+ att = @attr || NORMAL
266
+ cp = get_color($datacolor, fg, bg)
267
+
268
+ if @selected_indices.include? lineno
269
+ # print selected row in reverse
270
+ sele = true
271
+ fg = @source.selected_color || fg
272
+ bg = @source.selected_bgcolor || bg
273
+ att = @source.selected_attr || REVERSE
274
+ cp = get_color($datacolor, fg, bg)
275
+ elsif lineno == @source.current_index
276
+ # print focussed row in different attrib
277
+ if @source.should_show_focus
278
+ # bold was supposed to be if the object loses focus, but although render is called
279
+ # however, padrefresh is not happening since we do not paint on exiting a widget
280
+ att = BOLD
281
+ if @source.focussed
282
+ att = @row_focussed_attr
283
+ end
284
+ end
285
+ # take current index into account as BOLD
286
+ # and oldindex as normal
287
+ end
288
+ FFI::NCurses.wattron(pad,FFI::NCurses.COLOR_PAIR(cp) | att)
289
+ FFI::NCurses.mvwaddstr(pad, lineno, 0, @left_margin_text) if @left_margin_text
290
+ FFI::NCurses.mvwaddstr(pad, lineno, @left_margin, text)
291
+ FFI::NCurses.wattroff(pad,FFI::NCurses.COLOR_PAIR(cp) | att)
292
+
293
+ # the above only sets the attrib under the text not the whole line, we
294
+ # need the whole line to be REVERSE
295
+ # Strangely in testlistbox1 unselecting removes the entire lines REVERSE
296
+ # but in testlistbox.rb the previous selected lines REV only partially goes
297
+ # so we have to make the entire line in current attrib
298
+ sele = true
299
+ if sele
300
+ FFI::NCurses.mvwchgat(pad, y=lineno, x=@left_margin, @source.width - @left_margin - @int_w, att, cp, nil)
301
+ end
302
+ end
303
+ # clear row before writing so previous contents are erased and don't show through
304
+ # I could do this everytime i write but trying to make it faster
305
+ # and only call this if +fire_row_changed+ is called.
306
+ # NOTE: in clear_row one is supposed to clear to the width of the pad, not window
307
+ # otherwise on scrolling you might get black bg if you have some other color bg.
308
+ # This is mostly important if you have a bgcolor that is different from the terminal
309
+ # bgcolor.
310
+ # @param - pad
311
+ # @param - line number (index of row to clear)
312
+ def _clear_row pad, lineno
313
+ raise "unused"
314
+ @color_pair ||= get_color($datacolor, @source.color, @source.bgcolor)
315
+ cp = @color_pair
316
+ att = NORMAL
317
+ @_clearstring ||= " " * (@source.width - @left_margin - @int_w)
318
+ # with int_w = 3 we get that one space in popuplist
319
+ # added attr on 2014-05-02 - 00:16 otherwise a list inside a white bg messagebox shows
320
+ # empty rows in black bg.
321
+ FFI::NCurses.wattron(pad,FFI::NCurses.COLOR_PAIR(cp) | att)
322
+ FFI::NCurses.mvwaddstr(pad,lineno, @left_margin, @_clearstring)
323
+ FFI::NCurses.wattroff(pad,FFI::NCurses.COLOR_PAIR(cp) | att)
324
+ end
325
+ end
326
+ end # module