diff options
author | Walter Bender <walter@sugarlabs.org> | 2010-04-26 17:22:12 (GMT) |
---|---|---|
committer | Walter Bender <walter@sugarlabs.org> | 2010-04-26 17:22:12 (GMT) |
commit | e9fddf1e00857ad985238410f631a3975de04995 (patch) | |
tree | cb5dcd5c43ecb7952a9985f6e1ca8e42ee2673fc /TurtleArtMiniActivity.py | |
parent | 6606449090a9e66269d636451cb4712c78a19d73 (diff) |
mini version to parallel Java version
Diffstat (limited to 'TurtleArtMiniActivity.py')
-rw-r--r-- | TurtleArtMiniActivity.py | 1552 |
1 files changed, 1552 insertions, 0 deletions
diff --git a/TurtleArtMiniActivity.py b/TurtleArtMiniActivity.py new file mode 100644 index 0000000..9bea6c7 --- /dev/null +++ b/TurtleArtMiniActivity.py @@ -0,0 +1,1552 @@ +#Copyright (c) 2007, Playful Invention Company +#Copyright (c) 2008-10, Walter Bender +#Copyright (c) 2009,10 Raul Gutierrez Segales + +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is +#furnished to do so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in +#all copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import logging +_logger = logging.getLogger('turtleart-activity') + +from sugar.activity import activity +try: # 0.86 toolbar widgets + from sugar.activity.widgets import ActivityToolbarButton + from sugar.activity.widgets import StopButton + from sugar.graphics.toolbarbox import ToolbarBox + from sugar.graphics.toolbarbox import ToolbarButton + NEW_SUGAR_SYSTEM = True +except ImportError: + NEW_SUGAR_SYSTEM = False +from sugar.graphics.toolbutton import ToolButton +from sugar.datastore import datastore + +import telepathy +from dbus.service import signal +from dbus.gobject_service import ExportedGObject +from sugar.presence import presenceservice +from sugar.presence.tubeconn import TubeConnection + +from sugar import profile +from gettext import gettext as _ +import os.path +import tarfile + +from taconstants import PALETTE_NAMES, OVERLAY_LAYER +from taexporthtml import save_html +from taexportlogo import save_logo +from tautils import data_to_file, data_to_string, data_from_string, get_path +from tawindow import TurtleArtWindow +from taturtle import Turtle + +SERVICE = 'org.laptop.TurtleArtMiniActivity' +IFACE = SERVICE +PATH = '/org/laptop/TurtleArtMiniActivity' + +class TurtleArtMiniActivity(activity.Activity): + + def __init__(self, handle): + """ Activity subclass for Turtle Art """ + super(TurtleArtMiniActivity, self).__init__(handle) + + datapath = get_path(activity, 'data') + + self._setup_visibility_handler() + + self.new_sugar_system = NEW_SUGAR_SYSTEM + self._setup_toolbar() + + canvas = self._setup_scrolled_window() + + self._check_ver_change(datapath) + + self._setup_canvas(canvas) + + self._load_python_code() + + self._setup_sharing() + + + # Activity toolbar callbacks + + def do_save_as_html_cb(self, button): + """ Write html out to datastore. """ + self.save_as_html.set_icon("htmlon") + _logger.debug("saving html code") + # until we have URLs for datastore objects, always embed images + embed_flag = True + + # grab code from stacks + html = save_html(self, self.tw, embed_flag) + if len(html) == 0: + return + + # save the html code to the instance directory + datapath = get_path(activity, 'instance') + + save_type = '.html' + if len(self.tw.saved_pictures) > 0: + if self.tw.saved_pictures[0].endswith(('.svg')): + save_type = '.xml' + + html_file = os.path.join(datapath, "portfolio" + save_type) + f = file(html_file, "w") + f.write(html) + f.close() + + if embed_flag == False: + # need to make a tarball that includes the images + tar_path = os.path.join(datapath, 'portfolio.tar') + tar_fd = tarfile.open(tar_path, 'w') + try: + tar_fd.add(html_file, "portfolio.html") + import glob + image_list = glob.glob(os.path.join(datapath, 'image*')) + for i in image_list: + tar_fd.add(i, os.path.basename(i)) + finally: + tar_fd.close() + + # Create a datastore object + dsobject = datastore.create() + + # Write any metadata (here we specifically set the title of the file + # and specify that this is a plain text file). + dsobject.metadata['title'] = self.metadata['title'] + " " + \ + _("presentation") + dsobject.metadata['icon-color'] = profile.get_color().to_string() + if embed_flag == True: + if save_type == '.xml': + dsobject.metadata['mime_type'] = 'application/xml' + else: + dsobject.metadata['mime_type'] = 'text/html' + dsobject.set_file_path(html_file) + else: + dsobject.metadata['mime_type'] = 'application/x-tar' + dsobject.set_file_path(tar_path) + + dsobject.metadata['activity'] = 'org.laptop.WebActivity' + datastore.write(dsobject) + dsobject.destroy() + gobject.timeout_add(250, self.save_as_html.set_icon, "htmloff") + + self.tw.saved_pictures = [] + return + + def do_save_as_logo_cb(self, button): + """ Write logo code out to datastore. """ + self.save_as_logo.set_icon("logo-saveon") + # grab code from stacks + logocode = save_logo(self.tw) + if len(logocode) == 0: + return + filename = "logosession.lg" + + # Create a datastore object + dsobject = datastore.create() + + # Write any metadata (here we specifically set the title of the file + # and specify that this is a plain text file). + dsobject.metadata['title'] = self.metadata['title'] + ".lg" + dsobject.metadata['mime_type'] = 'text/plain' + dsobject.metadata['icon-color'] = profile.get_color().to_string() + + # save the Logo code to the instance directory + datapath = get_path(activity, 'instance') + + # Write the file to the data directory of this activity's root. + file_path = os.path.join(datapath, filename) + f = open(file_path, 'w') + try: + f.write(logocode) + finally: + f.close() + + # Set the file_path in the datastore. + dsobject.set_file_path(file_path) + + datastore.write(dsobject) + gobject.timeout_add(250, self.save_as_logo.set_icon, "logo-saveoff") + return + + def do_load_ta_project_cb(self, button): + """ Load a project from the Journal """ + from sugar.graphics.objectchooser import ObjectChooser + chooser = ObjectChooser(_("Project"), None, gtk.DIALOG_MODAL | \ + gtk.DIALOG_DESTROY_WITH_PARENT) + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + dsobject = chooser.get_selected_object() + try: + _logger.debug("opening %s " % dsobject.file_path) + self.read_file(dsobject.file_path, False) + except: + _logger.debug("couldn't open %s" % dsobject.file_path) + dsobject.destroy() + finally: + chooser.destroy() + del chooser + return + + def do_load_python_cb(self, button): + """ Load Python code from the Journal. """ + self.load_python.set_icon("pippy-openon") + self.import_py() + gobject.timeout_add(250, self.load_python.set_icon, "pippy-openoff") + return + + def import_py(self): + """ Import Python code from the Journal to load into 'myblock'. """ + from sugar.graphics.objectchooser import ObjectChooser + chooser = ObjectChooser('Python code', None, gtk.DIALOG_MODAL | \ + gtk.DIALOG_DESTROY_WITH_PARENT) + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + dsobject = chooser.get_selected_object() + self._load_python(dsobject) + finally: + chooser.destroy() + del chooser + + def _load_python(self, dsobject): + """ Read the Python code from the Journal object """ + try: + _logger.debug("opening %s " % dsobject.file_path) + file_handle = open(dsobject.file_path, "r") + self.tw.myblock = file_handle.read() + file_handle.close() + self.tw.set_userdefined() + # save reference to Pythin code in the project metadata + self.metadata['python code'] = dsobject.object_id + except: + _logger.debug("couldn't open %s" % dsobject.file_path) + dsobject.destroy() + + def do_save_as_image_cb(self, button): + """ Save the canvas to the Journal. """ + self.save_as_image.set_icon("image-saveon") + _logger.debug("saving image to journal") + + self.tw.save_as_image() + gobject.timeout_add(250, self.save_as_image.set_icon, "image-saveoff") + return + + def do_keep_cb(self, button): + """ Save a snapshot of the project to the Journal. """ + datapath = get_path(activity, 'instance') + tafile = os.path.join(datapath,"tmpfile.ta") + try: + data_to_file(self.tw.assemble_data_to_save(), tafile) + except: + _logger.debug("couldn't save snapshot to journal") + + # Create a datastore object + dsobject = datastore.create() + + # Write any metadata + dsobject.metadata['title'] = self.metadata['title'] + " " + \ + _("snapshot") + dsobject.metadata['icon-color'] = profile.get_color().to_string() + dsobject.metadata['mime_type'] = 'application/x-turtle-art' + dsobject.metadata['activity'] = 'org.laptop.TurtleArtActivity' + dsobject.set_file_path(tafile) + datastore.write(dsobject) + + # Clean up + dsobject.destroy() + os.remove(tafile) + return + + # Main toolbar button callbacks + + def do_palette_cb(self, button): + """ Show/hide palette """ + if self.tw.palette == True: + self.tw.hideshow_palette(False) + self.palette_button.set_icon("paletteon") + self.palette_button.set_tooltip(_('Show palette')) + if self.new_sugar_system and self.tw.selected_palette is not None: + self.palette_buttons[self.tw.selected_palette].set_icon( + PALETTE_NAMES[self.tw.selected_palette]+'off') + else: + self.tw.hideshow_palette(True) + self.palette_button.set_icon("paletteoff") + self.palette_button.set_tooltip(_('Hide palette')) + if self.new_sugar_system: + self.palette_buttons[0].set_icon(PALETTE_NAMES[0]+'on') + + def do_palette_buttons_cb(self, button, i): + """ Palette selector buttons """ + if self.tw.selected_palette is not None: + if self.tw.selected_palette != i: + self.palette_buttons[self.tw.selected_palette].set_icon( + PALETTE_NAMES[self.tw.selected_palette]+'off') + self.palette_buttons[i].set_icon(PALETTE_NAMES[i]+'on') + self.tw.show_palette(i) + self.palette_button.set_icon("paletteoff") + self.palette_button.set_tooltip(_('Hide palette')) + + # These methods are called both from buttons and palette. + + def do_hidepalette(self): + """ Hide the palette. """ + self.palette_button.set_icon("paletteon") + self.palette_button.set_tooltip(_('Show palette')) + + def do_showpalette(self): + """ Show the palette. """ + self.palette_button.set_icon("paletteoff") + self.palette_button.set_tooltip(_('Hide palette')) + + def do_hideshow_cb(self, button): + """ Toggle visibility. """ + self.tw.hideshow_button() + if self.tw.hide == True: # we just hid the blocks + self.blocks_button.set_icon("hideshowon") + self.blocks_button.set_tooltip(_('Show blocks')) + else: + self.blocks_button.set_icon("hideshowoff") + self.blocks_button.set_tooltip(_('Hide blocks')) + # update palette buttons too + if self.tw.palette == False: + self.palette_button.set_icon("paletteon") + self.palette_button.set_tooltip(_('Show palette')) + else: + self.palette_button.set_icon("paletteoff") + self.palette_button.set_tooltip(_('Hide palette')) + + def do_hide(self): + """ Hide blocks. """ + self.blocks_button.set_icon("hideshowon") + self.blocks_button.set_tooltip(_('Show blocks')) + self.palette_button.set_icon("paletteon") + self.palette_button.set_tooltip(_('Show palette')) + + def do_show(self): + """ Show blocks. """ + self.blocks_button.set_icon("hideshowoff") + self.blocks_button.set_tooltip(_('Hide blocks')) + self.palette_button.set_icon("paletteoff") + self.palette_button.set_tooltip(_('Hide palette')) + + def do_eraser_cb(self, button): + """ Clear the screen and recenter. """ + self.eraser_button.set_icon("eraseroff") + self.recenter() + self.tw.eraser_button() + gobject.timeout_add(250, self.eraser_button.set_icon, "eraseron") + + def do_run_cb(self, button): + """ Callback for run button (rabbit). """ + self.run_button.set_icon("run-faston") + self.tw.lc.trace = 0 + self.tw.run_button(0) + gobject.timeout_add(1000, self.run_button.set_icon, "run-fastoff") + + def do_step_cb(self, button): + """ Callback for step button (turtle). """ + self.step_button.set_icon("run-slowon") + self.tw.lc.trace = 0 + self.tw.run_button(3) + gobject.timeout_add(1000, self.step_button.set_icon, "run-slowoff") + + def do_debug_cb(self, button): + """ Callback for debug button (bug). """ + self.debug_button.set_icon("debugon") + self.tw.lc.trace = 1 + self.tw.run_button(6) + gobject.timeout_add(1000, self.debug_button.set_icon, "debugoff") + + def do_stop_cb(self, button): + """ Callback for stop button. """ + self.stop_button.set_icon("stopitoff") + self.tw.stop_button() + self.step_button.set_icon("run-slowoff") + self.run_button.set_icon("run-fastoff") + + def do_samples_cb(self, button): + """ Sample projects open dialog """ + # FIXME: encapsulation! + self.tw.load_file(True) + # run the activity + self.stop_button.set_icon("stopiton") + self.tw.run_button(0) + + def recenter(self): + """ Recenter scrolled window around canvas. """ + hadj = self.sw.get_hadjustment() + hadj.set_value(0) + self.sw.set_hadjustment(hadj) + vadj = self.sw.get_vadjustment() + vadj.set_value(0) + self.sw.set_vadjustment(vadj) + + def do_fullscreen_cb(self, button): + """ Hide the Sugar toolbars. """ + self.fullscreen() + self.recenter() + + def do_resize_blocks_cb(self, button, scale_factor): + """ Scale the blocks. """ + self.tw.block_scale *= scale_factor + self.tw.resize_blocks() + + def do_cartesian_cb(self, button): + """ Display Cartesian coordinate grid. """ + if self.tw.cartesian: + self.tw.set_cartesian(False) + else: + self.tw.set_cartesian(True) + + def do_polar_cb(self, button): + """ Display Polar coordinate grid. """ + if self.tw.polar: + self.tw.set_polar(False) + else: + self.tw.set_polar(True) + + def do_rescale_cb(self, button): + """ Rescale coordinate system (100==height/2 or 100 pixels). """ + if self.tw.coord_scale == 1: + self.tw.coord_scale = self.tw.height/200 + self.rescale_button.set_icon("contract-coordinates") + self.rescale_button.set_tooltip(_('Rescale coordinates down')) + self.tw.eraser_button() + if self.tw.cartesian: + self.tw.overlay_shapes['Cartesian_labeled'].hide() + self.tw.overlay_shapes['Cartesian'].set_layer(OVERLAY_LAYER) + else: + self.tw.coord_scale = 1 + self.rescale_button.set_icon("expand-coordinates") + self.rescale_button.set_tooltip(_('Rescale coordinates up')) + self.tw.eraser_button() + if self.tw.cartesian: + self.tw.overlay_shapes['Cartesian'].hide() + self.tw.overlay_shapes['Cartesian_labeled'].set_layer( + OVERLAY_LAYER) + + def get_document_path(self, async_cb, async_err_cb): + """ View Logo code as part of view source. """ + logo_code_path = self._dump_logo_code() + async_cb(logo_code_path) + + def _dump_logo_code(self): + """ Save Logo code to Journal. """ + datapath = get_path(activity, 'instance') + tafile = os.path.join(datapath,"tmpfile.ta") + try: + code = save_logo(self.tw) + f = file(tafile, "w") + f.write(code) + f.close() + except Exception, e: + _logger.error("Couldn't dump code to view source: " + str(e)) + return tafile + + # Sharing-related callbacks + + def _shared_cb(self, activity): + """ Either set up initial share... """ + if self._shared_activity is None: + _logger.error("Failed to share or join activity ... \ + _shared_activity is null in _shared_cb()") + return + + self.initiating = True + self.waiting_for_turtles = False + self.turtle_dictionary = \ + {profile.get_nick_name():profile.get_color().to_string()} + _logger.debug('I am sharing...') + + self.conn = self._shared_activity.telepathy_conn + self.tubes_chan = self._shared_activity.telepathy_tubes_chan + self.text_chan = self._shared_activity.telepathy_text_chan + + # call back for "NewTube" signal + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal \ + ('NewTube', self._new_tube_cb) + + _logger.debug('This is my activity: making a tube...') + id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( + SERVICE, {}) + + def _joined_cb(self, activity): + """ ...or join an exisiting share. """ + if self._shared_activity is None: + _logger.error("Failed to share or join activity ... \ + _shared_activity is null in _shared_cb()") + return + + self.initiating = False + self.conn = self._shared_activity.telepathy_conn + self.tubes_chan = self._shared_activity.telepathy_tubes_chan + self.text_chan = self._shared_activity.telepathy_text_chan + + # call back for "NewTube" signal + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( \ + 'NewTube', self._new_tube_cb) + + _logger.debug('I am joining an activity: waiting for a tube...') + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( + reply_handler=self._list_tubes_reply_cb, + error_handler=self._list_tubes_error_cb) + + # Joiner should request current state from sharer. + self.waiting_for_turtles = True + + def _list_tubes_reply_cb(self, tubes): + for tube_info in tubes: + self._new_tube_cb(*tube_info) + + def _list_tubes_error_cb(self, e): + _logger.error('ListTubes() failed: %s', e) + + def _new_tube_cb(self, id, initiator, type, service, params, state): + """ Create a new tube. """ + _logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' + 'params=%r state=%d', id, initiator, type, service, + params, state) + + if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): + if state == telepathy.TUBE_STATE_LOCAL_PENDING: + self.tubes_chan[ \ + telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) + + tube_conn = TubeConnection(self.conn, + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, \ + group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) + + # We'll use a chat tube to send serialized stacks back and forth. + self.chattube = ChatTube(tube_conn, self.initiating, \ + self.event_received_cb) + + # Now that we have the tube, we can ask for the turtle dictionary. + if self.waiting_for_turtles: + _logger.debug("Sending a request for the turtle dictionary") + # we need to send our own nick and colors + colors = profile.get_color().to_string() + _logger.debug("t|"+data_to_string([self.tw.nick,colors])) + self.send_event("t|%s" % \ + (data_to_string([self.tw.nick,colors]))) + + def event_received_cb(self, text): + """ Handle the receiving of events in share """ + _logger.debug(text) + + """ + Events are sent as a tuple, nick|cmd, where nick is a turle name + and cmd is a turtle event. Everyone gets the turtle dictionary from + the sharer and watches for 't' events, which indicate that a new + turtle has joined. + + """ + # Save active Turtle + save_active_turtle = self.tw.active_turtle + if text[0] == 't': # request for turtle dictionary + e = text.split("|", 2) + text = e[1] + if text > 0: + [nick, colors] = data_from_string(text) + if nick != self.tw.nick: + # There may not be a turtle dictionary. + if hasattr(self, "turtle_dictionary"): + self.turtle_dictionary[nick] = colors + else: + self.turtle_dictionary = {nick:colors} + # Add new turtle for the joiner. + self.tw.canvas.set_turtle(nick, colors) + # Sharer should send turtle dictionary. + if self.initiating: + text = data_to_string(self.turtle_dictionary) + self.send_event("T|" + text) + elif text[0] == 'T': # Receiving the turtle dictionary. + if self.waiting_for_turtles: + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + self.turtle_dictionary = data_from_string(text) + for nick in self.turtle_dictionary: + if nick != self.tw.nick: + colors = self.turtle_dictionary[nick] + # add new turtle for the joiner + self.tw.canvas.set_turtle(nick, colors) + self.waiting_for_turtles = False + elif text[0] == 'f': # move a turtle forward + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, x] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.forward(x, False) + elif text[0] == 'a': # move a turtle in an arc + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, [a, r]] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.arc(a, r, False) + elif text[0] == 'r': # rotate turtle + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, h] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.seth(h, False) + elif text[0] == 'x': # set turtle xy position + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, [x, y]] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.setxy(x, y, False) + elif text[0] == 'c': # set turtle pen color + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, x] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.setcolor(x, False) + elif text[0] == 's': # set turtle pen shade + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, x] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.setshade(x, False) + elif text[0] == 'w': # set turtle pen width + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, x] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.setpensize(x, False) + elif text[0] == 'p': # set turtle pen state + e = text.split("|", 2) + text = e[1] + if len(text) > 0: + [nick, x] = data_from_string(text) + if nick != self.tw.nick: + self.tw.canvas.set_turtle(nick) + self.tw.canvas.setpen(x, False) + # Restore active Turtle + self.tw.canvas.set_turtle(self.tw.turtles.get_turtle_key( + save_active_turtle)) + + def send_event(self, entry): + """ Send event through the tube. """ + if hasattr(self, 'chattube') and self.chattube is not None: + self.chattube.SendText(entry) + + def __visibility_notify_cb(self, window, event): + """ Callback method for when the activity's visibility changes. """ + if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED: + self.tw.lc.ag = None + elif event.state in \ + [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]: + pass + + def update_title_cb(self, widget, event, toolbox): + """ Update the title. """ + toolbox._activity_toolbar._update_title_cb() + toolbox._activity_toolbar._update_title_sid = True + + def _keep_clicked_cb(self, button): + """ Keep button clicked. """ + self.jobject_new_patch() + + def _setup_toolbar(self): + """ Setup toolbar according to Sugar version """ + if self.new_sugar_system: + # Use 0.86 toolbar design + toolbar_box = ToolbarBox() + # Buttons added to the Activity toolbar + activity_button = ActivityToolbarButton(self) + + """ + + # Save snapshot is like Keep, but it creates a new activity id + self.keep_button = ToolButton('filesave') + self.keep_button.set_tooltip(_("Save snapshot")) + self.keep_button.connect('clicked', self.do_keep_cb) + self.keep_button.show() + activity_button.props.page.insert(self.keep_button, -1) + + # Save as HTML + self.save_as_html = ToolButton('htmloff') + self.save_as_html.set_tooltip(_("Save as HTML")) + self.save_as_html.connect('clicked', self.do_save_as_html_cb) + self.save_as_html.show() + activity_button.props.page.insert(self.save_as_html, -1) + + # Save as Logo + self.save_as_logo = ToolButton('logo-saveoff') + self.save_as_logo.set_tooltip(_("Save as Logo")) + self.save_as_logo.connect('clicked', self.do_save_as_logo_cb) + self.save_as_logo.show() + activity_button.props.page.insert(self.save_as_logo, -1) + + """ + + # Save as image + self.save_as_image = ToolButton('image-saveoff') + self.save_as_image.set_tooltip(_("Save as image")) + self.save_as_image.connect('clicked', self.do_save_as_image_cb) + self.save_as_image.show() + activity_button.props.page.insert(self.save_as_image, -1) + + """ + + # Load Python code into programmable brick + self.load_python = ToolButton('pippy-openoff') + self.load_python.set_tooltip(_("Load my block")) + self.load_python.connect('clicked', self.do_load_python_cb) + self.load_python.show() + activity_button.props.page.insert(self.load_python, -1) + + """ + + # Open project from the Journal + self.load_ta_project = ToolButton('load-from-journal') + self.load_ta_project.set_tooltip(\ + _("Import project from the Journal")) + self.load_ta_project.connect('clicked', self.do_load_ta_project_cb) + self.load_ta_project.show() + activity_button.props.page.insert(self.load_ta_project, -1) + + toolbar_box.toolbar.insert(activity_button, 0) + activity_button.show() + + # The edit toolbar -- copy and paste + edit_toolbar = EditToolbar(self) + edit_toolbar_button = ToolbarButton( + page=edit_toolbar, + icon_name='toolbar-edit') + edit_toolbar.show() + toolbar_box.toolbar.insert(edit_toolbar_button, -1) + edit_toolbar_button.show() + + # The view toolbar + view_toolbar = gtk.Toolbar() + + fullscreen_button = ToolButton('view-fullscreen') + fullscreen_button.set_tooltip(_("Fullscreen")) + fullscreen_button.props.accelerator = '<Alt>Enter' + fullscreen_button.connect('clicked', self.do_fullscreen_cb) + view_toolbar.insert(fullscreen_button, -1) + fullscreen_button.show() + + cartesian_button = ToolButton('view-Cartesian') + cartesian_button.set_tooltip(_("Cartesian coordinates")) + cartesian_button.connect('clicked', self.do_cartesian_cb) + view_toolbar.insert(cartesian_button, -1) + cartesian_button.show() + + polar_button = ToolButton('view-polar') + polar_button.set_tooltip(_("Polar coordinates")) + polar_button.connect('clicked', self.do_polar_cb) + view_toolbar.insert(polar_button, -1) + polar_button.show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = True + view_toolbar.insert(separator, -1) + separator.show() + + self.coordinates_label = \ + gtk.Label(_("xcor") + " = 0 " + _("ycor") + " = 0 " + \ + _("heading") + " = 0") + self.coordinates_label.set_line_wrap(True) + self.coordinates_label.show() + self.coordinates_toolitem = gtk.ToolItem() + self.coordinates_toolitem.add(self.coordinates_label) + view_toolbar.insert(self.coordinates_toolitem, -1) + self.coordinates_toolitem.show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + view_toolbar.insert(separator, -1) + separator.show() + + self.rescale_button = ToolButton('expand-coordinates') + self.rescale_button.set_tooltip(_("Rescale coordinates up")) + self.rescale_button.connect('clicked', self.do_rescale_cb) + view_toolbar.insert(self.rescale_button, -1) + self.rescale_button.show() + + """ + + self.resize_up_button = ToolButton('resize+') + self.resize_up_button.set_tooltip(_("Grow blocks")) + self.resize_up_button.connect('clicked', + self.do_resize_blocks_cb, 1.5) + view_toolbar.insert(self.resize_up_button, -1) + self.resize_up_button.show() + + self.resize_down_button = ToolButton('resize-') + self.resize_down_button.set_tooltip(_("Shrink blocks")) + self.resize_down_button.connect('clicked', + self.do_resize_blocks_cb, 0.667) + view_toolbar.insert(self.resize_down_button, -1) + self.resize_down_button.show() + + """ + + view_toolbar_button = ToolbarButton( + page=view_toolbar, + icon_name='toolbar-view') + view_toolbar.show() + toolbar_box.toolbar.insert(view_toolbar_button, -1) + view_toolbar_button.show() + + # palette toolbar + palette_toolbar = gtk.Toolbar() + self.palette_buttons = [] + for i, name in enumerate(PALETTE_NAMES): + if i > 0: + self.palette_buttons.append(ToolButton(name+'off')) + else: + self.palette_buttons.append(ToolButton(name+'on')) + self.palette_buttons[i].props.sensitive = True + self.palette_buttons[i].connect('clicked', + self.do_palette_buttons_cb, i) + palette_toolbar.insert(self.palette_buttons[i], -1) + self.palette_buttons[i].show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + palette_toolbar.insert(separator, -1) + separator.show() + + self.palette_button = ToolButton( "paletteoff" ) + self.palette_button.set_tooltip(_('Hide palette')) + self.palette_button.props.sensitive = True + self.palette_button.connect('clicked', self.do_palette_cb) + self.palette_button.props.accelerator = _('<Ctrl>p') + palette_toolbar.insert(self.palette_button, -1) + self.palette_button.show() + + self.blocks_button = ToolButton( "hideshowoff" ) + self.blocks_button.set_tooltip(_('Hide blocks')) + self.blocks_button.props.sensitive = True + self.blocks_button.connect('clicked', self.do_hideshow_cb) + self.blocks_button.props.accelerator = _('<Ctrl>b') + palette_toolbar.insert(self.blocks_button, -1) + self.blocks_button.show() + + palette_toolbar_button = ToolbarButton( + page=palette_toolbar, + icon_name='palette') + palette_toolbar.show() + toolbar_box.toolbar.insert(palette_toolbar_button, -1) + palette_toolbar_button.set_expanded(True) + palette_toolbar_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + # eraser button + self.eraser_button = ToolButton( "eraseron" ) + self.eraser_button.set_tooltip(_('Clean')) + self.eraser_button.props.sensitive = True + self.eraser_button.connect('clicked', self.do_eraser_cb) + self.eraser_button.props.accelerator = _('<Ctrl>e') + toolbar_box.toolbar.insert(self.eraser_button, -1) + self.eraser_button.show() + + # run button + self.run_button = ToolButton( "run-fastoff" ) + self.run_button.set_tooltip(_('Run')) + self.run_button.props.sensitive = True + self.run_button.connect('clicked', self.do_run_cb) + self.run_button.props.accelerator = _('<Ctrl>r') + toolbar_box.toolbar.insert(self.run_button, -1) + self.run_button.show() + + # step button + self.step_button = ToolButton( "run-slowoff" ) + self.step_button.set_tooltip(_('Step')) + self.step_button.props.sensitive = True + self.step_button.connect('clicked', self.do_step_cb) + self.step_button.props.accelerator = _('<Ctrl>w') + toolbar_box.toolbar.insert(self.step_button, -1) + self.step_button.show() + + """ + + # debug button + self.debug_button = ToolButton( "debugoff" ) + self.debug_button.set_tooltip(_('Debug')) + self.debug_button.props.sensitive = True + self.debug_button.connect('clicked', self.do_debug_cb) + self.debug_button.props.accelerator = _('<Alt>d') + toolbar_box.toolbar.insert(self.debug_button, -1) + self.debug_button.show() + + """ + + # stop button + self.stop_button = ToolButton( "stopitoff" ) + self.stop_button.set_tooltip(_('Stop turtle')) + self.stop_button.props.sensitive = True + self.stop_button.connect('clicked', self.do_stop_cb) + self.stop_button.props.accelerator = _('<Ctrl>s') + toolbar_box.toolbar.insert(self.stop_button, -1) + self.stop_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + # The Help toolbar -- sample code and hover help + help_toolbar = gtk.Toolbar() + samples_button = ToolButton( "stock-open" ) + samples_button.set_tooltip(_('Samples')) + samples_button.connect('clicked', self.do_samples_cb) + samples_button.show() + help_toolbar.insert(samples_button, -1) + + separator = gtk.SeparatorToolItem() + separator.props.draw = True + help_toolbar.insert(separator, -1) + separator.show() + + self.hover_help_label = gtk.Label(' ') + self.hover_help_label.set_line_wrap(True) + self.hover_help_label.show() + self.hover_toolitem = gtk.ToolItem() + self.hover_toolitem.add(self.hover_help_label) + help_toolbar.insert(self.hover_toolitem, -1) + self.hover_toolitem.show() + + help_toolbar_button = ToolbarButton( + label=_("Help"), + page=help_toolbar, + icon_name='help-toolbar') + help_toolbar.show() + toolbar_box.toolbar.insert(help_toolbar_button, -1) + help_toolbar_button.show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + # The ever-present Stop Button + stop_button = StopButton(self) + stop_button.props.accelerator = '<Ctrl>Q' + toolbar_box.toolbar.insert(stop_button, -1) + stop_button.show() + + self.set_toolbar_box(toolbar_box) + toolbar_box.show() + + else: + # Use pre-0.86 toolbar design + self.toolbox = activity.ActivityToolbox(self) + self.set_toolbox(self.toolbox) + + # Add additional panels + self.projectToolbar = ProjectToolbar(self) + self.toolbox.add_toolbar( _('Project'), self.projectToolbar ) + self.viewToolbar = ViewToolbar(self) + self.toolbox.add_toolbar(_('View'), self.viewToolbar) + self.editToolbar = EditToolbar(self) + self.toolbox.add_toolbar(_('Edit'), self.editToolbar) + self.saveasToolbar = SaveAsToolbar(self) + self.toolbox.add_toolbar( _('Import/Export'), self.saveasToolbar ) + self.helpToolbar = HelpToolbar(self) + self.toolbox.add_toolbar(_('Help'), self.helpToolbar) + self.toolbox.show() + + # Set the project toolbar as the initial one selected + self.toolbox.set_current_toolbar(1) + + def _setup_scrolled_window(self): + """ Create a scrolled window to contain the turtle canvas. """ + self.sw = gtk.ScrolledWindow() + self.set_canvas(self.sw) + self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.sw.show() + canvas = gtk.DrawingArea() + width = gtk.gdk.screen_width() * 2 + height = gtk.gdk.screen_height() * 2 + canvas.set_size_request(width, height) + self.sw.add_with_viewport(canvas) + canvas.show() + return canvas + + def _check_ver_change(self, datapath): + """ To be replaced with date checking. """ + # Check to see if the version has changed + try: + version = os.environ['SUGAR_BUNDLE_VERSION'] + except: + version = " unknown" + + filename = "version.dat" + versiondata = [] + newversion = True + try: + FILE = open(os.path.join(datapath, filename), "r") + if FILE.readline() == version: + newversion = False + except: + _logger.debug("Creating a tamyblock.py Journal entry") + + # Make sure there is a copy of tamyblock.py in the Journal + if newversion: + dsobject = datastore.create() + dsobject.metadata['title'] = 'tamyblock.py' + dsobject.metadata['icon-color'] = \ + profile.get_color().to_string() + dsobject.metadata['mime_type'] = 'text/x-python' + dsobject.metadata['activity'] = 'org.laptop.Pippy' + dsobject.set_file_path(os.path.join( \ + activity.get_bundle_path(), 'tamyblock.py')) + datastore.write(dsobject) + dsobject.destroy() + + versiondata.append(version) + file_handle = open(os.path.join(datapath, filename), "w") + file_handle.writelines(versiondata) + file_handle.close() + return + + def _setup_canvas(self, canvas): + """ Initialize the turtle art canvas. """ + bundle_path = activity.get_bundle_path() + self.tw = TurtleArtWindow(canvas, bundle_path, self, + profile.get_color().to_string()) + # self.tw.activity = self + self.tw.window.grab_focus() + path = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'], 'data') + self.tw.save_folder = path + + if self._jobject and self._jobject.file_path: + self.read_file(self._jobject.file_path) + else: # if new, load a start brick onto the canvas + self.tw.load_start() + + def _load_python_code(self): + """ Check to see if there is Python code to be loaded. """ + try: + dsobject = datastore.get(self.metadata['python code']) + self._load_python(dsobject) + except: + pass + + def _setup_sharing(self): + """ A simplistic sharing model: the sharer is the master """ + # TODO: hand off role of master is sharer leaves + # Get the Presence Service + self.pservice = presenceservice.get_instance() + self.initiating = None # sharing (True) or joining (False) + + # Add my buddy object to the list + owner = self.pservice.get_owner() + self.owner = owner + self.tw.buddies.append(self.owner) + self._share = "" + + self.connect('shared', self._shared_cb) + self.connect('joined', self._joined_cb) + + + def _setup_visibility_handler(self): + """ Notify when the visibility state changes """ + self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK) + self.connect("visibility-notify-event", self.__visibility_notify_cb) + + def write_file(self, file_path): + """ Write the project to the Journal. """ + _logger.debug("Write file: %s" % file_path) + self.metadata['mime_type'] = 'application/x-turtle-art' + data_to_file(self.tw.assemble_data_to_save(), file_path) + + def read_file(self, file_path, run_it = True): + """ Read a project in and then run it. """ + import tarfile, os, tempfile, shutil + + if hasattr(self, 'tw'): + _logger.debug("Read file: %s" % file_path) + # Could be a gtar (newer builds) or tar (767) file + if file_path[-5:] == ".gtar" or file_path[-4:] == ".tar": + tar_fd = tarfile.open(file_path, 'r') + tmpdir = tempfile.mkdtemp() + try: + # We'll get 'ta_code.ta' and possibly a 'ta_image.png' + # but we will ignore the .png file + # If run_it is True, we want to create a new project + tar_fd.extractall(tmpdir) + self.tw.load_files(os.path.join(tmpdir,'ta_code.ta'), \ + run_it) # create a new project flag + finally: + shutil.rmtree(tmpdir) + tar_fd.close() + # Otherwise, assume it is a .ta file + else: + _logger.debug("trying to open a .ta file:" + file_path) + self.tw.load_files(file_path, run_it) + + # run the activity + if run_it: + try: + # Use 0.86 toolbar design + self.stop_button.set_icon("stopiton") + except: + # Use pre-0.86 toolbar design + self.projectToolbar.stop.set_icon("stopiton") + + self.tw.run_button(0) + else: + _logger.debug("Deferring reading file %s" % file_path) + + def jobject_new_patch(self): + """ Save instance to Journal. """ + oldj = self._jobject + self._jobject = datastore.create() + self._jobject.metadata['title'] = oldj.metadata['title'] + self._jobject.metadata['title_set_by_user'] = \ + oldj.metadata['title_set_by_user'] + # self._jobject.metadata['activity'] = self.get_service_name() + self._jobject.metadata['activity_id'] = self.get_id() + self._jobject.metadata['keep'] = '0' + # Is this the correct syntax for saving the buddies list? + # self._jobject.metadata['buddies'] = self.tw.buddies + self._jobject.metadata['preview'] = '' + self._jobject.metadata['icon-color'] = profile.get_color().to_string() + self._jobject.file_path = '' + datastore.write(self._jobject, + reply_handler=self._internal_jobject_create_cb, + error_handler=self._internal_jobject_error_cb) + self._jobject.destroy() + +class ChatTube(ExportedGObject): + + def __init__(self, tube, is_initiator, stack_received_cb): + """Class for setting up tube for sharing.""" + super(ChatTube, self).__init__(tube, PATH) + self.tube = tube + self.is_initiator = is_initiator # Are we sharing or joining activity? + self.stack_received_cb = stack_received_cb + self.stack = '' + + self.tube.add_signal_receiver(self.send_stack_cb, 'SendText', IFACE, \ + path=PATH, sender_keyword='sender') + + def send_stack_cb(self, text, sender=None): + if sender == self.tube.get_unique_name(): + return + self.stack = text + self.stack_received_cb(text) + + @signal(dbus_interface=IFACE, signature='s') + def SendText(self, text): + self.stack = text + +class ViewToolbar(gtk.Toolbar): + def __init__(self, pc): + """ View toolbar: fullscreen, Cartesian, polar, coordinates """ + gtk.Toolbar.__init__(self) + self.activity = pc + + # full screen + self.activity.fullscreen_button = ToolButton( "view-fullscreen" ) + self.activity.fullscreen_button.set_tooltip(_('Fullscreen')) + self.activity.fullscreen_button.props.sensitive = True + try: + self.activity.fullscreen_button.props.accelerator = '<Alt>Enter' + except: + pass + self.activity.fullscreen_button.connect('clicked', \ + self.activity.do_fullscreen_cb) + self.insert(self.activity.fullscreen_button, -1) + self.activity.fullscreen_button.show() + + # Cartesian coordinates + self.activity.cartesian_button = ToolButton( "view-Cartesian" ) + self.activity.cartesian_button.set_tooltip(_('Cartesian coordinates')) + self.activity.cartesian_button.props.sensitive = True + self.activity.cartesian_button.connect('clicked', \ + self.activity.do_cartesian_cb) + self.insert(self.activity.cartesian_button, -1) + self.activity.cartesian_button.show() + + # polar coordinates + self.activity.polar_button = ToolButton( "view-polar" ) + self.activity.polar_button.set_tooltip(_('Polar coordinates')) + self.activity.polar_button.props.sensitive = True + self.activity.polar_button.connect('clicked', \ + self.activity.do_polar_cb) + self.insert(self.activity.polar_button, -1) + self.activity.polar_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + self.insert(separator, -1) + separator.show() + + # Coordinates label + self.activity.coordinates_label = \ + gtk.Label(_("xcor") + "= 0 " + _("ycor") + "= 0 " + \ + _("heading") + "= 0") + self.activity.coordinates_label.show() + self.activity.coordinates_toolitem = gtk.ToolItem() + self.activity.coordinates_toolitem.add(self.activity.coordinates_label) + self.insert(self.activity.coordinates_toolitem, -1) + self.activity.coordinates_toolitem.show() + + """ + + separator = gtk.SeparatorToolItem() + separator.set_draw(False) + separator.set_expand(True) + self.insert(separator, -1) + separator.show() + + self.activity.resize_up_button = ToolButton('resize+') + self.activity.resize_up_button.set_tooltip(_("Grow blocks")) + self.activity.resize_up_button.connect('clicked', + self.activity.do_resize_blocks_cb, 1.5) + self.insert(self.activity.resize_up_button, -1) + self.activity.resize_up_button.show() + + self.activity.resize_down_button = ToolButton('resize-') + self.activity.resize_down_button.set_tooltip(_("Shrink blocks")) + self.activity.resize_down_button.connect('clicked', + self.activity.do_resize_blocks_cb, 0.667) + self.insert(self.activity.resize_down_button, -1) + self.activity.resize_down_button.show() + + self.activity.rescale_button = ToolButton('expand-coordinates') + self.activity.rescale_button.set_tooltip(_("Rescale coordinates up")) + self.activity.rescale_button.connect('clicked', \ + self.activity.do_rescale_cb) + self.insert(self.activity.rescale_button, -1) + self.activity.rescale_button.show() + + """ + +class EditToolbar(gtk.Toolbar): + def __init__(self, pc): + """ Edit toolbar: copy and paste text and stacks """ + gtk.Toolbar.__init__(self) + self.activity = pc + + # Copy button + self.copy = ToolButton( "edit-copy" ) + self.copy.set_tooltip(_('Copy')) + self.copy.props.sensitive = True + self.copy.connect('clicked', self._copy_cb) + try: + self.copy.props.accelerator = '<Ctrl>C' + except: + pass + self.insert(self.copy, -1) + self.copy.show() + + # Paste button + self.paste = ToolButton( "edit-paste" ) + self.paste.set_tooltip(_('Paste')) + self.paste.props.sensitive = True + self.paste.connect('clicked', self._paste_cb) + try: + self.paste.props.accelerator = '<Ctrl>V' + except: + pass + self.insert(self.paste, -1) + self.paste.show() + + def _copy_cb(self, button): + clipBoard = gtk.Clipboard() + _logger.debug("serialize the project and copy to clipboard") + data = self.activity.tw.assemble_data_to_save(False, False) + if data is not []: + text = data_to_string(data) + clipBoard.set_text(text) + + def _paste_cb(self, button): + clipBoard = gtk.Clipboard() + _logger.debug("paste to the project") + text = clipBoard.wait_for_text() + if text is not None: + if self.activity.tw.selected_blk is not None and\ + self.activity.tw.selected_blk.name == 'string': + for i in text: + self.activity.tw.process_alphanumeric_input(i, -1) + self.activity.tw.selected_blk.resize() + else: + self.activity.tw.process_data(data_from_string(text)) + +class HelpToolbar(gtk.Toolbar): + def __init__(self, pc): + """ Help toolbar: Just an icon and a label for displaying hover help """ + gtk.Toolbar.__init__(self) + self.activity = pc + + # Help icon + self.help = ToolButton( "help-toolbar" ) + self.help.props.sensitive = False + self.insert(self.help, -1) + self.help.show() + + # Help label + self.activity.hover_help_label = gtk.Label(' ') + self.activity.hover_help_label.set_line_wrap(True) + self.activity.hover_help_label.show() + self.activity.hover_toolitem = gtk.ToolItem() + self.activity.hover_toolitem.add(self.activity.hover_help_label) + self.insert(self.activity.hover_toolitem, -1) + self.activity.hover_toolitem.show() + +class SaveAsToolbar(gtk.Toolbar): + def __init__(self, pc): + """ SaveAs toolbar """ + gtk.Toolbar.__init__(self) + self.activity = pc + + """ + + # HTML save source button + self.activity.save_as_html = ToolButton( "htmloff" ) + self.activity.save_as_html.set_tooltip(_('Save as HTML')) + self.activity.save_as_html.props.sensitive = True + self.activity.save_as_html.connect('clicked', \ + self.activity.do_save_as_html_cb) + self.insert(self.activity.save_as_html, -1) + self.activity.save_as_html.show() + + # Berkeley Logo save source button + self.activity.save_as_logo = ToolButton( "logo-saveoff" ) + self.activity.save_as_logo.set_tooltip(_('Save Logo')) + self.activity.save_as_logo.props.sensitive = True + self.activity.save_as_logo.connect('clicked', \ + self.activity.do_save_as_logo_cb) + self.insert(self.activity.save_as_logo, -1) + self.activity.save_as_logo.show() + + """ + + # Save as image button + self.activity.save_as_image = ToolButton( "image-saveoff" ) + self.activity.save_as_image.set_tooltip(_('Save as image')) + self.activity.save_as_image.props.sensitive = True + self.activity.save_as_image.connect('clicked', \ + self.activity.do_save_as_image_cb) + self.insert(self.activity.save_as_image, -1) + self.activity.save_as_image.show() + + """ + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + self.insert(separator, -1) + separator.show() + + # Pippy load myblock source button + self.activity.load_python = ToolButton( "pippy-openoff" ) + self.activity.load_python.set_tooltip(_('Load my block')) + self.activity.load_python.props.sensitive = True + self.activity.load_python.connect('clicked', \ + self.activity.do_load_python_cb) + self.insert(self.activity.load_python, -1) + self.activity.load_python.show() + + """ + + # Open TA project from the Journal + self.activity.load_ta_project = ToolButton('load-from-journal') + self.activity.load_ta_project.set_tooltip(\ + _("Import project from the Journal")) + self.activity.load_ta_project.props.sensitive = True + self.activity.load_ta_project.connect('clicked', \ + self.activity.do_load_ta_project_cb) + self.insert(self.activity.load_ta_project, -1) + self.activity.load_ta_project.show() + + +class ProjectToolbar(gtk.Toolbar): + + def __init__(self, pc): + """ Project toolbar """ + gtk.Toolbar.__init__(self) + self.activity = pc + + # palette button (blocks) + self.activity.palette_button = ToolButton( "paletteoff" ) + self.activity.palette_button.set_tooltip(_('Hide palette')) + self.activity.palette_button.props.sensitive = True + self.activity.palette_button.connect('clicked', \ + self.activity.do_palette_cb) + try: + self.activity.palette_button.props.accelerator = _('<Ctrl>p') + except: + pass + self.insert(self.activity.palette_button, -1) + self.activity.palette_button.show() + + # blocks button (hideshow) + self.activity.blocks_button = ToolButton( "hideshowoff" ) + self.activity.blocks_button.set_tooltip(_('Hide blocks')) + self.activity.blocks_button.props.sensitive = True + self.activity.blocks_button.connect('clicked', \ + self.activity.do_hideshow_cb) + try: + self.activity.blocks_button.props.accelerator = _('<Ctrl>b') + except: + pass + self.insert(self.activity.blocks_button, -1) + self.activity.blocks_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + self.insert(separator, -1) + separator.show() + + # run button + self.activity.run_button = ToolButton( "run-fastoff" ) + self.activity.run_button.set_tooltip(_('Run')) + self.activity.run_button.props.sensitive = True + self.activity.run_button.connect('clicked', self.activity.do_run_cb) + try: + self.activity.run_button.props.accelerator = _('<Ctrl>r') + except: + pass + self.insert(self.activity.run_button, -1) + self.activity.run_button.show() + + # step button + self.activity.step_button = ToolButton( "run-slowoff" ) + self.activity.step_button.set_tooltip(_('Step')) + self.activity.step_button.props.sensitive = True + self.activity.step_button.connect('clicked', self.activity.do_step_cb) + try: + self.activity.step_button.props.accelerator = _('<Ctrl>w') + except: + pass + self.insert(self.activity.step_button, -1) + self.activity.step_button.show() + + """ + + # debug button + self.activity.debug_button = ToolButton( "debugoff" ) + self.activity.debug_button.set_tooltip(_('Debug')) + self.activity.debug_button.props.sensitive = True + self.activity.debug_button.connect('clicked', \ + self.activity.do_debug_cb) + try: + self.activity.debug_button.props.accelerator = _('<Ctrl>d') + except: + pass + self.insert(self.activity.debug_button, -1) + self.activity.debug_button.show() + + """ + + # stop button + self.activity.stop_button = ToolButton( "stopitoff" ) + self.activity.stop_button.set_tooltip(_('Stop turtle')) + self.activity.stop_button.props.sensitive = True + self.activity.stop_button.connect('clicked', self.activity.do_stop_cb) + try: + self.activity.stop_button.props.accelerator = _('<Ctrl>s') + except: + pass + self.insert(self.activity.stop_button, -1) + self.activity.stop_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + self.insert(separator, -1) + separator.show() + + # eraser button + self.activity.eraser_button = ToolButton( "eraseron" ) + self.activity.eraser_button.set_tooltip(_('Clean')) + self.activity.eraser_button.props.sensitive = True + self.activity.eraser_button.connect('clicked', \ + self.activity.do_eraser_cb) + try: + self.activity.eraser_button.props.accelerator = _('<Ctrl>e') + except: + pass + self.insert(self.activity.eraser_button, -1) + self.activity.eraser_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + self.insert(separator, -1) + separator.show() + + """ + + # Save snapshot ("keep") + self.activity.keep_button = ToolButton( "filesave" ) + self.activity.keep_button.set_tooltip(_('Save snapshot')) + self.activity.keep_button.props.sensitive = True + try: + self.activity.keep_button.props.accelerator = '<Alt>S' + except: + pass + self.activity.keep_button.connect('clicked', \ + self.activity.do_keep_cb) + self.insert(self.activity.keep_button, -1) + self.activity.keep_button.show() + + separator = gtk.SeparatorToolItem() + separator.set_draw(True) + self.insert(separator, -1) + separator.show() + + """ + + # project open + self.activity.samples_button = ToolButton( "stock-open" ) + self.activity.samples_button.set_tooltip(_('Samples')) + self.activity.samples_button.props.sensitive = True + self.activity.samples_button.connect('clicked', \ + self.activity.do_samples_cb) + try: + self.activity.samples_button.props.accelerator = _('<Ctrl>o') + except: + pass + self.insert(self.activity.samples_button, -1) + self.activity.samples_button.show() + + + |