root/trunk/umitGUI/radialnet/ControlWidget.py @ 3726

Revision 3726, 37.3 kB (checked in by luis, 5 years ago)

Fixed import barriers (RadialNet integration)

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