# python import import logging, os # .. from functools import partial from gettext import gettext as _ # gtk import import gobject, gtk, glib # sugar import from sugar.activity import activity # atoidejouer import from atoidejouer.db import story from atoidejouer.tools import config, image, storage, ui # get application logger logger = logging.getLogger('atoidejouer') COLOR_GREY_DARK = ui.get_color(0.5, 0.5, 0.5) COLOR_GREY_LIGHT = ui.get_color(0.75, 0.75, 0.75) COLOR_GREY_WHITE = ui.get_color(0.85, 0.85, 0.85) COLOR_WHITE = ui.get_color(1.0, 1.0, 1.0) def _set_bg(widget): # bg widget.modify_bg(gtk.STATE_NORMAL, COLOR_GREY_WHITE) widget.modify_bg(gtk.STATE_PRELIGHT, COLOR_GREY_WHITE) widget.modify_bg(gtk.STATE_ACTIVE, COLOR_WHITE) # fg widget.modify_fg(gtk.STATE_NORMAL, COLOR_WHITE) def _on_position_clicked(widget, panel, move, value): # shortcut _activity = panel.screen.toolbar.activity if _activity._thread._pause is False\ or panel.key is None: pass elif move == 'x': panel.key.x += value elif move == 'y': panel.key.y += value else: raise Exception('[ui.panel] _on_position_clicked"\ " - invalid position move: %s' % move) # DB update story.DB().update(panel.key) # update panel entries panel.entry_x.set_text(str(panel.key.x)) panel.entry_y.set_text(str(-panel.key.y)) # refresh scene panel.screen.scene.refresh(key=panel.key) def _on_layout_clicked(widget, panel, move): # shortcut _activity = panel.screen.toolbar.activity # get max _layout_max = story.DB().get_layout_max() # do nothing if _activity._thread._pause is False\ or panel.key is None: return # layout factory elif move == 'move_up_up': panel.key.layout = _layout_max elif move == 'move_up': panel.key.layout = panel.key.layout + 1\ if panel.key.layout < _layout_max else _layout_max elif move == 'move_down': panel.key.layout = panel.key.layout - 1\ if panel.key.layout > 0 else 0 elif move == 'move_down_down': panel.key.layout = 0 else: raise Exception('[ui.panel] _on_layout_clicked"\ " - invalid layout move: %s' % move) # DB update story.DB().update(panel.key) # update entry panel.entry_layout.set_text(str(panel.key.layout)) # refresh scene panel.screen.scene.refresh() def _on_time_clicked(widget, panel, value): # shortcut _activity = panel.screen.toolbar.activity # little check if _activity._thread._pause is False\ or panel.key is None: return else: _time = _activity._thread._time # time factory _time += value panel.key.time = 0 if _time < 0 else _time # DB update story.DB().update(panel.key) # entry update panel.time_entry.set_text('%1d:%02d' % divmod(_time, 60)) # update thread time _activity._thread.set_time(time_=_time) def _on_remove_key_clicked(widget, panel): # shortcut _activity = panel.screen.toolbar.activity if _activity._thread._pause is False\ or panel.key is None: return else: # delete story.DB()._del(panel.key) # empty key panel.key = None # refresh scene panel.screen.scene.refresh() # and reset panel panel.refresh() def _on_duration_clicked(widget, panel, value): # shortcut _activity = panel.screen.toolbar.activity _duration_max = story.DB().get_duration_max() # do nothing if _activity._thread._pause is False\ or panel.key is None: pass elif panel.key.duration + value < 0: panel.key.duration = 0 elif panel.key.duration + value > _duration_max: panel.key.duration = _duration_max else: panel.key.duration += value # DB update story.DB().update(panel.key) # update panel entries panel.entry_duration.set_text( '%1d:%02d' % divmod(panel.key.duration, 60)) def _on_loop_click(toggle, panel, image): # update image _stock_id = 'repeat_grey' if toggle.get_active() is True else 'repeat' image.set_from_file(storage.get_icon_path(_stock_id)) # shortcut _activity = panel.screen.toolbar.activity # do nothing if _activity._thread._pause is False\ or panel.key is None: return else: panel.key.loop = toggle.get_active() # DB update story.DB().update(panel.key) def _get_next_time(panel, factor): # get the current frame _time = 0.0 if panel.screen.toolbar.activity._thread is None\ else panel.screen.toolbar.activity._thread._time # get rate _rate = config.Config().get_rate_value() # next time _next = _time + factor * _rate # get max _max = panel.screen.toolbar.activity._number_of_keys - 1 if _next < _max: # ok! return _next else: # return max + pause return _max def _get_previous_time(panel, factor): # get the current frame _time = 0.0 if panel.screen.toolbar.activity._thread is None\ else panel.screen.toolbar.activity._thread._time # get rate _rate = config.Config().get_rate_value() # previous time _previous = _time - factor * _rate # .. if _previous < 0: # return min return 0 else: # ok return _previous def _on_key_press(widget, event, parent): # .. _keyval = event.keyval _name = gtk.gdk.keyval_name(_keyval) _mod = gtk.accelerator_get_label(_keyval, event.state) # .. if parent.screen != parent.screen.toolbar.activity.get_current_screen(): return # key factory elif panel.screen.toolbar.name == 'edit': # POSITION if _name == 'Left' and _mod.startswith('Ctrl+'): # big left _on_position_clicked(widget, parent, 'x', -10) elif _name == 'Left': # left _on_position_clicked(widget, parent, 'x', -1) elif _name == 'Right' and _mod.startswith('Ctrl+'): # big right _on_position_clicked(widget, parent, 'x', 10) elif _name == 'Right': # right _on_position_clicked(widget, parent, 'x', 1) elif _name == 'Up' and _mod.startswith('Ctrl+'): # big top _on_position_clicked(widget, parent, 'y', -10) elif _name == 'Up': # top _on_position_clicked(widget, parent, 'y', -1) elif _name == 'Down' and _mod.startswith('Ctrl+'): # big bottom _on_position_clicked(widget, parent, 'y', 10) elif _name == 'Down': # bottom _on_position_clicked(widget, parent, 'y', 1) # LAYOUT elif _name == 'Page_Up' and _mod.startswith('Ctrl+'): _on_layout_clicked(widget, parent, 'move_up_up') elif _name == 'Page_Up': _on_layout_clicked(widget, parent, 'move_up') elif _name == 'Page_Down' and _mod.startswith('Ctrl+'): _on_layout_clicked(widget, parent, 'move_down_down') elif _name == 'Page_Down': _on_layout_clicked(widget, parent, 'move_down') # TIME elif _name == 'plus' and _mod.startswith('Ctrl+'): _on_time_clicked(widget, parent, 10) elif _name == 'plus': _on_time_clicked(widget, parent, 1) elif _name == 'minus' and _mod.startswith('Ctrl+'): _on_time_clicked(widget, parent, -10) elif _name == 'minus': _on_time_clicked(widget, parent, -1) # DELETE elif _name == 'BackSpace': _on_remove_key_clicked(widget, parent) # IMAGE # TODO ... # IN EVERY CASE if parent.screen.toolbar.name in ['edit', 'story']: # shortcut _thread = parent.screen.toolbar.activity._thread # .. if _name == 'space': # play right # _time = _get_next_time(parent, 1) # _thread.set_time(time_=_time, pause=True) elif _name == 'space' and _mod.startswith('Ctrl+'): # play left # _time = _get_previous_time(parent, 1) # _thread.set_time(time_=_time, pause=True) # PLAY elif _name == 'Return': # .. if _thread._pause is True: parent.screen.toolbar.play() _thread.play() # .. else: parent.screen.toolbar.pause() _thread.pause() else: pass # avoid propagation for rendering issue widget.emit_stop_by_name('key-press-event') class PanelEdit(gtk.Frame): def __init__(self, screen): # init parent gtk.Frame.__init__(self) self.set_shadow_type(gtk.SHADOW_NONE) # set screen self.screen = screen # key var self.key = None # get mode self._mode = config.Config().get('activity>mode') self._conf = config.Config().get('mode>%s' % self._mode, type_=list) # ... self.set_size_request(298, screen.scene._screen_height) # do show self.show() # init vars self._store = None self.sequence_name = None # .. self.time_entry = None # add vbox to the panel for sub frames self.main_box = gtk.VBox(homogeneous=False, spacing=0) # do show self.main_box.show() # add it to the panel self.add(self.main_box) # .. self.__init_handler() # main vars self.entry_layout = None # .. self.entry_x = None self.entry_y = None # add specific self._frame_layout = None self._frame_position = None self._add_frame_layout() self._add_frame_position() # init sound fields self.entry_duration = None self.toggle_loop = None self.image_loop = None # add specific self._frame_sound = None self._add_frame_sound() # add common self._frame_time = None self._frame_remove = None self.add_frame_time() self.add_frame_remove() def __init_handler(self): _activity = self.screen.toolbar.activity _handler_id = _activity._handler_id if _handler_id: _activity.disconnect(_handler_id) _activity._handler_id = _activity.connect('key-press-event', _on_key_press, self) def clear(self): self.time_entry.set_text('') self.entry_duration.set_text('') self.toggle_loop.set_active(False) # .. self.entry_layout.set_text('') self.entry_x.set_text('') self.entry_y.set_text('') def _get_pixbuf(self, graphic_name, dir_='graphics'): # get the image path _graphic_path = storage.get_image_path(graphic_name, dir_=dir_) # return pix and path return image.get_pixbuf(_graphic_path, 48, 36), _graphic_path def __refresh_image(self): # hide frame sound self._frame_sound.hide() # shortcut _activity = self.screen.toolbar.activity # set layout value self.entry_layout.set_text(str(self.key.layout)) # set x value self.entry_x.set_text(str(self.key.x)) # set y value self.entry_y.set_text(str(-self.key.y)) # hide frame image self._frame_layout.show() self._frame_position.show() def __refresh_sound(self): # hide frame image self._frame_layout.hide() self._frame_position.hide() # update duration value self.entry_duration.set_text('%1d:%02d' % divmod(self.key.duration, 60)) # update loop value self.toggle_loop.set_active(self.key.loop==1) # update image _stock_id = 'repeat_grey' if self.key.loop==1 else 'repeat' self.image_loop.set_from_file(storage.get_icon_path(_stock_id)) # show frame sound self._frame_sound.show() def refresh(self, key=None): self.key = key if not key: """ self._frame_layout.hide() self._frame_position.hide() self._frame_sound.hide() self._frame_time.hide() self._frame_remove.hide() """ self.show_all() return self.clear() elif key.type == 'image': self.__refresh_image() elif key.type == 'sound': self.__refresh_sound() else: raise Exception('[ui.panel] refresh - invalid key: %s' % key) # update common time value self.time_entry.set_text( '%1d:%02d' % divmod(key.time, 60)) self._frame_time.show() self._frame_remove.show() def __get_time_button(self, name, value, tooltip_text): _button = ui.get_button(stock_id=name) _button.set_tooltip_text(tooltip_text) _button.connect('clicked', _on_time_clicked, self, value) return _button def add_frame_time(self): # init frame self._frame_time = gtk.Frame(label=_('Time')) self._frame_time.set_border_width(1) # do show self._frame_time.show() # do add self.main_box.pack_start(self._frame_time, expand=False, fill=True) # get over/under spin buttons _time_box = gtk.HBox(homogeneous=False, spacing=4) _time_box.set_border_width(4) # before .. _time_box.pack_start(self.__get_time_button('go_left', -10, _('Play Before (10 Frames)')), expand=False, fill=True) _time_box.pack_start(self.__get_time_button('go_left_small', -1, _('Play Before (1 Frames)')), expand=False, fill=True) # entry self.time_entry = gtk.Entry() # show self.time_entry.show() # set value - should be a string self.time_entry.set_text('') self.time_entry.set_alignment(1) self.time_entry.set_property('editable', False) # add entry _time_box.pack_start(self.time_entry, expand=True, fill=True) # .. after _time_box.pack_start(self.__get_time_button('go_right_small', 1, _('Play After (1 Frames)')), expand=False, fill=True) _time_box.pack_start(self.__get_time_button('go_right', 10, _('Play After (10 Frames)')), expand=False, fill=True) # do add self._frame_time.add(_time_box) def add_frame_remove(self): # init frame self._frame_remove = gtk.Frame(label=_('Remove')) self._frame_remove.set_border_width(1) # do show self._frame_remove.show() # do add self.main_box.pack_start(self._frame_remove, expand=False, fill=True) # init container _in_vbox = gtk.HBox(homogeneous=True, spacing=4) _in_vbox.set_border_width(4) # do add self._frame_remove.add(_in_vbox) # prepare remove sequence button _rm_key_button = ui.get_button(label=_('Key'), stock_id='remove_item', width=48, padding=(12, 0)) _rm_key_button.set_tooltip_text(_('Remove Key')) # set cb _rm_key_button.connect('clicked', _on_remove_key_clicked, self) # get remove image button _in_vbox.pack_start(_rm_key_button, expand=False, fill=True) def __get_layout_button(self, name, tooltip_text): _button = ui.get_button(stock_id=name) _button.set_tooltip_text(tooltip_text) _button.connect('clicked', _on_layout_clicked, self, name) return _button def _add_frame_layout(self): # init frame self._frame_layout = gtk.Frame(label=_('Layout')) self._frame_layout.set_border_width(1) # do add self.main_box.pack_start(self._frame_layout, expand=False, fill=True) # vbox for the frame _in_vbox = gtk.VBox(homogeneous=False, spacing=4) _in_vbox.set_border_width(4) # do add self._frame_layout.add(_in_vbox) # get over/under spin buttons _layer_box = gtk.HBox(homogeneous=True, spacing=4) # down .. _layer_box.pack_start(self.__get_layout_button('move_down_down', _('Layer to Bottom')), expand=False, fill=True) _layer_box.pack_start(self.__get_layout_button('move_down', _('Lower Layer')), expand=False, fill=True) # entry self.entry_layout = gtk.Entry() # set value - should be a string self.entry_layout.set_text("") self.entry_layout.set_alignment(1) self.entry_layout.set_property('editable', False) # add entry _layer_box.pack_start(self.entry_layout, expand=False, fill=True) # .. up _layer_box.pack_start(self.__get_layout_button('move_up', _('Raise Layer')), expand=False, fill=True) _layer_box.pack_start(self.__get_layout_button('move_up_up', _('Layer to Top')), expand=False, fill=True) # add row sequence _in_vbox.pack_start(_layer_box, expand=True, fill=True) def __get_position_button(self, name, move, value, tooltip_text): # init button _button = ui.get_button(stock_id=name) _button.set_tooltip_text(tooltip_text) _button.connect('clicked', _on_position_clicked, self, move, value) return _button def _add_frame_position(self): # init frame self._frame_position = gtk.Frame(label=_('Position')) self._frame_position.set_border_width(1) # do add self.main_box.pack_start(self._frame_position, expand=False, fill=True) # _vbox _in_vbox = gtk.VBox(homogeneous=False, spacing=4) _in_vbox.set_border_width(4) # first _row _in_vbox.pack_start(self.__get_position_button('y_up_up', 'y', -10, _('Move Up by 10%')), expand=False, fill=False) # second _row _in_vbox.pack_start(self.__get_position_button('y_up', 'y', -1, _('Move Up by 1%')), expand=False, fill=False) # third _row _row3 = gtk.HBox(homogeneous=False, spacing=4) _row3.pack_start(self.__get_position_button('x_left_left', 'x', -10, _('Move Left by 10%')), expand=False, fill=True) _row3.pack_start(self.__get_position_button('x_left', 'x', -1, _('Move Left by 1%')), expand=False, fill=True) # prepare middle box _middle_box = gtk.VBox(homogeneous=True, spacing=4) # get entries _entry_box_x = ui.get_entry(label='X') _entry_box_y = ui.get_entry(label='Y') # update main vars self.entry_x = _entry_box_x.get_children()[1] self.entry_y = _entry_box_y.get_children()[1] # add entries to the box _middle_box.pack_start(_entry_box_x, expand=False, fill=True) _middle_box.pack_start(_entry_box_y, expand=False, fill=True) _middle_box.set_size_request(64, -1) # add the box to the row _row3.pack_start(_middle_box, expand=True, fill=True) _row3.pack_start(self.__get_position_button('x_right', 'x', 1, _('Move Right by 1%')), expand=False, fill=True) _row3.pack_start(self.__get_position_button('x_right_right', 'x', 10, _('Move Right by 10%')), expand=False, fill=True) # and add the third row _in_vbox.pack_start(_row3, expand=False, fill=False) # fourth _row _in_vbox.pack_start(self.__get_position_button('y_down', 'y', 1, _('Move Down by 1%')), expand=False, fill=False) # fifth _row _in_vbox.pack_start(self.__get_position_button('y_down_down', 'y', 10, _('Move Down by 10%')), expand=False, fill=False) # put it in self._frame_position.add(_in_vbox) def _get_time(self, value): """Format the time value to display """ return '%1d:%02d' % divmod(value, 60) def __get_duration_button(self, name, value, tooltip_text): _button = ui.get_button(stock_id=name) _button.set_tooltip_text(tooltip_text) _button.connect('clicked', _on_duration_clicked, self, value) return _button def _get_duration_box(self): # get less/more spin buttons _duration_box = gtk.HBox(homogeneous=True, spacing=4) # down .. _duration_box.pack_start(self.__get_duration_button('less', -10, _('Duration -10s')), expand=False, fill=True) _duration_box.pack_start(self.__get_duration_button('less_small', -1, _('Duration -1s')), expand=False, fill=True) # entry self.entry_duration = gtk.Entry() # set value - should be a string self.entry_duration.set_text('') # self._get_time(0) self.entry_duration.set_alignment(1) self.entry_duration.set_property('editable', False) self.entry_duration.set_size_request(64, -1) # add entry _duration_box.pack_start(self.entry_duration, expand=False, fill=True) _duration_box.pack_start(self.__get_duration_button('more_small', 1, _('Duration +1s')), expand=False, fill=True) _duration_box.pack_start(self.__get_duration_button('more', 10, _('Duration +10s')), expand=False, fill=True) # return it return _duration_box def _init_loop_box(self): # init row _loop_box = gtk.HBox(homogeneous=False, spacing=4) # create image self.image_loop = gtk.Image() # get img path self.image_loop.set_from_file(storage.get_icon_path('repeat')) self.image_loop.set_size_request(48, -1) # add image _loop_box.pack_start(self.image_loop, expand=False, fill=True) # create label _label = gtk.Label(_('Repeat')) _label.set_alignment(0, 0.5) # add label _loop_box.pack_start(_label, expand=True, fill=True) # create checkbox self.toggle_loop = gtk.ToggleButton() # set tooltip self.toggle_loop.set_tooltip_text(_('Loop (On/Off)')) self.toggle_loop.add(_loop_box) # set cb self.toggle_loop.connect('toggled', _on_loop_click, self, self.image_loop) def _add_frame_sound(self): # init frame self._frame_sound = gtk.Frame(label=_('Sound')) self._frame_sound.set_border_width(1) # do add self.main_box.pack_start(self._frame_sound, expand=False, fill=True) # vbox for the fram _in_vbox = gtk.VBox(homogeneous=False, spacing=4) _in_vbox.set_border_width(4) # do add self._frame_sound.add(_in_vbox) # add duration box _in_vbox.pack_start(self._get_duration_box(), expand=False, fill=True) # add loop button self._init_loop_box() _in_vbox.pack_start(self.toggle_loop, expand=False, fill=True)