canis 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/CHANGES +52 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +2 -0
- data/canis.gemspec +25 -0
- data/examples/alpmenu.rb +46 -0
- data/examples/app.sample +19 -0
- data/examples/appemail.rb +191 -0
- data/examples/atree.rb +105 -0
- data/examples/bline.rb +181 -0
- data/examples/common/devel.rb +319 -0
- data/examples/common/file.rb +93 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +59 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +16 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +506 -0
- data/examples/dirtree.rb +177 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +212 -0
- data/examples/tasks.rb +179 -0
- data/examples/term2.rb +88 -0
- data/examples/testbuttons.rb +307 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testdb.rb +182 -0
- data/examples/testfields.rb +208 -0
- data/examples/testflowlayout.rb +43 -0
- data/examples/testkeypress.rb +98 -0
- data/examples/testlistbox.rb +187 -0
- data/examples/testlistbox1.rb +199 -0
- data/examples/testmessagebox.rb +144 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +107 -0
- data/examples/testsplitlayout.rb +53 -0
- data/examples/testsplitlayout1.rb +49 -0
- data/examples/teststacklayout.rb +48 -0
- data/examples/testwsshortcuts.rb +68 -0
- data/examples/testwsshortcuts2.rb +129 -0
- data/lib/canis.rb +16 -0
- data/lib/canis/core/docs/index.txt +104 -0
- data/lib/canis/core/docs/list.txt +16 -0
- data/lib/canis/core/docs/style_help.yml +34 -0
- data/lib/canis/core/docs/tabbedpane.txt +15 -0
- data/lib/canis/core/docs/table.txt +31 -0
- data/lib/canis/core/docs/textpad.txt +48 -0
- data/lib/canis/core/docs/tree.txt +23 -0
- data/lib/canis/core/include/.DS_Store +0 -0
- data/lib/canis/core/include/action.rb +83 -0
- data/lib/canis/core/include/actionmanager.rb +49 -0
- data/lib/canis/core/include/appmethods.rb +179 -0
- data/lib/canis/core/include/bordertitle.rb +49 -0
- data/lib/canis/core/include/canisparser.rb +100 -0
- data/lib/canis/core/include/colorparser.rb +437 -0
- data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
- data/lib/canis/core/include/io.rb +320 -0
- data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
- data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
- data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
- data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
- data/lib/canis/core/include/listbindings.rb +89 -0
- data/lib/canis/core/include/listeditable.rb +319 -0
- data/lib/canis/core/include/listoperations.rb +61 -0
- data/lib/canis/core/include/listselectionmodel.rb +388 -0
- data/lib/canis/core/include/multibuffer.rb +173 -0
- data/lib/canis/core/include/ractionevent.rb +73 -0
- data/lib/canis/core/include/rchangeevent.rb +27 -0
- data/lib/canis/core/include/rhistory.rb +95 -0
- data/lib/canis/core/include/rinputdataevent.rb +47 -0
- data/lib/canis/core/include/textdocument.rb +111 -0
- data/lib/canis/core/include/vieditable.rb +175 -0
- data/lib/canis/core/include/widgetmenu.rb +66 -0
- data/lib/canis/core/system/colormap.rb +165 -0
- data/lib/canis/core/system/keydefs.rb +32 -0
- data/lib/canis/core/system/ncurses.rb +237 -0
- data/lib/canis/core/system/panel.rb +129 -0
- data/lib/canis/core/system/window.rb +1081 -0
- data/lib/canis/core/util/ansiparser.rb +119 -0
- data/lib/canis/core/util/app.rb +696 -0
- data/lib/canis/core/util/basestack.rb +412 -0
- data/lib/canis/core/util/defaultcolorparser.rb +84 -0
- data/lib/canis/core/util/extras/README +5 -0
- data/lib/canis/core/util/extras/bottomline.rb +1815 -0
- data/lib/canis/core/util/extras/padreader.rb +192 -0
- data/lib/canis/core/util/focusmanager.rb +31 -0
- data/lib/canis/core/util/helpmanager.rb +160 -0
- data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
- data/lib/canis/core/util/promptmenu.rb +235 -0
- data/lib/canis/core/util/rcommandwindow.rb +933 -0
- data/lib/canis/core/util/rdialogs.rb +520 -0
- data/lib/canis/core/util/textutils.rb +74 -0
- data/lib/canis/core/util/viewer.rb +238 -0
- data/lib/canis/core/util/widgetshortcuts.rb +508 -0
- data/lib/canis/core/widgets/applicationheader.rb +103 -0
- data/lib/canis/core/widgets/box.rb +58 -0
- data/lib/canis/core/widgets/divider.rb +310 -0
- data/lib/canis/core/widgets/extras/README.md +12 -0
- data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
- data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
- data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
- data/lib/canis/core/widgets/listbox.rb +326 -0
- data/lib/canis/core/widgets/listfooter.rb +86 -0
- data/lib/canis/core/widgets/rcombo.rb +210 -0
- data/lib/canis/core/widgets/rcontainer.rb +415 -0
- data/lib/canis/core/widgets/rlink.rb +30 -0
- data/lib/canis/core/widgets/rmenu.rb +970 -0
- data/lib/canis/core/widgets/rmenulink.rb +30 -0
- data/lib/canis/core/widgets/rmessagebox.rb +400 -0
- data/lib/canis/core/widgets/rprogress.rb +118 -0
- data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
- data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/canis/core/widgets/rwidget.rb +3634 -0
- data/lib/canis/core/widgets/scrollbar.rb +147 -0
- data/lib/canis/core/widgets/statusline.rb +113 -0
- data/lib/canis/core/widgets/table.rb +1072 -0
- data/lib/canis/core/widgets/tabular.rb +264 -0
- data/lib/canis/core/widgets/textpad.rb +1674 -0
- data/lib/canis/core/widgets/tree.rb +690 -0
- data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
- data/lib/canis/version.rb +3 -0
- metadata +229 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
|
2
|
+
# File: colorparser.rb
|
|
3
|
+
# Description: Default parse for our tmux format
|
|
4
|
+
# The aim is to be able to specify parsers so different kinds
|
|
5
|
+
# of formatting or documents can be used, such as ANSI formatted
|
|
6
|
+
# manpages.
|
|
7
|
+
# Author: jkepler http://github.com/mare-imbrium/canis/
|
|
8
|
+
# Date: 07.11.11 - 13:17
|
|
9
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
10
|
+
# Last update: 2013-04-01 13:43
|
|
11
|
+
# ----------------------------------------------------------------------------- #
|
|
12
|
+
# == TODO
|
|
13
|
+
# - perhaps we can compile the regexp once and reuse
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
module Canis
|
|
17
|
+
class AnsiParser
|
|
18
|
+
|
|
19
|
+
# NOTE: Experimental and minimal
|
|
20
|
+
# parses the formatted string and yields either an array of color, bgcolor and attrib
|
|
21
|
+
# or the text. This will be called by convert_to_chunk.
|
|
22
|
+
#
|
|
23
|
+
# Currently, assumes colors and attributes are correct. No error checking or fancy stuff.
|
|
24
|
+
# s="#[fg=green]hello there#[fg=yellow, bg=black, dim]"
|
|
25
|
+
# @since 1.4.1 2011-11-3 experimental, can change
|
|
26
|
+
# @return [nil] knows nothign about output format.
|
|
27
|
+
|
|
28
|
+
def parse_format s # yields attribs or text
|
|
29
|
+
## set default colors
|
|
30
|
+
color = :white
|
|
31
|
+
bgcolor = :black
|
|
32
|
+
attrib = FFI::NCurses::A_NORMAL
|
|
33
|
+
text = ""
|
|
34
|
+
|
|
35
|
+
## split #[...]
|
|
36
|
+
#a = s.split /(#\[[^\]]*\])/
|
|
37
|
+
a = s.split /(\x1b\[\d*(?:;\d+)*?[a-zA-Z])/
|
|
38
|
+
a.each { |e|
|
|
39
|
+
## process color or attrib portion
|
|
40
|
+
#[ "", "\e[1m", "", "\e[34m", "", "\e[47m", "Showing all items...", "\e[0m", "", "\e[0m", "\n"]
|
|
41
|
+
if e[0,1] == "\x1b" && e[-1,1] == "m"
|
|
42
|
+
|
|
43
|
+
#e.each { |f| x=/^.\[(.*).$/.match(f)
|
|
44
|
+
$log.debug "XXX: ANSI e #{e} "
|
|
45
|
+
x=/^.\[(.*).$/.match(e)
|
|
46
|
+
color, bgcolor, attrib = nil, nil, nil
|
|
47
|
+
$log.debug "XXX: ANSI #{x} ..... #{x[1]} "
|
|
48
|
+
args = x[1].split ';'
|
|
49
|
+
## first split on commas to separate fg, bg and attr
|
|
50
|
+
# http://ascii-table.com/ansi-escape-sequences.php
|
|
51
|
+
args.each { |att|
|
|
52
|
+
$log.debug "XXX: ANSI att: #{att} "
|
|
53
|
+
case att.to_i
|
|
54
|
+
when 0
|
|
55
|
+
color, bgcolor, attrib = nil, nil, nil
|
|
56
|
+
yield :reset # actually this resets all so we need an endall or clearall reset
|
|
57
|
+
|
|
58
|
+
when 1
|
|
59
|
+
attrib = 'bold'
|
|
60
|
+
when 2
|
|
61
|
+
attrib = 'dim'
|
|
62
|
+
when 4
|
|
63
|
+
attrib = 'underline'
|
|
64
|
+
when 5
|
|
65
|
+
attrib = 'blink'
|
|
66
|
+
when 7
|
|
67
|
+
attrib = 'reverse'
|
|
68
|
+
when 8
|
|
69
|
+
attrib = 'hidden' # XXX
|
|
70
|
+
when 30
|
|
71
|
+
color = 'black'
|
|
72
|
+
when 31
|
|
73
|
+
color = 'red'
|
|
74
|
+
when 32
|
|
75
|
+
color = 'green'
|
|
76
|
+
when 33
|
|
77
|
+
color = 'yellow'
|
|
78
|
+
when 34
|
|
79
|
+
color = 'blue'
|
|
80
|
+
when 35
|
|
81
|
+
color = 'magenta'
|
|
82
|
+
when 36
|
|
83
|
+
color = 'cyan'
|
|
84
|
+
when 37
|
|
85
|
+
color = 'white'
|
|
86
|
+
|
|
87
|
+
#Background colors
|
|
88
|
+
when 40
|
|
89
|
+
bgcolor = 'black'
|
|
90
|
+
when 41
|
|
91
|
+
bgcolor = 'red'
|
|
92
|
+
when 42
|
|
93
|
+
bgcolor = 'green'
|
|
94
|
+
when 43
|
|
95
|
+
bgcolor = 'yellow'
|
|
96
|
+
when 44
|
|
97
|
+
bgcolor = 'blue'
|
|
98
|
+
when 45
|
|
99
|
+
bgcolor = 'magenta'
|
|
100
|
+
when 46
|
|
101
|
+
bgcolor = 'cyan'
|
|
102
|
+
when 47
|
|
103
|
+
bgcolor = 'white'
|
|
104
|
+
else
|
|
105
|
+
$log.warn "XXX: WARN ANSI not used #{att} "
|
|
106
|
+
end
|
|
107
|
+
} # args.ea
|
|
108
|
+
#} # e.each
|
|
109
|
+
$log.debug "XXX: ANSI YIELDING #{color} , #{bgcolor} , #{attrib} "
|
|
110
|
+
yield [color,bgcolor,attrib] if block_given?
|
|
111
|
+
else
|
|
112
|
+
text = e
|
|
113
|
+
yield text if block_given?
|
|
114
|
+
end
|
|
115
|
+
} # a.each
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
* Name: App
|
|
3
|
+
* Description: Experimental Application class
|
|
4
|
+
* Author: jkepler (ABCD)
|
|
5
|
+
* file created 2010-09-04 22:10
|
|
6
|
+
Todo:
|
|
7
|
+
|
|
8
|
+
* 1.5.0 : redo the constructors of these widgets
|
|
9
|
+
as per stack flow improved, and make the constructor
|
|
10
|
+
simpler, no need for jugglery of row col etc. let user
|
|
11
|
+
specify in config.
|
|
12
|
+
--------
|
|
13
|
+
* License:
|
|
14
|
+
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
15
|
+
|
|
16
|
+
=end
|
|
17
|
+
require 'logger'
|
|
18
|
+
require 'canis'
|
|
19
|
+
require 'canis/core/util/widgetshortcuts'
|
|
20
|
+
|
|
21
|
+
include Canis
|
|
22
|
+
include Canis::Utils
|
|
23
|
+
include Io
|
|
24
|
+
module Canis
|
|
25
|
+
extend self
|
|
26
|
+
##
|
|
27
|
+
#
|
|
28
|
+
# @since 1.2.0
|
|
29
|
+
# TODO -
|
|
30
|
+
# / combo
|
|
31
|
+
# - popup
|
|
32
|
+
# - promptmenu
|
|
33
|
+
# - stack and flow should be objects in Form/App?, put in widget when creating
|
|
34
|
+
# - box / rect
|
|
35
|
+
# - para looks like a label that is more than one line, and calculates rows itself based on text
|
|
36
|
+
# - multicontainer
|
|
37
|
+
# - multitextview, multisplit
|
|
38
|
+
# - tabbedpane
|
|
39
|
+
# / table - more work regarding vim keys, also editable
|
|
40
|
+
# - margin - is left offset
|
|
41
|
+
# http://lethain.com/entry/2007/oct/15/getting-started-shoes-os-x/
|
|
42
|
+
#
|
|
43
|
+
|
|
44
|
+
# 2014-04-17 - 13:15 XXX are these used. required ???
|
|
45
|
+
class Widget
|
|
46
|
+
def changed *args, &block
|
|
47
|
+
bind :CHANGED, *args, &block
|
|
48
|
+
end
|
|
49
|
+
def leave *args, &block
|
|
50
|
+
bind :LEAVE, *args, &block
|
|
51
|
+
end
|
|
52
|
+
def enter *args, &block
|
|
53
|
+
bind :ENTER, *args, &block
|
|
54
|
+
end
|
|
55
|
+
# actually we already have command() for buttons
|
|
56
|
+
def click *args, &block
|
|
57
|
+
bind :PRESS, *args, &block
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
class CheckBox
|
|
61
|
+
# a little dicey XXX
|
|
62
|
+
def text(*val)
|
|
63
|
+
if val.empty?
|
|
64
|
+
@value ? @onvalue : @offvalue
|
|
65
|
+
else
|
|
66
|
+
super
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
# This is the Application class which does the job of setting up the
|
|
71
|
+
# environment, and closing it at the end.
|
|
72
|
+
class App
|
|
73
|
+
include Canis::WidgetShortcuts
|
|
74
|
+
attr_reader :config
|
|
75
|
+
attr_reader :form
|
|
76
|
+
attr_reader :window
|
|
77
|
+
attr_writer :quit_key
|
|
78
|
+
# the row on which to prompt user for any inputs
|
|
79
|
+
#attr_accessor :prompt_row # 2011-10-17 14:06:22
|
|
80
|
+
|
|
81
|
+
# TODO: i should be able to pass window coords here in config
|
|
82
|
+
# :title
|
|
83
|
+
def initialize config={}, &block
|
|
84
|
+
@config = config
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
widget_shortcuts_init
|
|
88
|
+
@variables = {}
|
|
89
|
+
# if we are creating child objects then we will not use outer form. this object will manage
|
|
90
|
+
@current_object = []
|
|
91
|
+
@_system_commands = %w{ bind_global bind_component field_help_text }
|
|
92
|
+
|
|
93
|
+
init_vars
|
|
94
|
+
$log.debug "XXX APP CONFIG: #{@config} " if $log.debug?
|
|
95
|
+
run &block
|
|
96
|
+
end
|
|
97
|
+
def init_vars
|
|
98
|
+
@quit_key ||= FFI::NCurses::KEY_F10
|
|
99
|
+
# actually this should be maintained inside ncurses pack, so not loaded 2 times.
|
|
100
|
+
# this way if we call an app from existing program, App won't start ncurses.
|
|
101
|
+
unless $ncurses_started
|
|
102
|
+
init_ncurses
|
|
103
|
+
end
|
|
104
|
+
$lastline = Ncurses.LINES - 1
|
|
105
|
+
#@message_row = Ncurses.LINES-1
|
|
106
|
+
#@prompt_row = @message_row # hope to use for ask etc # 2011-10-17 14:06:27
|
|
107
|
+
unless $log
|
|
108
|
+
logpath=ENV["CANIS_LOG_PATH"]
|
|
109
|
+
$log = create_logger(logpath || "/dev/null")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
def logger; return $log; end
|
|
113
|
+
def close
|
|
114
|
+
$log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} "
|
|
115
|
+
@window.destroy if !@window.nil?
|
|
116
|
+
$log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} "
|
|
117
|
+
if @stop_ncurses_on_close
|
|
118
|
+
Canis::stop_ncurses
|
|
119
|
+
$log.debug " CLOSING NCURSES"
|
|
120
|
+
end
|
|
121
|
+
$log.debug " CLOSING APP"
|
|
122
|
+
end
|
|
123
|
+
# not sure, but user shuld be able to trap keystrokes if he wants
|
|
124
|
+
# but do i still call handle_key if he does, or give him total control.
|
|
125
|
+
# But loop is already called by framework
|
|
126
|
+
def loop &block
|
|
127
|
+
@form.repaint
|
|
128
|
+
@window.wrefresh
|
|
129
|
+
Ncurses::Panel.update_panels
|
|
130
|
+
@break_key = ?\C-q.getbyte(0)
|
|
131
|
+
# added this extra loop since from some places we exit using throw :close
|
|
132
|
+
# amd that was in a much higher place, and was getting us right out, with
|
|
133
|
+
# no chance of user canceling quit. This extra loop allows us to remain
|
|
134
|
+
# added on 2011-11-24
|
|
135
|
+
while true
|
|
136
|
+
catch :close do
|
|
137
|
+
while((ch = @window.getchar()) != 999 )
|
|
138
|
+
#break if ch == @break_key
|
|
139
|
+
if ch == @break_key || ch == @quit_key
|
|
140
|
+
#stopping = @window.fire_close_handler
|
|
141
|
+
#break if stopping.nil? || stopping
|
|
142
|
+
break
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
if @keyblock
|
|
146
|
+
str = keycode_tos ch
|
|
147
|
+
@keyblock.call(str.gsub(/-/, "_").to_sym) # not used ever
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
yield ch if block # <<<----
|
|
151
|
+
# this is what the user should have control ove. earlier we would put this in
|
|
152
|
+
# a try catch block so user could do what he wanted with the error. Now we
|
|
153
|
+
# need to get it to him somehow, perhaps through a block or on_error event
|
|
154
|
+
begin
|
|
155
|
+
@form.handle_key ch
|
|
156
|
+
rescue => err
|
|
157
|
+
$log.debug( "handle_key rescue reached ")
|
|
158
|
+
$log.debug( err.to_s)
|
|
159
|
+
$log.debug(err.backtrace.join("\n"))
|
|
160
|
+
textdialog [err.to_s, *err.backtrace], :title => "Exception"
|
|
161
|
+
end
|
|
162
|
+
#@form.repaint # was this duplicate ?? handle calls repaint not needed
|
|
163
|
+
@window.wrefresh
|
|
164
|
+
end
|
|
165
|
+
end # catch
|
|
166
|
+
stopping = @window.fire_close_handler
|
|
167
|
+
@window.wrefresh
|
|
168
|
+
break if stopping.nil? || stopping
|
|
169
|
+
end # while
|
|
170
|
+
end
|
|
171
|
+
# if calling loop separately better to call this, since it will shut off ncurses
|
|
172
|
+
# and print error on screen.
|
|
173
|
+
def safe_loop &block
|
|
174
|
+
begin
|
|
175
|
+
loop &block
|
|
176
|
+
rescue => ex
|
|
177
|
+
$log.debug( "APP.rb rescue reached ")
|
|
178
|
+
$log.debug( ex) if ex
|
|
179
|
+
$log.debug(ex.backtrace.join("\n")) if ex
|
|
180
|
+
ensure
|
|
181
|
+
close
|
|
182
|
+
# putting it here allows it to be printed on screen, otherwise it was not showing at all.
|
|
183
|
+
if ex
|
|
184
|
+
puts "========== EXCEPTION =========="
|
|
185
|
+
p ex
|
|
186
|
+
puts "==============================="
|
|
187
|
+
puts(ex.backtrace.join("\n"))
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
# returns a symbol of the key pressed
|
|
192
|
+
# e.g. :C_c for Ctrl-C
|
|
193
|
+
# :Space, :bs, :M_d etc
|
|
194
|
+
def keypress &block
|
|
195
|
+
@keyblock = block
|
|
196
|
+
end
|
|
197
|
+
# updates a global var with text. Calling app has to set up a Variable with that name and attach to
|
|
198
|
+
# a label so it can be printed.
|
|
199
|
+
def message text
|
|
200
|
+
$status_message.value = text # trying out 2011-10-9
|
|
201
|
+
#@message.value = text # 2011-10-17 14:07:01
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# used only by LiveConsole, if enables in an app, usually only during testing.
|
|
205
|
+
def get_binding
|
|
206
|
+
return binding()
|
|
207
|
+
end
|
|
208
|
+
#
|
|
209
|
+
# suspends curses so you can play around on the shell
|
|
210
|
+
# or in cooked mode like Vim does. Expects a block to be passed.
|
|
211
|
+
# Purpose: you can print some stuff without creating a window, or
|
|
212
|
+
# just run shell commands without coming out.
|
|
213
|
+
# NOTE: if you pass clear as true, then the screen will be cleared
|
|
214
|
+
# and you can use puts or print to print. You may have to flush.
|
|
215
|
+
# However, with clear as false, the screen will not be cleared. You
|
|
216
|
+
# will have to print using printw, and if you expect user input
|
|
217
|
+
# you must do a "system /bin/stty sane"
|
|
218
|
+
# If you print stuff, you will have to put a getch() or system("read")
|
|
219
|
+
# to pause the screen.
|
|
220
|
+
def suspend clear=true
|
|
221
|
+
return unless block_given?
|
|
222
|
+
Ncurses.def_prog_mode
|
|
223
|
+
if clear
|
|
224
|
+
Ncurses.endwin
|
|
225
|
+
# NOTE: avoid false since screen remains half off
|
|
226
|
+
# too many issues
|
|
227
|
+
else
|
|
228
|
+
system "/bin/stty sane"
|
|
229
|
+
end
|
|
230
|
+
yield if block_given?
|
|
231
|
+
Ncurses.reset_prog_mode
|
|
232
|
+
if !clear
|
|
233
|
+
# Hope we don't screw your terminal up with this constantly.
|
|
234
|
+
Canis::stop_ncurses
|
|
235
|
+
Canis::start_ncurses
|
|
236
|
+
#@form.reset_all # not required
|
|
237
|
+
end
|
|
238
|
+
@form.repaint
|
|
239
|
+
@window.wrefresh
|
|
240
|
+
Ncurses::Panel.update_panels
|
|
241
|
+
end
|
|
242
|
+
def get_all_commands
|
|
243
|
+
opts = @_system_commands.dup
|
|
244
|
+
if respond_to? :get_commands
|
|
245
|
+
opts.push(*get_commands())
|
|
246
|
+
end
|
|
247
|
+
opts
|
|
248
|
+
end
|
|
249
|
+
# bind a key to a method at global (form) level
|
|
250
|
+
# Note that individual component may be overriding this.
|
|
251
|
+
def bind_global
|
|
252
|
+
opts = get_all_commands
|
|
253
|
+
cmd = rb_gets("Select a command (<tab> for choices) : ", opts)
|
|
254
|
+
if cmd.nil? || cmd == ""
|
|
255
|
+
rb_puts "Aborted."
|
|
256
|
+
return
|
|
257
|
+
end
|
|
258
|
+
key = []
|
|
259
|
+
str = ""
|
|
260
|
+
# the next is fine but does not allow user to enter a control or alt or function character
|
|
261
|
+
# since it uses Field. It is fine if you want to force alphanum input
|
|
262
|
+
ch = rb_getchar("Enter one or two keys. Finish with <ENTER>. Enter first key:")
|
|
263
|
+
unless ch
|
|
264
|
+
rb_puts "Aborted. <Press a key>"
|
|
265
|
+
return
|
|
266
|
+
end
|
|
267
|
+
key << ch
|
|
268
|
+
str << keycode_tos(ch)
|
|
269
|
+
ch = rb_getchar "Got #{str}. Enter second key or hit return:"
|
|
270
|
+
unless ch
|
|
271
|
+
rb_puts "Aborted. <Press a key>"
|
|
272
|
+
return
|
|
273
|
+
end
|
|
274
|
+
if ch == KEY_ENTER || ch == 13
|
|
275
|
+
else
|
|
276
|
+
key << ch
|
|
277
|
+
str << keycode_tos(ch)
|
|
278
|
+
end
|
|
279
|
+
if !key.empty?
|
|
280
|
+
rb_puts "Binding #{cmd} to #{str}. "
|
|
281
|
+
key = key[0] if key.size == 1
|
|
282
|
+
#@form.bind_key(key, cmd.to_sym) # not finding it, getting called by that comp
|
|
283
|
+
@form.bind_key(key){ send(cmd.to_sym) }
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
def bind_component
|
|
287
|
+
#rb_puts "Todo. ", :color_pair => get_color($promptcolor, :red, :black)
|
|
288
|
+
print_error_message "Todo this. "
|
|
289
|
+
# the idea here is to get the current component
|
|
290
|
+
# and bind some keys to some methods.
|
|
291
|
+
# however, how do we divine the methods we can map to
|
|
292
|
+
# and also in some cases the components itself has multiple components
|
|
293
|
+
end
|
|
294
|
+
# displays help_text associated with field. 2011-10-15
|
|
295
|
+
def field_help_text
|
|
296
|
+
f = @form.get_current_field
|
|
297
|
+
if f.respond_to?('help_text')
|
|
298
|
+
h = f.help_text
|
|
299
|
+
h = "No help text defined for this field.\nTry F1, or press '?' for key-bindings." unless h
|
|
300
|
+
textdialog "#{h}", :title => "Widget Help Text"
|
|
301
|
+
else
|
|
302
|
+
alert "Could not get field #{f} or does not respond to helptext. Try F1 or '?'"
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
# prompts user for a command. we need to get this back to the calling app
|
|
306
|
+
# or have some block stuff TODO
|
|
307
|
+
# Actually, this is naive, you would want to pass some values in like current data value
|
|
308
|
+
# or lines ??
|
|
309
|
+
# Also may want command completion, or help so all commands can be displayed
|
|
310
|
+
# NOTE: This is gonna change very soon - 2012-01-8
|
|
311
|
+
def get_command_from_user choices=["quit","help", "suspend", "shell_output"]
|
|
312
|
+
@_command_history ||= Array.new
|
|
313
|
+
str = rb_gets("Cmd: ", choices) { |q| q.default = @_previous_command; q.history = @_command_history }
|
|
314
|
+
@_command_history << str unless @_command_history.include? str
|
|
315
|
+
# shell the command
|
|
316
|
+
if str =~ /^!/
|
|
317
|
+
str = str[1..-1]
|
|
318
|
+
suspend(false) {
|
|
319
|
+
#system(str);
|
|
320
|
+
$log.debug "XXX STR #{str} " if $log.debug?
|
|
321
|
+
|
|
322
|
+
output=`#{str}`
|
|
323
|
+
system("echo ' ' ");
|
|
324
|
+
$log.debug "XXX output #{output} " if $log.debug?
|
|
325
|
+
system("echo '#{output}' ");
|
|
326
|
+
system("echo Press Enter to continue.");
|
|
327
|
+
system("read");
|
|
328
|
+
}
|
|
329
|
+
return nil # i think
|
|
330
|
+
else
|
|
331
|
+
# TODO
|
|
332
|
+
# here's where we can take internal commands
|
|
333
|
+
#alert "[#{str}] string did not match :!"
|
|
334
|
+
str = str.to_s #= str[1..-1]
|
|
335
|
+
cmdline = str.split
|
|
336
|
+
cmd = cmdline.shift #.to_sym
|
|
337
|
+
return unless cmd # added 2011-09-11 FFI
|
|
338
|
+
f = @form.get_current_field
|
|
339
|
+
if respond_to?(cmd, true)
|
|
340
|
+
if cmd == "close"
|
|
341
|
+
throw :close # other seg faults in del_panel window.destroy executes 2x
|
|
342
|
+
else
|
|
343
|
+
res = send cmd, *cmdline
|
|
344
|
+
end
|
|
345
|
+
elsif f.respond_to?(cmd, true)
|
|
346
|
+
res = f.send(cmd, *cmdline)
|
|
347
|
+
else
|
|
348
|
+
alert "App: #{self.class} does not respond to #{cmd} "
|
|
349
|
+
ret = false
|
|
350
|
+
# what is this execute_this: some kind of general routine for all apps ?
|
|
351
|
+
ret = execute_this(cmd, *cmdline) if respond_to?(:execute_this, true)
|
|
352
|
+
rb_puts("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret
|
|
353
|
+
# should be able to say in red as error
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
#
|
|
358
|
+
# @group methods to create widgets easily
|
|
359
|
+
#
|
|
360
|
+
# process arguments based on datatype, perhaps making configuration
|
|
361
|
+
# of some components easier for caller avoiding too much boiler plate code
|
|
362
|
+
#
|
|
363
|
+
#instance_eval &block if block_given?
|
|
364
|
+
# or
|
|
365
|
+
#@blk = block # for later execution using @blk.call()
|
|
366
|
+
#colorlabel = Label.new @form, {'text' => "Select a color:", "row" => row, "col" => col, "color"=>"cyan", "mnemonic" => 'S'}
|
|
367
|
+
alias :text :label
|
|
368
|
+
|
|
369
|
+
# print a title on first row -- this is so bad, not even a label
|
|
370
|
+
def title string, config={}
|
|
371
|
+
raise "don't use DELETE dead code"
|
|
372
|
+
## TODO center it
|
|
373
|
+
@window.printstring 1, 30, string, $normalcolor, 'reverse'
|
|
374
|
+
end
|
|
375
|
+
# print a sutitle on second row, center and use a label, if this is even used.
|
|
376
|
+
def subtitle string, config={}
|
|
377
|
+
raise "don't use DELETE"
|
|
378
|
+
@window.printstring 2, 30, string, $datacolor, 'normal'
|
|
379
|
+
end
|
|
380
|
+
# menu bar
|
|
381
|
+
|
|
382
|
+
# displays a horizontal line
|
|
383
|
+
# takes col (column to start from) from current stack
|
|
384
|
+
# take row from app_row
|
|
385
|
+
#
|
|
386
|
+
# requires width to be passed in config, else defaults to 20
|
|
387
|
+
# @example
|
|
388
|
+
# hline :width => 55
|
|
389
|
+
def hline config={}
|
|
390
|
+
row = config[:row] || @app_row
|
|
391
|
+
width = config[:width] || 20
|
|
392
|
+
_position config
|
|
393
|
+
col = config[:col] || 1
|
|
394
|
+
@color_pair = config[:color_pair] || $datacolor
|
|
395
|
+
@attrib = config[:attrib] || Ncurses::A_NORMAL
|
|
396
|
+
@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
|
|
397
|
+
@window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width)
|
|
398
|
+
@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
|
|
399
|
+
@app_row += 1
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
# ADD new widget above this
|
|
404
|
+
|
|
405
|
+
# @endgroup
|
|
406
|
+
|
|
407
|
+
# @group positioning of components
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
private
|
|
411
|
+
def quit
|
|
412
|
+
throw(:close)
|
|
413
|
+
end
|
|
414
|
+
#def help; display_app_help; end
|
|
415
|
+
# i am removing above from rdialog. 2014-05-21 - 12:42 hope next
|
|
416
|
+
# line works UNTESTED
|
|
417
|
+
def help; @form.help_manager.display_help; end
|
|
418
|
+
|
|
419
|
+
# Initialize curses
|
|
420
|
+
def init_ncurses
|
|
421
|
+
Canis::start_ncurses # this is initializing colors via ColorMap.setup
|
|
422
|
+
#$ncurses_started = true
|
|
423
|
+
@stop_ncurses_on_close = true
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# returns length of longest
|
|
427
|
+
def longest_in_list list #:nodoc:
|
|
428
|
+
longest = list.inject(0) do |memo,word|
|
|
429
|
+
memo >= word.length ? memo : word.length
|
|
430
|
+
end
|
|
431
|
+
longest
|
|
432
|
+
end
|
|
433
|
+
# returns longest item
|
|
434
|
+
# rows = list.max_by(&:length)
|
|
435
|
+
#
|
|
436
|
+
def longest_in_list2 list #:nodoc:
|
|
437
|
+
longest = list.inject(list[0]) do |memo,word|
|
|
438
|
+
memo.length >= word.length ? memo : word
|
|
439
|
+
end
|
|
440
|
+
longest
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
# if partial command entered then returns matches
|
|
444
|
+
def _resolve_command opts, cmd
|
|
445
|
+
return cmd if opts.include? cmd
|
|
446
|
+
matches = opts.grep Regexp.new("^#{cmd}")
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def run &block
|
|
450
|
+
begin
|
|
451
|
+
|
|
452
|
+
# check if user has passed window coord in config, else root window
|
|
453
|
+
@window = Canis::Window.root_window
|
|
454
|
+
awin = @window
|
|
455
|
+
catch(:close) do
|
|
456
|
+
@form = Form.new @window
|
|
457
|
+
@form.bind_key([?\C-x, ?c], 'suspend') { suspend(false) do
|
|
458
|
+
system("tput cup 26 0")
|
|
459
|
+
system("tput ed")
|
|
460
|
+
system("echo Enter C-d to return to application")
|
|
461
|
+
system (ENV['PS1']='\s-\v\$ ')
|
|
462
|
+
system(ENV['SHELL']);
|
|
463
|
+
end
|
|
464
|
+
}
|
|
465
|
+
# this is a very rudimentary default command executer, it does not
|
|
466
|
+
# allow tab completion. App should use M-x with names of commands
|
|
467
|
+
# as in appgmail
|
|
468
|
+
# NOTE: This is gonna change very soon - 2012-01-8
|
|
469
|
+
@form.bind_key(?:, 'prompt') {
|
|
470
|
+
str = get_command_from_user
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
# this M-x stuff has to be moved out so it can be used by all. One should be able
|
|
474
|
+
# to add_commands properly to this, and to C-x. I am thinking how to go about this,
|
|
475
|
+
# and what function M-x actually serves.
|
|
476
|
+
|
|
477
|
+
@form.bind_key(?\M-x, 'M-x commands'){
|
|
478
|
+
# TODO previous command to be default
|
|
479
|
+
opts = get_all_commands()
|
|
480
|
+
@_command_history ||= Array.new
|
|
481
|
+
# previous command should be in opts, otherwise it is not in this context
|
|
482
|
+
cmd = rb_gets("Command: ", opts){ |q| q.default = @_previous_command; q.history = @_command_history }
|
|
483
|
+
if cmd.nil? || cmd == ""
|
|
484
|
+
else
|
|
485
|
+
@_command_history << cmd unless @_command_history.include? cmd
|
|
486
|
+
cmdline = cmd.split
|
|
487
|
+
cmd = cmdline.shift
|
|
488
|
+
# check if command is a substring of a larger command
|
|
489
|
+
if !opts.include?(cmd)
|
|
490
|
+
rcmd = _resolve_command(opts, cmd) if !opts.include?(cmd)
|
|
491
|
+
if rcmd.size == 1
|
|
492
|
+
cmd = rcmd.first
|
|
493
|
+
elsif !rcmd.empty?
|
|
494
|
+
rb_puts "Cannot resolve #{cmd}. Matches are: #{rcmd} "
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
if respond_to?(cmd, true)
|
|
498
|
+
@_previous_command = cmd
|
|
499
|
+
begin
|
|
500
|
+
send cmd, *cmdline
|
|
501
|
+
rescue => exc
|
|
502
|
+
$log.error "ERR EXC: send throwing an exception now. Duh. IMAP keeps crashing haha !! #{exc} " if $log.debug?
|
|
503
|
+
if exc
|
|
504
|
+
$log.debug( exc)
|
|
505
|
+
$log.debug(exc.backtrace.join("\n"))
|
|
506
|
+
rb_puts exc.to_s
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
else
|
|
510
|
+
rb_puts("Command [#{cmd}] not supported by #{self.class} ", :color_pair => $promptcolor)
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
}
|
|
514
|
+
#@form.bind_key(KEY_F1, 'help'){ display_app_help } # NOT REQUIRED NOW 2012-01-7 since form does it
|
|
515
|
+
@form.bind_key([?q,?q], 'quit' ){ throw :close } if $log.debug?
|
|
516
|
+
|
|
517
|
+
#@message = Variable.new
|
|
518
|
+
#@message.value = ""
|
|
519
|
+
$status_message ||= Variable.new # remember there are multiple levels of apps
|
|
520
|
+
$status_message.value = ""
|
|
521
|
+
#$error_message.update_command { @message.set_value($error_message.value) }
|
|
522
|
+
if block
|
|
523
|
+
begin
|
|
524
|
+
yield_or_eval &block if block_given? # modified 2010-11-17 20:36
|
|
525
|
+
# how the hell does a user trap exception if the loop is hidden from him ? FIXME
|
|
526
|
+
loop
|
|
527
|
+
rescue => ex
|
|
528
|
+
$log.debug( "APP.rb rescue reached ")
|
|
529
|
+
$log.debug( ex) if ex
|
|
530
|
+
$log.debug(ex.backtrace.join("\n")) if ex
|
|
531
|
+
ensure
|
|
532
|
+
close
|
|
533
|
+
# putting it here allows it to be printed on screen, otherwise it was not showing at all.
|
|
534
|
+
if ex
|
|
535
|
+
puts "========== EXCEPTION =========="
|
|
536
|
+
p ex
|
|
537
|
+
puts "==============================="
|
|
538
|
+
puts(ex.backtrace.join("\n"))
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
nil
|
|
542
|
+
else
|
|
543
|
+
#@close_on_terminate = true
|
|
544
|
+
self
|
|
545
|
+
end #if block
|
|
546
|
+
end # :close
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
# process args, all widgets should call this
|
|
550
|
+
def _process_args args, config, block_event, events #:nodoc:
|
|
551
|
+
args.each do |arg|
|
|
552
|
+
case arg
|
|
553
|
+
when Array
|
|
554
|
+
# please don't use this, keep it simple and use hash NOTE
|
|
555
|
+
# we can use r,c, w, h
|
|
556
|
+
row, col, width, height = arg
|
|
557
|
+
config[:row] = row
|
|
558
|
+
config[:col] = col
|
|
559
|
+
config[:width] = width if width
|
|
560
|
+
# width for most XXX ?
|
|
561
|
+
config[:height] = height if height
|
|
562
|
+
when Hash
|
|
563
|
+
config.merge!(arg)
|
|
564
|
+
if block_event
|
|
565
|
+
block_event = config.delete(:block_event){ block_event }
|
|
566
|
+
raise "Invalid event. Use #{events}" unless events.include? block_event
|
|
567
|
+
end
|
|
568
|
+
when String
|
|
569
|
+
config[:name] = arg
|
|
570
|
+
config[:title] = arg # some may not have title
|
|
571
|
+
#config[:text] = arg # some may not have title
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end # _process
|
|
575
|
+
end # class
|
|
576
|
+
end # module
|
|
577
|
+
if $0 == __FILE__
|
|
578
|
+
include Canis
|
|
579
|
+
#app = App.new
|
|
580
|
+
#window = app.window
|
|
581
|
+
#window.printstring 2, 30, "Demo of Listbox - canis", $normalcolor, 'reverse'
|
|
582
|
+
#app.logger.info "beforegetch"
|
|
583
|
+
#window.getch
|
|
584
|
+
#app.close
|
|
585
|
+
# this was the yield example, but now we've moved to instance eval
|
|
586
|
+
App.new do
|
|
587
|
+
@window.printstring 0, 30, "Demo of Listbox - canis", $normalcolor, 'reverse'
|
|
588
|
+
@window.printstring 1, 30, "Hit F1 to quit", $datacolor, 'normal'
|
|
589
|
+
form = @form
|
|
590
|
+
fname = "Search"
|
|
591
|
+
r, c = 7, 30
|
|
592
|
+
c += fname.length + 1
|
|
593
|
+
#field1 = field( [r,c, 30], fname, :bgcolor => "cyan", :block_event => :CHANGE) do |fld|
|
|
594
|
+
stack :margin_top => 2, :margin => 10 do
|
|
595
|
+
lbl = label({:text => fname, :color=>'white',:bgcolor=>'red', :mnemonic=> 's'})
|
|
596
|
+
field1 = field( [r,c, 30], fname, :bgcolor => "cyan",:block_event => :CHANGE) do |fld|
|
|
597
|
+
message("You entered #{fld.getvalue}. To quit enter quit and tab out")
|
|
598
|
+
if fld.getvalue == "quit"
|
|
599
|
+
logger.info "you typed quit!"
|
|
600
|
+
throw :close
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
#field1.set_label Label.new @form, {:text => fname, :color=>'white',:bgcolor=>'red', :mnemonic=> 's'}
|
|
604
|
+
field1.set_label( lbl )
|
|
605
|
+
field1.enter do
|
|
606
|
+
message "you entered this field"
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
stack :margin_top => 2, :margin => 0 do
|
|
610
|
+
#label( [8, 30, 60],{:text => "A label", :color=>'white',:bgcolor=>'blue'} )
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
@bluelabel = label( [8, 30, 60],{:text => "B label", :color=>'white',:bgcolor=>'blue'} )
|
|
614
|
+
|
|
615
|
+
stack :margin_top => 2, :margin => 0 do
|
|
616
|
+
toggle :onvalue => " Toggle Down ", :offvalue => " Untoggle ", :mnemonic => 'T', :value => true
|
|
617
|
+
|
|
618
|
+
toggle :onvalue => " On ", :offvalue => " Off ", :value => true do |e|
|
|
619
|
+
alert "You pressed me #{e.state}"
|
|
620
|
+
end
|
|
621
|
+
check :text => "Check me!", :onvalue => "Checked", :offvalue => "Unchecked", :value => true do |e|
|
|
622
|
+
# this works but long and complicated
|
|
623
|
+
#@bluelabel.text = e.item.getvalue ? e.item.onvalue : e.item.offvalue
|
|
624
|
+
@bluelabel.text = e.item.text
|
|
625
|
+
end
|
|
626
|
+
radio :text => "red", :value => "RED", :color => "red", :group => :colors
|
|
627
|
+
radio :text => "green", :value => "GREEN", :color => "green", :group => :colors
|
|
628
|
+
flow do
|
|
629
|
+
button_row = 17
|
|
630
|
+
ok_button = button( [button_row,30], "OK", {:mnemonic => 'O'}) do
|
|
631
|
+
alert("About to dump data into log file!")
|
|
632
|
+
message "Dumped data to log file"
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
# using ampersand to set mnemonic
|
|
636
|
+
cancel_button = button( [button_row, 40], "&Cancel" ) do
|
|
637
|
+
if confirm("Do your really want to quit?")== :YES
|
|
638
|
+
#throw(:close);
|
|
639
|
+
quit
|
|
640
|
+
else
|
|
641
|
+
message "Quit aborted"
|
|
642
|
+
end
|
|
643
|
+
end # cancel
|
|
644
|
+
button "Don't know"
|
|
645
|
+
end
|
|
646
|
+
flow :margin_top => 2 do
|
|
647
|
+
button "Another"
|
|
648
|
+
button "Line"
|
|
649
|
+
end
|
|
650
|
+
stack :margin_top => 2, :margin => 0 do
|
|
651
|
+
@pbar = progress :width => 20, :bgcolor => 'white', :color => 'red'
|
|
652
|
+
@pbar1 = progress :width => 20, :style => :old
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
end # stack
|
|
656
|
+
# lets make another column
|
|
657
|
+
stack :margin_top => 2, :margin => 70 do
|
|
658
|
+
l = label "Column 2"
|
|
659
|
+
f1 = field "afield", :bgcolor => 'white', :color => 'black'
|
|
660
|
+
listbox "A list", :list => ["Square", "Oval", "Rectangle", "Somethinglarge"], :choose => ["Square"]
|
|
661
|
+
lb = listbox "Another", :list => ["Square", "Oval", "Rectangle", "Somethinglarge"] do |list|
|
|
662
|
+
#f1.set_buffer list.text
|
|
663
|
+
#f1.text list.text
|
|
664
|
+
f1.text = list.text
|
|
665
|
+
l.text = list.current_value.upcase
|
|
666
|
+
end
|
|
667
|
+
t = textarea :height => 10 do |e|
|
|
668
|
+
#@bluelabel.text = e.to_s.tr("\n",' ')
|
|
669
|
+
@bluelabel.text = e.text.gsub("\n"," ")
|
|
670
|
+
len = e.source.get_text.length
|
|
671
|
+
len = len % 20 if len > 20
|
|
672
|
+
$log.debug " PBAR len of text is #{len}: #{len/20.0} "
|
|
673
|
+
@pbar.fraction(len/20.0)
|
|
674
|
+
@pbar1.fraction(len/20.0)
|
|
675
|
+
i = ((len/20.0)*100).to_i
|
|
676
|
+
@pbar.text = "completed:#{i}"
|
|
677
|
+
end
|
|
678
|
+
t.leave do |c|
|
|
679
|
+
@bluelabel.text = c.get_text.gsub("\n"," ")
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
# Allow user to get the keys
|
|
685
|
+
keypress do |key|
|
|
686
|
+
if key == :C_c
|
|
687
|
+
message "You tried to cancel"
|
|
688
|
+
#throw :close
|
|
689
|
+
quit
|
|
690
|
+
else
|
|
691
|
+
#app.message "You pressed #{key}, #{char} "
|
|
692
|
+
message "You pressed #{key}"
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
end
|
|
696
|
+
end
|