Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2011-04-07 20:39:28 (GMT)
committer Walter Bender <walter.bender@gmail.com>2011-04-07 20:39:28 (GMT)
commit7acb67aa157a1cc2b55706ecb0441bce4a67c07f (patch)
tree75b2cf3ccf2ece5bb8b447e67ee2a4462c6ea877 /TurtleArt
parentbe16028cda8509d971dda42afb8307b95ff243a4 (diff)
refactoring of export logo code
Diffstat (limited to 'TurtleArt')
-rw-r--r--TurtleArt/tabasics.py24
-rw-r--r--TurtleArt/taexportlogo.py400
-rw-r--r--TurtleArt/tapalette.py8
3 files changed, 169 insertions, 263 deletions
diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py
index 0cc27d3..490fa21 100644
--- a/TurtleArt/tabasics.py
+++ b/TurtleArt/tabasics.py
@@ -62,7 +62,7 @@ from time import time
from math import sqrt
from random import uniform
-from tapalette import make_palette
+from tapalette import make_palette, define_logo_function
from talogo import primitive_dictionary, logoerror
from tautils import convert, chr_to_ord, round_int, strtype
from taconstants import BLACK, WHITE, CONSTANTS
@@ -180,6 +180,8 @@ degrees)'))
self.tw.lc.def_prim('arc', 2,
lambda self, x, y: primitive_dictionary['arc'](
self.tw.canvas.arc, x, y))
+ define_logo_function('taarc', 'to taarc :a :r\rrepeat round :a \
+[right 1 forward (0.0175 * :r)]\rend\r')
palette.add_block('setxy2',
style='basic-style-2arg',
@@ -192,6 +194,7 @@ degrees)'))
self.tw.lc.def_prim('setxy2', 2,
lambda self, x, y: primitive_dictionary['move'](
self.tw.canvas.setxy, x, y))
+ define_logo_function('tasetxy', 'to tasetxy :x :y\rsetxy :x :y\rend\r')
primitive_dictionary['set'] = self._prim_set
palette.add_block('seth',
@@ -257,6 +260,8 @@ turtle (can be used in place of a number block)'),
self.tw.lc.def_prim('setxy', 2,
lambda self, x, y: primitive_dictionary['move'](
self.tw.canvas.setxy, x, y, pendown=False))
+ define_logo_function('tasetxypenup', 'to tasetxypenup :x :y\rpenup\r\
+setxy :x :y\rpendown\rend\r')
def _pen_palette(self):
""" The basic Turtle Art pen palette """
@@ -294,6 +299,8 @@ turtle'))
self.tw.lc.def_prim('setpensize', 1,
lambda self, x: primitive_dictionary['set'](
'pensize', self.tw.canvas.setpensize, x))
+ define_logo_function('tasetpensize', 'to tasetpensize :a\rsetpensize \
+round :a\rend\r')
palette.add_block('fillscreen',
style='basic-style-2arg',
@@ -305,6 +312,8 @@ turtle'))
shade)'))
self.tw.lc.def_prim('fillscreen', 2,
lambda self, x, y: self.tw.canvas.fillscreen(x, y))
+ define_logo_function('tasetbackground', 'to tasetbackground :color \
+:shade\rtasetshade :shade\rsetbackground :color\rend\r')
palette.add_block('pensize',
style='box-style',
@@ -315,6 +324,8 @@ in place of a number block)'),
prim_name='pensize',
logo_command='pensize')
self.tw.lc.def_prim('pensize', 0, lambda self: self.tw.canvas.pensize)
+ define_logo_function('tapensize', 'to tapensize\routput first round \
+pensize\rend\r')
palette.add_block('startfill',
style='basic-style-extended-vertical',
@@ -466,6 +477,8 @@ turtle'))
top numeric input'))
self.tw.lc.def_prim(
'minus', 2, lambda self, x, y: primitive_dictionary['minus'](x, y))
+ define_logo_function('taminus', 'to taminus :y :x\routput sum :x minus \
+:y\rend\r')
primitive_dictionary['product'] = self._prim_product
palette.add_block('product2',
@@ -535,7 +548,10 @@ blocks'))
help_string=_('returns random number between minimum \
(top) and maximum (bottom) values'))
self.tw.lc.def_prim(
- 'random', 2, lambda self, x, y: primitive_dictionary['random'](x, y))
+ 'random', 2, lambda self, x, y: primitive_dictionary['random'](
+ x, y))
+ define_logo_function('tarandom', 'to tarandom :min :max\r \
+output (random (:max - :min)) + :min\rend\r')
palette.add_block('number',
style='box-style',
@@ -791,7 +807,7 @@ variable'))
label=_('action'),
prim_name='nop3',
default=_('stack'),
- logo_command='action',
+ logo_command='to action',
help_string=_('top of nameable action stack'))
self.tw.lc.def_prim('nop3', 1, lambda self, x: None)
@@ -816,7 +832,7 @@ variable'))
style='basic-style-1arg',
label=_('action'),
prim_name='stack',
- logo_command='runstack',
+ logo_command='action',
default=_('action'),
help_string=_('invokes named action stack'))
self.tw.lc.def_prim('stack', 1, primitive_dictionary['stack'], True)
diff --git a/TurtleArt/taexportlogo.py b/TurtleArt/taexportlogo.py
index ec9e14f..a8143ab 100644
--- a/TurtleArt/taexportlogo.py
+++ b/TurtleArt/taexportlogo.py
@@ -1,4 +1,4 @@
-#Copyright (c) 2008-10, Walter Bender
+#Copyright (c) 2008-11, Walter Bender
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
@@ -18,18 +18,16 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
-IGNORE = ['hideblocks', 'showblocks', 'fullscreen', 'polar', 'cartesian',
- 'sandwichbottom', 'id']
-
-import math
try:
from sugar.datastore import datastore
except:
pass
+from TurtleArt.tapalette import logo_commands, logo_functions
def save_logo(tw):
""" 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\
@@ -101,269 +99,157 @@ make "colors [ \
make "shade 50 \r\
tasetshade :shade \r'
- bs = tw.just_blocks()
- code = ''
+ # We need to catch several special cases: stacks, boxes, labels, etc.
+ dispatch_table = {
+ 'label': _add_label,
+ 'to action': _add_named_stack,
+ 'action': _add_reference_to_stack,
+ 'storeinbox': _add_named_box,
+ 'box': _add_reference_to_box
+ }
+ constants_table = {
+ 'lpos': _lpos,
+ 'tpos': _tpos,
+ 'rpos': _rpos,
+ 'bpos': _bpos,
+ }
+
+ stacks_of_blocks = tw.just_blocks()
stack_count = 0
- show = 0
-
- # These flags are used to trigger the prepending of additional procedures.
- random = False
- fillscreen = False
- setcolor = False
- setxy = False
- setxy2 = False
- pensize = False
- setpensize = False
- arc = False
- heap = False
- write = False
- minus = False
- division = False
- image = False
+
+ logocode = ''
"""
Walk through the code, substituting UCB Logo for Turtle Art primitives.
"""
- for b in bs:
+ for stack in stacks_of_blocks:
this_stack = ''
- data = walk_stack(tw.lc, b, tw.block_list.list)
- # 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
+ psuedocode = _walk_stack(tw, stack)
+ if psuedocode == []:
+ continue
+
+ skip = False
+ for i in range(len(psuedocode)):
+ if skip:
+ skip = False
+ continue
+ blk = psuedocode[i]
+ if type(blk) == type((1, 2)):
+ (blk, _blk_no) = blk
+ if blk in logo_commands:
+ logo_command = logo_commands[blk]
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 += 'tasetxypenup'
- elif d == 'setxy2':
- setxy2 = 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 == 'setpensize':
- setpensize = True
- this_stack += 'tasetpensize'
- 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 == 'division':
- this_stack += 'quotient'
- elif d == 'lpos':
- this_stack += str(-tw.canvas.width / (tw.coord_scale * 2))
- elif d == 'rpos':
- this_stack += str(tw.canvas.width / (tw.coord_scale * 2))
- elif d == 'bpos':
- this_stack += str(-tw.canvas.height / (tw.coord_scale * 2))
- elif d == 'tpos':
- this_stack += str(tw.canvas.height / (tw.coord_scale * 2))
- 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
+ logo_command = None
+ if i == 0 and not logo_command in ['to stack1\r', 'to stack2\r',
+ 'to action', 'to start\r']:
+ this_stack = 'to turtleblocks_%d\r' % (stack_count)
+ stack_count += 1
+ if logo_command in dispatch_table:
+ if i + 1 < len(psuedocode):
+ this_stack += dispatch_table[logo_command](
+ psuedocode[i + 1])
+ skip = True
else:
- this_stack += d
+ print 'missing arg to %s' % (logo_command)
+ elif logo_command in constants_table:
+ this_stack += constants_table[logo_command](tw)
+ elif logo_command is not None:
+ this_stack += logo_command
+ else: # assume it is an argument
+ if not blk in ['nop', 'nop1', 'nop2', 'nop3']:
+ if type(blk) == str and blk[0:2] == '#s':
+ this_stack += str(blk[2:]).replace(' ', '_')
+ else:
+ this_stack += str(blk).replace(' ', '_')
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
- if fillscreen: # Set shade than background color
- 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
- if setpensize: # Set int of pensize
- code = 'to tasetpensize :a\rsetpensize round :a\rend\r' + code
- if pensize: # Return only the first argument.
- code = 'to tapensize\routput first round pensize\rend\r' + code
- if setxy2: # Swap and round arguments
- code = 'to tasetxy :x :y\rsetxy :x :y\rend\r' + code
- if setxy: # Swap and round arguments and add pen up/down
- 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
- 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 = 'window\r' + code
- return code
-
-
-def walk_stack(lc, blk, list):
+
+ logocode += this_stack
+ logocode += '\rend\r'
+
+ # We may need to prepend some additional procedures.
+ for key in logo_functions.iterkeys():
+ if key in logocode:
+ logocode = logo_functions[key] + logocode
+
+ if 'tasetshade' in logocode or 'tasetcolor' in logocode or \
+ 'tasetbackground' in logocode:
+ logocode = color_processing + logocode
+
+ logocode = 'window\r' + logocode
+ return logocode
+
+
+def _add_label(string):
+ if type(string) == str and string[0:8] in ['#smedia_', '#saudio_',
+ '#svideo_', '#sdescr_']:
+ try:
+ dsobject = datastore.get(string[8:])
+ string = dsobject.metadata['title']
+ except:
+ print 'failed to get title for %s' % (string)
+ string = string[8:]
+ else:
+ string = str(string)
+ if string[0:2] == '#s':
+ string = string[2:]
+ string = '"' + string
+ if string.count(' ') > 0:
+ return 'label sentence %s\r' % (string.replace(' ', ' "'))
+ else:
+ return 'label %s' % (string.replace(' ', '_'))
+
+
+def _add_named_stack(action):
+ if type(action) == str and action[0:2] == '#s':
+ return 'to %s\r' % (str(action[2:]).replace(' ', '_'))
+ else:
+ return 'to %s\r' % (str(action).replace(' ', '_'))
+
+
+def _add_reference_to_stack(action):
+ if type(action) == str and action[0:2] == '#s':
+ return '%s' % (str(action[2:]).replace(' ', '_'))
+ else:
+ return '%s' % (str(action).replace(' ', '_'))
+
+
+def _add_named_box(box_name):
+ if type(box_name) == str and box_name[0:2] == '#s':
+ return 'make "%s' % (str(box_name[2:]).replace(' ', '_'))
+ else:
+ return 'make "%s' % (str(box_name).replace(' ', '_'))
+
+
+def _add_reference_to_box(box_name):
+ if type(box_name) == str and box_name[0:2] == '#s':
+ return ':%s' % (str(box_name[2:]).replace(' ', '_'))
+ else:
+ return ':%s' % (str(box_name).replace(' ', '_'))
+
+# TODO: Add the rest of the constants
+def _lpos(tw):
+ return str(-tw.canvas.width / (tw.coord_scale * 2))
+
+
+def _tpos(tw):
+ return str(tw.canvas.height / (tw.coord_scale * 2))
+
+
+def _rpos(tw):
+ return str(tw.canvas.width / (tw.coord_scale * 2))
+
+
+def _bpos(tw):
+ return str(-tw.canvas.height / (tw.coord_scale * 2))
+
+
+def _walk_stack(tw, blk_in_stack):
""" Convert blocks to logo psuedocode. """
from tautils import find_top_block
- top = find_top_block(blk)
- if blk == top:
- code = lc.run_blocks(top, list, False)
- return code
+ top = find_top_block(blk_in_stack)
+ if blk_in_stack == top:
+ psuedocode = tw.lc.run_blocks(top, tw.block_list.list, False)
+ return psuedocode
else:
return []
diff --git a/TurtleArt/tapalette.py b/TurtleArt/tapalette.py
index fbad7c3..6c10825 100644
--- a/TurtleArt/tapalette.py
+++ b/TurtleArt/tapalette.py
@@ -27,6 +27,7 @@ block_names = {}
block_primitives = {}
default_values = {}
logo_commands = {}
+logo_functions = {}
special_names = {} # Names for blocks without names for popup help
content_blocks = ['number', 'string', 'description', 'audio', 'video',
'journal']
@@ -175,6 +176,9 @@ def palette_name_to_index(palette_name):
else:
return None
+def define_logo_function(key, value):
+ ''' Add a logo function to the table. '''
+ logo_functions[key] = value
class Block():
""" a class for defining new block primitives """
@@ -230,8 +234,8 @@ class Block():
if self._prim_name is not None:
block_primitives[self._name] = self._prim_name
- if self._logo_command is not None:
- logo_commands[self._name] = self._logo_command
+ if self._logo_command is not None and self._prim_name is not None:
+ logo_commands[self._prim_name] = self._logo_command
if self._default is not None:
default_values[self._name] = self._default