From 324fb287d7b540bbb09a58350e2614507ed5c530 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 11 Dec 2013 20:16:42 +0000 Subject: massive commit to reconstruct world before commits were lost --- (limited to 'activity.py') diff --git a/activity.py b/activity.py index f63e686..4bf6a49 100644 --- a/activity.py +++ b/activity.py @@ -1,57 +1,95 @@ -""" - Physics, a 2D Physics Playground for Kids - Copyright (C) 2008 Alex Levenson and Brian Jordan +# Physics, a 2D Physics Playground for Kids - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. +# Copyright (C) 2008 Alex Levenson and Brian Jordan +# Copyright (C) 2012 Daniel Francis +# Copyright (C) 2012-13 Walter Bender +# Copyright (C) 2013 Sai Vineet +# Copyright (C) 2012-13 Sugar Labs - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. - You should have received a copy of the GNU General Public License - along with this program. If not, see . +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. -""" -import tools -import olpcgames -import pygame -from sugar.graphics.radiotoolbutton import RadioToolButton -from sugar.graphics.toolbutton import ToolButton -from sugar.activity import activity -from gettext import gettext as _ +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os import gtk +import csv +import tempfile +import json +from StringIO import StringIO +from gettext import gettext as _ +import logging +import pygame +import sugargame +import sugargame.canvas -try: - # >= 0.86 toolbars - from sugar.graphics.toolbarbox import ToolbarBox - from sugar.activity.widgets import ActivityToolbarButton - from sugar.activity.widgets import StopButton -except ImportError: - # <= 0.84 toolbars - pass +from sugar.activity import activity +from sugar.activity.widgets import ActivityToolbarButton +from sugar.activity.widgets import StopButton +from sugar.graphics.radiotoolbutton import RadioToolButton +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.alert import ConfirmationAlert +from sugar.graphics.toolbarbox import ToolbarBox +from sugar.graphics.toolbarbox import ToolbarButton +from sugar.graphics.style import GRID_CELL_SIZE +import tools +import physics -class PhysicsActivity(olpcgames.PyGameActivity): - game_name = 'physics' - game_title = _('Physics') - game_size = None # Olpcgame will choose size +class PhysicsActivity(activity.Activity): def __init__(self, handle): super(PhysicsActivity, self).__init__(handle) self.metadata['mime_type'] = 'application/x-physics-activity' self.add_events(gtk.gdk.ALL_EVENTS_MASK | gtk.gdk.VISIBILITY_NOTIFY_MASK) + self.connect('visibility-notify-event', self._focus_event) self.connect('window-state-event', self._window_event) + self._canvas = sugargame.canvas.PygameCanvas(self) + self.game = physics.main(self) + self.preview = None + self.build_toolbar() + + self.set_canvas(self._canvas) + gtk.gdk.screen_get_default().connect('size-changed', + self.__configure_cb) + + logging.debug(os.path.join( + activity.get_activity_root(), 'data', 'data')) + self._canvas.run_pygame(self.game.run) + + def __configure_cb(self, event): + ''' Screen size has changed ''' + self.write_file(os.path.join( + activity.get_activity_root(), 'data', 'data')) + pygame.display.set_mode((gtk.gdk.screen_width(), + gtk.gdk.screen_height() - 2 * GRID_CELL_SIZE), + pygame.RESIZABLE) + self.read_file(os.path.join( + activity.get_activity_root(), 'data', 'data')) + self.game.run(True) + + def read_file(self, file_path): + self.game.read_file(file_path) + + def write_file(self, file_path): + self.game.write_file(file_path) + def get_preview(self): - """Custom preview code to get image from pygame. - """ + """ Custom preview code to get image from pygame. """ + if self.preview: + return self.preview surface = pygame.display.get_surface() width, height = surface.get_width(), surface.get_height() pixbuf = gtk.gdk.pixbuf_new_from_data(pygame.image.tostring(surface, @@ -62,6 +100,7 @@ class PhysicsActivity(olpcgames.PyGameActivity): pixbuf = pixbuf.scale_simple(300, 225, gtk.gdk.INTERP_BILINEAR) preview_data = [] + def save_func(buf, data): data.append(buf) @@ -70,67 +109,89 @@ class PhysicsActivity(olpcgames.PyGameActivity): return preview_data - # Setup the toolbar def build_toolbar(self): - try: - # Use new >= 0.86 toolbar - self.max_participants = 1 - toolbar_box = ToolbarBox() - activity_button = ActivityToolbarButton(self) - toolbar_box.toolbar.insert(activity_button, 0) - activity_button.show() - - separator = gtk.SeparatorToolItem() - toolbar_box.toolbar.insert(separator, -1) - separator.show() - - self._insert_create_tools(toolbar_box.toolbar) - - separator = gtk.SeparatorToolItem() - separator.props.draw = False - separator.set_size_request(0, -1) - separator.set_expand(True) - toolbar_box.toolbar.insert(separator, -1) - separator.show() - - stop_button = StopButton(self) - toolbar_box.toolbar.insert(stop_button, -1) - stop_button.show() - - self.set_toolbar_box(toolbar_box) - toolbar_box.show() - return toolbar_box - - except NameError: - # Use old <= 0.84 toolbar design - toolbox = activity.ActivityToolbox(self) - activity_toolbar = toolbox.get_activity_toolbar() - activity_toolbar.share.props.visible = False - - create_toolbar = gtk.Toolbar() - self._insert_create_tools(create_toolbar) - - toolbox.add_toolbar(_("Create"), create_toolbar) - create_toolbar.show() - toolbox.set_current_toolbar(1) - - toolbox.show() - self.set_toolbox(toolbox) - return activity_toolbar + self.max_participants = 1 + toolbar_box = ToolbarBox() + activity_button = ActivityToolbarButton(self) + toolbar_box.toolbar.insert(activity_button, 0) + activity_button.show() - def _insert_create_tools(self, create_toolbar): - # Stop/play button + create_toolbar = ToolbarButton() + create_toolbar.props.page = gtk.Toolbar() + create_toolbar.props.icon_name = 'magicpen' + create_toolbar.props.label = _('Create') + toolbar_box.toolbar.insert(create_toolbar, -1) + self._insert_create_tools(create_toolbar) + + self._insert_stop_play_button(toolbar_box.toolbar) + + separator = gtk.SeparatorToolItem() + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + self._insert_clear_all_button(toolbar_box.toolbar) + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_size_request(0, -1) + separator.set_expand(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + stop = StopButton(self) + toolbar_box.toolbar.insert(stop, -1) + stop.show() + + separator = gtk.SeparatorToolItem() + activity_button.props.page.insert(separator, -1) + separator.show() + + export_json = ToolButton("save-as-json") + export_json.set_tooltip(_("Export tracked objects to journal")) + export_json.connect('clicked', self._export_json_cb) + activity_button.props.page.insert(export_json, -1) + export_json.show() + + export_csv = ToolButton("save-as-csv") + export_csv.set_tooltip(_("Export tracked objects to journal")) + export_csv.connect('clicked', self._export_csv_cb) + activity_button.props.page.insert(export_csv, -1) + export_csv.show() + + self.set_toolbar_box(toolbar_box) + toolbar_box.show_all() + create_toolbar.set_expanded(True) + return toolbar_box + + def can_close(self): + self.preview = self.get_preview() + self.game.loop = False + return True + + def _insert_stop_play_button(self, toolbar): self.stop_play_state = True self.stop_play = ToolButton('media-playback-stop') self.stop_play.set_tooltip(_("Stop")) self.stop_play.set_accelerator(_('space')) self.stop_play.connect('clicked', self.stop_play_cb) - create_toolbar.insert(self.stop_play, -1) + toolbar.insert(self.stop_play, -1) self.stop_play.show() - separator = gtk.SeparatorToolItem() - create_toolbar.insert(separator, -1) - separator.show() + def _insert_clear_all_button(self, toolbar): + self.clear_all = ToolButton('clear_all') + self.clear_all.set_tooltip(_("Erase All")) + self.clear_all.set_accelerator(_('a')) + self.clear_all.connect('clicked', self.clear_all_cb) + toolbar.insert(self.clear_all, -1) + self.clear_all.show() + + def _insert_create_tools(self, create_toolbar): + + def _insert_item(toolbar, item, pos=-1): + if hasattr(toolbar, 'insert'): + toolbar.insert(item, pos) + else: + toolbar.props.page.insert(item, pos) # Make + add the component buttons self.radioList = {} @@ -142,18 +203,25 @@ class PhysicsActivity(olpcgames.PyGameActivity): else: button.set_group(None) firstButton = button + + if c.name == tools.EraseAllTool.name: + # Add a separator - Erase all tool is a dangerous tool + separator = gtk.SeparatorToolItem() + _insert_item(create_toolbar, separator, -1) + separator.show() + button.set_tooltip(c.toolTip) - button.set_accelerator(c.toolAccelerator) + # button.set_accelerator(c.toolAccelerator) button.connect('clicked', self.radioClicked) - create_toolbar.insert(button, -1) + _insert_item(create_toolbar, button, -1) button.show() self.radioList[button] = c.name def stop_play_cb(self, button): - pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, - action="stop_start_toggle")) + pygame.event.post(pygame.event.Event(pygame.USEREVENT, + action="stop_start_toggle")) self.stop_play_state = not self.stop_play_state - # Update button + if self.stop_play_state: self.stop_play.set_icon('media-playback-stop') self.stop_play.set_tooltip(_("Stop")) @@ -161,23 +229,76 @@ class PhysicsActivity(olpcgames.PyGameActivity): self.stop_play.set_icon('media-playback-start') self.stop_play.set_tooltip(_("Start")) + def clear_all_cb(self, button): + def clear_all_alert_cb(alert, response_id): + self.remove_alert(alert) + if response_id is gtk.RESPONSE_OK: + pygame.event.post(pygame.event.Event(pygame.USEREVENT, + action="clear_all")) + + clear_all_alert = ConfirmationAlert() + clear_all_alert.props.title = _('Are You Sure?') + clear_all_alert.props.msg = \ + _('All you work will be discarded. This cannot be undone!') + clear_all_alert.connect('response', clear_all_alert_cb) + self.add_alert(clear_all_alert) + def radioClicked(self, button): - pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, - action=self.radioList[button])) + pygame.event.post(pygame.event.Event(pygame.USEREVENT, + action=self.radioList[button])) def _focus_event(self, event, data=None): - """Send focus events to pygame to allow it to idle when in background. - """ + """ Send focus events to pygame to allow it to idle when in + background. """ + if not self.game.pygame_started: + logging.debug('focus_event: pygame not yet initialized') + return if data.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED: - pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, - action="focus_out")) + pygame.event.post(pygame.event.Event(pygame.USEREVENT, + action="focus_out")) else: - pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, - action="focus_in")) + self.game.show_fake_cursor = True + pygame.event.post(pygame.event.Event(pygame.USEREVENT, + action="focus_in")) + + def _export_json_cb(self, button): + jobject = datastore.create() + jobject.metadata['title'] = _("Physics export") + jobject.metadata['mime_type'] = "text/plain" + + tmp_dir = os.path.join(self.get_activity_root(), 'instance') + fd, file_path = tempfile.mkstemp(dir=tmp_dir) + os.close(fd) + + data = self.game.full_pos_list + jsonfile = open(file_path, "wb") + jsonfile.write(json.dumps(data)) + jsonfile.close() + + jobject.set_file_path(os.path.abspath(csvfile.name)) + datastore.write(jobject) + + def _export_csv_cb(self, button): + jobject = datastore.create() + jobject.metadata['title'] = _("Physics export") + jobject.metadata['mime_type'] = "text/csv" + + tmp_dir = os.path.join(self.get_activity_root(), 'instance') + fd, file_path = tempfile.mkstemp(dir=tmp_dir) + os.close(fd) + + data = self.game.full_pos_list + csvfile = open(file_path, "wb") + writer = csv.writer(csvfile) + writer.writerows(data) + csvfile.close() + + jobject.set_file_path(os.path.abspath(csvfile.name)) + datastore.write(jobject) def _window_event(self, window, event): - """Send focus out event to pygame when switching to a desktop view. - """ + """ Send focus out event to pygame when switching to a desktop + view. """ if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: - pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, - action="focus_out")) + pygame.event.post(pygame.event.Event(pygame.USEREVENT, + action="focus_out")) -- cgit v0.9.1