Mercurial > MadButterfly
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) |