"Fossies" - the Fresh Open Source Software Archive

Member "radialnet/gui/ControlWidget.py" (18 Feb 2008, 38217 Bytes) of package /linux/privat/old/radialnet-0.44.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "ControlWidget.py" see the Fossies "Dox" file reference documentation.

    1 # vim: set fileencoding=utf-8 :
    2 
    3 # Copyright (C) 2007, 2008 Insecure.Com LLC.
    4 #
    5 # Author: João Paulo de Souza Medeiros <ignotus21@gmail.com>
    6 #
    7 # This program is free software; you can redistribute it and/or modify
    8 # it under the terms of the GNU General Public License as published by
    9 # the Free Software Foundation; either version 2 of the License, or
   10 # (at your option) any later version.
   11 #
   12 # This program is distributed in the hope that it will be useful,
   13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15 # GNU General Public License for more details.
   16 #
   17 # You should have received a copy of the GNU General Public License
   18 # along with this program; if not, write to the Free Software
   19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   20 
   21 import gtk
   22 import math
   23 import gobject
   24 
   25 import bestwidgets as bw
   26 import util.drawing as drawing
   27 import util.geometry as geometry
   28 
   29 from core.Coordinate import PolarCoordinate
   30 from gui.RadialNet import *
   31 
   32 
   33 OPTIONS = ['address',
   34            'hostname',
   35            'icon',
   36            'latency',
   37            'ring',
   38            'region',
   39            'slow in/out']
   40 
   41 REFRESH_RATE = 500
   42 
   43 
   44 
   45 class ControlWidget(bw.BWVBox):
   46     """
   47     """
   48     def __init__(self, radialnet):
   49         """
   50         """
   51         bw.BWVBox.__init__(self)
   52         self.set_border_width(6)
   53 
   54         self.radialnet = radialnet
   55 
   56         self.__create_widgets()
   57 
   58 
   59     def __create_widgets(self):
   60         """
   61         """
   62         self.__action = ControlAction(self.radialnet)
   63         self.__interpolation = ControlInterpolation(self.radialnet)
   64         self.__layout = ControlLayout(self.radialnet)
   65         self.__view = ControlView(self.radialnet)
   66 
   67         self.bw_pack_start_noexpand_nofill(self.__action)
   68         self.bw_pack_start_noexpand_nofill(self.__interpolation)
   69         self.bw_pack_start_noexpand_nofill(self.__layout)
   70         self.bw_pack_start_noexpand_nofill(self.__view)
   71 
   72 
   73 
   74 class ControlAction(bw.BWExpander):
   75     """
   76     """
   77     def __init__(self, radialnet):
   78         """
   79         """
   80         bw.BWExpander.__init__(self, 'Action')
   81         self.set_expanded(True)
   82 
   83         self.radialnet = radialnet
   84 
   85         self.__create_widgets()
   86 
   87 
   88     def __create_widgets(self):
   89         """
   90         """
   91         self.__tbox = bw.BWTable(1, 4)
   92         self.__tbox.bw_set_spacing(0)
   93         self.__vbox = bw.BWVBox()
   94 
   95         self.__tooltips = gtk.Tooltips()
   96 
   97         self.__jump_to = gtk.RadioToolButton(None, gtk.STOCK_JUMP_TO)
   98         self.__jump_to.set_tooltip(self.__tooltips, 'Change focus')
   99         self.__jump_to.connect('toggled',
  100                                self.__change_pointer,
  101                                POINTER_JUMP_TO)
  102 
  103         self.__info = gtk.RadioToolButton(self.__jump_to, gtk.STOCK_INFO)
  104         self.__info.set_tooltip(self.__tooltips, 'Show information')
  105         self.__info.connect('toggled',
  106                             self.__change_pointer,
  107                             POINTER_INFO)
  108 
  109         self.__group = gtk.RadioToolButton(self.__jump_to, gtk.STOCK_ADD)
  110         self.__group.set_tooltip(self.__tooltips, 'Group children')
  111         self.__group.connect('toggled',
  112                              self.__change_pointer,
  113                              POINTER_GROUP)
  114 
  115         self.__region = gtk.RadioToolButton(self.__jump_to,
  116                                             gtk.STOCK_SELECT_COLOR)
  117         self.__region.set_tooltip(self.__tooltips, 'Fill region')
  118         self.__region.connect('toggled',
  119                               self.__change_pointer,
  120                               POINTER_FILL)
  121 
  122         self.__region_color = gtk.combo_box_new_text()
  123         self.__region_color.append_text('Red')
  124         self.__region_color.append_text('Yellow')
  125         self.__region_color.append_text('Green')
  126         self.__region_color.connect('changed', self.__change_region)
  127         self.__region_color.set_active(self.radialnet.get_region_color())
  128 
  129         self.__tbox.bw_attach_next(self.__jump_to)
  130         self.__tbox.bw_attach_next(self.__info)
  131         self.__tbox.bw_attach_next(self.__group)
  132         self.__tbox.bw_attach_next(self.__region)
  133 
  134         self.__vbox.bw_pack_start_noexpand_nofill(self.__tbox)
  135         self.__vbox.bw_pack_start_noexpand_nofill(self.__region_color)
  136 
  137         self.bw_add(self.__vbox)
  138 
  139         self.__jump_to.set_active(True)
  140         self.__region_color.set_no_show_all(True)
  141         self.__region_color.hide()
  142 
  143 
  144     def __change_pointer(self, widget, pointer):
  145         """
  146         """
  147         if pointer != self.radialnet.get_pointer_status():
  148             self.radialnet.set_pointer_status(pointer)
  149 
  150         if pointer == POINTER_FILL:
  151             self.__region_color.show()
  152         else:
  153             self.__region_color.hide()
  154 
  155 
  156     def __change_region(self, widget):
  157         """
  158         """
  159         self.radialnet.set_region_color(self.__region_color.get_active())
  160 
  161 
  162 
  163 class ControlVariableWidget(gtk.DrawingArea):
  164     """
  165     """
  166     def __init__(self, name, value, update, increment=1):
  167         """
  168         """
  169         gtk.DrawingArea.__init__(self)
  170 
  171         self.__variable_name = name
  172         self.__value = value
  173         self.__update = update
  174         self.__increment_pass = increment
  175 
  176         self.__radius = 6
  177         self.__increment_time = 100
  178 
  179         self.__pointer_position = 0
  180         self.__active_increment = False
  181 
  182         self.__last_value = self.__value()
  183 
  184         self.connect('expose_event', self.expose)
  185         self.connect('button_press_event', self.button_press)
  186         self.connect('button_release_event', self.button_release)
  187         self.connect('motion_notify_event', self.motion_notify)
  188 
  189         self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
  190                         gtk.gdk.BUTTON_RELEASE_MASK |
  191                         gtk.gdk.MOTION_NOTIFY |
  192                         gtk.gdk.POINTER_MOTION_HINT_MASK |
  193                         gtk.gdk.POINTER_MOTION_MASK)
  194 
  195         gobject.timeout_add(REFRESH_RATE, self.verify_value)
  196 
  197 
  198     def verify_value(self):
  199         """
  200         """
  201         if self.__value() != self.__last_value:
  202             self.__last_value = self.__value()
  203 
  204         self.queue_draw()
  205 
  206         return True
  207 
  208 
  209     def button_press(self, widget, event):
  210         """
  211         """
  212         self.__active_increment = False
  213         pointer = self.get_pointer()
  214 
  215         if self.__button_is_clicked(pointer) and event.button == 1:
  216 
  217             event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
  218             self.__active_increment = True
  219             self.__increment_value()
  220 
  221 
  222     def button_release(self, widget, event):
  223         """
  224         """
  225         event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
  226 
  227         self.__active_increment = False
  228         self.__pointer_position = 0
  229 
  230         self.queue_draw()
  231 
  232 
  233     def motion_notify(self, widget, event):
  234         """
  235         Drawing callback
  236         @type  widget: GtkWidget
  237         @param widget: Gtk widget superclass
  238         @type  event: GtkEvent
  239         @param event: Gtk event of widget
  240         @rtype: boolean
  241         @return: Indicator of the event propagation
  242         """
  243         if self.__active_increment == True:
  244 
  245             xc, yc = self.__center_of_widget
  246             x, _ = self.get_pointer()
  247 
  248             if x - self.__radius > 0 and x + self.__radius < 2 * xc:
  249                 self.__pointer_position = x - xc
  250 
  251         self.queue_draw()
  252 
  253 
  254     def expose(self, widget, event):
  255         """
  256         Drawing callback
  257         @type  widget: GtkWidget
  258         @param widget: Gtk widget superclass
  259         @type  event: GtkEvent
  260         @param event: Gtk event of widget
  261         @rtype: boolean
  262         @return: Indicator of the event propagation
  263         """
  264         self.set_size_request(100, 30)
  265 
  266         self.context = widget.window.cairo_create()
  267         self.__draw()
  268 
  269         return True
  270 
  271 
  272     def __draw(self):
  273         """
  274         """
  275         allocation = self.get_allocation()
  276 
  277         self.__center_of_widget = (allocation.width / 2,
  278                                    allocation.height / 2)
  279 
  280         xc, yc = self.__center_of_widget
  281 
  282         # draw line
  283         self.context.set_line_width(1)
  284         self.context.set_dash([1,2])
  285         self.context.move_to(self.__radius,
  286                              yc + self.__radius)
  287         self.context.line_to(2 * xc - 5,
  288                              yc + self.__radius)
  289         self.context.stroke()
  290 
  291         # draw text
  292         self.context.set_dash([1,0])
  293         self.context.set_font_size(10)
  294 
  295         width = self.context.text_extents(self.__variable_name)[2]
  296         self.context.move_to(5, yc - self.__radius)
  297         self.context.show_text(self.__variable_name)
  298 
  299         width = self.context.text_extents(str(self.__value()))[2]
  300         self.context.move_to(2 * xc - width - 5, yc - self.__radius)
  301         self.context.show_text(str(self.__value()))
  302 
  303         self.context.set_line_width(1)
  304         self.context.stroke()
  305 
  306         # draw node
  307         self.context.arc(xc + self.__pointer_position,
  308                          yc + self.__radius,
  309                          self.__radius, 0, 2 * math.pi)
  310         if self.__active_increment == True:
  311             self.context.set_source_rgb(0.0, 0.0, 0.0)
  312         else:
  313             self.context.set_source_rgb(1.0, 1.0, 1.0)
  314         self.context.fill_preserve()
  315         self.context.set_source_rgb(0.0, 0.0, 0.0)
  316         self.context.stroke()
  317 
  318 
  319     def __button_is_clicked(self, pointer):
  320         """
  321         """
  322         xc, yc = self.__center_of_widget
  323         center = (xc, yc + self.__radius)
  324 
  325         if geometry.is_in_circle(pointer, 6, center) == True:
  326             return True
  327 
  328         return False
  329 
  330 
  331     def __increment_value(self):
  332         """
  333         """
  334         self.__update(self.__value() + self.__pointer_position / 4)
  335 
  336         self.queue_draw()
  337 
  338         if self.__active_increment == True:
  339 
  340             gobject.timeout_add(self.__increment_time,
  341                                 self.__increment_value)
  342 
  343 
  344     def set_value_function(self, value):
  345         """
  346         """
  347         self.__value = value
  348 
  349 
  350     def set_update_function(self, update):
  351         """
  352         """
  353         self.__update = update
  354 
  355 
  356 
  357 class ControlVariable(bw.BWHBox):
  358     """
  359     """
  360     def __init__(self, name, get_function, set_function, increment=1):
  361         """
  362         """
  363         bw.BWHBox.__init__(self, spacing=0)
  364 
  365         self.__increment_pass = increment
  366         self.__increment_time = 200
  367         self.__increment = False
  368 
  369         self.__name = name
  370         self.__get_function = get_function
  371         self.__set_function = set_function
  372 
  373         self.__create_widgets()
  374 
  375 
  376     def __create_widgets(self):
  377         """
  378         """
  379         self.__control = ControlVariableWidget(self.__name,
  380                                                self.__get_function,
  381                                                self.__set_function,
  382                                                self.__increment_pass)
  383 
  384         self.__left_button = gtk.Button()
  385         self.__left_button.set_size_request(20, 20)
  386         self.__left_arrow = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_NONE)
  387         self.__left_button.add(self.__left_arrow)
  388         self.__left_button.connect('pressed',
  389                                    self.__pressed,
  390                                    -self.__increment_pass)
  391         self.__left_button.connect('released', self.__released)
  392 
  393         self.__right_button = gtk.Button()
  394         self.__right_button.set_size_request(20, 20)
  395         self.__right_arrow = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_NONE)
  396         self.__right_button.add(self.__right_arrow)
  397         self.__right_button.connect('pressed',
  398                                     self.__pressed,
  399                                     self.__increment_pass)
  400         self.__right_button.connect('released', self.__released)
  401 
  402         self.bw_pack_start_noexpand_nofill(self.__left_button)
  403         self.bw_pack_start_expand_fill(self.__control)
  404         self.bw_pack_start_noexpand_nofill(self.__right_button)
  405 
  406 
  407     def __pressed(self, widget, increment):
  408         """
  409         """
  410         self.__increment = True
  411         self.__increment_function(increment)
  412 
  413 
  414     def __increment_function(self, increment):
  415         """
  416         """
  417         if self.__increment:
  418 
  419             self.__set_function(self.__get_function() + increment)
  420             self.__control.verify_value()
  421 
  422             gobject.timeout_add(self.__increment_time,
  423                                 self.__increment_function,
  424                                 increment)
  425 
  426 
  427     def __released(self, widget):
  428         """
  429         """
  430         self.__increment = False
  431 
  432 
  433 
  434 
  435 class ControlFisheye(bw.BWVBox):
  436     """
  437     """
  438     def __init__(self, radialnet):
  439         """
  440         """
  441         bw.BWVBox.__init__(self)
  442         self.set_border_width(6)
  443 
  444         self.radialnet = radialnet
  445         self.__ring_max_value = self.radialnet.get_number_of_rings()
  446 
  447         self.__create_widgets()
  448 
  449 
  450     def __create_widgets(self):
  451         """
  452         """
  453         self.__params = bw.BWHBox()
  454 
  455         self.__fisheye_label = gtk.Label('<b>Fisheye</b> on ring')
  456         self.__fisheye_label.set_use_markup(True)
  457 
  458         self.__ring = gtk.Adjustment(0, 0, self.__ring_max_value, 0.01, 0.01)
  459 
  460         self.__ring_spin = gtk.SpinButton(self.__ring)
  461         self.__ring_spin.set_digits(2)
  462 
  463         self.__ring_scale = gtk.HScale(self.__ring)
  464         self.__ring_scale.set_size_request(100, -1)
  465         self.__ring_scale.set_digits(2)
  466         self.__ring_scale.set_value_pos(gtk.POS_LEFT)
  467         self.__ring_scale.set_draw_value(False)
  468         self.__ring_scale.set_update_policy(gtk.UPDATE_CONTINUOUS)
  469 
  470         self.__interest_label = gtk.Label('with interest factor')
  471         self.__interest = gtk.Adjustment(0, 0, 10, 0.01)
  472         self.__interest_spin = gtk.SpinButton(self.__interest)
  473         self.__interest_spin.set_digits(2)
  474 
  475         self.__spread_label = gtk.Label('and spread factor')
  476         self.__spread = gtk.Adjustment(0, -1.0, 1.0, 0.01, 0.01)
  477         self.__spread_spin = gtk.SpinButton(self.__spread)
  478         self.__spread_spin.set_digits(2)
  479 
  480         self.__params.bw_pack_start_noexpand_nofill(self.__fisheye_label)
  481         self.__params.bw_pack_start_noexpand_nofill(self.__ring_spin)
  482         self.__params.bw_pack_start_expand_fill(self.__ring_scale)
  483         self.__params.bw_pack_start_noexpand_nofill(self.__interest_label)
  484         self.__params.bw_pack_start_noexpand_nofill(self.__interest_spin)
  485         self.__params.bw_pack_start_noexpand_nofill(self.__spread_label)
  486         self.__params.bw_pack_start_noexpand_nofill(self.__spread_spin)
  487 
  488         self.bw_pack_start_noexpand_nofill(self.__params)
  489 
  490         self.__ring.connect('value_changed', self.__change_ring)
  491         self.__interest.connect('value_changed', self.__change_interest)
  492         self.__spread.connect('value_changed', self.__change_spread)
  493 
  494         gobject.timeout_add(REFRESH_RATE, self.__update_fisheye)
  495 
  496 
  497     def __update_fisheye(self):
  498         """
  499         """
  500         # adjust ring scale to radialnet number of nodes
  501         ring_max_value = self.radialnet.get_number_of_rings() - 1
  502 
  503         if ring_max_value != self.__ring_max_value:
  504 
  505             value = self.__ring.get_value()
  506 
  507             if value == 0 and ring_max_value != 0:
  508                 value = 1
  509 
  510             elif value > ring_max_value:
  511                 value = ring_max_value
  512 
  513             self.__ring.set_all(value, 1, ring_max_value, 0.01, 0.01, 0)
  514             self.__ring_max_value = ring_max_value
  515 
  516             self.__ring_scale.queue_draw()
  517 
  518         # check ring value
  519         ring_value = self.radialnet.get_fisheye_ring()
  520 
  521         if self.__ring.get_value() != ring_value:
  522             self.__ring.set_value(ring_value)
  523 
  524         # check interest value
  525         interest_value = self.radialnet.get_fisheye_interest()
  526 
  527         if self.__interest.get_value() != interest_value:
  528             self.__interest.set_value(interest_value)
  529 
  530         # check spread value
  531         spread_value = self.radialnet.get_fisheye_spread()
  532 
  533         if self.__spread.get_value() != spread_value:
  534             self.__spread.set_value(spread_value)
  535 
  536         return True
  537 
  538 
  539     def active_fisheye(self):
  540         """
  541         """
  542         self.radialnet.set_fisheye(True)
  543         self.__change_ring()
  544         self.__change_interest()
  545 
  546 
  547     def deactive_fisheye(self):
  548         """
  549         """
  550         self.radialnet.set_fisheye(False)
  551 
  552 
  553     def __change_ring(self, widget=None):
  554         """
  555         """
  556         if not self.radialnet.is_in_animation():
  557             self.radialnet.set_fisheye_ring(self.__ring.get_value())
  558         else:
  559             self.__ring.set_value(self.radialnet.get_fisheye_ring())
  560 
  561 
  562     def __change_interest(self, widget=None):
  563         """
  564         """
  565         if not self.radialnet.is_in_animation():
  566             self.radialnet.set_fisheye_interest(self.__interest.get_value())
  567         else:
  568             self.__interest.set_value(self.radialnet.get_fisheye_interest())
  569 
  570 
  571     def __change_spread(self, widget=None):
  572         """
  573         """
  574         if not self.radialnet.is_in_animation():
  575             self.radialnet.set_fisheye_spread(self.__spread.get_value())
  576         else:
  577             self.__spread.set_value(self.radialnet.get_fisheye_spread())
  578 
  579 
  580 
  581 class ControlInterpolation(bw.BWExpander):
  582     """
  583     """
  584     def __init__(self, radialnet):
  585         """
  586         """
  587         bw.BWExpander.__init__(self, 'Interpolation')
  588 
  589         self.radialnet = radialnet
  590 
  591         self.__create_widgets()
  592 
  593 
  594     def __create_widgets(self):
  595         """
  596         """
  597         self.__vbox = bw.BWVBox()
  598 
  599         self.__cartesian_radio = gtk.RadioButton(None, 'Cartesian')
  600         self.__polar_radio = gtk.RadioButton(self.__cartesian_radio, 'Polar')
  601         self.__cartesian_radio.connect('toggled',
  602                                        self.__change_system,
  603                                        INTERPOLATION_CARTESIAN)
  604         self.__polar_radio.connect('toggled',
  605                                    self.__change_system,
  606                                    INTERPOLATION_POLAR)
  607 
  608         self.__system_box = bw.BWHBox()
  609         self.__system_box.bw_pack_start_noexpand_nofill(self.__polar_radio)
  610         self.__system_box.bw_pack_start_noexpand_nofill(self.__cartesian_radio)
  611 
  612         self.__frames_box = bw.BWHBox()
  613         self.__frames_label = gtk.Label('Frames')
  614         self.__frames_label.set_alignment(0.0, 0.5)
  615         self.__frames = gtk.Adjustment(self.radialnet.get_number_of_frames(),
  616                                        1,
  617                                        1000,
  618                                        1)
  619         self.__frames.connect('value_changed', self.__change_frames)
  620         self.__frames_spin = gtk.SpinButton(self.__frames)
  621         self.__frames_box.bw_pack_start_expand_fill(self.__frames_label)
  622         self.__frames_box.bw_pack_start_noexpand_nofill(self.__frames_spin)
  623 
  624         self.__vbox.bw_pack_start_noexpand_nofill(self.__frames_box)
  625         self.__vbox.bw_pack_start_noexpand_nofill(self.__system_box)
  626 
  627         self.bw_add(self.__vbox)
  628 
  629         gobject.timeout_add(REFRESH_RATE, self.__update_animation)
  630 
  631 
  632     def __update_animation(self):
  633         """
  634         """
  635         active = self.radialnet.get_interpolation()
  636 
  637         if active == INTERPOLATION_CARTESIAN:
  638             self.__cartesian_radio.set_active(True)
  639 
  640         else:
  641             self.__polar_radio.set_active(True)
  642 
  643         return True
  644 
  645 
  646     def __change_system(self, widget, value):
  647         """
  648         """
  649         if not self.radialnet.set_interpolation(value):
  650 
  651             active = self.radialnet.get_interpolation()
  652 
  653             if active == INTERPOLATION_CARTESIAN:
  654                 self.__cartesian_radio.set_active(True)
  655 
  656             else:
  657                 self.__polar_radio.set_active(True)
  658 
  659 
  660     def __change_frames(self, widget):
  661         """
  662         """
  663         if not self.radialnet.set_number_of_frames(self.__frames.get_value()):
  664             self.__frames.set_value(self.radialnet.get_number_of_frames())
  665 
  666 
  667 
  668 class ControlLayout(bw.BWExpander):
  669     """
  670     """
  671     def __init__(self, radialnet):
  672         """
  673         """
  674         bw.BWExpander.__init__(self, 'Layout')
  675 
  676         self.radialnet = radialnet
  677 
  678         self.__create_widgets()
  679 
  680 
  681     def __create_widgets(self):
  682         """
  683         """
  684         self.__hbox = bw.BWHBox()
  685 
  686         self.__layout = gtk.combo_box_new_text()
  687         self.__layout.append_text('Symmetric')
  688         self.__layout.append_text('Weighted')
  689         self.__layout.set_active(self.radialnet.get_layout())
  690         self.__layout.connect('changed', self.__change_layout)
  691         self.__force = gtk.ToolButton(gtk.STOCK_REFRESH)
  692         self.__force.connect('clicked', self.__force_update)
  693 
  694         self.__hbox.bw_pack_start_expand_fill(self.__layout)
  695         self.__hbox.bw_pack_start_noexpand_nofill(self.__force)
  696 
  697         self.bw_add(self.__hbox)
  698 
  699         self.__check_layout()
  700 
  701 
  702     def __check_layout(self):
  703         """
  704         """
  705         if self.__layout.get_active() == LAYOUT_WEIGHTED:
  706             self.__force.set_sensitive(True)
  707 
  708         else:
  709             self.__force.set_sensitive(False)
  710 
  711         return True
  712 
  713 
  714     def __force_update(self, widget):
  715         """
  716         """
  717         self.__fisheye_ring = self.radialnet.get_fisheye_ring()
  718         self.radialnet.update_layout()
  719 
  720 
  721     def __change_layout(self, widget):
  722         """
  723         """
  724         if not self.radialnet.set_layout(self.__layout.get_active()):
  725             self.__layout.set_active(self.radialnet.get_layout())
  726 
  727         else:
  728             self.__check_layout()
  729 
  730 
  731 
  732 class ControlRingGap(bw.BWVBox):
  733     """
  734     """
  735     def __init__(self, radialnet):
  736         """
  737         """
  738         bw.BWVBox.__init__(self)
  739 
  740         self.radialnet = radialnet
  741 
  742         self.__create_widgets()
  743 
  744 
  745     def __create_widgets(self):
  746         """
  747         """
  748         self.__radius = ControlVariable('Ring gap',
  749                                         self.radialnet.get_ring_gap,
  750                                         self.radialnet.set_ring_gap)
  751 
  752         self.__label = gtk.Label('Lower ring gap')
  753         self.__label.set_alignment(0.0, 0.5)
  754         self.__adjustment = gtk.Adjustment(self.radialnet.get_min_ring_gap(),
  755                                            0,
  756                                            50,
  757                                            1)
  758         self.__spin = gtk.SpinButton(self.__adjustment)
  759         self.__spin.connect('value_changed', self.__change_lower)
  760 
  761         self.__lower_hbox = bw.BWHBox()
  762         self.__lower_hbox.bw_pack_start_expand_fill(self.__label)
  763         self.__lower_hbox.bw_pack_start_noexpand_nofill(self.__spin)
  764 
  765         self.bw_pack_start_noexpand_nofill(self.__radius)
  766         self.bw_pack_start_noexpand_nofill(self.__lower_hbox)
  767 
  768 
  769     def __change_lower(self, widget):
  770         """
  771         """
  772         if not self.radialnet.set_min_ring_gap(self.__adjustment.get_value()):
  773             self.__adjustment.set_value(self.radialnet.get_min_ring_gap())
  774 
  775 
  776 
  777 class ControlOptions(bw.BWScrolledWindow):
  778     """
  779     """
  780     def __init__(self, radialnet):
  781         """
  782         """
  783         bw.BWScrolledWindow.__init__(self)
  784 
  785         self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
  786         self.set_shadow_type(gtk.SHADOW_NONE)
  787 
  788         self.radialnet = radialnet
  789 
  790         self.__create_widgets()
  791 
  792 
  793     def __create_widgets(self):
  794         """
  795         """
  796         self.__liststore = gtk.ListStore(gobject.TYPE_BOOLEAN,
  797                                          gobject.TYPE_STRING)
  798 
  799         self.__liststore.append([None, OPTIONS[0]])
  800         self.__liststore.append([None, OPTIONS[1]])
  801         self.__liststore.append([None, OPTIONS[2]])
  802         self.__liststore.append([None, OPTIONS[3]])
  803         self.__liststore.append([None, OPTIONS[4]])
  804         self.__liststore.append([None, OPTIONS[5]])
  805         self.__liststore.append([None, OPTIONS[6]])
  806 
  807         self.__cell_toggle = gtk.CellRendererToggle()
  808         self.__cell_toggle.set_property('activatable', True)
  809         self.__cell_toggle.connect('toggled',
  810                                    self.__change_option,
  811                                    self.__liststore)
  812 
  813         self.__column_toggle = gtk.TreeViewColumn('', self.__cell_toggle)
  814         self.__column_toggle.add_attribute(self.__cell_toggle, 'active', 0)
  815 
  816         self.__cell_text = gtk.CellRendererText()
  817 
  818         self.__column_text = gtk.TreeViewColumn('Enable',
  819                                                 self.__cell_text,
  820                                                 text=1)
  821 
  822         self.__treeview = gtk.TreeView(self.__liststore)
  823         self.__treeview.set_enable_search(True)
  824         self.__treeview.set_search_column(1)
  825         self.__treeview.append_column(self.__column_toggle)
  826         self.__treeview.append_column(self.__column_text)
  827 
  828         self.add_with_viewport(self.__treeview)
  829 
  830         gobject.timeout_add(REFRESH_RATE, self.__update_options)
  831 
  832 
  833     def __update_options(self):
  834         """
  835         """
  836         model = self.__liststore
  837 
  838         model[OPTIONS.index('address')][0] = self.radialnet.get_show_address()
  839         model[OPTIONS.index('hostname')][0] = self.radialnet.get_show_hostname()
  840         model[OPTIONS.index('icon')][0] = self.radialnet.get_show_icon()
  841         model[OPTIONS.index('latency')][0] = self.radialnet.get_show_latency()
  842         model[OPTIONS.index('ring')][0] = self.radialnet.get_show_ring()
  843         model[OPTIONS.index('region')][0] = self.radialnet.get_show_region()
  844         model[OPTIONS.index('slow in/out')][0] = self.radialnet.get_slow_inout()
  845 
  846         return True
  847 
  848 
  849     def __change_option(self, cell, option, model):
  850         """
  851         """
  852         option = int(option)
  853         model[option][0] = not model[option][0]
  854 
  855         if OPTIONS[option] == 'address':
  856             self.radialnet.set_show_address(model[option][0])
  857 
  858         elif OPTIONS[option] == 'hostname':
  859             self.radialnet.set_show_hostname(model[option][0])
  860 
  861         elif OPTIONS[option] == 'icon':
  862             self.radialnet.set_show_icon(model[option][0])
  863 
  864         elif OPTIONS[option] == 'latency':
  865             self.radialnet.set_show_latency(model[option][0])
  866 
  867         elif OPTIONS[option] == 'ring':
  868             self.radialnet.set_show_ring(model[option][0])
  869 
  870         elif OPTIONS[option] == 'region':
  871             self.radialnet.set_show_region(model[option][0])
  872 
  873         elif OPTIONS[option] == 'slow in/out':
  874             self.radialnet.set_slow_inout(model[option][0])
  875 
  876 
  877 
  878 class ControlView(bw.BWExpander):
  879     """
  880     """
  881     def __init__(self, radialnet):
  882         """
  883         """
  884         bw.BWExpander.__init__(self, 'View')
  885         self.set_expanded(True)
  886 
  887         self.radialnet = radialnet
  888 
  889         self.__create_widgets()
  890 
  891 
  892     def __create_widgets(self):
  893         """
  894         """
  895         self.__vbox = bw.BWVBox(spacing=0)
  896 
  897         self.__zoom = ControlVariable('Zoom',
  898                                       self.radialnet.get_zoom,
  899                                       self.radialnet.set_zoom)
  900 
  901         self.__ring_gap = ControlRingGap(self.radialnet)
  902         self.__navigation = ControlNavigation(self.radialnet)
  903 
  904         self.__options = ControlOptions(self.radialnet)
  905         self.__options.set_border_width(0)
  906 
  907         self.__vbox.bw_pack_start_expand_nofill(self.__options)
  908         self.__vbox.bw_pack_start_noexpand_nofill(self.__navigation)
  909         self.__vbox.bw_pack_start_noexpand_nofill(self.__zoom)
  910         self.__vbox.bw_pack_start_noexpand_nofill(self.__ring_gap)
  911 
  912         self.bw_add(self.__vbox)
  913 
  914 
  915 
  916 class ControlNavigation(gtk.DrawingArea):
  917     """
  918     """
  919     def __init__(self, radialnet):
  920         """
  921         """
  922         gtk.DrawingArea.__init__(self)
  923 
  924         self.radialnet = radialnet
  925 
  926         self.__rotate_node = PolarCoordinate()
  927         self.__rotate_node.set_coordinate(40, 90)
  928         self.__center_of_widget = (50, 50)
  929         self.__moving = None
  930         self.__centering = False
  931         self.__rotating = False
  932         self.__move_pass = 100
  933 
  934         self.__move_position = (0, 0)
  935         self.__move_addition = [(-1, 0),
  936                                 (-1,-1),
  937                                 ( 0,-1),
  938                                 ( 1,-1),
  939                                 ( 1, 0),
  940                                 ( 1, 1),
  941                                 ( 0, 1),
  942                                 (-1, 1)]
  943 
  944         self.__move_factor = 1
  945         self.__move_factor_limit = 20
  946 
  947         self.__rotate_radius = 6
  948         self.__move_radius = 6
  949 
  950         self.__rotate_clicked = False
  951         self.__move_clicked = None
  952 
  953         self.connect('expose_event', self.expose)
  954         self.connect('button_press_event', self.button_press)
  955         self.connect('button_release_event', self.button_release)
  956         self.connect('motion_notify_event', self.motion_notify)
  957         self.connect('enter_notify_event', self.enter_notify)
  958         self.connect('leave_notify_event', self.leave_notify)
  959         self.connect('key_press_event', self.key_press)
  960         self.connect('key_release_event', self.key_release)
  961 
  962         self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
  963                         gtk.gdk.BUTTON_RELEASE_MASK |
  964                         gtk.gdk.ENTER_NOTIFY |
  965                         gtk.gdk.LEAVE_NOTIFY |
  966                         gtk.gdk.MOTION_NOTIFY |
  967                         gtk.gdk.NOTHING |
  968                         gtk.gdk.KEY_PRESS_MASK |
  969                         gtk.gdk.KEY_RELEASE_MASK |
  970                         gtk.gdk.POINTER_MOTION_HINT_MASK |
  971                         gtk.gdk.POINTER_MOTION_MASK)
  972 
  973         self.__rotate_node.set_coordinate(40, self.radialnet.get_rotation())
  974 
  975 
  976     def key_press(self, widget, event):
  977         """
  978         """
  979         key = gtk.gdk.keyval_name(event.keyval)
  980 
  981         self.queue_draw()
  982 
  983         return True
  984 
  985 
  986     def key_release(self, widget, event):
  987         """
  988         """
  989         key = gtk.gdk.keyval_name(event.keyval)
  990 
  991         self.queue_draw()
  992 
  993         return True
  994 
  995 
  996     def enter_notify(self, widget, event):
  997         """
  998         """
  999         return False
 1000 
 1001 
 1002     def leave_notify(self, widget, event):
 1003         """
 1004         """
 1005         self.queue_draw()
 1006 
 1007         return False
 1008 
 1009 
 1010     def button_press(self, widget, event):
 1011         """
 1012         Drawing callback
 1013         @type  widget: GtkWidget
 1014         @param widget: Gtk widget superclass
 1015         @type  event: GtkEvent
 1016         @param event: Gtk event of widget
 1017         @rtype: boolean
 1018         @return: Indicator of the event propagation
 1019         """
 1020         pointer = self.get_pointer()
 1021 
 1022         direction = False
 1023 
 1024         if self.__rotate_is_clicked(pointer) == True:
 1025 
 1026             event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
 1027             self.__rotating = True
 1028 
 1029         direction = self.__move_is_clicked(pointer)
 1030 
 1031         if direction != None and self.__moving == None:
 1032 
 1033             event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
 1034             self.__moving = direction
 1035             self.__move_in_direction(direction)
 1036 
 1037         if self.__center_is_clicked(pointer) == True:
 1038 
 1039             event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
 1040             self.__centering = True
 1041             self.__move_position = (0, 0)
 1042             self.radialnet.set_translation(self.__move_position)
 1043 
 1044         self.queue_draw()
 1045 
 1046         return False
 1047 
 1048 
 1049     def button_release(self, widget, event):
 1050         """
 1051         Drawing callback
 1052         @type  widget: GtkWidget
 1053         @param widget: Gtk widget superclass
 1054         @type  event: GtkEvent
 1055         @param event: Gtk event of widget
 1056         @rtype: boolean
 1057         @return: Indicator of the event propagation
 1058         """
 1059         self.__moving = None        # stop moving
 1060         self.__centering = False
 1061         self.__rotating = False     # stop rotate
 1062         self.__move_factor = 1
 1063 
 1064         event.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
 1065 
 1066         self.queue_draw()
 1067 
 1068         return False
 1069 
 1070 
 1071     def motion_notify(self, widget, event):
 1072         """
 1073         Drawing callback
 1074         @type  widget: GtkWidget
 1075         @param widget: Gtk widget superclass
 1076         @type  event: GtkEvent
 1077         @param event: Gtk event of widget
 1078         @rtype: boolean
 1079         @return: Indicator of the event propagation
 1080         """
 1081         xc, yc = self.__center_of_widget
 1082         x, y = self.get_pointer()
 1083 
 1084         status = not self.radialnet.is_in_animation()
 1085         status = status and not self.radialnet.is_empty()
 1086 
 1087         if self.__rotating == True and status:
 1088 
 1089             r, t = self.__rotate_node.get_coordinate()
 1090             t = math.degrees(math.atan2(yc - y, x - xc))
 1091 
 1092             if t < 0:
 1093                 t = 360 + t
 1094 
 1095             self.radialnet.set_rotation(t)
 1096             self.__rotate_node.set_coordinate(r, t)
 1097 
 1098             self.queue_draw()
 1099         
 1100         return False
 1101 
 1102 
 1103     def expose(self, widget, event):
 1104         """
 1105         Drawing callback
 1106         @type  widget: GtkWidget
 1107         @param widget: Gtk widget superclass
 1108         @type  event: GtkEvent
 1109         @param event: Gtk event of widget
 1110         @rtype: boolean
 1111         @return: Indicator of the event propagation
 1112         """
 1113         self.set_size_request(120, 130)
 1114 
 1115         self.context = widget.window.cairo_create()
 1116         self.__draw()
 1117 
 1118         return False
 1119 
 1120 
 1121     def __draw_rotate_control(self):
 1122         """
 1123         """
 1124         xc, yc = self.__center_of_widget
 1125         r, t = self.__rotate_node.get_coordinate()
 1126         x, y = self.__rotate_node.to_cartesian()
 1127 
 1128         # draw text
 1129         self.context.set_font_size(10)
 1130         self.context.move_to(xc - 49, yc - 48)
 1131         self.context.show_text("Navigation")
 1132 
 1133         width = self.context.text_extents(str(int(t)))[2]
 1134         self.context.move_to(xc + 49 - width - 2, yc - 48)
 1135         self.context.show_text(str(round(t, 1)))
 1136         self.context.set_line_width(1)
 1137         self.context.stroke()
 1138 
 1139         # draw arc
 1140         self.context.set_dash([1,2])
 1141         self.context.arc(xc, yc, 40, 0, 2 * math.pi)
 1142         self.context.set_source_rgb(0.0, 0.0, 0.0)
 1143         self.context.set_line_width(1)
 1144         self.context.stroke()
 1145 
 1146         # draw node
 1147         self.context.set_dash([1,0])
 1148         self.context.arc(xc + x, yc - y, self.__rotate_radius, 0, 2 * math.pi)
 1149 
 1150         if self.__rotating == True:
 1151             self.context.set_source_rgb(0.0, 0.0, 0.0)
 1152 
 1153         else:
 1154             self.context.set_source_rgb(1.0, 1.0, 1.0)
 1155 
 1156         self.context.fill_preserve()
 1157         self.context.set_source_rgb(0.0, 0.0, 0.0)
 1158         self.context.set_line_width(1)
 1159         self.context.stroke()
 1160 
 1161         return False
 1162 
 1163 
 1164     def __draw_move_control(self):
 1165         """
 1166         """
 1167         xc, yc = self.__center_of_widget
 1168         pc = PolarCoordinate()
 1169 
 1170         self.context.set_dash([1,1])
 1171         self.context.arc(xc, yc, 23, 0, 2 * math.pi)
 1172         self.context.set_source_rgb(0.0, 0.0, 0.0)
 1173         self.context.set_line_width(1)
 1174         self.context.stroke()
 1175 
 1176         for i in range(8):
 1177 
 1178             pc.set_coordinate(23, 45 * i)
 1179             x, y = pc.to_cartesian()
 1180         
 1181             self.context.set_dash([1,1])
 1182             self.context.move_to(xc, yc)
 1183             self.context.line_to(xc + x, yc - y)
 1184             self.context.stroke()
 1185 
 1186             self.context.set_dash([1,0])
 1187             self.context.arc(xc + x, yc - y, self.__move_radius, 0, 2 * math.pi)
 1188 
 1189             if i == self.__moving:
 1190                 self.context.set_source_rgb(0.0, 0.0, 0.0)
 1191             else:
 1192                 self.context.set_source_rgb(1.0, 1.0, 1.0)
 1193             self.context.fill_preserve()
 1194             self.context.set_source_rgb(0.0, 0.0, 0.0)
 1195             self.context.set_line_width(1)
 1196             self.context.stroke()
 1197 
 1198         self.context.arc(xc, yc, 6, 0, 2 * math.pi)
 1199 
 1200         if self.__centering == True:
 1201             self.context.set_source_rgb(0.0, 0.0, 0.0)
 1202         else:
 1203             self.context.set_source_rgb(1.0, 1.0, 1.0)
 1204         self.context.fill_preserve()
 1205         self.context.set_source_rgb(0.0, 0.0, 0.0)
 1206         self.context.set_line_width(1)
 1207         self.context.stroke()
 1208 
 1209         return False
 1210 
 1211 
 1212     def __draw(self):
 1213         """
 1214         Drawing method
 1215         """
 1216         # Getting allocation reference
 1217         allocation = self.get_allocation()
 1218 
 1219         self.__center_of_widget = (allocation.width / 2,
 1220                                    allocation.height / 2)
 1221 
 1222         self.__draw_rotate_control()
 1223         self.__draw_move_control()
 1224 
 1225         return False
 1226 
 1227 
 1228     def __move_in_direction(self, direction):
 1229         """
 1230         """
 1231         if self.__moving != None:
 1232 
 1233             bx, by = self.__move_position
 1234             ax, ay = self.__move_addition[direction]
 1235 
 1236             self.__move_position = (bx + self.__move_factor * ax,
 1237                                     by + self.__move_factor * ay)
 1238             self.radialnet.set_translation(self.__move_position)
 1239 
 1240             if self.__move_factor < self.__move_factor_limit:
 1241                 self.__move_factor += 1
 1242 
 1243             gobject.timeout_add(self.__move_pass,
 1244                                 self.__move_in_direction,
 1245                                 direction)
 1246 
 1247         return False
 1248 
 1249 
 1250     def __rotate_is_clicked(self, pointer):
 1251         """
 1252         """
 1253         xn, yn = self.__rotate_node.to_cartesian()
 1254         xc, yc = self.__center_of_widget
 1255 
 1256         center = (xc + xn, yc - yn)
 1257         result = geometry.is_in_circle(pointer, self.__rotate_radius, center)
 1258 
 1259         if result == True:
 1260             return True
 1261 
 1262         return False
 1263 
 1264 
 1265     def __center_is_clicked(self, pointer):
 1266         """
 1267         """
 1268         result = geometry.is_in_circle(pointer,
 1269                                        self.__move_radius,
 1270                                        self.__center_of_widget)
 1271 
 1272         if result == True:
 1273             return True
 1274 
 1275         return False
 1276 
 1277 
 1278     def __move_is_clicked(self, pointer):
 1279         """
 1280         """
 1281         xc, yc = self.__center_of_widget
 1282         pc = PolarCoordinate()
 1283 
 1284         for i in range(8):
 1285 
 1286             pc.set_coordinate(23, 45 * i)
 1287             x, y = pc.to_cartesian()
 1288         
 1289             center = (xc + x, yc - y)
 1290             result = geometry.is_in_circle(pointer,
 1291                                            self.__move_radius,
 1292                                            center)
 1293 
 1294             if result == True:
 1295                 return i
 1296 
 1297         return None
 1298 
 1299