Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2013-12-13 22:51:54 (GMT)
committer Walter Bender <walter@sugarlabs.org>2013-12-13 22:51:54 (GMT)
commit3d4c26ccfd8fc851b8dd34dab753d3dc70ea8160 (patch)
tree3e0188fb9c2123968d5fd8c9e43f648d8dd5d480
parentad5db297b65e5bf1894066b1d1474d6a3f465f5c (diff)
194.4v194.4
-rw-r--r--NEWS5
-rw-r--r--TurtleArt/tablock.py3
-rw-r--r--TurtleArt/tacanvas.py6
-rw-r--r--TurtleArt/taconstants.py5
-rw-r--r--TurtleArt/taexportpython.py28
-rw-r--r--TurtleArt/talogo.py68
-rwxr-xr-xTurtleArt/tasprite_factory.py12
-rw-r--r--TurtleArt/tawindow.py63
-rw-r--r--activity/activity.info2
-rw-r--r--plugins/turtle_blocks_extras/turtle_blocks_extras.py190
-rw-r--r--samples/sensors-camera.tb85
-rw-r--r--samples/sensors-vumeter.ta140
-rw-r--r--samples/thumbnails/sensors-camera.pngbin0 -> 95913 bytes
13 files changed, 376 insertions, 231 deletions
diff --git a/NEWS b/NEWS
index 070da31..6cdac1e 100644
--- a/NEWS
+++ b/NEWS
@@ -6,7 +6,8 @@ ENHANCEMENTS:
* Add load/save plugin dialog to GNOME version (Daniel Francis)
* Add busy cursor when projects are being prepared to run
* Reworked Duplicate Blocks warning graphic to reflect current block shapes
-* Refactored until block to better reflect flow logic
+* Refactor until block shape to better reflect flow logic
+* Enabled load file to heap/save heap to file to use the Sugar journal
* New translations
BUG FIX:
@@ -17,7 +18,7 @@ BUG FIX:
* Fixed problem with running_blocks flag not being cleared (cause of spurious
"hit stop button" messages.
* Fixed problem with errant text entry widget on run.
-* Fixed problem with WeDo plugin (Alan Aguiar)
+* Fixed problem with text wrap of SVG output #1856 (Jorge Alberto Gómez López)
193
diff --git a/TurtleArt/tablock.py b/TurtleArt/tablock.py
index 3b9650f..402de33 100644
--- a/TurtleArt/tablock.py
+++ b/TurtleArt/tablock.py
@@ -1088,7 +1088,8 @@ class Block:
self.svg.docks[4][1], ']']]
def _make_clamp_style_until(self, svg, extend_x=0, extend_y=4):
- self.svg.expand(self.dx + self.ex + extend_x, self.ey + extend_y)
+ self.svg.expand(self.dx + self.ex + extend_x, self.ey + extend_y,
+ 0, self.ey2)
self.svg.set_slot(True)
self.svg.set_tab(True)
self.svg.set_boolean(True)
diff --git a/TurtleArt/tacanvas.py b/TurtleArt/tacanvas.py
index 4bac442..f37a3a4 100644
--- a/TurtleArt/tacanvas.py
+++ b/TurtleArt/tacanvas.py
@@ -305,10 +305,14 @@ class TurtleGraphics:
''' Draw text '''
def _draw_text(cr, label, x, y, size, width, scale, heading, rgb):
+ import textwrap
+ final_scale = int(size * scale) * pango.SCALE
+ label = str(label)
+ label = '\n'.join(textwrap.wrap(label, int(width / scale)))
cc = pangocairo.CairoContext(cr)
pl = cc.create_layout()
fd = pango.FontDescription('Sans')
- fd.set_size(int(size * scale) * pango.SCALE)
+ fd.set_size(final_scale)
pl.set_font_description(fd)
if isinstance(label, (str, unicode)):
pl.set_text(label.replace('\0', ' '))
diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py
index 75288c1..3e92956 100644
--- a/TurtleArt/taconstants.py
+++ b/TurtleArt/taconstants.py
@@ -341,8 +341,6 @@ VOICES = {'af': 'afrikaans', 'cy': 'welsh-test', 'el': 'greek',
MACROS = {
'ifthenelse': # Because it is too big to fit on the palette
[[0, 'ifelse', 0, 0, [None, None, None, None, None]]],
- 'untilmacro': # Because it is too big to fit on the palette
- [[0, 'until', 0, 0, [None, None, None, None]]],
'kbinput':
[[0, 'until', 0, 0, [None, 1, 4, None]],
[1, 'greater2', 0, 0, [0, 2, 3, None]],
@@ -544,4 +542,7 @@ MACROS = {
[25, 'description', 0, 0, [24, None]]],
'reskin':
[[0, 'skin', 0, 0, [None, 1, None]],
+ [1, 'journal', 0, 0, [0, None]]],
+ 'loadheapfromjournal':
+ [[0, 'loadheap', 0, 0, [None, 1, None]],
[1, 'journal', 0, 0, [0, None]]]}
diff --git a/TurtleArt/taexportpython.py b/TurtleArt/taexportpython.py
index 9135302..60bf0c1 100644
--- a/TurtleArt/taexportpython.py
+++ b/TurtleArt/taexportpython.py
@@ -45,18 +45,22 @@ _ALTERNATIVE_INSTALL_PATH = \
'/usr/local/share/sugar/activities/TurtleArt.activity'
import os, sys
-if os.path.exists('../TurtleBlocks.activity'):
- sys.path.insert(0, '../TurtleBlocks.activity')
-elif os.path.exists(os.path.join(os.path.expanduser('~'), 'Activities',
- 'TurtleBlocks.activity')):
- sys.path.insert(0, os.path.join(os.path.expanduser('~'), 'Activities',
- 'TurtleBlocks.activity'))
-elif os.path.exists(_INSTALL_PATH):
- sys.path.insert(0, _INSTALL_PATH)
-elif os.path.exists(_ALTERNATIVE_INSTALL_PATH):
- sys.path.insert(0, _ALTERNATIVE_INSTALL_PATH)
-else:
- print 'This code require the TurtleBlocks activity to be installed.'
+paths = []
+paths.append('../%s.activity')
+paths.append(os.path.expanduser('~') + '/Activities/%s.activity')
+paths.append('/usr/share/sugar/activities/%s.activity')
+paths.append('/usr/local/share/sugar/activities/%s.activity')
+
+flag = False
+for path in paths:
+ for activity in ['TurtleBlocks', 'TurtleBots']:
+ p = path % activity
+ if os.path.exists(p):
+ flag = True
+ sys.path.insert(0, p)
+
+if not flag:
+ print 'This code require the Turtle Blocks/Bots activity to be installed.'
exit(1)
from time import *
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index 5380137..5792043 100644
--- a/TurtleArt/talogo.py
+++ b/TurtleArt/talogo.py
@@ -835,24 +835,35 @@ class LogoCode:
name = float(name)
return 'stack3' + str(name)
- def load_heap(self, path):
+ def load_heap(self, obj):
""" Load FILO from file """
if self.tw.running_sugar:
- # Choose a datastore object and push data to heap (Sugar only)
- chooser_dialog(self.tw.parent, path, self.push_file_data_to_heap)
+ # Is the object a dsobject?
+ if isinstance(obj, Media) and obj.value:
+ from sugar.datastore import datastore
+ try:
+ dsobject = datastore.get(obj.value)
+ except:
+ debug_output("Couldn't find dsobject %s" %
+ (obj.value), self.tw.running_sugar)
+ if dsobject is not None:
+ self.push_file_data_to_heap(dsobject)
+ # Or is it a path?
+ elif os.path.exists(obj):
+ self.push_file_data_to_heap(None, path=obj)
+ else:
+ # Finally try choosing a datastore object
+ chooser_dialog(self.tw.parent, obj,
+ self.push_file_data_to_heap)
else:
- if not os.path.exists(path):
- path, self.tw.load_save_folder = get_load_name(
+ # If you cannot find the file, open a chooser.
+ if not os.path.exists(obj):
+ obj, self.tw.load_save_folder = get_load_name(
'.*', self.tw.load_save_folder)
- if path is None:
- return
+ if obj is not None:
+ self.push_file_data_to_heap(None, path=obj)
- data = data_from_file(path)
- if data is not None:
- for val in data:
- self.heap.append(val)
-
- def save_heap(self, path):
+ def save_heap(self, obj):
""" save FILO to file """
if self.tw.running_sugar:
from sugar import profile
@@ -861,22 +872,23 @@ class LogoCode:
# Save JSON-encoded heap to temporary file
heap_file = os.path.join(get_path(activity, 'instance'),
- str(path) + '.txt')
+ 'heap.txt')
data_to_file(self.heap, heap_file)
- # Create a datastore object
- dsobject = datastore.create()
-
- # Write any metadata (specifically set the title of the file
- # and specify that this is a plain text file).
- dsobject.metadata['title'] = str(path)
- dsobject.metadata['icon-color'] = profile.get_color().to_string()
- dsobject.metadata['mime_type'] = 'text/plain'
+ # Write to an existing or new dsobject
+ if isinstance(obj, Media) and obj.value:
+ dsobject = datastore.get(obj.value)
+ else:
+ dsobject = datastore.create()
+ dsobject.metadata['title'] = str(obj)
+ dsobject.metadata['icon-color'] = \
+ profile.get_color().to_string()
+ dsobject.metadata['mime_type'] = 'text/plain'
dsobject.set_file_path(heap_file)
datastore.write(dsobject)
dsobject.destroy()
else:
- heap_file = path
+ heap_file = obj
data_to_file(self.heap, heap_file)
def get_heap(self):
@@ -1172,9 +1184,15 @@ class LogoCode:
int(self.tw.canvas.textsize * self.scale / 100.),
self.tw.canvas.width - x)
- def push_file_data_to_heap(self, dsobject):
+ def push_file_data_to_heap(self, dsobject, path=None):
""" push contents of a data store object (assuming json encoding) """
- data = data_from_file(dsobject.file_path)
+ if dsobject:
+ data = data_from_file(dsobject.file_path)
+ elif path is not None:
+ data = data_from_file(path)
+ else:
+ data = None
+ debug_output("No file to open", self.tw.running_sugar)
if data is not None:
for val in data:
self.heap.append(val)
diff --git a/TurtleArt/tasprite_factory.py b/TurtleArt/tasprite_factory.py
index 7f9494c..8360dbb 100755
--- a/TurtleArt/tasprite_factory.py
+++ b/TurtleArt/tasprite_factory.py
@@ -634,22 +634,12 @@ stroke-width="3.5" fill="%s" stroke="none" />\n' % (self._stroke)
svg += self._inverse_corner(1, 1, 90, 0, 0)
svg += self._do_slot()
svg += self._rline_to(self._radius, 0)
- if self._second_clamp:
- svg += self._corner(-1, 1)
- svg += self.line_to(xx, self._y)
- svg += self._rline_to(-self._expand_x, 0)
- svg += self._do_tab()
- svg += self._inverse_corner(-1, 1, 90, 0, 0)
- svg += self._rline_to(0, self._expand_y2)
- svg += self._inverse_corner(1, 1, 90, 0, 0)
- svg += self._do_slot()
- svg += self._rline_to(self._radius, 0)
if self._innie[0] is True:
svg += self._do_innie()
else:
self.margins[2] = \
int((self._x - self._stroke_width + 0.5) * self._scale)
- svg += self._rline_to(0, self._radius * 3)
+ svg += self._rline_to(0, self._radius + self._expand_y2)
if self._bool is True:
svg += self._do_boolean()
svg += self._corner(-1, 1)
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index 2f0a036..4584726 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -2554,10 +2554,14 @@ before making changes to your program'))
continue
if blk.name in EXPANDABLE_FLOW:
if blk.name in block_styles['clamp-style-1arg'] or \
- blk.name in block_styles['clamp-style-boolean'] or \
- blk.name in block_styles['clamp-style-until']:
+ blk.name in block_styles['clamp-style-boolean']:
if blk.connections[2] is not None:
self._resize_clamp(blk, blk.connections[2])
+ elif blk.name in block_styles['clamp-style-until']:
+ if blk.connections[2] is not None:
+ self._resize_clamp(blk, blk.connections[2])
+ if blk.connections[1] is not None:
+ self._resize_clamp(blk, blk.connections[1], dockn=1)
elif blk.name in block_styles['clamp-style']:
if blk.connections[1] is not None:
self._resize_clamp(blk, blk.connections[1])
@@ -3392,12 +3396,18 @@ before making changes to your program'))
if best_destination.name in \
block_styles['clamp-style-1arg'] or \
best_destination.name in \
- block_styles['clamp-style-boolean'] or \
- best_destination.name in \
- block_styles['clamp-style-until']:
+ block_styles['clamp-style-boolean']:
if best_destination_dockn == 2:
self._resize_clamp(best_destination,
self.drag_group[0])
+ elif best_destination.name in \
+ block_styles['clamp-style-until']:
+ if best_destination_dockn == 2:
+ self._resize_clamp(best_destination,
+ self.drag_group[0])
+ elif best_destination_dockn == 1:
+ self._resize_clamp(best_destination,
+ self.drag_group[0], dockn=1)
elif best_destination.name in block_styles['clamp-style'] or \
best_destination.name in \
block_styles['clamp-style-collapsible']:
@@ -3496,16 +3506,18 @@ before making changes to your program'))
self._cascade_expandable(blk2)
elif c is not None and blk2.name in EXPANDABLE_FLOW:
if blk2.name in block_styles['clamp-style-1arg'] or \
- blk2.name in block_styles['clamp-style-boolean'] or \
- blk2.name in block_styles['clamp-style-until']:
+ blk2.name in block_styles['clamp-style-boolean']:
if c == 2:
- self._resize_clamp(blk2, None, c)
+ self._resize_clamp(blk2, None, dockn=c)
+ elif blk2.name in block_styles['clamp-style-until']:
+ if c in [1, 2]:
+ self._resize_clamp(blk2, None, dockn=c)
elif blk2.name in block_styles['clamp-style'] or \
blk2.name in block_styles['clamp-style-collapsible']:
if c == 1:
self._resize_clamp(blk2, None)
elif blk2.name in block_styles['clamp-style-else']:
- if c == 2 or c == 3:
+ if c in [2, 3]:
self._resize_clamp(blk2, None, dockn=c)
while blk3 is not None and blk3.connections[dockn] is not None:
self._resize_clamp(blk3, blk3.connections[dockn], dockn=dockn)
@@ -3521,22 +3533,35 @@ before making changes to your program'))
y1 = blk.docks[-1][3]
if blk.name in block_styles['clamp-style-else'] and dockn == 3:
blk.reset_y2()
+ elif blk.name in block_styles['clamp-style-until'] and dockn == 1:
+ blk.reset_y2()
else:
blk.reset_y()
dy = 0
# Calculate height of drag group
- while gblk is not None:
- delta = int((gblk.docks[-1][3] - gblk.docks[0][3]) / gblk.scale)
- if delta == 0:
- dy += 21 # Fixme: don't hardcode size of stop action block
- else:
- dy += delta
- gblk = gblk.connections[-1]
- # Clamp has room for one 'standard' block by default
- if dy > 0:
- dy -= 21 # Fixme: don't hardcode
+ if blk.name in block_styles['clamp-style-until'] and dockn == 1:
+ if gblk is not None:
+ dy = int(gblk.spr.rect.height / gblk.scale)
+ # Room for part of one 'standard' boolean by default
+ if dy > 0:
+ dy -= 25 # Fixme: don't hardcode size of slot
+ if dy < 0:
+ dy = 0
+ else:
+ while gblk is not None:
+ delta = int((gblk.docks[-1][3] - gblk.docks[0][3]) / gblk.scale)
+ if delta == 0:
+ dy += 21 # Fixme: don't hardcode size of slot
+ else:
+ dy += delta
+ gblk = gblk.connections[-1]
+ # Clamp has room for one 'standard' block by default
+ if dy > 0:
+ dy -= 21 # Fixme: don't hardcode size of slot
if blk.name in block_styles['clamp-style-else'] and dockn == 3:
blk.expand_in_y2(dy)
+ elif blk.name in block_styles['clamp-style-until'] and dockn == 1:
+ blk.expand_in_y2(dy)
else:
blk.expand_in_y(dy)
y2 = blk.docks[-1][3]
diff --git a/activity/activity.info b/activity/activity.info
index 5faffd9..726034d 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,6 +1,6 @@
[Activity]
name = TurtleBlocks
-activity_version = 194.3
+activity_version = 194.4
license = MIT
bundle_id = org.laptop.TurtleArtActivity
exec = sugar-activity TurtleArtActivity.TurtleArtActivity
diff --git a/plugins/turtle_blocks_extras/turtle_blocks_extras.py b/plugins/turtle_blocks_extras/turtle_blocks_extras.py
index 62dd40f..556ed41 100644
--- a/plugins/turtle_blocks_extras/turtle_blocks_extras.py
+++ b/plugins/turtle_blocks_extras/turtle_blocks_extras.py
@@ -93,7 +93,6 @@ boolean operators from Numbers palette'))
True)
palette.add_block('until',
- hidden=True, # Too big to fit on palette
style='clamp-style-until',
label=_('until'),
prim_name='until',
@@ -116,13 +115,6 @@ boolean operators from Numbers palette'))
ArgSlot(TYPE_OBJECT)]),
True)
- # macro
- palette.add_block('untilmacro',
- style='basic-style-extended-vertical',
- label=_('until'),
- help_string=_('do-until-True operator that uses \
-boolean operators from Numbers palette'))
-
palette.add_block('sandwichclamp',
style='clamp-style-collapsible',
label=' ',
@@ -541,21 +533,38 @@ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n')
prim_name='saveheap',
help_string=_('saves FILO (first-in \
last-out heap) to a file'))
+
self.tw.lc.def_prim('saveheap', 1,
Primitive(self.tw.lc.save_heap,
- arg_descs=[ArgSlot(TYPE_STRING)]))
+ arg_descs=[ArgSlot(TYPE_OBJECT)]))
- palette.add_block('loadheap',
- style='basic-style-1arg',
- label=_('load heap from file'),
- default=_('filename'),
- prim_name='loadheap',
- help_string=_('loads FILO (first-in \
+ if self.tw.running_sugar:
+ palette.add_block('loadheap',
+ style='basic-style-1arg',
+ hidden=True,
+ label=_('load heap from file'),
+ default=_('filename'),
+ prim_name='loadheap',
+ help_string=_('loads FILO (first-in \
+last-out heap) from a file'))
+ # macro
+ palette.add_block('loadheapfromjournal',
+ style='basic-style-1arg',
+ label=_('load heap from file'),
+ help_string=_('loads FILO (first-in \
last-out heap) from a file'))
+ else:
+ palette.add_block('loadheap',
+ style='basic-style-1arg',
+ label=_('load heap from file'),
+ default=_('filename'),
+ prim_name='loadheap',
+ help_string=_('loads FILO (first-in \
+last-out heap) from a file'))
+
self.tw.lc.def_prim('loadheap', 1,
Primitive(self.tw.lc.load_heap,
- arg_descs=[ArgSlot(TYPE_STRING)],
- return_type=TYPE_STRING,
+ arg_descs=[ArgSlot(TYPE_OBJECT)],
call_afterwards=self.after_push))
palette.add_block('isheapempty2',
@@ -735,57 +744,36 @@ module found in the Journal'))
MEDIA_SHAPES.append('pythonoff')
MEDIA_SHAPES.append('pythonon')
- palette.add_block('loadblock',
- style='basic-style-var-arg',
- label=_('load'),
- prim_name='loadblock',
- default=_('forward'),
- help_string=_('loads a block'))
- self.tw.lc.def_prim('loadblock', 1,
- Primitive(self.tw.prim_load_block,
- export_me=False,
+ palette.add_block('getfromurl',
+ style='number-style-1arg',
+ #TRANS: URL is universal resource locator
+ label=_('URL'),
+ default=\
+'http://wiki.sugarlabs.org/images/2/2c/Logo_alt_3.svg',
+ prim_name='getfromurl',
+ help_string=\
+_('gets a text string or an image from a URL'))
+ self.tw.lc.def_prim('getfromurl', 1,
+ Primitive(self.tw.lc.get_from_url,
arg_descs=[ArgSlot(TYPE_STRING)]))
- palette.add_block('loadblock2arg',
- style='basic-style-var-arg',
- hidden=True,
- label=_('load'),
- prim_name='loadblock2',
- string_or_number=True,
- default=[_('forward'), 100],
- help_string=_('loads a block'))
- self.tw.lc.def_prim('loadblock2', 2,
- Primitive(self.tw.prim_load_block,
- export_me=False,
- arg_descs=[ArgSlot(TYPE_STRING),
- ArgSlot(TYPE_OBJECT)]))
- palette.add_block('loadblock3arg',
- style='basic-style-var-arg',
+ palette.add_block('skin',
hidden=True,
- label=_('load'),
- string_or_number=True,
- prim_name='loadblock3',
- default=[_('setxy'), 0, 0],
- help_string=_('loads a block'))
- self.tw.lc.def_prim('loadblock3', 3,
- Primitive(self.tw.prim_load_block,
- export_me=False,
- arg_descs=[ArgSlot(TYPE_STRING),
- ArgSlot(TYPE_OBJECT),
- ArgSlot(TYPE_OBJECT)]))
+ colors=["#FF0000", "#A00000"],
+ style='basic-style-1arg',
+ label=_('turtle shell'),
+ prim_name='skin',
+ help_string=_("put a custom 'shell' on the turtle"))
+ self.tw.lc.def_prim('skin', 1,
+ Primitive(self.tw.lc.reskin,
+ arg_descs=[ArgSlot(TYPE_OBJECT)]))
- palette.add_block('loadpalette',
+ # macro
+ palette.add_block('reskin',
style='basic-style-1arg',
- string_or_number=True,
- label=_('select palette'),
- prim_name='loadpalette',
- default=_('turtle'),
- help_string=_('selects a palette'))
- self.tw.lc.def_prim('loadpalette', 1,
- Primitive(self.tw.prim_load_palette,
- export_me=False,
- arg_descs=[ArgSlot(TYPE_STRING)]))
+ label=_('turtle shell'),
+ help_string=_("put a custom 'shell' on the turtle"))
palette.add_block('addturtle',
style='basic-style-1arg',
@@ -845,23 +833,6 @@ module found in the Journal'))
arg_descs=[ArgSlot(TYPE_OBJECT)],
return_type=TYPE_BOX))
- palette.add_block('skin',
- hidden=True,
- colors=["#FF0000", "#A00000"],
- style='basic-style-1arg',
- label=_('turtle shell'),
- prim_name='skin',
- help_string=_("put a custom 'shell' on the turtle"))
- self.tw.lc.def_prim('skin', 1,
- Primitive(self.tw.lc.reskin,
- arg_descs=[ArgSlot(TYPE_OBJECT)]))
-
- # macro
- palette.add_block('reskin',
- style='basic-style-1arg',
- label=_('turtle shell'),
- help_string=_("put a custom 'shell' on the turtle"))
-
palette.add_block('sandwichclampcollapsed',
hidden=True,
style='clamp-style-collapsed',
@@ -870,17 +841,56 @@ module found in the Journal'))
special_name=_('top'),
help_string=_('top of a collapsed stack'))
- palette.add_block('getfromurl',
- style='number-style-1arg',
- #TRANS: URL is universal resource locator
- label=_('URL'),
- default=\
-'http://wiki.sugarlabs.org/images/2/2c/Logo_alt_3.svg',
- prim_name='getfromurl',
- help_string=\
-_('gets a text string or an image from a URL'))
- self.tw.lc.def_prim('getfromurl', 1,
- Primitive(self.tw.lc.get_from_url,
+ palette.add_block('loadblock',
+ style='basic-style-var-arg',
+ label=_('load'),
+ prim_name='loadblock',
+ default=_('forward'),
+ help_string=_('loads a block'))
+ self.tw.lc.def_prim('loadblock', 1,
+ Primitive(self.tw.prim_load_block,
+ export_me=False,
+ arg_descs=[ArgSlot(TYPE_STRING)]))
+
+ palette.add_block('loadblock2arg',
+ style='basic-style-var-arg',
+ hidden=True,
+ label=_('load'),
+ prim_name='loadblock2',
+ string_or_number=True,
+ default=[_('forward'), 100],
+ help_string=_('loads a block'))
+ self.tw.lc.def_prim('loadblock2', 2,
+ Primitive(self.tw.prim_load_block,
+ export_me=False,
+ arg_descs=[ArgSlot(TYPE_STRING),
+ ArgSlot(TYPE_OBJECT)]))
+
+ palette.add_block('loadblock3arg',
+ style='basic-style-var-arg',
+ hidden=True,
+ label=_('load'),
+ string_or_number=True,
+ prim_name='loadblock3',
+ default=[_('setxy'), 0, 0],
+ help_string=_('loads a block'))
+ self.tw.lc.def_prim('loadblock3', 3,
+ Primitive(self.tw.prim_load_block,
+ export_me=False,
+ arg_descs=[ArgSlot(TYPE_STRING),
+ ArgSlot(TYPE_OBJECT),
+ ArgSlot(TYPE_OBJECT)]))
+
+ palette.add_block('loadpalette',
+ style='basic-style-1arg',
+ string_or_number=True,
+ label=_('select palette'),
+ prim_name='loadpalette',
+ default=_('turtle'),
+ help_string=_('selects a palette'))
+ self.tw.lc.def_prim('loadpalette', 1,
+ Primitive(self.tw.prim_load_palette,
+ export_me=False,
arg_descs=[ArgSlot(TYPE_STRING)]))
def _portfolio_palette(self):
diff --git a/samples/sensors-camera.tb b/samples/sensors-camera.tb
new file mode 100644
index 0000000..95101a2
--- /dev/null
+++ b/samples/sensors-camera.tb
@@ -0,0 +1,85 @@
+[[0, ["start", 2.0], 320, 120, [null, 1]],
+[1, "clean", 320, 166, [0, 10]],
+[2, "setscale", 338, 586, [81, 4, null]],
+[3, "scale", 910, 250, [62, null]],
+[4, ["minus2", 0], 415, 586, [2, 83, 5]],
+[5, ["number", 1], 512, 628, [4, null]],
+[6, ["repeat", 147], 320, 250, [10, 7, 74, null]],
+[7, ["number", 37], 379, 250, [6, null]],
+[8, "show", 338, 334, [74, 9, 72]],
+[9, ["camera", "CAMERA"], 396, 334, [8, null]],
+[10, "setscale", 320, 208, [1, 11, 6]],
+[11, ["number", 50], 397, 208, [10, null]],
+[12, "forward", 1118, 250, [17, 15, 18]],
+[13, ["storein", 0], 718, 208, [68, 14, 58, 59]],
+[14, ["string", "alto"], 786, 208, [13, null]],
+[15, "box", 1189, 250, [12, 16, null]],
+[16, ["string", "alto"], 1244, 250, [15, null]],
+[17, "penup", 1118, 208, [71, 12]],
+[18, "pendown", 1118, 292, [12, 19]],
+[19, "right", 1118, 334, [18, 20, 24]],
+[20, ["number", 90], 1176, 334, [19, null]],
+[21, ["storein", 0], 718, 374, [59, 22, 60, null]],
+[22, ["string", "ancho"], 786, 374, [21, null]],
+[23, ["number", 225], 910, 458, [61, null]],
+[24, "forward", 1118, 376, [19, 25, 27]],
+[25, "box", 1189, 376, [24, 26, null]],
+[26, ["string", "ancho"], 1244, 376, [25, null]],
+[27, "right", 1118, 418, [24, 28, 29]],
+[28, ["number", 90], 1176, 418, [27, null]],
+[29, "forward", 1118, 460, [27, 35, 42]],
+[30, ["product2", 0], 1189, 586, [34, 43, 31]],
+[31, ["number", 2], 1243, 628, [30, null]],
+[32, "right", 1118, 796, [52, 33, 53]],
+[33, ["number", 90], 1176, 796, [32, null]],
+[34, "forward", 1118, 586, [39, 30, 41]],
+[35, ["product2", 0], 1189, 460, [29, 37, 36]],
+[36, ["number", 2], 1243, 502, [35, null]],
+[37, "box", 1243, 460, [35, 38, null]],
+[38, ["string", "alto"], 1298, 460, [37, null]],
+[39, "right", 1118, 544, [42, 40, 34]],
+[40, ["number", 90], 1176, 544, [39, null]],
+[41, ["vspace", 0], 1118, 628, [34, 45]],
+[42, ["vspace", 0], 1118, 502, [29, 39]],
+[43, "box", 1243, 586, [30, 44, null]],
+[44, ["string", "ancho"], 1298, 586, [43, null]],
+[45, "right", 1118, 670, [41, 46, 47]],
+[46, ["number", 90], 1176, 670, [45, null]],
+[47, "forward", 1118, 712, [45, 51, 52]],
+[48, ["number", 2], 1243, 754, [51, null]],
+[49, "box", 1243, 712, [51, 50, null]],
+[50, ["string", "alto"], 1298, 712, [49, null]],
+[51, ["product2", 0], 1189, 712, [47, 49, 48]],
+[52, ["vspace", 0], 1118, 754, [47, 32]],
+[53, "forward", 1118, 838, [32, 54, 79]],
+[54, "box", 1189, 838, [53, 55, null]],
+[55, ["string", "ancho"], 1244, 838, [54, null]],
+[56, "scale", 910, 416, [61, null]],
+[57, ["number", 33], 880, 332, [58, null]],
+[58, ["division2", 20], 786, 250, [13, 62, 57]],
+[59, ["vspace", 20], 718, 292, [13, 21]],
+[60, ["division2", 20], 786, 416, [21, 61, 64]],
+[61, ["product2", 0], 856, 416, [60, 56, 23]],
+[62, ["product2", 0], 856, 250, [58, 3, 63]],
+[63, ["number", 125], 910, 292, [62, null]],
+[64, ["number", 33], 880, 498, [60, null]],
+[65, "penup", 338, 418, [72, 76]],
+[66, "hat", 700, 120, [null, 67, 68]],
+[67, ["string", "calc_size"], 758, 132, [66, null]],
+[68, ["sandwichclamp", 104], 700, 174, [66, 13, null]],
+[69, "hat", 1100, 120, [null, 70, 71]],
+[70, ["string", "draw_rect"], 1158, 132, [69, null]],
+[71, "sandwichclampcollapsed", 1100, 174, [69, 17, null]],
+[72, "stack", 338, 376, [8, 73, 65]],
+[73, ["string", "draw_rect"], 396, 376, [72, null]],
+[74, "stack", 338, 292, [6, 75, 8]],
+[75, ["string", "calc_size"], 396, 292, [74, null]],
+[76, ["setxy2", 0], 338, 460, [65, 77, 78, 81]],
+[77, ["number", 0], 396, 460, [76, null]],
+[78, ["number", 0], 396, 502, [76, null]],
+[79, "left", 1118, 880, [53, 80, null]],
+[80, ["number", 90], 1176, 880, [79, null]],
+[81, "right", 338, 544, [76, 82, 2]],
+[82, ["number", 10], 396, 544, [81, null]],
+[83, "scale", 488, 586, [4, null]],
+[-1, ["turtle", "Yertle"], 0.0, 0.0, 10.0, 0, 50, 5]] \ No newline at end of file
diff --git a/samples/sensors-vumeter.ta b/samples/sensors-vumeter.ta
index 642e4bc..6bc52ff 100644
--- a/samples/sensors-vumeter.ta
+++ b/samples/sensors-vumeter.ta
@@ -1,67 +1,73 @@
-[[0, ["start", 2.0], 34, 198, [null, 18]],
-[1, "forever", 34, 450, [31, 10, 2]],
-[2, ["vspace", 0], 34, 486, [1, null]],
-[3, ["setxy2", 0], 160, 528, [10, 4, 8, null]],
-[4, ["number", 0], 218, 528, [3, null]],
-[5, "volume", 326, 570, [6, null]],
-[6, ["division2", 0], 272, 570, [8, 5, 7]],
-[7, ["number", 10], 350, 612, [6, null]],
-[8, ["minus2", 20], 218, 570, [3, 6, 9]],
-[9, ["number", 200], 296, 652, [8, null]],
-[10, "repeat", 98, 468, [1, 11, 3, 12]],
-[11, ["number", 20], 146, 468, [10, null]],
-[12, ["vspace", 20], 98, 546, [10, 20]],
-[13, ["setxy2", 0], 652, 319, [17, 14, 15, 29]],
-[14, ["number", 0], 710, 319, [13, null]],
-[15, ["number", -200], 710, 361, [13, null]],
-[16, "penup", 652, 109, [19, 21]],
-[17, "pendown", 652, 277, [24, 13]],
-[18, "hideblocks", 34, 240, [0, 26]],
-[19, "hat1", 652, 67, [null, 16]],
-[20, "stack1", 98, 628, [12, null]],
-[21, ["setxy2", 0], 652, 151, [16, 22, 23, 24]],
-[22, ["number", 0], 710, 151, [21, null]],
-[23, "toppos", 710, 193, [21, null]],
-[24, "setcolor", 652, 235, [21, 28, 17]],
-[25, "white", 120, 282, [26, null]],
-[26, ["fillscreen", 0], 34, 282, [18, 25, 27, 37]],
-[27, ["number", 80], 120, 324, [26, null]],
-[28, "white", 730, 235, [24, null]],
-[29, "setcolor", 652, 403, [13, 30, null]],
-[30, ["number", 0], 730, 403, [29, null]],
-[31, "setpensize", 34, 408, [37, 32, 1]],
-[32, ["number", 30], 137, 408, [31, null]],
-[33, "hat2", 883, 65, [null, 62]],
-[34, "repeat", 883, 359, [42, 35, 43, 36]],
-[35, ["number", 6], 931, 359, [34, null]],
-[36, ["vspace", 80], 883, 437, [34, 53]],
-[37, "stack2", 34, 366, [26, 31]],
-[38, ["setxy2", 0], 883, 233, [41, 39, 40, 42]],
-[39, ["number", -100], 941, 233, [38, null]],
-[40, ["number", -200], 941, 275, [38, null]],
-[41, "penup", 883, 191, [60, 38]],
-[42, "pendown", 883, 317, [38, 34]],
-[43, "right", 945, 419, [34, 44, 45]],
-[44, ["number", 90], 1003, 419, [43, null]],
-[45, "forward", 945, 461, [43, 46, 47]],
-[46, ["number", 20], 1017, 461, [45, null]],
-[47, "back", 945, 503, [45, 48, 49]],
-[48, ["number", 20], 1003, 503, [47, null]],
-[49, "left", 945, 545, [47, 50, 54]],
-[50, ["number", 90], 1003, 545, [49, null]],
-[51, "forward", 945, 711, [64, 52, null]],
-[52, ["number", 100], 1017, 711, [51, null]],
-[53, "penup", 883, 639, [36, null]],
-[54, "show", 945, 587, [49, 66, 64]],
-[55, "ycor", 1165, 629, [57, null]],
-[56, ["number", 200], 1165, 671, [57, null]],
-[57, ["plus2", 0], 1111, 629, [58, 55, 56]],
-[58, ["product2", 20], 1057, 629, [66, 57, 59]],
-[59, ["number", 10], 1111, 711, [58, null]],
-[60, "setpensize", 883, 149, [62, 61, 41]],
-[61, ["number", 5], 986, 149, [60, null]],
-[62, "setscale", 883, 107, [33, 63, 60]],
-[63, ["number", 25.0], 962, 107, [62, null]],
-[64, ["vspace", 20], 945, 629, [54, 51]],
-[65, ["string", " "], 1057, 587, [66, null]],
-[66, ["plus2", 0], 1003, 587, [54, 65, 58]]]
+[[0, ["start", 2.0], 360, 120, [null, 62]],
+[1, ["forever", 134], 360, 418, [28, 9, null]],
+[2, ["setxy2", 0], 396, 536, [60, 3, 7, null]],
+[3, ["number", 0], 454, 536, [2, null]],
+[4, "volume", 597, 578, [5, null]],
+[5, ["division2", 0], 527, 578, [7, 4, 6]],
+[6, ["number", 10], 621, 620, [5, null]],
+[7, ["minus2", 20], 454, 578, [2, 5, 8]],
+[8, ["number", 200], 551, 660, [7, null]],
+[9, ["repeat", 42], 378, 452, [1, 10, 60, 11]],
+[10, ["number", 20], 437, 452, [9, null]],
+[11, ["vspace", 20], 378, 638, [9, 70]],
+[12, ["setxy2", 0], 660, 384, [16, 13, 14, 26]],
+[13, ["number", 0], 718, 384, [12, null]],
+[14, ["number", -300], 718, 426, [12, null]],
+[15, "penup", 660, 174, [65, 18]],
+[16, "pendown", 660, 342, [21, 12]],
+[17, "hideblocks", 360, 208, [62, 23]],
+[18, ["setxy2", 0], 660, 216, [15, 19, 20, 21]],
+[19, ["number", 0], 718, 216, [18, null]],
+[20, "toppos", 718, 258, [18, null]],
+[21, "setcolor", 660, 300, [18, 25, 16]],
+[22, "white", 442, 250, [23, null]],
+[23, ["fillscreen", 0], 360, 250, [17, 22, 24, 68]],
+[24, ["number", 80], 442, 292, [23, null]],
+[25, "white", 737, 300, [21, null]],
+[26, "setcolor", 660, 468, [12, 27, null]],
+[27, ["number", 0], 737, 468, [26, null]],
+[28, "setpensize", 360, 376, [68, 29, 1]],
+[29, ["number", 30], 462, 376, [28, null]],
+[30, ["repeat", 166], 920, 426, [36, 31, 37, 47]],
+[31, ["number", 6], 979, 426, [30, null]],
+[32, ["setxy2", 0], 920, 300, [35, 33, 34, 36]],
+[33, ["number", -100], 978, 300, [32, null]],
+[34, ["number", -300], 978, 342, [32, null]],
+[35, "penup", 920, 258, [54, 32]],
+[36, "pendown", 920, 384, [32, 30]],
+[37, "right", 938, 468, [30, 38, 39]],
+[38, ["number", 90], 996, 468, [37, null]],
+[39, "forward", 938, 510, [37, 40, 41]],
+[40, ["number", 20], 1009, 510, [39, null]],
+[41, "back", 938, 552, [39, 42, 43]],
+[42, ["number", 20], 996, 552, [41, null]],
+[43, "left", 938, 594, [41, 44, 48]],
+[44, ["number", 90], 996, 594, [43, null]],
+[45, "forward", 938, 800, [58, 46, null]],
+[46, ["number", 100], 1009, 800, [45, null]],
+[47, "penup", 920, 860, [30, null]],
+[48, "show", 938, 636, [43, 59, 58]],
+[49, "ycor", 1158, 678, [51, null]],
+[50, ["number", 300], 1158, 720, [51, null]],
+[51, ["plus2", 0], 1104, 678, [52, 49, 50]],
+[52, ["product2", 20], 1050, 678, [59, 51, 53]],
+[53, ["number", 10], 1104, 760, [52, null]],
+[54, "setpensize", 920, 216, [56, 55, 35]],
+[55, ["number", 5], 1022, 216, [54, null]],
+[56, "setscale", 920, 174, [67, 57, 54]],
+[57, ["number", 25], 997, 174, [56, null]],
+[58, ["vspace", 40], 938, 678, [48, 45]],
+[59, ["plus2", 0], 996, 636, [48, 63, 52]],
+[60, "setcolor", 396, 494, [9, 61, 2]],
+[61, "green", 473, 494, [60, null]],
+[62, "clean", 360, 166, [0, 17]],
+[63, ["number", 0], 1050, 636, [59, null]],
+[64, ["string", "draw_scale"], 978, 132, [67, null]],
+[65, "hat", 660, 120, [null, 66, 15]],
+[66, ["string", "clean_line"], 718, 132, [65, null]],
+[67, "hat", 920, 120, [null, 64, 56]],
+[68, "stack", 360, 334, [23, 69, 28]],
+[69, ["string", "draw_scale"], 418, 334, [68, null]],
+[70, "stack", 378, 720, [11, 71, null]],
+[71, ["string", "clean_line"], 436, 720, [70, null]],
+[-1, ["turtle", "Yertle"], 0.0, 380.8918666666666, 0.0, 40, 50, 30.0]] \ No newline at end of file
diff --git a/samples/thumbnails/sensors-camera.png b/samples/thumbnails/sensors-camera.png
new file mode 100644
index 0000000..f6d91ba
--- /dev/null
+++ b/samples/thumbnails/sensors-camera.png
Binary files differ