Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt
diff options
context:
space:
mode:
Diffstat (limited to 'TurtleArt')
-rw-r--r--TurtleArt/tablock.py37
-rw-r--r--TurtleArt/taconstants.py2
-rw-r--r--TurtleArt/talogo.py70
-rw-r--r--TurtleArt/tapalette.py2
-rwxr-xr-xTurtleArt/tasprite_factory.py86
-rw-r--r--TurtleArt/tawindow.py22
6 files changed, 171 insertions, 48 deletions
diff --git a/TurtleArt/tablock.py b/TurtleArt/tablock.py
index cd5515e..3b9650f 100644
--- a/TurtleArt/tablock.py
+++ b/TurtleArt/tablock.py
@@ -209,7 +209,7 @@ class Block:
self._visible = True
self.unknown = False # Block is of unknown style
- self.block_methods = {
+ self._block_methods = {
'basic-style': self._make_basic_style,
'blank-style': self._make_blank_style,
'basic-style-head': self._make_basic_style_head,
@@ -241,6 +241,7 @@ class Block:
'clamp-style-collapsed': self._make_clamp_style_collapsed,
'clamp-style-1arg': self._make_clamp_style_1arg,
'clamp-style-boolean': self._make_clamp_style_boolean,
+ 'clamp-style-until': self._make_clamp_style_until,
'clamp-style-else': self._make_clamp_style_else,
'flow-style-tail': self._make_flow_style_tail,
'portfolio-style-2x2': self._make_portfolio_style_2x2,
@@ -679,7 +680,8 @@ class Block:
y = self.docks[1][3] - int(int(self.font_size[0] * 1.3))
self.spr.set_label_attributes(int(self.font_size[0] + 0.5),
True, 'right', y_pos=y, i=0)
- elif self.name in block_styles['clamp-style-boolean']:
+ elif self.name in block_styles['clamp-style-boolean'] or \
+ self.name in block_styles['clamp-style-until']:
y = self.docks[1][3] - int(int(self.font_size[0] * 1.3))
self.spr.set_label_attributes(int(self.font_size[0] + 0.5),
True, 'right', y_pos=y, i=0)
@@ -709,19 +711,18 @@ class Block:
self._right = 0
self._bottom = 0
self.svg.set_stroke_width(STANDARD_STROKE_WIDTH)
- self.svg.clear_docks()
if isinstance(self.name, unicode):
self.name = self.name.encode('utf-8')
for k in block_styles.keys():
if self.name in block_styles[k]:
- if isinstance(self.block_methods[k], list):
- self.block_methods[k][0](svg, self.block_methods[k][1],
- self.block_methods[k][2])
+ if isinstance(self._block_methods[k], list):
+ self._block_methods[k][0](svg, self._block_methods[k][1],
+ self._block_methods[k][2])
else:
- self.block_methods[k](svg)
+ self._block_methods[k](svg)
return
error_output('ERROR: block type not found %s' % (self.name))
- self.block_methods['blank-style'](svg)
+ self._block_methods['blank-style'](svg)
self.unknown = True
def _set_colors(self, svg):
@@ -1086,6 +1087,24 @@ class Block:
['flow', False, self.svg.docks[4][0],
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.set_slot(True)
+ self.svg.set_tab(True)
+ self.svg.set_boolean(True)
+ self.svg.second_clamp(False)
+ self._make_block_graphics(svg, self.svg.clamp_until)
+ # Dock positions are flipped
+ self.docks = [['flow', True, self.svg.docks[0][0],
+ self.svg.docks[0][1]],
+ ['bool', False, self.svg.docks[3][0],
+ self.svg.docks[3][1]],
+ ['flow', False, self.svg.docks[1][0],
+ self.svg.docks[1][1], '['],
+ # Skip bottom of clamp
+ ['flow', False, self.svg.docks[4][0],
+ self.svg.docks[4][1], ']']]
+
def _make_clamp_style_else(self, svg, extend_x=0, extend_y=4):
self.svg.expand(self.dx + self.ex + extend_x, self.ey + extend_y,
self.dx + self.ex + extend_x, self.ey2 + extend_y)
@@ -1194,6 +1213,7 @@ class Block:
def _make_block_graphics(self, svg, function, arg=None):
self._set_colors(svg)
self.svg.set_gradient(True, GRADIENT_COLOR)
+ self.svg.clear_docks()
if arg is None:
pixbuf = svg_str_to_pixbuf(function())
else:
@@ -1203,6 +1223,7 @@ class Block:
self.shapes[0] = _pixbuf_to_cairo_surface(pixbuf,
self.width, self.height)
self.svg.set_gradient(False)
+ self.svg.clear_docks()
if arg is None:
pixbuf = svg_str_to_pixbuf(function())
else:
diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py
index 78cb9e1..75288c1 100644
--- a/TurtleArt/taconstants.py
+++ b/TurtleArt/taconstants.py
@@ -341,6 +341,8 @@ 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]],
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index 67aa32c..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):
@@ -1011,7 +1023,7 @@ class LogoCode:
self.filepath = None
self.dsobject = None
- if os_path_exists(obj.value): # file path
+ if obj.value is not None and os_path_exists(obj.value):
self.filepath = obj.value
elif self.tw.running_sugar: # datastore object
from sugar.datastore import datastore
@@ -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/tapalette.py b/TurtleArt/tapalette.py
index fd8fac7..2cf568a 100644
--- a/TurtleArt/tapalette.py
+++ b/TurtleArt/tapalette.py
@@ -71,6 +71,7 @@ block_styles = {'basic-style': [],
'clamp-style-collapsed': [],
'clamp-style-1arg': [],
'clamp-style-boolean': [],
+ 'clamp-style-until': [],
'clamp-style-else': [],
'portfolio-style-2x2': [],
'portfolio-style-1x1': [],
@@ -289,6 +290,7 @@ class _ProtoBlock():
'clamp-style-collapsible',
'clamp-style-1arg',
'clamp-style-boolean',
+ 'clamp-style-until',
'clamp-style-else']:
EXPANDABLE_FLOW.append(self._name)
diff --git a/TurtleArt/tasprite_factory.py b/TurtleArt/tasprite_factory.py
index 2bd8993..7f9494c 100755
--- a/TurtleArt/tasprite_factory.py
+++ b/TurtleArt/tasprite_factory.py
@@ -609,6 +609,61 @@ stroke-width="3.5" fill="%s" stroke="none" />\n' % (self._stroke)
svg += self.footer()
return self.header() + svg
+ def clamp_until(self):
+ ''' Until block is like clamp but docks are flipped '''
+ self.reset_min_max()
+ x = self._stroke_width / 2.0
+ y = self._stroke_width / 2.0 + self._radius
+ self.margins[0] = int((x + self._stroke_width + 0.5) * self._scale)
+ self.margins[1] = int((self._stroke_width + 0.5) * self._scale)
+ self.margins[2] = 0
+ self.margins[3] = 0
+ svg = self.new_path(x, y)
+ svg += self._corner(1, -1)
+ svg += self._do_slot()
+ svg += self._rline_to(self._radius + self._stroke_width, 0)
+ svg += self._rline_to(self._expand_x, 0)
+ xx = self._x
+ svg += self._corner(1, 1, skip=True)
+ svg += self._corner(-1, 1, skip=True)
+ 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_y)
+ 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)
+ if self._bool is True:
+ svg += self._do_boolean()
+ svg += self._corner(-1, 1)
+ svg += self._rline_to(-self._radius - self._stroke_width, 0)
+ svg += self._do_tab()
+ svg += self._corner(-1, -1)
+ svg += self._close_path()
+ self.calc_w_h()
+ svg += self.style()
+ if self._collapsible:
+ svg += self._hide_dot()
+ svg += self.footer()
+ return self.header() + svg
+
def status_block(self, graphic=None):
''' Generate a status block '''
self.reset_min_max()
@@ -950,7 +1005,8 @@ stroke-width="3.5" fill="%s" stroke="none" />\n' % (self._stroke)
0)
return svg_str
- def _corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, end=True):
+ def _corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, end=True,
+ skip=False):
svg_str = ""
if sign_x == 1 and sign_y == -1: # Upper-left corner
self._hide_x = self._x + self._radius + self._stroke_width
@@ -970,7 +1026,7 @@ stroke-width="3.5" fill="%s" stroke="none" />\n' % (self._stroke)
if start:
if sign_x * sign_y == 1:
svg_str += self._rline_to(sign_x * r2, 0)
- else:
+ elif not skip:
svg_str += self._rline_to(0, sign_y * r2)
x = self._x + sign_x * r2
y = self._y + sign_y * r2
@@ -978,7 +1034,7 @@ stroke-width="3.5" fill="%s" stroke="none" />\n' % (self._stroke)
if end:
if sign_x * sign_y == 1:
svg_str += self._rline_to(0, sign_y * r2)
- else:
+ elif not skip:
svg_str += self._rline_to(sign_x * r2, 0)
return svg_str
@@ -1237,6 +1293,7 @@ def close_file(f):
def generator(datapath):
+ '''
svg = SVG()
f = open_file(datapath, "turtle.svg")
svg.set_scale(2)
@@ -1471,29 +1528,42 @@ def generator(datapath):
close_file(f)
svg = SVG()
- f = open_file(datapath, "clampb.svg")
+ f = open_file(datapath, "clampe.svg")
svg.set_scale(2)
svg.expand(30, 0, 0, 0)
svg.set_slot(True)
svg.set_tab(True)
svg.set_boolean(True)
- svg.second_clamp(False)
+ svg.second_clamp(True)
svg_str = svg.clamp()
f.write(svg_str)
close_file(f)
+ '''
svg = SVG()
- f = open_file(datapath, "clampe.svg")
+ f = open_file(datapath, "clampb.svg")
svg.set_scale(2)
- svg.expand(30, 0, 0, 0)
+ svg.expand(0, 30, 0, 0)
svg.set_slot(True)
svg.set_tab(True)
svg.set_boolean(True)
- svg.second_clamp(True)
+ svg.second_clamp(False)
svg_str = svg.clamp()
f.write(svg_str)
close_file(f)
+ svg = SVG()
+ f = open_file(datapath, "clampu.svg")
+ svg.set_scale(2)
+ svg.expand(0, 30, 0, 0)
+ svg.set_slot(True)
+ svg.set_tab(True)
+ svg.set_boolean(True)
+ svg.second_clamp(False)
+ svg_str = svg.clamp_until()
+ f.write(svg_str)
+ close_file(f)
+
def main():
return 0
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index 2aa8f89..2f0a036 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -2553,8 +2553,9 @@ before making changes to your program'))
if blk is None:
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']:
+ 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']:
if blk.connections[2] is not None:
self._resize_clamp(blk, blk.connections[2])
elif blk.name in block_styles['clamp-style']:
@@ -3391,7 +3392,9 @@ 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']:
+ block_styles['clamp-style-boolean'] or \
+ best_destination.name in \
+ block_styles['clamp-style-until']:
if best_destination_dockn == 2:
self._resize_clamp(best_destination,
self.drag_group[0])
@@ -3492,8 +3495,9 @@ before making changes to your program'))
self._expand_expandable(blk2, blk, dy)
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']:
+ 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']:
if c == 2:
self._resize_clamp(blk2, None, c)
elif blk2.name in block_styles['clamp-style'] or \
@@ -3542,12 +3546,18 @@ before making changes to your program'))
drag_group = find_group(blk.connections[-1])
for gblk in drag_group:
gblk.spr.move_relative((0, y2-y1))
- # We may have to move the else clamp group down too.
+ # We may have to move the else clamp group up or down too.
if blk.name in block_styles['clamp-style-else'] and dockn == 2:
if blk.connections[3] is not None:
drag_group = find_group(blk.connections[3])
for gblk in drag_group:
gblk.spr.move_relative((0, y2 - y1))
+ # We may have to move the bool group up or down too.
+ if blk.name in block_styles['clamp-style-until']:
+ if blk.connections[1] is not None:
+ drag_group = find_group(blk.connections[1])
+ for gblk in drag_group:
+ gblk.spr.move_relative((0, y2 - y1))
def _expandable_flow_above(self, blk):
''' Is there an expandable flow block above this one? '''