comparison pyink/FSM_window.py @ 1478:6fe773e62b2a

Add state to FSM. - Add a state if user left-click on the background of FSM window. - pop a dialog that user can specify name and radius of the new state.
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 25 Apr 2011 17:52:51 +0800
parents eddec4543761
children 92a8497d0361
comparison
equal deleted inserted replaced
1477:e217c7743905 1478:6fe773e62b2a
1 import gtk 1 import gtk
2 import os 2 import os
3 import data_monitor 3 import data_monitor
4 4
5 class FSM_window_base(object): 5 class FSM_window_base(object):
6 _state_editor = None
7 _state_name = None
8 _state_radius = None
9
10 _error_dialog = None
11 _error_dialog_label = None
12
6 def __init__(self): 13 def __init__(self):
7 super(FSM_window_base, self).__init__() 14 super(FSM_window_base, self).__init__()
8 15
9 dirname = os.path.dirname(__file__) 16 dirname = os.path.dirname(__file__)
10 fname = os.path.join(dirname, 'FSM_window.glade') 17 fname = os.path.join(dirname, 'FSM_window.glade')
12 builder = gtk.Builder() 19 builder = gtk.Builder()
13 builder.add_from_file(fname) 20 builder.add_from_file(fname)
14 21
15 main_win = builder.get_object("FSM_main_win") 22 main_win = builder.get_object("FSM_main_win")
16 view_box = builder.get_object("view_box") 23 view_box = builder.get_object("view_box")
24
25 state_editor = builder.get_object("state_editor")
26 state_name = builder.get_object('state_name')
27 state_radius = builder.get_object('state_radius')
28
29 error_dialog = builder.get_object('error_dialog')
30 error_dialog_label = builder.get_object('error_dialog_label')
17 31
18 builder.connect_signals(self) 32 builder.connect_signals(self)
19 33
20 self._builder = builder 34 self._builder = builder
21 self._main_win = main_win 35 self._main_win = main_win
22 self._view_box = view_box 36 self._view_box = view_box
37
38 self._state_editor = state_editor
39 self._state_name = state_name
40 self._state_radius = state_radius
41
42 self._error_dialog = error_dialog
43 self._error_dialog_label = error_dialog_label
44 pass
45
46 def show_error(self, msg):
47 error_dialog = self._error_dialog
48 error_dialog_label = self._error_dialog_label
49
50 error_dialog_label.set_text(msg)
51 error_dialog.show()
52 pass
53
54 def hide_error(self):
55 error_dialog = self._error_dialog
56 error_dialog.hide()
57 pass
58
59 def show_state_editor(self, state_name=''):
60 state_name_inp = self._state_name
61 state_radius_inp = self._state_radius
62 state_editor = self._state_editor
63
64 state_name_inp.set_text(state_name)
65 state_radius_inp.set_text('30')
66 state_editor.show()
67 pass
68
69 def hide_state_editor(self):
70 state_editor = self._state_editor
71 state_editor.hide()
23 pass 72 pass
24 73
25 def show(self): 74 def show(self):
26 self._main_win.show() 75 self._main_win.show()
27 pass 76 pass
28 77
29 def hide(self): 78 def hide(self):
30 self._main_win.hide() 79 self._main_win.hide()
31 pass 80 pass
81
82 def gtk_widget_hide(self, widget, event, *data):
83 widget.hide()
84 return True
32 85
33 def on_start_state_activate(self, *args): 86 def on_start_state_activate(self, *args):
34 pass 87 pass
35 88
36 def on_rename_state_activate(self, *args): 89 def on_rename_state_activate(self, *args):
53 106
54 def on_close_window_activate(self, *args): 107 def on_close_window_activate(self, *args):
55 pass 108 pass
56 109
57 def on_FSM_main_win_destroy_event(self, *args): 110 def on_FSM_main_win_destroy_event(self, *args):
111 pass
112
113 def on_state_apply_clicked(self, *args):
114 pass
115
116 def on_state_cancel_clicked(self, *args):
117 state_editor = self._state_editor
118 state_editor.hide()
119 pass
120
121 def on_error_dialog_ok_clicked(self, *args):
122 error_dialog = self._error_dialog
123 error_dialog.hide()
58 pass 124 pass
59 pass 125 pass
60 126
61 class FSM_transition(object): 127 class FSM_transition(object):
62 _doc = None 128 _doc = None
280 _background = None 346 _background = None
281 _fsm_layer = None 347 _fsm_layer = None
282 _control_layer = None 348 _control_layer = None
283 width = 1024 349 width = 1024
284 height = 768 350 height = 768
351
352 _grab_hdl = None
353 _bg_hdl = None
354
355 _saved_x = 0
356 _saved_y = 0
285 357
286 def __init__(self, domview_ui, close_cb, destroy_cb): 358 def __init__(self, domview_ui, close_cb, destroy_cb):
287 super(FSM_window, self).__init__() 359 super(FSM_window, self).__init__()
288 360
289 self._locker = domview_ui 361 self._locker = domview_ui
317 389
318 control_layer = doc.createElement('svg:g') 390 control_layer = doc.createElement('svg:g')
319 control_layer.setAttribute('inkscape:groupmode', 'layer') 391 control_layer.setAttribute('inkscape:groupmode', 'layer')
320 root.appendChild(control_layer) 392 root.appendChild(control_layer)
321 self._control_layer = control_layer 393 self._control_layer = control_layer
394
395 self.grab_bg(self.on_add_state_background)
322 pass 396 pass
323 397
324 def _doc(self): 398 def _doc(self):
325 view_widget = self._view_widget 399 view_widget = self._view_widget
326 view = view_widget.view 400 view = view_widget.view
329 403
330 def _root(self): 404 def _root(self):
331 doc = self._doc() 405 doc = self._doc()
332 root = doc.root() 406 root = doc.root()
333 return root 407 return root
408
409 def _translate_xy(self, x, y):
410 return x, y
334 411
335 def _clear_view(self): 412 def _clear_view(self):
336 if not self._background: 413 if not self._background:
337 self._init_layers() 414 self._init_layers()
338 return 415 return
345 pass 422 pass
346 423
347 self._states = {} 424 self._states = {}
348 pass 425 pass
349 426
427 def _draw_state_domview(self, state_name):
428 domview = self._domview
429 doc = self._doc()
430 fsm_layer = self._fsm_layer
431
432 state = FSM_state(state_name)
433 state.init(doc, domview, self._fsm_layer, self._control_layer)
434 self._states[state_name] = state
435
436 state.draw(fsm_layer)
437 pass
438
350 def _update_view(self): 439 def _update_view(self):
351 self._clear_view() 440 self._clear_view()
352 441
353 domview = self._domview 442 domview = self._domview
354 doc = self._doc()
355 fsm_layer = self._fsm_layer
356 443
357 state_names = domview.all_state_names() 444 state_names = domview.all_state_names()
358 for state_name in state_names: 445 for state_name in state_names:
359 state = FSM_state(state_name) 446 self._draw_state_domview(state_name)
360 state.init(doc, domview, self._fsm_layer, self._control_layer)
361 self._states[state_name] = state
362
363 state.draw(fsm_layer)
364 pass 447 pass
365 pass 448 pass
366 449
367 def set_svg_view(self, view): 450 def set_svg_view(self, view):
368 self._view_box.add(view) 451 self._view_box.add(view)
380 def on_FSM_main_win_delete_event(self, *args): 463 def on_FSM_main_win_delete_event(self, *args):
381 self._destroy_cb() 464 self._destroy_cb()
382 pass 465 pass
383 466
384 def on_add_state_toggled(self, *args): 467 def on_add_state_toggled(self, *args):
468 self.ungrab_bg()
469 self.grab_bg(self.on_add_state_background)
470 pass
471
472 def on_move_state_toggled(self, *args):
473 self.ungrab_bg()
474 self.grab_bg(self.on_move_state_background)
475 pass
476
477 def on_add_state_background(self, item, evtype, buttons, x, y):
478 import pybInkscape
479
480 if evtype == pybInkscape.PYSPItem.PYB_EVENT_BUTTON_RELEASE and \
481 buttons == 1:
482 self._saved_x = x
483 self._saved_y = y
484 self.show_state_editor()
485 pass
486 pass
487
488 def on_move_state_background(self, item, evtype, buttons, x, y):
489 pass
490
491 def on_state_apply_clicked(self, *args):
492 import traceback
493
494 domview = self._domview
495 x, y = self._translate_xy(self._saved_x, self._saved_y)
496
497 state_name = self._state_name.get_text()
498 r_txt = self._state_radius.get_text()
499 try:
500 r = float(r_txt)
501 except ValueError:
502 traceback.print_exc()
503 self.show_error('Invalid value: "%s" is not a valid value '
504 'for radius.' % (r_txt))
505 return
506
507 try:
508 domview.add_state(state_name)
509 except:
510 traceback.print_exc()
511 self.show_error('Invalid state name: "%s" is existing' %
512 (state_name))
513 return
514 domview.set_state_xy(state_name, x, y)
515 domview.set_state_r(state_name, r)
516
517 self._draw_state_domview(state_name)
518
519 self.hide_state_editor()
385 pass 520 pass
386 521
387 def _install_test_data(self): 522 def _install_test_data(self):
388 self._init_layers() 523 self._init_layers()
389 524
430 self._install_test_data() 565 self._install_test_data()
431 self._install_test_data = lambda: None 566 self._install_test_data = lambda: None
432 self._update_view() 567 self._update_view()
433 super(FSM_window, self).show() 568 super(FSM_window, self).show()
434 pass 569 pass
570
571 def grab_mouse(self, callback):
572 assert self._grab_hdl is None
573
574 root = self._root()
575 root.setAttribute('inkscape:groupmode', '')
576 self._grab_hdl = root.spitem.connect('mouse-event', callback)
577 pass
578
579 def ungrab_mouse(self):
580 if not self._grab_hdl:
581 return
582
583 root = self._root()
584 root.spitem.disconnect(self._grab_hdl)
585 self._grab_hdl = None
586 root.setAttribute('inkscape:groupmode', 'layer')
587 pass
588
589 def grab_bg(self, callback):
590 assert self._bg_hdl is None
591 assert self._background
592
593 background = self._background
594 bg_hdl = background.spitem.connect('mouse-event', callback)
595 self._bg_hdl = bg_hdl
596 pass
597
598 def ungrab_bg(self):
599 if not self._bg_hdl:
600 return
601
602 background = self._background
603 bg_hdl = self._bg_hdl
604 background.spitem.disconnect(bg_hdl)
605 self._bg_hdl = None
606 pass
435 pass 607 pass
436 608
437 if __name__ == '__main__': 609 if __name__ == '__main__':
438 win = FSM_window() 610 win = FSM_window()
439 win._main_win.connect('destroy', gtk.main_quit) 611 win._main_win.connect('destroy', gtk.main_quit)