Class: Kaitai::Struct::Visualizer::Tree

Inherits:
Object
  • Object
show all
Defined in:
lib/kaitai/struct/visualizer/tree.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ui, st) ⇒ Tree

Returns a new instance of Tree.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 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]'
  @max_scr_ln = @ui.rows - 3

  @hv_shift_x = @ui.cols - HexViewer.line_width - 1

  @cur_io = nil
  @hv = HexViewer.new(ui, nil, @hv_shift_x, self)
  @hv_hidden = false

  @cur_line = 0
  @cur_shift = 0
  @do_exit = false
end

Class Method Details

.explore_object(obj, level) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/kaitai/struct/visualizer/tree.rb', line 228

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

Instance Method Details

#clamp_cursorObject



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/kaitai/struct/visualizer/tree.rb', line 140

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_exitObject



193
194
195
# File 'lib/kaitai/struct/visualizer/tree.rb', line 193

def do_exit
  @do_exit = true
end

#draw_rec(n) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/kaitai/struct/visualizer/tree.rb', line 162

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) ⇒ Object



209
210
211
212
213
214
215
216
217
218
# File 'lib/kaitai/struct/visualizer/tree.rb', line 209

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_ioObject



197
198
199
200
201
202
203
204
205
206
207
# File 'lib/kaitai/struct/visualizer/tree.rb', line 197

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_keypressObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/kaitai/struct/visualizer/tree.rb', line 78

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

#redrawObject



153
154
155
156
157
158
159
160
# File 'lib/kaitai/struct/visualizer/tree.rb', line 153

def redraw
  @draw_time = 0
  Benchmark.realtime {
    @ui.clear
    @ln = 0
    draw_rec(@root)
  }
end

#runObject



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/kaitai/struct/visualizer/tree.rb', line 27

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_widthObject



220
221
222
223
224
225
226
# File 'lib/kaitai/struct/visualizer/tree.rb', line 220

def tree_width
  if @hv_hidden
    @ui.cols
  else
    @hv_shift_x
  end
end