rbcurse 1.4.0 → 1.4.1.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/NOTES +68 -0
  2. data/README.markdown +73 -330
  3. data/TODO2.txt +2 -2
  4. data/VERSION +1 -1
  5. data/examples/abasiclist.rb +8 -2
  6. data/examples/alpmenu.rb +1 -1
  7. data/examples/app.rb +1 -24
  8. data/examples/appdirtree.rb +1 -1
  9. data/examples/appemail.rb +8 -14
  10. data/examples/appemaillb.rb +2 -2
  11. data/examples/appgcompose.rb +7 -5
  12. data/examples/common/file.rb +40 -0
  13. data/examples/{rmail.rb → common/rmail.rb} +0 -0
  14. data/examples/data/README.markdown +9 -0
  15. data/examples/data/brew.txt +38 -0
  16. data/examples/data/color.2 +37 -0
  17. data/examples/data/gemlist.txt +60 -0
  18. data/examples/data/lotr.txt +12 -0
  19. data/examples/data/ports.txt +136 -0
  20. data/examples/data/tasks.txt +27 -0
  21. data/examples/{todocsv.csv → data/todocsv.csv} +0 -0
  22. data/examples/data/unix1.txt +21 -0
  23. data/examples/data/unix2.txt +11 -0
  24. data/examples/dbdemo.rb +49 -14
  25. data/examples/{appgmail.rb → deprecated/appgmail.rb} +1 -1
  26. data/examples/{splitp.rb → deprecated/splitp.rb} +0 -0
  27. data/examples/{testscrolllb.rb → deprecated/testscrolllb.rb} +0 -0
  28. data/examples/{testscrollp.rb → deprecated/testscrollp.rb} +0 -0
  29. data/examples/{testscrollta.rb → deprecated/testscrollta.rb} +0 -0
  30. data/examples/{testscrolltable.rb → deprecated/testscrolltable.rb} +0 -0
  31. data/examples/{testsplit.rb → deprecated/testsplit.rb} +0 -0
  32. data/examples/{testsplit2.rb → deprecated/testsplit2.rb} +0 -0
  33. data/examples/{testsplit3.rb → deprecated/testsplit3.rb} +0 -0
  34. data/examples/{testsplit3_1.rb → deprecated/testsplit3_1.rb} +0 -0
  35. data/examples/{testsplit3a.rb → deprecated/testsplit3a.rb} +0 -0
  36. data/examples/{testsplit3b.rb → deprecated/testsplit3b.rb} +0 -0
  37. data/examples/{testsplitta.rb → deprecated/testsplitta.rb} +0 -0
  38. data/examples/{testsplittv.rb → deprecated/testsplittv.rb} +0 -0
  39. data/examples/{testsplittvv.rb → deprecated/testsplittvv.rb} +0 -0
  40. data/examples/{testtpane.rb → deprecated/testtpane.rb} +0 -0
  41. data/examples/{testtpane2.rb → deprecated/testtpane2.rb} +0 -0
  42. data/examples/{testtpanetable.rb → deprecated/testtpanetable.rb} +0 -0
  43. data/examples/dirtree.rb +17 -7
  44. data/examples/experimental/resultsetdemo.rb +280 -0
  45. data/examples/experimental/testmform.rb +35 -0
  46. data/examples/{testscroller.rb → experimental/testscroller.rb} +1 -19
  47. data/examples/experimental/teststackflow.rb +111 -0
  48. data/examples/menu1.rb +1 -0
  49. data/examples/multispl.rb +4 -4
  50. data/examples/newmessagebox.rb +130 -0
  51. data/examples/newtabbedwindow.rb +100 -0
  52. data/examples/newtesttabp.rb +0 -3
  53. data/examples/qdfilechooser.rb +0 -3
  54. data/examples/rfe.rb +134 -18
  55. data/examples/rfe_renderer.rb +48 -2
  56. data/examples/sqlc.rb +2 -1
  57. data/examples/sqlm.rb +0 -2
  58. data/examples/table1.rb +1 -7
  59. data/examples/term2.rb +4 -1
  60. data/examples/test1.rb +0 -5
  61. data/examples/test2.rb +42 -31
  62. data/examples/testapp2.rb +8 -1
  63. data/examples/testchars.rb +0 -4
  64. data/examples/testcombo.rb +5 -9
  65. data/examples/testkeypress.rb +0 -3
  66. data/examples/testmenu.rb +0 -4
  67. data/examples/testmulticomp.rb +3 -5
  68. data/examples/testmulticontainer.rb +94 -0
  69. data/examples/testtable.rb +0 -5
  70. data/examples/testtabp.rb +16 -18
  71. data/examples/testtodo.rb +1 -5
  72. data/examples/testwsshortcuts.rb +64 -0
  73. data/examples/testwsshortcuts2.rb +126 -0
  74. data/examples/viewtodo.rb +1 -4
  75. data/lib/rbcurse.rb +1 -1
  76. data/lib/rbcurse/app.rb +92 -69
  77. data/lib/rbcurse/applicationheader.rb +46 -6
  78. data/lib/rbcurse/celleditor.rb +1 -9
  79. data/lib/rbcurse/comboboxcellrenderer.rb +0 -4
  80. data/lib/rbcurse/common/ansiparser.rb +117 -0
  81. data/{examples → lib/rbcurse/common}/appmethods.rb +25 -0
  82. data/lib/rbcurse/common/basestack.rb +407 -0
  83. data/lib/rbcurse/common/bordertitle.rb +41 -0
  84. data/lib/rbcurse/common/chunk.rb +177 -0
  85. data/lib/rbcurse/common/colorparser.rb +71 -0
  86. data/lib/rbcurse/common/keydefs.rb +30 -0
  87. data/lib/rbcurse/common/widgetshortcuts.rb +302 -0
  88. data/lib/rbcurse/deprecated/README.markdown +12 -0
  89. data/lib/rbcurse/{rscrollpane.rb → deprecated/rscrollpane.rb} +0 -0
  90. data/lib/rbcurse/{rsplitpane.rb → deprecated/rsplitpane.rb} +0 -0
  91. data/lib/rbcurse/{rsplitpane2.rb → deprecated/rsplitpane2.rb} +0 -0
  92. data/lib/rbcurse/{rviewport.rb → deprecated/rviewport.rb} +0 -0
  93. data/lib/rbcurse/experimental/README.markdown +14 -0
  94. data/lib/rbcurse/experimental/resultsettextview.rb +585 -0
  95. data/lib/rbcurse/experimental/stackflow.rb +478 -0
  96. data/lib/rbcurse/extras/bottomline.rb +85 -16
  97. data/lib/rbcurse/extras/box.rb +58 -0
  98. data/lib/rbcurse/extras/directorylist.rb +1 -1
  99. data/lib/rbcurse/extras/horizlist.rb +203 -0
  100. data/lib/rbcurse/extras/listselectable.rb +8 -0
  101. data/lib/rbcurse/extras/multiform.rb +330 -0
  102. data/lib/rbcurse/extras/multilinelabel.rb +142 -0
  103. data/lib/rbcurse/extras/newmessagebox.rb +328 -0
  104. data/lib/rbcurse/extras/newtabbedpane.rb +612 -0
  105. data/lib/rbcurse/extras/newtabbedwindow.rb +68 -0
  106. data/lib/rbcurse/extras/padreader.rb +189 -0
  107. data/lib/rbcurse/extras/rcomboedit.rb +256 -0
  108. data/lib/rbcurse/extras/resultsetbrowser.rb +281 -0
  109. data/lib/rbcurse/extras/statusline.rb +44 -6
  110. data/lib/rbcurse/extras/tabularwidget.rb +141 -104
  111. data/lib/rbcurse/extras/textpad.rb +516 -0
  112. data/lib/rbcurse/extras/viewer.rb +2 -0
  113. data/lib/rbcurse/io.rb +120 -3
  114. data/lib/rbcurse/listcellrenderer.rb +2 -1
  115. data/lib/rbcurse/listkeys.rb +1 -1
  116. data/lib/rbcurse/listscrollable.rb +72 -7
  117. data/lib/rbcurse/rbasiclistbox.rb +64 -12
  118. data/lib/rbcurse/rchangeevent.rb +0 -1
  119. data/lib/rbcurse/rcombo.rb +54 -59
  120. data/lib/rbcurse/rcommandwindow.rb +46 -10
  121. data/lib/rbcurse/rcontainer.rb +415 -0
  122. data/lib/rbcurse/rdialogs.rb +242 -165
  123. data/lib/rbcurse/rinputdataevent.rb +0 -1
  124. data/lib/rbcurse/rlistbox.rb +19 -9
  125. data/lib/rbcurse/rmessagebox.rb +1 -5
  126. data/lib/rbcurse/rmulticontainer.rb +64 -61
  127. data/lib/rbcurse/rmultitextview.rb +0 -2
  128. data/lib/rbcurse/rpopupmenu.rb +0 -2
  129. data/lib/rbcurse/rscrollform.rb +61 -12
  130. data/lib/rbcurse/rtabbedpane.rb +89 -73
  131. data/lib/rbcurse/rtabbedwindow.rb +53 -211
  132. data/lib/rbcurse/rtable.rb +0 -2
  133. data/lib/rbcurse/rtextarea.rb +14 -14
  134. data/lib/rbcurse/rtextview.rb +165 -50
  135. data/lib/rbcurse/rvimsplit.rb +15 -12
  136. data/lib/rbcurse/rwidget.rb +404 -150
  137. data/lib/rbcurse/table/tablecellrenderer.rb +1 -4
  138. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -3
  139. data/lib/ver/ncurses.rb +1 -9
  140. data/lib/ver/rpad.rb +375 -0
  141. data/lib/ver/window.rb +262 -440
  142. metadata +73 -31
@@ -18,7 +18,6 @@
18
18
  # i am tired of maintaining this everywhere.
19
19
  require 'rbcurse'
20
20
  require 'rbcurse/rlistbox'
21
- require 'rbcurse/rtextview'
22
21
  require 'rbcurse/extras/divider'
23
22
  require 'rbcurse/extras/focusmanager'
24
23
 
@@ -184,6 +183,7 @@ module RubyCurses
184
183
  lb = Listbox.new nil, :list => c , :name => "list#{@components.size}"
185
184
  c = lb
186
185
  when String
186
+ require 'rbcurse/rtextview'
187
187
  lb = TextView.new nil, :name => "text#{@components.size}"
188
188
  lb.set_content c
189
189
  c = lb
@@ -273,10 +273,7 @@ module RubyCurses
273
273
  def repaint
274
274
  my_win = @form ? @form.window : @target_window
275
275
  @graphic = my_win unless @graphic
276
- raise " #{@name} neither form, nor target window given TV paint " unless my_win
277
- raise " #{@name} NO GRAPHIC set as yet TV paint " unless @graphic
278
- @win_left = my_win.left
279
- @win_top = my_win.top
276
+ raise " #{@name} NO GRAPHIC set as yet VIMSPLIT paint " unless @graphic
280
277
 
281
278
  #return unless @repaint_required
282
279
  @recalculate_splits = true if @rc.nil?
@@ -292,31 +289,37 @@ module RubyCurses
292
289
 
293
290
 
294
291
  @graphic.attron(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
295
- @gbwid ||= 0
292
+
293
+ ## The following calculations are only calcing the 2 split areas
294
+ ## and divider locations based on V or H and weight.
295
+
296
+ @gbwid ||= 0 # grabbar width
296
297
  roffset = 1
297
298
  loffset = 2
298
299
  if @suppress_borders
299
300
  loffset = roffset = 0
300
301
  end
302
+ # vertical split
301
303
  if v?
302
304
  @rc ||= (@width * @weight).to_i
303
- rc = @rc
305
+ rc = @rc # divider location
304
306
  $log.debug "SPLP #{@name} prtingign split vline divider 1, rc: #{rc}, h:#{@height} - 2 "
305
- unless @vb
307
+ unless @vb # if grabbar not created
306
308
  @gbwid = 1
307
309
  _create_divider
308
- else
310
+ else # created, so set it
309
311
  @vb.row @row+roffset
310
312
  @vb.col rc+@col
311
313
  #@vb.repaint
312
314
  end
313
315
  #@graphic.mvvline(@row+1, rc+@col, 0, @height-2)
314
316
  # TODO don;t keep recreating, if present, reset values
317
+ ## calculate cordinated of both split areas/boxes
315
318
  @c1rc = Coord.new(@row,@col, @height -0, rc-@gbwid)
316
319
  @c2rc = Coord.new(@row,rc+@col+@gbwid,@height-0, @width - rc-@gbwid)
317
- else
320
+ else # horizontal split
318
321
  @rc ||= (@height * @weight).to_i
319
- rc = @rc
322
+ rc = @rc # dividers row col location
320
323
  $log.debug "SPLP #{@name} prtingign split hline divider rc: #{rc} , 1 , w:#{@width} - 2"
321
324
  unless @vb
322
325
  @gbwid = 1
@@ -334,7 +337,7 @@ module RubyCurses
334
337
  @c1rc = Coord.new(@row+a,@col+a, rc-a, @width-@internal_width)
335
338
  @c2rc = Coord.new(@row+rc+a,@col+a, @height-rc-2, @width - @internal_width)
336
339
  else
337
- # flush
340
+ # flush against border
338
341
  #@c1rc = Coord.new(@row,@col, @height -0, rc-@gbwid)
339
342
  #@c2rc = Coord.new(@row,rc+@col+@gbwid,@height-0, @width - rc-@gbwid)
340
343
  a = 0
@@ -1,6 +1,5 @@
1
1
  =begin
2
- * Name: rwidget: base class and then popup and other derived widgets
3
- * $Id$
2
+ * Name: rwidget: base class and then basic widgets like field, button and label
4
3
  * Description
5
4
  Some simple light widgets for creating ncurses applications. No reliance on ncurses
6
5
  forms and fields.
@@ -10,6 +9,7 @@
10
9
  * Author: rkumar (arunachalesha)
11
10
  * Date: 2008-11-19 12:49
12
11
  * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
12
+ * Last update: 2011-11-08 - 16:55
13
13
 
14
14
  == CHANGES
15
15
  * 2011-10-2 Added PropertyVetoException to rollback changes to property
@@ -24,28 +24,16 @@
24
24
 
25
25
  =end
26
26
  require 'logger'
27
- #require 'rbcurse/mapper'
28
27
  require 'rbcurse/colormap'
29
28
  require 'rbcurse/orderedhash'
30
29
  require 'rbcurse/rinputdataevent' # for FIELD 2010-09-11 12:31
31
30
  require 'rbcurse/io'
31
+ require 'rbcurse/common/keydefs'
32
32
 
33
- # some of these will get overriden by ncurses when we include
34
- KEY_TAB = 9
35
- KEY_F1 = FFI::NCurses::KEY_F1
36
- KEY_ENTER = 10 # FFI::NCurses::KEY_ENTER gives 343
37
- KEY_BTAB = 353 # nc gives same
38
- KEY_RETURN = 13 # Nc gives 343 for KEY_ENTER
39
- KEY_DELETE = 330
40
- KEY_BACKSPACE = KEY_BSPACE = 127 # Nc gives 263 for BACKSPACE
41
- KEY_CC = 3 # C-c
42
- KEY_LEFT = FFI::NCurses::KEY_LEFT
43
- KEY_RIGHT = FFI::NCurses::KEY_RIGHT
44
- KEY_UP = FFI::NCurses::KEY_UP
45
- KEY_DOWN = FFI::NCurses::KEY_DOWN
46
- C_LEFT = 18168
47
- C_RIGHT = 18167
48
- S_F9 = 17949126
33
+ BOLD = FFI::NCurses::A_BOLD
34
+ REVERSE = FFI::NCurses::A_REVERSE
35
+ UNDERLINE = FFI::NCurses::A_UNDERLINE
36
+ NORMAL = FFI::NCurses::A_NORMAL
49
37
 
50
38
  class Object
51
39
  # thanks to terminal-table for this method
@@ -116,11 +104,12 @@ class Module
116
104
  if oldvalue != newvalue
117
105
  # trying to reduce calls to fire, when object is being created
118
106
  begin
107
+ @property_changed = true
119
108
  fire_property_change("#{sym}", oldvalue, newvalue) if !oldvalue.nil?
120
109
  @#{sym} = tmp
121
110
  @config["#{sym}"]=@#{sym}
122
111
  rescue PropertyVetoException
123
- $log.warn "PropertyVetoException for #{sym}:" + oldvalue + "-> "+newvalue
112
+ $log.warn "PropertyVetoException for #{sym}:" + oldvalue.to_s + "-> "+ newvalue.to_s
124
113
  end
125
114
  end # if old
126
115
  self
@@ -177,6 +166,28 @@ module RubyCurses
177
166
  # e.g. a single call of foo() may set a var, a repeated call of foo() may append to var
178
167
  $inside_multiplier_action = true
179
168
 
169
+ # This has been put here since the API is not yet stable, and i
170
+ # don't want to have to change in many places. 2011-11-10
171
+ #
172
+ # Converts formatted text into chunkline objects.
173
+ #
174
+ # To print chunklines you may for each row:
175
+ # window.wmove row+height, col
176
+ # a = get_attrib @attrib
177
+ # window.show_colored_chunks content, color, a
178
+ #
179
+ # @param [color_parser] object or symbol :tmux, :ansi
180
+ # the color_parser implements parse_format, the symbols
181
+ # relate to default parsers provided.
182
+ # @param [String] string containing formatted text
183
+ def parse_formatted_text(color_parser, formatted_text)
184
+ require 'rbcurse/common/chunk'
185
+ cp = Chunks::ColorParser.new color_parser
186
+ l = []
187
+ formatted_text.each { |e| l << cp.convert_to_chunk(e) }
188
+ return l
189
+ end
190
+
180
191
  ##
181
192
  # wraps text given max length, puts newlines in it.
182
193
  # it does not take into account existing newlines
@@ -271,6 +282,73 @@ module RubyCurses
271
282
  acolor = ColorMap.get_color(color, bgcolor)
272
283
  return acolor
273
284
  end
285
+ #
286
+ # convert a string to integer attribute
287
+ # FIXME: what if user wishes to OR two attribs, this will give error
288
+ # @param [String] e.g. reverse bold normal underline
289
+ # if a Fixnum is passed, it is returned as is assuming to be
290
+ # an attrib
291
+ def get_attrib str
292
+ return FFI::NCurses::A_NORMAL unless str
293
+ # next line allows us to do a one time conversion and keep the value
294
+ # in the same variable
295
+ if str.is_a? Fixnum
296
+ if [
297
+ FFI::NCurses::A_BOLD,
298
+ FFI::NCurses::A_REVERSE,
299
+ FFI::NCurses::A_NORMAL,
300
+ FFI::NCurses::A_UNDERLINE,
301
+ FFI::NCurses::A_STANDOUT,
302
+ FFI::NCurses::A_DIM,
303
+ FFI::NCurses::A_BOLD | FFI::NCurses::A_REVERSE,
304
+ FFI::NCurses::A_BOLD | FFI::NCurses::A_UNDERLINE,
305
+ FFI::NCurses::A_REVERSE | FFI::NCurses::A_UNDERLINE,
306
+ FFI::NCurses::A_BLINK
307
+ ].include? str
308
+ return str
309
+ else
310
+ raise ArgumentError, "get_attrib got a wrong value: #{str} "
311
+ end
312
+ end
313
+
314
+
315
+ att = nil
316
+ str = str.downcase.to_sym if str.is_a? String
317
+ case str #.to_s.downcase
318
+ when :bold
319
+ att = FFI::NCurses::A_BOLD
320
+ when :reverse
321
+ att = FFI::NCurses::A_REVERSE
322
+ when :normal
323
+ att = FFI::NCurses::A_NORMAL
324
+ when :underline
325
+ att = FFI::NCurses::A_UNDERLINE
326
+ when :standout
327
+ att = FFI::NCurses::A_STANDOUT
328
+ when :bold_reverse
329
+ att = FFI::NCurses::A_BOLD | FFI::NCurses::A_REVERSE
330
+ when :bold_underline
331
+ att = FFI::NCurses::A_BOLD | FFI::NCurses::A_UNDERLINE
332
+ when :dim
333
+ att = FFI::NCurses::A_DIM
334
+ when :blink
335
+ att = FFI::NCurses::A_BLINK # unlikely to work
336
+ else
337
+ att = FFI::NCurses::A_NORMAL
338
+ end
339
+ return att
340
+ end
341
+
342
+ # returns last line of full screen, should it be current window ?
343
+ def last_line; FFI::NCurses.LINES-1; end
344
+
345
+ # Create a one line window typically at the bottom
346
+ # should we really put this here, too much clutter ?
347
+ def one_line_window at=last_line(), config={}, &blk
348
+ at ||= last_line()
349
+ at = FFI::NCurses.LINES-at if at < 0
350
+ VER::Window.new(1,0,at,0)
351
+ end
274
352
  ## repeats the given action based on how value of universal numerica argument
275
353
  ##+ set using the C-u key. Or in vim-mode using numeric keys
276
354
  def repeatm
@@ -320,6 +398,9 @@ module RubyCurses
320
398
  @key_args ||= {}
321
399
  @key_args[keycode] = args
322
400
  end
401
+ def bind_keys keycodes, *args, &blk
402
+ keycodes.each { |k| bind_key k, *args, &blk }
403
+ end
323
404
  # e.g. process_key ch, self
324
405
  # returns UNHANDLED if no block for it
325
406
  # after form handles basic keys, it gives unhandled key to current field, if current field returns
@@ -494,6 +575,7 @@ module RubyCurses
494
575
  end
495
576
  end # module config
496
577
 
578
+ # Adding widget shortcuts here for non-App cases 2011-10-12 . MOVE these to widget shortcuts
497
579
  #
498
580
  # prints a status line at bottom where mode's statuses et can be reflected
499
581
  def status_line config={}, &block
@@ -501,15 +583,33 @@ module RubyCurses
501
583
  sl = RubyCurses::StatusLine.new @form, config, &block
502
584
  end
503
585
 
586
+ # add a standard application header
587
+ # == Example
588
+ # header = app_header "rbcurse ", :text_center => "Browser Demo", :text_right =>"New Improved!",
589
+ # :color => :black, :bgcolor => :white, :attr => :bold
590
+ def app_header title, config={}, &block
591
+ require 'rbcurse/applicationheader'
592
+ header = ApplicationHeader.new @form, title, config, &block
593
+ end
594
+
595
+ # prints pine-like key labels
596
+ def dock labels, config={}, &block
597
+ require 'rbcurse/keylabelprinter'
598
+ klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
599
+ end
600
+
504
601
  ##
505
- # Basic widget class.
506
- # NOTE: I may soon remove the config hash. I don't use it and its just making things heavy.
507
- # Unless someone convinces me otherwise.
602
+ # Basic widget class superclass. Anything embedded in a form should
603
+ # extend this, if it wants to be repainted or wants focus. Otherwise.
604
+ # form will be unaware of it.
605
+
606
+
508
607
  class Widget
509
608
  include EventHandler
510
609
  include ConfigSetup
511
610
  include RubyCurses::Utils
512
611
  include Io # added 2010-03-06 13:05
612
+ # common interface for text related to a field, label, textview, button etc
513
613
  dsl_property :text
514
614
 
515
615
  # next 3 to be checked if used or not. Copied from TK.
@@ -517,11 +617,12 @@ module RubyCurses
517
617
  dsl_property :highlight_foreground, :highlight_background # color init_pair
518
618
  dsl_property :disabled_foreground, :disabled_background # color init_pair
519
619
 
520
- # FIXME is enabled used?
620
+ # FIXME is enabled used? is menu using it
521
621
  dsl_accessor :focusable, :enabled # boolean
522
622
  dsl_property :row, :col # location of object
523
623
  dsl_property :color, :bgcolor # normal foreground and background
524
- dsl_property :color_pair # instead of colors give just color_pair
624
+ # moved to a method which calculates color 2011-11-12
625
+ #dsl_property :color_pair # instead of colors give just color_pair
525
626
  dsl_property :attr # attribute bold, normal, reverse
526
627
  dsl_accessor :name # name to refr to or recall object by_name
527
628
  attr_accessor :id #, :zorder
@@ -538,6 +639,7 @@ module RubyCurses
538
639
  dsl_property :preferred_height # added 2009-10-28 13:40 for splitpanes and better resizing
539
640
  dsl_property :min_width # added 2009-10-28 13:40 for splitpanes and better resizing
540
641
  dsl_property :min_height # added 2009-10-28 13:40 for splitpanes and better resizing
642
+ # widget also has height and width as a method
541
643
 
542
644
  attr_accessor :_object_created # 2010-09-16 12:12 to prevent needless property change firing when object being set
543
645
 
@@ -563,7 +665,7 @@ module RubyCurses
563
665
  @col_offset ||= 0
564
666
  #@ext_row_offset = @ext_col_offset = 0 # 2010-02-07 20:18 # removed on 2011-09-29
565
667
  @state = :NORMAL
566
- @attr = nil
668
+ #@attr = nil # 2011-11-5 i could be removing what's been entered since super is called
567
669
 
568
670
  @handler = nil # we can avoid firing if nil
569
671
  @event_args = {}
@@ -584,9 +686,8 @@ module RubyCurses
584
686
  end
585
687
  # 2010-09-20 13:12 moved down, so it does not create problems with other who want to set their
586
688
  # own default
587
- @bgcolor ||= "black" # 0
588
- @color ||= "white" # $datacolor
589
- # @id = form.add_widget(self) if !form.nil? and form.respond_to? :add_widget
689
+ #@bgcolor ||= "black" # 0
690
+ #@color ||= "white" # $datacolor
590
691
  set_form(form) unless form.nil?
591
692
  end
592
693
  def init_vars
@@ -622,6 +723,7 @@ module RubyCurses
622
723
 
623
724
  ## got left out by mistake 2008-11-26 20:20
624
725
  def on_enter
726
+ @state = :HIGHLIGHTED # duplicating since often these are inside containers
625
727
  @focussed = true
626
728
  if @handler && @handler.has_key?(:ENTER)
627
729
  fire_handler :ENTER, self
@@ -629,6 +731,7 @@ module RubyCurses
629
731
  end
630
732
  ## got left out by mistake 2008-11-26 20:20
631
733
  def on_leave
734
+ @state = :NORMAL # duplicating since often these are inside containers
632
735
  @focussed = false
633
736
  if @handler && @handler.has_key?(:LEAVE)
634
737
  fire_handler :LEAVE, self
@@ -657,6 +760,8 @@ module RubyCurses
657
760
  # widget does not have display_length.
658
761
  def repaint
659
762
  r,c = rowcol
763
+ @bgcolor ||= $def_bg_color # moved down 2011-11-5
764
+ @color ||= $def_fg_color
660
765
  $log.debug("widget repaint : r:#{r} c:#{c} col:#{@color}" )
661
766
  value = getvalue_for_paint
662
767
  len = @display_length || value.length
@@ -673,32 +778,7 @@ module RubyCurses
673
778
  Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
674
779
  @window.delwin if !@window.nil?
675
780
  end
676
- # @deprecated pls call windows method
677
- def printstring(win, r,c,string, color, att = Ncurses::A_NORMAL)
678
-
679
- att = Ncurses::A_NORMAL if att.nil?
680
- case att.to_s.downcase
681
- when 'underline'
682
- att = Ncurses::A_UNDERLINE
683
- $log.debug "UL att #{att}"
684
- when 'bold'
685
- att = Ncurses::A_BOLD
686
- when 'blink'
687
- att = Ncurses::A_BLINK
688
- when 'reverse'
689
- att = Ncurses::A_REVERSE
690
- else
691
- att = Ncurses::A_NORMAL
692
- end
693
- #$log.debug "att #{att}"
694
-
695
- #att = bold ? Ncurses::A_BLINK|Ncurses::A_BOLD : Ncurses::A_NORMAL
696
- # att = bold ? Ncurses::A_BOLD : Ncurses::A_NORMAL
697
- win.attron(Ncurses.COLOR_PAIR(color) | att)
698
- win.mvprintw(r, c, "%s", string);
699
- win.attroff(Ncurses.COLOR_PAIR(color) | att)
700
- end
701
- # in those rare cases where we create widget without a form, and later give it to
781
+ # in those cases where we create widget without a form, and later give it to
702
782
  # some other program which sets the form. Dirty, we should perhaps create widgets
703
783
  # without forms, and add explicitly.
704
784
  def set_form form
@@ -720,10 +800,13 @@ module RubyCurses
720
800
  #@form.row = @row + 1
721
801
  r, c = rowcol
722
802
  $log.warn " empty set_form_row in widget #{self} r = #{r} , c = #{c} "
803
+ #raise "trying to set 0, maybe called repaint before container has set value" if row <= 0
723
804
  setrowcol row, nil
724
805
  end
725
806
  # set cursor on correct column, widget
726
807
  # Ideally, this should be overriden, as it is not likely to be correct.
808
+ # NOTE: this is okay for some widgets but NOT for containers
809
+ # that will call their own components SFR and SFC
727
810
  def set_form_col col1=@curpos
728
811
  @curpos = col1 || 0 # 2010-01-14 21:02
729
812
  #@form.col = @col + @col_offset + @curpos
@@ -810,6 +893,7 @@ module RubyCurses
810
893
  newvalue = @width
811
894
  @config["width"]=@width
812
895
  if oldvalue != newvalue
896
+ @property_changed = true
813
897
  fire_property_change(:width, oldvalue, newvalue)
814
898
  repaint_all(true) # added 2010-01-08 18:51 so widgets can redraw everything.
815
899
  end
@@ -841,9 +925,9 @@ module RubyCurses
841
925
  newvalue = @height
842
926
  @config[:height]=@height
843
927
  if oldvalue != newvalue
928
+ @property_changed = true
844
929
  fire_property_change(:height, oldvalue, newvalue)
845
- $log.debug " widget #{@name} setting repaint_all to true"
846
- @repaint_all=true
930
+ repaint_all true
847
931
  end
848
932
  end
849
933
  end
@@ -904,7 +988,9 @@ module RubyCurses
904
988
  #c += @ext_col_offset unless c.nil?
905
989
  if @form
906
990
  @form.setrowcol r, c
991
+ #elsif @parent_component
907
992
  else
993
+ raise "Parent component not defined for #{self}, #{self.class} " unless @parent_component
908
994
  @parent_component.setrowcol r, c
909
995
  end
910
996
  #setformrowcol r,c
@@ -929,6 +1015,33 @@ module RubyCurses
929
1015
  return @@events if defined? @@events
930
1016
  nil
931
1017
  end
1018
+ # 2011-11-12 trying to make color setting a bit sane
1019
+ # You may set as a color_pair using get_color which gives a fixnum
1020
+ # or you may give 2 color symbols so i can update color, bgcolor and colorpair in one shot
1021
+ # if one of them is nil, i just use the existing value
1022
+ def color_pair(*val)
1023
+ if val.empty?
1024
+ return @color_pair
1025
+ end
1026
+
1027
+ oldvalue = @color_pair
1028
+ case val.size
1029
+ when 1
1030
+ raise ArgumentError, "Expecting fixnum for color_pair." unless val[0].is_a? Fixnum
1031
+ @color_pair = val[0]
1032
+ @color, @bgcolor = ColorMap.get_colors_for_pair @color_pair
1033
+ when 2
1034
+ @color = val.first if val.first
1035
+ @bgcolor = val.last if val.last
1036
+ @color_pair = get_color $datacolor, @color, @bgcolor
1037
+ end
1038
+ if oldvalue != @color_pair
1039
+ fire_property_change(:color_pair, oldvalue, @color_pair)
1040
+ @property_changed = true
1041
+ repaint_all true
1042
+ end
1043
+ self
1044
+ end
932
1045
  ##
933
1046
  ## ADD HERE WIDGET
934
1047
  end
@@ -978,6 +1091,7 @@ module RubyCurses
978
1091
  attr_accessor :cols_panned # HACK added 2009-12-30 16:01 BUFFERED USED ??? CLEANUP XXX
979
1092
 
980
1093
  ## next 2 added since tabbedpanes offset needs to be accounted by form inside it.
1094
+ # NOTE: if you set a form inside another set parent_form in addition to these 2.
981
1095
  attr_accessor :add_cols # 2010-01-26 20:23 additional columns due to being placed in some container
982
1096
  attr_accessor :add_rows # 2010-01-26 20:23 additional columns due to being placed in some container
983
1097
 
@@ -1071,6 +1185,8 @@ module RubyCurses
1071
1185
  $log.debug " form repaint:#{self}, #{@name} , r #{@row} c #{@col} " if $log.debug?
1072
1186
  @widgets.each do |f|
1073
1187
  next if f.visible == false # added 2008-12-09 12:17
1188
+ #$log.debug "XXX: FORM CALLING REPAINT OF WIDGET #{f} IN LOOP"
1189
+ #raise "Row or col nil #{f.row} #{f.col} for #{f}, #{f.name} " if f.row.nil? || f.col.nil?
1074
1190
  f.repaint
1075
1191
  f._object_created = true # added 2010-09-16 13:02 now prop handlers can be fired
1076
1192
  end
@@ -1098,7 +1214,7 @@ module RubyCurses
1098
1214
  # move cursor to where the fields row and col are
1099
1215
  # private
1100
1216
  def setpos r=@row, c=@col
1101
- $log.debug "setpos : (#{self}) #{r} #{c}"
1217
+ $log.debug "setpos : (#{self.name}) #{r} #{c} XXX"
1102
1218
  ## adding just in case things are going out of bounds of a parent and no cursor to be shown
1103
1219
  return if r.nil? or c.nil? # added 2009-12-29 23:28 BUFFERED
1104
1220
  return if r<0 or c<0 # added 2010-01-02 18:49 stack too deep coming if goes above screen
@@ -1180,7 +1296,14 @@ module RubyCurses
1180
1296
  # not be triggered. The highlighted part
1181
1297
  def on_enter f
1182
1298
  return if f.nil? || !f.focusable # added focusable, else label was firing 2010-09
1299
+
1183
1300
  f.state = :HIGHLIGHTED
1301
+ # If the widget has a color defined for focussed, set repaint
1302
+ # otherwise it will not be repainted unless user edits !
1303
+ if f.highlight_background || f.highlight_foreground
1304
+ f.repaint_required true
1305
+ end
1306
+
1184
1307
  f.modified false
1185
1308
  #f.set_modified false
1186
1309
  f.on_enter if f.respond_to? :on_enter
@@ -1206,9 +1329,9 @@ module RubyCurses
1206
1329
  @window.wmove @row, @col # added RK FFI 2011-09-7 = setpos
1207
1330
 
1208
1331
  f.set_form_row # added 2011-10-5 so when embedded in another form it can get the cursor
1209
- f.set_form_col
1332
+ f.set_form_col # this can wreak havoc in containers, unless overridden
1210
1333
 
1211
- f.curpos = 0
1334
+ f.curpos = 0 # why was this, okay is it because of prev obj's cursor ?
1212
1335
  repaint
1213
1336
  @window.refresh
1214
1337
  else
@@ -1342,7 +1465,7 @@ module RubyCurses
1342
1465
  ##
1343
1466
  # move cursor by num columns. Form
1344
1467
  def addcol num
1345
- return if @col.nil? or @col == -1
1468
+ return if @col.nil? || @col == -1
1346
1469
  @col += num
1347
1470
  @window.wmove @row, @col
1348
1471
  ## 2010-01-30 23:45 exchange calling parent with calling this forms setrow
@@ -1373,7 +1496,7 @@ module RubyCurses
1373
1496
  @col = c unless c.nil?
1374
1497
  r += @add_rows unless r.nil? # 2010-01-26 20:31
1375
1498
  c += @add_cols unless c.nil? # 2010-01-26 20:31
1376
- $log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self} r = #{r} , c = #{c} "
1499
+ $log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self} r = #{r} , c = #{c}, parent: #{@parent_form} "
1377
1500
  if !@parent_form.nil? and @parent_form != self
1378
1501
  $log.debug " (#{@name}) addrow calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self: #{self}, #{self.class} "
1379
1502
  #r += @parent_form.window.top unless r.nil?
@@ -1462,6 +1585,16 @@ module RubyCurses
1462
1585
  end
1463
1586
  return 0
1464
1587
  end
1588
+ #
1589
+ # These mappings will only trigger if the current field
1590
+ # does not use them.
1591
+ #
1592
+ def map_keys
1593
+ return if @keys_mapped
1594
+ bind_keys([?\M-?,?\?]) { alert(get_current_field.help_text, 'title' => 'Help Text', :bgcolor => 'green', :color => :white) if get_current_field.help_text }
1595
+ #bind_key(?\?) { alert(get_current_field.help_text.split(",")) if get_current_field.help_text }
1596
+ @keys_mapped = true
1597
+ end
1465
1598
 
1466
1599
  ## forms handle keys
1467
1600
  # mainly traps tab and backtab to navigate between widgets.
@@ -1471,6 +1604,7 @@ module RubyCurses
1471
1604
  # NOTE : please rescue exceptions when you use this in your main loop and alert() user
1472
1605
  #
1473
1606
  def handle_key(ch)
1607
+ map_keys unless @keys_mapped
1474
1608
  handled = :UNHANDLED # 2011-10-4
1475
1609
  if ch == ?\C-u.getbyte(0)
1476
1610
  ret = universal_argument
@@ -1504,7 +1638,7 @@ module RubyCurses
1504
1638
  field = get_current_field
1505
1639
  if $log.debug?
1506
1640
  keycode = keycode_tos(ch)
1507
- $log.debug " form HK #{ch} #{self}, #{@name}, #{keycode}, field: giving to: #{field}, #{field.name} "
1641
+ $log.debug " form HK #{ch} #{self}, #{@name}, #{keycode}, field: giving to: #{field}, #{field.name} " if field
1508
1642
  end
1509
1643
  handled = :UNHANDLED
1510
1644
  handled = field.handle_key ch unless field.nil? # no field focussable
@@ -1538,6 +1672,7 @@ module RubyCurses
1538
1672
  $log.debug " form before repaint #{self} , #{@name}, ret #{ret}"
1539
1673
  repaint
1540
1674
  $last_key = ch
1675
+ ret || 0 # 2011-10-17
1541
1676
  end
1542
1677
  ##
1543
1678
  # test program to dump data onto log
@@ -1640,16 +1775,22 @@ module RubyCurses
1640
1775
  class Field < Widget
1641
1776
  dsl_accessor :maxlen # maximum length allowed into field
1642
1777
  attr_reader :buffer # actual buffer being used for storage
1643
- dsl_accessor :label # label of field
1644
- dsl_accessor :default # TODO use set_buffer for now
1778
+ #
1779
+ # this was unused earlier. Unlike set_label which creates a separate label
1780
+ # object, this stores a label and prints it before the string. This is less
1781
+ # customizable, however, in some cases when a field is attached to some container
1782
+ # the label gets left out. This labels is gauranteed to print to the left of the field
1783
+ #
1784
+ dsl_accessor :label # label of field Unused earlier, now will print
1785
+ dsl_property :label_color_pair # label of field Unused earlier, now will print
1786
+ dsl_property :label_attr # label of field Unused earlier, now will print
1787
+ #dsl_accessor :default # now alias of text 2011-11-5
1645
1788
  dsl_accessor :values # validate against provided list
1646
1789
  dsl_accessor :valid_regex # validate against regular expression
1647
1790
  dsl_accessor :valid_range # validate against numeric range # 2011-09-29 V1.3.1
1648
1791
 
1649
1792
  dsl_accessor :chars_allowed # regex, what characters to allow, will ignore all else
1650
1793
  dsl_accessor :display_length # how much to display
1651
- #dsl_property :bgcolor # background color 'red' 'black' 'cyan' etc # 2011-09-29 IN WIDGET
1652
- #dsl_property :color # foreground colors from Ncurses COLOR_xxxx
1653
1794
  dsl_accessor :show # what charactr to show for each char entered (password field)
1654
1795
  dsl_accessor :null_allowed # allow nulls, don't validate if null # added 2008-12-22 12:38
1655
1796
 
@@ -1664,7 +1805,11 @@ module RubyCurses
1664
1805
  attr_reader :original_value # value on entering field
1665
1806
  attr_accessor :overwrite_mode # true or false INSERT OVERWRITE MODE
1666
1807
 
1667
- def initialize form, config={}, &block
1808
+ # For consistency, now width equates to display_length
1809
+ alias :width :display_length
1810
+ alias :width= :display_length=
1811
+
1812
+ def initialize form=nil, config={}, &block
1668
1813
  @form = form
1669
1814
  @buffer = String.new
1670
1815
  #@type=config.fetch("type", :varchar)
@@ -1672,8 +1817,8 @@ module RubyCurses
1672
1817
  @maxlen = @display_length
1673
1818
  @row = 0
1674
1819
  @col = 0
1675
- @bgcolor = $def_bg_color
1676
- @color = $def_fg_color
1820
+ #@bgcolor = $def_bg_color
1821
+ #@color = $def_fg_color
1677
1822
  @editable = true
1678
1823
  @focusable = true
1679
1824
  @event_args = {} # arguments passed at time of binding, to use when firing event
@@ -1702,10 +1847,10 @@ module RubyCurses
1702
1847
  ##
1703
1848
  # define a datatype, currently only influences chars allowed
1704
1849
  # integer and float. what about allowing a minus sign?
1705
- # 2010-09-10 20:59 changed string to symbol
1706
1850
  def type dtype
1707
- return if !@chars_allowed.nil?
1708
- case dtype.to_s.downcase.to_sym # missing to_sym would have always failed due to to_s 2011-09-30 1.3.1
1851
+ return if @chars_allowed # disallow changing
1852
+ dtype = dtype.to_s.downcase.to_sym if dtype.is_a? String
1853
+ case dtype # missing to_sym would have always failed due to to_s 2011-09-30 1.3.1
1709
1854
  when :integer
1710
1855
  @chars_allowed = /\d/
1711
1856
  when :numeric, :float
@@ -1715,7 +1860,7 @@ module RubyCurses
1715
1860
  when :alnum
1716
1861
  @chars_allowed = /[a-zA-Z0-9]/
1717
1862
  else
1718
- raise "type: invalid datatype specified. Use :integer, :numeric, :float, :alpha, :alnum "
1863
+ raise ArgumentError, "Field type: invalid datatype specified. Use :integer, :numeric, :float, :alpha, :alnum "
1719
1864
  end
1720
1865
  end
1721
1866
 
@@ -1821,20 +1966,36 @@ module RubyCurses
1821
1966
  # create a label linked to this field
1822
1967
  # Typically one passes a Label, but now we can pass just a String, a label
1823
1968
  # is created
1969
+ # NOTE: 2011-10-20 when field attached to some container, label won't be attached
1824
1970
  # @param [Label, String] label object to be associated with this field
1971
+ # FIXME this may not work since i have disabled -1, now i do not set row and col 2011-11-5
1825
1972
  def set_label label
1826
1973
  # added case for user just using a string
1827
1974
  case label
1828
1975
  when String
1829
1976
  # what if no form at this point
1977
+ @label_unattached = true unless @form
1830
1978
  label = Label.new @form, {:text => label}
1831
1979
  end
1832
1980
  @label = label
1833
- label.row @row if label.row == -1
1834
- label.col @col-(label.name.length+1) if label.col == -1
1835
- label.label_for(self)
1981
+ # in the case of app it won't be set yet FIXME
1982
+ # So app sets label to 0 and t his won't trigger
1983
+ # can this be delayed to when paint happens XXX
1984
+ if @row
1985
+ position_label
1986
+ else
1987
+ @label_unplaced = true
1988
+ end
1836
1989
  label
1837
1990
  end
1991
+ # FIXME this may not work since i have disabled -1, now i do not set row and col
1992
+ def position_label
1993
+ $log.debug "XXX: LABEL row #{@label.row}, #{@label.col} "
1994
+ @label.row @row unless @label.row #if @label.row == -1
1995
+ @label.col @col-(@label.name.length+1) unless @label.col #if @label.col == -1
1996
+ @label.label_for(self) # this line got deleted when we redid stuff !
1997
+ $log.debug " XXX: LABEL row #{@label.row}, #{@label.col} "
1998
+ end
1838
1999
 
1839
2000
  ## Note that some older widgets like Field repaint every time the form.repaint
1840
2001
  ##+ is called, whether updated or not. I can't remember why this is, but
@@ -1842,7 +2003,17 @@ module RubyCurses
1842
2003
 
1843
2004
  def repaint
1844
2005
  return unless @repaint_required # 2010-11-20 13:13 its writing over a window i think TESTING
1845
- #$log.debug("repaint FIELD: #{id}, #{name}, #{focusable}")
2006
+ if @label_unattached
2007
+ alert "came here unattachd"
2008
+ @label.set_form(@form)
2009
+ end
2010
+ if @label_unplaced
2011
+ alert "came here unplaced"
2012
+ position_label
2013
+ end
2014
+ @bgcolor ||= $def_bg_color
2015
+ @color ||= $def_fg_color
2016
+ $log.debug("repaint FIELD: #{id}, #{name}, #{row} #{col}, #{focusable} st: #{@state} ")
1846
2017
  #return if display_length <= 0 # added 2009-02-17 00:17 sometimes editor comp has 0 and that
1847
2018
  # becomes negative below, no because editing still happens
1848
2019
  @display_length = 1 if display_length == 0
@@ -1855,11 +2026,25 @@ module RubyCurses
1855
2026
  printval = printval[@pcol..-1]
1856
2027
  end
1857
2028
  end
1858
- #printval = printval[0..display_length-1] if printval.length > display_length
2029
+
1859
2030
  acolor = @color_pair || get_color($datacolor, @color, @bgcolor)
2031
+ if @state == :HIGHLIGHTED
2032
+ _bgcolor = @highlight_background || @bgcolor
2033
+ _color = @highlight_foreground || @color
2034
+ acolor = get_color(acolor, _color, _bgcolor)
2035
+ end
1860
2036
  @graphic = @form.window if @graphic.nil? ## cell editor listbox hack
1861
- #$log.debug " Field g:#{@graphic}. r,c,displen:#{@row}, #{@col}, #{@display_length} "
1862
- @graphic.printstring row, col, sprintf("%-*s", display_length, printval), acolor, @attr
2037
+ #$log.debug " Field g:#{@graphic}. r,c,displen:#{@row}, #{@col}, #{@display_length} c:#{@color} bg:#{@bgcolor} a:#{@attr} :#{@name} "
2038
+ r = row
2039
+ c = col
2040
+ if label.is_a? String
2041
+ lcolor = @label_color_pair || $datacolor # this should be the same color as window bg XXX
2042
+ lattr = @label_attr || NORMAL
2043
+ @graphic.printstring row, col, label, lcolor, lattr
2044
+ c += label.length + 2
2045
+ @col_offset = c-@col # required so cursor lands in right place
2046
+ end
2047
+ @graphic.printstring r, c, sprintf("%-*s", display_length, printval), acolor, @attr
1863
2048
  @repaint_required = false
1864
2049
  end
1865
2050
  def set_focusable(tf)
@@ -2038,7 +2223,9 @@ module RubyCurses
2038
2223
  def modified?
2039
2224
  getvalue() != @original_value
2040
2225
  end
2041
- # field, a convenience method, since set_buffer sucks, it was "inspired" by ncurses itself
2226
+ #
2227
+ # Use this to set a default text to the field. This does not imply that if the field is left
2228
+ # blank, this value will be used. It only provides this value for editing when field is shown.
2042
2229
  # @since 1.2.0
2043
2230
  def text(*val)
2044
2231
  if val.empty?
@@ -2049,6 +2236,7 @@ module RubyCurses
2049
2236
  set_buffer(s)
2050
2237
  end
2051
2238
  end
2239
+ alias :default :text
2052
2240
  def text=(val)
2053
2241
  return unless val # added 2010-11-17 20:11, dup will fail on nil
2054
2242
  set_buffer(val.dup)
@@ -2160,25 +2348,31 @@ module RubyCurses
2160
2348
  end
2161
2349
  end
2162
2350
  ##
2163
- # the preferred way of printing text on screen, esp if you want to modify it at run time.
2351
+ # The preferred way of printing text on screen, esp if you want to modify it at run time.
2164
2352
  # Use display_length to ensure no spillage.
2165
2353
  # This can use text or text_variable for setting and getting data (inh from Widget).
2354
+ # 2011-11-12 making it simpler, and single line only. The original multiline label
2355
+ # has moved to extras/multilinelabel.rb
2356
+ #
2166
2357
  class Label < Widget
2167
- #dsl_accessor :label_for # related field or buddy
2168
- dsl_accessor :mnemonic # keyboard focus is passed to buddy based on this key (ALT mask)
2358
+ dsl_accessor :mnemonic # keyboard focus is passed to buddy based on this key (ALT mask)
2359
+
2169
2360
  # justify required a display length, esp if center.
2170
- #dsl_accessor :justify # :right, :left, :center # added 2008-12-22 19:02
2171
- dsl_property :justify # :right, :left, :center # added 2008-12-22 19:02
2172
- dsl_property :display_length # please give this to ensure the we only print this much
2173
- dsl_property :height # if you want a multiline label.
2361
+ dsl_property :justify #:right, :left, :center
2362
+ dsl_property :display_length #please give this to ensure the we only print this much
2363
+ #dsl_property :height #if you want a multiline label. already added to widget
2364
+ # for consistency with others 2011-11-5
2365
+ alias :width :display_length
2366
+ alias :width= :display_length=
2174
2367
 
2175
2368
  def initialize form, config={}, &block
2176
2369
 
2177
- @row = config.fetch("row",-1)
2178
- @col = config.fetch("col",-1)
2179
- @bgcolor = config.fetch("bgcolor", $def_bg_color)
2180
- @color = config.fetch("color", $def_fg_color)
2181
- @text = config.fetch("text", "NOTFOUND")
2370
+ # this crap was used in position_label, find another way. where is it used ?
2371
+ #@row = config.fetch("row",-1) # why on earth this monstrosity ? 2011-11-5
2372
+ #@col = config.fetch("col",-1)
2373
+ #@bgcolor = config.fetch("bgcolor", $def_bg_color)
2374
+ #@color = config.fetch("color", $def_fg_color)
2375
+ @text = config.fetch(:text, "NOTFOUND")
2182
2376
  @editable = false
2183
2377
  @focusable = false
2184
2378
  super
@@ -2194,18 +2388,23 @@ module RubyCurses
2194
2388
  def label_for field
2195
2389
  @label_for = field
2196
2390
  #$log.debug " label for: #{@label_for}"
2197
- bind_hotkey unless @form.nil? # GRRR!
2391
+ if @form
2392
+ bind_hotkey
2393
+ else
2394
+ @when_form ||= []
2395
+ @when_form << lambda { bind_hotkey }
2396
+ end
2198
2397
  end
2199
2398
 
2200
2399
  ##
2201
2400
  # for a button, fire it when label invoked without changing focus
2202
2401
  # for other widgets, attempt to change focus to that field
2203
2402
  def bind_hotkey
2204
- if !@mnemonic.nil?
2403
+ if @mnemonic
2205
2404
  ch = @mnemonic.downcase()[0].ord ## 1.9 DONE
2206
2405
  # meta key
2207
2406
  mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0)) ## 1.9
2208
- if @label_for.is_a? RubyCurses::Button and @label_for.respond_to? :fire
2407
+ if (@label_for.is_a? RubyCurses::Button ) && (@label_for.respond_to? :fire)
2209
2408
  @form.bind_key(mch, @label_for) { |_form, _butt| _butt.fire }
2210
2409
  else
2211
2410
  $log.debug " bind_hotkey label for: #{@label_for}"
@@ -2215,53 +2414,56 @@ module RubyCurses
2215
2414
  end
2216
2415
 
2217
2416
  ##
2218
- # XXX need to move wrapping etc up and done once.
2417
+ # label's repaint - I am removing wrapping and Array stuff and making it simple 2011-11-12
2219
2418
  def repaint
2220
2419
  return unless @repaint_required
2420
+ raise "Label row or col nil #{@row} , #{@col}, #{@text} " if @row.nil? || @col.nil?
2221
2421
  r,c = rowcol
2422
+
2423
+ @bgcolor ||= $def_bg_color
2424
+ @color ||= $def_fg_color
2222
2425
  # value often nil so putting blank, but usually some application error
2223
2426
  value = getvalue_for_paint || ""
2224
- lablist = []
2225
- if @height && @height > 1
2226
- lablist = wrap_text(value, @display_length).split("\n")
2227
- else
2228
- # ensure we do not exceed
2229
- if !@display_length.nil?
2230
- if value.length > @display_length
2231
- value = value[0..@display_length-1]
2232
- end
2427
+
2428
+ if value.is_a? Array
2429
+ value = value.join " "
2430
+ end
2431
+ # ensure we do not exceed
2432
+ if @display_length
2433
+ if value.length > @display_length
2434
+ value = value[0..@display_length-1]
2233
2435
  end
2234
- lablist << value
2235
2436
  end
2236
2437
  len = @display_length || value.length
2237
- acolor = get_color $datacolor
2238
- #$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor #{acolor} j:#{@justify} dlL: #{@display_length} "
2239
- firstrow = r
2240
- _height = @height || 1
2438
+ #acolor = get_color $datacolor
2439
+ # the user could have set color_pair, use that, else determine color
2440
+ # This implies that if he sets cp, then changing col and bg won't have an effect !
2441
+ # A general routine that only changes color will not work here.
2442
+ acolor = @color_pair || get_color($datacolor, @color, @bgcolor)
2443
+ #$log.debug "label :#{@text}, #{value}, r #{r}, c #{c} col= #{@color}, #{@bgcolor} acolor #{acolor} j:#{@justify} dlL: #{@display_length} "
2241
2444
  str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
2242
- # loop added for labels that are wrapped.
2243
- # TODO clear separately since value can change in status like labels
2244
2445
 
2245
- @graphic = @form.window if @graphic.nil? ## HACK messagebox givig this in repaint, 423 not working ??
2246
- 0.upto(_height-1) { |i|
2247
- @graphic.printstring r+i, c, " " * len , acolor,@attr
2248
- }
2249
- lablist.each_with_index do |_value, ix|
2250
- break if ix >= _height
2251
- if @justify.to_sym == :center
2252
- padding = (@display_length - _value.length)/2
2253
- _value = " "*padding + _value + " "*padding # so its cleared if we change it midway
2254
- end
2255
- @graphic.printstring r, c, str % [len, _value], acolor,@attr
2256
- r += 1
2257
- end
2258
- if !@mnemonic.nil?
2446
+ @graphic ||= @form.window
2447
+ # clear the area
2448
+ @graphic.printstring r, c, " " * len , acolor, @attr
2449
+ if @justify.to_sym == :center
2450
+ padding = (@display_length - value.length)/2
2451
+ value = " "*padding + value + " "*padding # so its cleared if we change it midway
2452
+ end
2453
+ @graphic.printstring r, c, str % [len, value], acolor, @attr
2454
+ if @mnemonic
2259
2455
  ulindex = value.index(@mnemonic) || value.index(@mnemonic.swapcase)
2260
- @graphic.mvchgat(y=firstrow, x=c+ulindex, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, acolor, nil)
2456
+ @graphic.mvchgat(y=r, x=c+ulindex, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, acolor, nil)
2261
2457
  end
2262
- #@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, color, nil)
2263
2458
  @repaint_required = false
2264
2459
  end
2460
+ # Added 2011-10-22 to prevent some naive components from putting focus here.
2461
+ def on_enter
2462
+ raise "Cannot enter Label"
2463
+ end
2464
+ def on_leave
2465
+ raise "Cannot leave Label"
2466
+ end
2265
2467
  # ADD HERE LABEL
2266
2468
  end
2267
2469
  ##
@@ -2282,10 +2484,11 @@ module RubyCurses
2282
2484
  @_events ||= []
2283
2485
  @_events.push :PRESS
2284
2486
  super
2285
- @bgcolor ||= $datacolor
2286
- @color ||= $datacolor
2487
+
2488
+
2287
2489
  @surround_chars ||= ['[ ', ' ]']
2288
2490
  @col_offset = @surround_chars[0].length
2491
+ @text_offset = 0
2289
2492
  end
2290
2493
  ##
2291
2494
  # set button based on Action
@@ -2305,7 +2508,8 @@ module RubyCurses
2305
2508
  s = s.to_s if !s.is_a? String # 2009-01-15 17:32
2306
2509
  if (( ix = s.index('&')) != nil)
2307
2510
  s.slice!(ix,1)
2308
- @underline = ix unless @form.nil? # this setting a fake underline in messageboxes
2511
+ # 2011-10-20 NOTE XXX I have removed form check since bindkey is called conditionally
2512
+ @underline = ix #unless @form.nil? # this setting a fake underline in messageboxes
2309
2513
  mnemonic s[ix,1]
2310
2514
  end
2311
2515
  @text = s
@@ -2315,10 +2519,17 @@ module RubyCurses
2315
2519
  ##
2316
2520
  # FIXME this will not work in messageboxes since no form available
2317
2521
  # if already set mnemonic, then unbind_key, ??
2522
+ # NOTE: Some buttons like checkbox directly call mnemonic, so if they have no form
2523
+ # then this processing does not happen
2318
2524
 
2319
2525
  def mnemonic char
2320
- $log.error " #{self} COULD NOT SET MNEMONIC since form NIL" if @form.nil?
2321
- return if @form.nil?
2526
+ $log.error "ERROR WARN #{self} COULD NOT SET MNEMONIC since form NIL" if @form.nil?
2527
+ unless @form
2528
+ @when_form ||= []
2529
+ @when_form << lambda { mnemonic char }
2530
+ return
2531
+ end
2532
+ #return if @form.nil?
2322
2533
  @mnemonic = char
2323
2534
  ch = char.downcase()[0].ord ## 1.9
2324
2535
  # meta key
@@ -2331,7 +2542,13 @@ module RubyCurses
2331
2542
  # bind hotkey to form keys. added 2008-12-15 20:19
2332
2543
  # use ampersand in name or underline
2333
2544
  def bind_hotkey
2334
- return if @underline.nil? or @form.nil?
2545
+ if @form.nil?
2546
+ if @underline
2547
+ @when_form ||= []
2548
+ @when_form << lambda { bind_hotkey }
2549
+ end
2550
+ return
2551
+ end
2335
2552
  _value = @text || getvalue # hack for Togglebutton FIXME
2336
2553
  #_value = getvalue
2337
2554
  $log.debug " bind hot #{_value} #{@underline}"
@@ -2353,37 +2570,60 @@ module RubyCurses
2353
2570
  @surround_chars[0] + ret + @surround_chars[1]
2354
2571
  end
2355
2572
  def repaint # button
2356
- #$log.debug("BUTTon repaint : #{self} r:#{@row} c:#{@col} #{getvalue_for_paint}" )
2573
+ if @form
2574
+ if @when_form
2575
+ $log.debug "XXX:WHEN calling when_forms commands"
2576
+ @when_form.each { |c| c.call() }
2577
+ @when_form = nil
2578
+ end
2579
+ end
2580
+
2581
+ @bgcolor ||= $def_bg_color
2582
+ @color ||= $def_fg_color
2583
+ $log.debug("BUTTON repaint : #{self} r:#{@row} c:#{@col} , #{@color} , #{@bgcolor} , #{getvalue_for_paint}" )
2357
2584
  r,c = @row, @col #rowcol include offset for putting cursor
2358
2585
  # NOTE: please override both (if using a string), or else it won't work
2359
2586
  @highlight_foreground ||= $reversecolor
2360
2587
  @highlight_background ||= 0
2361
- bgcolor = @state==:HIGHLIGHTED ? @highlight_background : @bgcolor
2362
- color = @state==:HIGHLIGHTED ? @highlight_foreground : @color
2363
- if bgcolor.is_a? String and color.is_a? String
2364
- color = ColorMap.get_color(color, bgcolor)
2588
+ _bgcolor = @bgcolor
2589
+ _color = @color
2590
+ if @state == :HIGHLIGHTED
2591
+ _bgcolor = @state==:HIGHLIGHTED ? @highlight_background : @bgcolor
2592
+ _color = @state==:HIGHLIGHTED ? @highlight_foreground : @color
2593
+ elsif selected? # only for certain buttons lie toggle and radio
2594
+ _bgcolor = @selected_background || @bgcolor
2595
+ _color = @selected_foreground || @color
2596
+ end
2597
+ $log.debug "XXX: button #{text} STATE is #{@state} color #{_color} , bg: #{_bgcolor} "
2598
+ if _bgcolor.is_a?( Fixnum) && _color.is_a?( Fixnum)
2599
+ else
2600
+ _color = get_color($datacolor, _color, _bgcolor)
2365
2601
  end
2366
2602
  value = getvalue_for_paint
2367
- #$log.debug("button repaint :#{self} r:#{r} c:#{c} col:#{color} bg #{bgcolor} v: #{value} ul #{@underline} mnem #{@mnemonic}")
2603
+ $log.debug("button repaint :#{self} r:#{r} c:#{c} col:#{_color} bg #{_bgcolor} v: #{value} ul #{@underline} mnem #{@mnemonic} datacolor #{$datacolor} ")
2368
2604
  len = @display_length || value.length
2369
2605
  @graphic = @form.window if @graphic.nil? ## cell editor listbox hack
2370
- @graphic.printstring r, c, "%-*s" % [len, value], color, @attr
2606
+ @graphic.printstring r, c, "%-*s" % [len, value], _color, @attr
2371
2607
  # @form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, bgcolor, nil)
2372
2608
  # in toggle buttons the underline can change as the text toggles
2373
2609
  if @underline || @mnemonic
2374
- uline = @underline && (@underline + @text_offset) || value.index(@mnemonic) || value.index(@mnemonic.swapcase)
2375
- #$log.debug " mvchgat UNDERLI r= #{r} - #{@graphic.top} c #{c} c+x #{c+uline}- #{@graphic.left} #{@graphic} "
2376
- #$log.debug " HACK in next line related to UNDERLINES -graphic.top"
2610
+ uline = @underline && (@underline + @text_offset) || value.index(@mnemonic) ||
2611
+ value.index(@mnemonic.swapcase)
2377
2612
  # if the char is not found don't print it
2378
2613
  if uline
2379
2614
  y=r #-@graphic.top
2380
2615
  x=c+uline #-@graphic.left
2381
2616
  if @graphic.window_type == :PAD
2382
- x -= @graphic.left
2617
+ x -= @graphic.left
2383
2618
  y -= @graphic.top
2384
2619
  end
2385
- raise "button underline location error #{x} , #{y} " if x < 0 or c < 0
2386
- @graphic.mvchgat(y, x, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, color, nil)
2620
+ #
2621
+ # NOTE: often values go below zero since root windows are defined
2622
+ # with 0 w and h, and then i might use that value for calcaluting
2623
+ #
2624
+ $log.error "XXX button underline location error #{x} , #{y} " if x < 0 or c < 0
2625
+ raise " #{r} #{c} #{uline} button underline location error x:#{x} , y:#{y}. left #{@graphic.left} top:#{@graphic.top} " if x < 0 or c < 0
2626
+ @graphic.mvchgat(y, x, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, _color, nil)
2387
2627
  end
2388
2628
  end
2389
2629
  end
@@ -2401,6 +2641,8 @@ module RubyCurses
2401
2641
  #fire_handler :PRESS, @form changed on 2010-09-12 19:22
2402
2642
  fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
2403
2643
  end
2644
+ # for campatibility with all buttons, will apply to radio buttons mostly
2645
+ def selected?; false; end
2404
2646
 
2405
2647
  # Button
2406
2648
  def handle_key ch
@@ -2483,11 +2725,18 @@ module RubyCurses
2483
2725
  dsl_accessor :surround_chars
2484
2726
  dsl_accessor :variable # value linked to this variable which is a boolean
2485
2727
  dsl_accessor :display_length # 2009-01-06 00:10
2728
+ # background to use when selected, if not set then default
2729
+ dsl_accessor :selected_background
2730
+ dsl_accessor :selected_foreground
2731
+
2732
+ # For consistency, now width equates to display_length
2733
+ alias :width :display_length
2734
+ alias :width= :display_length=
2486
2735
 
2487
2736
  # item_event
2488
2737
  def initialize form, config={}, &block
2489
2738
  super
2490
- # no longer linked to text_variable, that was a misunderstanding
2739
+
2491
2740
  @value ||= (@variable.nil? ? false : @variable.get_value(@name)==true)
2492
2741
  end
2493
2742
  def getvalue
@@ -2603,6 +2852,10 @@ module RubyCurses
2603
2852
  def initialize form, config={}, &block
2604
2853
  @surround_chars = ['(', ')'] if @surround_chars.nil?
2605
2854
  super
2855
+ $log.warn "XXX: FIXME Please set 'value' for radiobutton. If you don't know, try setting it to 'text'" unless @value
2856
+ # I am setting value of value here if not set 2011-10-21
2857
+ @value ||= @text
2858
+ raise "A single Variable must be set for a group of Radio Buttons for this to work." unless @variable
2606
2859
  end
2607
2860
 
2608
2861
  # all radio buttons will return the value of the selected value, not the offered value
@@ -2659,3 +2912,4 @@ module RubyCurses
2659
2912
  end
2660
2913
 
2661
2914
  end # module
2915
+ include RubyCurses::Utils