2 from __future__ 
import division
 
    5 LAYOUT_ALGORITHM = 
'neato'  
    6 REPRESENT_CHANNELS_AS_NODES = 1
 
    7 DEFAULT_NODE_SIZE = 3.0 
 
    8 DEFAULT_TRANSMISSIONS_MEMORY = 5 
 
   13 PRIORITY_UPDATE_MODEL = -100
 
   14 PRIORITY_UPDATE_VIEW = 200
 
   17 if platform.system() == 
"Windows":
 
   18     SHELL_FONT = 
"Lucida Console 9" 
   20     SHELL_FONT = 
"Luxi Mono 10" 
   45     from higcontainer 
import HIGContainer
 
   46     gobject.threads_init()
 
   51 except ImportError, _import_error:
 
   52     import dummy_threading 
as threading
 
   61 from base 
import InformationWindow, PyVizObject, Link, lookup_netdevice_traits, PIXELS_PER_METER
 
   62 from base 
import transform_distance_simulation_to_canvas, transform_point_simulation_to_canvas
 
   63 from base 
import transform_distance_canvas_to_simulation, transform_point_canvas_to_simulation
 
   64 from base 
import load_plugins, register_plugin, plugins
 
   67 PI_TIMES_2 = math.pi*2
 
   75         'query-extra-tooltip-info': (gobject.SIGNAL_RUN_LAST, 
None, (object,)),
 
   85         self.canvas_item.set_data(
"pyviz-object", self)
 
  103     def set_svg_icon(self, file_base_name, width=None, height=None, align_x=0.5, align_y=0.5):
 
  105         Set a background SVG icon for the node. 
  107         @param file_base_name: base file name, including .svg 
  108         extension, of the svg file.  Place the file in the folder 
  109         src/contrib/visualizer/resource. 
  111         @param width: scale to the specified width, in meters 
  112         @param width: scale to the specified height, in meters 
  114         @param align_x: horizontal alignment of the icon relative to 
  115         the node position, from 0 (icon fully to the left of the node) 
  116         to 1.0 (icon fully to the right of the node) 
  118         @param align_y: vertical alignment of the icon relative to the 
  119         node position, from 0 (icon fully to the top of the node) to 
  120         1.0 (icon fully to the bottom of the node) 
  123         if width 
is None and height 
is None:
 
  124             raise ValueError(
"either width or height must be given")
 
  125         rsvg_handle = svgitem.rsvg_handle_factory(file_base_name)
 
  126         x = self.canvas_item.props.center_x
 
  127         y = self.canvas_item.props.center_y
 
  129         self.svg_item.props.parent = self.visualizer.canvas.get_root_item()
 
  130         self.svg_item.props.pointer_events = 0
 
  131         self.svg_item.lower(
None)
 
  132         self.svg_item.props.visibility = goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD
 
  133         if width 
is not None:
 
  135         if height 
is not None:
 
  148         assert isinstance(label, basestring)
 
  153         w = self.svg_item.width
 
  154         h = self.svg_item.height
 
  155         self.svg_item.set_properties(x=(x - (1-self.
svg_align_x)*w),
 
  160         self.visualizer.simulation.lock.acquire()
 
  162             ns3_node = ns.network.NodeList.GetNode(self.
node_index)
 
  163             ipv4 = ns3_node.GetObject(ns.internet.Ipv4.GetTypeId())
 
  164             ipv6 = ns3_node.GetObject(ns.internet.Ipv6.GetTypeId())
 
  166             name = 
'<b><u>Node %i</u></b>' % self.
node_index 
  167             node_name = ns.core.Names.FindName (ns3_node)
 
  168             if len(node_name)!=0:
 
  169                 name += 
' <b>(' + node_name + 
')</b>' 
  174             self.emit(
"query-extra-tooltip-info", lines)
 
  176             mob = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
 
  178                 lines.append(
'  <b>Mobility Model</b>: %s' % mob.GetInstanceTypeId().GetName())
 
  180             for devI 
in range(ns3_node.GetNDevices()):
 
  182                 lines.append(
'  <u>NetDevice %i:</u>' % devI)
 
  183                 dev = ns3_node.GetDevice(devI)
 
  184                 name = ns.core.Names.FindName(dev)
 
  186                     lines.append(
'    <b>Name:</b> %s' % name)
 
  187                 devname = dev.GetInstanceTypeId().GetName()
 
  188                 lines.append(
'    <b>Type:</b> %s' % devname)
 
  191                     ipv4_idx = ipv4.GetInterfaceForDevice(dev)
 
  194                             '%s/%s' % (ipv4.GetAddress(ipv4_idx, i).GetLocal(),
 
  195                                        ipv4.GetAddress(ipv4_idx, i).GetMask())
 
  196                             for i 
in range(ipv4.GetNAddresses(ipv4_idx))]
 
  197                         lines.append(
'    <b>IPv4 Addresses:</b> %s' % 
'; '.join(addresses))
 
  200                     ipv6_idx = ipv6.GetInterfaceForDevice(dev)
 
  203                             '%s/%s' % (ipv6.GetAddress(ipv6_idx, i).GetAddress(),
 
  204                                        ipv6.GetAddress(ipv6_idx, i).GetPrefix())
 
  205                             for i 
in range(ipv6.GetNAddresses(ipv6_idx))]
 
  206                         lines.append(
'    <b>IPv6 Addresses:</b> %s' % 
'; '.join(addresses))
 
  208                 lines.append(
'    <b>MAC Address:</b> %s' % (dev.GetAddress(),))
 
  210             tooltip.set_markup(
'\n'.join(lines))
 
  212             self.visualizer.simulation.lock.release()
 
  224     selected = property(_get_selected, _set_selected)
 
  231     highlighted = property(_get_highlighted, _set_highlighted)
 
  238         """Update the node aspect to reflect the selected/highlighted state""" 
  245         fill_color_rgba = (self.
_color & 0xffffff00) | alpha
 
  246         self.canvas_item.set_properties(radius_x=size, radius_y=size,
 
  247                                         fill_color_rgba=fill_color_rgba)
 
  251             line_width = size*.15
 
  253             stroke_color = 
'yellow' 
  255             stroke_color = 
'black' 
  256         self.canvas_item.set_properties(line_width=line_width, stroke_color=stroke_color)
 
  258         if self.
_label is not None:
 
  261                                                          font=
"Sans Serif 10",
 
  262                                                          fill_color_rgba=0x808080ff,
 
  263                                                          alignment=pango.ALIGN_CENTER,
 
  265                                                          parent=self.visualizer.canvas.get_root_item(),
 
  267                 self._label_canvas_item.lower(
None)
 
  269             self._label_canvas_item.set_properties(visibility=goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD,
 
  274         self.canvas_item.set_property(
"center_x", x)
 
  275         self.canvas_item.set_property(
"center_y", y)
 
  279         for link 
in self.
links:
 
  283             self._label_canvas_item.set_properties(x=x, y=(y+self.
_size*3))
 
  286         return (self.canvas_item.get_property(
"center_x"), self.canvas_item.get_property(
"center_y"))
 
  293         if isinstance(color, str):
 
  294             color = gtk.gdk.color_parse(color)
 
  295             color = ((color.red>>8) << 24) | ((color.green>>8) << 16) | ((color.blue>>8) << 8) | 0xff
 
  300         assert isinstance(link, Link)
 
  301         self.links.append(link)
 
  304         assert isinstance(link, Link)
 
  305         self.links.remove(link)
 
  310             node = ns.network.NodeList.GetNode(self.
node_index)
 
  311             mobility = node.GetObject(ns.mobility.MobilityModel.GetTypeId())
 
  321                                              stroke_color=
"grey", line_width=2.0,
 
  322                                              line_dash=goocanvas.LineDash([10.0, 10.0 ]),
 
  323                                              visibility=goocanvas.ITEM_VISIBLE)
 
  324         self.canvas_item.set_data(
"pyviz-object", self)
 
  328         self.canvas_item.set_property(
"center_x", x)
 
  329         self.canvas_item.set_property(
"center_y", y)
 
  331         for link 
in self.
links:
 
  335         return (self.canvas_item.get_property(
"center_x"), self.canvas_item.get_property(
"center_y"))
 
  340         assert isinstance(node1, Node)
 
  341         assert isinstance(node2, (Node, Channel))
 
  344         self.
canvas_item = goocanvas.Path(line_width=1.0, stroke_color=
"black")
 
  345         self.canvas_item.set_data(
"pyviz-object", self)
 
  346         self.node1.links.append(self)
 
  347         self.node2.links.append(self)
 
  350         pos1_x, pos1_y = self.node1.get_position()
 
  351         pos2_x, pos2_y = self.node2.get_position()
 
  352         self.canvas_item.set_property(
"data", 
"M %r %r L %r %r" % (pos1_x, pos1_y, pos2_x, pos2_y))
 
  358         super(SimulationThread, self).
__init__()
 
  359         assert isinstance(viz, Visualizer)
 
  362         self.
go = threading.Event()
 
  372             self.sim_helper.SetNodesOfInterest(nodes)
 
  388                     if ns3.core.Simulator.IsFinished():
 
  389                         self.viz.play_button.set_sensitive(
False)
 
  394                 self.sim_helper.SimulatorRunUntil(ns.core.Seconds(self.
target_time))
 
  396                 self.pause_messages.extend(self.sim_helper.GetPauseMessages())
 
  397                 gobject.idle_add(self.viz.update_model, priority=PRIORITY_UPDATE_MODEL)
 
  413     if _import_error 
is None:
 
  417             'populate-node-menu': (gobject.SIGNAL_RUN_LAST, 
None, (object, gtk.Menu,)),
 
  421             'simulation-periodic-update': (gobject.SIGNAL_RUN_LAST, 
None, ()),
 
  424             'topology-scanned': (gobject.SIGNAL_RUN_LAST, 
None, ()),
 
  427             'update-view': (gobject.SIGNAL_RUN_LAST, 
None, ()),
 
  432         assert Visualizer.INSTANCE 
is None 
  433         Visualizer.INSTANCE = self
 
  469         for plugin 
in plugins:
 
  473         assert isinstance(mode, ShowTransmissionsMode)
 
  476             self.simulation.set_nodes_of_interest(range(ns.network.NodeList.GetNNodes()))
 
  478             self.simulation.set_nodes_of_interest([])
 
  481                 self.simulation.set_nodes_of_interest([])
 
  483                 self.simulation.set_nodes_of_interest([self.selected_node.node_index])
 
  486         expander = gtk.Expander(
"Advanced")
 
  489         main_vbox = gobject.new(gtk.VBox, border_width=8, visible=
True)
 
  490         expander.add(main_vbox)
 
  492         main_hbox1 = gobject.new(gtk.HBox, border_width=8, visible=
True)
 
  493         main_vbox.pack_start(main_hbox1)
 
  495         show_transmissions_group = HIGContainer(
"Show transmissions")
 
  496         show_transmissions_group.show()
 
  497         main_hbox1.pack_start(show_transmissions_group, 
False, 
False, 8)
 
  499         vbox = gtk.VBox(
True, 4)
 
  501         show_transmissions_group.add(vbox)
 
  503         all_nodes = gtk.RadioButton(
None)
 
  504         all_nodes.set_label(
"All nodes")
 
  505         all_nodes.set_active(
True)
 
  509         selected_node = gtk.RadioButton(all_nodes)
 
  511         selected_node.set_label(
"Selected node")
 
  512         selected_node.set_active(
False)
 
  513         vbox.add(selected_node)
 
  515         no_node = gtk.RadioButton(all_nodes)
 
  517         no_node.set_label(
"Disabled")
 
  518         no_node.set_active(
False)
 
  522             if radio.get_active():
 
  524         all_nodes.connect(
"toggled", toggled)
 
  527             if radio.get_active():
 
  529         no_node.connect(
"toggled", toggled)
 
  532             if radio.get_active():
 
  534         selected_node.connect(
"toggled", toggled)
 
  538         misc_settings_group = HIGContainer(
"Misc Settings")
 
  539         misc_settings_group.show()
 
  540         main_hbox1.pack_start(misc_settings_group, 
False, 
False, 8)
 
  541         settings_hbox = gobject.new(gtk.HBox, border_width=8, visible=
True)
 
  542         misc_settings_group.add(settings_hbox)
 
  545         vbox = gobject.new(gtk.VBox, border_width=0, visible=
True)
 
  546         scale = gobject.new(gtk.HScale, visible=
True, digits=2)
 
  547         vbox.pack_start(scale, 
True, 
True, 0)
 
  548         vbox.pack_start(gobject.new(gtk.Label, label=
"Node Size", visible=
True), 
True, 
True, 0)
 
  549         settings_hbox.pack_start(vbox, 
False, 
False, 6)
 
  551         def node_size_changed(adj):
 
  552             for node 
in self.nodes.itervalues():
 
  553                 node.set_size(adj.value)
 
  554         self.node_size_adjustment.connect(
"value-changed", node_size_changed)
 
  555         self.node_size_adjustment.set_all(DEFAULT_NODE_SIZE, 0.01, 20, 0.1)
 
  558         vbox = gobject.new(gtk.VBox, border_width=0, visible=
True)
 
  559         scale = gobject.new(gtk.HScale, visible=
True, digits=1)
 
  560         vbox.pack_start(scale, 
True, 
True, 0)
 
  561         vbox.pack_start(gobject.new(gtk.Label, label=
"Tx. Smooth Factor (s)", visible=
True), 
True, 
True, 0)
 
  562         settings_hbox.pack_start(vbox, 
False, 
False, 6)
 
  564         self.transmissions_smoothing_adjustment.set_all(DEFAULT_TRANSMISSIONS_MEMORY*0.1, 0.1, 10, 0.1)
 
  569         __slots__ = [
'initial_mouse_pos', 
'initial_canvas_pos', 
'motion_signal']
 
  572         self.canvas.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
 
  574         x, y, dummy = widget.window.get_pointer()
 
  575         self._panning_state.initial_mouse_pos = (x, y)
 
  576         x = self._scrolled_window.get_hadjustment().value
 
  577         y = self._scrolled_window.get_vadjustment().value
 
  578         self._panning_state.initial_canvas_pos = (x, y)
 
  579         self._panning_state.motion_signal = self.canvas.connect(
"motion-notify-event", self.
_panning_motion)
 
  584         self.canvas.window.set_cursor(
None)
 
  585         self.canvas.disconnect(self._panning_state.motion_signal)
 
  591             x, y, dummy = widget.window.get_pointer()
 
  593             x, y = event.x, event.y
 
  595         hadj = self._scrolled_window.get_hadjustment()
 
  596         vadj = self._scrolled_window.get_vadjustment()
 
  597         mx0, my0 = self._panning_state.initial_mouse_pos
 
  598         cx0, cy0 = self._panning_state.initial_canvas_pos
 
  602         hadj.value = cx0 - dx
 
  603         vadj.value = cy0 - dy
 
  607         if event.button == 2:
 
  613         if event.button == 2:
 
  619         if event.direction == gtk.gdk.SCROLL_UP:
 
  620             self.zoom.value *= 1.25
 
  622         elif event.direction == gtk.gdk.SCROLL_DOWN:
 
  623             self.zoom.value /= 1.25
 
  628         return self._scrolled_window.get_hadjustment()
 
  630         return self._scrolled_window.get_vadjustment()
 
  633         self.
window = gtk.Window()
 
  634         vbox = gtk.VBox(); vbox.show()
 
  635         self.window.add(vbox)
 
  638         self.
canvas = goocanvas.Canvas()
 
  642         self.canvas.props.has_tooltip = 
True 
  645         sw = gtk.ScrolledWindow(); sw.show()
 
  648         vbox.pack_start(sw, 
True, 
True, 4)
 
  649         self.canvas.set_size_request(600, 450)
 
  650         self.canvas.set_bounds(-10000, -10000, 10000, 10000)
 
  651         self.canvas.scroll_to(0, 0)
 
  654         self.canvas.get_root_item().add_child(self.
links_group)
 
  655         self.links_group.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
 
  658         self.channels_group.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
 
  661         self.canvas.get_root_item().add_child(self.
nodes_group)
 
  662         self.nodes_group.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
 
  667         hbox = gtk.HBox(); hbox.show()
 
  668         vbox.pack_start(hbox, 
False, 
False, 4)
 
  671         zoom_adj = gtk.Adjustment(1.0, 0.01, 10.0, 0.02, 1.0, 0)
 
  673         def _zoom_changed(adj):
 
  674             self.canvas.set_scale(adj.value)
 
  675         zoom_adj.connect(
"value-changed", _zoom_changed)
 
  676         zoom = gtk.SpinButton(zoom_adj)
 
  679         hbox.pack_start(gobject.new(gtk.Label, label=
" Zoom:", visible=
True), 
False, 
False, 4)
 
  680         hbox.pack_start(zoom, 
False, 
False, 4)
 
  681         _zoom_changed(zoom_adj)
 
  684         speed_adj = gtk.Adjustment(1.0, 0.01, 10.0, 0.02, 1.0, 0)
 
  685         def _speed_changed(adj):
 
  686             self.
speed = adj.value
 
  689         speed_adj.connect(
"value-changed", _speed_changed)
 
  690         speed = gtk.SpinButton(speed_adj)
 
  693         hbox.pack_start(gobject.new(gtk.Label, label=
"  Speed:", visible=
True), 
False, 
False, 4)
 
  694         hbox.pack_start(speed, 
False, 
False, 4)
 
  695         _speed_changed(speed_adj)
 
  698         self.
time_label = gobject.new(gtk.Label, label=
"  Speed:", visible=
True)
 
  699         self.time_label.set_width_chars(20)
 
  700         hbox.pack_start(self.
time_label, 
False, 
False, 4)
 
  703         screenshot_button = gobject.new(gtk.Button,
 
  705                                        relief=gtk.RELIEF_NONE, focus_on_click=
False,
 
  707         hbox.pack_start(screenshot_button, 
False, 
False, 4)
 
  709         def load_button_icon(button, icon_name):
 
  713                 sys.stderr.write(
"Could not load icon %s due to missing gnomedesktop Python module\n" % icon_name)
 
  715                 icon = gnomedesktop.find_icon(gtk.icon_theme_get_default(), icon_name, 16, 0)
 
  717                     button.props.image = gobject.new(gtk.Image, file=icon, visible=
True)
 
  719         load_button_icon(screenshot_button, 
"applets-screenshooter")
 
  723         if ipython_view 
is not None:
 
  724             shell_button = gobject.new(gtk.Button,
 
  726                                            relief=gtk.RELIEF_NONE, focus_on_click=
False,
 
  728             hbox.pack_start(shell_button, 
False, 
False, 4)
 
  729             load_button_icon(shell_button, 
"gnome-terminal")
 
  734                                        image=gobject.new(gtk.Image, stock=gtk.STOCK_MEDIA_PLAY, visible=
True),
 
  735                                        label=
"Simulate (F3)",
 
  736                                        relief=gtk.RELIEF_NONE, focus_on_click=
False,
 
  737                                        use_stock=
True, visible=
True)
 
  738         accel_group = gtk.AccelGroup()
 
  739         self.window.add_accel_group(accel_group)
 
  740         self.play_button.add_accelerator(
"clicked", accel_group,
 
  741                                          gtk.keysyms.F3, 0, gtk.ACCEL_VISIBLE)
 
  752         print "scanning topology: %i nodes..." % (ns.network.NodeList.GetNNodes(),)
 
  753         graph = pygraphviz.AGraph()
 
  755         for nodeI 
in range(ns.network.NodeList.GetNNodes()):
 
  757             if seen_nodes == 100:
 
  758                 print "scan topology... %i nodes visited (%.1f%%)" % (nodeI, 100*nodeI/ns.network.NodeList.GetNNodes())
 
  760             node = ns.network.NodeList.GetNode(nodeI)
 
  761             node_name = 
"Node %i" % nodeI
 
  764             mobility = node.GetObject(ns.mobility.MobilityModel.GetTypeId())
 
  765             if mobility 
is not None:
 
  766                 node_view.set_color(
"red")
 
  767                 pos = mobility.GetPosition()
 
  771                 graph.add_node(node_name)
 
  773             for devI 
in range(node.GetNDevices()):
 
  774                 device = node.GetDevice(devI)
 
  776                 if device_traits.is_wireless:
 
  778                 if device_traits.is_virtual:
 
  780                 channel = device.GetChannel()
 
  781                 if channel.GetNDevices() > 2:
 
  782                     if REPRESENT_CHANNELS_AS_NODES:
 
  785                             channel_name = 
"Channel %s" % id(channel)
 
  786                             graph.add_edge(node_name, channel_name)
 
  791                         for otherDevI 
in range(channel.GetNDevices()):
 
  792                             otherDev = channel.GetDevice(otherDevI)
 
  793                             otherNode = otherDev.GetNode()
 
  794                             otherNodeView = self.
get_node(otherNode.GetId())
 
  795                             if otherNode 
is not node:
 
  796                                 if mobility 
is None and not otherNodeView.has_mobility:
 
  797                                     other_node_name = 
"Node %i" % otherNode.GetId()
 
  798                                     graph.add_edge(node_name, other_node_name)
 
  801                     for otherDevI 
in range(channel.GetNDevices()):
 
  802                         otherDev = channel.GetDevice(otherDevI)
 
  803                         otherNode = otherDev.GetNode()
 
  804                         otherNodeView = self.
get_node(otherNode.GetId())
 
  805                         if otherNode 
is not node:
 
  806                             if mobility 
is None and not otherNodeView.has_mobility:
 
  807                                 other_node_name = 
"Node %i" % otherNode.GetId()
 
  808                                 graph.add_edge(node_name, other_node_name)
 
  811         print "scanning topology: calling graphviz layout" 
  812         graph.layout(LAYOUT_ALGORITHM)
 
  813         for node 
in graph.iternodes():
 
  815             node_type, node_id = node.split(
' ')
 
  816             pos_x, pos_y = [float(s) 
for s 
in node.attr[
'pos'].split(
',')]
 
  817             if node_type == 
'Node':
 
  818                 obj = self.
nodes[int(node_id)]
 
  819             elif node_type == 
'Channel':
 
  821             obj.set_position(pos_x, pos_y)
 
  823         print "scanning topology: all done." 
  824         self.emit(
"topology-scanned")
 
  828             return self.
nodes[index]
 
  830             node = 
Node(self, index)
 
  831             self.
nodes[index] = node
 
  832             self.nodes_group.add_child(node.canvas_item)
 
  839             return self.
channels[id(ns3_channel)]
 
  842             self.
channels[id(ns3_channel)] = channel
 
  843             self.channels_group.add_child(channel.canvas_item)
 
  848         self.links_group.add_child(link.canvas_item)
 
  849         link.canvas_item.lower(
None)
 
  854         self.time_label.set_text(
"Time: %f s" % ns.core.Simulator.Now().GetSeconds())
 
  865         self.emit(
"update-view")
 
  868         for node 
in self.nodes.itervalues():
 
  869             if node.has_mobility:
 
  870                 ns3_node = ns.network.NodeList.GetNode(node.node_index)
 
  871                 mobility = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
 
  872                 if mobility 
is not None:
 
  873                     pos = mobility.GetPosition()
 
  875                     node.set_position(x, y)
 
  877                         hadj = self._scrolled_window.get_hadjustment()
 
  878                         vadj = self._scrolled_window.get_vadjustment()
 
  879                         px, py = self.canvas.convert_to_pixels(x, y)
 
  880                         hadj.value = px - hadj.page_size/2
 
  881                         vadj.value = py - vadj.page_size/2
 
  884         if isinstance(node, ns.network.Node):
 
  885             node = self.
nodes[node.GetId()]
 
  886         elif isinstance(node, (int, long)):
 
  887             node = self.
nodes[node]
 
  888         elif isinstance(node, Node):
 
  891             raise TypeError(
"expected int, viz.Node or ns.network.Node, not %r" % node)
 
  893         x, y = node.get_position()
 
  894         hadj = self._scrolled_window.get_hadjustment()
 
  895         vadj = self._scrolled_window.get_vadjustment()
 
  896         px, py = self.canvas.convert_to_pixels(x, y)
 
  897         hadj.value = px - hadj.page_size/2
 
  898         vadj.value = py - vadj.page_size/2
 
  902         self.simulation.lock.acquire()
 
  904             self.emit(
"simulation-periodic-update")
 
  906             self.simulation.lock.release()
 
  909         smooth_factor = int(self.transmissions_smoothing_adjustment.value*10)
 
  911         transmissions = self.simulation.sim_helper.GetTransmissionSamples()
 
  912         self._last_transmissions.append(transmissions)
 
  914             self._last_transmissions.pop(0)            
 
  916         drops = self.simulation.sim_helper.GetPacketDropSamples()
 
  917         self._last_drops.append(drops)
 
  919             self._last_drops.pop(0)
 
  922         hadj = self._scrolled_window.get_hadjustment()
 
  923         vadj = self._scrolled_window.get_vadjustment()
 
  924         bounds_x1, bounds_y1 = self.canvas.convert_from_pixels(hadj.value, vadj.value)
 
  925         bounds_x2, bounds_y2 = self.canvas.convert_from_pixels(hadj.value + hadj.page_size,
 
  926                                                                vadj.value + vadj.page_size)
 
  927         pos1_x, pos1_y, pos2_x, pos2_y = ns.visualizer.PyViz.LineClipping(bounds_x1, bounds_y1,
 
  928                                                                 bounds_x2, bounds_y2,
 
  931         return (pos1_x + pos2_x)/2, (pos1_y + pos2_y)/2
 
  934         transmissions_average = {}
 
  936             for transmission 
in transmission_set:
 
  937                 key = (transmission.transmitter.GetId(), transmission.receiver.GetId())
 
  938                 rx_bytes, count = transmissions_average.get(key, (0, 0))
 
  939                 rx_bytes += transmission.bytes
 
  941                 transmissions_average[key] = rx_bytes, count
 
  944         for arrow, label 
in old_arrows:
 
  945             arrow.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
 
  946             label.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
 
  949         k = self.node_size_adjustment.value/5
 
  951         for (transmitter_id, receiver_id), (rx_bytes, rx_count) 
in transmissions_average.iteritems():
 
  952             transmitter = self.
get_node(transmitter_id)
 
  953             receiver = self.
get_node(receiver_id)
 
  955                 arrow, label = old_arrows.pop()
 
  957                 arrow = goocanvas.Polyline(line_width=2.0, stroke_color_rgba=0x00C000C0, close_path=
False, end_arrow=
True)
 
  958                 arrow.set_property(
"parent", self.canvas.get_root_item())
 
  959                 arrow.props.pointer_events = 0
 
  962                 label = goocanvas.Text(parent=self.canvas.get_root_item(), pointer_events=0)
 
  965             arrow.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
 
  966             line_width = max(0.1, math.log(float(rx_bytes)/rx_count/self.
sample_period)*k)
 
  967             arrow.set_property(
"line-width", line_width)
 
  969             pos1_x, pos1_y = transmitter.get_position()
 
  970             pos2_x, pos2_y = receiver.get_position()
 
  971             points = goocanvas.Points([(pos1_x, pos1_y), (pos2_x, pos2_y)])
 
  972             arrow.set_property(
"points", points)
 
  975             label.set_properties(visibility=goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD,
 
  976                                  visibility_threshold=0.5,
 
  977                                  font=(
"Sans Serif %f" % int(1+BITRATE_FONT_SIZE*k)))
 
  978             angle = math.atan2((pos2_y - pos1_y), (pos2_x - pos1_x))
 
  979             if -PI_OVER_2 <= angle <= PI_OVER_2:
 
  980                 label.set_properties(text=(
"%.2f kbit/s →" % (kbps,)),
 
  981                                      alignment=pango.ALIGN_CENTER,
 
  983                                      x=0, y=-line_width/2)
 
  987                 label.set_transform(M)
 
  989                 label.set_properties(text=(
"← %.2f kbit/s" % (kbps,)),
 
  990                                      alignment=pango.ALIGN_CENTER,
 
  997                 label.set_transform(M)
 
  999             new_arrows.append((arrow, label))
 
 1007             for drop 
in drop_set:
 
 1008                 key = drop.transmitter.GetId()
 
 1009                 drop_bytes, count = drops_average.get(key, (0, 0))
 
 1010                 drop_bytes += drop.bytes
 
 1012                 drops_average[key] = drop_bytes, count
 
 1015         for arrow, label 
in old_arrows:
 
 1016             arrow.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
 
 1017             label.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
 
 1021         vadjustment = self._scrolled_window.get_vadjustment()
 
 1022         bottom_y = vadjustment.value + vadjustment.page_size
 
 1023         dummy, edge_y = self.canvas.convert_from_pixels(0, bottom_y)
 
 1025         k = self.node_size_adjustment.value/5
 
 1027         for transmitter_id, (drop_bytes, drop_count) 
in drops_average.iteritems():
 
 1028             transmitter = self.
get_node(transmitter_id)
 
 1030                 arrow, label = old_arrows.pop()
 
 1032                 arrow = goocanvas.Polyline(line_width=2.0, stroke_color_rgba=0xC00000C0, close_path=
False, end_arrow=
True)
 
 1033                 arrow.props.pointer_events = 0
 
 1034                 arrow.set_property(
"parent", self.canvas.get_root_item())
 
 1037                 label = goocanvas.Text()
 
 1038                 label.props.pointer_events = 0
 
 1039                 label.set_property(
"parent", self.canvas.get_root_item())
 
 1042             arrow.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
 
 1043             arrow.set_property(
"line-width", max(0.1, math.log(float(drop_bytes)/drop_count/self.
sample_period)*k))
 
 1044             pos1_x, pos1_y = transmitter.get_position()
 
 1045             pos2_x, pos2_y = pos1_x, edge_y
 
 1046             points = goocanvas.Points([(pos1_x, pos1_y), (pos2_x, pos2_y)])
 
 1047             arrow.set_property(
"points", points)
 
 1049             label.set_properties(visibility=goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD,
 
 1050                                  visibility_threshold=0.5,
 
 1051                                  font=(
"Sans Serif %i" % int(1+BITRATE_FONT_SIZE*k)),
 
 1052                                  text=(
"%.2f kbit/s" % (float(drop_bytes*8)/1e3/drop_count/self.
sample_period,)),
 
 1053                                  alignment=pango.ALIGN_CENTER,
 
 1054                                  x=(pos1_x + pos2_x)/2,
 
 1055                                  y=(pos1_y + pos2_y)/2)
 
 1057             new_arrows.append((arrow, label))
 
 1066         while not self.simulation.lock.acquire(
False):
 
 1067             while gtk.events_pending():
 
 1068                 gtk.main_iteration()
 
 1069         pause_messages = self.simulation.pause_messages
 
 1070         self.simulation.pause_messages = []
 
 1073             self.simulation.target_time = ns.core.Simulator.Now ().GetSeconds () + self.
sample_period 
 1076             self.simulation.lock.release()
 
 1080             dialog = gtk.MessageDialog(parent=self.
window, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_OK,
 
 1081                                        message_format=
'\n'.join(pause_messages))
 
 1082             dialog.connect(
"response", 
lambda d, r: d.destroy())
 
 1084             self.play_button.set_active(
False)
 
 1087         if not self.play_button.get_active():
 
 1092         self.simulation.go.set()
 
 1102                                                       priority=PRIORITY_UPDATE_VIEW)
 
 1105         if button.get_active():
 
 1115         self.simulation.quit = 
True 
 1116         self.simulation.go.set()
 
 1117         self.simulation.join()
 
 1127         original_runcode = self.ipython.runcode
 
 1128         def runcode(ip, *args):
 
 1130             self.simulation.lock.acquire()
 
 1132                 return original_runcode(*args)
 
 1135                 self.simulation.lock.release()
 
 1137         self.ipython.runcode = types.MethodType(runcode, self.
ipython)                
 
 1143         positions = [node.get_position() 
for node 
in self.nodes.itervalues()]
 
 1144         min_x, min_y = min(x 
for (x,y) 
in positions), min(y 
for (x,y) 
in positions)
 
 1145         max_x, max_y = max(x 
for (x,y) 
in positions), max(y 
for (x,y) 
in positions)
 
 1146         min_x_px, min_y_px = self.canvas.convert_to_pixels(min_x, min_y)
 
 1147         max_x_px, max_y_px = self.canvas.convert_to_pixels(max_x, max_y)
 
 1150         dx_px = max_x_px - min_x_px
 
 1151         dy_px = max_y_px - min_y_px
 
 1152         hadj = self._scrolled_window.get_hadjustment()
 
 1153         vadj = self._scrolled_window.get_vadjustment()
 
 1154         new_dx, new_dy = 1.5*dx_px, 1.5*dy_px
 
 1156         if new_dx == 0 
or new_dy == 0:
 
 1159         self.zoom.value = min(hadj.page_size/new_dx, vadj.page_size/new_dy)
 
 1161         x1, y1 = self.canvas.convert_from_pixels(hadj.value, vadj.value)
 
 1162         x2, y2 = self.canvas.convert_from_pixels(hadj.value+hadj.page_size, vadj.value+vadj.page_size)
 
 1165         center_x = (min_x + max_x) / 2
 
 1166         center_y = (min_y + max_y) / 2
 
 1168         self.canvas.scroll_to(center_x - width/2, center_y - height/2)
 
 1174         self.window.connect(
"delete-event", self.
_quit)
 
 1177         self.simulation.start()
 
 1190         if event.button == 1:
 
 1195         if event.button == 1:
 
 1198         elif event.button == 3:
 
 1201         elif event.button == 2:
 
 1207         if event.button == 2:
 
 1213         def __init__(self, canvas_x0, canvas_y0, sim_x0, sim_y0):
 
 1221         self.simulation.lock.acquire()
 
 1223             ns3_node = ns.network.NodeList.GetNode(node.node_index)
 
 1224             mob = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
 
 1229             pos = mob.GetPosition()
 
 1231             self.simulation.lock.release()            
 
 1232         x, y, dummy = self.canvas.window.get_pointer()
 
 1233         x0, y0 = self.canvas.convert_from_pixels(x, y)
 
 1235         self.node_drag_state.motion_signal = node.canvas_item.connect(
"motion-notify-event", self.
node_drag_motion, node)
 
 1238         self.simulation.lock.acquire()
 
 1240             ns3_node = ns.network.NodeList.GetNode(node.node_index)
 
 1241             mob = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
 
 1246             x, y, dummy = self.canvas.window.get_pointer()
 
 1247             canvas_x, canvas_y = self.canvas.convert_from_pixels(x, y)
 
 1248             dx = (canvas_x - self.node_drag_state.canvas_x0)
 
 1249             dy = (canvas_y - self.node_drag_state.canvas_y0)
 
 1250             pos = mob.GetPosition()
 
 1254             mob.SetPosition(pos)
 
 1257             self.simulation.lock.release()            
 
 1263         node.canvas_item.disconnect(self.node_drag_state.motion_signal)
 
 1268         self.emit(
"populate-node-menu", node, menu)
 
 1269         menu.popup(
None, 
None, 
None, event.button, event.time)
 
 1283                 self.simulation.lock.acquire()
 
 1285                     ns3_node = ns.network.NodeList.GetNode(self.selected_node.node_index)
 
 1287                     self.simulation.lock.release()
 
 1288             self.ipython.updateNamespace({
'selected_node': ns3_node})
 
 1292         if isinstance(node, ns.network.Node):
 
 1293             node = self.
nodes[node.GetId()]
 
 1294         elif isinstance(node, (int, long)):
 
 1295             node = self.
nodes[node]
 
 1296         elif isinstance(node, Node):
 
 1301             raise TypeError(
"expected None, int, viz.Node or ns.network.Node, not %r" % node)
 
 1307             self.selected_node.selected = 
False 
 1310             self.selected_node.selected = 
True 
 1314                 self.simulation.set_nodes_of_interest([])
 
 1316                 self.simulation.set_nodes_of_interest([self.selected_node.node_index])
 
 1322         self.information_windows.append(info_win)
 
 1323         self.simulation.lock.acquire()
 
 1327             self.simulation.lock.release()
 
 1330         self.information_windows.remove(info_win)
 
 1334         hadj = self._scrolled_window.get_hadjustment()
 
 1335         vadj = self._scrolled_window.get_vadjustment()
 
 1336         x, y = self.canvas.convert_from_pixels(hadj.value + x, vadj.value + y)
 
 1337         item = self.canvas.get_item_at(x, y, 
True)
 
 1341         while item 
is not None:
 
 1342             obj = item.get_data(
"pyviz-object")
 
 1344                 obj.tooltip_query(tooltip)
 
 1346             item = item.props.parent
 
 1350         sel = gtk.FileChooserDialog(
"Save...", self.canvas.get_toplevel(),
 
 1351                                     gtk.FILE_CHOOSER_ACTION_SAVE,
 
 1352                                     (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
 
 1353                                      gtk.STOCK_SAVE, gtk.RESPONSE_OK))
 
 1354         sel.set_default_response(gtk.RESPONSE_OK)
 
 1355         sel.set_local_only(
True)
 
 1356         sel.set_do_overwrite_confirmation(
True)
 
 1357         sel.set_current_name(
"Unnamed.pdf")
 
 1359         filter = gtk.FileFilter()
 
 1360         filter.set_name(
"Embedded PostScript")
 
 1361         filter.add_mime_type(
"image/x-eps")
 
 1362         sel.add_filter(filter)
 
 1364         filter = gtk.FileFilter()
 
 1365         filter.set_name(
"Portable Document Graphics")
 
 1366         filter.add_mime_type(
"application/pdf")
 
 1367         sel.add_filter(filter)
 
 1369         filter = gtk.FileFilter()
 
 1370         filter.set_name(
"Scalable Vector Graphics")
 
 1371         filter.add_mime_type(
"image/svg+xml")
 
 1372         sel.add_filter(filter)
 
 1375         if resp != gtk.RESPONSE_OK:
 
 1379         file_name = sel.get_filename()
 
 1386         if file_name 
is None:
 
 1390         x1 = self._scrolled_window.get_hadjustment().value
 
 1391         y1 = self._scrolled_window.get_vadjustment().value
 
 1392         x2 = x1 + self._scrolled_window.get_hadjustment().page_size
 
 1393         y2 = y1 + self._scrolled_window.get_vadjustment().page_size
 
 1394         bounds = goocanvas.Bounds()
 
 1395         bounds.x1, bounds.y1 = self.canvas.convert_from_pixels(x1, y1)
 
 1396         bounds.x2, bounds.y2 = self.canvas.convert_from_pixels(x2, y2)
 
 1397         dest_width = bounds.x2 - bounds.x1
 
 1398         dest_height = bounds.y2 - bounds.y1
 
 1401         dummy, extension = os.path.splitext(file_name)
 
 1402         extension = extension.lower()
 
 1403         if extension == 
'.eps':
 
 1404             surface = cairo.PSSurface(file_name, dest_width, dest_height)
 
 1405         elif extension == 
'.pdf':
 
 1406             surface = cairo.PDFSurface(file_name, dest_width, dest_height)
 
 1407         elif extension == 
'.svg':
 
 1408             surface = cairo.SVGSurface(file_name, dest_width, dest_height)
 
 1410             dialog = gtk.MessageDialog(parent  = self.canvas.get_toplevel(),
 
 1411                                flags   = gtk.DIALOG_DESTROY_WITH_PARENT,
 
 1412                                type    = gtk.MESSAGE_ERROR,
 
 1413                                buttons = gtk.BUTTONS_OK,
 
 1414                                message_format = 
"Unknown extension '%s' (valid extensions are '.eps', '.svg', and '.pdf')" 
 1421         cr = cairo.Context(surface)
 
 1422         cr.translate(-bounds.x1, -bounds.y1)
 
 1423         self.canvas.render(cr, bounds, self.zoom.value)
 
 1428         if isinstance(node, ns.network.Node):
 
 1429             node = self.
nodes[node.GetId()]
 
 1434             self.shell_window.present()
 
 1438         self.shell_window.set_size_request(750,550)
 
 1439         self.shell_window.set_resizable(
True)
 
 1440         scrolled_window = gtk.ScrolledWindow()
 
 1441         scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
 
 1443         self.ipython.modify_font(pango.FontDescription(SHELL_FONT))
 
 1444         self.ipython.set_wrap_mode(gtk.WRAP_CHAR)
 
 1446         scrolled_window.add(self.
ipython)
 
 1447         scrolled_window.show()
 
 1448         self.shell_window.add(scrolled_window)
 
 1449         self.shell_window.show()
 
 1453         self.ipython.updateNamespace({
'viz': self})
 
 1460 initialization_hooks = []
 
 1464     Adds a callback to be called after 
 1465     the visualizer is initialized, like this:: 
 1466        initialization_hook(visualizer, *args) 
 1468     global initialization_hooks
 
 1469     initialization_hooks.append((hook, args))
 
 1478         viz.canvas.set_bounds(cx1, cy1, cx2, cy2)
 
 1483     assert Visualizer.INSTANCE 
is None 
 1484     if _import_error 
is not None:
 
 1486         print >> sys.stderr, 
"No visualization support (%s)." % (str(_import_error),)
 
 1487         ns.core.Simulator.Run()
 
 1491     for hook, args 
in initialization_hooks:
 
 1492         gobject.idle_add(hook, viz, *args)
 
 1493     ns.network.Packet.EnablePrinting()
 
def _canvas_scroll_event(self, dummy_widget, event)
 
def on_enter_notify_event(self, view, target, event)
 
def _on_shell_window_destroy(self, window)
 
def transform_distance_simulation_to_canvas(d)
 
def _start_update_timer(self)
 
def _end_panning(self, event)
 
def _set_selected(self, value)
 
def _on_play_button_toggled(self, button)
 
def _monkey_patch_ipython(self)
 
def set_position(self, x, y)
 
def __init__(self, channel)
 
def on_root_button_press_event(self, view, target, event)
 
def remove_information_window(self, info_win)
 
def on_node_button_release_event(self, view, target, event, node)
 
def add_information_window(self, info_win)
 
def select_node(self, node)
 
def _quit(self, dummy_args)
 
def set_label(self, label)
 
def _create_advanced_controls(self)
 
def _update_svg_position(self, x, y)
 
def _update_appearance(self)
 
def _canvas_button_release(self, dummy_widget, event)
 
def __init__(self, node1, node2)
 
def get_vadjustment(self)
 
def create_link(self, node, node_or_channel)
 
def on_leave_notify_event(self, view, target, event)
 
def _begin_panning(self, widget, event)
 
def set_show_transmissions_mode(self, mode)
 
def transform_point_simulation_to_canvas(x, y)
 
def get_node(self, index)
 
def set_bounds(x1, y1, x2, y2)
 
def _update_position(self)
 
def _update_node_positions(self)
 
def on_node_button_press_event(self, view, target, event, node)
 
transmissions_smoothing_adjustment
 
def node_drag_motion(self, item, targe_item, event, node)
 
def remove_link(self, link)
 
def _get_highlighted(self)
 
def __init__(self, canvas_x0, canvas_y0, sim_x0, sim_y0)
 
def _canvas_button_press(self, widget, event)
 
def add_initialization_hook(hook, args)
 
def begin_node_drag(self, node)
 
def tooltip_query(self, tooltip)
 
def get_hadjustment(self)
 
def __init__(self, visualizer, node_index)
 
def _update_transmissions_view(self)
 
def center_on_node(self, node)
 
def set_position(self, x, y)
 
def set_color(self, color)
 
def _get_export_file_name(self)
 
def update_view_timeout(self)
 
def _panning_motion(self, widget, event)
 
def _take_screenshot(self, dummy_button)
 
def set_follow_node(self, node)
 
def do_simulation_periodic_update(self)
 
def _update_drops_view(self)
 
def lookup_netdevice_traits(class_type)
 
def _start_shell(self, dummy_button)
 
def _get_label_over_line_position(self, pos1_x, pos1_y, pos2_x, pos2_y)
 
def _set_highlighted(self, value)
 
def end_node_drag(self, node)
 
def _update_ipython_selected_node(self)
 
def set_nodes_of_interest(self, nodes)
 
def _canvas_tooltip_cb(self, canvas, x, y, keyboard_mode, tooltip)
 
def transform_distance_canvas_to_simulation(d)
 
def popup_node_menu(self, node, event)
 
def get_channel(self, ns3_channel)