Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--TurtleArtActivity.py446
-rw-r--r--tacanvas.py181
-rw-r--r--taexporthtml.py64
-rw-r--r--taexportlogo.py411
-rw-r--r--talogo.py372
-rw-r--r--taturtle.py34
-rw-r--r--tautils.py648
-rw-r--r--tawindow.py1720
-rwxr-xr-xturtleart.py72
10 files changed, 1890 insertions, 2062 deletions
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 = '<Alt>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Alt>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>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 = _('<Ctrl>o')
+ self.activity.samples_button.props.accelerator = _('<Ctrl>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<x2: minx,maxx=x1,x2
- else: minx,maxx=x2,x1
- if y1<y2: miny,maxy=y1,y2
- else: miny,maxy=y2,y1
- w,h=maxx-minx,maxy-miny
- self.canvas.images[0].draw_line(self.gc,x1,y1,x2,y2)
- self.invalt(minx-self.pensize*self.tw.coord_scale/2-3,
- miny-self.pensize*self.tw.coord_scale/2-3,
- w+self.pensize*self.tw.coord_scale+6,
- h+self.pensize*self.tw.coord_scale+6)
+ 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 < x2:
+ minx, maxx = x1, x2
+ else:
+ minx, maxx = x2, x1
+ if y1 < y2:
+ miny, maxy = y1, y2
+ else:
+ miny, maxy = y2, y1
+ w, h = maxx-minx, maxy-miny
+ self.canvas.images[0].draw_line(self.gc, x1, y1, x2, y2)
+ self.invalt(minx - self.pensize*self.tw.coord_scale/2 - 3,
+ miny - self.pensize*self.tw.coord_scale/2 - 3,
+ w + self.pensize*self.tw.coord_scale + 6,
+ h + self.pensize*self.tw.coord_scale + 6)
def turn_turtle(self):
self.tw.active_turtle.set_heading(self.heading)
def move_turtle(self):
- x, y = self.width/2+int(self.xcor), self.height/2-int(self.ycor)
- self.tw.active_turtle.move((self.cx+x-30, self.cy+y-30))
- # self.invalt(x-30,y-30,60,60)
+ x, y = self.width/2 + int(self.xcor), self.height/2 - int(self.ycor)
+ self.tw.active_turtle.move((self.cx + x - 30, self.cy + y - 30))
def invalt(self, x, y, w, h):
- rect = gtk.gdk.Rectangle(int(x+self.cx), int(y+self.cy), int(w),int(h))
+ rect = gtk.gdk.Rectangle(int(x+self.cx), int(y+self.cy), int(w),
+ int(h))
self.tw.area.invalidate_rect(rect, False)
def set_turtle(self, k):
@@ -379,8 +396,8 @@ class TurtleGraphics:
self.tw.active_turtle.set_pen_state(True)
self.tw.active_turtle = self.tw.turtles.get_turtle(k, False)
tx, ty = self.tw.active_turtle.get_xy()
- self.xcor = tx+30-self.width/2
- self.ycor = self.height/2-ty-30
+ self.xcor = tx + 30 - self.width/2
+ self.ycor = self.height/2 - ty - 30
self.heading = self.tw.active_turtle.get_heading()
self.setcolor(self.tw.active_turtle.get_color())
self.setshade(self.tw.active_turtle.get_shade())
diff --git a/taexporthtml.py b/taexporthtml.py
index 6589b03..5a0d163 100644
--- a/taexporthtml.py
+++ b/taexporthtml.py
@@ -21,33 +21,26 @@
import pygtk
pygtk.require('2.0')
import gtk
-try:
- from sugar.activity import activity
- from sugar.datastore import datastore
-except ImportError:
- pass
import os.path
-from talogo import get_pixbuf_from_journal
-from tautils import data_to_string, save_picture, image_to_base64, get_path
+from tautils import data_to_string, save_picture, image_to_base64
from gettext import gettext as _
def save_html(self, tw, embed_flag=True):
-
+ """ Either: Save canvas and code or pictures to HTML """
self.embed_images = embed_flag
# A dictionary to define the HTML wrappers around template elements
self.html_glue = {
- 'doctype': "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 "+\
+ 'doctype': "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " + \
"Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n",
'html': ("<html>\n", "</html>\n"),
'html_svg': ("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n",
"</html>\n"),
'head': ("<head>\n<!-- Created by Turtle Art -->\n", "</head>\n"),
- 'meta': "<meta http-equiv=\"content-type\" content=\"text/html; "+\
+ 'meta': "<meta http-equiv=\"content-type\" content=\"text/html; " + \
"charset=UTF-8\"/>\n",
'title': ("<title>", "</title>\n"),
'style': ("<style type=\"text/css\">\n<!--\n", "-->\n</style>\n"),
- 'style_svg': ("<style type=\"text/css\">\n<!--\n", "-->\n</style>\n"),
'body': ("<body>\n", "\n</body>\n"),
'div': ("<div>\n", "</div>\n"),
'slide': ("\n<a name=\"slide", "\"></a>\n"),
@@ -56,18 +49,24 @@ def save_html(self, tw, embed_flag=True):
'tr': ("<tr>\n", "</tr>\n"),
'td': ("<td valign=\"top\" width=\"400\" height=\"300\">\n",
"\n</td>\n"),
- 'img': ("<img width=\"400\" height=\"300\" alt=\"Image\" "+\
+ 'img': ("<img width=\"400\" height=\"300\" alt=\"Image\" " + \
"src=\"file://", ".png\" />\n"),
'img2': ("<img alt=\"Image\" src=\"image", ".png\" />\n"),
'img3': ("<img alt=\"Image\" src=\"file://", "\" />\n"),
'ul': ("<table>\n", "</table>\n"),
'li': ("<tr><td>", "</td></tr>\n") }
+ comment = "<!--\n\
+<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" [\n\
+ <!ENTITY ns_svg \"http://www.w3.org/2000/svg\">\n\
+ <!ENTITY ns_xlink \"http://www.w3.org/1999/xlink\">\n\
+]>\n\
+-->\n"
if self.embed_images == True:
- self.html_glue['img'] = ("<img width=\"400\" height=\"300\" alt="+\
+ self.html_glue['img'] = ("<img width=\"400\" height=\"300\" alt="+ \
"\"Image\" src=\"data:image/png;base64,\n",
" \"/>\n")
- self.html_glue['img2'] = ("<img alt=\"Image\" src=\"data:image/png;"+\
+ self.html_glue['img2'] = ("<img alt=\"Image\" src=\"data:image/png;"+ \
"base64,\n", " \"/>\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)<float(y)
except ValueError:
@@ -170,9 +157,11 @@ def taless(x, y):
raise logoerror("#syntaxerror")
def tamore(x, y):
+ """ Compare numbers and strings """
return taless(y, x)
def taplus(x, y):
+ """ Add numbers, concat strings """
if numtype(x) and numtype(y):
return(x+y)
else:
@@ -187,6 +176,7 @@ def taplus(x, y):
return(xx+yy)
def taminus(x, y):
+ """ Numerical subtraction """
if numtype(x) and numtype(y):
return(x-y)
try:
@@ -195,6 +185,7 @@ def taminus(x, y):
raise logoerror("#syntaxerror")
def taproduct(x, y):
+ """ Numerical multiplication """
if numtype(x) and numtype(y):
return(x*y)
try:
@@ -203,6 +194,7 @@ def taproduct(x, y):
raise logoerror("#syntaxerror")
def tamod(x, y):
+ """ Numerical mod """
if numtype(x) and numtype(y):
return(x%y)
try:
@@ -213,6 +205,7 @@ def tamod(x, y):
raise logoerror("#syntaxerror")
def tasqrt(x):
+ """ Square root """
if numtype(x):
if x < 0:
raise logoerror("#negroot")
@@ -225,37 +218,39 @@ def tasqrt(x):
raise logoerror("#syntaxerror")
def tarandom(x, y):
+ """ Random integer """
if numtype(x) and numtype(y):
- return(int(uniform(x,y)))
+ return(int(uniform(x, y)))
xx, xflag = chr_to_ord(x)
yy, yflag = chr_to_ord(y)
print xx, xflag, yy, yflag
if xflag and yflag:
- return chr(int(uniform(xx,yy)))
+ return chr(int(uniform(xx, yy)))
if not xflag:
xx = str_to_num(x)
if not yflag:
yy = str_to_num(y)
try:
- return(int(uniform(xx,yy)))
+ return(int(uniform(xx, yy)))
except TypeError:
raise logoerror("#syntaxerror")
def identity(x):
+ """ Identity function """
return(x)
-"""
-Stop_logo is called from the Stop button on the toolbar
-"""
def stop_logo(tw):
+ """ Stop logo is called from the Stop button on the toolbar """
tw.step_time = 0
tw.lc.step = just_stop()
tw.turtles.show_all()
def just_stop():
+ """ yield False to stop stack """
yield False
def millis():
+ """ Current time in milliseconds """
return int(clock()*1000)
"""
@@ -269,14 +264,14 @@ class LogoCode:
DEFPRIM = {
'(':[1, lambda self, x: self.prim_opar(x)],
- 'and':[2, lambda self,x,y: taand(x,y)],
+ 'and':[2, lambda self, x, y: taand(x, y)],
'arc':[2, lambda self, x, y: self.tw.canvas.arc(x, y)],
- 'back':[1, lambda self,x: self.tw.canvas.forward(-x)],
+ 'back':[1, lambda self, x: self.tw.canvas.forward(-x)],
'blue':[0, lambda self: 70],
'bpos':[0, lambda self: -self.tw.canvas.height/(self.tw.coord_scale*2)],
'boty':[0, lambda self: self.tw.bottomy],
'box1':[0, lambda self: self.boxes['box1']],
- 'box':[1, lambda self,x: self.box(x)],
+ 'box':[1, lambda self, x: self.box(x)],
'box2':[0, lambda self: self.boxes['box2']],
'bullet':[1, self.prim_bullet, True],
'bulletlist':[1, self.prim_list, True],
@@ -284,55 +279,56 @@ class LogoCode:
'clean':[0, lambda self: self.prim_clear()],
'clearheap':[0, lambda self: self.empty_heap()],
'color':[0, lambda self: self.tw.canvas.color],
- 'comment':[1, lambda self,x: self.prim_print(x, True)],
+ 'comment':[1, lambda self, x: self.prim_print(x, True)],
'container':[1, lambda self,x: x],
'cyan':[0, lambda self: 50],
'define':[2, self.prim_define],
- 'division':[2, lambda self,x,y: careful_divide(x,y)],
- 'equal?':[2, lambda self,x,y: taequal(x,y)],
+ 'division':[2, lambda self, x, y: careful_divide(x, y)],
+ 'equal?':[2, lambda self,x, y: taequal(x, y)],
'fillscreen':[2, lambda self, x, y: self.tw.canvas.fillscreen(x, y)],
'forever':[1, self.prim_forever, True],
'forward':[1, lambda self, x: self.tw.canvas.forward(x)],
'fullscreen':[0, lambda self: self.tw.set_fullscreen()],
- 'greater?':[2, lambda self,x,y: tamore(x,y)],
+ 'greater?':[2, lambda self, x, y: tamore(x, y)],
'green':[0, lambda self: 30],
'heading':[0, lambda self: self.tw.canvas.heading],
'hideblocks':[0, lambda self: self.tw.hideblocks()],
'hres':[0, lambda self: self.tw.canvas.width/self.tw.coord_scale],
- 'id':[1, lambda self,x: identity(x)],
+ 'id':[1, lambda self, x: identity(x)],
'if':[2, self.prim_if, True],
'ifelse':[3, self.prim_ifelse, True],
- 'insertimage':[1, lambda self,x: self.insert_image(x, False)],
+ 'insertimage':[1, lambda self, x: self.insert_image(x, False)],
'kbinput':[0, lambda self: self.prim_kbinput()],
'keyboard':[0, lambda self: self.keyboard],
- 'left':[1, lambda self,x: self.tw.canvas.right(-x)],
+ 'left':[1, lambda self, x: self.tw.canvas.right(-x)],
'leftx':[0, lambda self: self.tw.leftx],
'lpos':[0, lambda self: -self.tw.canvas.width/(self.tw.coord_scale*2)],
- 'less?':[2, lambda self,x,y: taless(x,y)],
- 'minus':[2, lambda self,x,y: taminus(x,y)],
- 'mod':[2, lambda self,x,y: tamod(x,y)],
- 'myfunction':[2, lambda self,f,x: self.myfunction(f, [x])],
- 'myfunction2':[3, lambda self,f,x,y: self.myfunction(f, [x, y])],
- 'myfunction3':[4, lambda self,f,x,y,z: self.myfunction(f, [x, y, z])],
+ 'less?':[2, lambda self, x, y: taless(x, y)],
+ 'minus':[2, lambda self, x, y: taminus(x, y)],
+ 'mod':[2, lambda self, x, y: tamod(x, y)],
+ 'myfunction':[2, lambda self, f, x: self.myfunction(f, [x])],
+ 'myfunction2':[3, lambda self, f, x, y: self.myfunction(f, [x, y])],
+ 'myfunction3':[4, lambda self, f, x, y, z: self.myfunction(
+ f, [x, y, z])],
'nop':[0, lambda self: None],
'nop1':[0, lambda self: None],
'nop2':[0, lambda self: None],
- 'nop3':[1, lambda self,x: None],
- 'not':[1, lambda self,x:not x],
+ 'nop3':[1, lambda self, x: None],
+ 'not':[1, lambda self, x: not x],
'orange':[0, lambda self: 10],
- 'or':[2, lambda self,x,y: taor(x,y)],
+ 'or':[2, lambda self, x, y: taor(x, y)],
'pendown':[0, lambda self: self.tw.canvas.setpen(True)],
'pensize':[0, lambda self: self.tw.canvas.pensize],
'penup':[0, lambda self: self.tw.canvas.setpen(False)],
- 'plus':[2, lambda self,x,y: taplus(x,y)],
+ 'plus':[2, lambda self, x, y: taplus(x, y)],
'polar':[0, lambda self: self.tw.set_polar(True)],
'pop':[0, lambda self: self.prim_pop()],
- 'print':[1, lambda self,x: self.prim_print(x, False)],
+ 'print':[1, lambda self, x: self.prim_print(x, False)],
'printheap':[0, lambda self: self.prim_print_heap()],
- 'product':[2, lambda self,x,y: taproduct(x,y)],
+ 'product':[2, lambda self, x, y: taproduct(x, y)],
'purple':[0, lambda self: 90],
- 'push':[1, lambda self,x: self.prim_push(x)],
- 'random':[2, lambda self,x,y: tarandom(x,y)],
+ 'push':[1, lambda self, x: self.prim_push(x)],
+ 'random':[2, lambda self, x, y: tarandom(x, y)],
'red':[0, lambda self: 0],
'repeat':[2, self.prim_repeat, True],
'right':[1, lambda self, x: self.tw.canvas.right(x)],
@@ -344,7 +340,7 @@ class LogoCode:
'setcolor':[1, lambda self, x: self.tw.canvas.setcolor(x)],
'seth':[1, lambda self, x: self.tw.canvas.seth(x)],
'setpensize':[1, lambda self, x: self.tw.canvas.setpensize(x)],
- 'setscale':[1, lambda self,x: self.set_scale(x)],
+ 'setscale':[1, lambda self, x: self.set_scale(x)],
'setshade':[1, lambda self, x: self.tw.canvas.setshade(x)],
'settextcolor':[1, lambda self, x: self.tw.canvas.settextcolor(x)],
'settextsize':[1, lambda self, x: self.tw.canvas.settextsize(x)],
@@ -353,21 +349,22 @@ class LogoCode:
'show':[1, lambda self, x: self.show(x, True)],
'showaligned':[1,lambda self, x: self.show(x, False)],
'showblocks':[0, lambda self: self.tw.showblocks()],
- 'sound':[1, lambda self,x: self.play_sound(x)],
- 'sqrt':[1, lambda self,x: tasqrt(x)],
+ 'sound':[1, lambda self, x: self.play_sound(x)],
+ 'sqrt':[1, lambda self, x: tasqrt(x)],
'stack1':[0, self.prim_stack1, True],
'stack':[1, self.prim_stack, True],
'stack2':[0, self.prim_stack2, True],
'start':[0, lambda self: self.prim_start()],
'stopstack':[0, lambda self: self.prim_stopstack()],
- 'storeinbox1':[1, lambda self,x: self.prim_setbox('box1', None ,x)],
- 'storeinbox2':[1, lambda self,x: self.prim_setbox('box2', None, x)],
- 'storeinbox':[2, lambda self,x,y: self.prim_setbox('box3', x, y)],
- 't1x1':[2, lambda self,x,y: self.show_template1x1(x, y)],
- 't1x1a':[2, lambda self,x,y: self.show_template1x1a(x, y)],
- 't1x2':[3, lambda self,x,y,z: self.show_template1x2(x, y, z)],
- 't2x1':[3, lambda self,x,y,z: self.show_template2x1(x, y, z)],
- 't2x2':[5, lambda self,x,y,z,a,b: self.show_template2x2(x, y, z, a, b)],
+ 'storeinbox1':[1, lambda self, x: self.prim_setbox('box1', None ,x)],
+ 'storeinbox2':[1, lambda self, x: self.prim_setbox('box2', None, x)],
+ 'storeinbox':[2, lambda self, x, y: self.prim_setbox('box3', x, y)],
+ 't1x1':[2, lambda self, x, y: self.show_template1x1(x, y)],
+ 't1x1a':[2, lambda self, x, y: self.show_template1x1a(x, y)],
+ 't1x2':[3, lambda self, x, y, z: self.show_template1x2(x, y, z)],
+ 't2x1':[3, lambda self, x, y, z: self.show_template2x1(x, y, z)],
+ 't2x2':[5, lambda self, x, y, z, a, b: self.show_template2x2(
+ x, y, z, a, b)],
'textcolor':[0, lambda self: self.tw.canvas.textcolor],
'textsize':[0, lambda self: self.tw.textsize],
'titlex':[0, lambda self: self.tw.titlex],
@@ -375,14 +372,14 @@ class LogoCode:
'topy':[0, lambda self: self.tw.topy],
'tpos':[0, lambda self: self.tw.canvas.height/(self.tw.coord_scale*2)],
'turtle':[1, lambda self, x: self.tw.canvas.set_turtle(x)],
- 'userdefined':[1, lambda self,x: self.prim_myblock([x])],
- 'userdefined2':[2, lambda self,x,y: self.prim_myblock([x,y])],
- 'userdefined3':[3, lambda self,x,y,z: self.prim_myblock([x,y,z])],
- 'video':[1, lambda self,x: self.play_movie(x)],
+ 'userdefined':[1, lambda self, x: self.prim_myblock([x])],
+ 'userdefined2':[2, lambda self, x, y: self.prim_myblock([x, y])],
+ 'userdefined3':[3, lambda self, x, y, z: self.prim_myblock([x, y, z])],
+ 'video':[1, lambda self, x: self.play_movie(x)],
'vres':[0, lambda self: self.tw.canvas.height/self.tw.coord_scale],
'wait':[1, self.prim_wait, True],
# 'while':[2, self.prim_while, True],
- 'write':[2, lambda self, x,y: self.write(self, x,y)],
+ 'write':[2, lambda self, x, y: self.write(self, x, y)],
'xcor':[0, lambda self: self.tw.canvas.xcor/self.tw.coord_scale],
'ycor':[0, lambda self: self.tw.canvas.ycor/self.tw.coord_scale],
'yellow':[0, lambda self: 20]}
@@ -407,6 +404,8 @@ class LogoCode:
self.stacks = {}
self.boxes = {'box1': 0, 'box2': 0}
self.heap = []
+ self.iresults = None
+ self.step = None
self.keyboard = 0
self.trace = 0
@@ -421,28 +420,22 @@ class LogoCode:
self.scale = 33
- """
- Define the primitives associated with the blocks
- """
def defprim(self, name, args, fcn, rprim=False):
+ """ Define the primitives associated with the blocks """
sym = self.intern(name)
sym.nargs, sym.fcn = args, fcn
sym.rprim = rprim
- """
- Add any new objects to the symbol list.
- """
- def intern(self, str):
- if str in self.oblist:
- return self.oblist[str]
- sym = symbol(str)
- self.oblist[str] = sym
+ def intern(self, string):
+ """ Add any new objects to the symbol list. """
+ if string in self.oblist:
+ return self.oblist[string]
+ sym = symbol(string)
+ self.oblist[string] = sym
return sym
- """
- Given a block to run...
- """
def run_blocks(self, blk, blocks, run_flag):
+ """ Given a block to run... """
for k in self.stacks.keys():
self.stacks[k] = None
self.stacks['stack1'] = None
@@ -454,7 +447,7 @@ class LogoCode:
if b.name == 'hat1':
code = self.blocks_to_code(b)
self.stacks['stack1'] = self.readline(code)
- if b.name=='hat2':
+ if b.name == 'hat2':
code = self.blocks_to_code(b)
self.stacks['stack2'] = self.readline(code)
if b.name == 'hat':
@@ -475,10 +468,8 @@ class LogoCode:
else:
return code
- """
- Convert a stack of blocks to pseudocode.
- """
def blocks_to_code(self, blk):
+ """ Convert a stack of blocks to pseudocode. """
if blk is None:
return ['%nothing%', '%nothing%']
code = []
@@ -490,29 +481,29 @@ class LogoCode:
if blk.primitive is not None: # make a tuple (prim, blk)
code.append((blk.primitive, self.tw.block_list.list.index(blk)))
elif len(blk.values)>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()<endtime:
@@ -807,37 +793,42 @@ class LogoCode:
self.ireturn()
yield True
- def prim_repeat(self, num, list):
+ def prim_repeat(self, num, blklist):
+ """ Repeat list num times. """
num = self.an_int(num)
for i in range(num):
- self.icall(self.evline, list[:])
+ self.icall(self.evline, blklist[:])
yield True
if self.procstop:
break
self.ireturn()
yield True
- def prim_bullet(self, list): # Depreciated block style
- self.show_bullets(list)
+ def prim_bullet(self, blklist):
+ """ Depreciated bullet-list block style """
+ self.show_bullets(blklist)
self.ireturn()
yield True
- def prim_list(self, list):
- self.show_list(list)
+ def prim_list(self, blklist):
+ """ Expandable list block """
+ self.show_list(blklist)
self.ireturn()
yield True
def myfunction(self, f, x):
+ """ Programmable block """
y = myfunc(f, x)
if y == None:
- raise logoerror("#syntaxerror")
stop_logo(self.tw)
+ raise logoerror("#syntaxerror")
else:
return y
- def prim_forever(self, list):
+ def prim_forever(self, blklist):
+ """ Do list forever """
while True:
- self.icall(self.evline, list[:])
+ self.icall(self.evline, blklist[:])
yield True
if self.procstop:
break
@@ -856,15 +847,17 @@ class LogoCode:
yield True
'''
- def prim_if(self, bool, list):
- if bool:
- self.icall(self.evline, list[:])
+ def prim_if(self, boolean, blklist):
+ """ If bool, do list """
+ if boolean:
+ self.icall(self.evline, blklist[:])
yield True
self.ireturn()
yield True
- def prim_ifelse(self, bool, list1, list2):
- if bool:
+ def prim_ifelse(self, boolean, list1, list2):
+ """ If bool, do list1, else do list2 """
+ if boolean:
self.ijmp(self.evline, list1[:])
yield True
else:
@@ -876,12 +869,14 @@ class LogoCode:
return val
def prim_define(self, name, body):
- if type(name) is not symtype:
+ """ Define a primitive """
+ if type(name) is not self.symtype:
name = self.intern(name)
name.nargs, name.fcn = 0, body
name.rprim = True
def prim_stack(self, x):
+ """ Process a named stack """
if type(convert(x, float, False)) == type(float):
if int(float(x)) == x:
x = int(x)
@@ -895,6 +890,7 @@ class LogoCode:
yield True
def prim_stack1(self):
+ """ Process Stack 1 """
if self.stacks['stack1'] is None:
raise logoerror("#nostack")
self.icall(self.evline, self.stacks['stack1'][:])
@@ -904,6 +900,7 @@ class LogoCode:
yield True
def prim_stack2(self):
+ """ Process Stack 2 """
if self.stacks['stack2'] is None:
raise logoerror("#nostack")
self.icall(self.evline, self.stacks['stack2'][:])
@@ -913,12 +910,15 @@ class LogoCode:
yield True
def prim_stopstack(self):
+ """ Stop execution of a stack """
self.procstop = True
def prim_print_heap(self):
+ """ Display contents of heap """
self.tw.showlabel('status', self.heap)
def an_int(self, n):
+ """ Raise an error if n doesn't convert to int. """
if type(n) == int:
return n
elif type(n) == float:
@@ -930,6 +930,7 @@ class LogoCode:
% (self.cfun.name, _("doesn't like"), str(n), _("as input")))
def box(self, x):
+ """ Retrieve value from named box """
if type(convert(x, float, False)) == float:
if int(float(x)) == x:
x = int(x)
@@ -939,6 +940,7 @@ class LogoCode:
raise logoerror("#emptybox")
def prim_myblock(self, x):
+ """ Run Python code imported from Journal """
if self.tw.myblock is not None:
try:
if len(x) == 1:
@@ -952,6 +954,7 @@ class LogoCode:
return
def prim_print(self, n, flag):
+ """ Print n """
if flag and (self.tw.hide or self.tw.step_time == 0):
return
if type(n) == str or type(n) == unicode:
@@ -973,6 +976,7 @@ class LogoCode:
self.tw.showlabel('status', round_int(n))
def prim_kbinput(self):
+ """ Query keyboard """
if len(self.tw.keypress) == 1:
self.keyboard = ord(self.tw.keypress[0])
else:
@@ -986,34 +990,41 @@ class LogoCode:
self.tw.keypress = ""
def prim_setbox(self, name, x, val):
+ """ Define value of named box """
if x is None:
- self.boxes[name]=val
+ self.boxes[name] = val
else:
if type(convert(x, float, False)) == type(float):
if int(float(x)) == x:
x = int(x)
- self.boxes[name+str(x)]=val
+ self.boxes[name+str(x)] = val
def prim_push(self, val):
+ """ Push value onto FILO """
self.heap.append(val)
def prim_pop(self):
+ """ Pop value off of FILO """
try:
return self.heap.pop(-1)
except:
raise logoerror ("#emptyheap")
def empty_heap(self):
+ """ Empty FILO """
self.heap = []
def save_picture(self, name):
+ """ Save canvas to file as PNG """
self.tw.save_as_image(name)
def save_svg(self, name):
+ """ Save SVG to file """
self.tw.canvas.svg_close()
self.tw.save_as_image(name, True)
def show_list(self, sarray):
+ """ Display list of media objects """
x = self.tw.canvas.xcor/self.tw.coord_scale
y = self.tw.canvas.ycor/self.tw.coord_scale
for s in sarray:
@@ -1022,14 +1033,11 @@ class LogoCode:
y -= int(self.tw.canvas.textsize*self.tw.lead)
def set_scale(self, x):
+ """ Set scale used by media object display """
self.scale = x
- """
- Show is the general-purpose media-rendering block. It will draw text
- strings, render media objects from the Journal, play sounds and movies.
- """
- # TODO: need to fix export logo to map show to write
def show(self, string, center=False):
+ """ Show is the general-purpose media-rendering block. """
# convert from Turtle coordinates to screen coordinates
x = self.tw.canvas.width/2+int(self.tw.canvas.xcor)
y = self.tw.canvas.height/2-int(self.tw.canvas.ycor)
@@ -1058,8 +1066,8 @@ class LogoCode:
self.scale/100),
self.tw.canvas.width-x)
- # Image only (at current x,y)
def insert_image(self, media, center):
+ """ Image only (at current x, y) """
w = (self.tw.canvas.width * self.scale)/100
h = (self.tw.canvas.height * self.scale)/100
# convert from Turtle coordinates to screen coordinates
@@ -1071,8 +1079,8 @@ class LogoCode:
if media[0:5] == 'media':
self.show_picture(media, x, y, w, h)
- # Description text only (at current x,y)
def insert_desc(self, media):
+ """ Description text only (at current x, y) """
w = (self.tw.canvas.width * self.scale)/100
h = (self.tw.canvas.height * self.scale)/100
# convert from Turtle coordinates to screen coordinates
@@ -1082,6 +1090,7 @@ class LogoCode:
self.show_description(media, x, y, w, h)
def play_sound(self, audio):
+ """ Sound file from Journal """
if audio == "" or audio[6:] == "":
raise logoerror("#nomedia")
if self.tw.running_sugar:
@@ -1095,6 +1104,7 @@ class LogoCode:
play_audio(self, audio[6:])
def show_picture(self, media, x, y, w, h):
+ """ Image file from Journal """
if media == "" or media[6:] == "":
pass
elif media[6:] is not "None":
@@ -1140,6 +1150,7 @@ class LogoCode:
self.filepath)
def show_description(self, media, x, y, w, h):
+ """ Description field from Journal """
if media == "" or media[6:] == "":
return
elif media[6:] != "None":
@@ -1168,18 +1179,18 @@ class LogoCode:
self.tw.canvas.draw_text(text, int(x), int(y),
self.body_height, int(w))
- """
- Depreciated block methods
- """
- # slide title
+
+ # Depreciated block methods
+
def draw_title(self, title, x, y):
+ """ slide title """
self.tw.canvas.draw_text(title, int(x), int(y),
self.title_height,
self.tw.canvas.width-x)
- # title, one image, and description
def show_template1x1(self, title, media):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t1x1')
+ """ title, one image, and description """
+ xo = self.tw.calc_position('t1x1')[2]
x = -(self.tw.canvas.width/2)+xo
y = self.tw.canvas.height/2
self.tw.canvas.setxy(x, y)
@@ -1205,10 +1216,10 @@ class LogoCode:
self.show(media.replace("media_","descr_"))
# restore text size
self.tw.canvas.settextsize(save_text_size)
-
- # title, two images (horizontal), two descriptions
+
def show_template2x1(self, title, media1, media2):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t2x1')
+ """ title, two images (horizontal), two descriptions """
+ xo = self.tw.calc_position('t2x1')[2]
x = -(self.tw.canvas.width/2)+xo
y = self.tw.canvas.height/2
self.tw.canvas.setxy(x, y)
@@ -1235,16 +1246,16 @@ class LogoCode:
if self.tw.running_sugar:
self.tw.canvas.setxy(x, y)
self.show(media2.replace("media_","descr_"))
- x = -(self.tw.canvas.width/2)+xo
+ x = -(self.tw.canvas.width/2) + xo
self.tw.canvas.setxy(x, y)
self.show(media1.replace("media_","descr_"))
# restore text size
self.tw.canvas.settextsize(save_text_size)
- # title and varible number of bullets
def show_bullets(self, sarray):
- w,h,xo,yo,dx,dy = self.tw.calc_position('bullet')
- x = -(self.tw.canvas.width/2)+xo
+ """ title and varible number of bullets """
+ xo = self.tw.calc_position('bullet')[2]
+ x = -(self.tw.canvas.width/2) + xo
y = self.tw.canvas.height/2
self.tw.canvas.setxy(x, y)
# save the text size so we can restore it later
@@ -1263,10 +1274,10 @@ class LogoCode:
# restore text size
self.tw.canvas.settextsize(save_text_size)
- # title, two images (vertical), two desciptions
def show_template1x2(self, title, media1, media2):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t1x2')
- x = -(self.tw.canvas.width/2)+xo
+ """ title, two images (vertical), two desciptions """
+ xo = self.tw.calc_position('t1x2')[2]
+ x = -(self.tw.canvas.width/2) + xo
y = self.tw.canvas.height/2
self.tw.canvas.setxy(x, y)
# save the text size so we can restore it later
@@ -1292,16 +1303,16 @@ class LogoCode:
y = -self.title_height
self.tw.canvas.setxy(x, y)
self.show(media2.replace("media_","descr_"))
- x = -(self.tw.canvas.width/2)+xo
+ x = -(self.tw.canvas.width/2) + xo
self.tw.canvas.setxy(x, y)
self.show(media2)
# restore text size
self.tw.canvas.settextsize(save_text_size)
- # title and four images
def show_template2x2(self, title, media1, media2, media3, media4):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t2x2')
- x = -(self.tw.canvas.width/2)+xo
+ """ title and four images """
+ xo = self.tw.calc_position('t2x2')[2]
+ x = -(self.tw.canvas.width/2) + xo
y = self.tw.canvas.height/2
self.tw.canvas.setxy(x, y)
# save the text size so we can restore it later
@@ -1326,16 +1337,16 @@ class LogoCode:
y = -self.title_height
self.tw.canvas.setxy(x, y)
self.show(media4)
- x = -(self.tw.canvas.width/2)+xo
+ x = -(self.tw.canvas.width/2) + xo
self.tw.canvas.setxy(x, y)
self.show(media3)
# restore text size
self.tw.canvas.settextsize(save_text_size)
- # title, one media object
def show_template1x1a(self, title, media1):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t1x1a')
- x = -(self.tw.canvas.width/2)+xo
+ """ title, one media object """
+ xo = self.tw.calc_position('t1x1a')[2]
+ x = -(self.tw.canvas.width/2) + xo
y = self.tw.canvas.height/2
self.tw.canvas.setxy(x, y)
# save the text size so we can restore it later
@@ -1358,7 +1369,8 @@ class LogoCode:
self.tw.canvas.settextsize(save_text_size)
def write(self, string, fsize):
- # convert from Turtle coordinates to screen coordinates
+ """ Write string at size """
x = self.tw.canvas.width/2+int(self.tw.canvas.xcor)
y = self.tw.canvas.height/2-int(self.tw.canvas.ycor)
- self.tw.canvas.draw_text(string,x,y-15,int(fsize),self.tw.canvas.width)
+ self.tw.canvas.draw_text(string, x, y-15, int(fsize),
+ self.tw.canvas.width)
diff --git a/taturtle.py b/taturtle.py
index 9de4f58..9c8fe26 100644
--- a/taturtle.py
+++ b/taturtle.py
@@ -19,12 +19,12 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
-from taconstants import *
+from taconstants import TURTLE_LAYER
from tasprite_factory import SVG, svg_str_to_pixbuf
from sprites import Sprite
-from gettext import gettext as _
def generate_turtle_pixbufs(colors):
+ """ Generate pixbufs for generic turtles """
shapes = []
svg = SVG()
svg.set_scale(1.0)
@@ -38,11 +38,13 @@ def generate_turtle_pixbufs(colors):
#
class Turtles:
def __init__(self, sprite_list):
+ """ Class to hold turtles """
self.dict = dict()
self.sprite_list = sprite_list
self.default_pixbufs = []
def get_turtle(self, k, append=False):
+ """ Find a turtle """
if self.dict.has_key(k):
return self.dict[k]
elif append is False:
@@ -52,22 +54,27 @@ class Turtles:
return self.dict[k]
def get_turtle_key(self, turtle):
+ """ Find a turtle's name """
for k in iter(self.dict):
if self.dict[k] == turtle:
return k
return None
def turtle_count(self):
+ """ How many turtles are there? """
return(len(self.dict))
def add_to_dict(self, k, turtle):
+ """ Add a new turtle """
self.dict[k] = turtle
def remove_from_dict(self, k):
+ """ Delete a turtle """
if self.dict.has_key(k):
del(self.dict[k])
def show_all(self):
+ """ Make all turtles visible """
for k in iter(self.dict):
self.dict[k].show()
@@ -75,23 +82,25 @@ class Turtles:
# sprite utilities
#
def spr_to_turtle(self, spr):
+ """ Find the turtle that corresponds to sprite spr. """
for k in iter(self.dict):
if spr == self.dict[k].spr:
return self.dict[k]
return None
def get_pixbufs(self):
+ """ Get the pixbufs for the default turtle shapes. """
if self.default_pixbufs == []:
- self.default_pixbufs = generate_turtle_pixbufs(
- ["#008000", "#00A000"])
+ self.default_pixbufs = generate_turtle_pixbufs(
+ ["#008000", "#00A000"])
return(self.default_pixbufs)
#
# A class for the individual turtles
#
class Turtle:
- # The turtle is not a block, just a sprite with an orientation
def __init__(self, turtles, key, colors=None):
+ """ The turtle is not a block, just a sprite with an orientation """
self.x = 0
self.y = 0
self.hidden = False
@@ -113,6 +122,7 @@ class Turtle:
turtles.add_to_dict(key, self)
def set_heading(self, heading):
+ """ Set the turtle heading (and shape: one per 10 degrees) """
self.heading = heading
i = (int(self.heading+5)%360)/10
if self.hidden is False:
@@ -123,46 +133,60 @@ class Turtle:
print "Turtle shape IndexError %f -> %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()&gtk.gdk.CONTROL_MASK, x, y)
if self._sharing():
if event.get_state()&gtk.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<i:
+ if c < i:
blocks[c].connections[0] = blocks[i]
blocks[c].connections[3] = None
else:
@@ -1101,68 +1000,64 @@ class TurtleArtWindow():
for j, cj in enumerate(data[c0][4]):
if cj == c:
blocks[c0].connections[j] = blocks[i]
- if c<i:
+ if c < i:
blocks[c].connections[0] = blocks[i]
blocks[c].connections[1] = None
else:
# Connection was to a block we haven't seen yet.
print "WARNING: dock check couldn't see the future"
else:
- print "WARNING: unknown connection state %s" %\
+ print "WARNING: unknown connection state %s" % \
(str(blocks[i].connections))
blocks[i].connections = cons[:]
# Block sizes and shapes may have changed.
- for b in blocks:
- self._adjust_dock_positions(b)
+ for blk in blocks:
+ self._adjust_dock_positions(blk)
# Look for any stacks that need to be collapsed or sandwiched
- for b in blocks:
- if self._collapsed(b):
- self._collapse_stack(self._find_sandwich_top(b))
- elif b.name == 'sandwichbottom' and self._collapsible(b):
- b.svg.set_hide(True)
- b.svg.set_show(False)
- b.refresh()
- self._grow_stack_arm(self._find_sandwich_top(b))
+ for blk in blocks:
+ if collapsed(blk):
+ collapse_stack(find_sandwich_top(blk))
+ elif blk.name == 'sandwichbottom' and collapsible(blk):
+ blk.svg.set_hide(True)
+ blk.svg.set_show(False)
+ blk.refresh()
+ grow_stack_arm(find_sandwich_top(blk))
if len(blocks) > 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 x<minx:
+ for gblk in find_group(blk):
+ (x, y) = gblk.spr.get_xy()
+ w, h = gblk.spr.get_dimensions()
+ if x < minx:
minx = x
- if y<miny:
+ if y < miny:
miny = y
- 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
- """
-
- """
- 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