More improvements:
authorJorge Gorbe <j.gorbe@stcsl.es>
Tue, 6 Nov 2012 19:03:54 +0000 (20:03 +0100)
committerJorge Gorbe <j.gorbe@stcsl.es>
Tue, 6 Nov 2012 19:03:54 +0000 (20:03 +0100)
- Highlight pointed nodes if a pointer is selected in treeview
- Expression text entry works
- Arrow labels are correctly placed now :)

samples/test4.cc
samples/view.py

index 607a0e9722e9007e46b7a9fe57b374d70f004069..576cab02e9a0b4b9f8dbcb5c208a0dabf3791745 100644 (file)
@@ -9,4 +9,7 @@ int main()
     m["lolailo"]=3;
     m["xyz"]=4;
     m["meh"]=5;
+
+    auto i = m.find("xyz");
+    return i->second;
 }
index 31b9999f9ded2a2c18f49e1646853cbfbdcd25ad..70f9a636d6cbdca3b0c2bb7f9962406d201fb45c 100644 (file)
@@ -1,6 +1,7 @@
 import gdb
 import gdb.types
 import gtk
+import cairo
 import pango
 import pangocairo
 import math
@@ -119,7 +120,6 @@ def arrow_points(A, B):
 
 class GraphViewerNode():
     def __init__(self, x, y, name, gdb_value):
-        print "node created: %d, %d, %s, %s"% (x, y, name, gdb_value.address)
         self.x = x
         self.y = y
         self.width = 30
@@ -132,33 +132,38 @@ class GraphViewerNode():
 
 
 
-class GraphViewer(gtk.DrawingArea):
+class GraphViewer(gtk.Layout):
     def __init__(self, value_viewer):
-        super(gtk.DrawingArea, self).__init__()
+        super(gtk.Layout, self).__init__()
         self.nodes = []
-        self.selected_node = None
+        self.selected_node = None     # node selected by clicking on it
+        self.highlighted_node = None  # node highlighted by selecting its address on the treeview
         self.value_viewer = value_viewer
         self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
         self.connect("expose_event", self.on_expose)
         self.connect("button_press_event", self.on_click)
 
     def on_expose(self, widget, event):
-        context = pangocairo.CairoContext(widget.window.cairo_create())
+        context = pangocairo.CairoContext(widget.bin_window.cairo_create())
         context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
         context.clip()
+        context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
         self.draw(context)
         return False
 
     def on_click(self, widget, event):
-        self.selected_node = None
+        new_selected_node = None
         for node in self.nodes:
             if event.x >= node.x and event.x < node.x + node.width and event.y >= node.y and event.y < node.y + node.height:
-                self.selected_node = node
+                new_selected_node = node
 
-        if self.selected_node != None:
-             self.value_viewer.set_value(self.selected_node.gdb_value)
+        if new_selected_node is not self.selected_node:
+            self.selected_node = new_selected_node
+            if self.selected_node is not None:
+                 self.value_viewer.set_value(self.selected_node.gdb_value)
+
+            self.queue_draw()
 
-        self.queue_draw()
         return False
 
 
@@ -167,6 +172,7 @@ class GraphViewer(gtk.DrawingArea):
         name_layout = context.create_layout()
         name_layout.set_font_description(pango.FontDescription("sans 8"))
         display_name = str(node.gdb_value.address) #node.name
+        #display_name = node.name
         if node is not self.selected_node:
             template_args_start = display_name.find("<")
             if template_args_start != -1:
@@ -184,6 +190,9 @@ class GraphViewer(gtk.DrawingArea):
         if node is self.selected_node:
             context.set_source_rgb(1,0,0)
             context.set_line_width(3)
+        elif node is self.highlighted_node:
+            context.set_source_rgb(0.3,0.7,0.4)
+            context.set_line_width(3)
         context.rectangle(node.x, node.y, node.width, node.height)
         context.stroke()
         context.restore()
@@ -215,10 +224,18 @@ class GraphViewer(gtk.DrawingArea):
         vy = p2[1]-p1[1]
         name_layout = context.create_layout()
         name_layout.set_font_description(pango.FontDescription("sans 8"))
-        name_layout.set_text(name)
+        name_layout.set_text(u"\u2192"+name)
         _, name_height = name_layout.get_pixel_size()
-        context.move_to((1-NAME_OFFSET)*p1[0] + NAME_OFFSET*p2[0], (1-NAME_OFFSET)*p1[1] + NAME_OFFSET*p2[1])
-        context.rotate(-orientation(vx, vy))
+        rotation = -orientation(vx, vy)
+        y_offset = -name_height - 2 # a couple of extra pixels to avoid text "stepping on the line"
+
+        # cairo seems to ignore context.translate for text ops, but set_matrix works ok :D
+        transform = cairo.Matrix()
+        transform.translate((1-NAME_OFFSET)*p1[0] + NAME_OFFSET*p2[0], (1-NAME_OFFSET)*p1[1] + NAME_OFFSET*p2[1] )
+        transform.rotate(rotation)
+        transform.translate(0, y_offset)
+        context.set_matrix(transform)
+        context.set_source_rgb(1,0,0)
         context.show_layout(name_layout)
         context.restore()
 
@@ -270,6 +287,27 @@ class GdbValueViewer(gtk.TreeView):
         self.set_search_column(0)
         self.field_column.set_sort_column_id(0)
 
+        self.selection = self.get_selection()
+        self.selection.set_mode(gtk.SELECTION_SINGLE)
+        self.selection.connect("changed", self.on_selection_changed)
+
+    def on_selection_changed(self, selection):
+        (model, iterator) = selection.get_selected()
+        new_highlighted_node = None
+
+        if iterator is not None:
+            value = model.get_value(iterator, 1)
+            for node in self.graph_viewer.nodes:
+                if str(node.gdb_value.address) == value:
+                    new_highlighted_node = node
+
+        if self.graph_viewer.highlighted_node is not new_highlighted_node:
+            self.graph_viewer.highlighted_node = new_highlighted_node
+            self.graph_viewer.queue_draw()
+
+    def set_graph_viewer(self, graph_viewer):
+        self.graph_viewer = graph_viewer
+
     def visit_value(self, value, store_iter):
         if type_has_fields(value.type):
             for f in value.type.fields():
@@ -298,8 +336,10 @@ class ViewerWindow(gtk.Window):
     def __init__(self):
         super(gtk.Window, self).__init__()
         self.entry = gtk.Entry()
+        self.entry.connect("activate", self.on_entry_changed)
         self.properties = GdbValueViewer()
-        self.viewer = GraphViewer(self.properties)
+        self.viewer = GraphViewer(self.properties)     # node viewer changes tree values when clicking on nodes
+        self.properties.set_graph_viewer(self.viewer)  # tree viewer can highlight nodes
         self.vbox = gtk.VBox()
         self.paned = gtk.HPaned()
         labelhbox = gtk.HBox()
@@ -314,6 +354,13 @@ class ViewerWindow(gtk.Window):
         self.set_default_size(1000,600)
         self.paned.set_position(750)
 
+    def on_entry_changed(self, entry):
+        expression = entry.get_text()
+        value = gdb.parse_and_eval(expression)
+        nodes = create_viewer_nodes(value, self.recursion_level)
+        self.viewer.nodes = nodes
+        self.viewer.queue_draw()
+
 def visit_values(node_dict, value, x, y, recursion_level):
     """
     Recursively traverse children of a gdb Value, storing pairs (address, GraphViewerNode).
@@ -354,7 +401,6 @@ def visit_values(node_dict, value, x, y, recursion_level):
 
 def create_viewer_nodes(value, recursion_level):
     # create the nodes
-    print "creating nodes"
     nodes = {}
     width, height = visit_values(nodes, value, 50, 50, recursion_level)
 
@@ -362,15 +408,12 @@ def create_viewer_nodes(value, recursion_level):
     for addr in nodes:
         value = nodes[addr].gdb_value
         if type_is_pointer(value.type) and value != 0:
-            print "pointer node"
             nodes[addr].connections["*"] = nodes[str(value)]
         else:
-            print "struct node@%s: %s"%(addr,value)
             for f in value.type.fields():
                 child = value[f.name]
                 if type_is_pointer(child.type):
                     if child != 0:
-                        print "connection %s --> %s"%(addr, child), value, f.name
                         if str(child) in nodes:
                             nodes[addr].connections[f.name] = nodes[str(child)]
 
@@ -405,11 +448,13 @@ class ViewerCommand(gdb.Command):
         else:
             recursion_level = 10
 
+
         is_gtk_main_running = False
 
         try:
             window = ViewerWindow()
             window.connect("destroy", gtk.main_quit)
+            window.recursion_level = recursion_level
             window.show_all()
 
             nodes = create_viewer_nodes(value, recursion_level)