window_blessing 0.0.1 → 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.
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