| 47 | | |
| 48 | | |
| 49 | | def expose(self, widget, event): |
| | 52 | self.connect("button_press_event", self.button_press) |
| | 53 | self.connect("button_release_event", self.button_release) |
| | 54 | self.connect("motion_notify_event", self.motion_notify) |
| | 55 | |
| | 56 | self.add_events(gdk.BUTTON_PRESS_MASK | |
| | 57 | gdk.BUTTON_RELEASE_MASK | |
| | 58 | gdk.POINTER_MOTION_MASK) |
| | 59 | |
| | 60 | |
| | 61 | def __getNodeByCoordinate(self, point): |
| | 62 | """ |
| | 63 | """ |
| | 64 | xc, yc = self.__centerOfWidget |
| | 65 | |
| | 66 | for id in range(self.__graph.getNumberOfNodes()): |
| | 67 | |
| | 68 | node = self.__graph.getNodeByID(id) |
| | 69 | |
| | 70 | xn, yn = node.getCartesianCoordinate() |
| | 71 | center = (xc + xn, yc - yn) |
| | 72 | radius = node.getDrawInfo('radius') |
| | 73 | |
| | 74 | if ( geometry.pointIsInCircle(point, radius, center) == True ): |
| | 75 | return node, center |
| | 76 | |
| | 77 | return None |
| | 78 | |
| | 79 | |
| | 80 | def button_press(self, widget, event): |
| | 90 | event.window.set_cursor(gdk.Cursor(gtk.gdk.X_CURSOR)) |
| | 91 | |
| | 92 | if event.button == 3: |
| | 93 | |
| | 94 | result = self.__getNodeByCoordinate(self.get_pointer()) |
| | 95 | |
| | 96 | if ( result != None ): |
| | 97 | |
| | 98 | xw, yw = self.window.get_origin() |
| | 99 | node, point = result |
| | 100 | x, y = point |
| | 101 | |
| | 102 | nodeView = NodeView(node, (int(xw + x), int(yw + y)), self) |
| | 103 | nodeView.show_all() |
| | 104 | |
| | 105 | return True |
| | 106 | |
| | 107 | |
| | 108 | def button_release(self, widget, event): |
| | 109 | """ |
| | 110 | Drawing callback |
| | 111 | @type widget: GtkWidget |
| | 112 | @param widget: Gtk widget superclass |
| | 113 | @type event: GtkEvent |
| | 114 | @param event: Gtk event of widget |
| | 115 | @rtype: boolean |
| | 116 | @return: Indicator of the event propagation |
| | 117 | """ |
| | 118 | event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)) |
| | 119 | |
| | 120 | return True |
| | 121 | |
| | 122 | |
| | 123 | def motion_notify(self, widget, event): |
| | 124 | """ |
| | 125 | Drawing callback |
| | 126 | @type widget: GtkWidget |
| | 127 | @param widget: Gtk widget superclass |
| | 128 | @type event: GtkEvent |
| | 129 | @param event: Gtk event of widget |
| | 130 | @rtype: boolean |
| | 131 | @return: Indicator of the event propagation |
| | 132 | """ |
| | 133 | xc, yc = self.__centerOfWidget |
| | 134 | pointer = self.get_pointer() |
| | 135 | |
| | 136 | for id in range(self.__graph.getNumberOfNodes()): |
| | 137 | node = self.__graph.getNodeByID(id) |
| | 138 | node.setDrawInfo('over', False) |
| | 139 | |
| | 140 | result = self.__getNodeByCoordinate(self.get_pointer()) |
| | 141 | |
| | 142 | if result != None: |
| | 143 | result[0].setDrawInfo('over', True) |
| | 144 | |
| | 145 | self.queue_draw() |
| | 146 | |
| | 147 | return True |
| | 148 | |
| | 149 | |
| | 150 | def expose(self, widget, event): |
| | 151 | """ |
| | 152 | Drawing callback |
| | 153 | @type widget: GtkWidget |
| | 154 | @param widget: Gtk widget superclass |
| | 155 | @type event: GtkEvent |
| | 156 | @param event: Gtk event of widget |
| | 157 | @rtype: boolean |
| | 158 | @return: Indicator of the event propagation |
| | 159 | """ |
| 144 | | (x, y) = node.getCartesianCoordinate() |
| 145 | | (r, g, b) = node.getDrawInfo('color') |
| 146 | | (xc, yc) = self.__centerOfWidget |
| 147 | | |
| 148 | | self.context.arc(xc + x, yc - y, 6, 0, 2 * math.pi) |
| | 244 | x, y = node.getCartesianCoordinate() |
| | 245 | r, g, b = node.getDrawInfo('color') |
| | 246 | xc, yc = self.__centerOfWidget |
| | 247 | |
| | 248 | radius = node.getDrawInfo('radius') |
| | 249 | |
| | 250 | if node.getDrawInfo('over') == True: |
| | 251 | self.context.arc(xc + x, yc - y, radius + 2, 0, 2 * math.pi) |
| | 252 | self.context.set_source_rgba(0.0, 0.0, 1.0, 0.3) |
| | 253 | self.context.fill_preserve() |
| | 254 | self.context.stroke() |
| | 255 | |
| | 256 | self.context.arc(xc + x, yc - y, radius, 0, 2 * math.pi) |
| | 330 | |
| | 331 | |
| | 332 | |
| | 333 | class NodeView(gtk.Window): |
| | 334 | """ |
| | 335 | """ |
| | 336 | def __init__(self, node, position, parent): |
| | 337 | """ |
| | 338 | """ |
| | 339 | gtk.Window.__init__(self, gtk.WINDOW_POPUP) |
| | 340 | self.move(position[0], position[1]) |
| | 341 | self.__button_press_position = self.get_pointer() |
| | 342 | self.set_size_request(200, 120) |
| | 343 | self.modify_bg(gtk.STATE_NORMAL, gdk.color_parse("#fbffc1")) |
| | 344 | |
| | 345 | self.__node = node |
| | 346 | self.__pressed = False |
| | 347 | self.__parent = parent |
| | 348 | |
| | 349 | self.connect("button_press_event", self.button_press) |
| | 350 | self.connect("button_release_event", self.button_release) |
| | 351 | self.connect("enter_notify_event", self.enter_notify) |
| | 352 | self.connect("leave_notify_event", self.leave_notify) |
| | 353 | self.connect("motion_notify_event", self.motion_notify) |
| | 354 | |
| | 355 | self.add_events(gdk.BUTTON_PRESS_MASK | |
| | 356 | gdk.BUTTON_RELEASE_MASK | |
| | 357 | gdk.POINTER_MOTION_MASK | |
| | 358 | gdk.ENTER_NOTIFY | |
| | 359 | gdk.LEAVE_NOTIFY | |
| | 360 | gdk.POINTER_MOTION_HINT_MASK) |
| | 361 | |
| | 362 | self.__draw_compact_layout() |
| | 363 | |
| | 364 | |
| | 365 | def __draw_compact_layout(self): |
| | 366 | """ |
| | 367 | """ |
| | 368 | self.__body = gtk.VBox() |
| | 369 | self.__body.set_spacing(5) |
| | 370 | self.__body.set_border_width(5) |
| | 371 | self.__head = gtk.HBox() |
| | 372 | self.__head.set_spacing(5) |
| | 373 | self.__head.set_border_width(5) |
| | 374 | |
| | 375 | self.__boldFont = pango.FontDescription('monospace bold 8') |
| | 376 | self.__boldFont = pango.FontDescription('monospace 8') |
| | 377 | |
| | 378 | self.__title = gtk.Label() |
| | 379 | self.__title.set_markup(self.__node.getInformation('ip')) |
| | 380 | self.__title.modify_font(self.__boldFont) |
| | 381 | |
| | 382 | self.__event = gtk.EventBox() |
| | 383 | self.__event.set_size_request(15, 15) |
| | 384 | r, g, b = drawing.cairoToGdkColor(self.__node.getDrawInfo('color')) |
| | 385 | self.__event.modify_bg(gtk.STATE_NORMAL, gdk.Color(r, g, b)) |
| | 386 | |
| | 387 | self.__head.pack_start(self.__event, False, False, 0) |
| | 388 | self.__head.pack_start(self.__title, False, False, 0) |
| | 389 | self.__body.pack_start(self.__head, False, False, 0) |
| | 390 | |
| | 391 | self.add(self.__body) |
| | 392 | |
| | 393 | |
| | 394 | def button_press(self, widget, event): |
| | 395 | """ |
| | 396 | """ |
| | 397 | self.__pressed = True |
| | 398 | self.__button_press_position = self.get_pointer() |
| | 399 | |
| | 400 | return True |
| | 401 | |
| | 402 | |
| | 403 | def button_release(self, widget, event): |
| | 404 | """ |
| | 405 | """ |
| | 406 | if event.button == 3: |
| | 407 | self.__node.setDrawInfo('over', False) |
| | 408 | self.destroy() |
| | 409 | self.__parent.queue_draw() |
| | 410 | |
| | 411 | self.__pressed = False |
| | 412 | |
| | 413 | return True |
| | 414 | |
| | 415 | |
| | 416 | def enter_notify(self, widget, event): |
| | 417 | """ |
| | 418 | """ |
| | 419 | self.__node.setDrawInfo('over', True) |
| | 420 | self.__parent.queue_draw() |
| | 421 | |
| | 422 | |
| | 423 | def leave_notify(self, widget, event): |
| | 424 | """ |
| | 425 | """ |
| | 426 | self.__node.setDrawInfo('over', False) |
| | 427 | |
| | 428 | |
| | 429 | def motion_notify(self, widget, event): |
| | 430 | """ |
| | 431 | """ |
| | 432 | self.__node.setDrawInfo('over', True) |
| | 433 | |
| | 434 | if event.is_hint == True: |
| | 435 | |
| | 436 | x, y, button_state = event.window.get_pointer() |
| | 437 | |
| | 438 | if button_state & gtk.gdk.BUTTON1_MASK and self.__pressed: |
| | 439 | |
| | 440 | xw, yw = event.window.get_root_origin() |
| | 441 | xd, yd = self.__button_press_position |
| | 442 | self.move(x + xw - xd, y + yw - yd) |
| | 443 | |
| | 444 | return True |