require "gui_geometry" module WindowBlessing module Tools include GuiGeo::Tools # returns pos, span # on return, pos is within 0..length and pos + span.length is <= length def overlapping_span(pos, span, length) if pos <= -span.length || pos >= length || length <= 0 return length, span.class.new elsif pos < 0 span = span[-pos..-1] pos = 0 end return pos, span[0..(length - pos - 1)] end def clone_value(v) case v when Fixnum, Bignum, Float, NilClass then v else v.clone end end # if the block is provided, yields the source elements and the target elements they are overlaying, in order, one at a time def overlay_span(pos, source_span, target_span, &block) pos, span = overlapping_span pos, source_span, target_span.length return target_span if span.length == 0 if block span = span.each_with_index.collect {|s,i| yield s, target_span[i+pos]} end if pos == 0 span + target_span[span.length..-1] else target_span[0..pos-1] + span + target_span[pos + span.length..-1] end end def overlay2d(loc, source, target) overlay_span(loc.y, source, target) do |s, t| overlay_span loc.x, s, t end end def resize2d(array2d, size, blank_element) array2d ||= [] blank_element = [blank_element] unless blank_element.kind_of?(String) if array2d.length != size.y array2d = array2d[0..(size.y-1)] blank_line = blank_element * size.x array2d += (size.y - array2d.length).times.collect {blank_line.clone} end array2d.collect do |line| if line.length!=size.x line = line[0..(size.x-1)] line + blank_element * (size.x - line.length) else line end end end def subarray2d(array2d, area) size = point(array2d[0].length,array2d.length) area = area | rect(size) x_range = area.x_range array2d[area.y_range].collect do |line| line[x_range] end end def fill_line(fill, length) line = fill * (length/fill.length) line = (line+fill)[0..length-1] if line.length != length line end def gen_array2d(size, fill) fill = case fill when String, Array then fill else [fill] end a = (size.x * size.y) full = fill * ((a / fill.length) + 1) if fill.kind_of?(String) full.scan /.{#{size.x}}/ else full.each_slice(size.x).collect {|a|a} end[0..size.y-1] end # r, g, b are in 0..1 def rgb_screen_color(r, g, b) return gray_screen_color(r) if r==g && g==b 16 + (r*5.9).to_i * 36 + (g*5.9).to_i * 6 + (b*5.9).to_i end # g is in 0..1 def gray_screen_color(g) g = (g*24.9).to_i case g when 0 then 0 when 24 then 15 else 232 + g end end def log(str); XtermLog.log "#{self.inspect}: #{str}" end def color(*args); WindowBlessing::Color.new *args end def window(*args); WindowBlessing::Window.new *args end def buffer(*args); WindowBlessing::Buffer.new *args end def range_length(range) 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 nil else l = range.last - range.first l += 1 unless range.exclude_end? l end end end end