window_blessing 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +43 -0
- data/Rakefile +12 -0
- data/bin/buffered_screen_demo.rb +92 -0
- data/bin/color_picker_demo.rb +176 -0
- data/bin/foiled_demo.rb +27 -0
- data/bin/text_editor_demo.rb +292 -0
- data/bin/windowed_screen_demo.rb +71 -0
- data/bin/xterm_screen_demo.rb +33 -0
- data/lib/window_blessing.rb +54 -0
- data/lib/window_blessing/buffer.rb +216 -0
- data/lib/window_blessing/buffered_screen.rb +29 -0
- data/lib/window_blessing/color.rb +71 -0
- data/lib/window_blessing/constants.rb +3 -0
- data/lib/window_blessing/event_manager.rb +75 -0
- data/lib/window_blessing/event_queue.rb +20 -0
- data/lib/window_blessing/evented.rb +19 -0
- data/lib/window_blessing/evented_variable.rb +47 -0
- data/lib/window_blessing/tools.rb +124 -0
- data/lib/window_blessing/version.rb +3 -0
- data/lib/window_blessing/widgets/draggable_background.rb +13 -0
- data/lib/window_blessing/widgets/label.rb +23 -0
- data/lib/window_blessing/widgets/slider.rb +53 -0
- data/lib/window_blessing/widgets/text_field.rb +92 -0
- data/lib/window_blessing/window.rb +273 -0
- data/lib/window_blessing/windowed_screen.rb +53 -0
- data/lib/window_blessing/xterm_event_parser.rb +156 -0
- data/lib/window_blessing/xterm_input.rb +40 -0
- data/lib/window_blessing/xterm_log.rb +7 -0
- data/lib/window_blessing/xterm_output.rb +213 -0
- data/lib/window_blessing/xterm_screen.rb +109 -0
- data/lib/window_blessing/xterm_state.rb +27 -0
- data/spec/buffer_spec.rb +170 -0
- data/spec/color_spec.rb +36 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/tools_spec.rb +142 -0
- data/spec/window_spec.rb +61 -0
- data/window_blessing.gemspec +28 -0
- metadata +226 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module WindowBlessing
|
3
|
+
class XtermInput
|
4
|
+
attr_reader :event_parser
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@event_parser = XtermEventParser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def read_events
|
11
|
+
events = []
|
12
|
+
if raw = read_pending_input
|
13
|
+
parsed = event_parser.parse(raw)
|
14
|
+
if parsed
|
15
|
+
new_events = parsed.events
|
16
|
+
events += new_events
|
17
|
+
new_events.length
|
18
|
+
else
|
19
|
+
events << {:type => :event_parser_failure, :raw => raw, :failure_info => event_parser.parser_failure_info}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
events
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def read_pending_input
|
27
|
+
read = nil
|
28
|
+
begin
|
29
|
+
while c = STDIN.read_nonblock(1000)
|
30
|
+
read = read ? read + c : c
|
31
|
+
end
|
32
|
+
rescue Errno::EAGAIN # nothing was ready to be read
|
33
|
+
rescue Errno::EINTR
|
34
|
+
rescue EOFError
|
35
|
+
end
|
36
|
+
read
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# ref: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
2
|
+
# ref: http://www.vt100.net/docs/vt102-ug/chapter5.html
|
3
|
+
|
4
|
+
module WindowBlessing
|
5
|
+
|
6
|
+
class XtermOutput
|
7
|
+
module SetColor
|
8
|
+
def change_fg(fg)
|
9
|
+
set_fg(fg) if fg!=@current_fg
|
10
|
+
@current_fg = fg
|
11
|
+
end
|
12
|
+
|
13
|
+
def change_bg(bg)
|
14
|
+
set_bg(bg) if bg!=@current_bg
|
15
|
+
@current_bg = bg
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_fg(fg)
|
19
|
+
out "\x1b[38;5;#{fg}m"
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_bg(bg)
|
23
|
+
out "\x1b[48;5;#{bg}m"
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :current_fg, :current_bg
|
27
|
+
|
28
|
+
def set_color(fg, bg=nil)
|
29
|
+
set_fg(fg) if fg
|
30
|
+
set_bg(bg) if bg
|
31
|
+
end
|
32
|
+
|
33
|
+
# fg and bg are r-g-b arrays: [0..255, 0..255, 0..255]
|
34
|
+
# This is not supported by iTerm2: http://code.google.com/p/iterm2/issues/detail?id=218
|
35
|
+
# konsole supports it: https://github.com/robertknight/konsole/blob/master/user-doc/README.moreColors
|
36
|
+
def set_color_24bit(fg, bg=nil)
|
37
|
+
out "\x1b[38;2;#{fg.join(';')}m" if fg
|
38
|
+
out "\x1b[48;2;#{bg.join(';')}m" if bg
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset_color
|
42
|
+
@current_fg = 7
|
43
|
+
@current_bg = 0
|
44
|
+
out "\x1b[0m"
|
45
|
+
end
|
46
|
+
|
47
|
+
def out_color(txt, fg, bg)
|
48
|
+
set_color(fg, bg)
|
49
|
+
out txt
|
50
|
+
reset_color
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_bold; out "\x1b[1m" end
|
54
|
+
def set_underline; out "\x1b[4m" end
|
55
|
+
end
|
56
|
+
include SetColor
|
57
|
+
|
58
|
+
module SetState
|
59
|
+
def show_cursor; out "\e[?25h"; end
|
60
|
+
def hide_cursor; out "\e[?25l"; end
|
61
|
+
|
62
|
+
def enable_mouse; out "\e[?1003h"; end
|
63
|
+
def disable_mouse; out "\e[?1003l"; end
|
64
|
+
|
65
|
+
def enable_focus_events; out "\e[?1004h" end
|
66
|
+
def disable_focus_events; out "\e[?1004l" end
|
67
|
+
|
68
|
+
def enable_utf8; out "\e%G" end
|
69
|
+
def disable_utf8; out "\e%@" end
|
70
|
+
|
71
|
+
def enable_alternate_screen
|
72
|
+
out "\e7"
|
73
|
+
out "\e[?47h"
|
74
|
+
end
|
75
|
+
|
76
|
+
def disable_alternate_screen
|
77
|
+
out "\e[?47l"
|
78
|
+
out "\e8"
|
79
|
+
end
|
80
|
+
|
81
|
+
# TODO: find out what stty raw -echo sends to xterm
|
82
|
+
# INTERNAL NOTE: out "\e[12h" # should turn off echo according to doc, but didn't work
|
83
|
+
# http://stackoverflow.com/questions/174933/how-to-get-a-single-character-without-pressing-enter
|
84
|
+
def echo_off; system "stty raw -echo"; end
|
85
|
+
|
86
|
+
# INTERNAL NOTE: out "\e[12l" # should turn echo back on
|
87
|
+
def echo_on; system "stty -raw echo"; end
|
88
|
+
|
89
|
+
=begin
|
90
|
+
raw may set the following:
|
91
|
+
00830 option(x + "-icrnl", ""); /* map CR to NL on input */
|
92
|
+
00831 option(x + "-ixon", ""); /* enable start/stop output control */
|
93
|
+
00832 option(x + "-opost", ""); /* perform output processing */
|
94
|
+
00833 option(x + "-onlcr", ""); /* Map NL to CR-NL on output */
|
95
|
+
00834 option(x + "-isig", ""); /* enable signals */
|
96
|
+
00835 option(x + "-icanon", "");/* canonical input (erase and kill enabled) */
|
97
|
+
00836 option(x + "-iexten", "");/* enable extended functions */
|
98
|
+
00837 option(x + "-echo", ""); /* enable echoing of input characters */
|
99
|
+
|
100
|
+
=end
|
101
|
+
|
102
|
+
# This seems to work - or at least it does SOMETHING
|
103
|
+
# def insert_mode; out "\e[4m"; end
|
104
|
+
# def replace_mode; out "\e[4l"; end
|
105
|
+
|
106
|
+
end
|
107
|
+
include SetState
|
108
|
+
|
109
|
+
attr_accessor :xterm_state
|
110
|
+
|
111
|
+
def initialize(xterm_state)
|
112
|
+
@xterm_state = xterm_state
|
113
|
+
end
|
114
|
+
|
115
|
+
# cursor 0, 0 is the upper left hand corner
|
116
|
+
# cursor point(0, 0) is also accepted
|
117
|
+
def cursor(loc_or_x, y=nil)
|
118
|
+
loc = y ? point(loc_or_x,y) : loc_or_x
|
119
|
+
out "\e[#{loc.y+1};#{loc.x+1}H"
|
120
|
+
end
|
121
|
+
|
122
|
+
# raw screen output
|
123
|
+
def out(str)
|
124
|
+
$stdout.print str
|
125
|
+
str
|
126
|
+
end
|
127
|
+
|
128
|
+
def out_at(loc, str)
|
129
|
+
cursor(loc)
|
130
|
+
out str
|
131
|
+
end
|
132
|
+
|
133
|
+
def out_at_with_color(loc, str, fg, bg)
|
134
|
+
return unless str.length > 0
|
135
|
+
cursor loc
|
136
|
+
|
137
|
+
change_fg fg[0]
|
138
|
+
change_bg bg[0]
|
139
|
+
|
140
|
+
current_attrs = [current_fg, current_bg]
|
141
|
+
|
142
|
+
next_output_pos = 0
|
143
|
+
pos = 0
|
144
|
+
|
145
|
+
fg.zip(bg).each do |attrs|
|
146
|
+
if current_attrs!=attrs
|
147
|
+
out str[next_output_pos..pos-1]
|
148
|
+
change_fg attrs[0]
|
149
|
+
change_bg attrs[1]
|
150
|
+
current_attrs = attrs
|
151
|
+
next_output_pos = pos
|
152
|
+
end
|
153
|
+
pos += 1
|
154
|
+
end
|
155
|
+
out str[next_output_pos..-1]
|
156
|
+
end
|
157
|
+
|
158
|
+
def draw_buffer(loc, buffer)
|
159
|
+
loc = loc.clone
|
160
|
+
reset_color
|
161
|
+
buffer.each_line do |line,fg,bg|
|
162
|
+
out_at_with_color loc, line, fg, bg
|
163
|
+
loc.y += 1
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# convert all \n to \n\r
|
168
|
+
def puts(s=nil)
|
169
|
+
width = xterm_state.size.x
|
170
|
+
lines = "#{s}\n".split("\n").collect do |line|
|
171
|
+
line + " " * (width - (line.length % width))
|
172
|
+
end
|
173
|
+
out lines.flatten.join "\n"
|
174
|
+
end
|
175
|
+
|
176
|
+
def clear; out "\e[2J"; end
|
177
|
+
|
178
|
+
|
179
|
+
# INTERNAL NOTE: xterm returns 3 numbers: ?, height, width
|
180
|
+
# Xterm sends back response as an escape sequence. XtermEventParser knows how to capture and interpret the result.
|
181
|
+
def request_xterm_size; out "\e[18t"; end
|
182
|
+
|
183
|
+
# INTERNAL NOTE: xterm returns 3 numbers: ?, height, width
|
184
|
+
# This returns the entire screen size in pixels - not just the pixel-size of the x-term
|
185
|
+
def request_display_pixel_size; out "\e[14t"; end
|
186
|
+
|
187
|
+
def request_cursor_position; out "\e[?6n"; end
|
188
|
+
|
189
|
+
def request_state_update
|
190
|
+
request_xterm_size
|
191
|
+
request_display_pixel_size
|
192
|
+
end
|
193
|
+
|
194
|
+
def enable_resize_events
|
195
|
+
Signal.trap "SIGWINCH" do
|
196
|
+
request_xterm_size
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def disable_resize_events
|
201
|
+
Signal.trap "SIGWINCH", "DEFAULT"
|
202
|
+
end
|
203
|
+
|
204
|
+
def reset_all
|
205
|
+
disable_focus_events
|
206
|
+
disable_mouse
|
207
|
+
disable_resize_events
|
208
|
+
reset_color
|
209
|
+
show_cursor
|
210
|
+
echo_on
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module WindowBlessing
|
2
|
+
class XtermScreen
|
3
|
+
include GuiGeo
|
4
|
+
include GuiGeo::Tools
|
5
|
+
|
6
|
+
attr_accessor :input, :output, :event_manager, :state, :event_queue
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@event_manager = EventManager.new(self)
|
10
|
+
@state = XtermState.new @event_manager
|
11
|
+
@input = XtermInput.new
|
12
|
+
@output = XtermOutput.new(@state)
|
13
|
+
@running = true
|
14
|
+
@pending_events = []
|
15
|
+
@event_queue = EventQueue.new
|
16
|
+
|
17
|
+
@event_manager.add_handler :key_press do |event|
|
18
|
+
quit if event[:key]==:control_q
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"<#{self.class}:#{object_id}>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def quit; @running = false; end
|
27
|
+
def running?; @running; end
|
28
|
+
|
29
|
+
def queue_event(e); event_queue << e end
|
30
|
+
def queued_events?; !event_queue.empty? end
|
31
|
+
|
32
|
+
def queue_pending_xterm_events
|
33
|
+
event_queue << input.read_events
|
34
|
+
end
|
35
|
+
|
36
|
+
def wait_for_events(max=100)
|
37
|
+
count = max
|
38
|
+
while !queued_events? && count > 0
|
39
|
+
queue_pending_xterm_events
|
40
|
+
count -= 1
|
41
|
+
sleep 0.01
|
42
|
+
end
|
43
|
+
raise "no events!" unless queued_events?
|
44
|
+
end
|
45
|
+
|
46
|
+
def process_queued_events
|
47
|
+
event_manager.handle_events event_queue.pop_all
|
48
|
+
end
|
49
|
+
|
50
|
+
def process_events
|
51
|
+
queue_pending_xterm_events
|
52
|
+
queue_event :type => :tick
|
53
|
+
process_queued_events
|
54
|
+
end
|
55
|
+
|
56
|
+
def event_loop
|
57
|
+
while running?
|
58
|
+
process_events
|
59
|
+
sleep 1/60.0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize_screen
|
64
|
+
output.request_state_update
|
65
|
+
wait_for_events
|
66
|
+
process_events
|
67
|
+
end
|
68
|
+
|
69
|
+
# run xterm raw-session
|
70
|
+
# options
|
71
|
+
#
|
72
|
+
def start(options={})
|
73
|
+
in_xterm_state(options) do
|
74
|
+
initialize_screen
|
75
|
+
yield self
|
76
|
+
event_loop
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# options
|
82
|
+
# :mouse => true
|
83
|
+
# :no_cursor => true
|
84
|
+
# :alternate_screen => true
|
85
|
+
# :full => true (enables all above features)
|
86
|
+
# :utf8
|
87
|
+
def in_xterm_state(options = {})
|
88
|
+
output.echo_off
|
89
|
+
output.enable_alternate_screen if options[:full] || options[:alternate_screen]
|
90
|
+
output.enable_mouse if options[:full] || options[:mouse]
|
91
|
+
output.hide_cursor if options[:full] || options[:no_cursor]
|
92
|
+
output.enable_utf8 if options[:utf8]
|
93
|
+
output.enable_focus_events
|
94
|
+
output.enable_resize_events
|
95
|
+
output.clear
|
96
|
+
|
97
|
+
yield self
|
98
|
+
ensure
|
99
|
+
output.reset_all
|
100
|
+
output.disable_utf8 if options[:utf8]
|
101
|
+
if options[:full] || options[:alternate_screen]
|
102
|
+
output.reset_color
|
103
|
+
output.clear
|
104
|
+
output.disable_alternate_screen
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module WindowBlessing
|
2
|
+
class XtermState
|
3
|
+
attr_accessor :state
|
4
|
+
|
5
|
+
def initialize(event_manager)
|
6
|
+
@state = {:size => point(-1,-1)}
|
7
|
+
|
8
|
+
event_manager.add_handler :xterm_state do |event|
|
9
|
+
state_type = event[:state_type]
|
10
|
+
old_state = state[state_type]
|
11
|
+
new_state = event[:state]
|
12
|
+
state[state_type] = new_state
|
13
|
+
if old_state!=new_state
|
14
|
+
case state_type
|
15
|
+
when :size
|
16
|
+
event_manager.handle_event :type => :resize, :old_size => old_state, :size => new_state, :raw => event[:raw]
|
17
|
+
else
|
18
|
+
event_manager.handle_event :type => :state_change, :state_type => state_type, :old_state => old_state, :state => new_state, :raw => event[:raw]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def size; state[:size] end
|
26
|
+
end
|
27
|
+
end
|
data/spec/buffer_spec.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module WindowBlessing
|
4
|
+
describe "Buffer" do
|
5
|
+
include Tools
|
6
|
+
|
7
|
+
def test_frame(options={})
|
8
|
+
buffer(point(4,4), {:contents => %w{1234 2345 3456 4567}}.merge(options))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "blank fb" do
|
12
|
+
buffer(point(4,4)).to_s.should == " \n \n \n "
|
13
|
+
end
|
14
|
+
|
15
|
+
it "string init" do
|
16
|
+
buffer(point(4,4),:contents => ["hi","there"]).to_s.should == "hi \nther\n \n "
|
17
|
+
buffer(point(4,4),:contents => "hi\nthere").to_s.should == "hi \nther\n \n "
|
18
|
+
buffer(point(4,4),:contents => "hi\n\t\0here").to_s.should == "hi \n??he\n \n "
|
19
|
+
end
|
20
|
+
|
21
|
+
it "inspect" do
|
22
|
+
buffer(point 4,4).inspect.class.should == String
|
23
|
+
end
|
24
|
+
|
25
|
+
it "invalid init" do
|
26
|
+
expect { buffer(point(4,4),:contents => 1) }.to raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it "subbuffer" do
|
30
|
+
test_frame.subbuffer(rect(1,1,2,2)).to_s.should == "34\n45"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "array init" do
|
34
|
+
test_frame.to_s.should == "1234\n2345\n3456\n4567"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "crop" do
|
38
|
+
(f=buffer(point 4,4)).cropped(rect(1,1,2,2)) do
|
39
|
+
f.crop_area.should == rect(1,1,2,2)
|
40
|
+
f.cropped?.should == true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "fill" do
|
45
|
+
fb = buffer(point(4,4))
|
46
|
+
fb.fill :string => "-"
|
47
|
+
fb.to_s.should == "----\n----\n----\n----"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "cropped fill" do
|
51
|
+
(f=test_frame).cropped(rect(1,1,2,1)) do
|
52
|
+
f.fill :string => '-'
|
53
|
+
end.to_s.should == "1234\n2--5\n3456\n4567"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "draw_rect" do
|
57
|
+
(f=buffer(point(4,4))).to_s.should == " \n \n \n "
|
58
|
+
f.draw_rect(rect(1,0,2,2),:string => "-")
|
59
|
+
f.to_s.should == " -- \n -- \n \n "
|
60
|
+
end
|
61
|
+
|
62
|
+
it "clear" do
|
63
|
+
fb = buffer(point 2,2).fill(:string => '-')
|
64
|
+
fb.to_s.should == "--\n--"
|
65
|
+
fb.clear
|
66
|
+
fb.to_s.should == " \n "
|
67
|
+
end
|
68
|
+
|
69
|
+
it "draw_buffer" do
|
70
|
+
f1 = test_frame
|
71
|
+
f2 = buffer(point(2,2), :contents => "ab\nbc")
|
72
|
+
f1.draw_buffer(point(1,1),f2)
|
73
|
+
f1.to_s.should == "1234\n2ab5\n3bc6\n4567"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "cropped draw_buffer" do
|
77
|
+
f1 = test_frame
|
78
|
+
f2 = buffer(point(2,2), :contents => "ab\nbc")
|
79
|
+
f1.cropped(rect(1,1,2,1)) do
|
80
|
+
f1.draw_buffer(point(1,1),f2)
|
81
|
+
end.to_s.should == "1234\n2ab5\n3456\n4567"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "fill only overwrites what is provided" do
|
85
|
+
f0 = test_frame :bg => 9, :fg => 8
|
86
|
+
|
87
|
+
f1 = f0.clone
|
88
|
+
f1.to_s.should == "1234\n2345\n3456\n4567"
|
89
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]
|
90
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
|
91
|
+
|
92
|
+
f1.fill :string => "!"
|
93
|
+
f1.to_s.should == "!!!!\n!!!!\n!!!!\n!!!!"
|
94
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]
|
95
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
|
96
|
+
|
97
|
+
f1 = f0.clone
|
98
|
+
f1.fill :bg => 0
|
99
|
+
f1.to_s.should == "1234\n2345\n3456\n4567"
|
100
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]
|
101
|
+
f1.bg_buffer.should == [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
102
|
+
|
103
|
+
f1 = f0.clone
|
104
|
+
f1.fill :fg => 0
|
105
|
+
f1.to_s.should == "1234\n2345\n3456\n4567"
|
106
|
+
f1.fg_buffer.should == [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
107
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
|
108
|
+
end
|
109
|
+
|
110
|
+
it "cropped fill only overwrites what is provided" do
|
111
|
+
f0 = test_frame :bg => 9, :fg => 8
|
112
|
+
|
113
|
+
f1 = f0.clone
|
114
|
+
f1.to_s.should == "1234\n2345\n3456\n4567"
|
115
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]
|
116
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
|
117
|
+
|
118
|
+
f1.cropped(rect(1,1,2,2)) {f1.fill :string => "!"}
|
119
|
+
f1.to_s.should == "1234\n2!!5\n3!!6\n4567"
|
120
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]
|
121
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
|
122
|
+
|
123
|
+
f1 = f0.clone
|
124
|
+
f1.cropped(rect(1,1,2,2)) {f1.fill :bg => 0}
|
125
|
+
f1.to_s.should == "1234\n2345\n3456\n4567"
|
126
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]
|
127
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 0, 0, 9], [9, 0, 0, 9], [9, 9, 9, 9]]
|
128
|
+
|
129
|
+
f1 = f0.clone
|
130
|
+
f1.cropped(rect(1,1,2,2)) {f1.fill :fg => 0}
|
131
|
+
f1.to_s.should == "1234\n2345\n3456\n4567"
|
132
|
+
f1.fg_buffer.should == [[8, 8, 8, 8], [8, 0, 0, 8], [8, 0, 0, 8], [8, 8, 8, 8]]
|
133
|
+
f1.bg_buffer.should == [[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "dirty" do
|
137
|
+
f1 = test_frame
|
138
|
+
f1.dirty?.should == false
|
139
|
+
f1.dirty rect(1,2,3,4)
|
140
|
+
f1.dirty?.should == true
|
141
|
+
|
142
|
+
f1.dirty_area.should == rect(1,2,3,2)
|
143
|
+
|
144
|
+
s = f1.dirty_subbuffer
|
145
|
+
s.to_s.should == "456\n567"
|
146
|
+
|
147
|
+
f1.clean
|
148
|
+
f1.dirty?.should == false
|
149
|
+
end
|
150
|
+
|
151
|
+
it "on_dirty" do
|
152
|
+
f1 = test_frame
|
153
|
+
|
154
|
+
is_now_dirty = false
|
155
|
+
f1.on_dirty do
|
156
|
+
is_now_dirty = true
|
157
|
+
end
|
158
|
+
is_now_dirty.should == false
|
159
|
+
f1.dirty
|
160
|
+
is_now_dirty.should == true
|
161
|
+
end
|
162
|
+
|
163
|
+
it "color buffers" do
|
164
|
+
f1 = test_frame
|
165
|
+
|
166
|
+
f1.fg_buffer.should == [[7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7]]
|
167
|
+
f1.bg_buffer.should == [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|