Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/olpcgames/canvas.py
diff options
context:
space:
mode:
authorManuel Kaufmann <humitos@gmail.com>2012-03-27 13:15:10 (GMT)
committer Rafael Ortiz <rafael@activitycentral.com>2012-03-28 18:05:22 (GMT)
commit335ad73456ba3ec8f56811abddcaca4650199db1 (patch)
treedb788baba57c7656c9bdb73eb9003a70dc87d59a /olpcgames/canvas.py
parent6deeb3f569e6c9a1c02a32a011b7a96a58fa8443 (diff)
Save and restore state of the game
Ability to 'save' (when the user closes the Activity) and 'restore' (when the user launch it from the Journal or the Home without holding Alt) the state of the game. For this ability I had to upgrade 'olpcgames' to 1.6 because 'olpcgames.FILE_READ_REQUEST' and 'olpcgames.FILE_WRITE_REQUEST' events are added in that version and those events are needed for this. The data is saved (as JSON, with json module) in the 'event.metadata["state"]' and the timestamp state is saved in 'event.filename'. This commit solves ticket #2393: * http://bugs.sugarlabs.org/ticket/2393 Signed-off-by: Manuel Kaufmann <humitos@gmail.com> Signed-off-by: Rafael Ortiz <rafael@activitycentral.com>
Diffstat (limited to 'olpcgames/canvas.py')
-rw-r--r--olpcgames/canvas.py99
1 files changed, 73 insertions, 26 deletions
diff --git a/olpcgames/canvas.py b/olpcgames/canvas.py
index 2eee2c9..2583827 100644
--- a/olpcgames/canvas.py
+++ b/olpcgames/canvas.py
@@ -1,9 +1,9 @@
-"""Implements bridge connection between Sugar/GTK and PyGame"""
+"""Implements bridge connection between Sugar/GTK and Pygame"""
import os
import sys
import logging
log = logging.getLogger( 'olpcgames.canvas' )
-#log.setLevel( logging.DEBUG )
+##log.setLevel( logging.DEBUG )
import threading
from pprint import pprint
@@ -15,29 +15,31 @@ import pygame
from olpcgames import gtkEvent, util
-__all__ = ['PyGameCanvas']
+__all__ = ['PygameCanvas']
-class PyGameCanvas(gtk.Layout):
- """Canvas providing bridge methods to run PyGame in GTK
+class PygameCanvas(gtk.Layout):
+ """Canvas providing bridge methods to run Pygame in GTK
- The PyGameCanvas creates a secondary thread in which the Pygame instance will
- live, providing synthetic PyGame events to that thread via a Queue. The GUI
- connection is done by having the PyGame canvas use a GTK Port object as it's
+ The PygameCanvas creates a secondary thread in which the Pygame instance will
+ live, providing synthetic Pygame events to that thread via a Queue. The GUI
+ connection is done by having the Pygame canvas use a GTK Port object as it's
window pointer, it draws to that X-level window in order to produce output.
"""
+ mod_name = None
def __init__(self, width, height):
"""Initializes the Canvas Object
width,height -- passed to the inner EventBox in order to request a given size,
- the Socket is the only child of this EventBox, and the PyGame commands
+ the Socket is the only child of this EventBox, and the Pygame commands
will be writing to the Window ID of the socket. The internal EventBox is
- centered via an Alignment instance within the PyGameCanvas instance.
+ centered via an Alignment instance within the PygameCanvas instance.
XXX Should refactor so that the internal setup can be controlled by the
sub-class, e.g. to get size from the host window, or something similar.
"""
# Build the main widget
- super(PyGameCanvas,self).__init__()
+ log.info( 'Creating the pygame canvas' )
+ super(PygameCanvas,self).__init__()
self.set_flags(gtk.CAN_FOCUS)
# Build the sub-widgets
@@ -57,7 +59,7 @@ class PyGameCanvas(gtk.Layout):
self._align.show()
- self.put(self._align, 0, 0)
+ self.put(self._align, 0,0)
# Construct a gtkEvent.Translator
self._translator = gtkEvent.Translator(self, self._inner_evb)
@@ -73,10 +75,11 @@ class PyGameCanvas(gtk.Layout):
Side effects:
Sets the SDL_WINDOWID variable to our socket's window ID
- Calls PyGame init
- Causes the gtkEvent.Translator to "hook" PyGame
- Creates and starts secondary thread for Game/PyGame event processing.
+ Calls Pygame init
+ Causes the gtkEvent.Translator to "hook" Pygame
+ Creates and starts secondary thread for Game/Pygame event processing.
"""
+ log.info( 'Connecting the pygame canvas' )
# Setup the embedding
os.environ['SDL_WINDOWID'] = str(self._socket.get_id())
#print 'Socket ID=%s'%os.environ['SDL_WINDOWID']
@@ -87,21 +90,23 @@ class PyGameCanvas(gtk.Layout):
# Load the modules
# NOTE: This is delayed because pygame.init() must come after the embedding is up
if ':' not in app:
- app += ':main'
+ app += ':main'
mod_name, fn_name = app.split(':')
+ self.mod_name = mod_name
mod = __import__(mod_name, globals(), locals(), [])
fn = getattr(mod, fn_name)
+
# Start Pygame
self.__thread = threading.Thread(target=self._start, args=[fn])
self.__thread.start()
def _start(self, fn):
"""The method that actually runs in the background thread"""
+ log.info( 'Staring the mainloop' )
import olpcgames
olpcgames.widget = olpcgames.WIDGET = self
try:
- import sugar.activity.activity
- import os
+ import sugar.activity.activity,os
except ImportError, err:
log.info( """Running outside Sugar""" )
else:
@@ -112,13 +117,55 @@ class PyGameCanvas(gtk.Layout):
try:
try:
- log.info( '''Running mainloop: %s''', fn )
- fn()
- except Exception, err:
- log.error(
- """Uncaught top-level exception: %s""",
- util.get_traceback( err ),
- )
- raise
+ try:
+ log.info( '''Running mainloop: %s''', fn )
+ fn()
+ except Exception, err:
+ log.error(
+ """Uncaught top-level exception: %s""",
+ util.get_traceback( err ),
+ )
+ raise
+ else:
+ log.info( "Mainloop exited" )
+ finally:
+ log.debug( "Clearing any pending events" )
+ from olpcgames import eventwrap
+ eventwrap.clear()
finally:
+ log.info( 'Main function finished, calling main_quit' )
gtk.main_quit()
+
+ source_object_id = None
+ def view_source(self):
+ """Implement the 'view source' key by saving
+ datastore, and then telling the Journal to view it."""
+ if self.source_object_id is None:
+ from sugar import profile
+ from sugar.datastore import datastore
+ from sugar.activity.activity import get_bundle_name, get_bundle_path
+ from gettext import gettext as _
+ import os.path
+ jobject = datastore.create()
+ metadata = {
+ 'title': _('%s Source') % get_bundle_name(),
+ 'title_set_by_user': '1',
+ 'suggested_filename': 'pippy_app.py',
+ 'icon-color': profile.get_color().to_string(),
+ 'mime_type': 'text/x-python',
+ }
+ for k,v in metadata.items():
+ jobject.metadata[k] = v # dict.update method is missing =(
+ jobject.file_path = os.path.join(get_bundle_path(), 'pippy_app.py')
+ datastore.write(jobject)
+ self.__source_object_id = jobject.object_id
+ jobject.destroy()
+ self.journal_show_object(self.__source_object_id)
+ def journal_show_object(self, object_id):
+ """Invoke journal_show_object from sugar.activity.activity if it
+ exists."""
+ try:
+ from sugar.activity.activity import show_object_in_journal
+ show_object_in_journal(object_id)
+ except ImportError:
+ pass # no love from sugar.