mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-09 09:32:20 +00:00
More general fixes to the tree view and BoxedPanel.
llvm-svn: 250478
This commit is contained in:
parent
09c1ffdc8f
commit
c12cc596ed
@ -12,6 +12,12 @@ class Point(object):
|
||||
|
||||
def __str__(self):
|
||||
return "(x=%u, y=%u)" % (self.x, self.y)
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return self.x == rhs.x and self.y == rhs.y
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return self.x != rhs.x or self.y != rhs.y
|
||||
|
||||
def is_valid_coordinate(self):
|
||||
return self.x >= 0 and self.y >= 0
|
||||
@ -27,6 +33,12 @@ class Size(object):
|
||||
def __str__(self):
|
||||
return "(w=%u, h=%u)" % (self.w, self.h)
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return self.w == rhs.w and self.h == rhs.h
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return self.w != rhs.w or self.h != rhs.h
|
||||
|
||||
class Rect(object):
|
||||
def __init__(self, x=0, y=0, w=0, h=0):
|
||||
self.origin = Point(x, y)
|
||||
@ -57,6 +69,12 @@ class Rect(object):
|
||||
return pt.y >= self.get_min_y()
|
||||
return False
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return self.origin == rhs.origin and self.size == rhs.size
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return self.origin != rhs.origin or self.size != rhs.size
|
||||
|
||||
class QuitException(Exception):
|
||||
def __init__(self):
|
||||
super(QuitException, self).__init__('QuitException')
|
||||
@ -74,7 +92,47 @@ class Window(object):
|
||||
def add_child(self, window):
|
||||
self.children.append(window)
|
||||
window.parent = self
|
||||
|
||||
def resize(self, size):
|
||||
self.window.resize(size.h, size.w)
|
||||
|
||||
def resize_child(self, child, delta_size, adjust_neighbors):
|
||||
if child in self.children:
|
||||
frame = self.get_frame()
|
||||
orig_frame = child.get_frame()
|
||||
new_frame = Rect(x=orig_frame.origin.x, y=orig_frame.origin.y, w=orig_frame.size.w + delta_size.w, h=orig_frame.size.h + delta_size.h)
|
||||
old_child_max_x = orig_frame.get_max_x()
|
||||
new_child_max_x = new_frame.get_max_x()
|
||||
window_max_x = frame.get_max_x()
|
||||
if new_child_max_x < window_max_x:
|
||||
child.resize(new_frame.size)
|
||||
if old_child_max_x == window_max_x:
|
||||
new_frame.origin.x += window_max_x - new_child_max_x
|
||||
child.set_position(new_frame.origin)
|
||||
elif new_child_max_x > window_max_x:
|
||||
new_frame.origin.x -= new_child_max_x - window_max_x
|
||||
child.set_position(new_frame.origin)
|
||||
child.resize(new_frame.size)
|
||||
|
||||
if adjust_neighbors:
|
||||
#print 'orig_frame = %s\r\n' % (str(orig_frame)),
|
||||
for curr_child in self.children:
|
||||
if curr_child is child:
|
||||
continue
|
||||
curr_child_frame = curr_child.get_frame()
|
||||
if delta_size.w != 0:
|
||||
#print 'curr_child_frame = %s\r\n' % (str(curr_child_frame)),
|
||||
if curr_child_frame.get_min_x() == orig_frame.get_max_x():
|
||||
curr_child_frame.origin.x += delta_size.w
|
||||
curr_child_frame.size.w -= delta_size.w
|
||||
#print 'adjusted curr_child_frame = %s\r\n' % (str(curr_child_frame)),
|
||||
curr_child.resize (curr_child_frame.size)
|
||||
curr_child.slide_position (Size(w=delta_size.w, h=0))
|
||||
elif curr_child_frame.get_max_x() == orig_frame.get_min_x():
|
||||
curr_child_frame.size.w -= delta_size.w
|
||||
#print 'adjusted curr_child_frame = %s\r\n' % (str(curr_child_frame)),
|
||||
curr_child.resize (curr_child_frame.size)
|
||||
|
||||
def add_key_action(self, arg, callback, decription):
|
||||
if isinstance(arg, list):
|
||||
for key in arg:
|
||||
@ -270,6 +328,15 @@ class Window(object):
|
||||
size = self.get_size()
|
||||
return Rect(x=position.x, y=position.y, w=size.w, h=size.h)
|
||||
|
||||
def get_frame_in_parent(self):
|
||||
position = self.get_position_in_parent()
|
||||
size = self.get_size()
|
||||
return Rect(x=position.x, y=position.y, w=size.w, h=size.h)
|
||||
|
||||
def get_position_in_parent(self):
|
||||
(y, x) = self.window.getparyx()
|
||||
return Point(x, y)
|
||||
|
||||
def get_position(self):
|
||||
(y, x) = self.window.getbegyx()
|
||||
return Point(x, y)
|
||||
@ -349,6 +416,16 @@ class Window(object):
|
||||
done = False
|
||||
while not done and n > 0:
|
||||
c = self.window.getch()
|
||||
if c == 27:
|
||||
self.timeout(0)
|
||||
escape_key = 0
|
||||
while True:
|
||||
escape_key = self.window.getch()
|
||||
if escape_key == -1:
|
||||
break
|
||||
else:
|
||||
c = c << 8 | escape_key
|
||||
self.timeout(timeout_msec)
|
||||
if c != -1:
|
||||
try:
|
||||
self.handle_key(c)
|
||||
@ -377,10 +454,10 @@ class Panel(Window):
|
||||
def set_position(self, pt):
|
||||
self.panel.move(pt.y, pt.x)
|
||||
|
||||
def slide_position(self, pt):
|
||||
def slide_position(self, size):
|
||||
new_position = self.get_position()
|
||||
new_position.x = new_position.x + pt.x
|
||||
new_position.y = new_position.y + pt.y
|
||||
new_position.x = new_position.x + size.w
|
||||
new_position.y = new_position.y + size.h
|
||||
self.set_position(new_position)
|
||||
|
||||
class BoxedPanel(Panel):
|
||||
@ -394,6 +471,8 @@ class BoxedPanel(Panel):
|
||||
self.add_key_action(curses.KEY_DOWN, self.select_next, "Select the next item")
|
||||
self.add_key_action(curses.KEY_HOME, self.scroll_begin, "Go to the beginning of the list")
|
||||
self.add_key_action(curses.KEY_END, self.scroll_end, "Go to the end of the list")
|
||||
self.add_key_action(0x1b4f48, self.scroll_begin, "Go to the beginning of the list")
|
||||
self.add_key_action(0x1b4f46, self.scroll_end, "Go to the end of the list")
|
||||
self.add_key_action(curses.KEY_PPAGE, self.scroll_page_backward, "Scroll to previous page")
|
||||
self.add_key_action(curses.KEY_NPAGE, self.scroll_page_forward, "Scroll to next forward")
|
||||
self.update()
|
||||
@ -436,6 +515,14 @@ class BoxedPanel(Panel):
|
||||
if update:
|
||||
self.update()
|
||||
|
||||
def scroll_to_line (self, idx):
|
||||
if idx < len(self.lines):
|
||||
self.selected_idx = idx
|
||||
max_visible_lines = self.get_usable_height()
|
||||
if idx < self.first_visible_idx or idx >= self.first_visible_idx + max_visible_lines:
|
||||
self.first_visible_idx = idx
|
||||
self.refresh()
|
||||
|
||||
def scroll_begin (self):
|
||||
self.first_visible_idx = 0
|
||||
if len(self.lines) > 0:
|
||||
@ -521,12 +608,25 @@ class BoxedPanel(Panel):
|
||||
is_selected = line_idx == self.selected_idx
|
||||
if is_selected:
|
||||
self.attron (curses.A_REVERSE)
|
||||
self.addnstr_at_point(pt, self.lines[line_idx], max_width)
|
||||
self.move(pt)
|
||||
self.addnstr(self.lines[line_idx], max_width)
|
||||
if is_selected:
|
||||
self.attroff (curses.A_REVERSE)
|
||||
else:
|
||||
return
|
||||
|
||||
def load_file(self, path):
|
||||
f = open(path)
|
||||
if f:
|
||||
self.lines = f.read().splitlines()
|
||||
for (idx, line) in enumerate(self.lines):
|
||||
# Remove any tabs from lines since they hose up the display
|
||||
if "\t" in line:
|
||||
self.lines[idx] = (8*' ').join(line.split('\t'))
|
||||
self.selected_idx = 0
|
||||
self.first_visible_idx = 0
|
||||
self.refresh()
|
||||
|
||||
class Item(object):
|
||||
def __init__(self, title, action):
|
||||
self.title = title
|
||||
@ -549,6 +649,9 @@ class TreeItemDelegate(object):
|
||||
|
||||
def draw_item(self, tree_window, item):
|
||||
self.draw_item_string(tree_window, item, item.title)
|
||||
|
||||
def do_action(self):
|
||||
pass
|
||||
|
||||
class TreeItem(object):
|
||||
def __init__(self, delegate, parent = None, title = None, action = None, is_expanded = False):
|
||||
@ -608,8 +711,9 @@ class TreeItem(object):
|
||||
rows = 1
|
||||
if self.is_expanded:
|
||||
children = self.get_children()
|
||||
for child in children:
|
||||
rows += child.get_num_visible_rows()
|
||||
if children:
|
||||
for child in children:
|
||||
rows += child.get_num_visible_rows()
|
||||
return rows
|
||||
def draw(self, tree_window, row):
|
||||
display_row = tree_window.get_display_row(row)
|
||||
@ -621,8 +725,12 @@ class TreeItem(object):
|
||||
tree_window.addch (curses.ACS_DIAMOND)
|
||||
tree_window.addch (curses.ACS_HLINE)
|
||||
elif self.parent and self.parent.children_might_have_children():
|
||||
tree_window.addch (curses.ACS_HLINE)
|
||||
tree_window.addch (curses.ACS_HLINE)
|
||||
if self.parent.parent:
|
||||
tree_window.addch (curses.ACS_HLINE)
|
||||
tree_window.addch (curses.ACS_HLINE)
|
||||
else:
|
||||
tree_window.addch (' ')
|
||||
tree_window.addch (' ')
|
||||
is_selected = tree_window.is_selected(row)
|
||||
if is_selected:
|
||||
tree_window.attron (curses.A_REVERSE)
|
||||
@ -650,8 +758,8 @@ class TreeItem(object):
|
||||
tree_window.addch (curses.ACS_VLINE)
|
||||
tree_window.addch (' ')
|
||||
|
||||
def was_selected(self):
|
||||
pass
|
||||
def was_selected(self):
|
||||
self.delegate.do_action()
|
||||
|
||||
class TreePanel(Panel):
|
||||
def __init__(self, frame, title, root_item):
|
||||
@ -665,8 +773,10 @@ class TreePanel(Panel):
|
||||
self.add_key_action(curses.KEY_DOWN, self.select_next, "Select the next item")
|
||||
self.add_key_action(curses.KEY_RIGHT,self.right_arrow, "Expand an item")
|
||||
self.add_key_action(curses.KEY_LEFT, self.left_arrow, "Unexpand an item or navigate to parent")
|
||||
self.add_key_action(curses.KEY_HOME, self.scroll_begin, "Go to the beginning of the list")
|
||||
self.add_key_action(curses.KEY_END, self.scroll_end, "Go to the end of the list")
|
||||
self.add_key_action(curses.KEY_HOME, self.scroll_begin, "Go to the beginning of the tree")
|
||||
self.add_key_action(curses.KEY_END, self.scroll_end, "Go to the end of the tree")
|
||||
self.add_key_action(0x1b4f48, self.scroll_begin, "Go to the beginning of the tree")
|
||||
self.add_key_action(0x1b4f46, self.scroll_end, "Go to the end of the tree")
|
||||
self.add_key_action(curses.KEY_PPAGE, self.scroll_page_backward, "Scroll to previous page")
|
||||
self.add_key_action(curses.KEY_NPAGE, self.scroll_page_forward, "Scroll to next forward")
|
||||
|
||||
@ -717,12 +827,9 @@ class TreePanel(Panel):
|
||||
def is_selected(self, row):
|
||||
return row == self.selected_idx
|
||||
|
||||
def get_num_lines(self):
|
||||
rows = 0
|
||||
children = self.root_item.get_children()
|
||||
for child in children:
|
||||
rows += child.get_num_visible_rows()
|
||||
return rows
|
||||
def get_num_lines(self):
|
||||
self.get_visible_items()
|
||||
return len(self.items)
|
||||
|
||||
def get_num_visible_lines(self):
|
||||
return self.get_size().h-2
|
||||
@ -730,7 +837,8 @@ class TreePanel(Panel):
|
||||
self.selected_idx += 1
|
||||
num_lines = self.get_num_lines()
|
||||
if self.selected_idx >= num_lines:
|
||||
self.selected_idx = num_lines - 1
|
||||
self.selected_idx = num_lines - 1
|
||||
self._selection_changed()
|
||||
self.refresh()
|
||||
|
||||
def select_prev (self):
|
||||
@ -741,6 +849,7 @@ class TreePanel(Panel):
|
||||
self.selected_idx = 0
|
||||
else:
|
||||
self.selected_idx = -1
|
||||
self._selection_changed()
|
||||
self.refresh()
|
||||
|
||||
def scroll_begin (self):
|
||||
@ -750,7 +859,7 @@ class TreePanel(Panel):
|
||||
self.selected_idx = 0
|
||||
else:
|
||||
self.selected_idx = -1
|
||||
self.update()
|
||||
self.refresh()
|
||||
|
||||
def redisplay_tree(self):
|
||||
self.items = None
|
||||
@ -775,35 +884,45 @@ class TreePanel(Panel):
|
||||
|
||||
def scroll_end (self):
|
||||
num_visible_lines = self.get_num_visible_lines()
|
||||
num_lines = len(self.lines)
|
||||
num_lines = self.get_num_lines()
|
||||
if num_lines > num_visible_lines:
|
||||
self.first_visible_idx = num_lines - num_visible_lines
|
||||
else:
|
||||
self.first_visible_idx = 0
|
||||
self.selected_idx = num_lines-1
|
||||
self.update()
|
||||
self.refresh()
|
||||
|
||||
def scroll_page_backward(self):
|
||||
num_visible_lines = self.get_num_visible_lines()
|
||||
new_index = self.first_visible_idx - num_visible_lines
|
||||
new_index = self.selected_idx - num_visible_lines
|
||||
if new_index < 0:
|
||||
self.first_visible_idx = 0
|
||||
self.selected_idx = 0
|
||||
else:
|
||||
self.first_visible_idx = new_index
|
||||
self.selected_idx = new_index
|
||||
self._selection_changed()
|
||||
self.refresh()
|
||||
|
||||
def scroll_page_forward(self):
|
||||
num_lines = self.get_num_lines()
|
||||
num_visible_lines = self.get_num_visible_lines()
|
||||
self.first_visible_idx += num_visible_lines
|
||||
self._adjust_first_visible_line()
|
||||
new_index = self.selected_idx + num_visible_lines
|
||||
if new_index >= num_lines:
|
||||
new_index = num_lines - 1
|
||||
self.selected_idx = new_index
|
||||
self._selection_changed()
|
||||
self.refresh()
|
||||
|
||||
def _adjust_first_visible_line(self):
|
||||
num_lines = len(self.lines)
|
||||
def _selection_changed(self):
|
||||
num_lines = self.get_num_lines()
|
||||
num_visible_lines = self.get_num_visible_lines()
|
||||
if (self.first_visible_idx >= num_lines) or (num_lines - self.first_visible_idx) > num_visible_lines:
|
||||
self.first_visible_idx = num_lines - num_visible_lines
|
||||
|
||||
last_visible_index = self.first_visible_idx + num_visible_lines
|
||||
if self.selected_idx >= last_visible_index:
|
||||
self.first_visible_idx += (self.selected_idx - last_visible_index + 1)
|
||||
if self.selected_idx < self.first_visible_idx:
|
||||
self.first_visible_idx = self.selected_idx
|
||||
if self.selected_idx >= 0 and self.selected_idx < len(self.items):
|
||||
item = self.items[self.selected_idx]
|
||||
item.was_selected()
|
||||
|
||||
|
||||
class Menu(BoxedPanel):
|
||||
|
Loading…
Reference in New Issue
Block a user