diff options
author | Walter Bender <walter.bender@gmail.com> | 2011-10-18 20:24:06 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2011-10-18 20:24:06 (GMT) |
commit | 2f0963e3d4c842a9f775100ccb27a20254eca13f (patch) | |
tree | 955a56985da836370f88cb5509e43f7f8dfd6cee | |
parent | 919e8066884eb4a520d2ccae22847909df15f464 (diff) |
added custom ball combo box
-rw-r--r-- | FractionBounceActivity.py | 27 | ||||
-rw-r--r-- | ball.py | 40 | ||||
-rw-r--r-- | toolbar_utils.py | 44 | ||||
-rw-r--r-- | utils.py | 24 |
4 files changed, 120 insertions, 15 deletions
diff --git a/FractionBounceActivity.py b/FractionBounceActivity.py index bc0ba92..dfa30d7 100644 --- a/FractionBounceActivity.py +++ b/FractionBounceActivity.py @@ -12,6 +12,7 @@ # Boston, MA 02111-1307, USA. import gtk +import os from sugar.activity import activity from sugar import profile @@ -36,14 +37,15 @@ from gettext import gettext as _ import logging _logger = logging.getLogger('fractionbounce-activity') -from toolbar_utils import image_factory, separator_factory, \ +from toolbar_utils import image_factory, separator_factory, combo_factory, \ label_factory, radio_factory, button_factory, entry_factory -from utils import json_load, json_dump +from utils import json_load, json_dump, chooser from svg_utils import svg_str_to_pixbuf, generate_xo_svg from bounce import Bounce +BALLS = [_('basketball'), _('soccer ball'), _('user defined')] SERVICE = 'org.sugarlabs.FractionBounceActivity' IFACE = SERVICE PATH = '/org/augarlabs/FractionBounceActivity' @@ -153,6 +155,10 @@ class FractionBounceActivity(activity.Activity): self._add_fraction_cb, tooltip=_('add new fraction'), accelerator='Return') + separator_factory(toolbar, expand=False, visible=True) + self._ball_selector = combo_factory(BALLS, toolbar, self._combo_cb, + default=_('basketball'), + tooltip=_('choose a ball')) def _setup_canvas(self): ''' Create a canvas ''' @@ -164,6 +170,23 @@ class FractionBounceActivity(activity.Activity): self.show_all() return canvas + def _combo_cb(self, arg=None): + ''' Load a new ball based on the selector value. ''' + if not hasattr(self, '_ball_selector'): + return + if BALLS[self._ball_selector.get_active()] == _('basketball'): + self.bounce_window.ball.new_ball(os.path.join( + activity.get_bundle_path(), 'basketball.svg')) + elif BALLS[self._ball_selector.get_active()] == _('soccer ball'): + self.bounce_window.ball.new_ball(os.path.join( + activity.get_bundle_path(), 'soccer.svg')) + else: + chooser(self, '', self._new_ball_from_journal) + + def _new_ball_from_journal(self, dsobject): + ''' Load an image from the Journal. ''' + self.bounce_window.ball.new_ball_from_image(dsobject.file_path) + def _fraction_cb(self, arg=None): ''' Set fraction mode ''' self.bounce_window.mode = 'fractions' @@ -11,10 +11,15 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. +import gtk + from sprites import Sprite from svg_utils import svg_header, svg_footer, svg_str_to_pixbuf, \ extract_svg_payload, svg_from_file +import logging +_logger = logging.getLogger('fractionbounce-activity') + SIZE = 85 ANIMATION = {10: (0, 1), 15: (1, 2), 20: (2, 1), 25: (1, 2), 30: (2, 1), @@ -76,11 +81,11 @@ class Ball(): interaction. ''' def __init__(self, sprites, filename): - ''' Create a ball object and Easter Egg animation from an SVG file. ''' - self.ball = Sprite(sprites, 0, 0, svg_str_to_pixbuf( - svg_from_file(filename))) self.current_frame = 0 self.frames = [] # Easter Egg animation + self.sprites = sprites + self.ball = Sprite(self.sprites, 0, 0, svg_str_to_pixbuf( + svg_from_file(filename))) self.ball.set_layer(1) self.ball.set_label_attributes(24) @@ -88,13 +93,34 @@ class Ball(): ball = extract_svg_payload(file(filename, 'r')) for i in range(8): self.frames.append(Sprite( - sprites, 0, 0, svg_str_to_pixbuf( + self.sprites, 0, 0, svg_str_to_pixbuf( svg_header(SIZE, SIZE, 1.0) + TRANSFORMS[i] + \ ball + PUNCTURE + AIR + '</g>' + svg_footer()))) - for spr in self.frames: - spr.set_layer(1) - spr.move((0, -SIZE)) # move animation frames off screen + for frame in self.frames: + frame.set_layer(1) + frame.move((0, -SIZE)) # move animation frames off screen + + def new_ball(self, filename): + ''' Create a ball object and Easter Egg animation from an SVG file. ''' + self.ball.images[0] = svg_str_to_pixbuf(svg_from_file(filename)) + + ball = extract_svg_payload(file(filename, 'r')) + for i in range(8): + self.frames[i].images[0] = svg_str_to_pixbuf( + svg_header(SIZE, SIZE, 1.0) + TRANSFORMS[i] + \ + ball + PUNCTURE + AIR + '</g>' + svg_footer()) + + def new_ball_from_image(self, filename): + ''' Just create a ball object from an image file ''' + if filename == '': + _logger.debug('Image file not found.') + return + try: + self.ball.images[0] = gtk.gdk.pixbuf_new_from_file_at_size( + filename, SIZE, SIZE) + except: + _logger.debug('Could not load image from %s.', filename) def ball_x(self): return self.ball.get_xy()[0] diff --git a/toolbar_utils.py b/toolbar_utils.py index 9dea658..b75a464 100644 --- a/toolbar_utils.py +++ b/toolbar_utils.py @@ -15,27 +15,59 @@ import gtk from sugar.graphics.radiotoolbutton import RadioToolButton from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.combobox import ComboBox +from sugar.graphics.toolcombobox import ToolComboBox -def entry_factory(default_string, toolbar, tooltip='', max=3): - """ Factory for adding a text box to a toolbar """ + +def combo_factory(combo_array, toolbar, callback, cb_arg=None, + tooltip=None, default=None): + '''Factory for making a toolbar combo box''' + combo = ComboBox() + if tooltip is not None and hasattr(combo, 'set_tooltip_text'): + combo.set_tooltip_text(tooltip) + if cb_arg is not None: + combo.connect('changed', callback, cb_arg) + else: + combo.connect('changed', callback) + for i, selection in enumerate(combo_array): + combo.append_item(i, selection, None) + combo.show() + toolitem = gtk.ToolItem() + toolitem.add(combo) + if hasattr(toolbar, 'insert'): # the main toolbar + toolbar.insert(toolitem, -1) + else: # or a secondary toolbar + toolbar.props.page.insert(toolitem, -1) + toolitem.show() + if default is not None: + combo.set_active(combo_array.index(default)) + return combo + + +def entry_factory(default_string, toolbar, tooltip=None, max=3): + ''' Factory for adding a text box to a toolbar ''' entry = gtk.Entry() entry.set_text(default_string) - if hasattr(entry, 'set_tooltip_text'): + if tooltip is not None and hasattr(entry, 'set_tooltip_text'): entry.set_tooltip_text(tooltip) entry.set_width_chars(max) entry.show() toolitem = gtk.ToolItem() toolitem.add(entry) - toolbar.insert(toolitem, -1) + if hasattr(toolbar, 'insert'): # the main toolbar + toolbar.insert(toolitem, -1) + else: # or a secondary toolbar + toolbar.props.page.insert(toolitem, -1) toolitem.show() return entry def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None, accelerator=None): - """Factory for making toolbar buttons""" + '''Factory for making toolbar buttons''' button = ToolButton(icon_name) - button.set_tooltip(tooltip) + if tooltip is not None: + button.set_tooltip(tooltip) button.props.sensitive = True if accelerator is not None: button.props.accelerator = accelerator @@ -11,6 +11,10 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. +import gtk + +from sugar.graphics.objectchooser import ObjectChooser + from StringIO import StringIO try: USING_JSON_READWRITE = False @@ -52,3 +56,23 @@ def json_dump(data): _io = StringIO() jdump(data, _io) return _io.getvalue() + + +def chooser(parent_window, filter, action): + """ Choose an object from the datastore and take some action """ + chooser = None + try: + chooser = ObjectChooser(parent=parent_window, what_filter=filter) + except TypeError: + chooser = ObjectChooser(None, parent_window, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + if chooser is not None: + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + dsobject = chooser.get_selected_object() + action(dsobject) + dsobject.destroy() + finally: + chooser.destroy() + del chooser |