From b9029092b88a641f8ff89d8a22c724201d2f40b0 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Thu, 11 Mar 2010 19:02:59 +0000 Subject: pylint cleanup --- diff --git a/NEWS b/NEWS index 210bd83..f6dc37d 100644 --- a/NEWS +++ b/NEWS @@ -14,12 +14,16 @@ o new prefix boolean logic o showblock to compliment hideblock o fullscreen block + o Cartesian and polor coordinate blocks + o color blocks o editible macros (used for presentation blocks) o labels on coordinate-grid overlays o more complete support in non-Sugar environments o new (and improved) sample code o Logo code for project added to View Source o save SVG block lets you generate SVG with Turtle Art + o improved export-to-HTML logic + o new translations * completed a major refactoring of the code o 90% smaller download bundle-size diff --git a/TurtleArtActivity.py b/TurtleArtActivity.py index 9292f65..93a367a 100644 --- a/TurtleArtActivity.py +++ b/TurtleArtActivity.py @@ -28,38 +28,30 @@ import gobject import logging _logger = logging.getLogger('turtleart-activity') -import sugar from sugar.activity import activity try: # 0.86 toolbar widgets - from sugar.bundle.activitybundle import ActivityBundle 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 + NEW_SUGAR_SYSTEM = True except ImportError: - _new_sugar_system = False - pass + NEW_SUGAR_SYSTEM = False from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.menuitem import MenuItem -from sugar.graphics.icon import Icon from sugar.datastore import datastore import telepathy -from dbus.service import method, signal +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 locale import os.path -import subprocess import tarfile -import sys -from taconstants import * +from taconstants import PALETTE_NAMES, OVERLAY_LAYER, HELP_STRINGS from taexporthtml import save_html from taexportlogo import save_logo from tautils import data_to_file, data_to_string, data_from_string, get_path @@ -72,30 +64,31 @@ PATH = '/org/laptop/TurtleArtActivity' class TurtleArtActivity(activity.Activity): def __init__(self, handle): + """ Activity subclass for Turtle Art """ super(TurtleArtActivity, self).__init__(handle) datapath = get_path(activity, 'data') self._setup_visibility_handler() - self.new_sugar_system = _new_sugar_system + self.new_sugar_system = NEW_SUGAR_SYSTEM self._setup_toolbar() canvas = self._setup_scrolled_window() - lang = self._check_ver_lang_change(datapath) + self._check_ver_change(datapath) - self._setup_canvas(canvas, lang) + self._setup_canvas(canvas) self._load_python_code() self._setup_sharing() - """ Activity toolbar callbacks """ + # Activity toolbar callbacks - def _do_save_as_html_cb(self, button): - # write html out to datastore + 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 @@ -153,16 +146,16 @@ class TurtleArtActivity(activity.Activity): dsobject.metadata['activity'] = 'org.laptop.WebActivity' datastore.write(dsobject) dsobject.destroy() - gobject.timeout_add(250,self.save_as_html.set_icon, "htmloff") + 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 + 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,self.tw) + logocode = save_logo(self.tw) if len(logocode) == 0: return filename = "logosession.lg" @@ -191,10 +184,11 @@ class TurtleArtActivity(activity.Activity): dsobject.set_file_path(file_path) datastore.write(dsobject) - gobject.timeout_add(250,self.save_as_logo.set_icon, "logo-saveoff") + gobject.timeout_add(250, self.save_as_logo.set_icon, "logo-saveoff") return - def _do_load_ta_project_cb(self, button): + 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) @@ -213,14 +207,15 @@ class TurtleArtActivity(activity.Activity): del chooser return - def _do_load_python_cb(self, button): + 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") + gobject.timeout_add(250, self.load_python.set_icon, "pippy-openoff") return - # Import Python code from the Journal to load into "myblock" 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) @@ -233,12 +228,13 @@ class TurtleArtActivity(activity.Activity): chooser.destroy() del chooser - def _load_python(self,dsobject): + def _load_python(self, dsobject): + """ Read the Python code from the Journal object """ try: _logger.debug("opening %s " % dsobject.file_path) - FILE = open(dsobject.file_path, "r") - self.tw.myblock = FILE.read() - FILE.close() + 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 @@ -246,21 +242,19 @@ class TurtleArtActivity(activity.Activity): _logger.debug("couldn't open %s" % dsobject.file_path) dsobject.destroy() - def _do_save_as_image_cb(self, button): + 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") + gobject.timeout_add(250, self.save_as_image.set_icon, "image-saveoff") return - """ Save snapshot """ - def _do_keep_cb(self, button): - # Create a datastore object + 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") - print tafile try: data_to_file(self.tw.assemble_data_to_save(), tafile) except: @@ -283,9 +277,10 @@ class TurtleArtActivity(activity.Activity): os.remove(tafile) return - """ Main toolbar button callbacks """ - """ Show/hide palette """ - def _do_palette_cb(self, button): + # 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") @@ -300,8 +295,8 @@ class TurtleArtActivity(activity.Activity): if self.new_sugar_system: self.palette_buttons[0].set_icon(PALETTE_NAMES[0]+'on') - """ Palette selector buttons """ - def _do_palette_buttons_cb(self, button, i): + 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( @@ -311,16 +306,20 @@ class TurtleArtActivity(activity.Activity): self.palette_button.set_icon("paletteoff") self.palette_button.set_tooltip(_('Hide palette')) - """ These methods are called both from buttons and 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): + 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") @@ -337,59 +336,64 @@ class TurtleArtActivity(activity.Activity): 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): + 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") + gobject.timeout_add(250, self.eraser_button.set_icon, "eraseron") - def _do_run_cb(self, button): + 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") + gobject.timeout_add(1000, self.run_button.set_icon, "run-fastoff") - def _do_step_cb(self, button): + 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") + gobject.timeout_add(1000, self.step_button.set_icon, "run-slowoff") - def _do_debug_cb(self, button): + 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") + gobject.timeout_add(1000, self.debug_button.set_icon, "debugoff") - def _do_stop_cb(self, button): + 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") - """ Sample projects open dialog """ - def _do_samples_cb(self, button): + 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) - """ - Recenter scrolled window around canvas - """ def recenter(self): + """ Recenter scrolled window around canvas. """ hadj = self.sw.get_hadjustment() hadj.set_value(0) self.sw.set_hadjustment(hadj) @@ -397,33 +401,32 @@ class TurtleArtActivity(activity.Activity): vadj.set_value(0) self.sw.set_vadjustment(vadj) - def _do_fullscreen_cb(self, button): + def do_fullscreen_cb(self, button): + """ Hide the Sugar toolbars. """ self.fullscreen() self.recenter() - def _do_resize_blocks_cb(self, button, scale_factor): + def do_resize_blocks_cb(self, button, scale_factor): + """ Scale the blocks. """ self.tw.block_scale *= scale_factor self.tw.resize_blocks() - """ - Display coordinate grids - """ - def _do_cartesian_cb(self, button): + 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): + 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) - """ - Rescale coordinate system to 100 == height/2 or 100 == 100 pixels (default) - """ - def _do_rescale_cb(self, button): + 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") @@ -442,29 +445,28 @@ class TurtleArtActivity(activity.Activity): self.tw.overlay_shapes['Cartesian_labeled'].set_layer( OVERLAY_LAYER) - """ - View logo code as part of view source. - """ 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, self.tw) + code = save_logo(self.tw) f = file(tafile, "w") f.write(code) f.close() except Exception, e: - print("couldn't dump code to view source: " + str(e)) + print("Couldn't dump code to view source: " + str(e)) return tafile - """ - Either set up initial share... - """ + # 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()") @@ -486,10 +488,8 @@ class TurtleArtActivity(activity.Activity): id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) - """ - ...or join an exisiting share. - """ 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()") @@ -521,10 +521,8 @@ class TurtleArtActivity(activity.Activity): def _list_tubes_error_cb(self, e): _logger.error('ListTubes() failed: %s', e) - """ - Create a new tube - """ 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) @@ -544,70 +542,67 @@ class TurtleArtActivity(activity.Activity): # now that we have the tube, we can ask for an initialization if self.waiting_for_blocks: - self._send_event("i") - - """ - Handle the receiving of events in share - Events are sent as a tuple - cmd:data - where cmd is a mouse or keyboard event and data are x,y coordinates - or a keysroke - """ + self.send_event("i") + def event_received_cb(self, text): + """ Handle the receiving of events in share """ + + """ DEPRECIATED + Events are sent as a tuple + cmd:data + where cmd is a mouse or keyboard event and data are x,y coordinates + or a keysroke + """ # maybe we can use a stack to share events to new-comers? # self._share += "text + "\n" if text[0] == 'p': # button press - e,x,y,mask = text.split(":") + e, x, y, mask = text.split(":") # _logger.debug("receiving button press: "+x+" "+y+" "+mask) if mask == 'T': - self.tw.button_press(True,int(x),int(y),False) + self.tw.button_press(True, int(x), int(y), False) else: - self.tw.button_press(False,int(x),int(y),False) + self.tw.button_press(False, int(x), int(y), False) elif text[0] == 'r': # block release - e,x,y = text.split(":") + e, x, y = text.split(":") # _logger.debug("receiving button release: " + x + " " + y) - self.tw.button_release(int(x),int(y),False) + self.tw.button_release(int(x), int(y), False) elif text[0] == 'm': # mouse move - e,x,y = text.split(":") + e, x, y = text.split(":") _logger.debug("receiving move: " + x + " " + y) - self.tw.mouse_move(0,0,False,int(x),int(y)) + self.tw.mouse_move(0, 0, False, int(x), int(y)) elif text[0] == 'k': # typing - e,mask,keyname = text.split(":",3) + e, mask, keyname = text.split(":", 3) # _logger.debug("recieving key press: " + mask + " " + keyname) if mask == 'T': - self.tw.key_press(True,keyname,False) + self.tw.key_press(True, keyname, False) else: - self.tw.key_press(False,keyname,False) + self.tw.key_press(False, keyname, False) elif text[0] == 'i': # request for current state # sharer should send current state to joiner if self.initiating: _logger.debug("serialize the project and send to joiner") text = data_to_string(self.tw.assemble_data_to_save(True, True)) - self._send_event("I:" + text) + self.send_event("I:" + text) self.tw.show_palette() elif text[0] == 'I': # receiving current state if self.waiting_for_blocks: _logger.debug("receiving project from sharer") - e,text = text.split(":",2) + e, text = text.split(":", 2) if len(text) > 0: self.tw.new_project() self.tw.process_data(data_from_string(text)) # all caught up self.waiting_for_blocks = False - """ - Send event through the tube - """ - def _send_event(self, entry): + def send_event(self, entry): + """ Send event through the tube. """ # nick = profile.get_nick_name() # nick = nick.upper() if hasattr(self, 'chattube') and self.chattube is not None: self.chattube.SendText(entry) - """ - Callback method for when the activity's visibility changes - """ def __visibility_notify_cb(self, window, event): + """ Callback method for when the activity's visibility changes. """ if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED: # _logger.debug("I am not visible so I should free the audio") self.tw.lc.ag = None @@ -616,18 +611,17 @@ class TurtleArtActivity(activity.Activity): 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() - """ - Setup toolbar according to Sugar version - """ def _setup_toolbar(self): - + """ Setup toolbar according to Sugar version """ if self.new_sugar_system: # Use 0.86 toolbar design toolbar_box = ToolbarBox() @@ -637,35 +631,35 @@ class TurtleArtActivity(activity.Activity): # 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.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.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.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.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.connect('clicked', self.do_load_python_cb) self.load_python.show() activity_button.props.page.insert(self.load_python, -1) @@ -673,7 +667,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_load_ta_project_cb) self.load_ta_project.show() activity_button.props.page.insert(self.load_ta_project, -1) @@ -695,20 +689,20 @@ class TurtleArtActivity(activity.Activity): fullscreen_button = ToolButton('view-fullscreen') fullscreen_button.set_tooltip(_("Fullscreen")) fullscreen_button.props.accelerator = 'Enter' - fullscreen_button.connect('clicked', self._do_fullscreen_cb) - view_toolbar.insert(fullscreen_button,-1) + 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.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.connect('clicked', self.do_polar_cb) + view_toolbar.insert(polar_button, -1) polar_button.show() separator = gtk.SeparatorToolItem() @@ -723,7 +717,7 @@ class TurtleArtActivity(activity.Activity): self.coordinates_label.show() self.coordinates_toolitem = gtk.ToolItem() self.coordinates_toolitem.add(self.coordinates_label) - view_toolbar.insert(self.coordinates_toolitem,-1) + view_toolbar.insert(self.coordinates_toolitem, -1) self.coordinates_toolitem.show() separator = gtk.SeparatorToolItem() @@ -734,22 +728,22 @@ class TurtleArtActivity(activity.Activity): 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.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.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.do_resize_blocks_cb, 0.667) + view_toolbar.insert(self.resize_down_button, -1) self.resize_down_button.show() view_toolbar_button = ToolbarButton( @@ -770,7 +764,7 @@ class TurtleArtActivity(activity.Activity): self.palette_buttons[i].set_tooltip(HELP_STRINGS[name]) self.palette_buttons[i].props.sensitive = True self.palette_buttons[i].connect('clicked', - self._do_palette_buttons_cb, i) + self.do_palette_buttons_cb, i) palette_toolbar.insert(self.palette_buttons[i], -1) self.palette_buttons[i].show() @@ -783,7 +777,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_palette_cb) self.palette_button.props.accelerator = _('p') palette_toolbar.insert(self.palette_button, -1) self.palette_button.show() @@ -791,7 +785,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_hideshow_cb) self.blocks_button.props.accelerator = _('b') palette_toolbar.insert(self.blocks_button, -1) self.blocks_button.show() @@ -813,7 +807,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_eraser_cb) self.eraser_button.props.accelerator = _('e') toolbar_box.toolbar.insert(self.eraser_button, -1) self.eraser_button.show() @@ -822,7 +816,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_run_cb) self.run_button.props.accelerator = _('r') toolbar_box.toolbar.insert(self.run_button, -1) self.run_button.show() @@ -831,7 +825,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_step_cb) self.step_button.props.accelerator = _('w') toolbar_box.toolbar.insert(self.step_button, -1) self.step_button.show() @@ -840,7 +834,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_debug_cb) self.debug_button.props.accelerator = _('d') toolbar_box.toolbar.insert(self.debug_button, -1) self.debug_button.show() @@ -849,7 +843,7 @@ class TurtleArtActivity(activity.Activity): 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.connect('clicked', self.do_stop_cb) self.stop_button.props.accelerator = _('s') toolbar_box.toolbar.insert(self.stop_button, -1) self.stop_button.show() @@ -863,7 +857,7 @@ class TurtleArtActivity(activity.Activity): help_toolbar = gtk.Toolbar() samples_button = ToolButton( "stock-open" ) samples_button.set_tooltip(_('Samples')) - samples_button.connect('clicked', self._do_samples_cb) + samples_button.connect('clicked', self.do_samples_cb) samples_button.show() help_toolbar.insert(samples_button, -1) @@ -878,7 +872,7 @@ class TurtleArtActivity(activity.Activity): 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) + help_toolbar.insert(self.hover_toolitem, -1) self.hover_toolitem.show() help_toolbar_button = ToolbarButton( @@ -919,16 +913,14 @@ class TurtleArtActivity(activity.Activity): 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.add_toolbar(_('Help'), self.helpToolbar) self.toolbox.show() # Set the project toolbar as the initial one selected self.toolbox.set_current_toolbar(1) - """ - Create a scrolled window to contain the turtle canvas - """ 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) @@ -941,40 +933,24 @@ class TurtleArtActivity(activity.Activity): canvas.show() return canvas - """ - To be replaced with date checking in tasetup.py; - each language group should be stored in it's own sub-directory - """ - def _check_ver_lang_change(self, datapath): - # Check to see if the version or language has changed + 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" - lang = locale.getdefaultlocale()[0] - if not lang: - lang = 'en' - lang = lang[0:2] - if not os.path.isdir(os.path.join(activity.get_bundle_path(), \ - 'images', lang)): - lang = 'en' - - # If either has changed, remove the old png files filename = "version.dat" versiondata = [] newversion = True try: FILE = open(os.path.join(datapath, filename), "r") - if FILE.readline() == lang + version: + if FILE.readline() == version: newversion = False - else: - _logger.debug("out with the old, in with the new") - cmd = "rm " + os.path.join(datapath, '*.png') - subprocess.check_call(cmd, shell=True) except: - _logger.debug("writing new version data") - _logger.debug("and creating a tamyblock.py Journal entry") + _logger.debug("Writing new version data...") + _logger.debug("...and creating a tamyblock.py Journal entry") # Make sure there is a copy of tamyblock.py in the Journal if newversion: @@ -989,46 +965,38 @@ class TurtleArtActivity(activity.Activity): datastore.write(dsobject) dsobject.destroy() - versiondata.append(lang + version) - FILE = open(os.path.join(datapath, filename), "w") - FILE.writelines(versiondata) - FILE.close() - - return lang + versiondata.append(version) + file_handle = open(os.path.join(datapath, filename), "w") + file_handle.writelines(versiondata) + file_handle.close() + return - """ - Initialize the turtle art canvas - """ - def _setup_canvas(self, canvas, lang): + def _setup_canvas(self, canvas): + """ Initialize the turtle art canvas. """ bundle_path = activity.get_bundle_path() - self.tw = TurtleArtWindow(canvas, bundle_path, lang, self, + 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 + 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() - """ - Check to see if there is Python code to be loaded - """ 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 - - """ - A simplistic sharing model: the sharer is the master; - TODO: hand off role of master is sharer leaves - """ 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) @@ -1043,26 +1011,20 @@ class TurtleArtActivity(activity.Activity): self.connect('joined', self._joined_cb) - """ - Notify when the visibility state changes - """ 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) - """ - Write the project to the Journal - """ 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) - """ - Read a project in and then run it - """ def read_file(self, file_path, run_it = True): - import tarfile,os,tempfile,shutil + """ Read a project in and then run it. """ + import tarfile, os, tempfile, shutil if hasattr(self, 'tw'): _logger.debug("Read file: %s" % file_path) @@ -1098,10 +1060,8 @@ class TurtleArtActivity(activity.Activity): else: _logger.debug("Deferring reading file %s" % file_path) - """ - Save instance to Journal - """ def jobject_new_patch(self): + """ Save instance to Journal. """ oldj = self._jobject self._jobject = datastore.create() self._jobject.metadata['title'] = oldj.metadata['title'] @@ -1120,12 +1080,10 @@ class TurtleArtActivity(activity.Activity): error_handler=self._internal_jobject_error_cb) self._jobject.destroy() -""" -Class for setting up tube for sharing -""" 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? @@ -1145,11 +1103,9 @@ class ChatTube(ExportedGObject): def SendText(self, text): self.stack = text -""" -View toolbar: fullscreen, Cartesian, polar, coordinates -""" class ViewToolbar(gtk.Toolbar): def __init__(self, pc): + """ View toolbar: fullscreen, Cartesian, polar, coordinates """ gtk.Toolbar.__init__(self) self.activity = pc @@ -1162,7 +1118,7 @@ class ViewToolbar(gtk.Toolbar): except: pass self.activity.fullscreen_button.connect('clicked', \ - self.activity._do_fullscreen_cb) + self.activity.do_fullscreen_cb) self.insert(self.activity.fullscreen_button, -1) self.activity.fullscreen_button.show() @@ -1171,7 +1127,7 @@ class ViewToolbar(gtk.Toolbar): 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.activity.do_cartesian_cb) self.insert(self.activity.cartesian_button, -1) self.activity.cartesian_button.show() @@ -1180,7 +1136,7 @@ class ViewToolbar(gtk.Toolbar): 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.activity.do_polar_cb) self.insert(self.activity.polar_button, -1) self.activity.polar_button.show() @@ -1196,7 +1152,7 @@ class ViewToolbar(gtk.Toolbar): 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.insert(self.activity.coordinates_toolitem, -1) self.activity.coordinates_toolitem.show() separator = gtk.SeparatorToolItem() @@ -1208,29 +1164,27 @@ class ViewToolbar(gtk.Toolbar): 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.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.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.do_rescale_cb) + self.insert(self.activity.rescale_button, -1) self.activity.rescale_button.show() -""" -Edit toolbar: copy and paste text and stacks -""" class EditToolbar(gtk.Toolbar): def __init__(self, pc): + """ Edit toolbar: copy and paste text and stacks """ gtk.Toolbar.__init__(self) self.activity = pc @@ -1279,11 +1233,9 @@ class EditToolbar(gtk.Toolbar): else: self.activity.tw.process_data(data_from_string(text)) -""" -Help toolbar: Just an icon and a label for displaying hover help -""" 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 @@ -1300,15 +1252,12 @@ class HelpToolbar(gtk.Toolbar): 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.insert(self.activity.hover_toolitem, -1) self.activity.hover_toolitem.show() -""" -SaveAs toolbar: (1) load samples; (2) save as HTML; (3) save as LOGO; -(4) save as PNG; and (5) import Python code. -""" class SaveAsToolbar(gtk.Toolbar): def __init__(self, pc): + """ SaveAs toolbar """ gtk.Toolbar.__init__(self) self.activity = pc @@ -1317,7 +1266,7 @@ class SaveAsToolbar(gtk.Toolbar): 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.activity.do_save_as_html_cb) self.insert(self.activity.save_as_html, -1) self.activity.save_as_html.show() @@ -1326,7 +1275,7 @@ class SaveAsToolbar(gtk.Toolbar): 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.activity.do_save_as_logo_cb) self.insert(self.activity.save_as_logo, -1) self.activity.save_as_logo.show() @@ -1335,7 +1284,7 @@ class SaveAsToolbar(gtk.Toolbar): 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.activity.do_save_as_image_cb) self.insert(self.activity.save_as_image, -1) self.activity.save_as_image.show() @@ -1349,7 +1298,7 @@ class SaveAsToolbar(gtk.Toolbar): 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.activity.do_load_python_cb) self.insert(self.activity.load_python, -1) self.activity.load_python.show() @@ -1359,18 +1308,15 @@ class SaveAsToolbar(gtk.Toolbar): _("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.activity.do_load_ta_project_cb) self.insert(self.activity.load_ta_project, -1) self.activity.load_ta_project.show() -""" -Project toolbar: show/hide palettes; show/hide blocks; run; walk; stop; erase; - save as snapshot -""" class ProjectToolbar(gtk.Toolbar): def __init__(self, pc): + """ Project toolbar """ gtk.Toolbar.__init__(self) self.activity = pc @@ -1379,7 +1325,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.do_palette_cb) try: self.activity.palette_button.props.accelerator = _('p') except: @@ -1392,7 +1338,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.do_hideshow_cb) try: self.activity.blocks_button.props.accelerator = _('b') except: @@ -1409,7 +1355,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.run_button.connect('clicked', self.activity.do_run_cb) try: self.activity.run_button.props.accelerator = _('r') except: @@ -1421,7 +1367,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.step_button.connect('clicked', self.activity.do_step_cb) try: self.activity.step_button.props.accelerator = _('w') except: @@ -1434,7 +1380,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.do_debug_cb) try: self.activity.debug_button.props.accelerator = _('d') except: @@ -1446,7 +1392,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.stop_button.connect('clicked', self.activity.do_stop_cb) try: self.activity.stop_button.props.accelerator = _('s') except: @@ -1464,7 +1410,7 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.do_eraser_cb) try: self.activity.eraser_button.props.accelerator = _('e') except: @@ -1486,7 +1432,7 @@ class ProjectToolbar(gtk.Toolbar): except: pass self.activity.keep_button.connect('clicked', \ - self.activity._do_keep_cb) + self.activity.do_keep_cb) self.insert(self.activity.keep_button, -1) self.activity.keep_button.show() @@ -1500,9 +1446,9 @@ class ProjectToolbar(gtk.Toolbar): 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) + self.activity.do_samples_cb) try: - self.activity.samples_button.props.accelerator = _('o') + self.activity.samples_button.props.accelerator = _('o') except: pass self.insert(self.activity.samples_button, -1) diff --git a/tacanvas.py b/tacanvas.py index 5516327..3225491 100644 --- a/tacanvas.py +++ b/tacanvas.py @@ -31,11 +31,13 @@ from taconstants import CANVAS_LAYER, DEFAULT_TURTLE def wrap100(n): n = int(n) n %= 200 - if n>99: n=199-n + if n > 99: + n = 199-n return n -def calc_shade(c,s): - if s<0: return int(c*(1+s*.8)) +def calc_shade(c, s): + if s < 0: + return int(c*(1+s*.8)) return int(c+(65536-c)*s*.9) colors = {} @@ -78,14 +80,21 @@ class TurtleGraphics: self.canvas.set_layer(CANVAS_LAYER) self.gc = self.canvas.images[0].new_gc() self.cm = self.gc.get_colormap() - self.fgrgb = [255,0,0] + self.fgrgb = [255, 0, 0] self.fgcolor = self.cm.alloc_color('red') - self.bgrgb = [255,248,222] + self.bgrgb = [255, 248, 222] self.bgcolor = self.cm.alloc_color('#fff8de') self.textsize = 48 self.textcolor = self.cm.alloc_color('blue') self.tw.active_turtle.show() self.shade = 0 + self.pendown = True + self.xcor = 0 + self.ycor = 0 + self.heading = 0 + self.pensize = 5 + self.tcolor = 0 + self.color = 0 self.svg = SVG() self.svg.set_fill_color('none') self.tw.svg_string = '' @@ -136,10 +145,10 @@ class TurtleGraphics: def seth(self, n): try: - self.heading = n + self.heading = n except: pass - self.heading%=360 + self.heading %= 360 self.turn_turtle() def right(self, n): @@ -147,14 +156,14 @@ class TurtleGraphics: self.heading += n except: pass - self.heading%=360 + self.heading %= 360 self.turn_turtle() def arc(self, a, r): self.gc.set_foreground(self.fgcolor) r *= self.tw.coord_scale try: - if a<0: + if a < 0: self.larc(-a, r) else: self.rarc(a, r) @@ -164,23 +173,26 @@ class TurtleGraphics: self.turn_turtle() def rarc(self, a, r): - if r<0: - r=-r; a=-a + if r < 0: + r = -r + a = -a oldx, oldy = self.xcor, self.ycor - cx = self.xcor+r*cos(self.heading*DEGTOR) - cy = self.ycor-r*sin(self.heading*DEGTOR) - x,y = self.width/2+int(cx-r), self.height/2-int(cy+r) - w,h = int(2*r), int(2*r) + cx = self.xcor + r*cos(self.heading*DEGTOR) + cy = self.ycor - r*sin(self.heading*DEGTOR) + x = self.width/2 + int(cx-r) + y = self.height/2 - int(cy+r) + w = int(2*r) + h = w if self.pendown: self.canvas.images[0].draw_arc(self.gc, False, x, y, w, h, - int(180-self.heading-a)*64, int(a)*64) - self.invalt(x-self.pensize*self.tw.coord_scale/2-3, - y-self.pensize*self.tw.coord_scale/2-3, - w+self.pensize*self.tw.coord_scale+6, - h+self.pensize*self.tw.coord_scale+6) + int(180 - self.heading - a)*64, int(a)*64) + self.invalt(x - self.pensize*self.tw.coord_scale/2 - 3, + y - self.pensize*self.tw.coord_scale/2 - 3, + w + self.pensize*self.tw.coord_scale + 6, + h + self.pensize*self.tw.coord_scale + 6) self.right(a) - self.xcor=cx-r*cos(self.heading*DEGTOR) - self.ycor=cy+r*sin(self.heading*DEGTOR) + self.xcor = cx - r*cos(self.heading*DEGTOR) + self.ycor = cy + r*sin(self.heading*DEGTOR) if self.tw.saving_svg and self.pendown: self.tw.svg_string += self.svg.new_path(oldx, self.height/2-oldy) self.tw.svg_string += self.svg.arc_to(self.xcor, @@ -190,23 +202,26 @@ class TurtleGraphics: self.tw.svg_string += self.svg.style() def larc(self, a, r): - if r<0: - r=-r; a=-a + if r < 0: + r = -r + a = -a oldx, oldy = self.xcor, self.ycor - cx = self.xcor-r*cos(self.heading*DEGTOR) - cy = self.ycor+r*sin(self.heading*DEGTOR) - x,y = self.width/2+int(cx-r), self.height/2-int(cy+r) - w,h = int(2*r), int(2*r) + cx = self.xcor - r*cos(self.heading*DEGTOR) + cy = self.ycor + r*sin(self.heading*DEGTOR) + x = self.width/2 + int(cx-r) + y = self.height/2 - int(cy+r) + w = int(2*r) + h = w if self.pendown: - self.canvas.images[0].draw_arc(self.gc,False, x, y, w, h, + self.canvas.images[0].draw_arc(self.gc, False, x, y, w, h, int(360-self.heading)*64, int(a)*64) - self.invalt(x-self.pensize*self.tw.coord_scale/2-3, - y-self.pensize*self.tw.coord_scale/2-3, - w+self.pensize*self.tw.coord_scale+6, - h+self.pensize*self.tw.coord_scale+6) + self.invalt(x - self.pensize*self.tw.coord_scale/2 - 3, + y - self.pensize*self.tw.coord_scale/2 - 3, + w + self.pensize*self.tw.coord_scale + 6, + h + self.pensize*self.tw.coord_scale + 6) self.right(-a) - self.xcor=cx+r*cos(self.heading*DEGTOR) - self.ycor=cy-r*sin(self.heading*DEGTOR) + self.xcor = cx + r*cos(self.heading*DEGTOR) + self.ycor = cy - r*sin(self.heading*DEGTOR) if self.tw.saving_svg and self.pendown: self.tw.svg_string += self.svg.new_path(oldx, self.height/2-oldy) self.tw.svg_string += self.svg.arc_to(self.xcor, @@ -219,15 +234,15 @@ class TurtleGraphics: x *= self.tw.coord_scale y *= self.tw.coord_scale try: - self.xcor,self.ycor = x, y + self.xcor, self.ycor = x, y except: pass self.move_turtle() - def setpensize(self,ps): + def setpensize(self, ps): try: - if ps<0: - ps=0; + if ps < 0: + ps = 0 self.pensize = ps except: pass @@ -236,7 +251,7 @@ class TurtleGraphics: gtk.gdk.LINE_SOLID, gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_MITER) self.svg.set_stroke_width(self.pensize) - def setcolor(self,c): + def setcolor(self, c): try: self.color = c self.tcolor = c @@ -246,7 +261,7 @@ class TurtleGraphics: self.set_fgcolor() self.set_textcolor() - def settextcolor(self,c): + def settextcolor(self, c): try: self.tcolor = c except: @@ -269,36 +284,36 @@ class TurtleGraphics: self.set_textcolor() def fillscreen(self, c, s): - oldc, olds = self.color,self.shade + oldc, olds = self.color, self.shade self.setcolor(c); self.setshade(s) - rect = gtk.gdk.Rectangle(0,0,self.width,self.height) + rect = gtk.gdk.Rectangle(0, 0, self.width, self.height) self.gc.set_foreground(self.fgcolor) self.bgrgb = self.fgrgb[:] self.canvas.images[0].draw_rectangle(self.gc, True, *rect) - self.invalt(0,0,self.width,self.height) + self.invalt(0, 0, self.width, self.height) self.setcolor(oldc); self.setshade(olds) - self.svg_string = '' + self.tw.svg_string = '' self.svg.reset_min_max() def set_fgcolor(self): - sh = (wrap100(self.shade)-50)/50.0 + sh = (wrap100(self.shade) - 50)/50.0 rgb = color_table[wrap100(self.color)] - r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 - r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) - self.fgrgb = [r>>8,g>>8,b>>8] - self.fgcolor = self.cm.alloc_color(r,g,b) + r, g, b = (rgb>>8)&0xff00, rgb&0xff00, (rgb<<8)&0xff00 + r, g, b = calc_shade(r, sh), calc_shade(g, sh), calc_shade(b, sh) + self.fgrgb = [r>>8, g>>8, b>>8] + self.fgcolor = self.cm.alloc_color(r, g, b) self.svg.set_stroke_color("#%02x%02x%02x" % (self.fgrgb[0], self.fgrgb[1], self.fgrgb[2])) def set_textcolor(self): - sh = (wrap100(self.shade)-50)/50.0 + sh = (wrap100(self.shade) - 50)/50.0 rgb = color_table[wrap100(self.tcolor)] - r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 - r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) - self.tw.textcolor = self.cm.alloc_color(r,g,b) + r, g, b = (rgb>>8)&0xff00, rgb&0xff00, (rgb<<8)&0xff00 + r, g, b = calc_shade(r, sh), calc_shade(g, sh), calc_shade(b, sh) + self.tw.textcolor = self.cm.alloc_color(r, g, b) - def setpen(self,bool): + def setpen(self, bool): self.pendown = bool def draw_pixbuf(self, pixbuf, a, b, x, y, w, h, path): @@ -322,49 +337,51 @@ class TurtleGraphics: try: fd.set_size(int(size*self.tw.coord_scale)*pango.SCALE) except: - print "set size (%d) failed" % (int(size*self.tw.coord_scale)) pass if type(label) == str or type(label) == unicode: pl = self.tw.window.create_pango_layout(label.replace("\0"," ")) elif type(label) == float or type(label) == int: pl = self.tw.window.create_pango_layout(str(label)) else: - print "draw text: Type Error: %s" % (type(label)) pl = self.tw.window.create_pango_layout(str(label)) pl.set_font_description(fd) - pl.set_width(int(w)*pango.SCALE) - self.canvas.images[0].draw_layout(self.gc,int(x),int(y),pl) - w,h = pl.get_pixel_size() - self.invalt(x,y,w,h) + pl.set_width(int(w) * pango.SCALE) + self.canvas.images[0].draw_layout(self.gc, int(x), int(y), pl) + w, h = pl.get_pixel_size() + self.invalt(x, y, w, h) if self.tw.saving_svg and self.pendown: - self.tw.svg_string += self.svg.text(x-self.width/2, - y+size, + self.tw.svg_string += self.svg.text(x - self.width/2, + y + size, size, w, label) - def draw_line(self,x1,y1,x2,y2): - x1,y1 = self.width/2+int(x1), self.height/2-int(y1) - x2,y2 = self.width/2+int(x2), self.height/2-int(y2) - if x1\n", 'html': ("\n", "\n"), 'html_svg': ("\n", "\n"), 'head': ("\n\n", "\n"), - 'meta': "\n", 'title': ("", "\n"), 'style': ("\n"), - 'style_svg': ("\n"), 'body': ("\n", "\n\n"), 'div': ("
\n", "
\n"), 'slide': ("\n\n"), @@ -56,18 +49,24 @@ def save_html(self, tw, embed_flag=True): 'tr': ("\n", "\n"), 'td': ("\n", "\n\n"), - 'img': ("\"Image\"\n"), 'img2': ("\"Image\"\n"), 'img3': ("\"Image\"\n"), 'ul': ("\n", "
\n"), 'li': ("", "\n") } + comment = "\n" if self.embed_images == True: - self.html_glue['img'] = ("+\
+        self.html_glue['img'] = (\n") - self.html_glue['img2'] = ("\"Image\"\n") """ @@ -78,8 +77,8 @@ def save_html(self, tw, embed_flag=True): if len(tw.saved_pictures) > 0: for i, p in enumerate(tw.saved_pictures): code += self.html_glue['slide'][0] + str(i) - code += self.html_glue['slide'][1] +\ - self.html_glue['div'][0] +\ + code += self.html_glue['slide'][1] + \ + self.html_glue['div'][0] + \ self.html_glue['h1'][0] if self.embed_images == True: f = open(p, "r") @@ -103,8 +102,8 @@ def save_html(self, tw, embed_flag=True): tmp = self.html_glue['img3'][0] tmp += p tmp += self.html_glue['img3'][1] - code += tmp +\ - self.html_glue['h1'][1] +\ + code += tmp + \ + self.html_glue['h1'][1] + \ self.html_glue['div'][1] else: if self.embed_images == True: @@ -123,24 +122,25 @@ def save_html(self, tw, embed_flag=True): else: title = _("Turtle Art") - header = self.html_glue['doctype'] +\ + header = self.html_glue['doctype'] + \ self.html_glue['html'][0] - + style = self.html_glue['style'][0] + \ + self.html_glue['style'][1] if len(tw.saved_pictures) > 0: if tw.saved_pictures[0].endswith(('.svg')): header = self.html_glue['html_svg'][0] + style = comment - code = header +\ - self.html_glue['head'][0] +\ - self.html_glue['meta'] +\ - self.html_glue['title'][0] +\ - title +\ - self.html_glue['title'][1] +\ - self.html_glue['style'][0] +\ - self.html_glue['style'][1] +\ - self.html_glue['head'][1] +\ - self.html_glue['body'][0] +\ - code +\ - self.html_glue['body'][1] +\ + code = header + \ + self.html_glue['head'][0] + \ + self.html_glue['meta'] + \ + self.html_glue['title'][0] + \ + title + \ + self.html_glue['title'][1] + \ + style + \ + self.html_glue['head'][1] + \ + self.html_glue['body'][0] + \ + code + \ + self.html_glue['body'][1] + \ self.html_glue['html'][1] return code diff --git a/taexportlogo.py b/taexportlogo.py index 06fd061..2311872 100644 --- a/taexportlogo.py +++ b/taexportlogo.py @@ -22,15 +22,14 @@ IGNORE = ["hideblocks", "showblocks", "fullscreen", "polar", "cartesian", "sandwichbottom"] import math +from tautils import walk_stack try: from sugar.datastore import datastore except: pass -def save_logo(self, tw): - """ - We need to set up the Turtle Art color palette and color processing. - """ +def save_logo(tw): + """ We need to set up the Turtle Art color palette and color processing. """ color_processing = "\ to tasetpalette :i :r :g :b :myshade \r\ make \"s ((:myshade - 50) / 50) \r\ @@ -123,225 +122,215 @@ tasetshade :shade \r" Walk through the code, substituting UCB Logo for Turtle Art primitives. """ for b in bs: - this_stack = "" - data = walk_stack(self, tw, b) - # We need to catch several special cases: stacks, random, etc. - stack = False - namedstack = False - namedbox = False - refstack = False - refbox = False - myvar = "" - for d in data: - if type(d) == type((1,2)): - (d,b) = d - if type(d) is float: - if namedbox: - myvar += str(d) - myvar += " " - elif write: - this_stack += "labelsize " - this_stack += str(d) - write = False - else: - this_stack += str(d) - elif show == 2: - # Use title for Journal objects - if d[0:8] == '#smedia_': - try: - dsobject = datastore.get(d[8:]) - this_stack += dsobject.metadata['title'] - dsobject.destroy() - except: - this_stack += str(d) - else: - this_stack += str(d) - show = 0 - else: - # Translate some Turtle Art primitives into UCB Logo - if namedstack: - this_stack += "to " - this_stack += d[2:].replace(" ","_") - this_stack += "\r" - stack = True - namedstack = False - elif namedbox: - if d[0:2] == "#s": - this_stack += "make \"" - this_stack += d[2:].replace(" ","_") - this_stack += " " - this_stack += myvar - namedbox = False - myvar = "" - else: - myvar += d - elif refstack: - this_stack += d[2:].replace(" ","_") - this_stack += " " - refstack = False - elif refbox: - this_stack += ":" - this_stack += d[2:].replace(" ","_") - refbox = False - elif d == "stack": - refstack = True - elif d == "box": - refbox = True - elif d == "storeinbox": - namedbox = True - elif d == "storeinbox1": - this_stack += "make \"box1" - elif d == "box1": - this_stack += ":box1" - elif d == "storeinbox2": - this_stack += "make \"box2" - elif d == "box2": - this_stack += ":box2" - elif d == "shade": - this_stack += ":shade" - elif d == "setshade": - setcolor = True - this_stack += "tasetshade" - elif d == "color": - this_stack += "pencolor" - elif d == "nop": - this_stack += " " - elif d == "start": - this_stack += "to start\r" - stack = True - elif d == "nop1": - this_stack += "to stack1\r" - stack = True - elif d == "nop2": - this_stack += "to stack2\r" - stack = True - elif d == "nop3": - namedstack = True - elif d == "stopstack": - this_stack += "stop" - elif d == "clean": - this_stack += "clearscreen" - elif d == "setxy": - setxy = True - this_stack += "tasetxy" - elif d == "color": - this_stack += ":color" - elif d == "plus": - this_stack += "sum" - elif d == "setcolor": - setcolor = True - this_stack += "tasetpencolor" - elif d == "fillscreen": - fillscreen = True - setcolor = True - this_stack += "tasetbackground" - elif d == "random": - random = True - this_stack += "tarandom" - elif d == "pensize": - pensize = True - this_stack += "tapensize" - elif d == "arc": - arc = True - this_stack += "taarc" - elif d == "pop": - heap = True - this_stack += "tapop" - elif d == "push": - heap = True - this_stack += "tapush" - elif d == "heap": - heap = True - this_stack += "taprintheap" - elif d == "emptyheap": - heap = True - this_stack += "taclearheap" - elif d == "kbinput": - this_stack += "make \"keyboard readchar" - elif d == "keyboard": - this_stack += ":keyboard" - elif d == 'insertimage': - image = True - elif image: - # Skip this arg - image = 2 - elif image == 2: - # Skip this arg - image = False - elif d[0:2] == "#s": - # output single characters as a string - if len(d[2:]): - this_stack += "\"" - this_stack += d[2:] - # make a sentence out of everything else - else: - this_stack += "sentence " - this_stack += d[2:].replace("\s"," \"") - this_stack += "\r" - elif d == "write": - this_stack += "label" - write = True - elif d == 'show' or d == 'showaligned': - this_stack += "label" - show = 1 - elif d == "minus2": - this_stack == "taminus" - minus = True - elif d in IGNORE: - this_stack += " " - elif show == 1 and d[0:2] == "#s": - this_stack += d[2:] - # We don't handle depreciated 'template' blocks - else: - this_stack += d - this_stack += " " - if stack: - stack = False - # if it is not a stack, we need to add a "to ta#" label - elif len(data) > 0: - this_stack = "to ta" + str(stack_count) + "\r" + this_stack - stack_count += 1 - if len(data) > 0: - code += this_stack - code += "\rend\r" + this_stack = "" + data = walk_stack(tw, b) + # We need to catch several special cases: stacks, random, etc. + stack = False + namedstack = False + namedbox = False + refstack = False + refbox = False + myvar = "" + for d in data: + if type(d) == type((1, 2)): + (d, b) = d + if type(d) is float: + if namedbox: + myvar += str(d) + myvar += " " + elif write: + this_stack += "labelsize " + this_stack += str(d) + write = False + else: + this_stack += str(d) + elif show == 2: + # Use title for Journal objects + if d[0:8] == '#smedia_': + try: + dsobject = datastore.get(d[8:]) + this_stack += dsobject.metadata['title'] + dsobject.destroy() + except: + this_stack += str(d) + else: + this_stack += str(d) + show = 0 + else: + # Translate some Turtle Art primitives into UCB Logo + if namedstack: + this_stack += "to " + this_stack += d[2:].replace(" ","_") + this_stack += "\r" + stack = True + namedstack = False + elif namedbox: + if d[0:2] == "#s": + this_stack += "make \"" + this_stack += d[2:].replace(" ","_") + this_stack += " " + this_stack += myvar + namedbox = False + myvar = "" + else: + myvar += d + elif refstack: + this_stack += d[2:].replace(" ","_") + this_stack += " " + refstack = False + elif refbox: + this_stack += ":" + this_stack += d[2:].replace(" ","_") + refbox = False + elif d == "stack": + refstack = True + elif d == "box": + refbox = True + elif d == "storeinbox": + namedbox = True + elif d == "storeinbox1": + this_stack += "make \"box1" + elif d == "box1": + this_stack += ":box1" + elif d == "storeinbox2": + this_stack += "make \"box2" + elif d == "box2": + this_stack += ":box2" + elif d == "shade": + this_stack += ":shade" + elif d == "setshade": + setcolor = True + this_stack += "tasetshade" + elif d == "color": + this_stack += "pencolor" + elif d == "nop": + this_stack += " " + elif d == "start": + this_stack += "to start\r" + stack = True + elif d == "nop1": + this_stack += "to stack1\r" + stack = True + elif d == "nop2": + this_stack += "to stack2\r" + stack = True + elif d == "nop3": + namedstack = True + elif d == "stopstack": + this_stack += "stop" + elif d == "clean": + this_stack += "clearscreen" + elif d == "setxy": + setxy = True + this_stack += "tasetxy" + elif d == "color": + this_stack += ":color" + elif d == "plus": + this_stack += "sum" + elif d == "setcolor": + setcolor = True + this_stack += "tasetpencolor" + elif d == "fillscreen": + fillscreen = True + setcolor = True + this_stack += "tasetbackground" + elif d == "random": + random = True + this_stack += "tarandom" + elif d == "pensize": + pensize = True + this_stack += "tapensize" + elif d == "arc": + arc = True + this_stack += "taarc" + elif d == "pop": + heap = True + this_stack += "tapop" + elif d == "push": + heap = True + this_stack += "tapush" + elif d == "heap": + heap = True + this_stack += "taprintheap" + elif d == "emptyheap": + heap = True + this_stack += "taclearheap" + elif d == "kbinput": + this_stack += "make \"keyboard readchar" + elif d == "keyboard": + this_stack += ":keyboard" + elif d == 'insertimage': + image = True + elif image: + # Skip this arg + image = 2 + elif image == 2: + # Skip this arg + image = False + elif d[0:2] == "#s": + # output single characters as a string + if len(d[2:]): + this_stack += "\"" + this_stack += d[2:] + # make a sentence out of everything else + else: + this_stack += "sentence " + this_stack += d[2:].replace("\s"," \"") + this_stack += "\r" + elif d == "write": + this_stack += "label" + write = True + elif d == 'show' or d == 'showaligned': + this_stack += "label" + show = 1 + elif d == "minus2": + this_stack == "taminus" + minus = True + elif d in IGNORE: + this_stack += " " + elif show == 1 and d[0:2] == "#s": + this_stack += d[2:] + # We don't handle depreciated 'template' blocks + else: + this_stack += d + this_stack += " " + if stack: + stack = False + # if it is not a stack, we need to add a "to ta#" label + elif len(data) > 0: + this_stack = "to ta" + str(stack_count) + "\r" + this_stack + stack_count += 1 + if len(data) > 0: + code += this_stack + code += "\rend\r" # We need to define some additional procedures. if minus: # Logo minus only takes one argument. code = "to taminus :y :x\routput sum :x minus :y\rend\r" + code if random: # to avoid negative numbers - code = "to tarandom :min :max\r" + \ - "output (random (:max - :min)) + :min\rend\r" +\ - code + code = "to tarandom :min :max\r" + \ + "output (random (:max - :min)) + :min\rend\r" + code if fillscreen: # Set shade than background color - code = "to tasetbackground :color :shade\r" + \ - "tasetshade :shade\rsetbackground :color\rend\r" + \ - code + code = "to tasetbackground :color :shade\r" + \ + "tasetshade :shade\rsetbackground :color\rend\r" + code if setcolor: # Load the Turtle Art color palette. - code = color_processing + code + code = color_processing + code if pensize: # Return only the first argument. - code = "to tapensize\routput first round pensize\rend\r" + code + code = "to tapensize\routput first round pensize\rend\r" + code if setxy: # Swap and round arguments - code = "to tasetxy :x :y\rpenup\rsetxy :x :y\rpendown\rend\r" + code + code = "to tasetxy :x :y\rpenup\rsetxy :x :y\rpendown\rend\r" + code if arc: # Turtle Art 'arc' needs to be redefined. - c = (2 * math.pi)/360 - code = "to taarc :a :r\rrepeat round :a [right 1 forward (" +\ - str(c) + " * :r)]\rend\r" + code + c = (2 * math.pi)/360 + code = "to taarc :a :r\rrepeat round :a [right 1 forward (" + \ + str(c) + " * :r)]\rend\r" + code if heap: # Add psuedo 'push' and 'pop' - code = "to tapush :foo\rmake \"taheap fput :foo :taheap\rend\r" + \ - "to tapop\rif emptyp :taheap [stop]\rmake \"tmp first :taheap\r" +\ - "make \"taheap butfirst :taheap\routput :tmp\rend\r" + \ - "to taclearheap\rmake \"taheap []\rend\r" + \ - "to taprintheap \rprint :taheap\rend\r" + \ - "make \"taheap []\r" + code + code = "to tapush :foo\rmake \"taheap fput :foo :taheap\rend\r" + \ + "to tapop\rif emptyp :taheap [stop]\rmake \"tmp first :taheap\r" + \ + "make \"taheap butfirst :taheap\routput :tmp\rend\r" + \ + "to taclearheap\rmake \"taheap []\rend\r" + \ + "to taprintheap \rprint :taheap\rend\r" + \ + "make \"taheap []\r" + code code = "window\r" + code return code -def walk_stack(self, tw, blk): - top = tw.find_top_block(blk) - if blk == top: - code = tw.lc.run_blocks(top, tw.block_list.list, False) - return code - else: - return [] - diff --git a/talogo.py b/talogo.py index 54cb7fb..99c2725 100644 --- a/talogo.py +++ b/talogo.py @@ -22,28 +22,25 @@ #THE SOFTWARE. import gtk -import gobject from time import clock from math import sqrt from random import uniform from operator import isNumberType -import audioop -import subprocess from UserDict import UserDict try: from sugar.datastore import datastore except: pass -from taconstants import PALETTES, PALETTE_NAMES, BOX_STYLE, TAB_LAYER +from taconstants import PALETTES, PALETTE_NAMES, TAB_LAYER from tagplay import play_audio, play_movie_from_file, stop_media from tajail import myfunc, myfunc_import -from tautils import get_pixbuf_from_journal, movie_media_type,\ +from tautils import get_pixbuf_from_journal, movie_media_type, convert, \ audio_media_type, text_media_type, round_int from gettext import gettext as _ class noKeyError(UserDict): - __missing__=lambda x,y: 0 + __missing__ = lambda x, y: 0 class symbol: def __init__(self, name): @@ -54,7 +51,7 @@ class symbol: def __str__(self): return self.name def __repr__(self): - return '#'+self.name + return '#' + self.name class logoerror(Exception): def __init__(self, value): @@ -62,28 +59,10 @@ class logoerror(Exception): def __str__(self): return repr(self.value) -""" -Utility functions -""" - -''' -The strategy for mixing numbers and strings is to first try -converting the string to a float; then if the string is a single -character, try converting it to an ord; finally, just treat it as a -string. Numbers appended to strings are first trreated as ints, then -floats. -''' -def convert(x, fn, try_ord=True): - try: - return fn(x) - except ValueError: - if try_ord: - xx, flag = chr_to_ord(x) - if flag: - return fn(xx) - return x +# Utility functions def numtype(x): + """ Is x a number type? """ if type(x) == int: return True if type(x) == float: @@ -93,6 +72,7 @@ def numtype(x): return False def strtype(x): + """ Is x a string type? """ if type(x) == str: return True if type(x) == unicode: @@ -100,6 +80,7 @@ def strtype(x): return False def str_to_num(x): + """ Try to comvert a string to a number """ xx = convert(x, float) if type(xx) is float: return xx @@ -111,6 +92,7 @@ def str_to_num(x): raise logoerror("#syntaxerror") def chr_to_ord(x): + """ Try to comvert a string to an ord """ if strtype(x) and len(x) == 1: try: return ord(x[0]), True @@ -119,12 +101,15 @@ def chr_to_ord(x): return x, False def taand(x, y): + """ Logical and """ return x&y def taor(x, y): + """ Logical or """ return x|y def careful_divide(x, y): + """ Raise error on divide by zero """ try: return x/y except ZeroDivisionError: @@ -138,6 +123,7 @@ def careful_divide(x, y): raise logoerror("#syntaxerror") def taequal(x, y): + """ Numeric and logical equal """ try: return float(x)==float(y) except TypeError: @@ -154,6 +140,7 @@ def taequal(x, y): raise logoerror("#syntaxerror") def taless(x, y): + """ Compare numbers and strings """ try: return float(x)0: # Extract the value from content blocks. - if blk.name=='number': + if blk.name == 'number': try: code.append(float(blk.values[0])) except ValueError: code.append(float(ord(blk.values[0][0]))) - elif blk.name=='string' or blk.name=='title': + elif blk.name == 'string' or blk.name == 'title': if type(blk.values[0]) == float or type(blk.values[0]) == int: if int(blk.values[0]) == blk.values[0]: blk.values[0] = int(blk.values[0]) code.append('#s'+str(blk.values[0])) else: code.append('#s'+blk.values[0]) - elif blk.name=='journal': + elif blk.name == 'journal': if blk.values[0] is not None: code.append('#smedia_'+str(blk.values[0])) else: code.append('#smedia_None') - elif blk.name=='description': + elif blk.name == 'description': if blk.values[0] is not None: code.append('#sdescr_'+str(blk.values[0])) else: code.append('#sdescr_None') - elif blk.name=='audio': + elif blk.name == 'audio': if blk.values[0] is not None: code.append('#saudio_'+str(blk.values[0])) else: @@ -533,14 +524,12 @@ class LogoCode: code.append('%nothing%') return code - """ - Execute the psuedocode. - """ - def setup_cmd(self, str): + def setup_cmd(self, string): + """ Execute the psuedocode. """ self.tw.active_turtle.hide() # Hide the turtle while we are running. self.procstop = False - list = self.readline(str) - self.step = self.start_eval(list) + blklist = self.readline(string) + self.step = self.start_eval(blklist) """ Convert the pseudocode into a list of commands. @@ -553,12 +542,12 @@ class LogoCode: token = line.pop(0) bindex = None if type(token) == tuple: - (token, bindex) = token + (token, bindex) = token if isNumberType(token): res.append(token) elif token.isdigit(): res.append(float(token)) - elif token[0]=='-' and token[1:].isdigit(): + elif token[0] == '-' and token[1:].isdigit(): res.append(-float(token[1:])) elif token[0] == '"': res.append(token[1:]) @@ -574,16 +563,14 @@ class LogoCode: res.append((self.intern(token), bindex)) return res - """ - Step through the list. - """ - def start_eval(self, list): + def start_eval(self, blklist): + """ Step through the list. """ if self.tw.running_sugar: self.tw.activity.stop_button.set_icon("stopiton") else: self.tw.toolbar_shapes['stopiton'].set_layer(TAB_LAYER) self.running = True - self.icall(self.evline, list) + self.icall(self.evline, blklist) yield True if self.tw.running_sugar: self.tw.activity.stop_button.set_icon("stopitoff") @@ -592,19 +579,15 @@ class LogoCode: yield False self.running = False - """ - Add a function and its arguments to the program stack. - """ def icall(self, fcn, *args): + """ Add a function and its arguments to the program stack. """ self.istack.append(self.step) self.step = fcn(*(args)) - """ - Evaluate a line of code from the list. - """ - def evline(self, list): + def evline(self, blklist): + """ Evaluate a line of code from the list. """ oldiline = self.iline - self.iline = list[:] + self.iline = blklist[:] self.arglist = None while self.iline: token = self.iline[0] @@ -652,10 +635,8 @@ class LogoCode: self.tw.display_coordinates() yield True - """ - Evaluate the next token on the line of code we are processing. - """ def eval(self): + """ Evaluate the next token on the line of code we are processing. """ token = self.iline.pop(0) bindex = None if type(token) == tuple: @@ -680,10 +661,8 @@ class LogoCode: self.ireturn(res) yield True - """ - Process primitive associated with symbol token - """ def evalsym(self, token): + """ Process primitive associated with symbol token """ self.debug_trace(token) self.undefined_check(token) oldcfun, oldarglist = self.cfun, self.arglist @@ -717,11 +696,12 @@ class LogoCode: yield True def ufuncall(self, body): - print "ufuncall: ", self.evline, body - ijmp(self.evline, body) + """ ufuncall """ + self.ijmp(self.evline, body) yield True def doevalstep(self): + """ evaluate one step """ starttime = millis() try: while (millis()-starttime)<120: @@ -740,18 +720,19 @@ class LogoCode: return True def ireturn(self, res=None): + """ return value """ self.step = self.istack.pop() - # print "ireturn: ", self.step self.iresult = res def ijmp(self, fcn, *args): - # print "ijmp: ", fcn, args + """ ijmp """ self.step = fcn(*(args)) def debug_trace(self, token): + """ Display debugging information """ if self.trace: if token.name in PALETTES[PALETTE_NAMES.index('turtle')]: - my_string = "%s\n%s=%d\n%s=%d\n%s=%d\n%s=%d" %\ + my_string = "%s\n%s=%d\n%s=%d\n%s=%d\n%s=%d" % \ (token.name, _('xcor'), int(self.tw.canvas.xcor), _('ycor'), int(self.tw.canvas.ycor), _('heading'), int(self.tw.canvas.heading), _('scale'), int(self.scale)) @@ -760,7 +741,7 @@ class LogoCode: penstatus = _('pen down') else: penstatus = _('pen up') - my_string = "%s\n%s\n%s=%d\n%s=%d\n%s=%.1f" %\ + my_string = "%s\n%s\n%s=%d\n%s=%d\n%s=%.1f" % \ (token.name, penstatus, _('color'), int(self.tw.canvas.color), _('shade'), int(self.tw.canvas.shade), _('pen size'), @@ -769,10 +750,11 @@ class LogoCode: my_string = "%s\n" % (token.name) for k, v in self.boxes.iteritems(): my_string += "%s: %s\n" % (k, str(v)) - self.tw.showlabel('info',my_string) + self.tw.showlabel('info', my_string) return def undefined_check(self, token): + """ Make sure token has a definition """ if token.fcn is not None: return False if token.name == '%nothing%': @@ -782,6 +764,7 @@ class LogoCode: raise logoerror(errormsg) def no_args_check(self): + """ Missing argument ? """ if self.iline and self.iline[0] is not self.symnothing: return raise logoerror("#noinput") @@ -791,14 +774,17 @@ class LogoCode: # def prim_clear(self): + """ Clear screen """ stop_media(self) self.tw.canvas.clearscreen() def prim_start(self): + """ Start block: recenter """ if self.tw.running_sugar: self.tw.activity.recenter() def prim_wait(self, time): + """ Show the turtle while we wait """ self.tw.active_turtle.show() endtime = millis()+self.an_int(time*1000) while millis() %d" % (heading, i) def set_color(self, color): + """ Set the pen color for this turtle. """ self.pen_color = color def set_shade(self, shade): + """ Set the pen shade for this turtle. """ self.pen_shade = shade def set_pen_size(self, pen_size): + """ Set the pen size for this turtle. """ self.pen_size = pen_size def set_pen_state(self, pen_state): + """ Set the pen state (down==True) for this turtle. """ self.pen_state = pen_state def hide(self): + """ Hide the turtle. """ self.spr.hide() self.hidden = True def show(self): + """ Show the turtle. """ self.spr.set_layer(TURTLE_LAYER) self.hidden = False self.move((self.x, self.y)) self.set_heading(self.heading) def move(self, pos): + """ Move the turtle. """ self.x, self.y = pos[0], pos[1] if self.hidden is False: self.spr.move(pos) + return(self.x, self.y) def get_xy(self): + """ Return the turtle's x, y coordinates. """ return(self.x, self.y) def get_heading(self): + """ Return the turtle's heading. """ return(self.heading) def get_color(self): + """ Return the turtle's color. """ return(self.pen_color) def get_shade(self): + """ Return the turtle's shade. """ return(self.pen_shade) def get_pen_size(self): + """ Return the turtle's pen size. """ return(self.pen_size) def get_pen_state(self): + """ Return the turtle's pen state. """ return(self.pen_state) diff --git a/tautils.py b/tautils.py index ab2904f..a0361e8 100644 --- a/tautils.py +++ b/tautils.py @@ -23,7 +23,7 @@ import gtk import pickle import subprocess try: - _old_Sugar_system = False + OLD_SUGAR_SYSTEM = False import json json.dumps from json import load as jload @@ -34,140 +34,175 @@ except (ImportError, AttributeError): from simplejson import load as jload from simplejson import dump as jdump except: - _old_Sugar_system = True - + OLD_SUGAR_SYSTEM = True +from taconstants import STRING_OR_NUMBER_ARGS, HIDE_LAYER, CONTENT_ARGS, \ + COLLAPSIBLE, BLOCK_LAYER, CONTENT_BLOCKS from StringIO import StringIO import os.path +from gettext import gettext as _ + + +''' +The strategy for mixing numbers and strings is to first try +converting the string to a float; then if the string is a single +character, try converting it to an ord; finally, just treat it as a +string. Numbers appended to strings are first trreated as ints, then +floats. +''' +def convert(x, fn, try_ord=True): + try: + return fn(x) + except ValueError: + if try_ord: + xx, flag = chr_to_ord(x) + if flag: + return fn(xx) + return x def magnitude(pos): + """ Calculate the magnitude of the distance between to blocks. """ x, y = pos return x*x+y*y def json_load(text): - if _old_Sugar_system is True: - listdata = json.read(text) + """ Load JSON data using what ever resources are available. """ + if OLD_SUGAR_SYSTEM is True: + _listdata = json.read(text) else: # strip out leading and trailing whitespace, nulls, and newlines text = text.lstrip() text = text.replace('\12','') text = text.replace('\00','') - io = StringIO(text.rstrip()) - listdata = jload(io) + _io = StringIO(text.rstrip()) + _listdata = jload(_io) # json converts tuples to lists, so we need to convert back, - return _tuplify(listdata) + return _tuplify(_listdata) -def _tuplify(t): - if type(t) is not list: - return t - return tuple(map(_tuplify, t)) +def _tuplify(tup): + """ Convert to tuples """ + if type(tup) is not list: + return tup + return tuple(map(_tuplify, tup)) -def get_id(c): - if c is None: +def get_id(connection): + """ Get a connection block ID. """ + if connection is None: return None - return c.id + return connection.id def json_dump(data): - if _old_Sugar_system is True: + """ Save data using available JSON tools. """ + if OLD_SUGAR_SYSTEM is True: return json.write(data) else: - io = StringIO() - jdump(data,io) - return io.getvalue() + _io = StringIO() + jdump(data, _io) + return _io.getvalue() def get_load_name(suffix, load_save_folder): - dialog = gtk.FileChooserDialog("Load...", None, - gtk.FILE_CHOOSER_ACTION_OPEN, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) - return do_dialog(dialog, suffix, load_save_folder) + """ Open a load file dialog. """ + _dialog = gtk.FileChooserDialog("Load...", None, + gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + _dialog.set_default_response(gtk.RESPONSE_OK) + return do_dialog(_dialog, suffix, load_save_folder) def get_save_name(suffix, load_save_folder, save_file_name): - dialog = gtk.FileChooserDialog("Save...", None, - gtk.FILE_CHOOSER_ACTION_SAVE, - (gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_SAVE, - gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) + """ Open a save file dialog. """ + _dialog = gtk.FileChooserDialog("Save...", None, + gtk.FILE_CHOOSER_ACTION_SAVE, + (gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE, + gtk.RESPONSE_OK)) + _dialog.set_default_response(gtk.RESPONSE_OK) if save_file_name is not None: - dialog.set_current_name(save_file_name+suffix) - return do_dialog(dialog, suffix, load_save_folder) + _dialog.set_current_name(save_file_name+suffix) + return do_dialog(_dialog, suffix, load_save_folder) # # We try to maintain read-compatibility with all versions of Turtle Art. # Try pickle first; then different versions of json. # def data_from_file(ta_file): - # Just open the .ta file, ignoring any .png file that might be present. - f = open(ta_file, "r") + """ Open the .ta file, ignoring any .png file that might be present. """ + file_handle = open(ta_file, "r") try: - data = pickle.load(f) + _data = pickle.load(file_handle) except: # Rewind necessary because of failed pickle.load attempt - f.seek(0) - text = f.read() - data = data_from_string(text) - f.close() - return data + file_handle.seek(0) + _text = file_handle.read() + _data = data_from_string(_text) + file_handle.close() + return _data def data_from_string(text): + """ JSON load data from a string. """ return json_load(text) def data_to_file(data, ta_file): - f = file(ta_file, "w") - f.write(data_to_string(data)) - f.close() + """ Write data to a file. """ + file_handle = file(ta_file, "w") + file_handle.write(data_to_string(data)) + file_handle.close() def data_to_string(data): + """ JSON dump a string. """ return json_dump(data) def do_dialog(dialog, suffix, load_save_folder): - result = None - filter = gtk.FileFilter() - filter.add_pattern('*'+suffix) - filter.set_name("Turtle Art") - dialog.add_filter(filter) + """ Open a file dialog. """ + _result = None + file_filter = gtk.FileFilter() + file_filter.add_pattern('*'+suffix) + file_filter.set_name("Turtle Art") + dialog.add_filter(file_filter) dialog.set_current_folder(load_save_folder) - response = dialog.run() - if response == gtk.RESPONSE_OK: - result = dialog.get_filename() + _response = dialog.run() + if _response == gtk.RESPONSE_OK: + _result = dialog.get_filename() load_save_folder = dialog.get_current_folder() dialog.destroy() - return result, load_save_folder - -def save_picture(canvas, fname=''): - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, canvas.width, - canvas.height) - pixbuf.get_from_drawable(canvas.canvas.images[0], - canvas.canvas.images[0].get_colormap(), - 0, 0, 0, 0, canvas.width, canvas.height) - if fname != '': - pixbuf.save(fname, 'png') - return pixbuf - -def save_svg(string, fname): - f = file(fname, "w") - f.write(string) - f.close() + return _result, load_save_folder + +def save_picture(canvas, file_name=''): + """ Save the canvas to a file. """ + _pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, canvas.width, + canvas.height) + _pixbuf.get_from_drawable(canvas.canvas.images[0], + canvas.canvas.images[0].get_colormap(), + 0, 0, 0, 0, canvas.width, canvas.height) + if file_name != '': + _pixbuf.save(file_name, 'png') + return _pixbuf + +def save_svg(string, file_name): + """ Write a string to a file. """ + file_handle = file(file_name, "w") + file_handle.write(string) + file_handle.close() def get_pixbuf_from_journal(dsobject, w, h): + """ Load a pixbuf from a Journal object. """ try: - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(dsobject.file_path, - int(w),int(h)) + _pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(dsobject.file_path, + int(w), int(h)) except: try: - pixbufloader = \ + _pixbufloader = \ gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - pixbufloader.set_size(min(300,int(w)),min(225,int(h))) - pixbufloader.write(dsobject.metadata['preview']) - pixbufloader.close() - pixbuf = pixbufloader.get_pixbuf() + _pixbufloader.set_size(min(300, int(w)), min(225, int(h))) + _pixbufloader.write(dsobject.metadata['preview']) + _pixbufloader.close() + _pixbuf = _pixbufloader.get_pixbuf() except: - pixbuf = None - return pixbuf + _pixbuf = None + return _pixbuf def get_path(activity, subpath ): + """ Find a Rainbow-approved place for temporary files. """ try: return(os.path.join(activity.get_activity_root(), subpath)) except: @@ -176,43 +211,456 @@ def get_path(activity, subpath ): "org.laptop.TurtleArtActivity", subpath)) def image_to_base64(pixbuf, activity): - filename = os.path.join(get_path(activity, 'instance'), 'imagetmp.png') + """ Convert an image to base64 """ + _file_name = os.path.join(get_path(activity, 'instance'), 'imagetmp.png') if pixbuf != None: - pixbuf.save(filename, "png") - base64 = os.path.join(get_path(activity, 'instance'), 'base64tmp') - cmd = "base64 <" + filename + " >" + base64 - subprocess.check_call(cmd, shell=True) - f = open( base64, 'r') - data = f.read() - f.close() - return data + pixbuf.save(_file_name, "png") + _base64 = os.path.join(get_path(activity, 'instance'), 'base64tmp') + _cmd = "base64 <" + _file_name + " >" + _base64 + subprocess.check_call(_cmd, shell=True) + _file_handle = open(_base64, 'r') + _data = _file_handle.read() + _file_handle.close() + return _data def movie_media_type(name): - return name.endswith(('.ogv','.vob','.mp4','.wmv','.mov', '.mpeg')) + """ Is it movie media? """ + return name.endswith(('.ogv', '.vob', '.mp4', '.wmv', '.mov', '.mpeg')) def audio_media_type(name): + """ Is it audio media? """ return name.endswith(('.ogg', '.oga', '.m4a')) def image_media_type(name): + """ Is it image media? """ return name.endswith(('.png', '.jpg', '.jpeg', '.gif', '.tiff', '.tif', '.svg')) def text_media_type(name): + """ Is it text media? """ return name.endswith(('.txt', '.py', '.lg', '.doc', '.rtf')) -def round_int(n): - if int(float(n)) == n: - return int(n) +def round_int(num): + """ Remove trailing decimal places if number is an int """ + if int(float(num)) == num: + return int(num) else: - nn = int(float(n+0.05)*10)/10. - if int(float(nn)) == nn: - return int(nn) - return nn + _nn = int(float(num+0.05)*10)/10. + if int(float(_nn)) == _nn: + return int(_nn) + return _nn + +def calc_image_size(spr): + """ Calculate the maximum size for placing an image onto a sprite. """ + return spr.label_safe_width(), spr.label_safe_height() + + + +# Collapsible stacks live between 'sandwichtop' and 'sandwichbottom' blocks + +def reset_stack_arm(top): + """ When we undock, retract the 'arm' that extends from 'sandwichtop'. """ + if top is not None and top.name == 'sandwichtop': + if top.ey > 0: + top.reset_y() + +def grow_stack_arm(top): + """ When we dock, grow an 'arm' from 'sandwichtop'. """ + if top is not None and top.name == 'sandwichtop': + _bot = find_sandwich_bottom(top) + if _bot is None: + return + if top.ey > 0: + top.reset_y() + _ty = top.spr.get_xy()[1] + _th = top.spr.get_dimensions()[1] + _by = _bot.spr.get_xy()[1] + _dy = _by-(_ty + _th) + if _dy > 0: + top.expand_in_y(_dy/top.scale) + top.refresh() + +def find_sandwich_top(blk): + """ Find the sandwich top above this block. """ + # Always follow the main branch of a flow: the first connection. + _blk = blk.connections[0] + while _blk is not None: + if _blk.name in COLLAPSIBLE: + return None + if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while']: + if blk != _blk.connections[len(_blk.connections) - 1]: + return None + if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': + return _blk + blk = _blk + _blk = _blk.connections[0] + return None + +def find_sandwich_bottom(blk): + """ Find the sandwich bottom below this block. """ + # Always follow the main branch of a flow: the last connection. + _blk = blk.connections[len(blk.connections) - 1] + while _blk is not None: + if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': + return None + if _blk.name in COLLAPSIBLE: + return _blk + _blk = _blk.connections[len(_blk.connections) - 1] + return None + +def find_sandwich_top_below(blk): + """ Find the sandwich top below this block. """ + if blk.name == 'sandwichtop' or blk.name == 'sandwichtop2': + return blk + # Always follow the main branch of a flow: the last connection. + _blk = blk.connections[len(blk.connections) - 1] + while _blk is not None: + if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': + return _blk + _blk = _blk.connections[len(_blk.connections) - 1] + return None + +def restore_stack(top): + """ Restore the blocks between the sandwich top and sandwich bottom. """ + _group = find_group(top.connections[len(top.connections) - 1]) + _hit_bottom = False + _bot = find_sandwich_bottom(top) + for _blk in _group: + if not _hit_bottom and _blk == _bot: + _hit_bottom = True + if len(_blk.values) == 0: + _blk.values.append(0) + else: + _blk.values[0] = 0 + _olddx = _blk.docks[1][2] + _olddy = _blk.docks[1][3] + # Replace 'sandwichcollapsed' shape with 'sandwichbottom' shape + _blk.name = 'sandwichbottom' + _blk.spr.set_label(' ') + _blk.svg.set_show(False) + _blk.svg.set_hide(True) + _blk.refresh() + # Redock to previous block in group + _you = _blk.connections[0] + (_yx, _yy) = _you.spr.get_xy() + _yd = _you.docks[len(_you.docks) - 1] + (_bx, _by) = _blk.spr.get_xy() + _dx = _yx + _yd[2] - _blk.docks[0][2] - _bx + _dy = _yy + _yd[3] - _blk.docks[0][3] - _by + _blk.spr.move_relative((_dx, _dy)) + # Since the shapes have changed, the dock positions have too. + _newdx = _blk.docks[1][2] + _newdy = _blk.docks[1][3] + _dx += _newdx - _olddx + _dy += _newdy - _olddy + else: + if not _hit_bottom: + _blk.spr.set_layer(BLOCK_LAYER) + _blk.status = None + else: + _blk.spr.move_relative((_dx, _dy)) + # Add 'sandwichtop' arm + top.name = 'sandwichtop' + top.refresh() + grow_stack_arm(top) + +def uncollapse_forks(top, looping=False): + """ From the top, find and restore any collapsible stacks on forks. """ + if top == None: + return + if looping and top.name == 'sandwichtop' or top.name == 'sandwichtop2': + restore_stack(top) + return + if len(top.connections) == 0: + return + _blk = top.connections[len(top.connections) - 1] + while _blk is not None: + if _blk.name in COLLAPSIBLE: + return + if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': + restore_stack(_blk) + return + # Follow a fork + if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while', 'until']: + top = find_sandwich_top_below( + _blk.connections[len(_blk.connections) - 2]) + if top is not None: + uncollapse_forks(top, True) + if _blk.name == 'ifelse': + top = find_sandwich_top_below( + _blk.connections[len(_blk.connections) - 3]) + if top is not None: + uncollapse_forks(top, True) + _blk = _blk.connections[len(_blk.connections) - 1] + return + +def collapse_stack(top): + """ Hide all the blocks between the sandwich top and sandwich bottom. """ + # First uncollapse any nested stacks + uncollapse_forks(top) + _hit_bottom = False + _bot = find_sandwich_bottom(top) + _group = find_group(top.connections[len(top.connections) - 1]) + for _blk in _group: + if not _hit_bottom and _blk == _bot: + _hit_bottom = True + # Replace 'sandwichbottom' shape with 'sandwichcollapsed' shape + if len(_blk.values) == 0: + _blk.values.append(1) + else: + _blk.values[0] = 1 + _olddx = _blk.docks[1][2] + _olddy = _blk.docks[1][3] + _blk.name = 'sandwichcollapsed' + _blk.svg.set_show(True) + _blk.svg.set_hide(False) + _blk._dx = 0 + _blk._ey = 0 + _blk.spr.set_label(' ') + _blk.resize() + _blk.spr.set_label(_('click to open')) + _blk.resize() + # Redock to sandwich top in group + _you = find_sandwich_top(_blk) + (_yx, _yy) = _you.spr.get_xy() + _yd = _you.docks[len(_you.docks) - 1] + (_bx, _by) = _blk.spr.get_xy() + _dx = _yx + _yd[2] - _blk.docks[0][2] - _bx + _dy = _yy + _yd[3] - _blk.docks[0][3] - _by + _blk.spr.move_relative((_dx, _dy)) + # Since the shapes have changed, the dock positions have too. + _newdx = _blk.docks[1][2] + _newdy = _blk.docks[1][3] + _dx += _newdx - _olddx + _dy += _newdy - _olddy + else: + if not _hit_bottom: + _blk.spr.set_layer(HIDE_LAYER) + _blk.status = 'collapsed' + else: + _blk.spr.move_relative((_dx, _dy)) + # Remove 'sandwichtop' arm + top.name = 'sandwichtop2' + top.refresh() + +def collapsed(blk): + """ Is this stack collapsed? """ + if blk is not None and blk.name in COLLAPSIBLE and\ + len(blk.values) == 1 and blk.values[0] != 0: + return True + return False + +def collapsible(blk): + """ Can this stack be collapsed? """ + if blk is None or blk.name not in COLLAPSIBLE: + return False + if find_sandwich_top(blk) is None: + return False + return True + +def hide_button_hit(spr, x, y): + """ Did the sprite's hide (contract) button get hit? """ + _red, _green, _blue, _alpha = spr.get_pixel((x, y)) + if (_red == 255 and _green == 0) or _green == 255: + return True + else: + return False + +def show_button_hit(spr, x, y): + """ Did the sprite's show (expand) button get hit? """ + _red, _green, _blue, _alpha = spr.get_pixel((x, y)) + if _green == 254: + return True + else: + return False + +def numeric_arg(value): + """ Dock test: looking for a numeric value """ + if type(convert(value, float)) is float: + return True + return False + +def zero_arg(value): + """ Dock test: looking for a zero argument """ + if numeric_arg(value): + if convert(value, float) == 0: + return True + return False + +def neg_arg(value): + """ Dock test: looking for a negative argument """ + if numeric_arg(value): + if convert(value, float) < 0: + return True + return False + +def dock_dx_dy(block1, dock1n, block2, dock2n): + """ Find the distance between the dock points of two blocks. """ + _dock1 = block1.docks[dock1n] + _dock2 = block2.docks[dock2n] + _d1type, _d1dir, _d1x, _d1y = _dock1[0:4] + _d2type, _d2dir, _d2x, _d2y = _dock2[0:4] + if block1 == block2: + return (100, 100) + if _d1dir == _d2dir: + return (100, 100) + if (_d2type is not 'number') or (dock2n is not 0): + if block1.connections is not None and \ + dock1n < len(block1.connections) and \ + block1.connections[dock1n] is not None: + return (100, 100) + if block2.connections is not None and \ + dock2n < len(block2.connections) and \ + block2.connections[dock2n] is not None: + return (100, 100) + if _d1type != _d2type: + if block1.name in STRING_OR_NUMBER_ARGS: + if _d2type == 'number' or _d2type == 'string': + pass + elif block1.name in CONTENT_ARGS: + if _d2type in CONTENT_BLOCKS: + pass + else: + return (100, 100) + (_b1x, _b1y) = block1.spr.get_xy() + (_b2x, _b2y) = block2.spr.get_xy() + return ((_b1x + _d1x) - (_b2x + _d2x), (_b1y + _d1y) - (_b2y + _d2y)) + +def arithmetic_check(blk1, blk2, dock1, dock2): + """ Dock strings only if they convert to numbers. Avoid /0 and root(-1)""" + if blk1 == None or blk2 == None: + return True + if blk1.name in ['sqrt', 'number', 'string'] and\ + blk2.name in ['sqrt', 'number', 'string']: + if blk1.name == 'number' or blk1.name == 'string': + if not numeric_arg(blk1.values[0]) or neg_arg(blk1.values[0]): + return False + elif blk2.name == 'number' or blk2.name == 'string': + if not numeric_arg(blk2.values[0]) or neg_arg(blk2.values[0]): + return False + elif blk1.name in ['division2', 'number', 'string'] and\ + blk2.name in ['division2', 'number', 'string']: + if blk1.name == 'number' or blk1.name == 'string': + if not numeric_arg(blk1.values[0]): + return False + if dock2 == 2 and zero_arg(blk1.values[0]): + return False + elif blk2.name == 'number' or blk2.name == 'string': + if not numeric_arg(blk2.values[0]): + return False + if dock1 == 2 and zero_arg(blk2.values[0]): + return False + elif blk1.name in ['product2', 'minus2', 'random', 'remainder2', + 'string'] and\ + blk2.name in ['product2', 'minus2', 'random', 'remainder2', + 'string']: + if blk1.name == 'string': + if not numeric_arg(blk1.values[0]): + return False + elif blk1.name == 'string': + if not numeric_arg(blk2.values[0]): + return False + elif blk1.name in ['greater2', 'less2'] and blk2.name == 'string': + # Non-numeric stings are OK if only both args are strings; + # Lots of test conditions... + if dock1 == 1 and blk1.connections[2] is not None: + if blk1.connections[2].name == 'number': + if not numeric_arg(blk2.values[0]): + return False + elif dock1 == 2 and blk1.connections[1] is not None: + if blk1.connections[1].name == 'number': + if not numeric_arg(blk2.values[0]): + return False + elif blk2.name in ['greater2', 'less2'] and blk1.name == 'string': + if dock2 == 1 and blk2.connections[2] is not None: + if blk2.connections[2].name == 'number': + if not numeric_arg(blk1.values[0]): + return False + elif dock2 == 2 and blk2.connections[1] is not None: + if blk2.connections[1].name == 'number': + if not numeric_arg(blk1.values[0]): + return False + elif blk1.name in ['greater2', 'less2'] and blk2.name == 'number': + if dock1 == 1 and blk1.connections[2] is not None: + if blk1.connections[2].name == 'string': + if not numeric_arg(blk1.connections[2].values[0]): + return False + elif dock1 == 2 and blk1.connections[1] is not None: + if blk1.connections[1].name == 'string': + if not numeric_arg(blk1.connections[1].values[0]): + return False + elif blk2.name in ['greater2', 'less2'] and blk1.name == 'number': + if dock2 == 1 and blk2.connections[2] is not None: + if blk2.connections[2].name == 'string': + if not numeric_arg(blk2.connections[2].values[0]): + return False + elif dock2 == 2 and blk2.connections[1] is not None: + if blk2.connections[1].name == 'string': + if not numeric_arg(blk2.connections[1].values[0]): + return False + return True + +def xy(event): + """ Where is the mouse event? """ + return map(int, event.get_coords()) """ -Calculate the maximum size for placing an image onto a sprite. +Utilities related to finding blocks in stacks. """ -def calc_image_size(spr): - w = spr.label_safe_width() - h = spr.label_safe_height() - return w, h +def find_block_to_run(blk): + """ Find a stack to run (any stack without a 'def action'on the top). """ + _top = find_top_block(blk) + if blk == _top and blk.name[0:3] is not 'def': + return True + else: + return False + +def find_top_block(blk): + """ Find the top block in a stack. """ + if len(blk.connections) == 0: + return blk + while blk.connections[0] is not None: + blk = blk.connections[0] + return blk + +def find_start_stack(blk): + """ Find a stack with a 'start' block on top. """ + if find_top_block(blk).name == 'start': + return True + else: + return False + +def find_group(blk): + """ Find the connected group of block in a stack. """ + if blk is None: + return [] + _group = [blk] + if blk.connections is not None: + for _blk2 in blk.connections[1:]: + if _blk2 is not None: + _group.extend(find_group(_blk2)) + return _group + +def find_blk_below(blk, name): + """ Find a specific block below this block. """ + if blk == None or len(blk.connections) == 0: + return + _group = find_group(blk) + for _gblk in _group: + if _gblk.name == name: + return _gblk + return None + +def olpc_xo_1(): + """ Is the an OLPC XO-1 or XO-1.5? """ + return os.path.exists('/etc/olpc-release') or \ + os.path.exists('/sys/power/olpc-pm') + +def walk_stack(tw, blk): + """ Convert blocks to logo psuedocode. """ + top = find_top_block(blk) + if blk == top: + code = tw.lc.run_blocks(top, tw.block_list.list, False) + return code + else: + return [] diff --git a/tawindow.py b/tawindow.py index 5f9b69b..7d46cf1 100644 --- a/tawindow.py +++ b/tawindow.py @@ -21,21 +21,12 @@ #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. - -# TODO: -# - better comments! -# - many methods could have their logic simplified! -# - verbose flag should be in the scope of the object instance - - import pygtk pygtk.require('2.0') import gtk -import pango import gobject import os import os.path -import time from math import atan2, pi DEGTOR = 2*pi/360 from gettext import gettext as _ @@ -47,53 +38,40 @@ try: except ImportError: pass -from taconstants import * -from talogo import LogoCode, stop_logo, convert, str_to_num +from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ + PALETTE_NAMES, TITLEXY, MEDIA_SHAPES, STATUS_SHAPES, \ + OVERLAY_SHAPES, TOOLBAR_SHAPES, TAB_LAYER, \ + OVERLAY_LAYER, CATEGORY_LAYER, BLOCKS_WITH_SKIN, \ + ICON_SIZE, PALETTES, PALETTE_SCALE, BOX_STYLE_MEDIA, \ + PALETTE_WIDTH, MACROS, TOP_LAYER, BLOCK_LAYER, \ + CONTENT_BLOCKS, DEFAULTS, SPECIAL_NAMES, HELP_STRINGS, \ + CURSOR, EXPANDABLE, COLLAPSIBLE, RETURN, \ + DEAD_DICTS, DEAD_KEYS, TEMPLATES, PYTHON_SKIN, \ + PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK, OLD_NAMES, \ + BOOLEAN_STYLE, BLOCK_NAMES +from talogo import LogoCode, stop_logo from tacanvas import TurtleGraphics from tablock import Blocks, Block from taturtle import Turtles, Turtle -from tautils import magnitude, get_load_name, get_save_name, data_from_file,\ - data_to_file, round_int, get_id, get_pixbuf_from_journal,\ - movie_media_type, audio_media_type, image_media_type,\ - save_picture, save_svg, calc_image_size, get_path +from tautils import magnitude, get_load_name, get_save_name, data_from_file, \ + data_to_file, round_int, get_id, get_pixbuf_from_journal, \ + movie_media_type, audio_media_type, image_media_type, \ + save_picture, save_svg, calc_image_size, get_path, \ + reset_stack_arm, grow_stack_arm, find_sandwich_top, \ + find_sandwich_bottom, restore_stack, collapse_stack, \ + collapsed, collapsible, hide_button_hit, show_button_hit, \ + arithmetic_check, xy, find_block_to_run, find_top_block, \ + find_start_stack, find_group, find_blk_below, olpc_xo_1, \ + dock_dx_dy from tasprite_factory import SVG, svg_str_to_pixbuf, svg_from_file from sprites import Sprites, Sprite -""" -Dock tests -""" - -def numeric_arg(value): - if type(convert(value, float)) is float: - return True - return False - -def zero_arg(value): - if numeric_arg(value): - if convert(value, float) == 0: - return True - return False - -def neg_arg(value): - if numeric_arg(value): - if convert(value, float) < 0: - return True - return False - -""" -TurtleArt Window class abstraction -""" class TurtleArtWindow(): - - # Time out for triggering help + """ TurtleArt Window class abstraction """ timeout_tag = [0] - def __init__(self, win, path, lang, parent=None, mycolors=None): - self._setup_initial_values(win, path, lang, parent, mycolors) - self._setup_misc() - self._show_toolbar_palette(0, False) - - def _setup_initial_values(self, win, path, lang, parent, mycolors): + def __init__(self, win, path, parent=None, mycolors=None): + self.win = None self.window = win self.path = path self.load_save_folder = os.path.join(path, 'samples') @@ -117,7 +95,7 @@ class TurtleArtWindow(): self.area = self.window.window self.gc = self.area.new_gc() self.orientation = HORIZONTAL_PALETTE - if self._OLPC_XO_1(): + if olpc_xo_1(): self.lead = 1.0 self.scale = 0.67 if self.running_sugar and not self.activity.new_sugar_system: @@ -184,10 +162,12 @@ class TurtleArtWindow(): self.lc = LogoCode(self) self.saved_pictures = [] - """ - Register the events we listen to. - """ + self._setup_misc() + self._show_toolbar_palette(0, False) + self.block_operation = '' + def _setup_events(self): + """ Register the events we listen to. """ self.window.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.window.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self.window.add_events(gtk.gdk.POINTER_MOTION_MASK) @@ -198,112 +178,90 @@ class TurtleArtWindow(): self.window.connect("motion-notify-event", self._move_cb) self.window.connect("key_press_event", self._keypress_cb) - """ - Misc. sprites for status, overlays, etc. - """ def _setup_misc(self): + """ Misc. sprites for status, overlays, etc. """ # media blocks get positioned into other blocks - for name in MEDIA_SHAPES: - if name[0:7] == 'journal' and not self.running_sugar: - filename = 'file'+name[7:] + for _name in MEDIA_SHAPES: + if _name[0:7] == 'journal' and not self.running_sugar: + file_name = 'file'+_name[7:] else: - filename = name - self.media_shapes[name] = \ - svg_str_to_pixbuf(svg_from_file("%s/images/%s.svg" % ( - self.path, filename))) - - for i, name in enumerate(STATUS_SHAPES): - self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file( - "%s/images/%s.svg" % (self.path, name))) + file_name = _name + self.media_shapes[_name] = svg_str_to_pixbuf(svg_from_file( + "%s/images/%s.svg" % (self.path, file_name))) + + for i, _name in enumerate(STATUS_SHAPES): + self.status_shapes[_name] = svg_str_to_pixbuf(svg_from_file( + "%s/images/%s.svg" % (self.path, _name))) self.status_spr = Sprite(self.sprite_list, 0, self.height-200, self.status_shapes['status']) self.status_spr.hide() self.status_spr.type = 'status' - for name in OVERLAY_SHAPES: - self.overlay_shapes[name] = Sprite(self.sprite_list, - int(self.width/2-600), int(self.height/2-450), - svg_str_to_pixbuf(svg_from_file( - "%s/images/%s.svg" % (self.path, name)))) - self.overlay_shapes[name].hide() - self.overlay_shapes[name].type = 'overlay' + for _name in OVERLAY_SHAPES: + self.overlay_shapes[_name] = Sprite(self.sprite_list, + int(self.width/2-600), int(self.height/2-450), + svg_str_to_pixbuf(svg_from_file( + "%s/images/%s.svg" % (self.path, _name)))) + self.overlay_shapes[_name].hide() + self.overlay_shapes[_name].type = 'overlay' if not self.running_sugar: - o = self.width-55*len(TOOLBAR_SHAPES) - for i, name in enumerate(TOOLBAR_SHAPES): - self.toolbar_shapes[name] = Sprite(self.sprite_list, i*55+o, 0, - svg_str_to_pixbuf(svg_from_file( - "%s/icons/%s.svg" % (self.path, name)))) - self.toolbar_shapes[name].set_layer(TAB_LAYER) - self.toolbar_shapes[name].name = name - self.toolbar_shapes[name].type = 'toolbar' + offset = self.width-55*len(TOOLBAR_SHAPES) + for i, _name in enumerate(TOOLBAR_SHAPES): + self.toolbar_shapes[_name] = Sprite(self.sprite_list, + i*55+offset, 0, + svg_str_to_pixbuf( + svg_from_file("%s/icons/%s.svg" % (self.path, _name)))) + self.toolbar_shapes[_name].set_layer(TAB_LAYER) + self.toolbar_shapes[_name].name = _name + self.toolbar_shapes[_name].type = 'toolbar' self.toolbar_shapes['stopiton'].hide() - - """ - Is a chattube available for sharing? - """ def _sharing(self): + """ Is a chattube available for sharing? """ if self.running_sugar and hasattr(self.activity, 'chattube') and\ - self.activity.chattube is not None: - return True + self.activity.chattube is not None: + return True return False - """ - Is the an OLPC XO-1 or XO-1.5? - """ - def _OLPC_XO_1(self): - return os.path.exists('/etc/olpc-release') or \ - os.path.exists('/sys/power/olpc-pm') - - """ - Repaint - """ def _expose_cb(self, win, event): + """ Repaint """ self.sprite_list.redraw_sprites() # self.canvas.cr_expose(event) return True - """ - Eraser_button (Always hide status block when clearing the screen.) - """ def eraser_button(self): + """ Eraser_button (hide status block when clearing the screen.) """ if self.status_spr is not None: self.status_spr.hide() self.lc.prim_clear() self.display_coordinates() - """ - Run turtle! - """ def run_button(self, time): + """ Run turtle! """ if self.running_sugar: self.activity.recenter() # Look for a 'start' block for blk in self.just_blocks(): - if self._find_start_stack(blk): + if find_start_stack(blk): self.step_time = time print "running stack starting from %s" % (blk.name) self._run_stack(blk) return # If there is no 'start' block, run stacks that aren't 'def action' for blk in self.just_blocks(): - if self._find_block_to_run(blk): + if find_block_to_run(blk): self.step_time = time print "running stack starting from %s" % (blk.name) self._run_stack(blk) return - """ - Stop button - """ def stop_button(self): + """ Stop button """ stop_logo(self) - """ - Change the icon for user-defined blocks after Python code is loaded. - """ def set_userdefined(self): + """ Change icon for user-defined blocks after Python code is loaded. """ for blk in self.just_blocks(): if blk.name in PYTHON_SKIN: x, y = self._calc_image_offset('pythonon', blk.spr) @@ -311,19 +269,14 @@ class TurtleArtWindow(): self._resize_skin(blk) self.nop = 'pythonloaded' - - """ - Enter fullscreen mode - """ def set_fullscreen(self): + """ Enter fullscreen mode """ if self.running_sugar: self.activity.fullscreen() self.activity.recenter() - """ - Turn on/off Cartesian coordinates - """ def set_cartesian(self, flag): + """ Turn on/off Cartesian coordinates """ if flag: if self.coord_scale == 1: self.overlay_shapes['Cartesian_labeled'].set_layer( @@ -338,10 +291,8 @@ class TurtleArtWindow(): self.overlay_shapes['Cartesian'].hide() self.cartesian = False - """ - Turn on/off polar coordinates - """ def set_polar(self, flag): + """ Turn on/off polar coordinates """ if flag: self.overlay_shapes['polar'].set_layer(OVERLAY_LAYER) self.polar = True @@ -349,10 +300,8 @@ class TurtleArtWindow(): self.overlay_shapes['polar'].hide() self.polar = False - """ - Hide/show button - """ def hideshow_button(self): + """ Hide/show button """ if not self.hide: for blk in self.just_blocks(): blk.spr.hide() @@ -364,29 +313,26 @@ class TurtleArtWindow(): blk.spr.set_layer(BLOCK_LAYER) self.show_palette() if self.activity is not None and self.activity.new_sugar_system: - self.activity.palette_buttons[0].set_icon(PALETTE_NAMES[0]+'on') + self.activity.palette_buttons[0].set_icon( + PALETTE_NAMES[0] + 'on') self.hide = False self.canvas.canvas.inval() - """ - Hide or show palette - """ def hideshow_palette(self, state): + """ Hide or show palette """ if not state: - self.palette == False + self.palette = False if self.running_sugar: self.activity.do_hidepalette() self.hide_palette() else: - self.palette == True + self.palette = True if self.running_sugar: self.activity.do_showpalette() self.show_palette() - """ - Show palette - """ def show_palette(self, n=0): + """ Show palette """ self._show_toolbar_palette(n) self.palette_button[self.orientation].set_layer(TAB_LAYER) self.palette_button[2].set_layer(TAB_LAYER) @@ -394,10 +340,8 @@ class TurtleArtWindow(): self.toolbar_spr.set_layer(CATEGORY_LAYER) self.palette = True - """ - Hide the palette. - """ def hide_palette(self): + """ Hide the palette. """ self._hide_toolbar_palette() self.palette_button[self.orientation].hide() self.palette_button[2].hide() @@ -405,60 +349,52 @@ class TurtleArtWindow(): self.toolbar_spr.hide() self.palette = False - """ - Callback from 'hide blocks' block - """ def hideblocks(self): + """ Callback from 'hide blocks' block """ self.hide = False self.hideshow_button() if self.running_sugar: self.activity.do_hide() - """ - Callback from 'show blocks' block - """ def showblocks(self): + """ Callback from 'show blocks' block """ self.hide = True self.hideshow_button() if self.running_sugar: self.activity.do_show() - """ - Resize all of the blocks - """ def resize_blocks(self): + """ Resize all of the blocks """ # We need to restore collapsed stacks before resizing. - for b in self.just_blocks(): - if b.status == 'collapsed': - bot = self._find_sandwich_bottom(b) - if self._collapsed(bot): + for blk in self.just_blocks(): + if blk.status == 'collapsed': + bot = find_sandwich_bottom(blk) + if collapsed(bot): dy = bot.values[0] - self._restore_stack(self._find_sandwich_top(b)) + restore_stack(find_sandwich_top(blk)) bot.values[0] = dy # Do the resizing. - for b in self.just_blocks(): - b.rescale(self.block_scale) - for b in self.just_blocks(): - self._adjust_dock_positions(b) + for blk in self.just_blocks(): + blk.rescale(self.block_scale) + for blk in self.just_blocks(): + self._adjust_dock_positions(blk) # Re-collapsed stacks after resizing. - for b in self.just_blocks(): - if self._collapsed(b): - self._collapse_stack(self._find_sandwich_top(b)) - for b in self.just_blocks(): - if b.name == 'sandwichtop': - self._grow_stack_arm(b) + for blk in self.just_blocks(): + if collapsed(blk): + collapse_stack(find_sandwich_top(blk)) + for blk in self.just_blocks(): + if blk.name == 'sandwichtop': + grow_stack_arm(blk) # Resize the skins on some blocks: media content and Python - for b in self.just_blocks(): - if b.name in BLOCKS_WITH_SKIN: - self._resize_skin(b) + for blk in self.just_blocks(): + if blk.name in BLOCKS_WITH_SKIN: + self._resize_skin(blk) - """ - Show the toolbar palettes, creating them on init_only - """ def _show_toolbar_palette(self, n, init_only=False): + """ Show the toolbar palettes, creating them on init_only """ if (self.activity is None or not self.activity.new_sugar_system) and\ self.selectors == []: # Create the selectors @@ -469,12 +405,12 @@ class TurtleArtWindow(): self.path, name))) b = svg_str_to_pixbuf(svg_from_file("%s/icons/%son.svg" % ( self.path, name))) - self.selector_shapes.append([a,b]) + self.selector_shapes.append([a, b]) self.selectors.append(Sprite(self.sprite_list, x, y, a)) self.selectors[i].type = 'selector' self.selectors[i].name = name self.selectors[i].set_layer(TAB_LAYER) - w, h = self.selectors[i].get_dimensions() + w = self.selectors[i].get_dimensions()[0] x += int(w) # Create the toolbar background @@ -489,11 +425,11 @@ class TurtleArtWindow(): # Create the empty palettes if len(self.palettes) == 0: for i in range(len(PALETTES)): - self.palettes.append([]); + self.palettes.append([]) # Create empty palette backgrounds for i in PALETTE_NAMES: - self.palette_sprs.append([None,None]) + self.palette_sprs.append([None, None]) # Create the palette orientation button self.palette_button.append(Sprite(self.sprite_list, 0, @@ -561,14 +497,12 @@ class TurtleArtWindow(): blk.spr.set_layer(TAB_LAYER) if n == self.trash_index: for blk in self.trash_stack: - for b in self._find_group(blk): - if b.status != 'collapsed': - b.spr.set_layer(TAB_LAYER) + for gblk in find_group(blk): + if gblk.status != 'collapsed': + gblk.spr.set_layer(TAB_LAYER) - """ - Hide the toolbar palettes - """ def _hide_toolbar_palette(self): + """ Hide the toolbar palettes """ self._hide_previous_palette() if self.activity is None or not self.activity.new_sugar_system: # Hide the selectors @@ -576,14 +510,12 @@ class TurtleArtWindow(): self.selectors[i].hide() elif self.selected_palette is not None: self.activity.palette_buttons[self.selected_palette].set_icon( - PALETTE_NAMES[self.selected_palette]+'off') + PALETTE_NAMES[self.selected_palette] + 'off') self.selected_palette = None self.previous_palette = None - """ - Hide just the previously viewed toolbar palette - """ def _hide_previous_palette(self): + """ Hide just the previously viewed toolbar palette """ # Hide previous palette if self.previous_palette is not None: for i in range(len(PALETTES[self.previous_palette])): @@ -593,85 +525,79 @@ class TurtleArtWindow(): if self.activity is None or not self.activity.new_sugar_system: self.selectors[self.previous_palette].set_shape( self.selector_shapes[self.previous_palette][0]) - elif self.previous_palette is not None and\ + elif self.previous_palette is not None and \ self.previous_palette != self.selected_palette: self.activity.palette_buttons[self.previous_palette].set_icon( - PALETTE_NAMES[self.previous_palette]+'off') + PALETTE_NAMES[self.previous_palette] + 'off') if self.previous_palette == self.trash_index: - for b in self.trash_stack: - for bb in self._find_group(b): - bb.spr.hide() + for blk in self.trash_stack: + for gblk in find_group(blk): + gblk.spr.hide() - """ - Position prototypes in a horizontal palette. - """ def _horizontal_layout(self, x, y, blocks): + """ Position prototypes in a horizontal palette. """ _max_w = 0 - for b in blocks: - _w, _h = self._width_and_height(b) - if y+_h > PALETTE_HEIGHT+self.toolbar_offset: + for blk in blocks: + _w, _h = self._width_and_height(blk) + if y + _h > PALETTE_HEIGHT + self.toolbar_offset: x += int(_max_w+3) - y = self.toolbar_offset+3 + y = self.toolbar_offset + 3 _max_w = 0 - (_bx, _by) = b.spr.get_xy() + (_bx, _by) = blk.spr.get_xy() _dx = x-_bx _dy = y-_by - for g in self._find_group(b): + for g in find_group(blk): g.spr.move_relative((int(_dx), int(_dy))) y += int(_h+3) if _w > _max_w: _max_w = _w return x, y, _max_w - """ - Position prototypes in a vertical palette. - """ def _vertical_layout(self, x, y, blocks): + """ Position prototypes in a vertical palette. """ _row = [] _row_w = 0 _max_h = 0 for _b in blocks: _w, _h = self._width_and_height(_b) - if x+_w > PALETTE_WIDTH: + if x + _w > PALETTE_WIDTH: # Recenter row. _dx = int((PALETTE_WIDTH-_row_w)/2) for _r in _row: - for _g in self._find_group(_r): - _g.spr.move_relative((_dx, 0)) + for _g in find_group(_r): + _g.spr.move_relative((_dx, 0)) _row = [] _row_w = 0 x = 4 y += int(_max_h+3) _max_h = 0 _row.append(_b) - _row_w += (4+_w) + _row_w += (4 + _w) (_bx, _by) = _b.spr.get_xy() - _dx = int(x-_bx) - _dy = int(y-_by) - for _g in self._find_group(_b): + _dx = int(x - _bx) + _dy = int(y - _by) + for _g in find_group(_b): _g.spr.move_relative((_dx, _dy)) - x += int(_w+4) + x += int(_w + 4) if _h > _max_h: _max_h = _h # Recenter last row. - _dx = int((PALETTE_WIDTH-_row_w)/2) + _dx = int((PALETTE_WIDTH - _row_w)/2) for _r in _row: - for _g in self._find_group(_r): + for _g in find_group(_r): _g.spr.move_relative((_dx, 0)) return x, y, _max_h - """ - Layout prototypes in a palette. - """ def _layout_palette(self, n): + """ Layout prototypes in a palette. """ if n is not None: if self.orientation == HORIZONTAL_PALETTE: - _x, _y = 20, self.toolbar_offset+5 + _x, _y = 20, self.toolbar_offset + 5 _x, _y, _max = self._horizontal_layout(_x, _y, self.palettes[n]) if n == self.trash_index: _x, _y, _max = self._horizontal_layout(_x+_max, _y, self.trash_stack) - _w = _x+_max+25 + _w = _x + _max + 25 if self.palette_sprs[n][self.orientation] is None: svg = SVG() self.palette_sprs[n][self.orientation] = Sprite( @@ -684,15 +610,15 @@ class TurtleArtWindow(): svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT))) self.palette_button[2].move((_w-20, self.toolbar_offset)) else: - _x, _y = 5, self.toolbar_offset+15 + _x, _y = 5, self.toolbar_offset + 15 _x, _y, _max = self._vertical_layout(_x, _y, self.palettes[n]) if n == PALETTE_NAMES.index('trash'): - _x, _y, _max = self._vertical_layout(_x, _y+_max, + _x, _y, _max = self._vertical_layout(_x, _y + _max, self.trash_stack) - _h = _y+_max+25-self.toolbar_offset + _h = _y + _max + 25 - self.toolbar_offset if self.palette_sprs[n][self.orientation] is None: svg = SVG() - self.palette_sprs[n][self.orientation] =\ + self.palette_sprs[n][self.orientation] = \ Sprite(self.sprite_list, 0, self.toolbar_offset, svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h))) self.palette_sprs[n][self.orientation].type = 'category' @@ -704,18 +630,16 @@ class TurtleArtWindow(): self.toolbar_offset)) self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) - """ - Button press - """ def _buttonpress_cb(self, win, event): + """ Button press """ self.window.grab_focus() - x, y = self._xy(event) + x, y = xy(event) self.button_press(event.get_state()>k.gdk.CONTROL_MASK, x, y) if self._sharing(): if event.get_state()>k.gdk.CONTROL_MASK: - self.activity._send_event("p:%d:%d:T" % (x, y)) + self.activity.send_event("p:%d:%d:T" % (x, y)) else: - self.activity._send_event("p:%d:%d:F" % (x, y)) + self.activity.send_event("p:%d:%d:F" % (x, y)) return True def button_press(self, mask, x, y, verbose=False): @@ -732,7 +656,7 @@ class TurtleArtWindow(): self.status_spr.hide() # Find out what was clicked - spr = self.sprite_list.find_sprite((x,y)) + spr = self.sprite_list.find_sprite((x, y)) self.dx = 0 self.dy = 0 if spr is None: @@ -744,9 +668,9 @@ class TurtleArtWindow(): if blk is not None: if blk.type == 'block': self.selected_blk = blk - self._block_pressed(mask, x, y, blk) + self._block_pressed(x, y, blk) elif blk.type == 'trash': - self._restore_from_trash(self.find_top_block(blk)) + self._restore_from_trash(find_top_block(blk)) elif blk.type == 'proto': if blk.name == 'restoreall': self._restore_all_from_trash() @@ -755,7 +679,7 @@ class TurtleArtWindow(): elif blk.name == 'empty': self._empty_trash() elif MACROS.has_key(blk.name): - self._new_macro(blk.name, x+20, y+20) + self._new_macro(blk.name, x + 20, y + 20) else: blk.highlight() self._new_block(blk.name, x, y) @@ -778,40 +702,38 @@ class TurtleArtWindow(): elif spr.type == 'selector': self._select_category(spr) elif spr.type == 'category': - if self._hide_button_hit(spr, x, y): + if hide_button_hit(spr, x, y): self.hideshow_palette(False) elif spr.type == 'palette': - if spr.name == _('next'): - i = self.selected_palette+1 - if i == len(PALETTE_NAMES): - i = 0 - if self.activity is None or\ - not self.activity.new_sugar_system: - self._select_category(self.selectors[i]) - else: - if self.selected_palette is not None: - self.activity.palette_buttons[ - self.selected_palette].set_icon( - PALETTE_NAMES[self.selected_palette]+'off') - self.activity.palette_buttons[i].set_icon( - PALETTE_NAMES[i]+'on') - self.show_palette(i) - else: - self.orientation = 1-self.orientation - self.palette_button[self.orientation].set_layer(TAB_LAYER) - self.palette_button[1-self.orientation].hide() - self.palette_sprs[self.selected_palette][ - 1-self.orientation].hide() - self._layout_palette(self.selected_palette) - self.show_palette(self.selected_palette) + if spr.name == _('next'): + i = self.selected_palette + 1 + if i == len(PALETTE_NAMES): + i = 0 + if self.activity is None or \ + not self.activity.new_sugar_system: + self._select_category(self.selectors[i]) + else: + if self.selected_palette is not None: + self.activity.palette_buttons[ + self.selected_palette].set_icon( + PALETTE_NAMES[self.selected_palette] + 'off') + self.activity.palette_buttons[i].set_icon( + PALETTE_NAMES[i] + 'on') + self.show_palette(i) + else: + self.orientation = 1 - self.orientation + self.palette_button[self.orientation].set_layer(TAB_LAYER) + self.palette_button[1 - self.orientation].hide() + self.palette_sprs[self.selected_palette][ + 1 - self.orientation].hide() + self._layout_palette(self.selected_palette) + self.show_palette(self.selected_palette) elif spr.type == 'toolbar': - self._select_toolbar_button(spr) + self._select_toolbar_button(spr) return True - """ - Select a category from the toolbar (Not used in new Sugar systems). - """ def _select_category(self, spr): + """ Select a category from the toolbar (old Sugar systems only). """ i = self.selectors.index(spr) spr.set_shape(self.selector_shapes[i][1]) if self.selected_selector is not None: @@ -823,10 +745,8 @@ class TurtleArtWindow(): self.selected_selector = spr self.show_palette(i) - """ - Select a toolbar button (Used when not running Sugar). - """ def _select_toolbar_button(self, spr): + """ Select a toolbar button (Used when not running Sugar). """ if not hasattr(spr, 'name'): return if spr.name == 'run-fastoff': @@ -846,117 +766,104 @@ class TurtleArtWindow(): elif spr.name == 'hideshowoff': self.hideshow_button() - """ - Put a group of blocks into the trash. - """ def _put_in_trash(self, blk, x=0, y=0): + """ Put a group of blocks into the trash. """ self.trash_stack.append(blk) - group = self._find_group(blk) - for b in group: - if b.status == 'collapsed': + group = find_group(blk) + for gblk in group: + if gblk.status == 'collapsed': # Collapsed stacks are restored for rescaling # and then recollapsed after they are moved to the trash. - bot = self._find_sandwich_bottom(b) - if self._collapsed(bot): + bot = find_sandwich_bottom(gblk) + if collapsed(bot): dy = bot.values[0] - self._restore_stack(self._find_sandwich_top(b)) + restore_stack(find_sandwich_top(gblk)) bot.values[0] = dy - b.type = 'trash' - b.rescale(self.trash_scale) - blk.spr.move((x,y)) - for b in group: - self._adjust_dock_positions(b) + gblk.type = 'trash' + gblk.rescale(self.trash_scale) + blk.spr.move((x, y)) + for gblk in group: + self._adjust_dock_positions(gblk) # Re-collapsing any stacks we had restored for scaling - for b in group: - if self._collapsed(b): - self._collapse_stack(self._find_sandwich_top(b)) + for gblk in group: + if collapsed(gblk): + collapse_stack(find_sandwich_top(gblk)) # And resize any skins. - for b in group: - if b.name in BLOCKS_WITH_SKIN: - self._resize_skin(b) + for gblk in group: + if gblk.name in BLOCKS_WITH_SKIN: + self._resize_skin(gblk) # self.show_palette(self.trash_index) if self.selected_palette != self.trash_index: - for b in group: - b.spr.hide() + for gblk in group: + gblk.spr.hide() - - """ - Restore all the blocks in the trash can. - """ def _restore_all_from_trash(self): - for b in self.block_list.list: - if b.type == 'trash': - self._restore_from_trash(b) + """ Restore all the blocks in the trash can. """ + for blk in self.block_list.list: + if blk.type == 'trash': + self._restore_from_trash(blk) - """ - Restore most recent blocks from the trash can. - """ def _restore_latest_from_trash(self): + """ Restore most recent blocks from the trash can. """ if len(self.trash_stack) == 0: return - self._restore_from_trash(self.trash_stack[len(self.trash_stack)-1]) + self._restore_from_trash(self.trash_stack[len(self.trash_stack) - 1]) def _restore_from_trash(self, blk): - group = self._find_group(blk) - for b in group: - b.rescale(self.block_scale) - b.spr.set_layer(BLOCK_LAYER) - x,y = b.spr.get_xy() + group = find_group(blk) + for gblk in group: + gblk.rescale(self.block_scale) + gblk.spr.set_layer(BLOCK_LAYER) + x, y = gblk.spr.get_xy() if self.orientation == 0: - b.spr.move((x,y+PALETTE_HEIGHT+self.toolbar_offset)) + gblk.spr.move((x, y + PALETTE_HEIGHT + self.toolbar_offset)) else: - b.spr.move((x+PALETTE_WIDTH,y)) - b.type = 'block' - for b in group: - self._adjust_dock_positions(b) + gblk.spr.move((x + PALETTE_WIDTH, y)) + gblk.type = 'block' + for gblk in group: + self._adjust_dock_positions(gblk) # If the stack had been collapsed before going into the trash, # collapse it again now. - for b in group: - if self._collapsed(b): - self._collapse_stack(self._find_sandwich_top(b)) + for gblk in group: + if collapsed(gblk): + collapse_stack(find_sandwich_top(gblk)) # And resize any skins. - for b in group: - if b.name in BLOCKS_WITH_SKIN: - self._resize_skin(b) + for gblk in group: + if gblk.name in BLOCKS_WITH_SKIN: + self._resize_skin(gblk) self.trash_stack.remove(blk) - """ - Permanently remove all blocks presently in the trash can. - """ def _empty_trash(self): - for b in self.block_list.list: - if b.type == 'trash': - b.type = 'deleted' - b.spr.hide() + """ Permanently remove all blocks presently in the trash can. """ + for blk in self.block_list.list: + if blk.type == 'trash': + blk.type = 'deleted' + blk.spr.hide() self.trash_stack = [] - """ - Is x,y over the trash can? - """ def _in_the_trash(self, x, y): + """ Is x, y over the trash can? """ """ if self.selected_palette == self.trash_index and \ - self.palette_sprs[self.trash_index][self.orientation].hit((x,y)): + self.palette_sprs[self.trash_index][self.orientation].hit((x, y)): return True """ if self.selected_palette is not None and\ self.palette_sprs[self.selected_palette][self.orientation].hit( - (x,y)): + (x, y)): return True return False - """ - Block pressed - """ - def _block_pressed(self, mask, x, y, blk): + def _block_pressed(self, x, y, blk): + """ Block pressed """ if blk is not None: blk.highlight() self._disconnect(blk) - self.drag_group = self._find_group(blk) + self.drag_group = find_group(blk) (sx, sy) = blk.spr.get_xy() self.drag_pos = x-sx, y-sy for blk in self.drag_group: @@ -964,10 +871,8 @@ class TurtleArtWindow(): blk.spr.set_layer(TOP_LAYER) self.saved_string = blk.spr.labels[0] - """ - Unselect block - """ def _unselect_block(self): + """ Unselect block """ # After unselecting a 'number' block, we need to check its value if self.selected_blk.name == 'number': self._number_check() @@ -976,16 +881,14 @@ class TurtleArtWindow(): self.selected_blk.unhighlight() self.selected_blk = None - """ - Make a new block. - """ def _new_block(self, name, x, y): + """ Make a new block. """ if name in CONTENT_BLOCKS: - newblk = Block(self.block_list, self.sprite_list, name, x-20, y-20, - 'block', DEFAULTS[name], self.block_scale) + newblk = Block(self.block_list, self.sprite_list, name, x - 20, + y - 20, 'block', DEFAULTS[name], self.block_scale) else: - newblk = Block(self.block_list, self.sprite_list, name, x-20, y-20, - 'block', [], self.block_scale) + newblk = Block(self.block_list, self.sprite_list, name, x - 20, + y - 20, 'block', [], self.block_scale) # Add a 'skin' to some blocks if name in PYTHON_SKIN: @@ -1003,13 +906,13 @@ class TurtleArtWindow(): if DEFAULTS.has_key(newblk.name): for i, argvalue in enumerate(DEFAULTS[newblk.name]): # skip the first dock position since it is always a connector - dock = newblk.docks[i+1] + dock = newblk.docks[i + 1] argname = dock[0] if argname == 'unavailable': continue if argname == 'media': argname = 'journal' - elif argname == 'number' and\ + elif argname == 'number' and \ (type(argvalue) is str or type(argvalue) is unicode): argname = 'string' elif argname == 'bool': @@ -1027,42 +930,38 @@ class TurtleArtWindow(): argname, 0, 0, 'block', [], self.block_scale) argdock = argblk.docks[0] - nx, ny = sx+dock[2]-argdock[2], sy+dock[3]-argdock[3] + nx = sx + dock[2] - argdock[2] + ny = sy + dock[3] - argdock[3] if argname == 'journal': self._block_skin('journaloff', argblk) argblk.spr.move((nx, ny)) argblk.spr.set_layer(TOP_LAYER) argblk.connections = [newblk, None] - newblk.connections[i+1] = argblk - self.drag_group = self._find_group(newblk) + newblk.connections[i + 1] = argblk + self.drag_group = find_group(newblk) self.block_operation = 'new' - """ - Create a "macro" (predefined stack of blocks). - """ def _new_macro(self, name, x, y): + """ Create a "macro" (predefined stack of blocks). """ macro = MACROS[name] macro[0][2] = x macro[0][3] = y top = self.process_data(macro) self.block_operation = 'new' self._check_collapsibles(top) - self.drag_group = self._find_group(top) + self.drag_group = find_group(top) - """ - Process data (from a macro, a file, or the clipboard) into blocks. - """ def process_data(self, data): + """ Process data (from a macro, a file, or the clipboard). """ # Create the blocks (or turtle). blocks = [] - for b in data: - if not self._found_a_turtle(b): - blk = self.load_block(b) - blocks.append(blk) + for blk in data: + if not self._found_a_turtle(blk): + blocks.append(self.load_block(blk)) # Make the connections. for i in range(len(blocks)): - cons=[] + cons = [] # Normally, it is simply a matter of copying the connections. if blocks[i].connections == None: for c in data[i][4]: @@ -1087,7 +986,7 @@ class TurtleArtWindow(): for j, cj in enumerate(data[c0][4]): if cj == c: blocks[c0].connections[j] = blocks[i] - if c 0: return blocks[0] else: return None - """ - Adjust the dock x,y positions - """ def _adjust_dock_positions(self, blk): + """ Adjust the dock x, y positions """ (sx, sy) = blk.spr.get_xy() for i, c in enumerate(blk.connections): - if i>0 and c is not None: + if i > 0 and c is not None: bdock = blk.docks[i] for j in range(len(c.docks)): if c.connections[j] == blk: cdock = c.docks[j] - nx, ny = sx+bdock[2]-cdock[2], sy+bdock[3]-cdock[3] + nx = sx + bdock[2] - cdock[2] + ny = sy + bdock[3] - cdock[3] c.spr.move((nx, ny)) self._adjust_dock_positions(c) - """ - Turtle pressed - """ def _turtle_pressed(self, x, y): + """ Turtle pressed """ (tx, ty) = self.selected_turtle.get_xy() - dx, dy = x-tx-30, y-ty-30 - if dx*dx+dy*dy > 200: + dx = x - tx - 30 + dy = y - ty - 30 + if (dx * dx) + (dy * dy) > 200: self.drag_turtle = ('turn', - self.canvas.heading-atan2(dy,dx)/DEGTOR, 0) + self.canvas.heading - atan2(dy, dx)/DEGTOR, 0) else: - self.drag_turtle = ('move', x-tx, y-ty) + self.drag_turtle = ('move', x - tx, y - ty) - """ - Mouse move - """ def _move_cb(self, win, event): - x, y = self._xy(event) + """ Mouse move """ + x, y = xy(event) self._mouse_move(x, y) return True @@ -1179,14 +1074,17 @@ class TurtleArtWindow(): if mdx != 0 or mdy != 0: dx, dy = mdx, mdy else: - dx, dy = x-dragx-sx, y-dragy-sy - self.selected_turtle.move((sx+dx, sy+dy)) + dx = x - dragx - sx + dy = y - dragy - sy + self.selected_turtle.move((sx + dx, sy + dy)) else: if mdx != 0 or mdy != 0: - dx, dy = mdx, mdy + dx = mdx + dy = mdy else: - dx, dy = x-sx-30, y-sy-30 - self.canvas.seth(int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10) + dx = x - sx - 30 + dy = y - sy - 30 + self.canvas.seth(int(dragx + atan2(dy, dx)/DEGTOR + 5)/10 * 10) # If we are hoving, show popup help. elif self.drag_group is None: self._show_popup(x, y) @@ -1195,27 +1093,29 @@ class TurtleArtWindow(): elif self.drag_group[0] is not None: blk = self.drag_group[0] # Don't move a bottom blk is the stack is collapsed - if self._collapsed(blk): + if collapsed(blk): return self.selected_spr = blk.spr dragx, dragy = self.drag_pos if mdx != 0 or mdy != 0: - dx, dy = mdx, mdy + dx = mdx + dy = mdy else: - (sx,sy) = blk.spr.get_xy() - dx, dy = x-dragx-sx, y-dragy-sy + (sx, sy) = blk.spr.get_xy() + dx = x - dragx - sx + dy = y - dragy - sy # Take no action if there was a move of 0,0. if dx == 0 and dy == 0: return - self.drag_group = self._find_group(blk) + self.drag_group = find_group(blk) # Prevent blocks from ending up with a negative x... - for b in self.drag_group: - (bx, by) = b.spr.get_xy() - if bx+dx < 0: - dx += -(bx+dx) + for gblk in self.drag_group: + (bx, by) = gblk.spr.get_xy() + if bx + dx < 0: + dx += -(bx + dx) """ # ...or under the palette. if self.selected_palette is not None and\ @@ -1232,20 +1132,19 @@ class TurtleArtWindow(): """ # Move the stack. - for b in self.drag_group: - (bx, by) = b.spr.get_xy() - b.spr.move((bx+dx, by+dy)) + for gblk in self.drag_group: + (bx, by) = gblk.spr.get_xy() + gblk.spr.move((bx + dx, by + dy)) if mdx != 0 or mdy != 0: - dx, dy = 0, 0 + dx = 0 + dy = 0 else: self.dx += dx self.dy += dy - """ - Let's help our users by displaying a little help. - """ def _show_popup(self, x, y): - spr = self.sprite_list.find_sprite((x,y)) + """ Let's help our users by displaying a little help. """ + spr = self.sprite_list.find_sprite((x, y)) blk = self.block_list.spr_to_block(spr) if spr and blk is not None: if self.timeout_tag[0] == 0: @@ -1279,10 +1178,8 @@ class TurtleArtWindow(): except: self.timeout_tag[0] = 0 - """ - Fetch the help text and display it. - """ def _do_show_popup(self, block_name): + """ Fetch the help text and display it. """ if SPECIAL_NAMES.has_key(block_name): block_name_s = SPECIAL_NAMES[block_name] elif BLOCK_NAMES.has_key(block_name): @@ -1305,14 +1202,12 @@ class TurtleArtWindow(): self.win.set_title(_("Turtle Art") + " — " + label) return 0 - """ - Button release - """ def _buttonrelease_cb(self, win, event): - x, y = self._xy(event) + """ Button release """ + x, y = xy(event) self.button_release(x, y) if self._sharing(): - self.activity._send_event("r:"+str(x)+":"+str(y)) + self.activity.send_event("r:" + str(x) + ":" + str(y)) return True def button_release(self, x, y, verbose=False): @@ -1320,7 +1215,7 @@ class TurtleArtWindow(): if self._sharing(): if verbose: print "processing move: %d %d" % (self.dx, self.dy) - self.activity._send_event("m:%d:%d" % (self.dx, self.dy)) + self.activity.send_event("m:%d:%d" % (self.dx, self.dy)) self.dx = 0 self.dy = 0 if verbose: @@ -1330,8 +1225,10 @@ class TurtleArtWindow(): if self.selected_turtle is not None: (tx, ty) = self.selected_turtle.get_xy() (cx, cy) = self.canvas.canvas.get_xy() - self.canvas.xcor = tx-self.canvas.canvas._width/2+30-cx - self.canvas.ycor = self.canvas.canvas._height/2-ty-30+cy + # self.canvas.xcor = tx - self.canvas.canvas._width/2 + 30 - cx + # self.canvas.ycor = self.canvas.canvas._height/2 - ty - 30 + cy + self.canvas.xcor = tx - self.canvas.width/2 + 30 - cx + self.canvas.ycor = self.canvas.height/2 - ty - 30 + cy self.canvas.move_turtle() if self.running_sugar: self.display_coordinates() @@ -1344,84 +1241,83 @@ class TurtleArtWindow(): blk = self.drag_group[0] # Remove blocks by dragging them onto the trash palette. - if self.block_operation=='move' and self._in_the_trash(x, y): + if self.block_operation == 'move' and self._in_the_trash(x, y): self._put_in_trash(blk, x, y) self.drag_group = None return # Pull a stack of new blocks off of the category palette. - if self.block_operation=='new': - for b in self.drag_group: - (bx, by) = b.spr.get_xy() + if self.block_operation == 'new': + for gblk in self.drag_group: + (bx, by) = gblk.spr.get_xy() if self.orientation == 0: - b.spr.move((bx+20, by+PALETTE_HEIGHT+self.toolbar_offset)) + gblk.spr.move((bx+20, + by+PALETTE_HEIGHT+self.toolbar_offset)) else: - b.spr.move((bx+PALETTE_WIDTH, by+20)) + gblk.spr.move((bx+PALETTE_WIDTH, by+20)) # Look to see if we can dock the current stack. self._snap_to_dock() self._check_collapsibles(blk) - for b in self.drag_group: - if b.status != 'collapsed': - b.spr.set_layer(BLOCK_LAYER) + for gblk in self.drag_group: + if gblk.status != 'collapsed': + gblk.spr.set_layer(BLOCK_LAYER) self.drag_group = None # Find the block we clicked on and process it. - if self.block_operation=='click': + if self.block_operation == 'click': self._click_block(x, y) - """ - Click block - """ def _click_block(self, x, y): + """ Click block """ blk = self.block_list.spr_to_block(self.selected_spr) if blk is None: return self.selected_blk = blk - if blk.name=='number' or blk.name=='string': + if blk.name == 'number' or blk.name == 'string': self.saved_string = blk.spr.labels[0] blk.spr.labels[0] += CURSOR elif blk.name in BOX_STYLE_MEDIA: self._import_from_journal(self.selected_blk) if blk.name == 'journal' and self.running_sugar: self._load_description_block(blk) - elif blk.name=='identity2' or blk.name=='hspace': - group = self._find_group(blk) - if self._hide_button_hit(blk.spr, x, y): + elif blk.name == 'identity2' or blk.name == 'hspace': + group = find_group(blk) + if hide_button_hit(blk.spr, x, y): dx = blk.reset_x() - elif self._show_button_hit(blk.spr, x, y): + elif show_button_hit(blk.spr, x, y): dx = 20 blk.expand_in_x(dx) else: dx = 0 - for b in group: - if b != blk: - b.spr.move_relative((dx*blk.scale, 0)) - elif blk.name=='vspace': - group = self._find_group(blk) - if self._hide_button_hit(blk.spr, x, y): + for gblk in group: + if gblk != blk: + gblk.spr.move_relative((dx * blk.scale, 0)) + elif blk.name == 'vspace': + group = find_group(blk) + if hide_button_hit(blk.spr, x, y): dy = blk.reset_y() - elif self._show_button_hit(blk.spr, x, y): + elif show_button_hit(blk.spr, x, y): dy = 20 blk.expand_in_y(dy) else: dy = 0 - for b in group: - if b != blk: - b.spr.move_relative((0, dy*blk.scale)) - self._grow_stack_arm(self._find_sandwich_top(blk)) + for gblk in group: + if gblk != blk: + gblk.spr.move_relative((0, dy * blk.scale)) + grow_stack_arm(find_sandwich_top(blk)) elif blk.name in EXPANDABLE or blk.name == 'nop': - if self._show_button_hit(blk.spr, x, y): + if show_button_hit(blk.spr, x, y): n = len(blk.connections) - group = self._find_group(blk.connections[n-1]) + group = find_group(blk.connections[n-1]) if blk.name == 'myfunc1arg': - blk.spr.labels[1] = 'f(x,y)' + blk.spr.labels[1] = 'f(x, y)' blk.spr.labels[2] = ' ' dy = blk.add_arg() blk.primitive = 'myfunction2' blk.name = 'myfunc2arg' elif blk.name == 'myfunc2arg': - blk.spr.labels[1] = 'f(x,y,z)' + blk.spr.labels[1] = 'f(x, y, z)' dy = blk.add_arg(False) blk.primitive = 'myfunction3' blk.name = 'myfunc3arg' @@ -1435,8 +1331,8 @@ class TurtleArtWindow(): blk.name = 'userdefined3args' else: dy = blk.add_arg() - for b in group: - b.spr.move_relative((0, dy)) + for gblk in group: + gblk.spr.move_relative((0, dy)) blk.connections.append(blk.connections[n-1]) argname = blk.docks[n-1][0] argvalue = DEFAULTS[blk.name][len(DEFAULTS[blk.name])-1] @@ -1444,332 +1340,73 @@ class TurtleArtWindow(): 0, 0, 'block', [argvalue], self.block_scale) argdock = argblk.docks[0] (bx, by) = blk.spr.get_xy() - nx = bx+blk.docks[n-1][2]-argdock[2] - ny = by+blk.docks[n-1][3]-argdock[3] + nx = bx + blk.docks[n - 1][2] - argdock[2] + ny = by + blk.docks[n - 1][3] - argdock[3] argblk.spr.move((nx, ny)) argblk.spr.set_layer(TOP_LAYER) argblk.connections = [blk, None] - blk.connections[n-1] = argblk - self._grow_stack_arm(self._find_sandwich_top(blk)) - elif blk.name in PYTHON_SKIN and self.myblock==None: + blk.connections[n - 1] = argblk + grow_stack_arm(find_sandwich_top(blk)) + elif blk.name in PYTHON_SKIN and self.myblock == None: self._import_py() else: self._run_stack(blk) elif blk.name in COLLAPSIBLE: - top = self._find_sandwich_top(blk) - if self._collapsed(blk): - self._restore_stack(top) + top = find_sandwich_top(blk) + if collapsed(blk): + restore_stack(top) elif top is not None: - self._collapse_stack(top) + collapse_stack(top) else: self._run_stack(blk) - """ - Collapsible stacks live between 'sandwichtop' and 'sandwichbottom' blocks - What follows are a number of utilities for managing collapsible stacks. - Alas, corner-cases abound. - """ - - """ - From the top, find and restore any collapsible stacks on forks. - """ - def _uncollapse_forks(self, top, looping=False): - if top == None: - return - if looping and top.name == 'sandwichtop' or top.name == 'sandwichtop2': - self._restore_stack(top) - return - if len(top.connections) == 0: - return - b = top.connections[len(top.connections)-1] - while b is not None: - if b.name in COLLAPSIBLE: - return - if b.name == 'sandwichtop' or b.name == 'sandwichtop2': - self._restore_stack(b) - return - # Follow a fork - if b.name in ['repeat','if','ifelse','forever','while','until']: - top = self._find_sandwich_top_below( - b.connections[len(b.connections)-2]) - if top is not None: - self._uncollapse_forks(top, True) - if b.name == 'ifelse': - top = self._find_sandwich_top_below( - b.connections[len(b.connections)-3]) - if top is not None: - self._uncollapse_forks(top, True) - b = b.connections[len(b.connections)-1] - return - - """ - Find the sandwich top above this block. - """ - def _find_sandwich_top(self, blk): - # Always follow the main branch of a flow: the first connection. - b = blk.connections[0] - while b is not None: - if b.name in COLLAPSIBLE: - return None - if b.name in ['repeat', 'if', 'ifelse', 'forever', 'while']: - if blk != b.connections[len(b.connections)-1]: - return None - if b.name == 'sandwichtop' or b.name == 'sandwichtop2': - return b - blk = b - b = b.connections[0] - return None - - """ - Find the sandwich bottom below this block. - """ - def _find_sandwich_bottom(self, blk): - # Always follow the main branch of a flow: the last connection. - b = blk.connections[len(blk.connections)-1] - while b is not None: - if b.name == 'sandwichtop' or b.name == 'sandwichtop2': - return None - if b.name in COLLAPSIBLE: - return b - b = b.connections[len(b.connections)-1] - return None - - """ - Find the sandwich top below this block. - """ - def _find_sandwich_top_below(self, blk): - if blk.name == 'sandwichtop' or blk.name == 'sandwichtop2': - return blk - # Always follow the main branch of a flow: the last connection. - b = blk.connections[len(blk.connections)-1] - while b is not None: - if b.name == 'sandwichtop' or b.name == 'sandwichtop2': - return b - b = b.connections[len(b.connections)-1] - return None - - """ - Hide all the blocks between the sandwich top and sandwich bottom. - """ - def _collapse_stack(self, top): - # First uncollapse any nested stacks - self._uncollapse_forks(top) - hit_bottom = False - bot = self._find_sandwich_bottom(top) - group = self._find_group(top.connections[len(top.connections)-1]) - for b in group: - if not hit_bottom and b == bot: - hit_bottom = True - - # Replace 'sandwichbottom' shape with 'sandwichcollapsed' shape - if len(b.values) == 0: - b.values.append(1) - else: - b.values[0] = 1 - olddx = b.docks[1][2] - olddy = b.docks[1][3] - b.name = 'sandwichcollapsed' - b.svg.set_show(True) - b.svg.set_hide(False) - b._dx = 0 - b._ey = 0 - b.spr.set_label(' ') - b.resize() - b.spr.set_label(_('click to open')) - b.resize() - - # Redock to sandwich top in group - you = self._find_sandwich_top(b) - (yx, yy) = you.spr.get_xy() - yd = you.docks[len(you.docks)-1] - (bx, by) = b.spr.get_xy() - dx = yx+yd[2]-b.docks[0][2]-bx - dy = yy+yd[3]-b.docks[0][3]-by - b.spr.move_relative((dx, dy)) - - # Since the shapes have changed, the dock positions have too. - newdx = b.docks[1][2] - newdy = b.docks[1][3] - dx += newdx-olddx - dy += newdy-olddy - else: - if not hit_bottom: - b.spr.set_layer(HIDE_LAYER) - b.status = 'collapsed' - else: - b.spr.move_relative((dx, dy)) - # Remove 'sandwichtop' arm - top.name = 'sandwichtop2' - top.refresh() - # self._reset_stack_arm(top) - - """ - Restore all the blocks between the sandwich top and sandwich bottom. - """ - def _restore_stack(self, top): - group = self._find_group(top.connections[len(top.connections)-1]) - hit_bottom = False - bot = self._find_sandwich_bottom(top) - for b in group: - if not hit_bottom and b == bot: - hit_bottom = True - if len(b.values) == 0: - b.values.append(0) - else: - b.values[0] = 0 - olddx = b.docks[1][2] - olddy = b.docks[1][3] - # Replace 'sandwichcollapsed' shape with 'sandwichbottom' shape - b.name = 'sandwichbottom' - b.spr.set_label(' ') - b.svg.set_show(False) - b.svg.set_hide(True) - b.refresh() - - # Redock to previous block in group - you = b.connections[0] - (yx, yy) = you.spr.get_xy() - yd = you.docks[len(you.docks)-1] - (bx, by) = b.spr.get_xy() - dx = yx+yd[2]-b.docks[0][2]-bx - dy = yy+yd[3]-b.docks[0][3]-by - b.spr.move_relative((dx, dy)) - - # Since the shapes have changed, the dock positions have too. - newdx = b.docks[1][2] - newdy = b.docks[1][3] - dx += newdx-olddx - dy += newdy-olddy - else: - if not hit_bottom: - b.spr.set_layer(BLOCK_LAYER) - b.status = None - else: - b.spr.move_relative((dx, dy)) - - # Add 'sandwichtop' arm - top.name = 'sandwichtop' - top.refresh() - self._grow_stack_arm(top) - - """ - When we undock, retract the 'arm' that extends down from 'sandwichtop'. - """ - def _reset_stack_arm(self, top): - if top is not None and top.name == 'sandwichtop': - if top.ey > 0: - top.reset_y() - - """ - When we dock, grow an 'arm' the length of the stack from 'sandwichtop'. - """ - def _grow_stack_arm(self, top): - if top is not None and top.name == 'sandwichtop': - bot = self._find_sandwich_bottom(top) - if bot is None: - return - if top.ey > 0: - top.reset_y() - tx, ty = top.spr.get_xy() - tw, th = top.spr.get_dimensions() - bx, by = bot.spr.get_xy() - dy = by-(ty+th) - if dy > 0: - top.expand_in_y(dy/top.scale) - top.refresh() - - """ - Check the state of collapsible blocks upon change in dock state. - """ def _check_collapsibles(self, blk): - group = self._find_group(blk) - for b in group: - if b.name in COLLAPSIBLE: - if self._collapsed(b): - b.svg.set_show(True) - b.svg.set_hide(False) - self._reset_stack_arm(self._find_sandwich_top(b)) - elif self._collapsible(b): - b.svg.set_hide(True) - b.svg.set_show(False) - self._grow_stack_arm(self._find_sandwich_top(b)) + """ Check the state of collapsible blocks upon change in dock state. """ + group = find_group(blk) + for gblk in group: + if gblk.name in COLLAPSIBLE: + if collapsed(gblk): + gblk.svg.set_show(True) + gblk.svg.set_hide(False) + reset_stack_arm(find_sandwich_top(gblk)) + elif collapsible(gblk): + gblk.svg.set_hide(True) + gblk.svg.set_show(False) + grow_stack_arm(find_sandwich_top(gblk)) else: - b.svg.set_hide(False) - b.svg.set_show(False) + gblk.svg.set_hide(False) + gblk.svg.set_show(False) # Ouch: When you tear off the sandwich bottom, you # no longer have access to the group with the sandwich top # so check them all. - for bb in self.just_blocks(): - if bb.name == 'sandwichtop': - if self._find_sandwich_bottom(bb) is None: - self._reset_stack_arm(bb) - b.refresh() - - """ - Is this stack collapsed? - """ - def _collapsed(self, blk): - if blk is not None and blk.name in COLLAPSIBLE and\ - len(blk.values) == 1 and blk.values[0] != 0: - return True - return False + for b in self.just_blocks(): + if b.name == 'sandwichtop': + if find_sandwich_bottom(b) is None: + reset_stack_arm(b) + gblk.refresh() - """ - Can this stack be collapsed? - """ - def _collapsible(self, blk): - if blk is None or blk.name not in COLLAPSIBLE: - return False - if self._find_sandwich_top(blk) is None: - return False - return True - - """ - Run a stack of blocks. - """ def _run_stack(self, blk): + """ Run a stack of blocks. """ if blk is None: return self.lc.ag = None - top = self.find_top_block(blk) + top = find_top_block(blk) self.lc.run_blocks(top, self.just_blocks(), True) gobject.idle_add(self.lc.doevalstep) - """ - Did the sprite's hide (contract) button get hit? - """ - def _hide_button_hit(self, spr, x, y): - r,g,b,a = spr.get_pixel((x, y)) - if (r == 255 and g == 0) or g == 255: - return True - else: - return False - - """ - Did the sprite's show (expand) button get hit? - """ - def _show_button_hit(self, spr, x, y): - r,g,b,a = spr.get_pixel((x, y)) - if g == 254: - return True - else: - return False - - """ - Snap a block to the dock of another block. - """ def _snap_to_dock(self): + """ Snap a block to the dock of another block. """ my_block = self.drag_group[0] d = 200 for my_dockn in range(len(my_block.docks)): - for i, your_block in enumerate(self.just_blocks()): + for your_block in self.just_blocks(): # don't link to a block to which you're already connected if your_block in self.drag_group: continue # check each dock of your_block for a possible connection for your_dockn in range(len(your_block.docks)): - this_xy = self._dock_dx_dy(your_block, your_dockn, - my_block, my_dockn) + this_xy = dock_dx_dy(your_block, your_dockn, + my_block, my_dockn) if magnitude(this_xy) > d: continue d = magnitude(this_xy) @@ -1777,13 +1414,13 @@ class TurtleArtWindow(): best_you = your_block best_your_dockn = your_dockn best_my_dockn = my_dockn - if d<200: - if not self._arithmetic_check(my_block, best_you, best_my_dockn, - best_your_dockn): + if d < 200: + if not arithmetic_check(my_block, best_you, best_my_dockn, + best_your_dockn): return for blk in self.drag_group: (sx, sy) = blk.spr.get_xy() - blk.spr.move((sx+best_xy[0], sy+best_xy[1])) + blk.spr.move((sx + best_xy[0], sy + best_xy[1])) # If there was already a block docked there, move it to the trash. blk_in_dock = best_you.connections[best_your_dockn] @@ -1795,87 +1432,8 @@ class TurtleArtWindow(): if my_block.connections is not None: my_block.connections[best_my_dockn] = best_you - """ - Additional docking check for arithmetic blocks: dock strings only if they - convert to numbers. Also, avoid /0 and root(-1) - """ - def _arithmetic_check(self, b1, b2, d1, d2): - if b1 == None or b2 == None: - return True - if b1.name in ['sqrt', 'number', 'string'] and\ - b2.name in ['sqrt', 'number', 'string']: - if b1.name == 'number' or b1.name == 'string': - if not numeric_arg(b1.values[0]) or neg_arg(b1.values[0]): - return False - elif b2.name == 'number' or b2.name == 'string': - if not numeric_arg(b2.values[0]) or neg_arg(b2.values[0]): - return False - elif b1.name in ['division2', 'number', 'string'] and\ - b2.name in ['division2', 'number', 'string']: - if b1.name == 'number' or b1.name == 'string': - if not numeric_arg(b1.values[0]): - return False - if d2 == 2 and zero_arg(b1.values[0]): - return False - elif b2.name == 'number' or b2.name == 'string': - if not numeric_arg(b2.values[0]): - return False - if d1 == 2 and zero_arg(b2.values[0]): - return False - elif b1.name in ['product2', 'minus2', 'random', 'remainder2', - 'string'] and\ - b2.name in ['product2', 'minus2', 'random', 'remainder2', - 'string']: - if b1.name == 'string': - if not numeric_arg(b1.values[0]): - return False - elif b1.name == 'string': - if not numeric_arg(b2.values[0]): - return False - elif b1.name in ['greater2', 'less2'] and b2.name == 'string': - # Non-numeric stings are OK if only both args are strings; - # Lots of test conditions... - if d1 == 1 and b1.connections[2] is not None: - if b1.connections[2].name == 'number': - if not numeric_arg(b2.values[0]): - return False - elif d1 == 2 and b1.connections[1] is not None: - if b1.connections[1].name == 'number': - if not numeric_arg(b2.values[0]): - return False - elif b2.name in ['greater2', 'less2'] and b1.name == 'string': - if d2 == 1 and b2.connections[2] is not None: - if b2.connections[2].name == 'number': - if not numeric_arg(b1.values[0]): - return False - elif d2 == 2 and b2.connections[1] is not None: - if b2.connections[1].name == 'number': - if not numeric_arg(b1.values[0]): - return False - elif b1.name in ['greater2', 'less2'] and b2.name == 'number': - if d1 == 1 and b1.connections[2] is not None: - if b1.connections[2].name == 'string': - if not numeric_arg(b1.connections[2].values[0]): - return False - elif d1 == 2 and b1.connections[1] is not None: - if b1.connections[1].name == 'string': - if not numeric_arg(b1.connections[1].values[0]): - return False - elif b2.name in ['greater2', 'less2'] and b1.name == 'number': - if d2 == 1 and b2.connections[2] is not None: - if b2.connections[2].name == 'string': - if not numeric_arg(b2.connections[2].values[0]): - return False - elif d2 == 2 and b2.connections[1] is not None: - if b2.connections[1].name == 'string': - if not numeric_arg(b2.connections[1].values[0]): - return False - return True - - """ - Import a file from the Sugar Journal - """ def _import_from_journal(self, blk): + """ Import a file from the Sugar Journal """ if self.running_sugar: chooser = ObjectChooser('Choose image', None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) @@ -1895,36 +1453,19 @@ class TurtleArtWindow(): return self._update_media_icon(blk, fname) - """ - When we load a journal block, look for a corresponding description block - """ def _load_description_block(self, blk): + """ Look for a corresponding description block """ if blk == None or blk.name != 'journal' or len(blk.values) == 0 or\ blk.connections[0] is None: return - cblk = blk.connections[0] - dblk = self._find_blk_below(cblk, 'description') - # Only autoupdate the block if it is empty + _blk = blk.connections[0] + dblk = find_blk_below(_blk, 'description') + # Autoupdate the block if it is empty if dblk != None and (len(dblk.values) == 0 or dblk.values[0] == None): - # Copy the dsobject id and update the icon self._update_media_icon(dblk, None, blk.values[0]) - """ - Find a specific block below this block. - """ - def _find_blk_below(self, blk, name): - if blk == None or len(blk.connections) == 0: - return - group = self._find_group(blk) - for b in group: - if b.name == name: - return b - return None - - """ - Update the icon on a 'loaded' media block. - """ def _update_media_icon(self, blk, name, value=''): + """ Update the icon on a 'loaded' media block. """ if blk.name == 'journal': self._load_image_thumb(name, blk) elif blk.name == 'audio': @@ -1933,16 +1474,14 @@ class TurtleArtWindow(): self._block_skin('descriptionon', blk) if value == '': value = name - if len(blk.values)>0: + if len(blk.values) > 0: blk.values[0] = value else: blk.values.append(value) blk.spr.set_label(' ') - """ - Replace icon with a preview image. - """ def _load_image_thumb(self, picture, blk): + """ Replace icon with a preview image. """ pixbuf = None self._block_skin('descriptionon', blk) @@ -1965,57 +1504,18 @@ class TurtleArtWindow(): blk.set_image(pixbuf, x, y) self._resize_skin(blk) - """ - Disconnect block from stack above it. - """ def _disconnect(self, blk): - if blk.connections[0]==None: + """ Disconnect block from stack above it. """ + if blk.connections[0] == None: return - if self._collapsed(blk): + if collapsed(blk): return - blk2=blk.connections[0] + blk2 = blk.connections[0] blk2.connections[blk2.connections.index(blk)] = None blk.connections[0] = None - """ - Find the distance between the dock points of two blocks. - """ - def _dock_dx_dy(self, block1, dock1n, block2, dock2n): - dock1 = block1.docks[dock1n] - dock2 = block2.docks[dock2n] - d1type, d1dir, d1x, d1y = dock1[0:4] - d2type, d2dir, d2x, d2y = dock2[0:4] - if block1 == block2: - return (100,100) - if d1dir == d2dir: - return (100,100) - if (d2type is not 'number') or (dock2n is not 0): - if block1.connections is not None and \ - dock1n < len(block1.connections) and \ - block1.connections[dock1n] is not None: - return (100,100) - if block2.connections is not None and \ - dock2n < len(block2.connections) and \ - block2.connections[dock2n] is not None: - return (100,100) - if d1type != d2type: - if block1.name in STRING_OR_NUMBER_ARGS: - if d2type == 'number' or d2type == 'string': - pass - elif block1.name in CONTENT_ARGS: - if d2type in CONTENT_BLOCKS: - pass - else: - return (100,100) - (b1x, b1y) = block1.spr.get_xy() - (b2x, b2y) = block2.spr.get_xy() - return ((b1x+d1x)-(b2x+d2x), (b1y+d1y)-(b2y+d2y)) - - - """ - Keyboard - """ def _keypress_cb(self, area, event): + """ Keyboard """ keyname = gtk.gdk.keyval_name(event.keyval) keyunicode = gtk.gdk.keyval_to_unicode(event.keyval) @@ -2025,9 +1525,9 @@ class TurtleArtWindow(): else: alt_mask = False alt_flag = 'F' - results = self._key_press(alt_mask, keyname, keyunicode) + self._key_press(alt_mask, keyname, keyunicode) if keyname is not None and self._sharing(): - self.activity._send_event("k:%s:%s:%s" % (alt_flag, keyname, + self.activity.send_event("k:%s:%s:%s" % (alt_flag, keyname, str(keyunicode))) return keyname @@ -2041,21 +1541,21 @@ class TurtleArtWindow(): # First, process Alt keys. if alt_mask and self.selected_blk is not None: - if keyname=="i" and self._sharing(): + if keyname == "i" and self._sharing(): self.activity.waiting_for_blocks = True - self.activity._send_event("i") # request sync for sharing - elif keyname=="p": + self.activity.send_event("i") # request sync for sharing + elif keyname == "p": self.hideshow_button() - elif keyname=='q': + elif keyname == 'q': exit() return True # Process keyboard input for 'number' blocks - if self.selected_blk is not None and\ + if self.selected_blk is not None and \ self.selected_blk.name == 'number': self._process_numeric_input(keyname) return True # Process keyboard input for 'string' blocks - elif self.selected_blk is not None and\ + elif self.selected_blk is not None and \ self.selected_blk.name == 'string': self.process_alphanumeric_input(keyname, keyunicode) if self.selected_blk is not None: @@ -2067,11 +1567,9 @@ class TurtleArtWindow(): if self.selected_blk is None: return False - ''' - Make sure numeric input is valid. - ''' def _process_numeric_input(self, keyname): - oldnum = self.selected_blk.spr.labels[0].replace(CURSOR,'') + ''' Make sure numeric input is valid. ''' + oldnum = self.selected_blk.spr.labels[0].replace(CURSOR, '') if len(oldnum) == 0: oldnum = '0' if keyname == 'minus': @@ -2088,7 +1586,7 @@ class TurtleArtWindow(): newnum = oldnum[:len(oldnum)-1] else: newnum = '' - elif keyname in ['0','1','2','3','4','5','6','7','8','9']: + elif keyname in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: if oldnum == '0': newnum = keyname else: @@ -2103,14 +1601,12 @@ class TurtleArtWindow(): if len(newnum) > 0 and newnum != '-': try: float(newnum) - except ValueError,e: + except ValueError, e: newnum = oldnum self.selected_blk.spr.set_label(newnum + CURSOR) - """ - Make sure alphanumeric input is properly parsed. - """ def process_alphanumeric_input(self, keyname, keyunicode): + """ Make sure alphanumeric input is properly parsed. """ if len(self.selected_blk.spr.labels[0]) > 0: c = self.selected_blk.spr.labels[0].count(CURSOR) if c == 0: @@ -2121,7 +1617,7 @@ class TurtleArtWindow(): oldright = '' else: try: # Why are getting a ValueError on occasion? - oldleft, oldright =\ + oldleft, oldright = \ self.selected_blk.spr.labels[0].split(CURSOR) except ValueError: print "[%s]" % self.selected_blk.spr.labels[0] @@ -2131,7 +1627,7 @@ class TurtleArtWindow(): oldleft = '' oldright = '' newleft = oldleft - if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock',\ + if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', \ 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift']: keyname = '' keyunicode = 0 @@ -2174,7 +1670,7 @@ class TurtleArtWindow(): return else: if self.dead_key is not '': - keyunicode =\ + keyunicode = \ DEAD_DICTS[DEAD_KEYS.index(self.dead_key[5:])][keyname] self.dead_key = '' if keyunicode > 0: @@ -2189,16 +1685,14 @@ class TurtleArtWindow(): newleft = oldleft+keyname self.selected_blk.spr.set_label("%s%s%s" % (newleft, CURSOR, oldright)) - """ - Use the keyboard to move blocks and turtle - """ def _process_keyboard_commands(self, keyname): - mov_dict = {'KP_Up':[0,10],'j':[0,10],'Up':[0,10], - 'KP_Down':[0,-10],'k':[0,-10],'Down':[0,-10], - 'KP_Left':[-10,0],'h':[-10,0],'Left':[-10,0], - 'KP_Right':[10,0],'l':[10,0],'Right':[10,0], - 'KP_Page_Down':[0,0], 'KP_Page_Up':[0,0], 'KP_End':[0,0], - 'KP_Home':[-1,-1],'Return':[-1,-1], 'Esc':[0,0]} + """ Use the keyboard to move blocks and turtle """ + mov_dict = {'KP_Up':[0, 10], 'j':[0, 10], 'Up':[0, 10], + 'KP_Down':[0, -10], 'k':[0, -10], 'Down':[0, -10], + 'KP_Left':[-10, 0], 'h':[-10, 0], 'Left':[-10, 0], + 'KP_Right':[10, 0], 'l':[10, 0], 'Right':[10, 0], + 'KP_Page_Down':[0, 0], 'KP_Page_Up':[0, 0], 'KP_End':[0, 0], + 'KP_Home':[-1, -1], 'Return':[-1, -1], 'Esc':[0, 0]} if not mov_dict.has_key(keyname): return if keyname == 'KP_End': @@ -2212,8 +1706,9 @@ class TurtleArtWindow(): self._click_block(x, y) elif keyname == 'KP_Page_Down': if self.drag_group == None: - self.drag_group = self._find_group(blk) - for b in self.drag_group: b.spr.hide() + self.drag_group = find_group(blk) + for gblk in self.drag_group: + gblk.spr.hide() self.drag_group = None else: self._jog_block(blk, mov_dict[keyname][0], @@ -2222,10 +1717,8 @@ class TurtleArtWindow(): self._jog_turtle(mov_dict[keyname][0], mov_dict[keyname][1]) return True - """ - Jog turtle - """ def _jog_turtle(self, dx, dy): + """ Jog turtle """ if dx == -1 and dy == -1: self.canvas.xcor = 0 self.canvas.ycor = 0 @@ -2236,30 +1729,26 @@ class TurtleArtWindow(): self.display_coordinates() self.selected_turtle = None - """ - Jog block - """ def _jog_block(self, blk, dx, dy): - if self._collapsed(blk): + """ Jog block """ + if collapsed(blk): return - self.drag_group = self._find_group(blk) + self.drag_group = find_group(blk) # check to see if any block ends up with a negative x for blk in self.drag_group: (sx, sy) = blk.spr.get_xy() if sx+dx < 0: - dx += -(sx+dx) + dx += -(sx + dx) # move the stack for blk in self.drag_group: (sx, sy) = blk.spr.get_xy() - blk.spr.move((sx+dx, sy-dy)) + blk.spr.move((sx + dx, sy - dy)) self._snap_to_dock() self.drag_group = None - """ - Make sure a 'number' block contains a number. - """ def _number_check(self): - n = self.selected_blk.spr.labels[0].replace(CURSOR,'') + """ Make sure a 'number' block contains a number. """ + n = self.selected_blk.spr.labels[0].replace(CURSOR, '') if n in ['-', '.', '-.']: n = 0 if n is not None: @@ -2280,87 +1769,74 @@ class TurtleArtWindow(): self.selected_blk.values[0] = n def _string_check(self): - s = self.selected_blk.spr.labels[0].replace(CURSOR,'') + s = self.selected_blk.spr.labels[0].replace(CURSOR, '') self.selected_blk.spr.set_label(s) - self.selected_blk.values[0] = s.replace(RETURN,"\12") + self.selected_blk.values[0] = s.replace(RETURN, "\12") - """ - Load Python code from a file - """ def load_python_code(self): + """ Load Python code from a file """ fname, self.load_save_folder = get_load_name('.py', self.load_save_folder) - if fname==None: + if fname == None: return f = open(fname, 'r') self.myblock = f.read() f.close() - """ - Import Python code into a block - """ def _import_py(self): + """ Import Python code into a block """ if self.running_sugar: self.activity.import_py() else: self.load_python_code() self.set_userdefined() - """ - Start a new project - """ def new_project(self): + """ Start a new project """ stop_logo(self) # Put current project in the trash. while len(self.just_blocks()) > 0: - b = self.just_blocks()[0] - top = self.find_top_block(b) + blk = self.just_blocks()[0] + top = find_top_block(blk) self._put_in_trash(top) self.canvas.clearscreen() self.save_file_name = None - """ - Load a project from a file - """ def load_files(self, ta_file, create_new_project=True): + """ Load a project from a file """ if create_new_project: self.new_project() - top = self.process_data(data_from_file(ta_file)) - self._check_collapsibles(top) + self._check_collapsibles(self.process_data(data_from_file(ta_file))) def load_file(self, create_new_project=True): - fname, self.load_save_folder = get_load_name('.ta', + _file_name, self.load_save_folder = get_load_name('.ta', self.load_save_folder) - if fname==None: + if _file_name == None: return - if fname[-3:] == '.ta': - fname=fname[0:-3] - self.load_files(fname+'.ta', create_new_project) + if _file_name[-3:] == '.ta': + _file_name = _file_name[0:-3] + self.load_files(_file_name+'.ta', create_new_project) if create_new_project: - self.save_file_name = os.path.basename(fname) - - """ - Turtles are either [-1, 'turtle', ...] or [-1, ['turtle', key], ...] - """ - def _found_a_turtle(self, b): - if b[1] == 'turtle': - self.load_turtle(b) + self.save_file_name = os.path.basename(_file_name) + + def _found_a_turtle(self, blk): + """ Either [-1, 'turtle', ...] or [-1, ['turtle', key], ...] """ + if blk[1] == 'turtle': + self.load_turtle(blk) return True - elif type(b[1]) == list and b[1][0] == 'turtle': - self.load_turtle(b, b[1][1]) + elif type(blk[1]) == list and blk[1][0] == 'turtle': + self.load_turtle(blk, blk[1][1]) return True - elif type(b[1]) == tuple: - btype, key = b[1] - if btype == 'turtle': - self.load_turtle(b, key) + elif type(blk[1]) == tuple: + _btype, _key = blk[1] + if _btype == 'turtle': + self.load_turtle(blk, _key) return True return False - """ - Restore a turtle from its saved state - """ - def load_turtle(self, b, key=1): - id, name, xcor, ycor, heading, color, shade, pensize = b + def load_turtle(self, blk, key=1): + """ Restore a turtle from its saved state """ + tid, name, xcor, ycor, heading, color, shade, pensize = blk self.canvas.set_turtle(key) self.canvas.setxy(xcor, ycor) self.canvas.seth(heading) @@ -2368,12 +1844,10 @@ class TurtleArtWindow(): self.canvas.setshade(shade) self.canvas.setpensize(pensize) - """ - Restore individual blocks from saved state - """ def load_block(self, b): + """ Restore individual blocks from saved state """ # A block is saved as: (i, (btype, value), x, y, (c0,... cn)) - # The x,y position is saved/loaded for backward compatibility + # The x, y position is saved/loaded for backward compatibility btype, value = b[1], None if type(btype) == tuple: btype, value = btype @@ -2402,8 +1876,8 @@ class TurtleArtWindow(): if OLD_NAMES.has_key(btype): btype = OLD_NAMES[btype] blk = Block(self.block_list, self.sprite_list, - btype, b[2]+self.canvas.cx, b[3]+self.canvas.cy, 'block', - values, self.block_scale) + btype, b[2] + self.canvas.cx, b[3] + self.canvas.cy, + 'block', values, self.block_scale) # Some blocks get transformed. if btype == 'string': blk.spr.set_label(blk.values[0].replace('\n', RETURN)) @@ -2416,12 +1890,12 @@ class TurtleArtWindow(): blk.expand_in_x(value) elif btype == 'templatelist' or btype == 'list': for i in range(len(b[4])-4): - dy = blk.add_arg() + blk.add_arg() elif btype == 'myfunc2arg' or btype == 'myfunc3arg' or\ btype == 'userdefined2args' or btype == 'userdefined3args': - dy = blk.add_arg() + blk.add_arg() if btype == 'myfunc3arg' or btype == 'userdefined3args': - dy = blk.add_arg(False) + blk.add_arg(False) if btype in PYTHON_SKIN: if self.nop == 'pythonloaded': self._block_skin('pythonon', blk) @@ -2453,7 +1927,7 @@ class TurtleArtWindow(): x, y = self._calc_image_offset('', blk.spr) blk.set_image(pixbuf, x, y) except: - print "Warning: Couldn't open dsobject (%s)" %\ + print "Warning: Couldn't open dsobject (%s)" % \ (blk.values[0]) self._block_skin('journaloff', blk) else: @@ -2476,86 +1950,77 @@ class TurtleArtWindow(): blk.connections = 'check' return blk - """ - Start a new project with a 'start' brick - """ - def load_start(self): - top = self.process_data([[0, "start", PALETTE_WIDTH+20, - self.toolbar_offset+PALETTE_HEIGHT+20, - [None, None]]]) + def load_start(self): + """ Start a new project with a 'start' brick """ + self.process_data([[0, "start", PALETTE_WIDTH + 20, + self.toolbar_offset+PALETTE_HEIGHT + 20, + [None, None]]]) - """ - Start a project to a file - """ def save_file(self): + """ Start a project to a file """ if self.save_folder is not None: self.load_save_folder = self.save_folder - fname, self.load_save_folder = get_save_name('.ta', + _file_name, self.load_save_folder = get_save_name('.ta', self.load_save_folder, self.save_file_name) - if fname is None: + if _file_name is None: return - if fname[-3:]=='.ta': - fname=fname[0:-3] - data = self.assemble_data_to_save() - data_to_file(data, fname+'.ta') - self.save_file_name = os.path.basename(fname) - - """ - Pack the project (or stack) into a data stream to be serialized - """ + if _file_name[-3:] == '.ta': + _file_name = _file_name[0:-3] + data_to_file(self.assemble_data_to_save(), _file_name + '.ta') + self.save_file_name = os.path.basename(_file_name) + def assemble_data_to_save(self, save_turtle=True, save_project=True): - data = [] - blks = [] + """ Pack the project (or stack) into a data stream to be serialized """ + _data = [] + _blks = [] if save_project: - blks = self.just_blocks() + _blks = self.just_blocks() else: - blks = self._find_group(self.find_top_block(self.selected_blk)) + _blks = find_group(find_top_block(self.selected_blk)) - for i, b in enumerate(blks): - b.id = i - for b in blks: - if b.name in CONTENT_BLOCKS or b.name in COLLAPSIBLE: - if len(b.values)>0: - name = (b.name, b.values[0]) + for _i, _blk in enumerate(_blks): + _blk.id = _i + for _blk in _blks: + if _blk.name in CONTENT_BLOCKS or _blk.name in COLLAPSIBLE: + if len(_blk.values) > 0: + _name = (_blk.name, _blk.values[0]) else: - name = (b.name) - elif b.name in EXPANDABLE: - ex, ey = b.get_expand_x_y() - if ex > 0: - name = (b.name, ex) - elif ey > 0: - name = (b.name, ey) + _name = (_blk.name) + elif _blk.name in EXPANDABLE: + _ex, _ey = _blk.get_expand_x_y() + if _ex > 0: + _name = (_blk.name, _ex) + elif _ey > 0: + _name = (_blk.name, _ey) else: - name = (b.name, 0) + _name = (_blk.name, 0) else: - name = (b.name) - if hasattr(b, 'connections'): - connections = [get_id(c) for c in b.connections] + _name = (_blk.name) + if hasattr(_blk, 'connections'): + connections = [get_id(_cblk) for _cblk in _blk.connections] else: connections = None - (sx, sy) = b.spr.get_xy() + (_sx, _sy) = _blk.spr.get_xy() # Add a slight offset for copy/paste if not save_project: - sx+=20 - sy+=20 - data.append((b.id, name, sx-self.canvas.cx, sy-self.canvas.cy, - connections)) + _sx += 20 + _sy += 20 + _data.append((_blk.id, _name, _sx-self.canvas.cx, + _sy-self.canvas.cy, connections)) if save_turtle: - for k in iter(self.turtles.dict): - self.canvas.set_turtle(k) - data.append((-1,['turtle', k], + for _turtle in iter(self.turtles.dict): + self.canvas.set_turtle(_turtle) + _data.append((-1, ['turtle', _turtle], self.canvas.xcor, self.canvas.ycor, self.canvas.heading, self.canvas.color, self.canvas.shade, self.canvas.pensize)) - return data + return _data - """ - Display the coordinates of the current turtle on the toolbar - """ def display_coordinates(self): + """ Display the coordinates of the current turtle on the toolbar """ x = round_int(self.canvas.xcor/self.coord_scale) y = round_int(self.canvas.ycor/self.coord_scale) h = round_int(self.canvas.heading) @@ -2567,10 +2032,8 @@ class TurtleArtWindow(): self.win.set_title("%s — %s: %d %s: %d %s: %d" % (_("Turtle Art"), _("xcor"), x, _("ycor"), y, _("heading"), h)) - """ - Display a message on a status block - """ - def showlabel(self, shp, label=''): + def showlabel(self, shp, label = ''): + """ Display a message on a status block """ if shp == 'syntaxerror' and str(label) != '': if self.status_shapes.has_key(str(label)[1:]): shp = str(label)[1:] @@ -2580,7 +2043,7 @@ class TurtleArtWindow(): elif shp[0] == '#': shp = shp[1:] label = '' - if shp=='notanumber': + if shp == 'notanumber': shp = 'overflowerror' self.status_spr.set_shape(self.status_shapes[shp]) self.status_spr.set_label(str(label)) @@ -2590,23 +2053,19 @@ class TurtleArtWindow(): else: self.status_spr.move((PALETTE_WIDTH, self.height-200)) - """ - Relative placement of portfolio objects (used by depreciated blocks) - """ - def calc_position(self, t): - w,h,x,y,dx,dy = TEMPLATES[t] + def calc_position(self, template): + """ Relative placement of portfolio objects (depreciated) """ + w, h, x, y, dx, dy = TEMPLATES[template] x *= self.canvas.width y *= self.canvas.height w *= (self.canvas.width-x) h *= (self.canvas.height-y) dx *= w dy *= h - return(w,h,x,y,dx,dy) + return(w, h, x, y, dx, dy) - """ - Grab the current canvas and save it. - """ def save_as_image(self, name="", svg=False): + """ Grab the current canvas and save it. """ if self.running_sugar: if svg: @@ -2670,98 +2129,37 @@ class TurtleArtWindow(): datastore.write(dsobject) dsobject.destroy() - """ - Where is the mouse event? - """ - def _xy(self, event): - return map(int, event.get_coords()) - - """ - Utilities related to finding blocks in stacks. - """ - - """ - Find a stack to run (any stack without a 'def action'on the top). - """ - def _find_block_to_run(self, blk): - top = self.find_top_block(blk) - if blk == top and blk.name[0:3] is not 'def': - return True - else: - return False - - """ - Find the top block in a stack. - """ - def find_top_block(self, blk): - if len(blk.connections) == 0: - return blk - while blk.connections[0] is not None: - blk = blk.connections[0] - return blk - - """ - Find a stack with a 'start' block on top. - """ - def _find_start_stack(self, blk): - top = self.find_top_block(blk) - if top.name == 'start': - return True - else: - return False - - """ - Find the connected group of block in a stack. - """ - def _find_group(self, blk): - if blk is None: - return [] - group=[blk] - if blk.connections is not None: - for blk2 in blk.connections[1:]: - if blk2 is not None: - group.extend(self._find_group(blk2)) - return group - - """ - Filter out 'proto', 'trash', and 'deleted' blocks - """ def just_blocks(self): + """ Filter out 'proto', 'trash', and 'deleted' blocks """ just_blocks_list = [] - for b in self.block_list.list: - if b.type == 'block': - just_blocks_list.append(b) + for _blk in self.block_list.list: + if _blk.type == 'block': + just_blocks_list.append(_blk) return just_blocks_list - """ - What are the width and height of a stack? - """ def _width_and_height(self, blk): + """ What are the width and height of a stack? """ minx = 10000 miny = 10000 maxx = -10000 maxy = -10000 - for b in self._find_group(blk): - (x, y) = b.spr.get_xy() - w, h = b.spr.get_dimensions() - if xmaxx: - maxx = x+w - if y+h>maxy: - maxy = y+h - return(maxx-minx, maxy-miny) - - """ - Utilities related to putting a image 'skin' on a block - """ - - """ - Calculate the postion for placing an image onto a sprite. - """ + if x + w > maxx: + maxx = x + w + if y + h > maxy: + maxy = y + h + return(maxx - minx, maxy - miny) + + # Utilities related to putting a image 'skin' on a block + def _calc_image_offset(self, name, spr, iw=0, ih=0): + """ Calculate the postion for placing an image onto a sprite. """ _l, _t = spr.label_left_top() if name == '': return _l, _t @@ -2770,12 +2168,10 @@ class TurtleArtWindow(): if iw == 0: iw = self.media_shapes[name].get_width() ih = self.media_shapes[name].get_height() - return int(_l+(_w-iw)/2), int(_t+(_h-ih)/2) + return int(_l + (_w - iw)/2), int(_t + (_h - ih)/2) - """ - Calculate new image size - """ def _calc_w_h(self, name, spr): + """ Calculate new image size """ target_w = spr.label_safe_width() target_h = spr.label_safe_height() if name == '': @@ -2791,36 +2187,30 @@ class TurtleArtWindow(): new_w = target_w*scale_factor return int(new_w), int(new_h) - """ - Utility for calculating proto skin images - """ def _proto_skin(self, name, n, i): + """ Utility for calculating proto skin images """ x, y = self._calc_image_offset(name, self.palettes[n][i].spr) self.palettes[n][i].spr.set_image(self.media_shapes[name], 1, x, y) - """ - Some blocks get a skin - """ def _block_skin(self, name, blk): + """ Some blocks get a skin """ x, y = self._calc_image_offset(name, blk.spr) blk.set_image(self.media_shapes[name], x, y) self._resize_skin(blk) - """ - Resize the 'skin' when block scale changes. - """ - def _resize_skin(self, b): - if b.name in PYTHON_SKIN: - w, h = self._calc_w_h('pythonoff', b.spr) - x, y = self._calc_image_offset('pythonoff', b.spr, w, h) - elif b.name == 'journal': - if len(b.values) == 1 and b.values[0] is not None: - w, h = self._calc_w_h('', b.spr) - x, y = self._calc_image_offset('journaloff', b.spr, w, h) + def _resize_skin(self, blk): + """ Resize the 'skin' when block scale changes. """ + if blk.name in PYTHON_SKIN: + w, h = self._calc_w_h('pythonoff', blk.spr) + x, y = self._calc_image_offset('pythonoff', blk.spr, w, h) + elif blk.name == 'journal': + if len(blk.values) == 1 and blk.values[0] is not None: + w, h = self._calc_w_h('', blk.spr) + x, y = self._calc_image_offset('journaloff', blk.spr, w, h) else: - w, h = self._calc_w_h('journaloff', b.spr) - x, y = self._calc_image_offset('journaloff', b.spr, w, h) + w, h = self._calc_w_h('journaloff', blk.spr) + x, y = self._calc_image_offset('journaloff', blk.spr, w, h) else: - w, h = self._calc_w_h('descriptionoff', b.spr) - x, y = self._calc_image_offset('descriptionoff', b.spr, w, h) - b.scale_image(x, y, w, h) + w, h = self._calc_w_h('descriptionoff', blk.spr) + x, y = self._calc_image_offset('descriptionoff', blk.spr, w, h) + blk.scale_image(x, y, w, h) diff --git a/turtleart.py b/turtleart.py index 3b887a3..9cad683 100755 --- a/turtleart.py +++ b/turtleart.py @@ -23,10 +23,8 @@ import pygtk pygtk.require('2.0') import gtk -import gobject import os import os.path -import locale from gettext import gettext as _ from taconstants import OVERLAY_LAYER from tautils import data_to_string, data_from_string, get_save_name @@ -34,45 +32,27 @@ from tautils import data_to_string, data_from_string, get_save_name from tawindow import TurtleArtWindow from taexporthtml import save_html -""" -Make a path if it doesn't previously exist -""" def makepath(path): - + """ Make a path if it doesn't previously exist """ from os import makedirs from os.path import normpath, dirname, exists dpath = normpath(dirname(path)) - if not exists(dpath): makedirs(dpath) - -""" -Launch Turtle Art from outside of Sugar -$ python turtleart.py + if not exists(dpath): + makedirs(dpath) -Caveats: - * no Sugar toolbars - * no Sugar Journal access - * no Sugar sharing -""" class TurtleMain(): def __init__(self): + """ Launch Turtle Art from outside of Sugar """ self.i = 0 - self.scale=2.0 - tw = None + self.scale = 2.0 + self.tw = None # make sure Sugar paths are present - tapath = os.path.join(os.environ['HOME'],'.sugar','default', \ + tapath = os.path.join(os.environ['HOME'], '.sugar', 'default', \ 'org.laptop.TurtleArtActivity') - map (makepath, (os.path.join(tapath,'data/'), \ - os.path.join(tapath,'instance/'))) - - """ - Find closest match for the user's $LANG - """ - lang = locale.getdefaultlocale()[0] - if not lang: - lang = 'en' - lang = lang[0:2] - + map (makepath, (os.path.join(tapath, 'data/'), \ + os.path.join(tapath, 'instance/'))) + win = gtk.Window(gtk.WINDOW_TOPLEVEL) try: data_file = open('.turtleartrc', 'r') @@ -88,10 +68,10 @@ class TurtleMain(): self.width = int(data_file.readline()) self.height = int(data_file.readline()) win.set_default_size(self.width, self.height) - win.move(self.x,self.y) + win.move(self.x, self.y) win.maximize() win.set_title(_("Turtle Art")) - win.connect("delete_event", lambda w,e: gtk.main_quit()) + win.connect("delete_event", lambda w, e: gtk.main_quit()) menu = gtk.Menu() @@ -229,25 +209,28 @@ class TurtleMain(): win.show_all() if os.path.exists('/usr/share/turtleart'): - self.tw = TurtleArtWindow(canvas, '/usr/share/turtleart', lang) + self.tw = TurtleArtWindow(canvas, '/usr/share/turtleart') elif os.path.exists('/usr/local/share/turtleart'): - self.tw = TurtleArtWindow(canvas, '/usr/local/share/turtleart', - lang) + self.tw = TurtleArtWindow(canvas, '/usr/local/share/turtleart') else: - self.tw = TurtleArtWindow(canvas, os.path.abspath('.'), lang) + self.tw = TurtleArtWindow(canvas, os.path.abspath('.')) self.tw.win = win self.tw.load_start() def _do_open_cb(self, widget): + """ Callback for open project. """ self.tw.load_file(True) def _do_save_cb(self, widget): + """ Callback for save project. """ self.tw.save_file() def _do_save_picture_cb(self, widget): + """ Callback for save canvas. """ self.tw.save_as_image() def _do_save_html_cb(self, widget): + """ Callback for save project to HTML. """ html = save_html(self, self.tw, False) if len(html) == 0: return @@ -263,6 +246,7 @@ class TurtleMain(): self.tw.saved_pictures = [] def _do_resize_cb(self, widget, factor): + """ Callback to resize blocks. """ if factor == -1: self.tw.block_scale = 2.0 else: @@ -270,6 +254,7 @@ class TurtleMain(): self.tw.resize_blocks() def _do_cartesian_cb(self, button): + """ Callback to display/hide Cartesian coordinate overlay. """ if self.tw.cartesian is True: if self.tw.coord_scale == 1: self.tw.overlay_shapes['Cartesian_labeled'].hide() @@ -285,6 +270,7 @@ class TurtleMain(): self.tw.cartesian = True def _do_polar_cb(self, button): + """ Callback to display/hide Polar coordinate overlay. """ if self.tw.polar is True: self.tw.overlay_shapes['polar'].hide() self.tw.polar = False @@ -293,6 +279,7 @@ class TurtleMain(): self.tw.polar = True def _do_rescale_cb(self, button): + """ Callback to rescale coordinate space. """ if self.tw.coord_scale == 1: self.tw.coord_scale = self.tw.height/200 self.tw.eraser_button() @@ -308,42 +295,51 @@ class TurtleMain(): OVERLAY_LAYER) def _do_palette_cb(self, widget): + """ Callback to show/hide palette of blocks. """ self.tw.show_palette(self.i) self.i += 1 if self.i == len(self.tw.palettes): self.i = 0 def _do_hide_palette_cb(self, widget): + """ Hide the palette of blocks. """ self.tw.hide_palette() def _do_hideshow_cb(self, widget): + """ Hide/show the blocks. """ self.tw.hideshow_button() def _do_eraser_cb(self, widget): + """ Callback for eraser button. """ self.tw.eraser_button() return def _do_run_cb(self, widget): + """ Callback for run button (rabbit). """ self.tw.lc.trace = 0 self.tw.run_button(0) return def _do_step_cb(self, widget): + """ Callback for step button (turtle). """ self.tw.lc.trace = 0 self.tw.run_button(3) return def _do_trace_cb(self, widget): + """ Callback for debug button (bug). """ self.tw.lc.trace = 1 self.tw.run_button(6) return def _do_stop_cb(self, widget): + """ Callback for stop button. """ self.tw.lc.trace = 0 self.tw.stop_button() return def _do_copy_cb(self, button): + """ Callback for copy button. """ clipBoard = gtk.Clipboard() data = self.tw.assemble_data_to_save(False, False) if data is not []: @@ -351,20 +347,22 @@ class TurtleMain(): clipBoard.set_text(text) def _do_paste_cb(self, button): + """ Callback for paste button. """ clipBoard = gtk.Clipboard() text = clipBoard.wait_for_text() if text is not None: self.tw.process_data(data_from_string(text)) def _window_event(self, event, data): + """ Callback for resize event. """ data_file = open('.turtleartrc', 'w') data_file.write(str(data.x)+'\n') data_file.write(str(data.y)+'\n') data_file.write(str(data.width)+'\n') data_file.write(str(data.height)+'\n') - def main(): + """ python turtleart.py """ gtk.main() return 0 -- cgit v0.9.1