diff options
author | Rafael Ortiz <rafael@activitycentral.com> | 2011-05-13 16:22:04 (GMT) |
---|---|---|
committer | Rafael Ortiz <rafael@activitycentral.com> | 2011-05-13 16:22:04 (GMT) |
commit | 56cf33caa9569b59f6ebb56a61ba43af3080b274 (patch) | |
tree | 3c0b72c12c9fb9b1505a9ad79d108837bf881b44 /olpcgames/activity.py | |
parent | e50ef664cb553acfa1c14ea541028a7e5a34d346 (diff) |
Ordering files
Diffstat (limited to 'olpcgames/activity.py')
-rw-r--r-- | olpcgames/activity.py | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/olpcgames/activity.py b/olpcgames/activity.py new file mode 100644 index 0000000..27392ea --- /dev/null +++ b/olpcgames/activity.py @@ -0,0 +1,220 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""Embeds the Canvas widget into a Sugar-specific Activity environment""" + +import logging +logging.root.setLevel(logging.WARN) +log = logging.getLogger('olpcgames.activity') +#log.setLevel( logging.INFO ) + +import pygtk +pygtk.require('2.0') +import gtk +import gtk.gdk + +from sugar.activity import activity +from sugar.graphics import style +from olpcgames.canvas import PyGameCanvas +from olpcgames import mesh, util + +__all__ = ['PyGameActivity'] + + +class PyGameActivity(activity.Activity): + + """PyGame-specific activity type, provides boilerplate toolbar, creates canvas + + Subclass Overrides: + + game_name -- specifies a fully-qualified name for the game's main-loop + format like so: + 'package.module:main' + if not function name is provided, "main" is assumed. + game_handler -- alternate specification via direct + reference to a main-loop + function + + game_size -- two-value tuple specifying the size of the display in pixels, + this is currently static, so once the window is created it cannot be + changed. + + If None, use the bulk of the screen for the PyGame surface based on + the values reported by the gtk.gdk functions. Note that None is + *not* the default value. + + game_title -- title to be displayed in the Sugar Shell UI + + pygame_mode -- chooses the rendering engine used for handling the + PyGame drawing mode, 'SDL' chooses the standard PyGame renderer, + 'Cairo' chooses the experimental pygamecairo renderer. + + PYGAME_CANVAS_CLASS -- normally PyGameCanvas, but can be overridden + if you want to provide a different canvas class, e.g. to provide a different + internal layout. Note: only used where pygame_mode == 'SDL' + + The Activity, once created, will be made available as olpcgames.ACTIVITY, + and that access mechanism should allow code to test for the presence of the + activity before accessing Sugar-specific functionality. + + XXX Note that currently the toolbar and window layout are hard-coded into + this super-class, with no easy way of overriding without completely rewriting + the __init__ method. We should allow for customising both the UI layout and + the toolbar contents/layout/connection. + + XXX Note that if you change the title of your activity in the toolbar you may + see the same focus issues as we have patched around in the build_toolbar + method. If so, please report them to Mike Fletcher. + + """ + + game_name = None + game_title = 'PyGame Game' + game_handler = None + game_size = (16 * style.GRID_CELL_SIZE, 11 * style.GRID_CELL_SIZE) + pygame_mode = 'SDL' + + def __init__(self, handle): + """Initialise the Activity with the activity-description handle""" + + super(PyGameActivity, self).__init__(handle) + self.make_global() + if self.game_size is None: + (width, height) = (gtk.gdk.screen_width(), + gtk.gdk.screen_height()) + log.info('Total screen size: %s %s', width, height) + + # for now just fudge the toolbar size... + + self.game_size = (width, height - 1 * style.GRID_CELL_SIZE) + self.set_title(self.game_title) + toolbar = self.build_toolbar() + log.debug('Toolbar size: %s', toolbar.get_size_request()) + canvas = self.build_canvas() + + def make_global(self): + """Hack to make olpcgames.ACTIVITY point to us + """ + + import weakref + import olpcgames + assert not olpcgames.ACTIVITY, \ + """Activity.make_global called twice, have you created two Activity instances in a single process?""" + olpcgames.ACTIVITY = weakref.proxy(self) + + def build_toolbar(self): + """Build our Activity toolbar for the Sugar system + + This is a customisation point for those games which want to + provide custom toolbars when running under Sugar. + """ + + try: + from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton + from sugar.activity.widgets import ActivityToolbarButton, StopButton, \ + ShareButton, KeepButton + from mybutton import MyActivityToolbarButton + + toolbar_box = ToolbarBox() + activity_button = MyActivityToolbarButton(self) + toolbar_box.toolbar.insert(activity_button, 0) + activity_button.show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + share_button = ShareButton(self) + toolbar_box.toolbar.insert(share_button, -1) + share_button.show() + + keep_button = KeepButton(self) + toolbar_box.toolbar.insert(keep_button, -1) + keep_button.show() + + stop_button = StopButton(self) + toolbar_box.toolbar.insert(stop_button, -1) + stop_button.show() + + self.set_toolbar_box(toolbar_box) + toolbar_box.show() + toolbar=toolbar_box.toolbar + except ImportError: + toolbar = activity.ActivityToolbar(self) + toolbar.show() + self.set_toolbox(toolbar) + toolbar.title.unset_flags(gtk.CAN_FOCUS) + + def shared_cb(*args, **kwargs): + log.info('shared: %s, %s', args, kwargs) + try: + mesh.activity_shared(self) + except Exception, err: + log.error("""Failure signaling activity sharing to mesh module: %s""" + , util.get_traceback(err)) + else: + log.info('mesh activity shared message sent, trying to grab focus' + ) + try: + self._pgc.grab_focus() + except Exception, err: + log.warn('Focus failed: %s', err) + else: + log.info('asserting focus') + assert self._pgc.is_focus(), \ + """Did not successfully set pygame canvas focus""" + log.info('callback finished') + + def joined_cb(*args, **kwargs): + log.info('joined: %s, %s', args, kwargs) + mesh.activity_joined(self) + self._pgc.grab_focus() + + self.connect('shared', shared_cb) + self.connect('joined', joined_cb) + + if self.get_shared(): + + # if set at this point, it means we've already joined (i.e., + # launched from Neighborhood) + + joined_cb() + + return toolbar + + PYGAME_CANVAS_CLASS = PyGameCanvas + + def build_canvas(self): + """Construct the PyGame or PyGameCairo canvas for drawing""" + + assert self.game_handler or self.game_name, \ + 'You must specify a game_handler or game_name on your Activity (%r)' \ + % (self.game_handler or self.game_name) + if self.pygame_mode != 'Cairo': + self._pgc = self.PYGAME_CANVAS_CLASS(*self.game_size) + self.set_canvas(self._pgc) + self._pgc.grab_focus() + self._pgc.connect_game(self.game_handler or self.game_name) + gtk.gdk.threads_init() + return self._pgc + else: + import hippo + self._drawarea = gtk.DrawingArea() + canvas = hippo.Canvas() + canvas.grab_focus() + self.set_canvas(canvas) + self.show_all() + + import pygamecairo + pygamecairo.install() + + pygamecairo.display.init(canvas) + app = self.game_handler or self.game_name + if ':' not in app: + app += ':main' + (mod_name, fn_name) = app.split(':') + mod = __import__(mod_name, globals(), locals(), []) + fn = getattr(mod, fn_name) + fn() + |