Browse code

Add support for tooltips.

- added support for tooltips
- fixed issue related to residual tooltip windows
- added tooltip window resize to label size

See https://github.com/jrfonseca/xdot.py/pull/81

Fixes https://github.com/jrfonseca/xdot.py/issues/71

notEvil authored on 06/07/2020 09:29:39 • Jose Fonseca committed on 20/07/2020 11:07:52
Showing 3 changed files

... ...
@@ -491,7 +491,7 @@ class XDotParser(DotParser):
491 491
             # create a Node object nevertheless, so that any edges to/from it
492 492
             # don't get lost.
493 493
             # TODO: Extract the position from subgraph > graph > bb attribute.
494
-            node = elements.Node(id, 0.0, 0.0, 0.0, 0.0, [], None)
494
+            node = elements.Node(id, 0.0, 0.0, 0.0, 0.0, [], None, None)
495 495
             self.node_by_name[id] = node
496 496
             return
497 497
 
... ...
@@ -509,7 +509,7 @@ class XDotParser(DotParser):
509 509
             url = None
510 510
         else:
511 511
             url = url.decode('utf-8')
512
-        node = elements.Node(id, x, y, w, h, shapes, url)
512
+        node = elements.Node(id, x, y, w, h, shapes, url, attrs.get("tooltip"))
513 513
         self.node_by_name[id] = node
514 514
         if shapes:
515 515
             self.nodes.append(node)
... ...
@@ -529,7 +529,7 @@ class XDotParser(DotParser):
529 529
         if shapes:
530 530
             src = self.node_by_name[src_id]
531 531
             dst = self.node_by_name[dst_id]
532
-            self.edges.append(elements.Edge(src, dst, points, shapes))
532
+            self.edges.append(elements.Edge(src, dst, points, shapes, attrs.get("tooltip")))
533 533
 
534 534
     def parse(self):
535 535
         DotParser.parse(self)
... ...
@@ -17,7 +17,8 @@ import gi
17 17
 gi.require_version('Gtk', '3.0')
18 18
 gi.require_version('PangoCairo', '1.0')
19 19
 
20
-from gi.repository import Gdk
20
+from gi.repository import Gdk, Gtk
21
+from xdot.ui.elements import Jump
21 22
 
22 23
 
23 24
 class DragAction(object):
... ...
@@ -63,6 +64,12 @@ class DragAction(object):
63 64
 
64 65
 
65 66
 class NullAction(DragAction):
67
+    _tooltip_window = Gtk.Window(Gtk.WindowType.POPUP)
68
+    _tooltip_label = Gtk.Label(xalign=0, yalign=0)
69
+    _tooltip_item = None
70
+
71
+    _tooltip_window.add(_tooltip_label)
72
+    _tooltip_label.show()
66 73
 
67 74
     def on_motion_notify(self, event):
68 75
         if event.is_hint:
... ...
@@ -76,9 +83,27 @@ class NullAction(DragAction):
76 83
         if item is not None:
77 84
             dot_widget.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2))
78 85
             dot_widget.set_highlight(item.highlight)
86
+            if item is not NullAction._tooltip_item:
87
+                if isinstance(item, Jump) and item.item.tooltip is not None:
88
+                    NullAction._tooltip_label.set_markup(item.item.tooltip.decode())
89
+                    NullAction._tooltip_window.resize(
90
+                      NullAction._tooltip_label.get_preferred_width().natural_width,
91
+                      NullAction._tooltip_label.get_preferred_height().natural_height
92
+                    )
93
+                    NullAction._tooltip_window.show()
94
+                else:
95
+                    NullAction._tooltip_window.hide()
96
+                    NullAction._tooltip_label.set_markup("")
97
+                NullAction._tooltip_item = item
98
+            if NullAction._tooltip_window.is_visible:
99
+                pointer = NullAction._tooltip_window.get_screen().get_root_window().get_pointer()
100
+                NullAction._tooltip_window.move(pointer.x + 15, pointer.y + 10)
79 101
         else:
80 102
             dot_widget.get_window().set_cursor(None)
81 103
             dot_widget.set_highlight(None)
104
+            NullAction._tooltip_window.hide()
105
+            NullAction._tooltip_label.set_markup("")
106
+            NullAction._tooltip_item = None
82 107
 
83 108
 
84 109
 class PanAction(DragAction):
... ...
@@ -469,7 +469,7 @@ class Element(CompoundShape):
469 469
 
470 470
 class Node(Element):
471 471
 
472
-    def __init__(self, id, x, y, w, h, shapes, url):
472
+    def __init__(self, id, x, y, w, h, shapes, url, tooltip):
473 473
         Element.__init__(self, shapes)
474 474
 
475 475
         self.id = id
... ...
@@ -482,6 +482,7 @@ class Node(Element):
482 482
         self.y2 = y + 0.5*h
483 483
 
484 484
         self.url = url
485
+        self.tooltip = tooltip
485 486
 
486 487
     def is_inside(self, x, y):
487 488
         return self.x1 <= x and x <= self.x2 and self.y1 <= y and y <= self.y2
... ...
@@ -510,11 +511,12 @@ def square_distance(x1, y1, x2, y2):
510 511
 
511 512
 class Edge(Element):
512 513
 
513
-    def __init__(self, src, dst, points, shapes):
514
+    def __init__(self, src, dst, points, shapes, tooltip):
514 515
         Element.__init__(self, shapes)
515 516
         self.src = src
516 517
         self.dst = dst
517 518
         self.points = points
519
+        self.tooltip = tooltip
518 520
 
519 521
     RADIUS = 10
520 522