class Kaitai::Struct::Visualizer::Tree
Public Class Methods
explore_object(obj, level)
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 238 def self.explore_object(obj, level) root = Node.new(obj, level) if obj.is_a?(Fixnum) or obj.is_a?(String) # do nothing else elsif obj.is_a?(Array) root = Node.new(obj, level) obj.each_with_index { |el, i| n = explore_object(el, level + 1) n.id = i root.add(n) } else root = Node.new(obj, level) obj.instance_variables.each { |k| k = k.to_s next if k =~ /^@_/ el = obj.instance_eval(k) n = explore_object(el, level + 1) n.id = k root.add(n) } end root end
new(ui, st)
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 9 def initialize(ui, st) @ui = ui @st = st @root = Node.new(self, st, 0) @root.id = '[root]' @cur_io = nil @hv = HexViewer.new(ui, nil, self) @hv_hidden = false recalc_sizes @cur_line = 0 @cur_shift = 0 @do_exit = false @ui.on_resize = proc { recalc_sizes redraw @hv.redraw } end
Public Instance Methods
clamp_cursor()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 150 def clamp_cursor if @cur_line @cur_line = 0 if @cur_line < 0 if @cur_line - @cur_shift < 0 @cur_shift = @cur_line end if @cur_line - @cur_shift > @max_scr_ln @cur_shift = @cur_line - @max_scr_ln end end end
do_exit()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 203 def do_exit @do_exit = true end
draw_rec(n)
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 172 def draw_rec(n) scr_ln = @ln - @cur_shift return if @cur_node and scr_ln > @max_scr_ln if @ln == @cur_line # Seeking cur_node by cur_line @cur_node = n @ui.bg_color = :gray @ui.fg_color = :black elsif @cur_node == n # Seeking cur_line by cur_node @cur_line = @ln @ui.bg_color = :gray @ui.fg_color = :black end @draw_time += Benchmark.realtime { # n.draw(@ui) if scr_ln >= 0 n.draw(@ui) if scr_ln >= 0 and scr_ln <= @max_scr_ln } @ui.reset_colors if @ln == @cur_line @ln += 1 if n.open? n.children.each { |ch| draw_rec(ch) break if scr_ln > @max_scr_ln } end end
highlight_regions(max_levels)
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 219 def highlight_regions(max_levels) node = @cur_node r = [] max_levels.times { |i| return r if node.nil? r << [node.pos1, node.pos2] node = node.parent } r end
hv_update_io()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 207 def hv_update_io io = @cur_node.io if io != @cur_io @cur_io = io io.seek(0) buf = io.read_bytes_full @hv.buf = buf # @hv.redraw end end
process_keypress()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 88 def process_keypress c = @ui.read_char_mapped case c when :up_arrow @cur_line -= 1 @cur_node = nil when :down_arrow @cur_line += 1 @cur_node = nil when :left_arrow if @cur_node.open? @cur_node.close else par = @cur_node.parent if par @cur_line = nil @cur_node = par end end when :right_arrow if @cur_node.openable? if @cur_node.open? @cur_line += 1 @cur_node = nil else @cur_node.open end end when :home @cur_line = @cur_shift = 0 @cur_node = nil when :end @cur_line = @root.height - 1 @cur_node = nil when :pg_up @cur_line -= 20 @cur_node = nil when :pg_dn @cur_line += 20 @cur_node = nil when :enter if @cur_node.hex? @ui.clear hv = HexViewer.new(@ui, @cur_node.value) hv.redraw hv.run @ui.clear redraw else @cur_node.toggle end when :tab @hv.run when 'H' @hv_hidden = !@hv_hidden @ui.clear redraw when 'q' @do_exit = true end end
recalc_sizes()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 32 def recalc_sizes @max_scr_ln = @ui.rows - 3 @hv.shift_x = @ui.cols - HexViewer.line_width - 1 end
redraw()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 163 def redraw @draw_time = 0 Benchmark.realtime { @ui.clear @ln = 0 draw_rec(@root) } end
run()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 37 def run c = nil loop { t = redraw if @cur_node.nil? and not @cur_line.nil? # gone beyond the end of the tree @cur_line = @root.height - 1 clamp_cursor redraw end raise '@cur_line is undetermined' if @cur_line.nil? raise '@cur_node is undetermined' if @cur_node.nil? thv = Benchmark.realtime { unless @hv_hidden hv_update_io unless @cur_node.pos1.nil? if (@hv.addr < @cur_node.pos1) or (@hv.addr >= @cur_node.pos2) @hv.addr = @cur_node.pos1 @hv.ensure_visible end end @hv.redraw regs = highlight_regions(4) @hv.highlight(regs) end } @ui.goto(0, @max_scr_ln + 1) printf "all: %d, tree: %d, tree_draw: %d, hexview: %d, ln: %d, ", (t + thv) * 1e6, t * 1e6, @draw_time * 1e6, thv * 1e6, @ln puts "highlight = #{@cur_node.pos1}..#{@cur_node.pos2}" #puts "keypress: #{c.inspect}" begin process_keypress rescue EOFError => e @ui.message_box_exception(e) rescue Kaitai::Struct::Stream::UnexpectedDataError => e @ui.message_box_exception(e) end return if @do_exit clamp_cursor } end
tree_width()
click to toggle source
# File lib/kaitai/struct/visualizer/tree.rb, line 230 def tree_width if @hv_hidden @ui.cols else @hv.shift_x end end