Class: RubyCurses::App
- Extended by:
- Forwardable
- Defined in:
- lib/rbcurse/app.rb
Overview
This is the Application class which does the job of setting up the environment, and closing it at the end.
Defined Under Namespace
Classes: Stack
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#form ⇒ Object
readonly
Returns the value of attribute form.
-
#prompt_row ⇒ Object
the row on which to prompt user for any inputs.
-
#quit_key ⇒ Object
writeonly
Sets the attribute quit_key.
-
#window ⇒ Object
readonly
Returns the value of attribute window.
methods to create widgets easily collapse
- #app_header(title, config = {}, &block) ⇒ Object
-
#basiclist(*args, &block) ⇒ Object
create a readonly list.
-
#blank(rows = 1, config = {}) ⇒ Object
creates a blank row.
- #button(*args, &block) ⇒ Object
-
#check(*args, &block) ⇒ Object
check button.
-
#combo(*args, &block) ⇒ Object
creates a simple readonly table, that allows users to click on rows and also on the header.
-
#divider(*args, &block) ⇒ Object
divider used to resize neighbouring components TOTEST XXX.
-
#dock(labels, config = {}, &block) ⇒ Object
prints pine-like key labels.
-
#field(*args, &block) ⇒ Object
process arguments based on datatype, perhaps making configuration of some components easier for caller avoiding too much boiler plate code.
-
#hline(config = {}) ⇒ Object
displays a horizontal line takes col (column to start from) from current stack take row from app_row.
-
#label(*args) ⇒ Object
(also: #text)
instance_eval &block if block_given? or colorlabel = Label.new @form, => “Select a color:”, “row” => row, “col” => col, “color”=>“cyan”, “mnemonic” => ‘S’ var = RubyCurses::Label.new @form, => $results, “row” => r, “col” => fc.
- #link(*args, &block) ⇒ Object
-
#list_box(*args, &block) ⇒ Object
create a list Since we are mouseless, one can traverse without selection.
- #master_detail(*args, &block) ⇒ Object
-
#menubar(&block) ⇒ Object
menu bar.
- #menulink(*args, &block) ⇒ Object
- #multisplit(*args, &block) ⇒ Object
-
#progress(*args, &block) ⇒ Object
progress bar.
-
#radio(*args, &block) ⇒ Object
radio button.
-
#scrollbar(*args, &block) ⇒ Object
scrollbar attached to the right of a parent object.
- #splitpane(*args, &block) ⇒ Object
-
#subtitle(string, config = {}) ⇒ Object
print a sutitle on second row.
-
#table(*args, &block) ⇒ Object
table widget.
-
#tabular_widget(*args, &block) ⇒ Object
creates a simple readonly table, that allows users to click on rows and also on the header.
-
#textarea(*args, &block) ⇒ Object
editable text area.
- #textview(*args, &block) ⇒ Object
-
#title(string, config = {}) ⇒ Object
print a title on first row.
-
#toggle(*args, &block) ⇒ Object
toggle button.
- #tree(*args, &block) ⇒ Object
- #vimsplit(*args, &block) ⇒ Object
positioning of components collapse
-
#flow(config = {}, &block) ⇒ Object
keep adding to right of previous and when no more space move down and continue fitting in.
- #stack(config = {}, &block) ⇒ Object
Instance Method Summary collapse
-
#bind_component ⇒ Object
message “Bound #str to #cmd ”.
-
#bind_global ⇒ Object
bind a key to a method at global (form) level Note that individual component may be overriding this.
- #close ⇒ Object
- #display_app_help ⇒ Object
- #get_all_commands ⇒ Object
-
#get_binding ⇒ Object
used only by LiveConsole, if enables in an app, usually only during testing.
-
#get_command_from_user(choices = ["quit"]) ⇒ Object
prompts user for a command.
- #init_vars ⇒ Object
-
#initialize(config = {}, &block) ⇒ App
constructor
TODO: i should be able to pass window coords here in config :title.
-
#keypress(&block) ⇒ Object
returns a symbol of the key pressed e.g.
-
#logger ⇒ Object
# trying without 2011-10-8 require ‘rbcurse/extras/stdscrwindow’ awin = StdscrWindow.new $tt.window = awin; $tt.message_row = @message_row.
-
#loop(&block) ⇒ Object
not sure, but user shuld be able to trap keystrokes if he wants but do i still call handle_key if he does, or give him total control.
-
#message(text) ⇒ Object
updates a global var with text.
-
#message_immediate(text) ⇒ Object
during a process, when you wish to update status, since ordinarily the thread is busy and form does not get control back, so the window won’t refresh.
- #message_row(row) ⇒ Object
-
#raw_message(text) ⇒ Object
deprecated
Deprecated.
since it uses stdscr. Use say_with_pause or use rdialogs status_window, see test2.rb
-
#raw_progress(arg) ⇒ Object
deprecated
Deprecated.
-
don’t use stdscr at all, use rdialogs status_window (see test2.rb)
-
-
#safe_loop(&block) ⇒ Object
if calling loop separately better to call this, since it will shut off ncurses and print error on screen.
-
#suspend(clear = true) ⇒ Object
suspends curses so you can play around on the shell or in cooked mode like Vim does.
Constructor Details
#initialize(config = {}, &block) ⇒ App
TODO: i should be able to pass window coords here in config :title
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/rbcurse/app.rb', line 87 def initialize config={}, &block #$log.debug " inside constructor of APP #{config} " @config = config @app_row = @app_col = 0 @stack = [] # stack's coordinates @flowstack = [] @variables = {} # if we are creating child objects then we will not use outer form. this object will manage @current_object = [] @_system_commands = %w{ bind_global bind_component } init_vars $log.debug "XXX APP CONFIG: #{@config} " if $log.debug? run &block end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
75 76 77 |
# File 'lib/rbcurse/app.rb', line 75 def config @config end |
#form ⇒ Object (readonly)
Returns the value of attribute form.
76 77 78 |
# File 'lib/rbcurse/app.rb', line 76 def form @form end |
#prompt_row ⇒ Object
the row on which to prompt user for any inputs
80 81 82 |
# File 'lib/rbcurse/app.rb', line 80 def prompt_row @prompt_row end |
#quit_key=(value) ⇒ Object (writeonly)
Sets the attribute quit_key
78 79 80 |
# File 'lib/rbcurse/app.rb', line 78 def quit_key=(value) @quit_key = value end |
#window ⇒ Object (readonly)
Returns the value of attribute window.
77 78 79 |
# File 'lib/rbcurse/app.rb', line 77 def window @window end |
Instance Method Details
#app_header(title, config = {}, &block) ⇒ Object
733 734 735 736 |
# File 'lib/rbcurse/app.rb', line 733 def app_header title, config={}, &block require 'rbcurse/applicationheader' header = ApplicationHeader.new @form, title, config, &block end |
#basiclist(*args, &block) ⇒ Object
create a readonly list
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 |
# File 'lib/rbcurse/app.rb', line 868 def basiclist *args, &block require 'rbcurse/rbasiclistbox' config = {} #TODO check these events = [ :LEAVE, :ENTER, :ENTER_ROW, :LEAVE_ROW, :LIST_DATA_EVENT ] # TODO how to do this so he gets selected row easily block_event = :ENTER_ROW _process_args args, config, block_event, events # some guesses at a sensible height for listbox if !config.has_key? :height ll = 0 ll = config[:list].length + 2 if config.has_key? :list config[:height] ||= ll config[:height] = 15 if config[:height] > 20 end _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last config[:width] ||= longest_in_list(config[:list])+2 #config.delete :title #config[:default_values] = config.delete :choose config[:selection_mode] = :single unless config.has_key? :selection_mode useform = nil useform = @form if @current_object.empty? w = BasicListbox.new useform, config # NO BLOCK GIVEN if block_given? field.bind(block_event, &block) end return w end |
#bind_component ⇒ Object
message “Bound #str to #cmd ”
371 372 373 374 375 376 |
# File 'lib/rbcurse/app.rb', line 371 def bind_component # the idea here is to get the current component # and bind some keys to some methods. # however, how do we divine the methods we can map to # and also in some cases the components itself has multiple components end |
#bind_global ⇒ Object
bind a key to a method at global (form) level Note that individual component may be overriding this.
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/rbcurse/app.rb', line 334 def bind_global opts = get_all_commands cmd = ask("Select a command (TAB for choices) : ", opts) if cmd.nil? || cmd == "" "Aborted." return end key = [] str = "" "Enter one or 2 keys. Finish with ENTER. Enter first key:" #raw_message "Enter first key:" ch = @window.getchar() if [KEY_ENTER, 10, 13, ?\C-g.getbyte(0)].include? ch "Aborted." return end key << ch str << keycode_tos(ch) "Enter second key or hit return:" ch = @window.getchar() if ch == 3 || ch == ?\C-g.getbyte(0) "Aborted." return end if ch == 10 || ch == KEY_ENTER || ch == 13 else key << ch str << keycode_tos(ch) end if !key.empty? "Binding #{cmd} to #{str} " key = key[0] if key.size == 1 #@form.bind_key(key, cmd.to_sym) # not finding it, getting called by that comp @form.bind_key(key){ send(cmd.to_sym) } end #message "Bound #{str} to #{cmd} " end |
#blank(rows = 1, config = {}) ⇒ Object
creates a blank row
711 712 713 |
# File 'lib/rbcurse/app.rb', line 711 def blank rows=1, config={} @app_row += rows end |
#button(*args, &block) ⇒ Object
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
# File 'lib/rbcurse/app.rb', line 469 def *args, &block config = {} events = [ :PRESS, :LEAVE, :ENTER ] block_event = :PRESS _process_args args, config, block_event, events config[:text] ||= config[:name] config.delete(:title) # flow gets precedence over stack _position(config) = Button.new @form, config # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited if block .bind(block_event, &block) end return end |
#check(*args, &block) ⇒ Object
check button
558 559 560 561 562 563 564 565 566 567 568 569 570 |
# File 'lib/rbcurse/app.rb', line 558 def check *args, &block config = {} # TODO confirm events events = [ :PRESS, :LEAVE, :ENTER ] block_event = :PRESS _process_args args, config, block_event, events _position(config) toggle = CheckBox.new @form, config if block toggle.bind(block_event, &block) end return toggle end |
#close ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rbcurse/app.rb', line 128 def close $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} " @window.destroy if !@window.nil? $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} " if @stop_ncurses_on_close $tt.destroy # added on 2011-10-9 since we created a window, but only hid it after use VER::stop_ncurses $log.debug " CLOSING NCURSES" end #p $error_message.value unless $error_message.value.nil? $log.debug " CLOSING APP" #end end |
#combo(*args, &block) ⇒ Object
creates a simple readonly table, that allows users to click on rows and also on the header. Header clicking is for column-sorting.
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 |
# File 'lib/rbcurse/app.rb', line 970 def combo *args, &block require 'rbcurse/rcombo' config = {} events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ] # XXX block_event = nil _process_args args, config, block_event, events _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last #config.delete :title useform = nil useform = @form if @current_object.empty? w = ComboBox.new useform, config # NO BLOCK GIVEN if block_given? @current_object << w yield_or_eval &block @current_object.pop end return w end |
#display_app_help ⇒ Object
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/rbcurse/app.rb', line 302 def display_app_help if respond_to? :help_text arr = help_text else arr = [] arr << " NO HELP SPECIFIED FOR APP " arr << " " arr << " --- General help --- " arr << " F10 - exit application " arr << " Alt-x - select commands " arr << " : - select commands " arr << " " end case arr when String arr = arr.split("\n") when Array end w = arr.max_by(&:length).length require 'rbcurse/extras/viewer' RubyCurses::Viewer.view(arr, :layout => [2, 10, [4+arr.size, 24].min, w+2],:close_key => KEY_RETURN, :title => "<Enter> to close", :print_footer => true) do |t| # you may configure textview further here. #t.suppress_borders true #t.color = :black #t.bgcolor = :white # or t.attr = :reverse end end |
#divider(*args, &block) ⇒ Object
divider used to resize neighbouring components TOTEST XXX
958 959 960 961 962 963 964 965 966 967 |
# File 'lib/rbcurse/app.rb', line 958 def divider *args, &block require 'rbcurse/extras/divider' config = {} events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :DRAG_EVENT ] # # none really at present block_event = nil _process_args args, config, block_event, events useform = nil useform = @form if @current_object.empty? sb = Divider.new useform, config end |
#dock(labels, config = {}, &block) ⇒ Object
prints pine-like key labels
739 740 741 742 |
# File 'lib/rbcurse/app.rb', line 739 def dock labels, config={}, &block require 'rbcurse/keylabelprinter' klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block end |
#field(*args, &block) ⇒ Object
process arguments based on datatype, perhaps making configuration of some components easier for caller avoiding too much boiler plate code
create a field
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 |
# File 'lib/rbcurse/app.rb', line 433 def field *args, &block config = {} events = [ :CHANGED, :LEAVE, :ENTER, :CHANGE ] block_event = :CHANGED # LEAVE, ENTER, CHANGE _process_args args, config, block_event, events config.delete(:title) _position config # hope next line doesn't bonk anything config[:display_length] ||= @stack.last.width if @stack.last # added here not sure 2010-11-17 18:43 field = Field.new @form, config # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited if block field.bind(block_event, &block) end return field end |
#flow(config = {}, &block) ⇒ Object
keep adding to right of previous and when no more space move down and continue fitting in. Useful for button positioning. Currently, we can use a second flow to get another row. TODO: move down when row filled TODO: align right, center
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 |
# File 'lib/rbcurse/app.rb', line 1029 def flow config={}, &block @inflow = true mt = config[:margin_top] || 0 @app_row += mt col = @flowstack.last || @stack.last.margin || @app_col col += config[:margin] || 0 @flowstack << col @flowcol = col #instance_eval &block if block_given? yield_or_eval &block if block_given? # modified 2010-11-17 20:36 @flowstack.pop @inflow = false if @flowstack.empty? end |
#get_all_commands ⇒ Object
295 296 297 298 299 300 301 |
# File 'lib/rbcurse/app.rb', line 295 def get_all_commands opts = @_system_commands.dup if respond_to? :get_commands opts.push(*get_commands()) end opts end |
#get_binding ⇒ Object
used only by LiveConsole, if enables in an app, usually only during testing.
258 259 260 |
# File 'lib/rbcurse/app.rb', line 258 def get_binding return binding() end |
#get_command_from_user(choices = ["quit"]) ⇒ Object
prompts user for a command. we need to get this back to the calling app or have some block stuff TODO Actually, this is naive, you would want to pass some values in like current data value or lines ?? Also may want command completion, or help so all commands can be displayed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
# File 'lib/rbcurse/app.rb', line 382 def get_command_from_user choices=["quit"] #code, str = rbgetstr(@window, $lastline, 0, "", 80, :default => ":") #return unless code == 0 @_command_history ||= Array.new str = ask("Cmd: ", choices) { |q| q.default = @_previous_command; q.history = @_command_history } @_command_history << str unless @_command_history.include? str # shell the command if str =~ /^!/ str = str[1..-1] suspend(false) { #system(str); $log.debug "XXX STR #{str} " if $log.debug? output=`#{str}` system("echo ' ' "); $log.debug "XXX output #{output} " if $log.debug? system("echo '#{output}' "); system("echo Press Enter to continue."); system("read"); } return nil # i think else # TODO # here's where we can take internal commands #alert "[#{str}] string did not match :!" str = str.to_s #= str[1..-1] cmdline = str.split cmd = cmdline.shift #.to_sym return unless cmd # added 2011-09-11 FFI if respond_to?(cmd, true) if cmd == "close" throw :close # other seg faults in del_panel window.destroy executes 2x else send cmd, *cmdline end else alert "#{self.class} does not respond to #{cmd} " ret = false ret = execute_this(cmd, *cmdline) if respond_to?(:execute_this, true) say_with_pause("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret # should be able to say in red as error end end end |
#hline(config = {}) ⇒ Object
displays a horizontal line takes col (column to start from) from current stack take row from app_row
requires width to be passed in config, else defaults to 20
721 722 723 724 725 726 727 728 729 730 731 732 |
# File 'lib/rbcurse/app.rb', line 721 def hline config={} row = config[:row] || @app_row width = config[:width] || 20 _position config col = config[:col] || 1 @color_pair = config[:color_pair] || $datacolor @attrib = config[:attrib] || Ncurses::A_NORMAL @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib) @window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width) @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib) @app_row += 1 end |
#init_vars ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/rbcurse/app.rb', line 102 def init_vars @quit_key ||= FFI::NCurses::KEY_F10 # actually this should be maintained inside ncurses pack, so not loaded 2 times. # this way if we call an app from existing program, App won't start ncurses. unless $ncurses_started init_ncurses end $lastline = Ncurses.LINES - 1 = Ncurses.LINES-1 @prompt_row = # hope to use for ask etc unless $log path = File.join(ENV["LOGDIR"] || "./" ,"rbc13.log") file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT) $log = Logger.new(path) $log.level = Logger::DEBUG # change to warn when you've tested your app. colors = Ncurses.COLORS $log.debug "START #{colors} colors --------- #{$0} win: #{@window} " end =begin # trying without 2011-10-8 require 'rbcurse/extras/stdscrwindow' awin = StdscrWindow.new $tt.window = awin; $tt.message_row = @message_row =end end |
#keypress(&block) ⇒ Object
returns a symbol of the key pressed e.g. :C_c for Ctrl-C :Space, :bs, :M_d etc
181 182 183 |
# File 'lib/rbcurse/app.rb', line 181 def keypress &block @keyblock = block end |
#label(*args) ⇒ Object Also known as: text
instance_eval &block if block_given? or colorlabel = Label.new @form, => “Select a color:”, “row” => row, “col” => col, “color”=>“cyan”, “mnemonic” => ‘S’ var = RubyCurses::Label.new @form, => $results, “row” => r, “col” => fc
456 457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/rbcurse/app.rb', line 456 def label *args events = block_event = nil config = {} _process_args args, config, block_event, events config[:text] ||= config[:name] config[:height] ||= 1 config.delete(:title) _position(config) label = Label.new @form, config # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited return label end |
#link(*args, &block) ⇒ Object
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 |
# File 'lib/rbcurse/app.rb', line 744 def link *args, &block require 'rbcurse/extras/rlink' config = {} events = [ :PRESS, :LEAVE, :ENTER ] block_event = :PRESS _process_args args, config, block_event, events _position(config) config[:text] ||= config.delete :title config[:highlight_foreground] = "yellow" config[:highlight_background] = "red" toggle = Link.new @form, config if block toggle.bind(block_event, toggle, &block) end return toggle end |
#list_box(*args, &block) ⇒ Object
create a list Since we are mouseless, one can traverse without selection. So we have a different way of selecting row/s and traversal. XXX this aspect of LB’s has always troubled me hugely.
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/rbcurse/app.rb', line 490 def list_box *args, &block config = {} # TODO confirm events # listdataevent has interval added and interval removed, due to multiple # selection, we have to make that simple for user here. events = [ :LEAVE, :ENTER, :ENTER_ROW, :LEAVE_ROW, :LIST_DATA_EVENT ] # TODO how to do this so he gets selected row easily block_event = :ENTER_ROW _process_args args, config, block_event, events # naive defaults, since list could be large or have very long items # usually user will provide if !config.has_key? :height ll = 0 ll = config[:list].length + 2 if config.has_key? :list config[:height] ||= ll config[:height] = 15 if config[:height] > 20 end if @current_object.empty? $log.debug "1 APP LB w: #{config[:width]} ,#{config[:name]} " config[:width] ||= @stack.last.width if @stack.last $log.debug "2 APP LB w: #{config[:width]} " config[:width] ||= longest_in_list(config[:list])+2 $log.debug "3 APP LB w: #{config[:width]} " end # if no width given, expand to flows width XXX SHOULD BE NOT EXPAND ? #config[:width] ||= @stack.last.width if @stack.last #if config.has_key? :choose config[:default_values] = config.delete :choose # we make the default single unless specified config[:selection_mode] = :single unless config.has_key? :selection_mode if @current_object.empty? if @instack # most likely you won't have row and col. should we check or just go ahead col = @stack.last.margin config[:row] = @app_row config[:col] = col @app_row += config[:height] # this needs to take into account height of prev object end end useform = nil useform = @form if @current_object.empty? field = Listbox.new useform, config # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited if block # this way you can't pass params to the block field.bind(block_event, &block) end return field end |
#logger ⇒ Object
# trying without 2011-10-8
require 'rbcurse/extras/stdscrwindow'
awin = StdscrWindow.new
$tt.window = awin; $tt. =
127 |
# File 'lib/rbcurse/app.rb', line 127 def logger; return $log; end |
#loop(&block) ⇒ Object
not sure, but user shuld be able to trap keystrokes if he wants but do i still call handle_key if he does, or give him total control. But loop is already called by framework
144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/rbcurse/app.rb', line 144 def loop &block @form.repaint @window.wrefresh Ncurses::Panel.update_panels while((ch = @window.getchar()) != @quit_key ) str = keycode_tos ch @keyblock.call(str.gsub(/-/, "_").to_sym) if @keyblock $log.debug "#{ch} got (#{str})" yield ch if block # <<<---- @form.handle_key ch @form.repaint @window.wrefresh end end |
#master_detail(*args, &block) ⇒ Object
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 |
# File 'lib/rbcurse/app.rb', line 899 def master_detail *args, &block require 'rbcurse/extras/masterdetail' config = {} events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ] block_event = nil _process_args args, config, block_event, events #config[:height] ||= 10 _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last #config.delete :title useform = nil useform = @form if @current_object.empty? w = MasterDetail.new useform, config # NO BLOCK GIVEN if block_given? @current_object << w yield_or_eval &block @current_object.pop end return w end |
#menubar(&block) ⇒ Object
menu bar
705 706 707 708 |
# File 'lib/rbcurse/app.rb', line 705 def &block require 'rbcurse/rmenu' RubyCurses::MenuBar.new &block end |
#menulink(*args, &block) ⇒ Object
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 |
# File 'lib/rbcurse/app.rb', line 760 def *args, &block require 'rbcurse/extras/rmenulink' config = {} events = [ :PRESS, :LEAVE, :ENTER ] block_event = :PRESS _process_args args, config, block_event, events _position(config) config[:text] ||= config.delete :title config[:highlight_foreground] = "yellow" config[:highlight_background] = "red" toggle = MenuLink.new @form, config if block toggle.bind(block_event, toggle, &block) end return toggle end |
#message(text) ⇒ Object
updates a global var with text. Calling app has to set up a Variable with that name and attach to a label so it can be printed.
186 187 188 189 |
# File 'lib/rbcurse/app.rb', line 186 def text .value = text # trying out 2011-10-9 .value = text end |
#message_immediate(text) ⇒ Object
during a process, when you wish to update status, since ordinarily the thread is busy and form does not get control back, so the window won’t refresh. NOTE: use this only if message is not working XXX Not sure if this is working after move to ffi-ncurses, check the demos
198 199 200 201 202 203 204 205 |
# File 'lib/rbcurse/app.rb', line 198 def text .value = text # trying out 2011-10-9 user needs to use in statusline command text if .repaint @window.refresh end end |
#message_row(row) ⇒ Object
190 191 192 193 |
# File 'lib/rbcurse/app.rb', line 190 def row raise "Please use create_message_label first as message_label is no longer default behaviour" unless .row = row end |
#multisplit(*args, &block) ⇒ Object
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 |
# File 'lib/rbcurse/app.rb', line 801 def multisplit *args, &block require 'rbcurse/rmultisplit' config = {} events = [ :PROPERTY_CHANGE, :LEAVE, :ENTER ] block_event = events[0] _process_args args, config, block_event, events _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last config.delete :title useform = nil useform = @form if @current_object.empty? w = MultiSplit.new useform, config #if block #w.bind(block_event, w, &block) #end if block_given? @current_object << w #instance_eval &block if block_given? yield w @current_object.pop end return w end |
#progress(*args, &block) ⇒ Object
progress bar
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/rbcurse/app.rb', line 637 def progress *args, &block require 'rbcurse/rprogress' config = {} # TODO confirm events many more events = [ :CHANGE, :LEAVE, :ENTER ] block_event = nil _process_args args, config, block_event, events config[:width] = config[:display_length] || 10 unless config.has_key? :width _position(config) w = Progress.new @form, config #if block #w.bind(block_event, &block) #end return w end |
#radio(*args, &block) ⇒ Object
radio button
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
# File 'lib/rbcurse/app.rb', line 572 def radio *args, &block config = {} # TODO confirm events events = [ :PRESS, :LEAVE, :ENTER ] block_event = :PRESS _process_args args, config, block_event, events a = config[:group] # FIXME we should check if user has set a varialbe in :variable. # we should create a variable, so he can use it if he wants. if @variables.has_key? a v = @variables[a] else v = Variable.new @variables[a] = v end config[:variable] = v config.delete(:group) _position(config) radio = RadioButton.new @form, config if block radio.bind(block_event, &block) end return radio end |
#raw_message(text) ⇒ Object
since it uses stdscr. Use say_with_pause or use rdialogs status_window, see test2.rb
NOTE XXX using stdscr results in the screen going black if a dialog or other window is popped up, this was great but has not worked out. print directly onto stdscr so that form or window does not require repainting and cursor not messed. however, once form paints then this will be overwritten so at end of printing raw_messages, use message() for final status. Usage: application is inside a long processing loop and wishes to print ongoing status (similar to message_immediate) but faster and less involved
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/rbcurse/app.rb', line 214 def text $log.warn "WARNING: don't use this method as it uses stdscr. Use rdialogs statuswindow." row = ? .row : Ncurses.LINES-1 # experimentally trying stdscr instead of label scr = FFI::NCurses.stdscr text = "%-80s" % text Ncurses.mvprintw row ,0, text #@_stext ||= "" #@_stext << text ## appending is quite a pain, maybe we should make it separate. #stext = "%-80s" % @_stext #Ncurses.mvprintw row ,0, stext[-80..-1] #scr.refresh() # NW w FFI XXX #FFI::NCurses.refresh end |
#raw_progress(arg) ⇒ Object
-
don’t use stdscr at all, use rdialogs status_window (see test2.rb)
shows a simple progress bar on last row, using stdscr If Array of two numbers is given then also print part/total on left of bar
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/rbcurse/app.rb', line 233 def raw_progress arg $log.warning "WARNING: don't use this method as it uses stdscr" row = ? .row : Ncurses.LINES-1 s = nil case arg when Array #calculate percentage pc = (arg[0]*1.0)/arg[1] # print items/total also s = "%-10s" % "(#{arg[0]}/#{arg[1]})" when Float pc = arg end scr = Ncurses.stdscr endcol = Ncurses.COLS-1 startcol = endcol - 12 stext = ("=" * (pc*10).to_i) text = "[" + "%-10s" % stext + "]" Ncurses.mvprintw( row ,startcol-10, s) if s Ncurses.mvprintw row ,startcol, text #scr.refresh() # XXX FFI NW end |
#safe_loop(&block) ⇒ Object
if calling loop separately better to call this, since it will shut off ncurses and print error on screen.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/rbcurse/app.rb', line 160 def safe_loop &block begin loop &block rescue => ex $log.debug( "APP.rb rescue reached ") $log.debug( ex) if ex $log.debug(ex.backtrace.join("\n")) if ex ensure close # putting it here allows it to be printed on screen, otherwise it was not showing at all. if ex puts "========== EXCEPTION ==========" p ex puts "===============================" puts(ex.backtrace.join("\n")) end end end |
#scrollbar(*args, &block) ⇒ Object
scrollbar attached to the right of a parent object
946 947 948 949 950 951 952 953 954 955 956 |
# File 'lib/rbcurse/app.rb', line 946 def *args, &block require 'rbcurse/extras/scrollbar' config = {} events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ] # # none really at present block_event = nil _process_args args, config, block_event, events raise "parent needed for scrollbar" if !config.has_key? :parent useform = nil useform = @form if @current_object.empty? sb = .new useform, config end |
#splitpane(*args, &block) ⇒ Object
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
# File 'lib/rbcurse/app.rb', line 776 def splitpane *args, &block require 'rbcurse/rsplitpane2' config = {} events = [ :PROPERTY_CHANGE, :LEAVE, :ENTER ] block_event = events[0] _process_args args, config, block_event, events _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last config.delete :title useform = nil useform = @form if @current_object.empty? w = SplitPane.new useform, config #if block #w.bind(block_event, w, &block) #end if block_given? @current_object << w #instance_eval &block if block_given? yield w @current_object.pop end return w end |
#stack(config = {}, &block) ⇒ Object
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 |
# File 'lib/rbcurse/app.rb', line 1004 def stack config={}, &block @instack = true mt = config[:margin_top] || 1 mr = config[:margin] || 0 # must take into account margin defw = Ncurses.COLS - mr config[:width] = defw if config[:width] == :EXPAND w = config[:width] || [50, defw].min s = Stack.new(mt, mr, w) @app_row += mt mr += @stack.last.margin if @stack.last #@stack << mr @stack << s #instance_eval &block if block_given? yield_or_eval &block if block_given? # modified 2010-11-17 20:36 @stack.pop @instack = false if @stack.empty? @app_row = 0 if @stack.empty? end |
#subtitle(string, config = {}) ⇒ Object
print a sutitle on second row
701 702 703 |
# File 'lib/rbcurse/app.rb', line 701 def subtitle string, config={} @window.printstring 2, 30, string, $datacolor, 'normal' end |
#suspend(clear = true) ⇒ Object
suspends curses so you can play around on the shell or in cooked mode like Vim does. Expects a block to be passed. Purpose: you can print some stuff without creating a window, or just run shell commands without coming out. NOTE: if you pass clear as true, then the screen will be cleared and you can use puts or print to print. You may have to flush. However, with clear as false, the screen will not be cleared. You will have to print using printw, and if you expect user input you must do a “system /bin/stty sane” If you print stuff, you will have to put a getch() or system(“read”) to pause the screen.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/rbcurse/app.rb', line 273 def suspend clear=true return unless block_given? Ncurses.def_prog_mode if clear Ncurses.endwin # NOTE: avoid false since screen remains half off # too many issues else system "/bin/stty sane" end yield if block_given? Ncurses.reset_prog_mode if !clear # Hope we don't screw your terminal up with this constantly. VER::stop_ncurses VER::start_ncurses #@form.reset_all # not required end @form.repaint @window.wrefresh Ncurses::Panel.update_panels end |
#table(*args, &block) ⇒ Object
table widget
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 |
# File 'lib/rbcurse/app.rb', line 660 def table *args, &block require 'rbcurse/rtable' config = {} # TODO confirm events many more events = [ :ENTER_ROW, :LEAVE, :ENTER ] block_event = events[0] _process_args args, config, block_event, events # if user is leaving out width, then we don't want it in config # else Widget will put a value of 10 as default, overriding what we've calculated if config.has_key? :display_length config[:width] = config[:display_length] unless config.has_key? :width end ext = config.delete :extended_keys model = nil _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last w = Table.new @form, config if ext require 'rbcurse/extras/tableextended' # so we can increase and decrease column width using keys w.extend TableExtended w.bind_key(?w){ w.next_column } w.bind_key(?b){ w.previous_column } w.bind_key(?+) { w.increase_column } w.bind_key(?-) { w.decrease_column } w.bind_key([?d, ?d]) { w.table_model.delete_at w.current_index } w.bind_key(?u) { w.table_model.undo w.current_index} end if block w.bind(block_event, &block) end return w end |
#tabular_widget(*args, &block) ⇒ Object
creates a simple readonly table, that allows users to click on rows and also on the header. Header clicking is for column-sorting.
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 |
# File 'lib/rbcurse/app.rb', line 923 def *args, &block require 'rbcurse/extras/tabularwidget' config = {} events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ] block_event = nil _process_args args, config, block_event, events config[:height] ||= 10 # not sure if this should be here _position(config) # if no width given, expand to stack width config[:width] ||= @stack.last.width if @stack.last #config.delete :title useform = nil useform = @form if @current_object.empty? w = TabularWidget.new useform, config # NO BLOCK GIVEN if block_given? @current_object << w yield_or_eval &block @current_object.pop end return w end |
#textarea(*args, &block) ⇒ Object
editable text area
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 |
# File 'lib/rbcurse/app.rb', line 597 def textarea *args, &block require 'rbcurse/rtextarea' config = {} # TODO confirm events many more events = [ :CHANGE, :LEAVE, :ENTER ] block_event = events[0] _process_args args, config, block_event, events config[:width] = config[:display_length] unless config.has_key? :width _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last useform = nil useform = @form if @current_object.empty? w = TextArea.new useform, config if block w.bind(block_event, &block) end return w end |
#textview(*args, &block) ⇒ Object
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
# File 'lib/rbcurse/app.rb', line 616 def textview *args, &block require 'rbcurse/rtextview' config = {} # TODO confirm events many more events = [ :PRESS, :LEAVE, :ENTER ] block_event = events[0] _process_args args, config, block_event, events config[:width] = config[:display_length] unless config.has_key? :width _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last raise "height needed for textview" if !config.has_key? :height useform = nil useform = @form if @current_object.empty? w = TextView.new useform, config if block w.bind(block_event, &block) end return w end |
#title(string, config = {}) ⇒ Object
print a title on first row
696 697 698 699 |
# File 'lib/rbcurse/app.rb', line 696 def title string, config={} ## TODO center it @window.printstring 1, 30, string, $normalcolor, 'reverse' end |
#toggle(*args, &block) ⇒ Object
toggle button
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 |
# File 'lib/rbcurse/app.rb', line 542 def toggle *args, &block config = {} # TODO confirm events events = [ :PRESS, :LEAVE, :ENTER ] block_event = :PRESS _process_args args, config, block_event, events config[:text] ||= longest_in_list2( [config[:onvalue], config[:offvalue]]) #config[:onvalue] # needed for flow, we need a better way FIXME _position(config) toggle = ToggleButton.new @form, config if block toggle.bind(block_event, &block) end return toggle end |
#tree(*args, &block) ⇒ Object
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
# File 'lib/rbcurse/app.rb', line 826 def tree *args, &block require 'rbcurse/rtree' config = {} events = [:TREE_WILL_EXPAND_EVENT, :TREE_EXPANDED_EVENT, :TREE_SELECTION_EVENT, :PROPERTY_CHANGE, :LEAVE, :ENTER ] block_event = nil _process_args args, config, block_event, events config[:height] ||= 10 _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last #config.delete :title useform = nil useform = @form if @current_object.empty? w = Tree.new useform, config, &block return w end |
#vimsplit(*args, &block) ⇒ Object
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 |
# File 'lib/rbcurse/app.rb', line 843 def vimsplit *args, &block require 'rbcurse/rvimsplit' config = {} #TODO check these events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ] block_event = nil _process_args args, config, block_event, events config[:height] ||= 10 _position(config) # if no width given, expand to flows width config[:width] ||= @stack.last.width if @stack.last #config.delete :title useform = nil useform = @form if @current_object.empty? w = VimSplit.new useform, config # NO BLOCK GIVEN if block_given? @current_object << w #instance_eval &block if block_given? yield w @current_object.pop end return w end |