Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TurtleArtActivity.py17
-rw-r--r--constants.py35
-rw-r--r--sprites.py4
-rw-r--r--talogo.py29
-rw-r--r--tawindow.py158
5 files changed, 168 insertions, 75 deletions
diff --git a/TurtleArtActivity.py b/TurtleArtActivity.py
index 0c9d747..8afbd9f 100644
--- a/TurtleArtActivity.py
+++ b/TurtleArtActivity.py
@@ -20,9 +20,6 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
-import tawindow
-import talogo
-
import pygtk
pygtk.require('2.0')
import gtk
@@ -59,11 +56,14 @@ import os.path
import subprocess
import tarfile
import sys
-from taexporthtml import *
-from taexportlogo import *
import re
from constants import *
+from taexporthtml import *
+from taexportlogo import *
+from tautils import *
+import tawindow
+import talogo
SERVICE = 'org.laptop.TurtleArtActivity'
IFACE = SERVICE
@@ -283,7 +283,7 @@ class TurtleArtActivity(activity.Activity):
print tafile
try:
# FIXME: encapsulation?
- self.tw.save_data(tafile)
+ data_to_file(self.tw.assemble_data_to_save(), tafile)
except:
_logger.debug("couldn't save snapshot to journal")
@@ -568,8 +568,7 @@ class TurtleArtActivity(activity.Activity):
# sharer should send current state to joiner
if self.initiating is True:
_logger.debug("serialize the project and send to joiner")
- data = self.tw.assemble_data_to_save(True, True)
- text = data_to_string(data)
+ text = data_to_string(self.tw.assemble_data_to_save(True, True))
self._send_event("I:" + text)
self.tw.show_palette()
elif text[0] == 'I': # receiving current state
@@ -1014,7 +1013,7 @@ class TurtleArtActivity(activity.Activity):
def write_file(self, file_path):
_logger.debug("Write file: %s" % file_path)
self.metadata['mime_type'] = 'application/x-turtle-art'
- self.tw.save_data(file_path)
+ data_to_file(self.tw.assemble_data_to_save(), file_path+'.ta')
"""
Read a project in and then run it
diff --git a/constants.py b/constants.py
index 6b0b382..f275395 100644
--- a/constants.py
+++ b/constants.py
@@ -43,7 +43,7 @@ PALETTES = [['forward', 'back', 'clean', 'left', 'right', 'show',
[ 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple'],
['plus2', 'minus2', 'product2',
'division2', 'identity2', 'remainder2', 'sqrt', 'random',
- 'number', 'greater', 'less', 'equal', 'not', 'and', 'or'],
+ 'number', 'greater2', 'less2', 'equal2', 'not', 'and2', 'or2'],
['wait', 'forever', 'repeat', 'if', 'ifelse', 'hspace',
'vspace', 'stopstack'],
['hat1', 'stack1', 'hat', 'hat2', 'stack2', 'stack',
@@ -111,8 +111,8 @@ NUMBER_STYLE_BLOCK = ['random']
NUMBER_STYLE_PORCH = ['minus2', 'division2', 'remainder2']
NUMBER_STYLE_1ARG = ['sqrt', 'identity2']
NUMBER_STYLE_1STRARG = ['box']
-COMPARE_STYLE = ['greater', 'less', 'equal']
-BOOLEAN_STYLE = ['and', 'or']
+COMPARE_STYLE = ['greater2', 'less2', 'equal2']
+BOOLEAN_STYLE = ['and2', 'or2']
NOT_STYLE = ['not']
FLOW_STYLE = ['forever', 'hspace']
FLOW_STYLE_1ARG = ['repeat']
@@ -130,6 +130,11 @@ PORTFOLIO_STYLE_1x2 = ['template1x2']
EXPANDABLE = ['vspace', 'hspace', 'list']
#
+# Old block styles that need dock adjustments
+#
+OLD_DOCK = ['and', 'or']
+
+#
# blocks that contain media
#
CONTENT_BLOCKS = ['number', 'string', 'description', 'audio', 'journal']
@@ -138,7 +143,7 @@ CONTENT_BLOCKS = ['number', 'string', 'description', 'audio', 'journal']
# block name dictionary
#
BLOCK_NAMES = {
- 'and':[_('and')],
+ 'and2':[_('and')],
'arc':[_('arc'),_('angle'),_('radius')],
'audio':[' '],
'back':[_('back')],
@@ -152,10 +157,11 @@ BLOCK_NAMES = {
'color':[_('color')],
'cyan':[_('cyan')],
'division2':['/'],
- 'equal':['='],
+ 'equal2':['='],
'fillscreen':[_('fill screen'),_('color'),_('shade')],
'forever':[_('forever')],
'forward':[_('forward')],
+ 'greater2':[">"],
'green':[_('green')],
'hat':[_('action')],
'hat1':[_('action 1')],
@@ -172,7 +178,7 @@ BLOCK_NAMES = {
'keyboard':[_('keyboard')],
'left':[_('left')],
'leftpos':[_('left')],
- 'less':['<'],'greater':[">"],
+ 'less2':['<'],
'list':[_('list')],
'minus2':['–'],
'myfunc':[_('Python'),_('code'),_('value')],
@@ -180,7 +186,7 @@ BLOCK_NAMES = {
'not':[_('not')],
'number':['100'],
'orange':[_('orange')],
- 'or':[_('or')],
+ 'or2':[_('or')],
'pendown':[_('pen down')],
'pensize':[_('pen size')],
'penup':[_('pen up')],
@@ -237,7 +243,7 @@ BLOCK_NAMES = {
#
PRIMITIVES = {
- 'and':'and',
+ 'and2':'and',
'arc':'arc',
'back':'back',
'blue':'blue',
@@ -250,11 +256,11 @@ PRIMITIVES = {
'color':'color',
'cyan':'cyan',
'division2':'division',
- 'equal':'equal?',
+ 'equal2':'equal?',
'fillscreen':'fillscreen',
'forever':'forever',
'forward':'forward',
- 'greater':'greater?',
+ 'greater2':'greater?',
'green':'green',
'hat':'nop3',
'hat1':'nop1',
@@ -270,14 +276,14 @@ PRIMITIVES = {
'keyboard':'keyboard',
'left':'left',
'leftpos':'lpos',
- 'less':'less?',
+ 'less2':'less?',
'list':'bullet',
'minus2':'minus',
'myfunc':'myfunc',
'nop':'userdefined',
'not':'not',
'orange':'orange',
- 'or':'or',
+ 'or2':'or',
'pendown':'pendown',
'pensize':'pensize',
'penup':'penup',
@@ -376,7 +382,7 @@ DEFAULTS = {
#
# Blocks that can interchange strings and numbers for their arguments
#
-STRING_OR_NUMBER_ARGS = ['plus2', 'equal', 'less', 'greater',
+STRING_OR_NUMBER_ARGS = ['plus2', 'equal2', 'less2', 'greater2',
'template1x1', 'template1x2', 'template2x1',
'template2x2', 'list', 'nop',
'print', 'stack', 'hat']
@@ -402,7 +408,8 @@ STATUS_SHAPES = ['status', 'info', 'nostack', 'noinput', 'emptyheap',
# Legacy names
#
OLD_NAMES = {'product':'product2', 'storeinbox':'storein',
- 'division':'division2', 'plus':'plus2',
+ 'division':'division2', 'plus':'plus2', 'and':'and2', 'or':'or2',
+ 'less':'less2', 'greater':'greater2', 'equal':'equal2',
'remainder':'remainder2', 'identity':'identity2',
'division':'division2', 'if else':'if', 'audiooff':'audio',
'descriptionoff':'description','template3':'list',
diff --git a/sprites.py b/sprites.py
index 9124494..ef5ed2b 100644
--- a/sprites.py
+++ b/sprites.py
@@ -43,7 +43,7 @@ Example usage:
# Create a "pixbuf" (in this example, from SVG).
my_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>")
- # Create a sprite at position x,y.
+ # Create a sprite at position x1, y1.
my_sprite = sprites.Sprite(self.sprite_list, x1, y1, my_pixbuf)
# Move the sprite to a new position.
@@ -52,7 +52,7 @@ Example usage:
# Create another "pixbuf".
your_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>")
- # Create a sprite at position x2,y2.
+ # Create a sprite at position x2, y2.
your_sprite = sprites.Sprite(self.sprite_list, x2, y2, my_pixbuf)
# Assign the sprites to layers.
diff --git a/talogo.py b/talogo.py
index 897f780..d812ddb 100644
--- a/talogo.py
+++ b/talogo.py
@@ -417,8 +417,10 @@ class LogoCode:
else:
code.append('#saudio_None')
else:
+ print "%s had nothing as a value" % (blk.name)
return ['%nothing%']
else:
+ print "%s had no value" % (blk.name)
return ['%nothing%']
for i in range(1,len(blk.connections)):
b = blk.connections[i]
@@ -561,21 +563,23 @@ class LogoCode:
def debug_trace(self, token):
if self.trace:
if token.name in PALETTES[PALETTE_NAMES.index('turtle')]:
- my_string = "%s\nxcor=%d\nycor=%d\nheading=%d\nscale=%d" %\
- (token.name,int(self.tw.canvas.xcor),
- int(self.tw.canvas.ycor),int(self.tw.canvas.heading),
- int(self.scale))
+ 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))
elif token.name in PALETTES[PALETTE_NAMES.index('pen')]:
if self.tw.canvas.pendown:
- penstatus = "pen down"
+ penstatus = _('pen down')
else:
- penstatus = "pen up"
- my_string = "%s\n%s\ncolor=%d\nshade=%d\npensize=%.1f" %\
- (token.name, penstatus, int(self.tw.canvas.color),
- int(self.tw.canvas.shade), self.tw.canvas.pensize)
+ penstatus = _('pen up')
+ 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'),
+ self.tw.canvas.pensize)
else:
- my_string = "%s\nblocks status:\n" % (token.name)
- for k,v in self.boxes.iteritems():
+ my_string = "%s\n%s:\n" % (token.name, _('box'))
+ for k, v in self.boxes.iteritems():
tmp = k +":" + str(v) + "\n"
my_string += tmp
shp = 'info'
@@ -590,7 +594,8 @@ class LogoCode:
raise logoerror("%s %s" % (_("I don't know how to"), token.name))
def no_args_check(self):
- if self.iline and self.iline[0] is not self.symnothing : return
+ if self.iline and self.iline[0] is not self.symnothing:
+ return
raise logoerror("#noinput")
def prim_wait(self, time):
diff --git a/tawindow.py b/tawindow.py
index 9f1a0ae..ab184ab 100644
--- a/tawindow.py
+++ b/tawindow.py
@@ -328,6 +328,8 @@ class TurtleArtWindow():
HIDE_LAYER)
self.selected_palette = None
self.toolbar_spr.set_layer(HIDE_LAYER)
+ self.palette_button[self.palette_orientation].set_layer(HIDE_LAYER)
+ self.palette_button[1-self.palette_orientation].set_layer(HIDE_LAYER)
def show_toolbar_palette(self, n, init_only=False):
if self.selectors == []:
@@ -375,6 +377,8 @@ class TurtleArtWindow():
self.palette_sprs[n][1-self.palette_orientation].set_layer(
HIDE_LAYER)
+ self.palette_button[self.palette_orientation].set_layer(TAB_LAYER)
+
for i in range(len(PALETTES)):
self.selectors[i].set_layer(TAB_LAYER)
@@ -417,6 +421,7 @@ class TurtleArtWindow():
def _layout_palette(self, n):
+ if n is not None:
_x, _y, _max = 5, ICON_SIZE+5, 0
if self.palette_orientation == 0:
for i in range(len(PALETTES[n])):
@@ -1402,6 +1407,21 @@ class TurtleArtWindow():
self.selected_blk.spr.set_label(s)
self.selected_blk.values[0] = s
+ """
+ Load Python code from a file
+ """
+ def load_python_code(self):
+ fname, self.load_save_folder = get_load_name('.py',
+ self.load_save_folder)
+ if fname==None:
+ return
+ f = open(fname, 'r')
+ self.myblock = f.read()
+ f.close()
+
+ """
+ Start a new project
+ """
def new_project(self):
stop_logo(self)
for b in self._just_blocks():
@@ -1409,6 +1429,14 @@ class TurtleArtWindow():
self.canvas.clearscreen()
self.save_file_name = None
+ """
+ Load a project from a file
+ """
+ def load_files(self, ta_file, create_new_project=True):
+ if create_new_project is True:
+ self.new_project()
+ 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',
self.load_save_folder)
@@ -1420,20 +1448,9 @@ class TurtleArtWindow():
if create_new_project is True:
self.save_file_name = os.path.basename(fname)
- def load_python_code(self):
- fname, self.load_save_folder = get_load_name('.py',
- self.load_save_folder)
- if fname==None:
- return
- f = open(fname, 'r')
- self.myblock = f.read()
- f.close()
-
- def load_files(self, ta_file, create_new_project=True):
- if create_new_project is True:
- self.new_project()
- self.process_data(data_from_file(ta_file))
-
+ """
+ Process data (from a file or clipboard) into blocks
+ """
def process_data(self, data):
# Create the blocks.
blocks = []
@@ -1448,12 +1465,46 @@ class TurtleArtWindow():
# Make the connections.
for i in range(len(blocks)):
cons=[]
- for c in data[i][4]:
- if c is None:
- cons.append(None)
- else:
- cons.append(blocks[c])
- blocks[i].connections = cons
+ # Ugly corner case of old-style booleans
+ if blocks[i].connections == 'check':
+ print "WARNING: ugly corner case for %s" % (blocks[i].name)
+ print "adding an extra connection"
+ cons.append(None) # 'and' or 'or' not be connected to 'if'
+ for c in data[i][4]:
+ if c is None:
+ cons.append(None)
+ else:
+ cons.append(blocks[c])
+ if data[i][4][0] is not None:
+ print "WARNING: patching %s connection" %\
+ (blocks[i].name)
+ c = data[i][4][0]
+ cons[0] = blocks[data[c][4][0]]
+ c0 = data[c][4][0]
+ print "WARNING: patching %s connection" %\
+ (blocks[c0].name)
+ for j, cj in enumerate(data[c0][4]):
+ if cj == c:
+ print "found a match in dock position %d" % (j)
+ blocks[c0].connections[j] = blocks[i]
+ if c<i:
+ print "WARNING: patching %s connections" %\
+ (blocks[c].name)
+ blocks[c].connections[0] = blocks[i]
+ blocks[c].connections[3] = None
+ else:
+ print "WARNING: could not look into the future"
+ print cons
+ print "%s: %d docks and %d connections" % (blocks[i].name,
+ len(blocks[i].docks), len(cons))
+ # Normally, it is simply a matter of copying the connections
+ else:
+ for c in data[i][4]:
+ if c is None:
+ cons.append(None)
+ else:
+ cons.append(blocks[c])
+ blocks[i].connections = cons[:]
# Adjust the x,y positions, as block sizes may have changed.
for b in blocks:
(sx, sy) = b.spr.get_xy()
@@ -1468,7 +1519,10 @@ class TurtleArtWindow():
cdock = c.docks[j]
nx, ny = sx+bdock[2]-cdock[2], sy+bdock[3]-cdock[3]
c.spr.move((nx, ny))
-
+
+ #
+ # Restore individual blocks from saved state
+ #
def load_block(self, b):
# A block is saved as: (i, (btype, value), x, y, (c0,... cn))
# The x,y position is saved/loaded for backward compatibility
@@ -1486,48 +1540,61 @@ class TurtleArtWindow():
else:
values = []
+ if btype in OLD_DOCK:
+ check_dock = True
+ print "WARNING: will need to preform dock check"
+ else:
+ check_dock = False
if OLD_NAMES.has_key(btype):
print "%s -> %s" % (btype, OLD_NAMES[btype])
btype = OLD_NAMES[btype]
-
+ else:
+ print "%s" % (btype)
blk = Block(self.block_list, self.sprite_list,
btype, b[2]+self.canvas.cx,
b[3]+self.canvas.cy, 'block', values)
- # Some blocks get a skin.
+ # Some blocks get transformed.
if btype == 'nop':
if self.nop == 'pythonloaded':
- blk.spr.set_image(self.media_shapes['pythonon'], 1, PYTHON_X, PYTHON_Y)
+ blk.spr.set_image(self.media_shapes['pythonon'], 1,
+ PYTHON_X, PYTHON_Y)
else:
- blk.spr.set_image(self.media_shapes['pythonoff'], 1, PYTHON_X, PYTHON_Y)
+ blk.spr.set_image(self.media_shapes['pythonoff'], 1,
+ PYTHON_X, PYTHON_Y)
blk.spr.set_label(' ')
elif btype in EXPANDABLE:
if btype == 'vspace':
- blk.expand_in_y(value)
+ if value is not None:
+ blk.expand_in_y(value)
elif btype == 'hspace':
- blk.expand_in_x(value)
+ if value is not None:
+ blk.expand_in_x(value)
elif btype == 'list':
for i in range(len(b[4])-4):
dy = blk.add_arg()
elif btype in BOX_STYLE_MEDIA and len(blk.values)>0:
if blk.values[0] == 'None':
- blk.spr.set_image(self.media_shapes[btype+'off'], 1, MEDIA_X, MEDIA_Y)
+ blk.spr.set_image(self.media_shapes[btype+'off'], 1,
+ MEDIA_X, MEDIA_Y)
elif btype == 'audio' or btype == 'description':
- blk.spr.set_image(self.media_shapes[btype+'on'], 1, MEDIA_X, MEDIA_Y)
+ blk.spr.set_image(self.media_shapes[btype+'on'], 1,
+ MEDIA_X, MEDIA_Y)
elif self.running_sugar:
try:
dsobject = datastore.get(blk.values[0])
if not movie_media_type(dsobject.file_path[-4:]):
- pixbuf = get_pixbuf_from_journal(dsobject, THUMB_W, THUMB_H)
+ pixbuf = get_pixbuf_from_journal(dsobject,
+ THUMB_W, THUMB_H)
if pixbuf is not None:
blk.spr.set_image(pixbuf, 1, PIXBUF_X, PIXBUF_Y)
else:
- blk.spr.set_image(
- self.media_shapes['journalon'], 1, MEDIA_X, MEDIA_Y)
+ blk.spr.set_image(self.media_shapes['journalon'], 1,
+ MEDIA_X, MEDIA_Y)
dsobject.destroy()
except:
print "couldn't open dsobject (%s)" % (blk.values[0])
- blk.spr.set_image(self.media_shapes['journaloff'],
- 1, MEDIA_X, MEDIA_Y)
+ blk.spr.set_image(self.media_shapes['journaloff'], 1,
+ MEDIA_X, MEDIA_Y)
else:
if not movie_media_type(blk.values[0][-4:]):
try:
@@ -1538,16 +1605,23 @@ class TurtleArtWindow():
blk.spr.set_image(self.media_shapes['journaloff'],
1, MEDIA_X, MEDIA_Y)
else:
- blk.spr.set_image(self.media_shapes['journalon'], 1, MEDIA_X, MEDIA_Y)
+ blk.spr.set_image(self.media_shapes['journalon'], 1,
+ MEDIA_X, MEDIA_Y)
blk.spr.set_label(' ')
blk.resize()
elif btype in BOX_STYLE_MEDIA:
blk.spr.set_label(' ')
- blk.spr.set_image(self.media_shapes[btype+'off'], 1, MEDIA_X, MEDIA_Y)
+ blk.spr.set_image(self.media_shapes[btype+'off'], 1,
+ MEDIA_X, MEDIA_Y)
blk.spr.set_layer(BLOCK_LAYER)
+ if check_dock is True:
+ blk.connections = 'check'
return blk
-
+
+ #
+ # Restore a turtle from its saved state
+ #
def load_turtle(self, b):
id, name, xcor, ycor, heading, color, shade, pensize = b
self.canvas.setxy(xcor, ycor)
@@ -1556,11 +1630,16 @@ class TurtleArtWindow():
self.canvas.setshade(shade)
self.canvas.setpensize(pensize)
- # start a new project with a start brick
+ #
+ # Start a new project with a 'start' brick
+ #
def load_start(self):
self.clone_stack("%s%s%s" % ("[[0,[\"start\",\"", _("start"),
"\"],250,250,[null,null]]]"))
+ #
+ # Start a project to a file
+ #
def save_file(self):
if self.save_folder is not None:
self.load_save_folder = self.save_folder
@@ -1575,6 +1654,9 @@ class TurtleArtWindow():
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
+ #
def assemble_data_to_save(self, save_turtle=True, save_project=True):
# TODO: if save_project is False: just the current stack
data = []