Class: MenuWindow
- Inherits:
-
Object
- Object
- MenuWindow
- Defined in:
- lib/menu_window.rb
Overview
Wraps a collection of objects into a menu window
Instance Attribute Summary collapse
-
#current_index ⇒ Object
Returns the value of attribute current_index.
-
#items ⇒ Object
Returns the value of attribute items.
-
#matches ⇒ Object
Returns the value of attribute matches.
-
#search_string ⇒ Object
Returns the value of attribute search_string.
Instance Method Summary collapse
- #beginning ⇒ Object
- #bottom ⇒ Object
-
#cancel_search ⇒ Object
Cancels local search only.
- #close ⇒ Object
- #create_page ⇒ Object
- #draw_arrow ⇒ Object
- #draw_line(text, item) ⇒ Object
-
#draw_menu(items = @page_content) ⇒ Object
Draws the actual menu on the screen, with appropriate color highlighting The color of the highlighting is determined by the model.
-
#draw_title ⇒ Object
TODO put the date range of the items in the title.
- #end ⇒ Object
- #erase_arrow ⇒ Object
- #flag_all ⇒ Object
- #highlight_global_matches(matches, search_string) ⇒ Object
- #highlight_matches(matches, search_string) ⇒ Object
-
#initialize(title, scr, items, current_index, matches = nil, options = {}) ⇒ MenuWindow
constructor
Matches are passed in when a search succeeds and certain items need to be indicated as matches TODO This should be changed into a hash parameter with keys.
- #middle ⇒ Object
- #move_arrow_or_page ⇒ Object
-
#move_to_item(item_index) ⇒ Object
Used to moved in constrainted way among a subset (search matches) of the larger set.
-
#move_to_next_item_in_set(set) ⇒ Object
set
is a set of indexes to the original larger set. - #move_to_prev_item_in_set(set) ⇒ Object
- #next_item(multiplier) ⇒ Object
- #next_page ⇒ Object
- #prev_item(multiplier) ⇒ Object
- #prev_page ⇒ Object
- #redraw_menu ⇒ Object
-
#toggle_flag ⇒ Object
TODO change this to coloring the line.
- #top ⇒ Object
- #unflag_all ⇒ Object
Constructor Details
#initialize(title, scr, items, current_index, matches = nil, options = {}) ⇒ MenuWindow
Matches are passed in when a search succeeds and certain items need to be indicated as matches TODO This should be changed into a hash parameter with keys
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/menu_window.rb', line 8 def initialize(title, scr, items, current_index, matches=nil, ={}) @options = @matches = matches @height = scr.maxy - 6 @width = scr.maxx - 2 scr.clear scr.setpos(2, 5) scr.refresh @title = title @title_box = Curses::Window.new(2, @width, 2, 5) # @window is the main content window @window = Curses::Window.new(@height, @width, 4, 2) @items = items if @items.empty? @title_box.addstr(@title) @title_box.refresh @window.clear @window.addstr(" No items") @window.refresh # need to disable some commands in the controller return end @pager = MenuPager.new(@height, @width) @current_index = current_index || 0 @window.clear if @window # page_content is an array of hashes with keys :item and :text @page_index, @page_content = create_page (@page_content) draw_title draw_arrow # draw pointer at current selection @window.refresh end |
Instance Attribute Details
#current_index ⇒ Object
Returns the value of attribute current_index.
3 4 5 |
# File 'lib/menu_window.rb', line 3 def current_index @current_index end |
#items ⇒ Object
Returns the value of attribute items.
3 4 5 |
# File 'lib/menu_window.rb', line 3 def items @items end |
#matches ⇒ Object
Returns the value of attribute matches.
3 4 5 |
# File 'lib/menu_window.rb', line 3 def matches @matches end |
#search_string ⇒ Object
Returns the value of attribute search_string.
3 4 5 |
# File 'lib/menu_window.rb', line 3 def search_string @search_string end |
Instance Method Details
#beginning ⇒ Object
387 388 389 390 391 |
# File 'lib/menu_window.rb', line 387 def beginning erase_arrow @current_index = @items.size - 1 move_arrow_or_page end |
#bottom ⇒ Object
371 372 373 374 375 376 377 378 379 |
# File 'lib/menu_window.rb', line 371 def bottom new_index = (@page_index + 1) * @height - 1 if new_index >= @items.size new_index = @items.size - 1 end erase_arrow @current_index = new_index move_arrow_or_page end |
#cancel_search ⇒ Object
Cancels local search only
100 101 102 103 104 |
# File 'lib/menu_window.rb', line 100 def cancel_search # Cancels local search only @matches = nil @search_string = nil end |
#close ⇒ Object
413 414 415 416 417 |
# File 'lib/menu_window.rb', line 413 def close @window.clear @window.refresh @window.close end |
#create_page ⇒ Object
52 53 54 |
# File 'lib/menu_window.rb', line 52 def create_page @pager.create_page(@items, @current_index, @matches, @options) end |
#draw_arrow ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/menu_window.rb', line 223 def draw_arrow # calculate where arrow should be drawn LOGGER.debug("Drawing arrow. Current index: #{@current_index}, Page index: #{@page_index}, Height: #{@height}") y = (@current_index - @page_index * @height) x = 0 LOGGER.debug "Drawing arrow at y #{y}" @window.setpos(y, x) @window.addstr("->") # move the cursor #@window.setpos(0,0) end |
#draw_line(text, item) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 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 |
# File 'lib/menu_window.rb', line 119 def draw_line(text, item) if item.is_a?(Entry) color = case when item.respond_to?(:flagged) && item.flagged && !@options[:turn_off_flagged_color] :red # when item.respond_to?(:is_new?) && item.is_new? # :green else nil end # local matches take precedence matches = @matches || @global_matches search_string = @search_string || @global_search_string if matches && !matches.empty? && matches.include?( @items.index(item) ) LOGGER.debug("matching line detected : search string #{search_string} : text: #{text}") text = text.gsub(/(#{search_string})/i, '%%%\1%%%') text.split(/%%%/).each_with_index do |chunk, index| if index % 2 == 0 @window.addstr(chunk, color) else @window.addstr(chunk, :yellow) end end else @window.addstr(text, color) end if @options[:show_feed_titles] # put the feed title in the title @window.addstr(" #{item.feed.title}", :cyan) end item_date = case when @options[:feed_title] == "All Entries" item.created_at when @options[:feed_title] == "Flagged Entries" item.flagged else item.date_published end if item_date item_date = " #{time_ago_in_words(item_date)} ago" else item_date = '' end @window.addstr(item_date, :magenta) @window.addstr("\n") # a feed or virtual feed else color = case when item.is_a?(VirtualFeed) && text =~ /Flagged Entries/ :red else nil end @window.addstr(text, color) # May not be the case with some virtual feeds # Add a column to feed that cached this attribute after an feed # update_self if item.is_a?(VirtualFeed) && item.title == "All Entries" # Use the created_at of the last entry entry = Entry.find(:first, :order => "id desc") last_updated = entry ? "#{time_ago_in_words(entry.created_at)} ago\n" : "\n" @window.addstr(" " + last_updated, :magenta) elsif item.is_a?(VirtualFeed) && item.title == "Flagged Entries" # Use the flagged timetamp of the last entry entry = Entry.find(:first, :conditions => "flagged IS NOT NULL", :order => "flagged desc") last_updated = entry ? "#{time_ago_in_words(entry.flagged)} ago\n" : "\n" @window.addstr(" " + last_updated , :magenta) elsif item.last_updated most_recent_entry = item.entries.first last_updated = (most_recent_entry && most_recent_entry.date_published) ? most_recent_entry.date_published : item.last_updated if last_updated last_updated = time_ago_in_words(last_updated) + " ago\n" else last_updated = '' end @window.addstr(" " + last_updated , :magenta) else @window.addstr("\n") end end end |
#draw_menu(items = @page_content) ⇒ Object
Draws the actual menu on the screen, with appropriate color highlighting The color of the highlighting is determined by the model. The item should have a :color attribute that returns the appropriate color as a symbol, which will be looked up on the Curses::Color table.
110 111 112 113 114 115 116 117 |
# File 'lib/menu_window.rb', line 110 def (items=@page_content) @window.setpos(0, 0) items.each do |x| draw_line(x[:text], x[:item]) end draw_arrow @window.refresh end |
#draw_title ⇒ Object
TODO put the date range of the items in the title
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/menu_window.rb', line 57 def draw_title @title_box.clear # This handles a list of feeds, which don't really have a date range unless @items.first && @items.first.respond_to?(:date_published) @title_box.addstr(@title) @title_box.refresh return end # Get the date range from the items in the page content dates = @page_content.map {|x| x[:item]}.map {|i| if i.respond_to?(:date_published) i.date_published elsif i.respond_to?(:last_updated) i.last_updated end } most_recent_date = dates.max.strftime('%B %d %Y') oldest_date = dates.min.strftime('%B %d %Y') if most_recent_date != oldest_date @title_box.addstr(@title + " | " + oldest_date + " - " + most_recent_date) else @title_box.addstr(@title + " | " + oldest_date) end @title_box.refresh end |
#end ⇒ Object
381 382 383 384 385 |
# File 'lib/menu_window.rb', line 381 def end erase_arrow @current_index = 0 move_arrow_or_page end |
#erase_arrow ⇒ Object
261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/menu_window.rb', line 261 def erase_arrow # calculate where arrow should be drawn y = (@current_index - @page_index * @height) x = 0 LOGGER.debug "Erasing arrow at y #{y}" @window.setpos(y, x) @window << " " return @window.delch @window.delch @window.delch @window.addstr end |
#flag_all ⇒ Object
254 255 256 257 258 259 |
# File 'lib/menu_window.rb', line 254 def flag_all @items.each do |item| item.update_attribute(:flagged, Time.now) end end |
#highlight_global_matches(matches, search_string) ⇒ Object
93 94 95 96 97 98 |
# File 'lib/menu_window.rb', line 93 def highlight_global_matches(matches, search_string) LOGGER.debug("setting matches to #{matches.inspect}") @global_search_string = search_string @global_matches = matches end |
#highlight_matches(matches, search_string) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/menu_window.rb', line 86 def highlight_matches(matches, search_string) LOGGER.debug("setting matches to #{matches.inspect}") @search_string = search_string @matches = matches end |
#middle ⇒ Object
360 361 362 363 364 365 366 367 368 369 |
# File 'lib/menu_window.rb', line 360 def middle new_index = (@page_index + 1) * (@height / 2) # Don't want the cursor positioned in a void when the list is short if new_index >= @items.size new_index = @items.size - 1 end erase_arrow @current_index = new_index move_arrow_or_page end |
#move_arrow_or_page ⇒ Object
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/menu_window.rb', line 393 def move_arrow_or_page new_page_index = @pager.calculate_page_for_index(@current_index) LOGGER.debug("Current page: #{@page_index}; New Page number: #{new_page_index}") if new_page_index == @page_index LOGGER.debug("Moving arrow") # move arrow draw_arrow @window.refresh else LOGGER.debug("Changing page") # change page # TODO change this implementation @page_index, @page_content = create_page end end |
#move_to_item(item_index) ⇒ Object
Used to moved in constrainted way among a subset (search matches) of the larger set
277 278 279 280 281 282 |
# File 'lib/menu_window.rb', line 277 def move_to_item(item_index) # move arrow, or change page erase_arrow @current_index = item_index move_arrow_or_page end |
#move_to_next_item_in_set(set) ⇒ Object
set
is a set of indexes to the original larger set
285 286 287 288 289 290 291 292 293 294 |
# File 'lib/menu_window.rb', line 285 def move_to_next_item_in_set(set) LOGGER.debug("set : #{set}") LOGGER.debug("@current_index : #{@current_index}") current_index = set.index( @current_index ) # move arrow, or change page return if current_index == set.length - 1 LOGGER.debug("current_index : #{current_index}") new_index = set[current_index + 1] move_to_item(new_index) end |
#move_to_prev_item_in_set(set) ⇒ Object
296 297 298 299 300 301 302 |
# File 'lib/menu_window.rb', line 296 def move_to_prev_item_in_set(set) current_index = set.index( @current_index ) # move arrow, or change page return if current_index == 0 new_index = set[current_index - 1] move_to_item(new_index) end |
#next_item(multiplier) ⇒ Object
305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/menu_window.rb', line 305 def next_item(multiplier) # move arrow, or change page new_index = @current_index + multiplier LOGGER.debug("New index is #{new_index}") if new_index >= @items.size new_index = @items.size - 1 end erase_arrow @current_index = new_index move_arrow_or_page end |
#next_page ⇒ Object
328 329 330 331 332 333 334 335 336 |
# File 'lib/menu_window.rb', line 328 def next_page new_index = (@page_index + 1) * @height if new_index >= @items.size new_index = @items.size - 1 end erase_arrow @current_index = new_index move_arrow_or_page end |
#prev_item(multiplier) ⇒ Object
317 318 319 320 321 322 323 324 325 326 |
# File 'lib/menu_window.rb', line 317 def prev_item(multiplier) # move arrow, or change page new_index = @current_index - multiplier if new_index < 0 new_index = 0 end erase_arrow @current_index = new_index move_arrow_or_page end |
#prev_page ⇒ Object
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 |
# File 'lib/menu_window.rb', line 338 def prev_page if @page_index == 0 top return end new_index = (@page_index - 1) * @height if new_index < 0 new_index = 0 end erase_arrow @current_index = new_index move_arrow_or_page # need to put cursor at bottom unless this is already 1st page bottom end |
#redraw_menu ⇒ Object
214 215 216 217 218 219 220 221 |
# File 'lib/menu_window.rb', line 214 def LOGGER.debug("Redrawing menu") @window.clear (@page_content) draw_arrow draw_title @window.refresh end |
#toggle_flag ⇒ Object
TODO change this to coloring the line
236 237 238 239 240 241 242 243 244 245 |
# File 'lib/menu_window.rb', line 236 def toggle_flag item = @items[@current_index] if item.flagged item.update_attribute(:flagged, nil) else item.update_attribute(:flagged, Time.now) end end |
#top ⇒ Object
354 355 356 357 358 |
# File 'lib/menu_window.rb', line 354 def top erase_arrow @current_index = (@page_index * @height) move_arrow_or_page end |
#unflag_all ⇒ Object
247 248 249 250 251 252 |
# File 'lib/menu_window.rb', line 247 def unflag_all @items.each do |item| item.update_attribute(:flagged, nil) end end |