diff options
Diffstat (limited to 'atoidejouerbeta/ui/toolbar.py')
-rw-r--r-- | atoidejouerbeta/ui/toolbar.py | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/atoidejouerbeta/ui/toolbar.py b/atoidejouerbeta/ui/toolbar.py new file mode 100644 index 0000000..8103319 --- /dev/null +++ b/atoidejouerbeta/ui/toolbar.py @@ -0,0 +1,721 @@ + +# python import +import logging, os, re, shutil +# ... +from functools import partial +from gettext import gettext as _ + +# gtk import +import gtk, glib + +# sugar import +from sugar.activity import activity + +# sugar import +from sugar.graphics.toolbutton import ToolButton + +# atoidejouerbeta import +from atoidejouerbeta.tools import config, storage +from atoidejouerbeta.ui import screens + +# get application logger +logger = logging.getLogger('atoidejouerbeta') + + +def _clean_dir(dir_path): + # little check first + if os.path.exists(dir_path): + pass + # ??? + else: + return + # .. + for _filename in os.listdir(dir_path): + # .. + _path = os.path.join(dir_path, _filename) + # little check + if os.path.isfile(_path): + os.remove(_path) + elif os.path.isdir(_path): + _clean_dir(_path) + else: + # ERRROR + logger.error('[toolbar] _clean_dir - path error: %s' % dir_path) + # remove dir at the end + os.removedirs(dir_path) + + +def _cb_seq_new(widget, toolbar): + # get screen + _screen = toolbar.activity.get_current_screen() + # remove items from preview boxes + _screen.sequence_preview.clear() + # .. + _screen.notebook.current_sequence = None + # clear entry + toolbar._sequence_entry.set_text("") + + +NON_ALPHA_NUM_PATTERN = re.compile('[\W_]+') + + +def _cb_seq_name(entry): + # ensure good string + _str = NON_ALPHA_NUM_PATTERN.sub('-', entry.get_text()) + # update entry + entry.set_text(_str) + + +def _cb_seq_remove(widget, toolbar): + # get sequence name + _name = toolbar._sequence_entry.get_text() + # get screen + _screen = toolbar.activity.get_current_screen() + # type shortcut 'graphic' or 'sound' + _type = _screen.notebook._type + # little check + if _name.strip() == '': + # do nothing + pass + else: + # get sequence path + _seq_path = storage.get_sequence_path(_type, _name) + # remove dir + if os.path.exists(_seq_path): + # do clean + os.remove(_seq_path) + # and clear all at the end + _screen.sequence_preview.clear() + # clear entry + toolbar._sequence_entry.set_text("") + # update notebook + _screen.notebook._get_store_sequence() + # update focus + _screen.notebook.focus_current_seq() + # nothing to do + else: + pass + + +def _cb_seq_save(widget, toolbar, remove=False): + storage.sequence_save(toolbar, remove=remove) + # get screen + _screen = toolbar.activity.get_current_screen() + # get sequence name + _name = toolbar._sequence_entry.get_text() + # update focus + _screen.notebook.focus_current_seq(name=_name) + + + +def _show_browser(toolbar, cls): + # next screen name + _screen_name = '%s_add' % toolbar.name + # do switch + toolbar._switch(_screen_name) + # get or create screen + _screen = toolbar.activity.get_screen(_screen_name)\ + if toolbar.activity.has_screen(_screen_name)\ + else cls(toolbar) + # update activity screens + toolbar.activity.set_current_screen(_screen_name, _screen) + # do show + _screen._show() + # update entry + _seq_name = _screen.notebook.current_sequence + if _seq_name is None: + pass + else: + # .. + toolbar._sequence_entry.set_text(_seq_name) + # pos + _current_pos = _screen.sequence_preview.get_current_pos() + # .. + if toolbar._frame_entry is None: + pass + else: + toolbar._frame_entry.set_text(str(_current_pos)) + + +def _cb_add(widget, toolbar): + # browser screen factory + if toolbar.name == 'graphics': + _show_browser(toolbar, screens.ScreenBrowserGraphics) + # .. + elif toolbar.name == 'sounds': + _show_browser(toolbar, screens.ScreenBrowserSounds) + # ?? + else: + # ERROR + logger.error('[toolbar] _cb_add - unknown: %s' % toolbar.name) + + +def _cb_remove(widget, toolbar): + # browser screen factory + if toolbar.name == 'graphics': + pass + # .. + elif toolbar.name == 'sounds': + pass + # ?? + else: + # ERROR + logger.error('[toolbar] _cb_remove - name: %s' % toolbar.name) + + +def _cb_frame_after(widget, toolbar): + if toolbar._frame_entry is None: + pass + else: + # get previous value + _value = int(toolbar._frame_entry.get_text()) + # inc it + _update_frame_entry(widget, toolbar, _value + 1) + # update sequence file + _cb_seq_save(widget, toolbar) + + +def _cb_frame_before(widget, toolbar): + if toolbar._frame_entry is None: + pass + else: + # get previous value + _value = int(toolbar._frame_entry.get_text()) + # dec it + _update_frame_entry(widget, toolbar, _value - 1) + # update sequence file + _cb_seq_save(widget, toolbar) + + +def _update_frame_entry(entry, toolbar, value): + # get screen + _screen = toolbar.activity.get_current_screen() + # get max value + _max = _screen.sequence_preview.number_of_items() - 1 + # prepare value + _new_val = None + if value > _max: + _new_val = _max + elif value < 0: + _new_val = 0 + # reset max just in case + else: + _new_val = value + # update entry + toolbar._frame_entry.set_text(str(_new_val)) + # update sequence + _screen.sequence_preview.move_current(_new_val) + + +def _cb_open(widget, toolbar): + pass + + +def _cb_back(widget, toolbar): + # do switch + toolbar._switch(toolbar.name.replace('_add', '')) + # restore screen + toolbar.activity._change_screen(toolbar) + # get screen now + _screen = toolbar.activity.get_current_screen() + _screen.scene.refresh() + + +def _cb_import(widget, toolbar): + # get the current sequence name + _sequence_name = toolbar._sequence_entry.get_text() + # get filenames + _screen = toolbar.activity.get_current_screen() + # shortcut + _filenames = _screen.sequence_preview.items + # add sequence to the story keys + if toolbar.story_keys.add_sequence(_sequence_name, _filenames): + # screen name factory + _screen_name = toolbar.name.replace('_add', '') + # get screen now + _screen = toolbar.activity.get_screen(_screen_name) + # add sequence to the timeline + _screen.timeline.add_sequence(_sequence_name) + # already added + else: + pass + + +def _cb_play(widget, toolbar): + # replace play button + toolbar._replace_button('play', 'pause') + # trigger playing + toolbar.activity._thread.play() + + +def _cb_pause(widget, toolbar): + # replace pause button + toolbar._replace_button('pause', 'play') + # trigger pausing + toolbar.activity._thread.pause() + + +def _cb_stop(widget, toolbar): + # replace pause button - if playing + if toolbar._has_button('pause'): + # .. + toolbar._replace_button('pause', 'play') + else: + pass + # update main thread + toolbar.activity._thread.pause(stop=True) + # .. + toolbar.activity._thread.set_time() + + +def _cb_view_fullscreen(widget, toolbar): + # replace fullscreen button with return button + toolbar._replace_button('view_fullscreen', 'view_return') + # ask_clear + toolbar.story_keys.ask_clear() + # get current screen + _screen = toolbar.activity.get_current_screen() + # enbale fullscreen + _screen.set_fullscreen(True) + + +def _cb_view_return(widget, toolbar): + # remove return button with fullscreen button + toolbar._replace_button('view_return', 'view_fullscreen') + # ask_clear + toolbar.story_keys.ask_clear() + # get current screen + _screen = toolbar.activity.get_current_screen() + # disable fullscreen + _screen.set_fullscreen(False) + + +def _cb_slider(widget, event, toolbar): + """action = 'press' or 'release' + """ + # ... + if event.type == gtk.gdk.BUTTON_PRESS: + pass + elif event.type == gtk.gdk.BUTTON_RELEASE: + toolbar.activity._thread.set_time(time_=widget.get_value()) + # ?? + else: + pass + + +def _cb_format_value(widget, value, toolbar): + """Format the slider value to display + """ + # return formated value + return '%1d:%02d' % divmod(value, 60) + +TOOLBAR_INDEXES = ['activity', 'story', 'graphics', 'sounds', 'help'] + +def _cb_help_back(widget, toolbar): + _previous = toolbar.activity._previous + # restore default tab + toolbar.activity._toolbox.set_current_toolbar( + TOOLBAR_INDEXES.index(_previous.replace('_add', ''))) + # restore previous + toolbar.activity._change_screen(name=_previous) + + +BUTTONS = { + 'add' : ['list-add', _cb_add], + 'back' : ['edit-undo', _cb_back], + 'backward' : ['media-seek-backward', None], + 'forward' : ['media-seek-forward', None], + 'frame_after' : ['go-right', _cb_frame_after], + 'frame_before' : ['go-left', _cb_frame_before], + 'frame_entry' : [None, None], + 'help_back' : ['edit-undo', _cb_help_back], + 'import' : ['insert-image', _cb_import], + 'open' : ['media', _cb_open], + 'pause' : ['media-playback-pause', _cb_pause], + 'play' : ['media-playback-start', _cb_play], + 'remove' : ['list-remove', _cb_remove], + 'separator' : [None, None], + 'seq_new' : ['document-generic', _cb_seq_new], + 'seq_name' : [None, _cb_seq_name], + 'seq_remove' : ['button_cancel', _cb_seq_remove], + 'seq_save' : ['dialog-apply', _cb_seq_save], + 'slider' : [None, _cb_slider], + 'stop' : ['media-playback-stop', _cb_stop], + 'view_fullscreen' : ['view-fullscreen', _cb_view_fullscreen], + 'view_return' : ['view-return', _cb_view_return], + } + +TOOLBARS = { + 'graphics' : [ + ['stop', 'play', 'slider', # 'backward', 'forward' + 'separator', + 'add'], + [] + ], + 'graphics_add' : [ + ['seq_new', 'seq_name', 'seq_save', 'seq_remove', + # 'separator', + # 'add', 'remove', + # ''separator', + # 'frame_before', 'frame_entry', 'frame_after' + ], + ['import', 'back'] + ], + 'sounds' : [ + ['stop', 'play', 'slider', # 'backward', 'forward' + 'separator', + 'add'], + [] + ], + 'sounds_add' : [ + ['seq_new', 'seq_name', 'seq_save', 'seq_remove', + # 'separator', + # 'add', 'remove', + # ''separator', + # 'frame_before', 'frame_entry', 'frame_after' + ], + ['import', 'back'] + ], + 'story' : [ + ['stop', 'play', 'slider', # 'backward', 'forward' + 'separator', + 'view_fullscreen'], + [] + ], + 'help' : [ + [], + ['help_back'] + ] + } + +TITLES = { + 'graphics' : { + 'toolbox': _('Graphic'), + 'buttons': { + # 'backward': _('Seek Backward'), + # 'forward': _('Seek Forward'), + 'pause': _('Pause Story'), + 'play': _('Play Story'), + 'slider': _('Progress Bar'), + 'stop': _('Stop Story'), + 'add': _('Add Graphic'), + } + }, + 'graphics_add' : { + 'toolbox': None, + 'buttons': { + 'add': _('Add Graphic'), + 'back': _('Back'), + 'frame_after': _('Frame Before'), + 'frame_before': _('Frame After'), + 'frame_entry': None, + 'import': _('Import Sequence'), + 'remove': _('Remove Graphic'), + 'seq_new': _('New Sequence'), + 'seq_name': None, + 'seq_remove': _('Remove Sequence'), + 'seq_save': _('Save Sequence'), + } + }, + 'sounds' : { + 'toolbox': _('Sound'), + 'buttons': { + # 'backward': _('Seek Backward'), + # 'forward': _('Seek Forward'), + 'pause': _('Pause Story'), + 'play': _('Play Story'), + 'slider': _('Progress Bar'), + 'stop': _('Stop Story'), + 'add': _('Add Sound'), + } + }, + 'sounds_add' : { + 'toolbox': None, + 'buttons': { + 'add': _('Add Sound'), + 'back': _('Back'), + 'frame_after': _('Frame Before'), + 'frame_before': _('Frame After'), + 'frame_entry': None, + 'import': _('Import Sequence'), + 'remove': _('Remove Sound'), + 'seq_new': _('New Sound'), + 'seq_name': None, + 'seq_remove': _('Remove Sequence'), + 'seq_save': _('Save Sequence'), + } + }, + 'story' : { + 'toolbox': _('Story'), + 'buttons': { + # 'open': _('Open Story'), + # 'backward': _('Seek Backward'), + # 'forward': _('Seek Forward'), + 'pause': _('Pause Story'), + 'play': _('Play Story'), + 'slider': _('Progress Bar'), + 'stop': _('Stop Story'), + 'view_fullscreen': _('Fullscreen'), + 'view_return': _('Default Screen'), + } + }, + 'help' : { + 'toolbox': _('Help'), + 'buttons': { + 'help_back': _('Back') + } + } + } + + +class Toolbar(gtk.Toolbar): + + def __init__(self, activity, name='player'): + # init parent + gtk.Toolbar.__init__(self) + # keep the name + self.set_name(name) + # keep activity + self.activity = activity + # .. + if self.name == 'graphics'\ + or self.name == 'story': + self.story_keys = self.activity.graphic_keys + else: + self.story_keys = self.activity.sound_keys + # adjustment + self._adjustment = None + self._number_of_keys = self.activity._number_of_keys + # keep components + self._sequence_entry = None + self._frame_entry = None + # init widget dict + self._button_dict = dict() + # init buttons + self._init_buttons() + # add tab in toolbox + _toolbox_name = TITLES[self.name]['toolbox'] + if _toolbox_name is None: + pass + else: + _toolbox = self.activity.get_toolbox() + _toolbox.add_toolbar(_toolbox_name, self) + # connect focus event + self.connect('focus', self._on_focus) + # show + self.show() + + def _switch(self, name): + # update toolbar + self._clear_buttons() + # switch name + self.set_name(name) + # reset + self._init_buttons() + + def _clear_buttons(self): + # remove all + for _k in self._button_dict.keys(): + self._remove_button(_k) + # remove separators + for _c in self.get_children(): + # remove it + self.remove(_c) + # and destroy it + _c.destroy() + + def _init_buttons(self): + # add buttons + _b_left, _b_right = TOOLBARS[self.name] + # place left buttons + for _b in _b_left: + # add button + self._add_button(_b) + # add expanded separator + _separator = gtk.SeparatorToolItem() + _separator.set_draw(False) + _separator.set_expand(True) + _separator.show() + self.add(_separator) + # place right buttons + for _b in _b_right: + # add button + self._add_button(_b) + + def update_slider(self, time_, pause): + # get slider + _s = self.get_slider() + # slider stuff + if _s is None: + pass + else: + _s.set_value(time_) + # update pause status + if pause is True: + self._replace_button('pause', 'play') + else: + self._replace_button('play', 'pause') + + def get_slider(self): + # little check + if 'slider' in self._button_dict: + _children = self._button_dict['slider'].get_children() + return None if len(_children) == 0 else _children[0] + else: + return None + + def play(self): + # do pause + _cb_play(None, self) + + def pause(self): + # do pause + _cb_pause(None, self) + + def refresh(self, value): + # ... + if self._number_of_keys != self.activity._number_of_keys: + # update nb of keys + self._number_of_keys = self.activity._number_of_keys + # update adjustment + if hasattr(self._adjustment, 'set_upper'): + self._adjustment.set_upper(self._number_of_keys-1) + else: + self._adjustment.upper = self._number_of_keys-1 + else: + pass + # get slider + _s = self.get_slider() + # slider stuff + if _s is None: + # just in case + value = 0 + else: + # update value + _s.set_value(int(value)) + # return _v to keep time value in thread + return value + + def _on_focus(self, widget, direction): + if self.name in ['graphics_add', 'sounds_add']: + self._switch(self.name.replace('_add', '')) + else: + # update current screen + self.activity._change_screen(self) + if 'add' in self._button_dict: + # enable or disble add + _mode = config.Config().get('activity>mode') + _conf = config.Config().get('mode>%s' % _mode, type_=list) + # .. + self._button_dict['add'].set_sensitive('remove' in _conf) + else: + pass + + def _has_button(self, button_id): + return button_id in self._button_dict + + def _add_button(self, button_id, index=None): + # get button icon and cb + _icon, _cb = BUTTONS[button_id] + # manage separator + if button_id == 'separator': + _buton = gtk.SeparatorToolItem() + _buton.set_draw(True) + # manage slider + elif button_id == 'slider': + # + self._adjustment = gtk.Adjustment(0, 0, self._number_of_keys-1, 1) + # .. + _hscale = gtk.HScale(self._adjustment) + _hscale.set_draw_value(True) + _hscale.set_digits(False) + _hscale.set_update_policy(gtk.UPDATE_CONTINUOUS) + # manage cb + _hscale.connect('button-release-event', _cb, self) + _hscale.connect('format-value', _cb_format_value, self) + # show + _hscale.show() + # .. + _buton = gtk.ToolItem() + _buton.set_expand(True) + _buton.add(_hscale) + elif button_id == 'seq_name': + self._sequence_entry = gtk.Entry() + # show + self._sequence_entry.show() + # .. + self._sequence_entry.connect('changed', _cb) + # .. + _buton = gtk.ToolItem() + _buton.set_expand(True) + _buton.add(self._sequence_entry) + elif button_id == 'frame_entry': + # ... + self._frame_entry = gtk.Entry() + # .. + self._frame_entry.set_editable(False) + self._frame_entry.set_width_chars(2) + self._frame_entry.set_size_request(44, -1) + # set value + self._frame_entry.set_text('0') + # center text + self._frame_entry.set_alignment(1) + # show + self._frame_entry.show() + # .. + _buton = gtk.ToolItem() + _buton.add(self._frame_entry) + # standard button + elif button_id in BUTTONS: + # get tooltip + _tooltip = TITLES[self.name]['buttons'][button_id] + # set icon + _buton = ToolButton(_icon) + # set tooltip + _buton.set_tooltip(_tooltip) + # do connect + if _cb is None: + pass + else: + _buton.connect('clicked', _cb, self) + # ?? + else: + # ERROR + logger.error('[toolbar] _add_button - ??: %s' % button_id) + return + # update the button dict + self._button_dict[button_id] = _buton + # add to the toolbar + if index is None: + self.add(_buton) + else: + self.insert(_buton, index) + # show it + _buton.show() + + def _remove_button(self, button_id): + # little check + if button_id in self._button_dict: + # get button + _buton = self._button_dict.pop(button_id) + # do remove - do it safe + glib.idle_add(partial(self.remove, _buton)) + # and destroy - safe + glib.idle_add(_buton.destroy) + # ?? + else: + # ERROR + logger.error('[toolbar] _remove_button - unknown: %s' % button_id) + + def _replace_button(self, button_id_out, button_id_in): + # little check + if button_id_out in self._button_dict: + # ... + _index = self.get_item_index(self._button_dict[button_id_out]) + # do remove + self._remove_button(button_id_out) + # do it safe + glib.idle_add(partial(self._add_button, button_id_in, _index)) + # ?? + else: + pass |