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

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

Instance Method Summary collapse

Constructor Details

#initialize(ui, st) ⇒ Tree

Returns a new instance of Tree.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/kaitai/struct/visualizer/tree.rb', line 12

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 { |redraw_needed|
    recalc_sizes
    redraw      if redraw_needed
    @hv.redraw  if redraw_needed
  }
end

Instance Method Details

#clamp_cursorObject



148
149
150
151
152
153
154
155
# File 'lib/kaitai/struct/visualizer/tree.rb', line 148

def clamp_cursor
  return unless @cur_line

  @cur_line = 0 if @cur_line.negative?

  @cur_shift = @cur_line if (@cur_line - @cur_shift).negative?
  @cur_shift = @cur_line - @max_scr_ln if (@cur_line - @cur_shift) > @max_scr_ln
end

#do_exitObject



198
199
200
# File 'lib/kaitai/struct/visualizer/tree.rb', line 198

def do_exit
  @do_exit = true
end

#draw_rec(n) ⇒ Object



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
192
193
194
195
196
# File 'lib/kaitai/struct/visualizer/tree.rb', line 166

def draw_rec(n)
  scr_ln = @ln - @cur_shift
  return if @cur_node && (scr_ln > @max_scr_ln)

  if @ln == @cur_line
    # Seeking cur_node by cur_line
    @cur_node = n
    @ui.bg_color = :white
    @ui.fg_color = :black
  elsif @cur_node == n
    # Seeking cur_line by cur_node
    @cur_line = @ln
    @ui.bg_color = :white
    @ui.fg_color = :black
  end

  @draw_time += Benchmark.realtime do
    # n.draw(@ui) if scr_ln >= 0
    n.draw(@ui) if (scr_ln >= 0) && (scr_ln <= @max_scr_ln)
  end

  @ui.reset_colors if @ln == @cur_line
  @ln += 1

  return unless n.open?

  n.children.each do |ch|
    draw_rec(ch)
    break if scr_ln > @max_scr_ln
  end
end

#highlight_regions(max_levels) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
# File 'lib/kaitai/struct/visualizer/tree.rb', line 214

def highlight_regions(max_levels)
  node = @cur_node
  r = []
  max_levels.times do |_i|
    return r if node.nil?

    r << [node.pos1, node.pos2]
    node = node.parent
  end
  r
end

#hv_update_ioObject



202
203
204
205
206
207
208
209
210
211
212
# File 'lib/kaitai/struct/visualizer/tree.rb', line 202

def hv_update_io
  io = @cur_node.io
  return unless io != @cur_io

  @cur_io = io
  io.seek(0)
  buf = io.read_bytes_full
  @hv.buf = buf

  # @hv.redraw
end

#process_keypressObject



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
139
140
141
142
143
144
145
146
# File 'lib/kaitai/struct/visualizer/tree.rb', line 86

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_sizesObject



35
36
37
38
# File 'lib/kaitai/struct/visualizer/tree.rb', line 35

def recalc_sizes
  @max_scr_ln = @ui.rows - 3
  @hv.shift_x = @ui.cols - HexViewer.line_width - 1
end

#redrawObject



157
158
159
160
161
162
163
164
# File 'lib/kaitai/struct/visualizer/tree.rb', line 157

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

#runObject



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
77
78
79
80
81
82
83
84
# File 'lib/kaitai/struct/visualizer/tree.rb', line 40

def run
  loop do
    t = redraw

    if @cur_node.nil? && !@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 do
      unless @hv_hidden
        hv_update_io

        if !@cur_node.pos1.nil? && ((@hv.addr < @cur_node.pos1) || (@hv.addr >= @cur_node.pos2))
          @hv.addr = @cur_node.pos1
          @hv.ensure_visible
        end

        @hv.redraw
        regs = highlight_regions(4)
        @hv.highlight(regs)
      end
    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 Kaitai::Struct::Visualizer::KSErrorMatcher => e
      @ui.message_box_exception(e)
    end

    return if @do_exit

    clamp_cursor
  end
end

#tree_widthObject



226
227
228
229
230
231
232
# File 'lib/kaitai/struct/visualizer/tree.rb', line 226

def tree_width
  if @hv_hidden
    @ui.cols
  else
    @hv.shift_x
  end
end