rbcurse 0.1.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG +126 -0
  2. data/Manifest.txt +53 -20
  3. data/README.markdown +423 -0
  4. data/Rakefile +3 -1
  5. data/examples/keytest.rb +177 -0
  6. data/examples/mpad2.rb +156 -0
  7. data/examples/newtesttabp.rb +121 -0
  8. data/examples/rfe.rb +48 -10
  9. data/examples/rfe_renderer.rb +4 -4
  10. data/examples/rvimsplit.rb +376 -0
  11. data/examples/sqlc.rb +97 -106
  12. data/examples/sqlm.rb +446 -0
  13. data/examples/test1.rb +4 -4
  14. data/examples/test2.rb +12 -12
  15. data/examples/testchars.rb +140 -0
  16. data/examples/testkeypress.rb +9 -4
  17. data/examples/testmulticomp.rb +72 -0
  18. data/examples/testscroller.rb +136 -0
  19. data/examples/testscrolllb.rb +86 -0
  20. data/examples/testscrollp.rb +87 -0
  21. data/examples/testscrollta.rb +80 -0
  22. data/examples/testscrolltable.rb +166 -0
  23. data/examples/testsplit.rb +87 -0
  24. data/examples/testsplit2.rb +123 -0
  25. data/examples/testsplit3.rb +215 -0
  26. data/examples/testsplit3_1.rb +244 -0
  27. data/examples/testsplit3a.rb +215 -0
  28. data/examples/testsplit3b.rb +237 -0
  29. data/examples/testsplitta.rb +148 -0
  30. data/examples/testsplittv.rb +142 -0
  31. data/examples/testsplittvv.rb +144 -0
  32. data/examples/testtable.rb +1 -1
  33. data/examples/testtabp.rb +3 -2
  34. data/examples/testtestw.rb +69 -0
  35. data/examples/testtodo.rb +5 -3
  36. data/examples/testtpane.rb +203 -0
  37. data/examples/testtpane2.rb +145 -0
  38. data/examples/testtpanetable.rb +199 -0
  39. data/examples/viewtodo.rb +5 -3
  40. data/lib/rbcurse.rb +1 -1
  41. data/lib/rbcurse/celleditor.rb +2 -2
  42. data/lib/rbcurse/colormap.rb +5 -5
  43. data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
  44. data/lib/rbcurse/io.rb +663 -0
  45. data/lib/rbcurse/listeditable.rb +306 -0
  46. data/lib/rbcurse/listkeys.rb +15 -15
  47. data/lib/rbcurse/listscrollable.rb +168 -27
  48. data/lib/rbcurse/mapper.rb +35 -13
  49. data/lib/rbcurse/rchangeevent.rb +28 -0
  50. data/lib/rbcurse/rform.rb +845 -0
  51. data/lib/rbcurse/rlistbox.rb +144 -34
  52. data/lib/rbcurse/rmessagebox.rb +10 -5
  53. data/lib/rbcurse/rmulticontainer.rb +325 -0
  54. data/lib/rbcurse/rmultitextview.rb +306 -0
  55. data/lib/rbcurse/rscrollform.rb +369 -0
  56. data/lib/rbcurse/rscrollpane.rb +511 -0
  57. data/lib/rbcurse/rsplitpane.rb +820 -0
  58. data/lib/rbcurse/rtabbedpane.rb +737 -109
  59. data/lib/rbcurse/rtabbedwindow.rb +326 -0
  60. data/lib/rbcurse/rtable.rb +220 -64
  61. data/lib/rbcurse/rtextarea.rb +340 -181
  62. data/lib/rbcurse/rtextview.rb +237 -101
  63. data/lib/rbcurse/rviewport.rb +203 -0
  64. data/lib/rbcurse/rwidget.rb +919 -95
  65. data/lib/rbcurse/scrollable.rb +7 -7
  66. data/lib/rbcurse/selectable.rb +4 -4
  67. data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
  68. data/lib/rbcurse/undomanager.rb +181 -0
  69. data/lib/rbcurse/vieditable.rb +100 -0
  70. data/lib/ver/window.rb +471 -21
  71. metadata +66 -22
  72. data/README.txt +0 -312
  73. data/examples/testd.db +0 -0
  74. data/examples/todocsv.csv +0 -28
@@ -102,8 +102,6 @@ module RubyCurses
102
102
  def delete obj
103
103
  off0 = @list.index obj
104
104
  return nil if off0.nil?
105
- # 2009-11-04 11:33 next line corrected to delete_at
106
- #ret=@list.delete off0
107
105
  ret=@list.delete_at off0
108
106
  lde = ListDataEvent.new(off0, off0, self, :INTERVAL_REMOVED)
109
107
  fire_handler :LIST_DATA_EVENT, lde
@@ -207,7 +205,7 @@ module RubyCurses
207
205
  instance_eval &block if block_given?
208
206
  @list_config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
209
207
  @height ||= [@max_visible_items || 10, @list.length].min
210
- #$log.debug " POPUP XXX #{@max_visible_items} ll:#{@list.length} h:#{@height}"
208
+ $log.debug " POPUP XXX #{@max_visible_items} ll:#{@list.length} h:#{@height}"
211
209
  # get widgets absolute coords
212
210
  if !@relative_to.nil?
213
211
  layout = @relative_to.form.window.layout
@@ -232,15 +230,9 @@ module RubyCurses
232
230
  @window = VER::Window.new(@layout)
233
231
  @form = RubyCurses::Form.new @window
234
232
  @window.bkgd(Ncurses.COLOR_PAIR($reversecolor));
235
- #@window.attron(Ncurses.COLOR_PAIR($reversecolor));
236
- #@window.wclear
237
- #@window.attroff(Ncurses.COLOR_PAIR($reversecolor));
238
233
  @window.wrefresh
239
234
  @panel = @window.panel # useless line ?
240
235
  Ncurses::Panel.update_panels
241
- # @message_row = @message_col = 2
242
- # print_borders
243
- # print_title
244
236
  print_input # creates the listbox
245
237
  @form.repaint
246
238
  @window.wrefresh
@@ -322,8 +314,10 @@ module RubyCurses
322
314
  def print_input
323
315
  r = c = 0
324
316
  width = @layout[:width]
317
+ #$log.debug " print_input POPUP ht:#{@height} lh:#{@layout[:height]} "
325
318
  height = @layout[:height]
326
- height = @height
319
+ #height = @height # 2010-01-06 12:52 why was this overriding previous line. its one less than layout
320
+ # i am now using layout height since it gives a closer size to whats asked for.
327
321
  parent = @relative_to
328
322
  defaultvalue = @default_value || ""
329
323
  list = @list
@@ -345,7 +339,6 @@ module RubyCurses
345
339
  default_values default_values
346
340
  is_popup true
347
341
  #add_observer parent
348
-
349
342
  end
350
343
  end
351
344
  # may need to be upgraded to new one XXX FIXME
@@ -410,6 +403,7 @@ module RubyCurses
410
403
  dsl_accessor :KEY_NEXT_SELECTION
411
404
  dsl_accessor :KEY_PREV_SELECTION
412
405
  dsl_accessor :valign # 2009-01-17 18:32
406
+ attr_accessor :one_key_selection # will pressing a single key select or not
413
407
 
414
408
  def initialize form, config={}, &block
415
409
  @focusable = true
@@ -425,8 +419,15 @@ module RubyCurses
425
419
  @row_offset = @col_offset = 1
426
420
  @content_rows = @list.length
427
421
  @selection_mode ||= 'multiple'
428
- @win = @form.window
429
- print_borders unless @win.nil? # in messagebox we don;t have window as yet!
422
+ @win = @graphic # 2010-01-04 12:36 BUFFERED replace form.window with graphic
423
+ # moving down to repaint so that scrollpane can set should_buffered
424
+ # added 2010-02-17 23:05 RFED16 so we don't need a form.
425
+ @win_left = 0
426
+ @win_top = 0
427
+ @multiplier = 0 # multiply motion commands
428
+
429
+ #x safe_create_buffer # 2010-01-04 12:36 BUFFERED moved here 2010-01-05 18:07
430
+ #x print_borders unless @win.nil? # in messagebox we don;t have window as yet!
430
431
  # next 2 lines carry a redundancy
431
432
  select_default_values
432
433
  # when the combo box has a certain row in focus, the popup should have the same row in focus
@@ -449,6 +450,16 @@ module RubyCurses
449
450
  @left_margin ||= @row_selected_symbol.length
450
451
  end
451
452
  @left_margin ||= 0
453
+ @one_key_selection ||= true
454
+ bind_key(?f){ ask_selection_for_char() }
455
+ bind_key(?\M-v){ @one_key_selection = false }
456
+ bind_key(?j){ next_row() }
457
+ bind_key(?k){ previous_row() }
458
+ bind_key(?G){ goto_bottom() }
459
+ bind_key([?g,?g]){ goto_top() }
460
+ bind_key(?/){ ask_search() }
461
+ bind_key(?n){ find_more() }
462
+
452
463
  end
453
464
  def install_bindings
454
465
 
@@ -470,7 +481,8 @@ module RubyCurses
470
481
  end
471
482
  # added 2009-01-07 13:05 so new scrollable can use
472
483
  def scrollatrow
473
- @height - 2
484
+ #@height - 2
485
+ @height - 3 # 2010-01-04 15:30 BUFFERED HEIGHT
474
486
  end
475
487
  def list alist=nil
476
488
  return @list if alist.nil?
@@ -505,16 +517,22 @@ module RubyCurses
505
517
  end
506
518
  def print_borders
507
519
  width = @width
508
- height = @height
509
- window = @form.window
520
+ height = @height-1 # 2010-01-04 15:30 BUFFERED HEIGHT
521
+ window = @graphic # 2010-01-04 12:37 BUFFERED
510
522
  startcol = @col
511
523
  startrow = @row
512
524
  @color_pair = get_color($datacolor)
525
+ #$log.debug "rlistb: window.print_border #{startrow}, #{startcol} , #{height} , #{width} , @color_pair, @attr "
513
526
  window.print_border startrow, startcol, height, width, @color_pair, @attr
514
527
  print_title
515
528
  end
516
529
  def print_title
517
- printstring(@form.window, @row, @col+(@width-@title.length)/2, @title, @color_pair, @title_attrib) unless @title.nil?
530
+ #printstring(@graphic, @row, @col+(@width-@title.length)/2, @title, @color_pair, @title_attrib) unless @title.nil?
531
+ # 2010-01-04 15:53 BUFFERED
532
+ # I notice that the old version would print a title that was longer than width,
533
+ #+ but the new version won't print anything if it exceeds width.
534
+ # TODO check title.length and truncate if exceeds width
535
+ @graphic.printstring( @row, @col+(@width-@title.length)/2, @title, @color_pair, @title_attrib) unless @title.nil?
518
536
  end
519
537
  ### START FOR scrollable ###
520
538
  def get_content
@@ -522,7 +540,7 @@ module RubyCurses
522
540
  @list_variable && @list_variable.value || @list
523
541
  end
524
542
  def get_window
525
- @form.window
543
+ @graphic # 2010-01-04 12:37 BUFFERED
526
544
  end
527
545
  ### END FOR scrollable ###
528
546
  # override widgets text
@@ -542,18 +560,18 @@ module RubyCurses
542
560
  previous_row
543
561
  when KEY_DOWN # show previous value
544
562
  next_row
545
- when @KEY_ROW_SELECTOR # 32:
563
+ when @KEY_ROW_SELECTOR # 32
546
564
  return if is_popup and @selection_mode == 'single' # not allowing select this way since there will be a difference
547
565
  toggle_row_selection @current_index #, @current_index
548
566
  @repaint_required = true
549
- when @KEY_SCROLL_FORWARD # ?\C-n:
567
+ when @KEY_SCROLL_FORWARD # ?\C-n
550
568
  scroll_forward
551
- when @KEY_SCROLL_BACKWARD # ?\C-p:
569
+ when @KEY_SCROLL_BACKWARD # ?\C-p
552
570
  scroll_backward
553
- when @KEY_GOTO_TOP # 48, ?\C-[:
571
+ when @KEY_GOTO_TOP # 48, ?\C-[
554
572
  # please note that C-[ gives 27, same as esc so will respond after ages
555
573
  goto_top
556
- when @KEY_GOTO_BOTTOM # ?\C-]:
574
+ when @KEY_GOTO_BOTTOM # ?\C-]
557
575
  goto_bottom
558
576
  when @KEY_NEXT_SELECTION # ?'
559
577
  $log.debug "insdie next selection"
@@ -568,9 +586,10 @@ module RubyCurses
568
586
  when @KEY_CLEAR_SELECTION
569
587
  clear_selection #if @select_mode == 'multiple'
570
588
  @repaint_required = true
571
- when 27, ?\C-c:
589
+ when 27, ?\C-c.getbyte(0)
572
590
  editing_canceled @current_index if @cell_editing_allowed
573
591
  cancel_block # block
592
+ @multiplier = 0
574
593
  when @KEY_ASK_FIND_FORWARD
575
594
  # ask_search_forward
576
595
  when @KEY_ASK_FIND_BACKWARD
@@ -585,6 +604,13 @@ module RubyCurses
585
604
  find_more
586
605
  when @KEY_BLOCK_SELECTOR
587
606
  mark_block #selection
607
+ when ?\C-u.getbyte(0)
608
+ # multiplier. Series is 4 16 64
609
+ @multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
610
+ return 0
611
+ when ?\C-c.getbyte(0)
612
+ @multiplier = 0
613
+ return 0
588
614
  else
589
615
  # this has to be fixed, if compo does not handle key it has to continue into next part FIXME
590
616
  ret = :UNHANDLED # changed on 2009-01-27 13:14 not going into unhandled, tab not released
@@ -599,15 +625,37 @@ module RubyCurses
599
625
  end
600
626
  end
601
627
  if ret == :UNHANDLED
602
- case ch
603
- when ?A..?Z, ?a..?z
604
- ret = set_selection_for_char ch.chr
628
+ if @one_key_selection
629
+ case ch
630
+ when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0), ?0.getbyte(0)..?9.getbyte(0)
631
+ # simple motion, key press defines motion
632
+ ret = set_selection_for_char ch.chr
633
+ else
634
+ ret = process_key ch, self
635
+ @multiplier = 0
636
+ return :UNHANDLED if ret == :UNHANDLED
637
+ end
605
638
  else
639
+ # no motion on single key, we can freak out like in vim, pref f <char> for set_selection
640
+ case ch
641
+ when ?0.getbyte(0)..?9.getbyte(0)
642
+ @multiplier *= 10 ; @multiplier += (ch-48)
643
+ return 0
644
+ end
606
645
  ret = process_key ch, self
646
+ @multiplier = 0
607
647
  return :UNHANDLED if ret == :UNHANDLED
608
648
  end
609
649
  end
610
650
  end
651
+ @multiplier = 0
652
+ end
653
+ def ask_selection_for_char
654
+ ch = @graphic.getch
655
+ if ch < 0 || ch > 255
656
+ return :UNHANDLED
657
+ end
658
+ ret = set_selection_for_char ch.chr
611
659
  end
612
660
  def ask_search_forward
613
661
  regex = get_string("Enter regex to search")
@@ -684,6 +732,12 @@ module RubyCurses
684
732
  # unfortunately 2009-01-11 19:47 combo boxes editable allows changing value
685
733
  editor.prepare_editor self, row, col, value
686
734
  editor.component.curpos = 0 # reset it after search, if user scrols down
735
+ #editor.component.graphic = @graphic # 2010-01-05 00:36 TRYING OUT BUFFERED
736
+ ## override is required if the listbox uses a buffer
737
+ if @should_create_buffer
738
+ $log.debug " overriding editors comp with GRAPHIC #{@graphic} "
739
+ editor.component.override_graphic(@graphic) # 2010-01-05 00:36 TRYING OUT BUFFERED
740
+ end
687
741
  set_form_col 0 #@left_margin
688
742
 
689
743
  # set original value so we can cancel
@@ -701,6 +755,7 @@ module RubyCurses
701
755
  if @cell_editing_allowed
702
756
  if !@cell_editor.nil?
703
757
  # $log.debug " cell editor (leave) setting value row: #{arow} val: #{@cell_editor.getvalue}"
758
+ $log.debug " cell editor #{@cell_editor.component.form.window} (leave) setting value row: #{arow} val: #{@cell_editor.getvalue}"
704
759
  @list[arow] = @cell_editor.getvalue #.dup 2009-01-10 21:42 boolean can't duplicate
705
760
  else
706
761
  $log.debug "CELL EDITOR WAS NIL, #{arow} "
@@ -744,7 +799,18 @@ module RubyCurses
744
799
  # processing. also, it pans the data horizontally giving the renderer
745
800
  # a section of it.
746
801
  def repaint
802
+ safe_create_buffer # 2010-01-04 12:36 BUFFERED moved here 2010-01-05 18:07
747
803
  return unless @repaint_required
804
+ # not sure where to put this, once for all or repeat 2010-02-17 23:07 RFED16
805
+ my_win = @form ? @form.window : @target_window
806
+ @graphic = my_win unless @graphic
807
+ #$log.warn "neither form not target window given!!! TV paint 368" unless my_win
808
+ raise " #{@name} neither form, nor target window given TV paint " unless my_win
809
+ raise " #{@name} NO GRAPHIC set as yet TV paint " unless @graphic
810
+ @win_left = my_win.left
811
+ @win_top = my_win.top
812
+
813
+ $log.debug " rlistbox repaint graphic #{@graphic} "
748
814
  print_borders if @to_print_borders == 1 # do this once only, unless everything changes
749
815
  rc = row_count
750
816
  maxlen = @maxlen ||= @width-2
@@ -783,20 +849,20 @@ module RubyCurses
783
849
  else
784
850
  selection_symbol = @row_unselected_symbol
785
851
  end
786
- @form.window.printstring r+hh, c, selection_symbol, acolor,@attr
852
+ @graphic.printstring r+hh, c, selection_symbol, acolor,@attr
787
853
  end
788
854
  #renderer = get_default_cell_renderer_for_class content.class.to_s
789
855
  renderer = cell_renderer()
790
856
  #renderer.show_selector @show_selector
791
857
  #renderer.row_selected_symbol @row_selected_symbol
792
858
  #renderer.left_margin @left_margin
793
- #renderer.repaint @form.window, r+hh, c+(colix*11), content, focussed, selected
859
+ #renderer.repaint @graphic, r+hh, c+(colix*11), content, focussed, selected
794
860
  ## added crow on 2009-02-06 23:03
795
861
  # since data is being truncated and renderer may need index
796
- renderer.repaint @form.window, r+hh, c+@left_margin, crow, content, focussed, selected
862
+ renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focussed, selected
797
863
  else
798
864
  # clear rows
799
- @form.window.printstring r+hh, c, " " * (@width-2), acolor,@attr
865
+ @graphic.printstring r+hh, c, " " * (@width-2), acolor,@attr
800
866
  end
801
867
  end
802
868
  if @cell_editing_allowed
@@ -804,6 +870,8 @@ module RubyCurses
804
870
  end
805
871
  @table_changed = false
806
872
  @repaint_required = false
873
+ @buffer_modified = true # required by form to call buffer_to_screen BUFFERED
874
+ buffer_to_window # RFED16 2010-02-17 23:16
807
875
  end
808
876
  def list_data_changed
809
877
  if row_count == 0 # added on 2009-02-02 17:13 so cursor not hanging on last row which could be empty
@@ -813,9 +881,27 @@ module RubyCurses
813
881
  end
814
882
  @repaint_required = true
815
883
  end
816
- def set_form_col col=0
817
- super col+@left_margin
818
- end
884
+ def set_form_col col1=0
885
+ # TODO BUFFERED use setrowcol @form.row, col
886
+ # TODO BUFFERED use cols_panned
887
+ @cols_panned ||= 0 # RFED16 2010-02-17 23:40
888
+ # editable listboxes will involve changing cursor and the form issue
889
+ ## added win_col on 2010-01-04 23:28 for embedded forms BUFFERED TRYING OUT
890
+ #win_col=@form.window.left
891
+ win_col = 0 # 2010-02-17 23:19 RFED16
892
+ #col = win_col + @orig_col + @col_offset + @curpos + @form.cols_panned
893
+ col2 = win_col + @col + @col_offset + col1 + @cols_panned + @left_margin
894
+ $log.debug " set_form_col in rlistbox #{@col}+ left_margin #{@left_margin} ( #{col2} ) "
895
+ #super col+@left_margin
896
+ #@form.setrowcol @form.row, col2 # added 2009-12-29 18:50 BUFFERED
897
+ setrowcol nil, col2 # 2010-02-17 23:19 RFED16
898
+ end
899
+ #def rowcol
900
+ ## $log.debug "rlistbox rowcol : #{@row+@row_offset+@winrow}, #{@col+@col_offset}"
901
+ #win_col=@form.window.left
902
+ #col2 = win_col + @col + @col_offset + @form.cols_panned + @left_margin
903
+ #return @row+@row_offset, col2
904
+ #end
819
905
  # experimental selection of multiple rows via block
820
906
  # specify a block start and then a block end
821
907
  # usage: bind mark_selection to a key. It works as a toggle.
@@ -851,7 +937,31 @@ module RubyCurses
851
937
  add_row_selection_interval(lower, higher)
852
938
  @repaint_required = true
853
939
  end
940
+ # 2010-02-18 11:40
941
+ # TRYING OUT - canceling editing if resized otherwise drawing errors can occur
942
+ # the earlier painted edited comp in yellow keeps showing until a key is pressed
854
943
 
944
+ def set_buffering params
945
+ super
946
+ ## Ensuring that changes to top get reflect in editing comp
947
+ #+ otherwise it raises an exception. Still the earlier cell_edit is being
948
+ #+ printed where it was , until a key is moved
949
+ # FIXME - do same for col
950
+ if @cell_editor
951
+ r,c = rowcol
952
+ if @cell_editor.component.row < @row_offset + @buffer_params[:screen_top]
953
+ @cell_editor.component.row = @row_offset + @buffer_params[:screen_top]
954
+ end
955
+ # TODO next block to be tested by placing a listbox in right split of vertical
956
+ if @cell_editor.component.col < @col_offset + @buffer_params[:screen_left]
957
+ @cell_editor.component.col = @col_offset + @buffer_params[:screen_left]
958
+ end
959
+ #editing_canceled @current_index if @cell_editing_allowed and @cell_editor
960
+ end
961
+ #set_form_row
962
+ @repaint_required = true
963
+ end
964
+
855
965
 
856
966
  # ADD HERE
857
967
  end # class listb
@@ -112,13 +112,13 @@ module RubyCurses
112
112
  when "ok_cancel" #, "input", "list", "field_list"
113
113
  make_buttons %w[&OK &Cancel]
114
114
  # experience 2009-02-22 12:52 trapping y and n - hopefully wont cause an edit problem
115
- @form.bind_key(?o){ press(?\M-o) }
116
- @form.bind_key(?c){ press(?\M-c) }
115
+ @form.bind_key(?o){ press(?\M-o) } # called method takes care of getbyte 1.9
116
+ @form.bind_key(?c){ press(?\M-c) } # called method takes care of getbyte 1.9
117
117
  when "yes_no"
118
118
  make_buttons %w[&Yes &No]
119
119
  # experience 2009-02-22 12:52 trapping y and n - hopefully wont cause an edit problem
120
- @form.bind_key(?y){ press(?\M-y) }
121
- @form.bind_key(?n){ press(?\M-n) }
120
+ @form.bind_key(?y){ press(?\M-y) } # called method takes care of getbyte 1.9
121
+ @form.bind_key(?n){ press(?\M-n) } # called method takes care of getbyte 1.9
122
122
  when "yes_no_cancel"
123
123
  make_buttons ["&Yes", "&No", "&Cancel"]
124
124
  when "custom"
@@ -176,10 +176,11 @@ module RubyCurses
176
176
  return @selected_index
177
177
  end
178
178
  def press ch
179
+ ch = ch.getbyte(0) if ch.class==String ## 1.9
179
180
  case ch
180
181
  when -1
181
182
  return
182
- when KEY_F1, 27, ?\C-q
183
+ when KEY_F1, 27, ?\C-q.getbyte(0)
183
184
  @selected_index = -1
184
185
  @stop = true
185
186
  return
@@ -238,6 +239,7 @@ module RubyCurses
238
239
  def print_message message=@message, row=nil
239
240
  @message_row = @message_col = 2
240
241
  display_length = @layout[:width]-8
242
+ $log.debug " print_message: dl:#{display_length} "
241
243
  # XXX this needs to go up and decide height of window
242
244
  if @message_height.nil?
243
245
  @message_height = (message.length/display_length)+1
@@ -258,10 +260,13 @@ module RubyCurses
258
260
  @message_col = (width-message.length)/2
259
261
  end
260
262
  @message_row = row
263
+ # added 2009-11-05 14:53 to fix erasure of border
264
+ display_length -= @message_col
261
265
  # FIXME : wont print if newline at end of message !!!
262
266
  #@window.printstring( row, @message_col , message, color=$reversecolor)
263
267
  # 2008-12-30 19:45 experimenting with label so we can get justify and wrapping.
264
268
  #@window.printstring( row, @message_col , message, color=$reversecolor)
269
+ $log.debug " print_message: row #{row}, col #{@message_col} "
265
270
  message_label = RubyCurses::Label.new @form, {'text' => message, "name"=>"message_label","row" => row, "col" => @message_col, "display_length" => display_length, "height" => @message_height, "attr"=>"reverse"}
266
271
 
267
272
  end
@@ -0,0 +1,325 @@
1
+ =begin
2
+ * Name: MultiContainer
3
+ * Description View (cycle) multiple components in one container using a key or menu
4
+ * Author: rkumar (arunachalesha)
5
+ * file created 2010-03-15 10:40
6
+ --------
7
+ * License:
8
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
9
+
10
+ =end
11
+ require 'rubygems'
12
+ require 'ncurses'
13
+ require 'logger'
14
+ require 'rbcurse'
15
+
16
+ include Ncurses
17
+ include RubyCurses
18
+ module RubyCurses
19
+ extend self
20
+
21
+ ##
22
+ # Extends TextView with ability to load more than one file or content
23
+ # and switch between files (buffers).
24
+ # NOTE: ideally, i should be able to dynamically add this functionality to either Textview
25
+ # or TextArea or even ListBox or Table someday. Should then be a Module rather than a class.
26
+ class MultiContainer < Widget
27
+ dsl_accessor :title
28
+ #include ListScrollable
29
+
30
+ def initialize form = nil, config={}, &block
31
+ @focusable = true
32
+ @row_offset = @col_offset = 1
33
+ super
34
+ @bmanager = BufferManager.new self
35
+ init_vars
36
+
37
+ end
38
+ def init_vars
39
+ super
40
+ bind_key(?\M-:, :buffer_menu)
41
+ # bind_key([?\C-x, ?f], :file_edit)
42
+ bind_key([?\C-x, ?k], :buffer_delete)
43
+ bind_key([?\C-x, ?\C-b], :buffers_list)
44
+ # easily cycle using p. n is used for next search.
45
+ #bind_key(?p, :buffer_previous)
46
+ @suppress_borders = false
47
+ @repaint_all = true
48
+ @name ||= "multicontainer"
49
+ end
50
+ ## returns current buffer
51
+ # @return [RBuffer] current buffer
52
+ def current_buffer
53
+ @bmanager.current
54
+ end
55
+ ##
56
+ # multi-container
57
+ def handle_key ch
58
+ $log.debug " MULTI handlekey #{ch}, #{@current_component} "
59
+ ret = :UNHANDLED
60
+ return :UNHANDLED unless @current_component
61
+ ret = @current_component.handle_key(ch)
62
+ $log.debug " MULTI = comp returned #{ret} "
63
+ if ret == :UNHANDLED
64
+ # check for bindings, these cannot override above keys since placed at end
65
+ begin
66
+ ret = process_key ch, self
67
+ $log.debug " MULTI = process_key returned #{ret} "
68
+ rescue => err
69
+ $error_message = err
70
+ @form.window.print_error_message
71
+ $log.error " Multicomponent process_key #{err} "
72
+ $log.debug(err.backtrace.join("\n"))
73
+ end
74
+ return :UNHANDLED if ret == :UNHANDLED
75
+ end
76
+ # check for any keys not handled and check our own ones
77
+ return ret #
78
+ end
79
+ def repaint
80
+ print_border if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
81
+ return unless @current_component
82
+ $log.debug " MULTI REPAINT "
83
+ ret = @current_component.repaint
84
+ end
85
+ def print_border
86
+ $log.debug " #{@name} print_borders, #{@graphic.name} "
87
+ color = $datacolor
88
+ @graphic.print_border_only @row, @col, @height-1, @width, color #, Ncurses::A_REVERSE
89
+ print_title
90
+ end
91
+ def print_title
92
+ $log.debug " print_title #{@row}, #{@col}, #{@width} "
93
+ @graphic.printstring( @row, @col+(@width-@title.length)/2, @title, $datacolor, @title_attrib) unless @title.nil?
94
+ end
95
+ # this is just a test of the simple "most" menu
96
+ # can use this for next, prev, first, last, new, delete, overwrite etc
97
+ def buffer_menu
98
+ menu = PromptMenu.new self
99
+ menu.add(menu.create_mitem( 'l', "list buffers", "list buffers ", :buffers_list ))
100
+ item = menu.create_mitem( 'b', "Buffer Options", "Buffer Options" )
101
+ menu1 = PromptMenu.new( self, "Buffer Options")
102
+ menu1.add(menu1.create_mitem( 'n', "Next", "Switched to next buffer", :buffer_next ))
103
+ menu1.add(menu1.create_mitem( 'p', "Prev", "Switched to previous buffer", :buffer_previous ))
104
+ menu1.add(menu1.create_mitem( 'f', "First", "Switched to first buffer", :buffer_first ))
105
+ menu1.add(menu1.create_mitem( 'l', "Last", "Switched to last buffer", :buffer_last ))
106
+ menu1.add(menu1.create_mitem( 'd', "Delete", "Deleted buffer", :buffer_delete ))
107
+ item.action = menu1
108
+ menu.add(item)
109
+ # how do i know what's available. the application or window should know where to place
110
+ menu.display @form.window, $error_message_row, $error_message_col, $datacolor #, menu
111
+ end
112
+
113
+ #%w[next previous first last].each do |pos|
114
+ #eval(
115
+ #"def _buffer_#{pos}
116
+ #@current_buffer = @bmanager.#{pos}
117
+ #set_current_buffer
118
+ #end"
119
+ #)
120
+ #end
121
+
122
+ def buffer_next
123
+ perror "No other buffer" and return if @bmanager.size < 2
124
+
125
+ @current_buffer = @bmanager.next
126
+ set_current_buffer
127
+ end
128
+ def buffer_previous
129
+ perror "No other buffer" and return if @bmanager.size < 2
130
+
131
+ @current_buffer = @bmanager.previous
132
+ $log.debug " buffer_prev got #{@current_buffer} "
133
+ set_current_buffer
134
+ end
135
+ def buffer_first
136
+ @current_buffer = @bmanager.first
137
+ $log.debug " buffer_first got #{@current_buffer} "
138
+ set_current_buffer
139
+ end
140
+ def buffer_last
141
+ @current_buffer = @bmanager.last
142
+ $log.debug " buffer_last got #{@current_buffer} "
143
+ set_current_buffer
144
+ end
145
+ def buffer_delete
146
+ if @bmanager.size > 1
147
+ @bmanager.delete_at
148
+ @current_buffer = @bmanager.previous
149
+ set_current_buffer
150
+ else
151
+ perror "Only one buffer. Cannot delete."
152
+ end
153
+ end
154
+
155
+ #%w[next previous first last].each do |pos|
156
+ #eval(
157
+ #"def _buffer_#{pos}
158
+ #@current_buffer = @bmanager.#{pos}
159
+ #set_current_buffer
160
+ #end"
161
+ #)
162
+ #end
163
+
164
+ def buffer_next
165
+ perror "No other buffer" and return if @bmanager.size < 2
166
+
167
+ @current_buffer = @bmanager.next
168
+ set_current_buffer
169
+ end
170
+ def buffer_previous
171
+ perror "No other buffer" and return if @bmanager.size < 2
172
+
173
+ @current_buffer = @bmanager.previous
174
+ $log.debug " buffer_prev got #{@current_buffer} "
175
+ set_current_buffer
176
+ end
177
+ def buffer_first
178
+ @current_buffer = @bmanager.first
179
+ $log.debug " buffer_first got #{@current_buffer} "
180
+ set_current_buffer
181
+ end
182
+ def buffer_last
183
+ @current_buffer = @bmanager.last
184
+ $log.debug " buffer_last got #{@current_buffer} "
185
+ set_current_buffer
186
+ end
187
+ def buffer_delete
188
+ if @bmanager.size > 1
189
+ @bmanager.delete_at
190
+ @current_buffer = @bmanager.previous
191
+ set_current_buffer
192
+ else
193
+ perror "Only one buffer. Cannot delete."
194
+ end
195
+ end
196
+ def buffer_at index
197
+ @current_buffer = @bmanager.element_at index
198
+ $log.debug " buffer_last got #{@current_buffer} "
199
+ set_current_buffer
200
+ end
201
+ ##
202
+ # Add a component with a title
203
+ # @param [Widget] component
204
+ # @param [String] title
205
+ def add component, title
206
+ component.row = @row+@row_offset+1
207
+ component.col = @col+@col_offset+1
208
+ component.width = @width-2
209
+ component.height = @height-2
210
+ component.form = @form
211
+ component.override_graphic(@graphic)
212
+ @current_buffer = @bmanager.add component, title
213
+ set_current_buffer
214
+ $log.debug " ADD got cb : #{@current_buffer} "
215
+ end
216
+ def set_current_buffer
217
+ @current_component = @current_buffer.component
218
+ @current_title = @current_buffer.title
219
+ @current_component.repaint_all true
220
+ end
221
+ def perror errmess=$error_message
222
+ @form.window.print_error_message errmess
223
+ end
224
+ def buffers_list
225
+ $log.debug " TODO buffers_list: #{@bmanager.size} "
226
+ menu = PromptMenu.new self
227
+ @bmanager.each_with_index{ |b, ix|
228
+ aproc = Proc.new { buffer_at(ix) }
229
+ name = b.title
230
+ num = ix + 1
231
+ menu.add(menu.create_mitem( num.to_s, name, "Switched to buffer #{ix}", aproc ))
232
+ }
233
+ menu.display @form.window, $error_message_row, $error_message_col, $datacolor
234
+ end
235
+ # required otherwise some components may not get correct cursor position on entry
236
+ # e.g. table
237
+ def on_enter
238
+ set_form_row
239
+ end
240
+ def set_form_row
241
+ if !@current_component.nil?
242
+ $log.debug " #{@name} set_form_row calling sfr for #{@current_component.name} "
243
+ @current_component.set_form_row
244
+ @current_component.set_form_col
245
+ end
246
+ end
247
+ end # class multitextview
248
+ ##
249
+ # Handles multiple buffers, navigation, maintenance etc
250
+ # Instantiated at startup of MultiTextView
251
+ #
252
+ class BufferManager
253
+ include Enumerable
254
+ def initialize source
255
+ @source = source
256
+ @buffers = [] # contains RBuffer
257
+ @counter = 0
258
+ # for each buffer i need to store data, current_index (row), curpos (col offset) and title (filename).
259
+ end
260
+ def element_at index
261
+ @buffers[index]
262
+ end
263
+ def each
264
+ @buffers.each {|k| yield(k)}
265
+ end
266
+
267
+ ##
268
+ # @return [RBuffer] current buffer/file
269
+ ##
270
+ def current
271
+ @buffers[@counter]
272
+ end
273
+ ##
274
+ # Would have liked to just return next buffer and not get lost in details of caller
275
+ #
276
+ # @return [RBuffer] next buffer/file
277
+ ##
278
+ def next
279
+ @counter += 1
280
+ @counter = 0 if @counter >= @buffers.size
281
+ @buffers[@counter]
282
+ end
283
+ ##
284
+ # @return [RBuffer] previous buffer/file
285
+ ##
286
+ def previous
287
+ $log.debug " previous bs: #{@buffers.size}, #{@counter} "
288
+ @counter -= 1
289
+ return last() if @counter < 0
290
+ $log.debug " previous ctr #{@counter} "
291
+ @buffers[@counter]
292
+ end
293
+ def first
294
+ @counter = 0
295
+ @buffers[@counter]
296
+ end
297
+ def last
298
+ @counter = @buffers.size - 1
299
+ @buffers[@counter]
300
+ end
301
+ ##
302
+ def delete_at index=@counter
303
+ @buffers.delete_at index
304
+ end
305
+ def delete_by_name name
306
+ @buffers.delete_if {|b| b.filename == name }
307
+ end
308
+ def insert component, position, title=nil
309
+ anew = RComponents.new(component, title)
310
+ @buffers.insert position, anew
311
+ @counter = position
312
+ return anew
313
+ end
314
+ def add component, title=nil
315
+ $log.debug " ADD H: #{component.height} C: #{component.width} "
316
+ insert component, @buffers.size, title
317
+ end
318
+ def size
319
+ @buffers.size
320
+ end
321
+ alias :count :size
322
+ end
323
+ RComponents = Struct.new(:component, :title)
324
+
325
+ end # modul