window_blessing 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGELOG.md +30 -0
  2. data/README.md +1 -1
  3. data/bin/buffered_screen_demo.rb +4 -4
  4. data/bin/color_picker_demo.rb +1 -0
  5. data/bin/windowed_screen_demo.rb +1 -1
  6. data/bin/xterm_screen_demo.rb +6 -4
  7. data/lib/window_blessing.rb +2 -2
  8. data/lib/window_blessing/buffer.rb +16 -6
  9. data/lib/window_blessing/buffered_screen.rb +2 -2
  10. data/lib/window_blessing/color.rb +1 -0
  11. data/lib/window_blessing/debug_tools/log_request_redraw_internal.rb +16 -0
  12. data/lib/window_blessing/event_manager.rb +11 -6
  13. data/lib/window_blessing/evented.rb +1 -1
  14. data/lib/window_blessing/evented_variable.rb +10 -1
  15. data/lib/window_blessing/tools.rb +11 -1
  16. data/lib/window_blessing/version.rb +1 -1
  17. data/lib/window_blessing/widgets/draggable_background.rb +1 -1
  18. data/lib/window_blessing/widgets/label.rb +1 -1
  19. data/lib/window_blessing/widgets/slider.rb +10 -2
  20. data/lib/window_blessing/widgets/text_field.rb +1 -1
  21. data/lib/window_blessing/window.rb +48 -45
  22. data/lib/window_blessing/window_redraw_areas.rb +23 -0
  23. data/lib/window_blessing/windowed_screen.rb +11 -13
  24. data/lib/window_blessing/xterm_event_parser.rb +68 -59
  25. data/lib/window_blessing/xterm_screen.rb +2 -2
  26. data/lib/window_blessing/xterm_state.rb +1 -1
  27. data/spec/buffer_spec.rb +56 -0
  28. data/spec/color_spec.rb +14 -0
  29. data/spec/event_manager_spec.rb +107 -0
  30. data/spec/event_queue_spec.rb +46 -0
  31. data/spec/evented_variable_spec.rb +43 -0
  32. data/spec/tools_spec.rb +18 -0
  33. data/spec/window_redraw_areas_spec.rb +79 -0
  34. data/spec/window_spec.rb +138 -3
  35. data/spec/xterm_event_parser_spec.rb +86 -0
  36. data/window_blessing.gemspec +4 -3
  37. metadata +20 -11
  38. data/bin/foiled_demo.rb +0 -27
  39. data/bin/text_editor_demo.rb +0 -292
@@ -0,0 +1,30 @@
1
+ ### vXXX
2
+
3
+ Improvement
4
+
5
+ * Track more than one redraw area. Two small redraw areas no longer become one large one.
6
+
7
+ Added
8
+
9
+ * EventedVariable#before_filter
10
+ * :fg and :bg options to Buffer#normalize
11
+ * EventManager#on_event_exception
12
+ * EventManager#on_every_event
13
+ * EventManager#on_unhandled_event
14
+ * simplified keyboard event modifier encoding (shift/alt/control)
15
+ * fixed keyboard modifiers for pageup/down/home/end & f5-f10
16
+
17
+ Removed
18
+
19
+ * redraw time log
20
+
21
+ Changed Events
22
+
23
+ * Escape: [:key_press, :escape]
24
+ * Enter: [:key_press, :enter]
25
+ * Tab: [:key_press, :tab]
26
+ * Control-Letter: [:kre_press, :[letter]]
27
+
28
+ ### v0.0.2, 2013-02-17
29
+
30
+ BugFixes
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # WindowBlessing
2
2
 
3
- Forget Curses! Try Blessings instead! WindowBlessing is an evented windowing framework for terminal apps.
3
+ Forget curses. Try blessings instead. WindowBlessing is an evented windowing framework for terminal apps.
4
4
 
5
5
  ## Installation
6
6
 
@@ -46,7 +46,7 @@ WindowBlessing::BufferedScreen.new.start(:full=>true) do |screen|
46
46
  r.size = demo_buffer.size
47
47
  old_r = r.clone
48
48
 
49
- screen.event_manager.add_handler :tick do |event|
49
+ screen.event_manager.on :tick do |event|
50
50
  if r != old_r
51
51
  r = rect(point(0,1), screen.state.size-point(0,1)).bound(r)
52
52
  if r != old_r
@@ -57,7 +57,7 @@ WindowBlessing::BufferedScreen.new.start(:full=>true) do |screen|
57
57
  end
58
58
  end
59
59
 
60
- screen.event_manager.add_handler :characters do |event|
60
+ screen.event_manager.on :characters do |event|
61
61
  case event[:raw]
62
62
  when " " then
63
63
  demo_buffer = demo_buffer == grayb ? colorb : grayb
@@ -65,7 +65,7 @@ WindowBlessing::BufferedScreen.new.start(:full=>true) do |screen|
65
65
  end
66
66
  end
67
67
 
68
- screen.event_manager.add_handler :key_press do |event|
68
+ screen.event_manager.on :key_press do |event|
69
69
  WindowBlessing::XtermLog.log "key_press: #{event[:key]}"
70
70
  case event[:key]
71
71
  when :home then r.loc.x = 0
@@ -85,7 +85,7 @@ WindowBlessing::BufferedScreen.new.start(:full=>true) do |screen|
85
85
  screen.screen_buffer.draw_buffer r.loc, demo_buffer
86
86
  end
87
87
 
88
- screen.event_manager.add_handler :pointer do |event|
88
+ screen.event_manager.on :pointer do |event|
89
89
  WindowBlessing::XtermLog.log "mouse: drag #{event[:loc]}"
90
90
  r.loc = event[:loc] - demo_buffer.size/2
91
91
  end
@@ -22,6 +22,7 @@ class FadeSlider < Slider
22
22
  end
23
23
  buffer.bg_buffer = size.y.times.collect {line.clone}
24
24
  buffer.fill :string => " ", :fg => value > 0.5 ? Color.black : Color.white
25
+ draw_handle
25
26
  end
26
27
  end
27
28
 
@@ -11,7 +11,7 @@ class DragWindow < Window
11
11
  def initialize(loc,buffer)
12
12
  super rect(loc,buffer.size)
13
13
  @buffer.draw_buffer point, buffer
14
- clean
14
+ clear_redraw_areas
15
15
 
16
16
  on :key_press do |event|
17
17
  XtermLog.log "key_press: #{event[:key]}"
@@ -2,13 +2,14 @@
2
2
  require File.expand_path File.join(File.dirname(__FILE__), %w{.. lib window_blessing})
3
3
  include GuiGeo
4
4
 
5
- WindowBlessing::XtermScreen.new.start(:full=>true) do |screen|
5
+ module WindowBlessing
6
+ XtermScreen.new.start(:full=>true) do |screen|
6
7
  event_manager = screen.event_manager
7
8
 
8
9
  last_event = nil
9
10
  event_count = 0
10
11
 
11
- event_manager.add_handler :tick do
12
+ event_manager.on :tick do
12
13
  screen.output.instance_eval do
13
14
  cursor(0,0)
14
15
  reset_color
@@ -25,9 +26,10 @@ WindowBlessing::XtermScreen.new.start(:full=>true) do |screen|
25
26
  end
26
27
  end
27
28
 
28
- event_manager.add_handler do |event|
29
+ event_manager.on do |event|
29
30
  event_count += 1
30
- WindowBlessing::XtermLog.log "last_event = #{event.inspect}"
31
31
  last_event = event
32
+ XtermLog.log "#{last_event.inspect}.should == parse(#{(last_event[:raw]||last_event[:string]).inspect})"
32
33
  end
33
34
  end
35
+ end
@@ -11,8 +11,8 @@ See README for licence information.
11
11
 
12
12
  %w{
13
13
  constants
14
- color
15
14
  tools
15
+ color
16
16
  buffer
17
17
  version
18
18
  event_queue
@@ -26,6 +26,7 @@ See README for licence information.
26
26
  xterm_input
27
27
  xterm_screen
28
28
  buffered_screen
29
+ window_redraw_areas
29
30
  window
30
31
  windowed_screen
31
32
  widgets/draggable_background
@@ -37,7 +38,6 @@ See README for licence information.
37
38
  end
38
39
 
39
40
  module WindowBlessing
40
- # Your code goes here...
41
41
  class << self
42
42
  include Tools
43
43
  def main(&block)
@@ -66,14 +66,22 @@ class Buffer
66
66
  @contents[range] = @contents[range].collect {|l| l.gsub(/[\x00-\x1f]/,'?')}
67
67
  end
68
68
 
69
- def normalize(range=0..-1)
69
+ # options
70
+ # :fg - color
71
+ # :bg - color
72
+ def normalize(range=0..-1, options={})
73
+ ranged_size = size.clone
74
+ ranged_size.y = range_length(range) || size.y
70
75
  @contents||=[]
71
76
  @fg_buffer||=[]
72
77
  @bg_buffer||=[]
73
- @contents = @contents.gsub(/[\x00-\x09\x11-\x1f]/,'?').split("\n") if @contents.kind_of?(String)
74
- @contents[range] = resize2d @contents[range] , size, " "
75
- @fg_buffer[range] = resize2d @fg_buffer[range], size, Buffer.default_fg
76
- @bg_buffer[range] = resize2d @bg_buffer[range], size, Buffer.default_bg
78
+ if @contents.kind_of?(String)
79
+ @contents = @contents.split("\n")
80
+ sanitize_contents
81
+ end
82
+ @contents[range] = resize2d @contents[range] , ranged_size, " "
83
+ @fg_buffer[range] = resize2d @fg_buffer[range], ranged_size, options[:fg] || Buffer.default_fg
84
+ @bg_buffer[range] = resize2d @bg_buffer[range], ranged_size, options[:bg] || Buffer.default_bg
77
85
  end
78
86
 
79
87
  def on_dirty(&block)
@@ -176,6 +184,8 @@ class Buffer
176
184
  fg = fg.to_screen_color if fg.kind_of?(Color)
177
185
  bg = bg.to_screen_color if bg.kind_of?(Color)
178
186
 
187
+ return if area.size==point
188
+
179
189
  if area != internal_area
180
190
  @contents = overlay2d(area.loc, gen_array2d(area.size, string), contents) if string
181
191
  @fg_buffer = overlay2d(area.loc, gen_array2d(area.size, fg), fg_buffer) if fg
@@ -196,7 +206,7 @@ class Buffer
196
206
  end
197
207
 
198
208
  def draw_buffer(loc, buffer, source_area = nil)
199
- source_area = (source_area || buffer.internal_area) | (crop_area - loc)
209
+ source_area = buffer.internal_area | source_area | (crop_area - loc)
200
210
  return unless source_area.present?
201
211
 
202
212
  unless source_area == buffer.internal_area
@@ -7,11 +7,11 @@ class BufferedScreen < XtermScreen
7
7
  super
8
8
  @screen_buffer = Buffer.new point(20,20)
9
9
 
10
- event_manager.add_handler :tick do
10
+ event_manager.on :tick do
11
11
  update_from_screen_buffer
12
12
  end
13
13
 
14
- event_manager.add_handler :resize do |event|
14
+ event_manager.on :resize do |event|
15
15
  @screen_buffer = Buffer.new event[:size]
16
16
  @screen_buffer.dirty
17
17
  end
@@ -1,5 +1,6 @@
1
1
  module WindowBlessing
2
2
  class Color < Struct.new(:r, :g, :b)
3
+ include Tools
3
4
  class <<self
4
5
 
5
6
  def black; Color.new(0) end
@@ -0,0 +1,16 @@
1
+ module WindowBlessing
2
+ module DebugTools
3
+ module LogRequestRedrawInternal
4
+
5
+ # sometimes you want to know where redraw requests are coming from
6
+ # Since request_redraw_internal is recursive, you don't want to log the stack trace with every call - just the first one
7
+ # This will log a stack-trace once per call
8
+ def log_request_redraw_internal
9
+ trace = Kernel.caller
10
+ return if trace.count {|line| line["request_redraw_internal"]} > 1
11
+ log "request_redraw_internal trace @requested_redraw_area=#{@requested_redraw_area} path:#{path}\n "+ trace.join("\n ")
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -1,13 +1,13 @@
1
1
  module WindowBlessing
2
2
 
3
3
  # Event handlers are procs which have one input: the event.
4
- # There can be more than one handler per event-type. Handlers for the same event type are called in the reverse of the order they were added with add_handler.
4
+ # There can be more than one handler per event-type. Handlers for the same event type are called in the reverse of the order they were added with on.
5
5
  # Event handlers return a true value if they handled the event and no more handlers should be called.
6
6
  #
7
7
  # Events are hashs. The :type field is a symbol specifying the event type. Other key/values are event-specific
8
8
  #
9
9
  # Special handlers:
10
- # :all => gets all (real) events. Returning true will NOT stop event processing.
10
+ # () => gets all (real) events. Returning true will NOT stop event processing.
11
11
  # All gets access to the events first - and can alter them
12
12
  # All does NOT get :tick events
13
13
  # :unhandled_event => if the event has no handler, this handler is used instead. New event looks like this:
@@ -20,23 +20,28 @@ class EventManager
20
20
  def initialize(parent)
21
21
  @parent = parent
22
22
  @event_handlers = {}
23
- add_handler(:event_exception) do |e|
23
+
24
+ init_standard_handlers
25
+ end
26
+
27
+ def init_standard_handlers
28
+ on(:event_exception) do |e|
24
29
  XtermLog.log "#{self.class}(parent=#{parent.inspect}): event_exception: #{e[:exception].inspect} event: #{e[:event].inspect}"
25
30
  XtermLog.log " "+ e[:exception].backtrace.join("\n ")
26
31
  end
27
- add_handler(){}
32
+ on(){}
28
33
  end
29
34
 
30
35
  def inspect
31
36
  "<#{self.class} :parent => #{parent.inspect} :handled_events => #{event_handlers.keys}>"
32
37
  end
33
38
 
34
- def add_handler(*event_type, &block)
39
+ def on(*event_type, &block)
35
40
  event_handlers[event_type] ||= []
36
41
  event_handlers[event_type] << block
37
42
  end
38
43
 
39
- def add_last_handler(*event_type, &block)
44
+ def on_last(*event_type, &block)
40
45
  event_handlers[event_type] = [block] + (event_handlers[event_type] || [])
41
46
  end
42
47
 
@@ -6,7 +6,7 @@ module Evented
6
6
 
7
7
  # define event handler
8
8
  def on(*args,&block)
9
- event_manager.add_handler *args, &block
9
+ event_manager.on *args, &block
10
10
  self
11
11
  end
12
12
 
@@ -15,11 +15,18 @@ module WindowBlessing
15
15
  # both :change and :refresh events only fire if the value actually changed
16
16
  class EventedVariable
17
17
  include Evented
18
+ include Tools
18
19
 
19
20
  def initialize(value)
20
21
  @value = value
21
22
  end
22
23
 
24
+ # set a block to be called to processes the set value
25
+ # block should return the processed value
26
+ def before_filter(&block)
27
+ @before_filter = block
28
+ end
29
+
23
30
  def inspect
24
31
  "<#{self.class}:#{object_id} value:#{@value.inspect}>"
25
32
  end
@@ -27,9 +34,10 @@ class EventedVariable
27
34
  def get; clone_value(@value) end
28
35
 
29
36
  # update the value & trigger :change and :refresh events
37
+ # returns the old value
30
38
  def set(value)
31
39
  old_value = refresh(value)
32
- handle_event :type => :change, :old_value => old_value, :value => value if old_value != value
40
+ handle_event :type => :change, :old_value => old_value, :value => @value if old_value != @value
33
41
  old_value
34
42
  end
35
43
 
@@ -37,6 +45,7 @@ class EventedVariable
37
45
  # subscribe to :refresh events if you need to know when the value changes, but you shouldn't change any model-state because of it
38
46
  # if you are changing model-state, subscribe to :change
39
47
  def refresh(value)
48
+ value = @before_filter.call(value,@value) if @before_filter
40
49
  old_value = @value
41
50
  @value = value
42
51
  handle_event :type => :refresh, :old_value => old_value, :value => value if old_value != value
@@ -18,7 +18,7 @@ module Tools
18
18
 
19
19
  def clone_value(v)
20
20
  case v
21
- when Fixnum, Bignum, Float then v
21
+ when Fixnum, Bignum, Float, NilClass then v
22
22
  else v.clone
23
23
  end
24
24
  end
@@ -120,5 +120,15 @@ module Tools
120
120
  def color(*args); WindowBlessing::Color.new *args end
121
121
  def window(*args); WindowBlessing::Window.new *args end
122
122
  def buffer(*args); WindowBlessing::Buffer.new *args end
123
+
124
+ def range_length(range)
125
+ if (range.last < 0 && range.first >=0) || (range.last >=0 && range.first < 0) # length depends on the string or array the range is applied to
126
+ nil
127
+ else
128
+ l = range.last - range.first
129
+ l += 1 unless range.exclude_end?
130
+ l
131
+ end
132
+ end
123
133
  end
124
134
  end
@@ -1,3 +1,3 @@
1
1
  module WindowBlessing
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -4,7 +4,7 @@ module DraggableBackground
4
4
 
5
5
  def initialize(*args)
6
6
  super *args
7
- on :pointer, :button1_down do |event| @mouse_offset = event[:loc] end
7
+ on :pointer, :button_down do |event| @mouse_offset = event[:loc] end
8
8
  on :pointer, :drag do |event| self.loc += event[:loc] - @mouse_offset end
9
9
  end
10
10
 
@@ -13,7 +13,7 @@ class Label < WindowBlessing::Window
13
13
 
14
14
  def pointer_inside?(loc) false; end
15
15
 
16
- def draw_internal
16
+ def draw_background
17
17
  buffer.contents = text
18
18
  buffer.fill :fg => fg, :bg => bg
19
19
  end
@@ -39,9 +39,17 @@ class Slider < WindowBlessing::Window
39
39
  end
40
40
  end
41
41
 
42
- def draw_internal
42
+ def handle_area
43
+ rect(point(handle_x,0),point(1,1))
44
+ end
45
+
46
+ def draw_handle
47
+ buffer.fill :area => handle_area, :string => "+"
48
+ end
49
+
50
+ def draw_background
43
51
  super
44
- buffer.fill :area => rect(point(handle_x,0),point(1,1)), :string => "+"
52
+ draw_handle
45
53
  end
46
54
 
47
55
  def handle_x; (value * screen_value_range).to_i end
@@ -80,7 +80,7 @@ class TextField < WindowBlessing::Window
80
80
  def text; evented_value.get end
81
81
  def text=(t); evented_value.set(t) if !validator || t[validator] end
82
82
 
83
- def draw_internal
83
+ def draw_background
84
84
  @cursor_pos = bound(0, @cursor_pos, text.length)
85
85
  buffer.contents = text
86
86
  buffer.fill :fg => fg, :bg => bg
@@ -37,18 +37,22 @@ ENDCODE
37
37
  end
38
38
 
39
39
  # event is in parent-space
40
- def pointer_event(event)
40
+ def route_pointer_event(event)
41
41
  focus
42
+ event = event.clone
42
43
  event[:loc] -= area.loc
44
+
43
45
  @pointer_focused ||= children.reverse_each.find do |child|
44
46
  child.pointer_inside? event[:loc]
45
47
  end || :background
46
- if @pointer_focused==:background
48
+
49
+ if @pointer_focused == :background
47
50
  handle_event(event)
48
51
  else
49
- @pointer_focused.pointer_event event
52
+ @pointer_focused.route_pointer_event event
50
53
  end
51
- @pointer_focused = nil if event[:button] == :button_up
54
+
55
+ @pointer_focused = nil if event[:type][1] == :button_up
52
56
  end
53
57
 
54
58
  module KeyboardFocus
@@ -117,6 +121,8 @@ ENDCODE
117
121
  end
118
122
  end
119
123
 
124
+ def internal_area; rect @area.size end
125
+
120
126
  def loc; area.loc; end
121
127
  def loc=(new_loc) self.area = rect new_loc, area.size end
122
128
 
@@ -131,11 +137,8 @@ ENDCODE
131
137
  self.area = parent_area.bound(area)
132
138
  end
133
139
 
134
- def internal_area; rect(@area.size); end
135
-
136
140
  private
137
141
  def resize_buffer(old_size)
138
- @requested_redraw_area = internal_area | @requested_redraw_area if @requested_redraw_area
139
142
  if area.size <= old_size
140
143
  @buffer = @buffer.subbuffer(rect(area.size))
141
144
  request_redraw
@@ -184,7 +187,7 @@ ENDCODE
184
187
  end
185
188
 
186
189
  def path
187
- [parent && parent.path,"#{self.class}#{self.area}"].flatten.compact.join(',')
190
+ [parent && parent.path,"#{self.class}#{self.area}#{":"+name if name}"].flatten.compact.join(',')
188
191
  end
189
192
 
190
193
  def parent_path
@@ -195,32 +198,36 @@ ENDCODE
195
198
 
196
199
  module Drawing
197
200
  Window.attr_accessor_with_redraw :bg, :fg
198
- attr_reader :requested_redraw_area, :buffer
199
-
200
- # sometimes you want to know where redraw requests are coming from
201
- # Since request_redraw_internal is recursive, you don't want to log the stack trace with every call - just the first one
202
- # This will log a stack-trace once per call
203
- def log_request_redraw_internal
204
- trace = Kernel.caller
205
- return if trace.count {|line| line["request_redraw_internal"]} > 1
206
- log "request_redraw_internal trace @requested_redraw_area=#{@requested_redraw_area} path:#{path}\n "+ trace.join("\n ")
201
+ attr_reader :redraw_areas, :buffer
202
+
203
+ def redraw_areas
204
+ (@redraw_areas && @redraw_areas.areas || [])
207
205
  end
208
206
 
209
- def request_redraw_internal(area = internal_area)
210
- #return if @requested_redraw_area && @requested_redraw_area.contains?(area) - the color_picker demo's info label fails to update with this uncommented - why?
211
- @requested_redraw_area = internal_area | (area & @requested_redraw_area)
212
- #log_request_redraw_internal
207
+ def add_redraw_area(area)
208
+ area = area | internal_area
209
+ (@redraw_areas ||= WindowRedrawAreas.new) << area
210
+ area
211
+ end
213
212
 
214
- request_redraw @requested_redraw_area
213
+ # return redraw_areas after clearing it (returns [] if none)
214
+ def clear_redraw_areas
215
+ ret = redraw_areas
216
+ @redraw_areas = nil
217
+ ret
218
+ end
219
+
220
+ def request_redraw_internal(area = internal_area)
221
+ request_redraw add_redraw_area(area)
215
222
  end
216
223
 
217
224
  # ask the parent to redraw all, or, if area is set, some of the area covered by this window
218
225
  def request_redraw(redraw_area = nil)
219
226
  redraw_area ||= internal_area
220
- parent && parent.request_redraw_internal(rect(redraw_area.loc + @area.loc, redraw_area.size))
227
+ parent && parent.request_redraw_internal(redraw_area + loc)
221
228
  end
222
229
 
223
- def redraw_requested?; !!requested_redraw_area end
230
+ def redraw_requested?; redraw_areas.length > 0 end
224
231
 
225
232
  # Reset @buffer to the designated background. The default implementation resets it to the ' ' character with @bg and @fg colors.
226
233
  #
@@ -238,34 +245,30 @@ ENDCODE
238
245
  # NOTE: Buffer may have a cropping area set
239
246
  #
240
247
  # NOTE: Safe to override. Calling 'super' is optional.
241
- def draw_internal
242
- draw_background
243
- children.each do |child|
244
- child.draw buffer, (buffer.crop_area - child.loc)
248
+ def draw_internal(area = nil)
249
+ buffer.cropped(area) do
250
+ draw_background
251
+ children.each do |child|
252
+ child.draw buffer, buffer.crop_area - child.loc
253
+ end
245
254
  end
246
255
  end
247
256
 
248
- # marks "redrawn_area" of @buffer "up to date" (redraw no longer required)
249
- def clean(redrawn_area = @requested_redraw_area)
250
- @requested_redraw_area = nil if redrawn_area && redrawn_area.contains?(@requested_redraw_area)
257
+ # perform the request redraws
258
+ # return the areas redrawn (returns [] if none)
259
+ def redraw
260
+ clear_redraw_areas.each {|area| draw_internal area}
251
261
  end
252
262
 
253
263
  # Draw the window:
254
264
  #
255
- # 1) Draw the specified internal_area, or @requested_redraw_area by default, into @buffer
256
- # 2) Draw @buffer to target_buffer (if set)
257
- # 3) returns the internal_area that was updated
258
- def draw(target_buffer = nil, internal_area = @requested_redraw_area)
259
- internal_area = self.internal_area | internal_area
260
-
261
- if internal_area.overlaps? @requested_redraw_area
262
- buffer.cropped(internal_area | @requested_redraw_area) {draw_internal}
263
- clean internal_area
264
- end
265
-
266
- target_buffer.draw_buffer(loc, buffer, internal_area) if target_buffer
267
-
268
- internal_area
265
+ # 1) Draw all requested internal redraw areas, and clear all requests.
266
+ # 2) Draw @buffer to target_buffer. Optionally, only draw the specified internal_area.
267
+ # 3) return an array of internal areas redrawn
268
+ def draw(target_buffer = nil, internal_area = self.internal_area)
269
+ ret = redraw
270
+ target_buffer.draw_buffer loc, buffer, internal_area if target_buffer
271
+ ret
269
272
  end
270
273
  end
271
274
  include Drawing