diff options
Diffstat (limited to 'TurtleArt')
-rw-r--r-- | TurtleArt/tablock.py | 190 | ||||
-rw-r--r-- | TurtleArt/tacanvas.py | 66 | ||||
-rw-r--r-- | TurtleArt/tajail.py | 4 | ||||
-rw-r--r-- | TurtleArt/talogo.py | 512 | ||||
-rw-r--r-- | TurtleArt/taturtle.py | 21 | ||||
-rw-r--r-- | TurtleArt/tautils.py | 133 | ||||
-rw-r--r-- | TurtleArt/tawindow.py | 276 |
7 files changed, 639 insertions, 563 deletions
diff --git a/TurtleArt/tablock.py b/TurtleArt/tablock.py index de7b18f..db9ef0b 100644 --- a/TurtleArt/tablock.py +++ b/TurtleArt/tablock.py @@ -34,8 +34,8 @@ from taconstants import EXPANDABLE, EXPANDABLE_BLOCKS, EXPANDABLE_ARGS, \ FLOW_STYLE_1ARG, FLOW_STYLE_BOOLEAN, FLOW_STYLE_WHILE, FLOW_STYLE_ELSE, \ COLLAPSIBLE_TOP, COLLAPSIBLE_TOP_NO_ARM, COLLAPSIBLE_TOP_NO_LABEL, \ COLLAPSIBLE_TOP_NO_ARM_NO_LABEL, COLLAPSIBLE_BOTTOM, PORTFOLIO_STYLE_2x2, \ - PORTFOLIO_STYLE_1x1, PORTFOLIO_STYLE_2x1, PORTFOLIO_STYLE_1x2, BOX_COLORS, \ - STANDARD_STROKE_WIDTH, SELECTED_STROKE_WIDTH, SELECTED_COLOR, \ + PORTFOLIO_STYLE_1x1, PORTFOLIO_STYLE_2x1, PORTFOLIO_STYLE_1x2, \ + STANDARD_STROKE_WIDTH, SELECTED_STROKE_WIDTH, SELECTED_COLOR, BOX_COLORS, \ BASIC_STYLE_EXTENDED_VERTICAL from tasprite_factory import SVG, svg_str_to_pixbuf import sprites @@ -43,10 +43,10 @@ import sprites import logging _logger = logging.getLogger('turtleart-activity') -# -# A class for the list of blocks and everything they share in common -# + class Blocks: + """ A class for the list of blocks and everything they share in common """ + def __init__(self, font_scale_factor=1, decimal_point='.'): self.list = [] self.font_scale_factor = font_scale_factor @@ -61,7 +61,7 @@ class Blocks: def length_of_list(self): return(len(self.list)) - def append_to_list(self,block): + def append_to_list(self, block): self.list.append(block) def remove_from_list(self, block): @@ -76,7 +76,7 @@ class Blocks: def set_scale(self, scale): for b in self.list: for i in range(len(b._font_size)): - b._font_size[i] *= b.scale*scale/self.font_scale_factor + b._font_size[i] *= b.scale * scale / self.font_scale_factor self.font_scale_factor = scale def spr_to_block(self, spr): @@ -112,14 +112,13 @@ class Blocks: break i += 1 return None - -# -# A class for the individual blocks -# + class Block: + """ A class for the individual blocks """ + def __init__(self, block_list, sprite_list, name, x, y, type='block', - values=[], scale=BLOCK_SCALE, colors=["#FF0000","#A00000"]): + values=[], scale=BLOCK_SCALE, colors=["#FF0000", "#A00000"]): self.block_list = block_list self.spr = None self.shapes = [None, None] @@ -143,7 +142,8 @@ class Block: self.name = OLD_NAMES[self.name] for i in range(len(self._font_size)): - self._font_size[i] *= self.scale*self.block_list.font_scale_factor + self._font_size[i] *= self.scale * \ + self.block_list.font_scale_factor for v in (values): self.values.append(v) @@ -165,46 +165,45 @@ class Block: self.block_list.append_to_list(self) - # We may want to highlight a block... def highlight(self): + """ We may want to highlight a block... """ if self.spr is not None: self.spr.set_shape(self.shapes[1]) - # Or unhighlight it. def unhighlight(self): + """ Or unhighlight it. """ if self.spr is not None: self.spr.set_shape(self.shapes[0]) - # We need to resize some blocks on the fly so that the labels fit. def resize(self): + """ We need to resize some blocks on the fly so the labels fit. """ if self.spr is None: return - dx = (self.spr.label_width()-self.spr.label_safe_width())/self.scale + dx = (self.spr.label_width() - self.spr.label_safe_width()) / \ + self.scale if dx !=0: self.dx += dx if self.dx < 0: self.dx = 0 self.refresh() - # Some blocks get a skin. def set_image(self, image, x, y): + """ Some blocks get a skin. """ if self.spr is None: return self._image = image self.spr.set_image(image, 1, x, y) - # The skin might need scaling. - # Keep the original here, the scaled version stays with the sprite. def scale_image(self, x, y, w, h): + """ The skin might need scaling. """ if self.spr is None: return if self._image is not None: - tmp = self._image.scale_simple(w, h, - gtk.gdk.INTERP_NEAREST) + tmp = self._image.scale_simple(w, h, gtk.gdk.INTERP_NEAREST) self.spr.set_image(tmp, 1, x, y) - # We may want to rescale blocks as well. def rescale(self, scale): + """ We may want to rescale blocks as well. """ if self.spr is None: return for i in range(len(self._font_size)): @@ -224,8 +223,8 @@ class Block: self._set_margins() self.spr.set_shape(self.shapes[0]) - # We may want to add additional slots for arguments ("innies"). def add_arg(self, keep_expanding=True): + """ We may want to add additional slots for arguments ("innies"). """ if self.spr is None: return h = self.svg.get_height() @@ -235,10 +234,10 @@ class Block: else: self.svg.set_show(False) self.refresh() - return self.svg.get_height()-h + return self.svg.get_height() - h - # We may want to grow a block vertically. def expand_in_y(self, dy): + """ We may want to grow a block vertically. """ if self.spr is None: return self.ey += dy @@ -253,8 +252,8 @@ class Block: self.svg.set_show(False) self.refresh() - # We may want to grow a block horizontally. def expand_in_x(self, dx): + """ We may want to grow a block horizontally. """ if self.spr is None: return self.ex += dx @@ -320,7 +319,7 @@ class Block: self.shapes[0] = copy_block.shapes[0] self.spr = sprites.Sprite(sprite_list, x, y, self.shapes[0]) self.spr._margins = copy_block.spr._margins[:] - if len(copy_block.shapes) > 1: + if len(copy_block.shapes) > 1: self.shapes[1] = copy_block.shapes[1] self.docks = copy_block.docks[:] else: @@ -349,7 +348,7 @@ class Block: elif self.name in BLOCK_NAMES: for i, n in enumerate(BLOCK_NAMES[self.name]): self._set_labels(i, n) - + if copy_block is None: if self.spr.label_width() > self.spr.label_safe_width(): self.resize() @@ -367,14 +366,14 @@ class Block: n = len(BLOCK_NAMES[self.name]) for i in range(n): if i == 1: # top - self.spr.set_label_attributes(int(self._font_size[1]+0.5), True, - "right", "top", i) + self.spr.set_label_attributes(int(self._font_size[1] + 0.5), + True, 'right', 'top', i) elif i == 2: # bottom - self.spr.set_label_attributes(int(self._font_size[1]+0.5), True, - "right", "bottom", i) + self.spr.set_label_attributes(int(self._font_size[1] + 0.5), + True, 'right', 'bottom', i) else: - self.spr.set_label_attributes(int(self._font_size[0]+0.5), True, - "center", "middle", i) + self.spr.set_label_attributes(int(self._font_size[0] + 0.5), + True, 'center', 'middle', i) def _set_labels(self, i, label): self.spr.set_label(label, i) @@ -474,13 +473,14 @@ class Block: self.svg.set_colors(self.colors) def _make_basic_style(self, svg, extend_x=0, extend_y=0): - 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) self._make_block_graphics(svg, self.svg.basic_block) - self.docks = [['flow',True,self.svg.docks[0][0],self.svg.docks[0][1]], - ['flow',False,self.svg.docks[1][0],self.svg.docks[1][1]]] + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], ['flow', + False, self.svg.docks[1][0], self.svg.docks[1][1]]] def _make_basic_style_head(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self.svg.set_slot(False) self.svg.set_cap(True) self._make_block_graphics(svg, self.svg.basic_block) @@ -489,7 +489,7 @@ class Block: self.svg.docks[0][1]]] def _make_basic_style_head_1arg(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self.svg.set_innie([True]) self.svg.set_slot(False) self.svg.set_cap(True) @@ -501,7 +501,7 @@ class Block: self.svg.docks[1][1]]] def _make_basic_style_tail(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self.svg.set_tab(False) self._make_block_graphics(svg, self.svg.basic_block) self.docks = [['flow', True, self.svg.docks[0][0], @@ -509,7 +509,7 @@ class Block: ['unavailable', False, 0, 0]] def _make_basic_style_1arg(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self.svg.set_innie([True]) self._make_block_graphics(svg, self.svg.basic_block) self.docks = [['flow', True, self.svg.docks[0][0], @@ -520,8 +520,8 @@ class Block: self.svg.docks[2][1]]] def _make_basic_style_2arg(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self.svg.set_innie([True,True]) + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) self._make_block_graphics(svg, self.svg.basic_block) self.docks = [['flow', True, self.svg.docks[0][0], self.svg.docks[0][1]], @@ -533,7 +533,7 @@ class Block: self.svg.docks[3][1]]] def _make_basic_style_var_arg(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) innie = [True] for i in range(self._ei): innie.append(True) @@ -544,13 +544,13 @@ class Block: ['number', False, self.svg.docks[1][0], self.svg.docks[1][1]]] for i in range(self._ei): - self.docks.append(['number', False, self.svg.docks[i+2][0], - self.svg.docks[i+2][1]]) - self.docks.append(['flow', False, self.svg.docks[self._ei+2][0], - self.svg.docks[self._ei+2][1]]) + self.docks.append(['number', False, self.svg.docks[i + 2][0], + self.svg.docks[i + 2][1]]) + self.docks.append(['flow', False, self.svg.docks[self._ei + 2][0], + self.svg.docks[self._ei + 2][1]]) def _make_bullet_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) innie = [True, True] for i in range(self._ei): innie.append(True) @@ -563,28 +563,28 @@ class Block: ['string', False, self.svg.docks[2][0], self.svg.docks[2][1]]] for i in range(self._ei): - self.docks.append(['string', False, self.svg.docks[i+3][0], - self.svg.docks[i+3][1]]) - self.docks.append(['flow', False, self.svg.docks[self._ei+3][0], - self.svg.docks[self._ei+3][1], ']']) + self.docks.append(['string', False, self.svg.docks[i + 3][0], + self.svg.docks[i + 3][1]]) + self.docks.append(['flow', False, self.svg.docks[self._ei + 3][0], + self.svg.docks[self._ei + 3][1], ']']) def _make_box_style(self, svg): - self.svg.expand(60+self.dx+self.ex, self.ey) + self.svg.expand(60 + self.dx + self.ex, self.ey) self._make_block_graphics(svg, self.svg.basic_box) self.docks = [['number', True, self.svg.docks[0][0], self.svg.docks[0][1]], ['unavailable', False, 0, 0]] def _make_media_style(self, svg): - self.svg.expand(40+self.dx+self.ex, 10+self.ey) + self.svg.expand(40 + self.dx + self.ex, 10 + self.ey) self._make_block_graphics(svg, self.svg.basic_box) self.docks = [['number', True, self.svg.docks[0][0], self.svg.docks[0][1]], ['unavailable', False, 0, 0]] def _make_number_style(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_innie([True,True]) + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) self.svg.set_outie(True) self.svg.set_tab(False) self.svg.set_slot(False) @@ -598,30 +598,30 @@ class Block: ['number', False, self.svg.docks[0][0], self.svg.docks[0][1]], ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]]] + self.svg.docks[1][1]]] def _make_number_style_var_arg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) innie = [True] - for i in range(self._ei+1): + for i in range(self._ei + 1): innie.append(True) self.svg.set_innie(innie) self.svg.set_outie(True) self.svg.set_tab(False) self.svg.set_slot(False) self._make_block_graphics(svg, self.svg.basic_block) - self.docks = [['number', True, self.svg.docks[2+self._ei][0], - self.svg.docks[2+self._ei][1]], + self.docks = [['number', True, self.svg.docks[2 + self._ei][0], + self.svg.docks[2 + self._ei][1]], ['number', False, self.svg.docks[0][0], self.svg.docks[0][1]]] - for i in range(self._ei+1): - self.docks.append(['number', False, self.svg.docks[i+1][0], - self.svg.docks[i+1][1]]) + for i in range(self._ei + 1): + self.docks.append(['number', False, self.svg.docks[i + 1][0], + self.svg.docks[i + 1][1]]) self.docks.append(['unavailable', False, 0, 0]) def _make_number_style_block(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_innie([True,True]) + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) self.svg.set_outie(True) self.svg.set_tab(False) self.svg.set_slot(False) @@ -635,7 +635,7 @@ class Block: ['unavailable', False, 0, 0, ')']] def _make_number_style_1arg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_innie([True]) self.svg.set_outie(True) self.svg.set_tab(False) @@ -647,7 +647,7 @@ class Block: self.svg.docks[0][1]]] def _make_number_style_1strarg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_innie([True]) self.svg.set_outie(True) self.svg.set_tab(False) @@ -660,8 +660,8 @@ class Block: ['unavailable', False, 0, 0]] def _make_number_style_porch(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_innie([True,True]) + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) self.svg.set_outie(True) self.svg.set_tab(False) self.svg.set_slot(False) @@ -672,10 +672,10 @@ class Block: ['number', False, self.svg.docks[0][0], self.svg.docks[0][1]], ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]]] + self.svg.docks[1][1]]] def _make_compare_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self._make_block_graphics(svg, self.svg.boolean_compare) self.docks = [['bool', True, self.svg.docks[0][0], self.svg.docks[0][1], '('], @@ -686,7 +686,7 @@ class Block: ['unavailable', False, 0, 0, ')']] def _make_boolean_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self._make_block_graphics(svg, self.svg.boolean_and_or) self.docks = [['bool', True, self.svg.docks[0][0], self.svg.docks[0][1]], @@ -694,9 +694,9 @@ class Block: self.svg.docks[1][1]], ['bool', False, self.svg.docks[2][0], self.svg.docks[2][1]]] - + def _make_not_style(self, svg): - self.svg.expand(15+self.dx+self.ex, self.ey) + self.svg.expand(15 + self.dx + self.ex, self.ey) self._make_block_graphics(svg, self.svg.boolean_not) self.docks = [['bool', True, self.svg.docks[0][0], self.svg.docks[0][1]], @@ -704,7 +704,7 @@ class Block: self.svg.docks[1][1]]] def _make_flow_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self.svg.set_slot(True) self.svg.set_tab(True) self._make_block_graphics(svg, self.svg.basic_flow) @@ -716,7 +716,7 @@ class Block: self.svg.docks[2][1], ']']] def _make_flow_style_tail(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) + self.svg.expand(10 + self.dx + self.ex, self.ey) self.svg.set_slot(True) self.svg.set_tab(False) self._make_block_graphics(svg, self.svg.basic_flow) @@ -726,7 +726,7 @@ class Block: self.svg.docks[1][1]]] def _make_flow_style_1arg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_slot(True) self.svg.set_tab(True) self.svg.set_innie([True]) @@ -741,7 +741,7 @@ class Block: self.svg.docks[3][1], ']']] def _make_flow_style_boolean(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_slot(True) self.svg.set_tab(True) self.svg.set_boolean(True) @@ -756,7 +756,7 @@ class Block: self.svg.docks[3][1], ']']] def _make_flow_style_while(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_slot(True) self.svg.set_tab(True) self.svg.set_boolean(True) @@ -771,7 +771,7 @@ class Block: self.svg.docks[3][1], ']']] def _make_flow_style_else(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_slot(True) self.svg.set_tab(True) self.svg.set_else(True) @@ -789,7 +789,7 @@ class Block: self.svg.docks[4][1], ']']] def _make_collapsible_style_top(self, svg, arm=True, label=True): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_arm(arm) self._make_block_graphics(svg, self.svg.sandwich_top, label) if label: @@ -806,17 +806,19 @@ class Block: self.svg.docks[1][1]]] def _make_collapsible_style_bottom(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) + self.svg.expand(self.dx + self.ex, self.ey) self._make_block_graphics(svg, self.svg.sandwich_bottom) - self.docks = [['flow',True,self.svg.docks[0][0],self.svg.docks[0][1]], - ['flow',False,self.svg.docks[1][0],self.svg.docks[1][1]]] + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], ['flow', False, + self.svg.docks[1][0], self.svg.docks[1][1]]] # Depreciated block styles + def _make_portfolio_style_2x2(self, svg): - self.svg.expand(30+self.dx+self.ex, 10+self.ey) + self.svg.expand(30 + self.dx + self.ex, 10 + self.ey) self.svg.set_slot(True) self.svg.set_tab(True) - self.svg.set_innie([True, True, False, True]) + self.svg.set_innie([True, True, False, True]) self._make_block_graphics(svg, self.svg.portfolio) self.docks = [['flow', True, self.svg.docks[0][0], self.svg.docks[0][1]], @@ -834,10 +836,10 @@ class Block: self.svg.docks[3][1]]] def _make_portfolio_style_2x1(self, svg): - self.svg.expand(30+self.dx+self.ex, 10+self.ey) + self.svg.expand(30 + self.dx + self.ex, 10 + self.ey) self.svg.set_slot(True) self.svg.set_tab(True) - self.svg.set_innie([True, True]) + self.svg.set_innie([True, True]) self._make_block_graphics(svg, self.svg.portfolio) self.docks = [['flow', True, self.svg.docks[0][0], self.svg.docks[0][1]], @@ -851,7 +853,7 @@ class Block: self.svg.docks[2][1]]] def _make_portfolio_style_1x2(self, svg): - self.svg.expand(30+self.dx+self.ex, 15+self.ey) + self.svg.expand(30 + self.dx + self.ex, 15 + self.ey) self.svg.set_slot(True) self.svg.set_tab(True) self.svg.set_innie([True, True, False, True]) @@ -869,10 +871,10 @@ class Block: self.svg.docks[1][1]]] def _make_portfolio_style_1x1(self, svg): - self.svg.expand(30+self.dx+self.ex, 15+self.ey) + self.svg.expand(30 + self.dx + self.ex, 15 + self.ey) self.svg.set_slot(True) self.svg.set_tab(True) - self.svg.set_innie([True, True]) + self.svg.set_innie([True, True]) self.svg.set_draw_innies(False) self._make_block_graphics(svg, self.svg.portfolio) self.docks = [['flow', True, self.svg.docks[0][0], diff --git a/TurtleArt/tacanvas.py b/TurtleArt/tacanvas.py index d930f62..2083ab8 100644 --- a/TurtleArt/tacanvas.py +++ b/TurtleArt/tacanvas.py @@ -102,7 +102,8 @@ class TurtleGraphics: self.height = height if self.tw.interactive_mode: self.canvas = Sprite(tw.sprite_list, 0, 0, - gtk.gdk.Pixmap(self.tw.area, self.width * 2, self.height * 2, -1)) + gtk.gdk.Pixmap(self.tw.area, self.width * 2, + self.height * 2, -1)) else: self.canvas = Sprite(None, 0, 0, self.tw.window) self.canvas.set_layer(CANVAS_LAYER) @@ -217,8 +218,7 @@ class TurtleGraphics: self.tw.svg_string += self.svg.style() if self.tw.sharing() and share: self.tw.activity.send_event("f|%s" % \ - (data_to_string([self.tw.nick, - int(n)]))) + (data_to_string([self.tw.nick, int(n)]))) def seth(self, n, share=True): """ Set the turtle heading. """ @@ -292,8 +292,7 @@ class TurtleGraphics: self.tw.svg_string += self.svg.new_path(oldx, self.height / 2 - oldy) self.tw.svg_string += self.svg.arc_to(self.xcor, - self.height / 2 - self.ycor, - r, a, 0, s) + self.height / 2 - self.ycor, r, a, 0, s) self.tw.svg_string += "\"\n" self.tw.svg_string += self.svg.style() @@ -308,8 +307,8 @@ class TurtleGraphics: oldx, oldy = self.xcor, self.ycor 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) + x = self.width / 2 + int(cx - r) + y = self.height / 2 - int(cy + r) w = int(2 * r) h = w if self.pendown: @@ -324,9 +323,10 @@ class TurtleGraphics: 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.new_path(oldx, + self.height / 2 - oldy) self.tw.svg_string += self.svg.arc_to(self.xcor, - self.height / 2-self.ycor, + self.height / 2 - self.ycor, r, a, 0, s) self.tw.svg_string += "\"\n" self.tw.svg_string += self.svg.style() @@ -361,7 +361,7 @@ class TurtleGraphics: _logger.debug("bad value sent to %s" % (__name__)) return self.tw.active_turtle.set_pen_size(ps) - self.gc.set_line_attributes(int(self.pensize*self.tw.coord_scale), + self.gc.set_line_attributes(int(self.pensize * self.tw.coord_scale), gtk.gdk.LINE_SOLID, gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_MITER) self.svg.set_stroke_width(self.pensize) if self.tw.sharing() and share: @@ -502,9 +502,7 @@ class TurtleGraphics: if self.tw.running_sugar: # In Sugar, we need to embed the images inside the SVG self.tw.svg_string += self.svg.image(x - self.width / 2, - y, w, h, path, - image_to_base64(pixbuf, - self.tw.activity)) + y, w, h, path, image_to_base64(pixbuf, self.tw.activity)) else: self.tw.svg_string += self.svg.image(x - self.width / 2, y, w, h, path) @@ -521,8 +519,8 @@ class TurtleGraphics: return if self.tw.interactive_mode: if type(label) == str or type(label) == unicode: - pl = self.tw.window.create_pango_layout(label.replace("\0", - " ")) + 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: @@ -533,7 +531,7 @@ class TurtleGraphics: w, h = pl.get_pixel_size() self.invalt(x, y, w, h) else: # pixmap doesn't support pango - message = str(label).replace("\0"," ") + message = str(label).replace('\0', ' ') context = self.canvas.images[0].cairo_create() context.set_font_size(size) q, k, w, h = context.text_extents(message)[:4] @@ -543,8 +541,7 @@ class TurtleGraphics: if self.tw.saving_svg and self.pendown: self.tw.svg_string += self.svg.text(x - self.width / 2, - y + size, - size, w, label) + y + size, size, w, label) def draw_line(self, x1, y1, x2, y2): """ Draw a line """ @@ -575,19 +572,18 @@ class TurtleGraphics: def move_turtle(self): """ Move the turtle """ - x, y = self.width / 2 + int(self.xcor), self.height / 2 - int(self.ycor) - self.tw.active_turtle.move((self.cx + x - \ - self.tw.active_turtle.spr.rect.width/2, - self.cy + y - \ - self.tw.active_turtle.spr.rect.height/2,)) + x, y = self.width / 2 + int(self.xcor), \ + self.height / 2 - int(self.ycor) + self.tw.active_turtle.move( + (self.cx + x - self.tw.active_turtle.spr.rect.width/2, + self.cy + y - self.tw.active_turtle.spr.rect.height/2)) def invalt(self, x, y, w, h): """ Mark a region for refresh """ if self.tw.interactive_mode: - self.tw.area.invalidate_rect(gtk.gdk.Rectangle(int(x + self.cx), - int(y + self.cy), - int(w), int(h)), - False) + self.tw.area.invalidate_rect( + gtk.gdk.Rectangle(int(x + self.cx), int(y + self.cy), + int(w), int(h)), False) def get_color_index(self, r, g, b, a=0): """ Find the closest palette entry to the rgb triplet """ @@ -613,8 +609,8 @@ class TurtleGraphics: cr = int((c & 0xff0000) >> 16) cg = int((c & 0x00ff00) >> 8) cb = int((c & 0x0000ff)) - distance_squared = ((cr - r) ** 2) + ((cg - g) ** 2) + \ - ((cb - b) ** 2) + distance_squared = \ + ((cr - r) ** 2) + ((cg - g) ** 2) + ((cb - b) ** 2) if distance_squared == 0: return i if distance_squared < min_distance: @@ -625,9 +621,9 @@ class TurtleGraphics: def get_pixel(self): """ Read the pixel at x, y """ if self.tw.interactive_mode: - return self.canvas.get_pixel((self.width / 2 + int(self.xcor), - self.height / 2 - int(self.ycor)), - 0, self.tw.color_mode) + return self.canvas.get_pixel( + (self.width / 2 + int(self.xcor), + self.height / 2 - int(self.ycor)), 0, self.tw.color_mode) else: return(-1, -1, -1, -1) @@ -643,9 +639,9 @@ class TurtleGraphics: self.tw.active_turtle.show() tx, ty = self.tw.active_turtle.get_xy() self.xcor = -self.width / 2 + tx + \ - self.tw.active_turtle.spr.rect.width/2 + self.tw.active_turtle.spr.rect.width / 2 self.ycor = self.height / 2 - ty - \ - self.tw.active_turtle.spr.rect.height/2 + self.tw.active_turtle.spr.rect.height / 2 self.heading = self.tw.active_turtle.get_heading() self.setcolor(self.tw.active_turtle.get_color(), False) self.setgray(self.tw.active_turtle.get_gray(), False) @@ -659,6 +655,6 @@ class TurtleGraphics: return self.svg.calc_w_h(False) self.tw.svg_string = "%s%s%s%s" % (self.svg.header(True), - self.svg.background("#%02x%02x%02x" %\ + self.svg.background("#%02x%02x%02x" % \ (self.bgrgb[0], self.bgrgb[1], self.bgrgb[2])), self.tw.svg_string, self.svg.footer()) diff --git a/TurtleArt/tajail.py b/TurtleArt/tajail.py index bacbb82..6d6c293 100644 --- a/TurtleArt/tajail.py +++ b/TurtleArt/tajail.py @@ -37,12 +37,12 @@ def myfunc(f, args): myf = "def f(x,y): return " + f.replace("import","") userdefined = {} exec myf in globals(), userdefined - return userdefined.values()[0](args[0],args[1]) + return userdefined.values()[0](args[0], args[1]) elif len(args) == 3: myf = "def f(x,y,z): return " + f.replace("import","") userdefined = {} exec myf in globals(), userdefined - return userdefined.values()[0](args[0],args[1],args[2]) + return userdefined.values()[0](args[0], args[1], args[2]) def myfunc_import(lc, f, x): diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py index 0801d75..0d467ac 100644 --- a/TurtleArt/talogo.py +++ b/TurtleArt/talogo.py @@ -47,9 +47,12 @@ _logger = logging.getLogger('turtleart-activity') class noKeyError(UserDict): + __missing__ = lambda x, y: 0 + class symbol: + def __init__(self, name): self.name = name self.nargs = None @@ -57,17 +60,22 @@ class symbol: def __str__(self): return self.name + def __repr__(self): return '#' + self.name + class logoerror(Exception): + def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) # Utility functions + def numtype(x): """ Is x a number type? """ if type(x) == int: @@ -78,9 +86,10 @@ def numtype(x): return True return False + def str_to_num(x): """ Try to comvert a string to a number """ - xx = convert(x.replace(self.tw.decimal_point,'.'), float) + xx = convert(x.replace(self.tw.decimal_point, '.'), float) if type(xx) is float: return xx else: @@ -90,18 +99,21 @@ def str_to_num(x): else: raise logoerror("#syntaxerror") + def taand(x, y): """ Logical and """ - return x&y + return x & y + def taor(x, y): """ Logical or """ - return x|y + return x | y + def careful_divide(x, y): """ Raise error on divide by zero """ try: - return x/y + return x / y except ZeroDivisionError: raise logoerror("#zerodivide") except TypeError: @@ -114,10 +126,11 @@ def careful_divide(x, y): except TypeError: raise logoerror("#notanumber") + def taequal(x, y): """ Numeric and logical equal """ try: - return float(x)==float(y) + return float(x) == float(y) except TypeError: typex, typey = False, False if strtype(x): @@ -131,10 +144,11 @@ def taequal(x, y): except ValueError: raise logoerror("#syntaxerror") + def taless(x, y): """ Compare numbers and strings """ try: - return float(x)<float(y) + return float(x) < float(y) except ValueError: typex, typey = False, False if strtype(x): @@ -148,14 +162,16 @@ def taless(x, y): except TypeError: raise logoerror("#notanumber") + 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) + return(x + y) else: if numtype(x): xx = str(round_int(x)) @@ -165,42 +181,46 @@ def taplus(x, y): yy = str(round_int(y)) else: yy = str(y) - return(xx+yy) - + return(xx + yy) + + def taminus(x, y): """ Numerical subtraction """ if numtype(x) and numtype(y): - return(x-y) + return(x - y) try: return str_to_num(x) - str_to_num(y) except TypeError: raise logoerror("#notanumber") - + + def taproduct(x, y): """ Numerical multiplication """ if numtype(x) and numtype(y): - return(x*y) + return(x * y) try: return str_to_num(x) * str_to_num(y) except TypeError: raise logoerror("#notanumber") + def tamod(x, y): """ Numerical mod """ if numtype(x) and numtype(y): - return(x%y) + return(x % y) try: return str_to_num(x) % str_to_num(y) except TypeError: raise logoerror("#notanumber") except ValueError: raise logoerror("#syntaxerror") - + + def tasqrt(x): """ Square root """ if numtype(x): if x < 0: - raise logoerror("#negroot") + raise logoerror("#negroot") return sqrt(x) try: return sqrt(str_to_num(x)) @@ -209,190 +229,199 @@ def tasqrt(x): except TypeError: raise logoerror("#notanumber") + def tarandom(x, y): """ Random integer """ if numtype(x) and numtype(y): - return(int(round(uniform(x, y),0))) + return(int(round(uniform(x, y), 0))) xx, xflag = chr_to_ord(x) yy, yflag = chr_to_ord(y) if xflag and yflag: - return chr(int(round(uniform(xx, yy),0))) + return chr(int(round(uniform(xx, yy), 0))) if not xflag: xx = str_to_num(x) if not yflag: yy = str_to_num(y) try: - return(int(round(uniform(xx, yy),0))) + return(int(round(uniform(xx, yy), 0))) except TypeError: raise logoerror("#notanumber") + def identity(x): """ Identity function """ return(x) - + + 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.active_turtle.show() + def just_stop(): """ yield False to stop stack """ yield False + def millis(): """ Current time in milliseconds """ - return int(clock()*1000) + return int(clock() * 1000) -""" -A class for parsing Logo Code -""" class LogoCode: + """ A class for parsing Logo code """ + def __init__(self, tw): self.tw = tw self.oblist = {} DEFPRIM = { - '(':[1, lambda self, x: self.prim_opar(x)], - '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)], - 'black':[0, lambda self: BLACK], - '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)], - 'box2':[0, lambda self: self.boxes['box2']], - 'bullet':[1, self.prim_bullet, True], - 'bulletlist':[1, self.prim_list, True], - 'cartesian':[0, lambda self: self.tw.set_cartesian(True)], - 'clean':[0, lambda self: self.prim_clear()], - 'clearheap':[0, lambda self: self.empty_heap()], - 'color':[0, lambda self: self.tw.canvas.color], - 'gray':[0, lambda self: self.tw.canvas.gray], - '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)], - '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)], - '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)], - 'if':[2, self.prim_if, True], - 'ifelse':[3, self.prim_ifelse, True], - '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)], - '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])], - '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], - 'orange':[0, lambda self: 10], - '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)], - '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)], - 'printheap':[0, lambda self: self.prim_print_heap()], - '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)], - 'readpixel':[0, lambda self: self.read_pixel()], - 'red':[0, lambda self: 0], - 'repeat':[2, self.prim_repeat, True], - 'right':[1, lambda self, x: self.tw.canvas.right(x)], - 'rightx':[0, lambda self: self.tw.rightx], - 'rpos':[0, lambda self: self.tw.canvas.width/(self.tw.coord_scale*2)], - 'savepix':[1, lambda self, x: self.save_picture(x)], - 'savesvg':[1, lambda self, x: self.save_svg(x)], - 'scale':[0, lambda self: self.scale], - 'see':[0, lambda self: self.see()], - 'setcolor':[1, lambda self, x: self.tw.canvas.setcolor(x)], - 'setgray':[1, lambda self, x: self.tw.canvas.setgray(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)], - '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)], - 'setxy2':[2, lambda self, x, y: self.tw.canvas.setxy(x, y)], - 'setxy':[2, lambda self, x, y: self.tw.canvas.setxy(x, y, + '(': [1, lambda self, x: self.prim_opar(x)], + '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)], + 'black': [0, lambda self: BLACK], + '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)], + 'box2': [0, lambda self: self.boxes['box2']], + 'bullet': [1, self.prim_bullet, True], + 'bulletlist': [1, self.prim_list, True], + 'cartesian': [0, lambda self: self.tw.set_cartesian(True)], + 'clean': [0, lambda self: self.prim_clear()], + 'clearheap': [0, lambda self: self.empty_heap()], + 'color': [0, lambda self: self.tw.canvas.color], + 'gray': [0, lambda self: self.tw.canvas.gray], + '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)], + '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)], + '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)], + 'if': [2, self.prim_if, True], + 'ifelse': [3, self.prim_ifelse, True], + '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)], + '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])], + '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], + 'orange': [0, lambda self: 10], + '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)], + '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)], + 'printheap': [0, lambda self: self.prim_print_heap()], + '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)], + 'readpixel': [0, lambda self: self.read_pixel()], + 'red': [0, lambda self: 0], + 'repeat': [2, self.prim_repeat, True], + 'right': [1, lambda self, x: self.tw.canvas.right(x)], + 'rightx': [0, lambda self: self.tw.rightx], + 'rpos': [0, lambda self: self.tw.canvas.width / \ + (self.tw.coord_scale * 2)], + 'savepix': [1, lambda self, x: self.save_picture(x)], + 'savesvg': [1, lambda self, x: self.save_svg(x)], + 'scale': [0, lambda self: self.scale], + 'see': [0, lambda self: self.see()], + 'setcolor': [1, lambda self, x: self.tw.canvas.setcolor(x)], + 'setgray': [1, lambda self, x: self.tw.canvas.setgray(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)], + '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)], + 'setxy2': [2, lambda self, x, y: self.tw.canvas.setxy(x, y)], + 'setxy': [2, lambda self, x, y: self.tw.canvas.setxy(x, y, pendown=False)], - 'shade':[0, lambda self: self.tw.canvas.shade], - '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()], - 'skin':[1, lambda self, x: self.reskin(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()], - 'startfill':[0, lambda self: self.tw.canvas.start_fill()], - 'stopfill':[0, lambda self: self.tw.canvas.stop_fill()], - '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( + 'shade': [0, lambda self: self.tw.canvas.shade], + '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()], + 'skin': [1, lambda self, x: self.reskin(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()], + 'startfill': [0, lambda self: self.tw.canvas.start_fill()], + 'stopfill': [0, lambda self: self.tw.canvas.stop_fill()], + '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)], - 'textcolor':[0, lambda self: self.tw.canvas.textcolor], - 'textsize':[0, lambda self: self.tw.textsize], - 'titlex':[0, lambda self: self.tw.titlex], - 'titley':[0, lambda self: self.tw.titley], - '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)], - 'vres':[0, lambda self: self.tw.canvas.height/self.tw.coord_scale], - 'wait':[1, self.prim_wait, True], - # 'while':[2, self.prim_while, True], - 'white':[0, lambda self: WHITE], - '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]} + 'textcolor': [0, lambda self: self.tw.canvas.textcolor], + 'textsize': [0, lambda self: self.tw.textsize], + 'titlex': [0, lambda self: self.tw.titlex], + 'titley': [0, lambda self: self.tw.titley], + '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)], + 'vres': [0, lambda self: self.tw.canvas.height / self.tw.coord_scale], + 'wait': [1, self.prim_wait, True], + # 'while': [2, self.prim_while, True], + 'white': [0, lambda self: WHITE], + '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]} for p in iter(DEFPRIM): if len(DEFPRIM[p]) == 2: self.defprim(p, DEFPRIM[p][0], DEFPRIM[p][1]) else: self.defprim(p, DEFPRIM[p][0], DEFPRIM[p][1], DEFPRIM[p][2]) - + self.symtype = type(self.intern('print')) self.listtype = type([]) self.symnothing = self.intern('%nothing%') @@ -419,17 +448,17 @@ class LogoCode: self.filepath = None # Scale factors for depreciated portfolio blocks - self.title_height = int((self.tw.canvas.height/20)*self.tw.scale) - self.body_height = int((self.tw.canvas.height/40)*self.tw.scale) - self.bullet_height = int((self.tw.canvas.height/30)*self.tw.scale) - + self.title_height = int((self.tw.canvas.height / 20) * self.tw.scale) + self.body_height = int((self.tw.canvas.height / 40) * self.tw.scale) + self.bullet_height = int((self.tw.canvas.height / 30) * self.tw.scale) + self.scale = DEFAULT_SCALE 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 + sym.rprim = rprim def intern(self, string): """ Add any new objects to the symbol list. """ @@ -438,7 +467,7 @@ class LogoCode: sym = symbol(string) self.oblist[string] = sym return sym - + def run_blocks(self, blk, blocks, run_flag): """ Given a block to run... """ for k in self.stacks.keys(): @@ -462,7 +491,7 @@ class LogoCode: if type(convert(x, float, False)) == float: if int(float(x)) == x: x = int(x) - self.stacks['stack3'+str(x)] = self.readline(code) + self.stacks['stack3' + str(x)] = self.readline(code) code = self.blocks_to_code(blk) if run_flag: @@ -479,13 +508,13 @@ class LogoCode: return ['%nothing%', '%nothing%'] code = [] dock = blk.docks[0] - if len(dock)>4: # There could be a '(', ')', '[' or ']'. + if len(dock) > 4: # There could be a '(', ')', '[' or ']'. code.append(dock[4]) if blk.name == 'savesvg': self.tw.saving_svg = True 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. + elif len(blk.values) > 0: # Extract the value from content blocks. if blk.name == 'number': try: code.append(float(blk.values[0])) @@ -495,22 +524,22 @@ class LogoCode: 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])) + code.append('#s' + str(blk.values[0])) else: - code.append('#s'+blk.values[0]) + code.append('#s' + blk.values[0]) elif blk.name == 'journal': if blk.values[0] is not None: - code.append('#smedia_'+str(blk.values[0])) + code.append('#smedia_' + str(blk.values[0])) else: code.append('#smedia_None') elif blk.name == 'description': if blk.values[0] is not None: - code.append('#sdescr_'+str(blk.values[0])) + code.append('#sdescr_' + str(blk.values[0])) else: code.append('#sdescr_None') elif blk.name == 'audio': if blk.values[0] is not None: - code.append('#saudio_'+str(blk.values[0])) + code.append('#saudio_' + str(blk.values[0])) else: code.append('#saudio_None') else: @@ -519,9 +548,9 @@ class LogoCode: return ['%nothing%'] if blk.connections is not None and len(blk.connections) > 0: for i in range(1, len(blk.connections)): - b = blk.connections[i] + b = blk.connections[i] dock = blk.docks[i] - if len(dock)>4: # There could be a '(', ')', '[' or ']'. + if len(dock) > 4: # There could be a '(', ')', '[' or ']'. for c in dock[4]: code.append(c) if b is not None: @@ -529,7 +558,7 @@ class LogoCode: elif blk.docks[i][0] not in ['flow', 'unavailable']: code.append('%nothing%') return code - + def setup_cmd(self, string): """ Execute the psuedocode. """ self.hidden_turtle = self.tw.active_turtle @@ -538,12 +567,12 @@ class LogoCode: blklist = self.readline(string) self.step = self.start_eval(blklist) - """ - Convert the pseudocode into a list of commands. + def readline(self, line): + """ + Convert the pseudocode into a list of commands. The block associated with the command is stored as the second element in a tuple, e.g., (#forward, 16) - """ - def readline(self, line): + """ res = [] while line: token = line.pop(0) @@ -609,8 +638,8 @@ class LogoCode: # In debugging modes, we pause between steps and show the turtle. if self.tw.step_time > 0: self.tw.active_turtle.show() - endtime = millis()+self.an_int(self.tw.step_time)*100 - while millis()<endtime: + endtime = millis() + self.an_int(self.tw.step_time) * 100 + while millis() < endtime: yield True self.tw.active_turtle.hide() @@ -641,7 +670,7 @@ class LogoCode: if not self.tw.hide and self.tw.step_time > 0: self.tw.display_coordinates() yield True - + def eval(self): """ Evaluate the next token on the line of code we are processing. """ token = self.iline.pop(0) @@ -706,12 +735,12 @@ class LogoCode: """ ufuncall """ self.ijmp(self.evline, body) yield True - + def doevalstep(self): """ evaluate one step """ starttime = millis() try: - while (millis()-starttime)<120: + while (millis() - starttime)<120: try: if self.step is not None: self.step.next() @@ -764,7 +793,7 @@ class LogoCode: my_string += "%s: %s\n" % (k, str(v)) self.tw.showlabel('info', my_string) return - + def undefined_check(self, token): """ Make sure token has a definition """ if token.fcn is not None: @@ -774,13 +803,13 @@ class LogoCode: else: errormsg = "%s %s" % (_("I don't know how to"), _(token.name)) 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") - + # # Primitives # @@ -802,13 +831,13 @@ class LogoCode: def prim_wait(self, time): """ Show the turtle while we wait """ self.tw.active_turtle.show() - endtime = millis()+self.an_int(time*1000) + endtime = millis() + self.an_int(time * 1000) while millis()<endtime: yield True self.tw.active_turtle.hide() self.ireturn() yield True - + def prim_repeat(self, num, blklist): """ Repeat list num times. """ num = self.an_int(num) @@ -910,7 +939,7 @@ class LogoCode: 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)) == float: @@ -934,7 +963,7 @@ class LogoCode: self.procstop = False self.ireturn() yield True - + def prim_stack2(self): """ Process Stack 2 """ if self.stacks['stack2'] is None: @@ -948,7 +977,7 @@ class LogoCode: 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) @@ -963,7 +992,7 @@ class LogoCode: return int(ord(n[0])) else: raise logoerror("%s %s %s %s" \ - % (self.cfun.name, _("doesn't like"), str(n), _("as input"))) + % (self.cfun.name, _("doesn't like"), str(n), _("as input"))) def box(self, x): """ Retrieve value from named box """ @@ -971,10 +1000,10 @@ class LogoCode: if int(float(x)) == x: x = int(x) try: - return self.boxes['box3'+str(x)] + return self.boxes['box3' + str(x)] except: raise logoerror("#emptybox") - + def prim_myblock(self, x): """ Run Python code imported from Journal """ if self.tw.myblock is not None: @@ -988,7 +1017,7 @@ class LogoCode: else: raise logoerror("#nocode") return - + def prim_print(self, n, flag): """ Print n """ if flag and (self.tw.hide or self.tw.step_time == 0): @@ -1011,7 +1040,7 @@ class LogoCode: else: self.tw.showlabel('status', str(round_int(n)).replace('.', self.tw.decimal_point)) - + def prim_kbinput(self): """ Query keyboard """ if len(self.tw.keypress) == 1: @@ -1021,7 +1050,7 @@ class LogoCode: self.keyboard = {'Escape': 27, 'space': 32, ' ': 32, 'Return': 13, \ 'KP_Up': 2, 'KP_Down': 4, 'KP_Left': 1, \ - 'KP_Right': 3,}[self.tw.keypress] + 'KP_Right': 3}[self.tw.keypress] except: self.keyboard = 0 self.tw.keypress = "" @@ -1034,7 +1063,7 @@ class LogoCode: if type(convert(x, float, False)) == 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 """ @@ -1045,7 +1074,7 @@ class LogoCode: try: return self.heap.pop(-1) except: - raise logoerror ("#emptyheap") + raise logoerror("#emptyheap") def empty_heap(self): """ Empty FILO """ @@ -1115,27 +1144,27 @@ class LogoCode: int(self.tw.canvas.textsize * \ self.scale / 100.), self.tw.canvas.width - x) - + def insert_image(self, media, center): """ Image only (at current x, y) """ w = int((self.tw.canvas.width * self.scale) / 100.) h = int((self.tw.canvas.height * self.scale) / 100.) # 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) + x = self.tw.canvas.width / 2 + int(self.tw.canvas.xcor) + y = self.tw.canvas.height / 2 - int(self.tw.canvas.ycor) if center: x -= int(w / 2.) y -= int(h / 2.) if media[0:5] == 'media': self.show_picture(media, x, y, w, h) - + def insert_desc(self, media): """ Description text only (at current x, y) """ w = int((self.tw.canvas.width * self.scale) / 100.) h = int((self.tw.canvas.height * self.scale) / 100.) # 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) + x = self.tw.canvas.width / 2 + int(self.tw.canvas.xcor) + y = self.tw.canvas.height / 2 - int(self.tw.canvas.ycor) if media[0:5] == 'descr': self.show_description(media, x, y, w, h) @@ -1181,7 +1210,7 @@ class LogoCode: media[6:], int(w), int(h)) except: self.filepath = None - self.tw.showlabel('nojournal', media[6:]) + self.tw.showlabel('nojournal', media[6:]) _logger.debug("Couldn't open Journal object %s" % \ (media[6:])) else: @@ -1195,8 +1224,9 @@ class LogoCode: media[6:], int(w), int(h)) except: self.filepath = None - self.tw.showlabel('nofile', media[6:]) - _logger.debug("Couldn't open media object %s" % (media[6:])) + self.tw.showlabel('nofile', media[6:]) + _logger.debug("Couldn't open media object %s" % \ + (media[6:])) if pixbuf is not None and show: self.tw.canvas.draw_pixbuf(pixbuf, 0, 0, int(x), int(y), int(w), int(h), @@ -1253,13 +1283,13 @@ class LogoCode: """ slide title """ self.tw.canvas.draw_text(title, int(x), int(y), self.title_height, - self.tw.canvas.width-x) + self.tw.canvas.width - x) def show_template1x1(self, title, media): """ 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 + x = -(self.tw.canvas.width / 2) + xo + y = self.tw.canvas.height / 2 self.tw.canvas.setxy(x, y, pendown=False) # save the text size so we can restore it later save_text_size = self.tw.canvas.textsize @@ -1267,28 +1297,28 @@ class LogoCode: self.tw.canvas.settextsize(self.title_height) self.show(title) # calculate and set scale for media blocks - myscale = 45 * (self.tw.canvas.height - self.title_height*2) \ + myscale = 45 * (self.tw.canvas.height - self.title_height * 2) \ / self.tw.canvas.height self.set_scale(myscale) # set body text size self.tw.canvas.settextsize(self.body_height) # render media object # leave some space below the title - y -= int(self.title_height*2*self.tw.lead) + y -= int(self.title_height * 2 * self.tw.lead) self.tw.canvas.setxy(x, y, pendown=False) self.show(media) if self.tw.running_sugar: x = 0 self.tw.canvas.setxy(x, y, pendown=False) - self.show(media.replace("media_","descr_")) + self.show(media.replace('media_', 'descr_')) # restore text size self.tw.canvas.settextsize(save_text_size) def show_template2x1(self, title, media1, media2): """ 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 + x = -(self.tw.canvas.width / 2) + xo + y = self.tw.canvas.height / 2 self.tw.canvas.setxy(x, y, pendown=False) # save the text size so we can restore it later save_text_size = self.tw.canvas.textsize @@ -1296,14 +1326,14 @@ class LogoCode: self.tw.canvas.settextsize(self.title_height) self.show(title) # calculate and set scale for media blocks - myscale = 45 * (self.tw.canvas.height - self.title_height*2)/\ + myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \ self.tw.canvas.height self.set_scale(myscale) # set body text size self.tw.canvas.settextsize(self.body_height) # render four quadrents # leave some space below the title - y -= int(self.title_height*2*self.tw.lead) + y -= int(self.title_height * 2 * self.tw.lead) self.tw.canvas.setxy(x, y, pendown=False) self.show(media1) x = 0 @@ -1312,18 +1342,18 @@ class LogoCode: y = -self.title_height if self.tw.running_sugar: self.tw.canvas.setxy(x, y, pendown=False) - self.show(media2.replace("media_","descr_")) - x = -(self.tw.canvas.width/2) + xo + self.show(media2.replace('media_', 'descr_')) + x = -(self.tw.canvas.width / 2) + xo self.tw.canvas.setxy(x, y, pendown=False) - self.show(media1.replace("media_","descr_")) + self.show(media1.replace('media_', 'descr_')) # restore text size self.tw.canvas.settextsize(save_text_size) def show_bullets(self, sarray): """ 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 + x = -(self.tw.canvas.width / 2) + xo + y = self.tw.canvas.height / 2 self.tw.canvas.setxy(x, y, pendown=False) # save the text size so we can restore it later save_text_size = self.tw.canvas.textsize @@ -1333,19 +1363,19 @@ class LogoCode: # set body text size self.tw.canvas.settextsize(self.bullet_height) # leave some space below the title - y -= int(self.title_height*2*self.tw.lead) + y -= int(self.title_height * 2 * self.tw.lead) for s in sarray[1:]: self.tw.canvas.setxy(x, y, pendown=False) self.show(s) - y -= int(self.bullet_height*2*self.tw.lead) + y -= int(self.bullet_height * 2 * self.tw.lead) # restore text size self.tw.canvas.settextsize(save_text_size) - + def show_template1x2(self, title, media1, media2): """ 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 + x = -(self.tw.canvas.width / 2) + xo + y = self.tw.canvas.height / 2 self.tw.canvas.setxy(x, y, pendown=False) # save the text size so we can restore it later save_text_size = self.tw.canvas.textsize @@ -1353,24 +1383,24 @@ class LogoCode: self.tw.canvas.settextsize(self.title_height) self.show(title) # calculate and set scale for media blocks - myscale = 45 * (self.tw.canvas.height - self.title_height*2)/\ + myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \ self.tw.canvas.height self.set_scale(myscale) # set body text size self.tw.canvas.settextsize(self.body_height) # render four quadrents # leave some space below the title - y -= int(self.title_height*2*self.tw.lead) + y -= int(self.title_height * 2 * self.tw.lead) self.tw.canvas.setxy(x, y, pendown=False) self.show(media1) if self.tw.running_sugar: x = 0 self.tw.canvas.setxy(x, y, pendown=False) - self.show(media1.replace("media_","descr_")) + self.show(media1.replace('media_', 'descr_')) y = -self.title_height self.tw.canvas.setxy(x, y, pendown=False) - self.show(media2.replace("media_","descr_")) - x = -(self.tw.canvas.width/2) + xo + self.show(media2.replace('media_', 'descr_')) + x = -(self.tw.canvas.width / 2) + xo self.tw.canvas.setxy(x, y, pendown=False) self.show(media2) # restore text size @@ -1379,8 +1409,8 @@ class LogoCode: def show_template2x2(self, title, media1, media2, media3, media4): """ title and four images """ xo = self.tw.calc_position('t2x2')[2] - x = -(self.tw.canvas.width/2) + xo - y = self.tw.canvas.height/2 + x = -(self.tw.canvas.width / 2) + xo + y = self.tw.canvas.height / 2 self.tw.canvas.setxy(x, y, pendown=False) # save the text size so we can restore it later save_text_size = self.tw.canvas.textsize @@ -1388,14 +1418,14 @@ class LogoCode: self.tw.canvas.settextsize(self.title_height) self.show(title) # calculate and set scale for media blocks - myscale = 45 * (self.tw.canvas.height - self.title_height*2)/\ + myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \ self.tw.canvas.height self.set_scale(myscale) # set body text size self.tw.canvas.settextsize(self.body_height) # render four quadrents # leave some space below the title - y -= int(self.title_height*2*self.tw.lead) + y -= int(self.title_height * 2 * self.tw.lead) self.tw.canvas.setxy(x, y, pendown=False) self.show(media1) x = 0 @@ -1404,7 +1434,7 @@ class LogoCode: y = -self.title_height self.tw.canvas.setxy(x, y, pendown=False) self.show(media4) - x = -(self.tw.canvas.width/2) + xo + x = -(self.tw.canvas.width / 2) + xo self.tw.canvas.setxy(x, y, pendown=False) self.show(media3) # restore text size @@ -1413,8 +1443,8 @@ class LogoCode: def show_template1x1a(self, title, media1): """ title, one media object """ xo = self.tw.calc_position('t1x1a')[2] - x = -(self.tw.canvas.width/2) + xo - y = self.tw.canvas.height/2 + x = -(self.tw.canvas.width / 2) + xo + y = self.tw.canvas.height / 2 self.tw.canvas.setxy(x, y, pendown=False) # save the text size so we can restore it later save_text_size = self.tw.canvas.textsize @@ -1422,14 +1452,14 @@ class LogoCode: self.tw.canvas.settextsize(self.title_height) self.show(title) # calculate and set scale for media blocks - myscale = 90 * (self.tw.canvas.height - self.title_height*2) /\ + myscale = 90 * (self.tw.canvas.height - self.title_height * 2) / \ self.tw.canvas.height self.set_scale(myscale) # set body text size self.tw.canvas.settextsize(self.body_height) # render media object # leave some space below the title - y -= int(self.title_height*2*self.tw.lead) + y -= int(self.title_height * 2 * self.tw.lead) self.tw.canvas.setxy(x, y, pendown=False) self.show(media1) # restore text size @@ -1437,7 +1467,7 @@ class LogoCode: def write(self, string, fsize): """ 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), + 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) diff --git a/TurtleArt/taturtle.py b/TurtleArt/taturtle.py index 7cfabf9..a11d15a 100644 --- a/TurtleArt/taturtle.py +++ b/TurtleArt/taturtle.py @@ -37,14 +37,13 @@ def generate_turtle_pixbufs(colors): svg = SVG() svg.set_scale(1.0) for i in range(SHAPES): - svg.set_orientation(i*10) + svg.set_orientation(i * 10) shapes.append(svg_str_to_pixbuf(svg.turtle(colors))) return shapes -# -# A class for the list of blocks and everything they share in common -# + class Turtles: + def __init__(self, sprite_list): """ Class to hold turtles """ self.dict = dict() @@ -77,7 +76,7 @@ class Turtles: def add_to_dict(self, k, turtle): """ Add a new turtle """ - self.dict[k] = turtle + self.dict[k] = turtle def remove_from_dict(self, k): """ Delete a turtle """ @@ -89,9 +88,6 @@ class Turtles: for k in iter(self.dict): self.dict[k].show() - # - # sprite utilities - # def spr_to_turtle(self, spr): """ Find the turtle that corresponds to sprite spr. """ for k in iter(self.dict): @@ -103,13 +99,12 @@ class Turtles: """ Get the pixbufs for the default turtle shapes. """ if self.default_pixbufs == []: self.default_pixbufs = generate_turtle_pixbufs( - ["#008000", "#00A000"]) + ["#008000", "#00A000"]) return(self.default_pixbufs) -# -# A class for the individual turtles -# + class Turtle: + def __init__(self, turtles, key, turtle_colors=None): """ The turtle is not a block, just a sprite with an orientation """ self.x = 0 @@ -180,7 +175,7 @@ class Turtle: def set_heading(self, heading): """ Set the turtle heading (one shape per 360/SHAPES degrees) """ - self.heading = heading + self.heading = heading i = (int(self.heading + 5) % 360) / (360 / SHAPES) if not self.hidden and self.spr is not None: try: diff --git a/TurtleArt/tautils.py b/TurtleArt/tautils.py index 8229166..9e9d2c3 100644 --- a/TurtleArt/tautils.py +++ b/TurtleArt/tautils.py @@ -44,20 +44,24 @@ from gettext import gettext as _ import logging _logger = logging.getLogger('turtleart-activity') + class pythonerror(Exception): + def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) -''' -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): + ''' + 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. + ''' try: return fn(x) except ValueError: @@ -67,6 +71,7 @@ def convert(x, fn, try_ord=True): return fn(xx) return x + def chr_to_ord(x): """ Try to comvert a string to an ord """ if strtype(x) and len(x) == 1: @@ -76,6 +81,7 @@ def chr_to_ord(x): return x, False return x, False + def strtype(x): """ Is x a string type? """ if type(x) == str: @@ -84,10 +90,12 @@ def strtype(x): return True return False + def magnitude(pos): """ Calculate the magnitude of the distance between to blocks. """ x, y = pos - return x*x+y*y + return x * x + y * y + def json_load(text): """ Load JSON data using what ever resources are available. """ @@ -96,12 +104,13 @@ def json_load(text): else: # strip out leading and trailing whitespace, nulls, and newlines text = text.lstrip() - text = text.replace('\12','') - text = text.replace('\00','') + text = text.replace('\12', '') + text = text.replace('\00', '') _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(tup): """ Convert to tuples """ @@ -109,12 +118,14 @@ def _tuplify(tup): return tup return tuple(map(_tuplify, tup)) + def get_id(connection): """ Get a connection block ID. """ if connection is None: return None return connection.id + def json_dump(data): """ Save data using available JSON tools. """ if OLD_SUGAR_SYSTEM is True: @@ -124,35 +135,34 @@ def json_dump(data): jdump(data, _io) return _io.getvalue() + def get_load_name(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)) + 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): """ 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)) + 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) + _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): """ Open the .ta file, ignoring any .png file that might be present. """ file_handle = open(ta_file, "r") + # + # We try to maintain read-compatibility with all versions of Turtle Art. + # Try pickle first; then different versions of json. + # try: _data = pickle.load(file_handle) except: @@ -163,25 +173,29 @@ def data_from_file(ta_file): file_handle.close() return _data + def data_from_string(text): """ JSON load data from a string. """ return json_load(text.replace(']],\n', ']], ')) + def data_to_file(data, ta_file): """ 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).replace(']], ', ']],\n') + def do_dialog(dialog, suffix, load_save_folder): """ Open a file dialog. """ _result = None file_filter = gtk.FileFilter() - file_filter.add_pattern('*'+suffix) + file_filter.add_pattern('*' + suffix) file_filter.set_name("Turtle Art") dialog.add_filter(file_filter) dialog.set_current_folder(load_save_folder) @@ -192,6 +206,7 @@ def do_dialog(dialog, suffix, load_save_folder): dialog.destroy() 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, @@ -203,12 +218,14 @@ def save_picture(canvas, 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: @@ -226,7 +243,8 @@ def get_pixbuf_from_journal(dsobject, w, h): _pixbuf = None return _pixbuf -def get_path(activity, subpath ): + +def get_path(activity, subpath): """ Find a Rainbow-approved place for temporary files. """ try: return(os.path.join(activity.get_activity_root(), subpath)) @@ -235,6 +253,7 @@ def get_path(activity, subpath ): return(os.path.join(os.environ['HOME'], ".sugar/default", "org.laptop.TurtleArtActivity", subpath)) + def image_to_base64(pixbuf, activity): """ Convert an image to base64 """ _file_name = os.path.join(get_path(activity, 'instance'), 'imagetmp.png') @@ -248,22 +267,28 @@ def image_to_base64(pixbuf, activity): _file_handle.close() return _data + def movie_media_type(name): """ Is it movie media? """ return name.endswith(('.ogv', '.vob', '.mp4', '.wmv', '.mov', '.mpeg')) -def audio_media_type(name): + +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(num): """ Remove trailing decimal places if number is an int """ try: @@ -275,14 +300,15 @@ def round_int(num): if int(float(num)) == num: return int(num) else: - if float(num)<0: - _nn = int((float(num)-0.005)*100)/100. + if float(num) < 0: + _nn = int((float(num) - 0.005) * 100) / 100. else: - _nn = int((float(num)+0.005)*100)/100. + _nn = int((float(num) + 0.005) * 100) / 100. 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 int(max(spr.label_safe_width(), 1)), \ @@ -290,12 +316,14 @@ def calc_image_size(spr): # 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 in ['sandwichtop', 'sandwichtop_no_label']: 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 in ['sandwichtop', 'sandwichtop_no_label']: @@ -307,11 +335,12 @@ def grow_stack_arm(top): _ty = top.spr.get_xy()[1] _th = top.spr.get_dimensions()[1] _by = _bot.spr.get_xy()[1] - _dy = _by-(_ty + _th) + _dy = _by - (_ty + _th) if _dy > 0: - top.expand_in_y(_dy/top.scale) + 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. @@ -329,6 +358,7 @@ def find_sandwich_top(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. @@ -342,10 +372,11 @@ def find_sandwich_bottom(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 in ['sandwichtop', 'sandwichtop_no_label', 'sandwichtop_no_arm', - 'sandwichtop_no_arm_no_label']: + if blk.name in ['sandwichtop', 'sandwichtop_no_label', + 'sandwichtop_no_arm', 'sandwichtop_no_arm_no_label']: return blk # Always follow the main branch of a flow: the last connection. _blk = blk.connections[len(blk.connections) - 1] @@ -356,6 +387,7 @@ def find_sandwich_top_below(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]) @@ -403,6 +435,7 @@ def restore_stack(top): 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: @@ -410,7 +443,7 @@ def uncollapse_forks(top, looping=False): if looping and top.name in ['sandwichtop_no_arm', 'sandwichtop_no_arm_no_label']: restore_stack(top) - return + return if len(top.connections) == 0: return _blk = top.connections[len(top.connections) - 1] @@ -418,22 +451,24 @@ def uncollapse_forks(top, looping=False): if _blk.name in COLLAPSIBLE: return if _blk.name in ['sandwichtop_no_arm', 'sandwichtop_no_arm_no_label']: - restore_stack(_blk) + restore_stack(_blk) return # Follow a fork - if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while', 'until']: + if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while', + 'until']: top = find_sandwich_top_below( - _blk.connections[len(_blk.connections) - 2]) + _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]) + _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 @@ -489,6 +524,7 @@ def collapse_stack(top): top.name = 'sandwichtop_no_arm_no_label' top.refresh() + def collapsed(blk): """ Is this stack collapsed? """ if blk is not None and blk.name in COLLAPSIBLE and\ @@ -496,6 +532,7 @@ def collapsed(blk): return True return False + def collapsible(blk): """ Can this stack be collapsed? """ if blk is None or blk.name not in COLLAPSIBLE: @@ -504,6 +541,7 @@ def collapsible(blk): 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)) @@ -512,6 +550,7 @@ def hide_button_hit(spr, x, y): 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)) @@ -520,12 +559,14 @@ def show_button_hit(spr, x, y): 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): @@ -533,6 +574,7 @@ def zero_arg(value): return True return False + def neg_arg(value): """ Dock test: looking for a negative argument """ if numeric_arg(value): @@ -540,6 +582,7 @@ def neg_arg(value): 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] @@ -572,6 +615,7 @@ def dock_dx_dy(block1, dock1n, block2, dock2n): (_b2x, _b2y) = block2.spr.get_xy() return ((_b1x + _d1x) - (_b2x + _d2x), (_b1y + _d1y) - (_b2y + _d2y)) + def journal_check(blk1, blk2, dock1, dock2): """ Dock blocks only if arg is Journal block """ if blk1 == None or blk2 == None: @@ -582,6 +626,7 @@ def journal_check(blk1, blk2, dock1, dock2): return False return True + 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: @@ -656,6 +701,7 @@ def arithmetic_check(blk1, blk2, dock1, dock2): return False return True + def xy(event): """ Where is the mouse event? """ return map(int, event.get_coords()) @@ -664,6 +710,7 @@ def xy(event): Utilities related to finding blocks in stacks. """ + 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) @@ -672,6 +719,7 @@ def find_block_to_run(blk): else: return False + def find_top_block(blk): """ Find the top block in a stack. """ if blk is None: @@ -682,6 +730,7 @@ def find_top_block(blk): blk = blk.connections[0] return blk + def find_start_stack(blk): """ Find a stack with a 'start' block on top. """ if blk is None: @@ -691,6 +740,7 @@ def find_start_stack(blk): else: return False + def find_group(blk): """ Find the connected group of block in a stack. """ if blk is None: @@ -702,6 +752,7 @@ def find_group(blk): _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: @@ -712,11 +763,13 @@ def find_blk_below(blk, 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) diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py index cdaa498..f3b4beb 100644 --- a/TurtleArt/tawindow.py +++ b/TurtleArt/tawindow.py @@ -28,7 +28,7 @@ import gobject import os import os.path from math import atan2, pi -DEGTOR = 2*pi/360 +DEGTOR = 2 * pi / 360 import locale from gettext import gettext as _ @@ -42,12 +42,12 @@ except ImportError: from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ PALETTE_NAMES, TITLEXY, MEDIA_SHAPES, STATUS_SHAPES, \ - OVERLAY_SHAPES, TOOLBAR_SHAPES, TAB_LAYER, \ + OVERLAY_SHAPES, TOOLBAR_SHAPES, TAB_LAYER, RETURN, \ 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, \ + CONTENT_BLOCKS, DEFAULTS, SPECIAL_NAMES, \ + HELP_STRINGS, CURSOR, EXPANDABLE, COLLAPSIBLE, \ DEAD_DICTS, DEAD_KEYS, TEMPLATES, PYTHON_SKIN, \ PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK, OLD_NAMES, \ BOOLEAN_STYLE, BLOCK_NAMES, DEFAULT_TURTLE, \ @@ -75,6 +75,7 @@ from sprites import Sprites, Sprite import logging _logger = logging.getLogger('turtleart-activity') + class TurtleArtWindow(): """ TurtleArt Window class abstraction """ timeout_tag = [0] @@ -116,7 +117,7 @@ class TurtleArtWindow(): self.save_folder = None self.save_file_name = None self.width = gtk.gdk.screen_width() - self.height = gtk.gdk.screen_height() + self.height = gtk.gdk.screen_height() self.rect = gtk.gdk.Rectangle(0, 0, 0, 0) self.keypress = '' @@ -213,7 +214,7 @@ class TurtleArtWindow(): self.rightx = 0 self.titley = (self.canvas.height * TITLEXY[1]) / \ (self.coord_scale * 2) - self.topy = (self.canvas.height*(TITLEXY[1] - 0.125)) / \ + self.topy = (self.canvas.height * (TITLEXY[1] - 0.125)) / \ (self.coord_scale * 2) self.bottomy = 0 @@ -252,22 +253,22 @@ class TurtleArtWindow(): 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_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), + 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: - offset = self.width-55*len(TOOLBAR_SHAPES) + 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, @@ -327,7 +328,7 @@ class TurtleArtWindow(): stop_logo(self) def set_userdefined(self): - """ Change icon for user-defined blocks after Python code is loaded. """ + """ Change icon for user-defined blocks after loading Python code. """ for blk in self.just_blocks(): if blk.name in PYTHON_SKIN: x, y = self._calc_image_offset('pythonon', blk.spr) @@ -394,10 +395,10 @@ class TurtleArtWindow(): def hideshow_button(self): """ Hide/show button """ - if not self.hide: + if not self.hide: for blk in self.just_blocks(): blk.spr.hide() - self.hide_palette() + self.hide_palette() self.hide = True else: for blk in self.just_blocks(): @@ -514,7 +515,7 @@ class TurtleArtWindow(): self.selectors[i].name = name self.selectors[i].set_layer(TAB_LAYER) w = self.selectors[i].get_dimensions()[0] - x += int(w) + x += int(w) # Create the toolbar background self.toolbar_offset = ICON_SIZE @@ -536,22 +537,22 @@ class TurtleArtWindow(): # Create the palette orientation button self.palette_button.append(Sprite(self.sprite_list, 0, - self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( - "%s/images/palettehorizontal.svg" %(self.path))))) + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettehorizontal.svg" % (self.path))))) self.palette_button.append(Sprite(self.sprite_list, 0, - self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( - "%s/images/palettevertical.svg" % (self.path))))) + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettevertical.svg" % (self.path))))) self.palette_button[0].name = _('orientation') self.palette_button[1].name = _('orientation') self.palette_button[0].type = 'palette' self.palette_button[1].type = 'palette' self.palette_button[self.orientation].set_layer(TAB_LAYER) - self.palette_button[1-self.orientation].hide() + self.palette_button[1 - self.orientation].hide() # Create the palette next button self.palette_button.append(Sprite(self.sprite_list, 16, - self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( - "%s/images/palettenext.svg" %(self.path))))) + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettenext.svg" % (self.path))))) self.palette_button[2].name = _('next') self.palette_button[2].type = 'palette' self.palette_button[2].set_layer(TAB_LAYER) @@ -563,7 +564,7 @@ class TurtleArtWindow(): self._hide_previous_palette() self.selected_palette = n - self.previous_palette = self.selected_palette + self.previous_palette = self.selected_palette if self.activity is None or not self.activity.new_sugar_system: self.selected_selector = self.selectors[n] @@ -580,14 +581,13 @@ class TurtleArtWindow(): # Create 'proto' blocks for each palette entry for i, name in enumerate(PALETTES[n]): self.palettes[n].append(Block(self.block_list, - self.sprite_list, name, - 0, 0, 'proto', [], PALETTE_SCALE)) + self.sprite_list, name, 0, 0, 'proto', [], PALETTE_SCALE)) self.palettes[n][i].spr.set_layer(TAB_LAYER) self.palettes[n][i].unhighlight() # Some proto blocks get a skin. if name in BOX_STYLE_MEDIA: - self._proto_skin(name+'small', n, i) + self._proto_skin(name + 'small', n, i) elif name[:8] == 'template': self._proto_skin(name[8:], n, i) elif name[:7] == 'picture': @@ -621,7 +621,7 @@ class TurtleArtWindow(): """ 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])): + for i in range(len(PALETTES[self.previous_palette])): self.palettes[self.previous_palette][i].spr.hide() self.palette_sprs[self.previous_palette][ self.orientation].hide() @@ -643,15 +643,15 @@ class TurtleArtWindow(): for blk in blocks: _w, _h = self._width_and_height(blk) if y + _h > PALETTE_HEIGHT + self.toolbar_offset: - x += int(_max_w+3) + x += int(_max_w + 3) y = self.toolbar_offset + 3 _max_w = 0 (_bx, _by) = blk.spr.get_xy() - _dx = x-_bx - _dy = y-_by + _dx = x - _bx + _dy = y - _by for g in find_group(blk): g.spr.move_relative((int(_dx), int(_dy))) - y += int(_h+3) + y += int(_h + 3) if _w > _max_w: _max_w = _w return x, y, _max_w @@ -665,14 +665,14 @@ class TurtleArtWindow(): _w, _h = self._width_and_height(_b) if x + _w > PALETTE_WIDTH: # Recenter row. - _dx = int((PALETTE_WIDTH-_row_w)/2) + _dx = int((PALETTE_WIDTH - _row_w) / 2) for _r in _row: for _g in find_group(_r): _g.spr.move_relative((_dx, 0)) _row = [] _row_w = 0 x = 4 - y += int(_max_h+3) + y += int(_max_h + 3) _max_h = 0 _row.append(_b) _row_w += (4 + _w) @@ -685,7 +685,7 @@ class TurtleArtWindow(): 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 find_group(_r): _g.spr.move_relative((_dx, 0)) @@ -696,9 +696,10 @@ class TurtleArtWindow(): if n is not None: if self.orientation == HORIZONTAL_PALETTE: _x, _y = 20, self.toolbar_offset + 5 - _x, _y, _max = self._horizontal_layout(_x, _y, self.palettes[n]) + _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, + _x, _y, _max = self._horizontal_layout(_x + _max, _y, self.trash_stack) _w = _x + _max + 25 if self.palette_sprs[n][self.orientation] is None: @@ -711,7 +712,7 @@ class TurtleArtWindow(): svg = SVG() self.palette_sprs[n][self.orientation].set_shape( svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT))) - self.palette_button[2].move((_w-20, self.toolbar_offset)) + self.palette_button[2].move((_w - 20, self.toolbar_offset)) else: _x, _y = 5, self.toolbar_offset + 15 _x, _y, _max = self._vertical_layout(_x, _y, self.palettes[n]) @@ -729,7 +730,7 @@ class TurtleArtWindow(): svg = SVG() self.palette_sprs[n][self.orientation].set_shape( svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h))) - self.palette_button[2].move((PALETTE_WIDTH-20, + self.palette_button[2].move((PALETTE_WIDTH - 20, self.toolbar_offset)) self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) @@ -740,7 +741,7 @@ class TurtleArtWindow(): self.mouse_flag = 1 self.mouse_x = x self.mouse_y = y - self.button_press(event.get_state()>k.gdk.CONTROL_MASK, x, y) + self.button_press(event.get_state() & gtk.gdk.CONTROL_MASK, x, y) return True def button_press(self, mask, x, y): @@ -816,16 +817,16 @@ class TurtleArtWindow(): if 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.activity.palette_buttons[i].set_icon( - PALETTE_NAMES[i] + 'on') + 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() + 1 - self.orientation].hide() self._layout_palette(self.selected_palette) self.show_palette(self.selected_palette) elif spr.type == 'toolbar': @@ -894,7 +895,7 @@ class TurtleArtWindow(): 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 gblk in group: @@ -952,9 +953,9 @@ class TurtleArtWindow(): self.palette_sprs[self.trash_index][self.orientation].hit((x, y)): return True """ - if self.selected_palette is not None and\ + 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 @@ -965,7 +966,7 @@ class TurtleArtWindow(): self._disconnect(blk) self.drag_group = find_group(blk) (sx, sy) = blk.spr.get_xy() - self.drag_pos = x-sx, y-sy + self.drag_pos = x - sx, y - sy for blk in self.drag_group: if blk.status != 'collapsed': blk.spr.set_layer(TOP_LAYER) @@ -997,12 +998,12 @@ class TurtleArtWindow(): else: self._block_skin('pythonoff', newblk) elif name in BOX_STYLE_MEDIA: - self._block_skin(name+'off', newblk) + self._block_skin(name + 'off', newblk) newspr = newblk.spr newspr.set_layer(TOP_LAYER) self.drag_pos = 20, 20 - newblk.connections = [None]*len(newblk.docks) + newblk.connections = [None] * len(newblk.docks) if newblk.name in DEFAULTS: for i, argvalue in enumerate(DEFAULTS[newblk.name]): # skip the first dock position since it is always a connector @@ -1039,7 +1040,7 @@ class TurtleArtWindow(): argblk.connections = [newblk, None] newblk.connections[i + 1] = argblk self.drag_group = find_group(newblk) - self.block_operation = 'new' + self.block_operation = 'new' def _new_macro(self, name, x, y): """ Create a "macro" (predefined stack of blocks). """ @@ -1047,7 +1048,7 @@ class TurtleArtWindow(): macro[0][2] = x macro[0][3] = y top = self.process_data(macro) - self.block_operation = 'new' + self.block_operation = 'new' self._check_collapsibles(top) self.drag_group = find_group(top) @@ -1072,7 +1073,7 @@ class TurtleArtWindow(): else: cons.append(blocks[c]) elif blocks[i].connections == 'check': - # Corner case to convert old-style boolean and arithmetic blocks + # Convert old-style boolean and arithmetic blocks cons.append(None) # Add an extra connection. for c in block_data[i][4]: if c is None: @@ -1146,21 +1147,21 @@ class TurtleArtWindow(): for j in range(len(c.docks)): if c.connections[j] == blk: cdock = c.docks[j] - nx = sx + bdock[2] - cdock[2] + nx = sx + bdock[2] - cdock[2] ny = sy + bdock[3] - cdock[3] c.spr.move((nx, ny)) self._adjust_dock_positions(c) def _turtle_pressed(self, x, y): (tx, ty) = self.selected_turtle.get_xy() - w = self.active_turtle.spr.rect.width/2 - h = self.active_turtle.spr.rect.height/2 + w = self.active_turtle.spr.rect.width / 2 + h = self.active_turtle.spr.rect.height / 2 dx = x - tx - w dy = y - ty - h # if x, y is near the edge, rotate if (dx * dx) + (dy * dy) > ((w * w) + (h * h)) / 6: 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) @@ -1183,9 +1184,10 @@ class TurtleArtWindow(): self.selected_turtle.spr.set_layer(TOP_LAYER) self.selected_turtle.move((sx + dx, sy + dy)) else: - dx = x - sx - self.active_turtle.spr.rect.width/2 - dy = y - sy - self.active_turtle.spr.rect.height/2 - self.canvas.seth(int(dragx + atan2(dy, dx)/DEGTOR + 5)/10 * 10) + dx = x - sx - self.active_turtle.spr.rect.width / 2 + dy = y - sy - self.active_turtle.spr.rect.height / 2 + 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: @@ -1275,9 +1277,9 @@ class TurtleArtWindow(): self.timeout_tag[0] = 0 except: self.timeout_tag[0] = 0 - elif spr and hasattr(spr,'type') and (spr.type == 'selector' or\ - spr.type == 'palette' or\ - spr.type == 'toolbar'): + elif spr and hasattr(spr, 'type') and (spr.type == 'selector' or \ + spr.type == 'palette' or \ + spr.type == 'toolbar'): if self.timeout_tag[0] == 0 and hasattr(spr, 'name'): self.timeout_tag[0] = self._do_show_popup(spr.name) self.selected_spr = spr @@ -1345,16 +1347,16 @@ class TurtleArtWindow(): self.turtles.remove_from_dict(k) else: self._move_turtle(tx - self.canvas.width / 2 + \ - self.active_turtle.spr.rect.width/2, + self.active_turtle.spr.rect.width / 2, self.canvas.height / 2 - ty - \ - self.active_turtle.spr.rect.height/2) + self.active_turtle.spr.rect.height / 2) self.selected_turtle = None self.active_turtle = self.turtles.get_turtle( self.default_turtle_name) return # If we don't have a group of blocks, then there is nothing to do. - if self.drag_group is None: + if self.drag_group is None: return blk = self.drag_group[0] @@ -1369,10 +1371,10 @@ class TurtleArtWindow(): for gblk in self.drag_group: (bx, by) = gblk.spr.get_xy() if self.orientation == 0: - gblk.spr.move((bx+20, - by+PALETTE_HEIGHT+self.toolbar_offset)) + gblk.spr.move((bx + 20, + by + PALETTE_HEIGHT + self.toolbar_offset)) else: - gblk.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() @@ -1387,7 +1389,7 @@ class TurtleArtWindow(): self._click_block(x, y) def _move_turtle(self, x, y): - """ Move the selected turtle to (x, y). """ + """ Move the selected turtle to (x, y). """ (cx, cy) = self.canvas.canvas.get_xy() self.canvas.xcor = x - cx self.canvas.ycor = y + cy @@ -1465,7 +1467,7 @@ class TurtleArtWindow(): elif blk.name in EXPANDABLE_ARGS or blk.name == 'nop': if show_button_hit(blk.spr, x, y): n = len(blk.connections) - group = 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[2] = ' ' @@ -1489,9 +1491,9 @@ class TurtleArtWindow(): dy = blk.add_arg() 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] + blk.connections.append(blk.connections[n - 1]) + argname = blk.docks[n - 1][0] + argvalue = DEFAULTS[blk.name][len(DEFAULTS[blk.name]) - 1] argblk = Block(self.block_list, self.sprite_list, argname, 0, 0, 'block', [argvalue], self.block_scale) argdock = argblk.docks[0] @@ -1571,7 +1573,7 @@ class TurtleArtWindow(): break def _check_collapsibles(self, blk): - """ Check the state of collapsible blocks upon change in dock state. """ + """ Check state of collapsible blocks upon change in dock state. """ group = find_group(blk) for gblk in group: if gblk.name in COLLAPSIBLE: @@ -1711,8 +1713,7 @@ class TurtleArtWindow(): def _import_from_journal(self, blk): """ Import a file from the Sugar Journal """ if self.running_sugar: - chooser = ObjectChooser('Choose image', self.parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + chooser = ObjectChooser(parent=self.parent) try: result = chooser.run() if result == gtk.RESPONSE_ACCEPT: @@ -1723,15 +1724,15 @@ class TurtleArtWindow(): chooser.destroy() del chooser else: - fname, self.load_save_folder = \ - get_load_name('.*', self.load_save_folder) + fname, self.load_save_folder = get_load_name('.*', + self.load_save_folder) if fname is None: return self._update_media_icon(blk, fname) def _load_description_block(self, blk): """ Look for a corresponding description block """ - if blk is None or blk.name != 'journal' or len(blk.values) == 0 or\ + if blk is None or blk.name != 'journal' or len(blk.values) == 0 or \ blk.connections[0] is None: return _blk = blk.connections[0] @@ -1785,7 +1786,7 @@ class TurtleArtWindow(): keyname = gtk.gdk.keyval_name(event.keyval) keyunicode = gtk.gdk.keyval_to_unicode(event.keyval) - if event.get_state()>k.gdk.MOD1_MASK: + if event.get_state() & gtk.gdk.MOD1_MASK: alt_mask = True alt_flag = 'T' else: @@ -1805,7 +1806,7 @@ class TurtleArtWindow(): self.hideshow_button() elif keyname == 'q': exit() - + elif self.selected_blk is not None: if self.selected_blk.name == 'number': self._process_numeric_input(keyname) @@ -1868,7 +1869,7 @@ class TurtleArtWindow(): 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) + c = self.selected_blk.spr.labels[0].count(CURSOR) if c == 0: oldleft = self.selected_blk.spr.labels[0] oldright = '' @@ -1906,21 +1907,21 @@ class TurtleArtWindow(): else: newleft = '' elif keyname == 'Home': - oldright = oldleft+oldright + oldright = oldleft + oldright newleft = '' elif keyname == 'Left': if len(oldleft) > 0: - oldright = oldleft[len(oldleft)-1:]+oldright - newleft = oldleft[:len(oldleft)-1] + oldright = oldleft[len(oldleft) - 1:] + oldright + newleft = oldleft[:len(oldleft) - 1] elif keyname == 'Right': if len(oldright) > 0: newleft = oldleft + oldright[0] oldright = oldright[1:] elif keyname == 'End': - newleft = oldleft+oldright + newleft = oldleft + oldright oldright = '' elif keyname == 'Return': - newleft = oldleft+RETURN + newleft = oldleft + RETURN elif keyname == 'Down': self._unselect_block() return @@ -1935,14 +1936,14 @@ class TurtleArtWindow(): self.dead_key = '' if keyunicode > 0: if unichr(keyunicode) != '\x00': - newleft = oldleft+unichr(keyunicode) + newleft = oldleft + unichr(keyunicode) else: newleft = oldleft elif keyunicode == -1: # clipboard text if keyname == '\n': - newleft = oldleft+RETURN + newleft = oldleft + RETURN else: - newleft = oldleft+keyname + newleft = oldleft + keyname self.selected_blk.spr.set_label("%s%s%s" % (newleft, CURSOR, oldright)) def _process_keyboard_commands(self, keyname, block_flag=True): @@ -2015,7 +2016,7 @@ class TurtleArtWindow(): for blk in self.drag_group: (sx, sy) = blk.spr.get_xy() - if sx+dx < 0: + if sx + dx < 0: dx += -(sx + dx) for blk in self.drag_group: @@ -2028,7 +2029,7 @@ class TurtleArtWindow(): def _number_check(self): """ Make sure a 'number' block contains a number. """ n = self.selected_blk.spr.labels[0].replace(CURSOR, '') - if n in ['-', '.', '-.', ',']: + if n in ['-', '.', '-.', ',', '-,']: n = 0 elif n is not None: try: @@ -2061,7 +2062,7 @@ class TurtleArtWindow(): f = open(fname, 'r') self.myblock = f.read() f.close() - + def _import_py(self): """ Import Python code into a block """ if self.running_sugar: @@ -2081,7 +2082,7 @@ class TurtleArtWindow(): self._put_in_trash(top) self.canvas.clearscreen() self.save_file_name = None - + def is_new_project(self): """ Is this a new project or was a old project loaded from a file? """ return self._loaded_project == "" @@ -2091,9 +2092,9 @@ class TurtleArtWindow(): try: f = open(self._loaded_project, 'r') saved_project_data = f.read() - f.close() + f.close() except: - _logger.debug("problem loading saved project data from %s" %\ + _logger.debug("problem loading saved project data from %s" % \ (self._loaded_project)) saved_project_data = "" current_project_data = data_to_string(self.assemble_data_to_save()) @@ -2106,15 +2107,15 @@ class TurtleArtWindow(): self.new_project() self._check_collapsibles(self.process_data(data_from_file(ta_file))) self._loaded_prokect = ta_file - + def load_file(self, create_new_project=True): _file_name, self.load_save_folder = get_load_name('.ta', self.load_save_folder) if _file_name is None: return if _file_name[-3:] == '.ta': - _file_name = _file_name[0:-3] - self.load_files(_file_name+'.ta', create_new_project) + _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(_file_name) if self.running_sugar: @@ -2125,7 +2126,7 @@ class TurtleArtWindow(): if blk[1] == 'turtle': self.load_turtle(blk) return True - elif type(blk[1]) == list and blk[1][0] == 'turtle': + elif type(blk[1]) == list and blk[1][0] == 'turtle': self.load_turtle(blk, blk[1][1]) return True elif type(blk[1]) == tuple: @@ -2150,7 +2151,7 @@ class TurtleArtWindow(): # A block is saved as: (i, (btype, value), x, y, (c0,... cn)) # The x, y position is saved/loaded for backward compatibility btype, value = b[1], None - if type(btype) == tuple: + if type(btype) == tuple: btype, value = btype elif type(btype) == list: btype, value = btype[0], btype[1] @@ -2169,7 +2170,7 @@ class TurtleArtWindow(): values = [value] else: values = [] - + if btype in OLD_DOCK: check_dock = True else: @@ -2210,11 +2211,11 @@ class TurtleArtWindow(): else: self._block_skin('pythonoff', blk) elif btype in BOX_STYLE_MEDIA and blk.spr is not None: - if len(blk.values) == 0 or blk.values[0] == 'None' or\ + if len(blk.values) == 0 or blk.values[0] == 'None' or \ blk.values[0] is None: - self._block_skin(btype+'off', blk) + self._block_skin(btype + 'off', blk) elif btype == 'audio' or btype == 'description': - self._block_skin(btype+'on', blk) + self._block_skin(btype + 'on', blk) elif self.running_sugar: try: dsobject = datastore.get(blk.values[0]) @@ -2235,7 +2236,7 @@ class TurtleArtWindow(): x, y = self._calc_image_offset('', blk.spr) blk.set_image(pixbuf, x, y) except: - _logger.debug("Warning: Couldn't open dsobject (%s)" % \ + _logger.debug("Couldn't open dsobject (%s)" % \ (blk.values[0])) self._block_skin('journaloff', blk) else: @@ -2258,27 +2259,27 @@ class TurtleArtWindow(): if check_dock: blk.connections = 'check' return blk - + def load_start(self, ta_file=None): """ Start a new project with a 'start' brick """ if ta_file is None: self.process_data([[0, "start", PALETTE_WIDTH + 20, - self.toolbar_offset+PALETTE_HEIGHT + 20, + self.toolbar_offset + PALETTE_HEIGHT + 20, [None, None]]]) else: self.process_data(data_from_file(ta_file)) - + def save_file(self, _file_name=None): """ Start a project to a file """ if self.save_folder is not None: self.load_save_folder = self.save_folder if _file_name is None: _file_name, self.load_save_folder = get_save_name('.ta', - self.load_save_folder, self.save_file_name) + self.load_save_folder, self.save_file_name) if _file_name is None: return if _file_name[-3:] == '.ta': - _file_name = _file_name[0:-3] + _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) if not self.running_sugar: @@ -2295,7 +2296,7 @@ class TurtleArtWindow(): if self.selected_blk is None: return [] _blks = find_group(find_top_block(self.selected_blk)) - + for _i, _blk in enumerate(_blks): _blk.id = _i for _blk in _blks: @@ -2326,32 +2327,31 @@ class TurtleArtWindow(): if not save_project: _sx += 20 _sy += 20 - _data.append((_blk.id, _name, _sx-self.canvas.cx, - _sy-self.canvas.cy, connections)) + _data.append((_blk.id, _name, _sx - self.canvas.cx, + _sy - self.canvas.cy, connections)) if save_turtle: 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)) + self.canvas.heading, self.canvas.color, + self.canvas.shade, self.canvas.pensize)) return _data 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) + x = round_int(self.canvas.xcor / self.coord_scale) + y = round_int(self.canvas.ycor / self.coord_scale) h = round_int(self.canvas.heading) if self.running_sugar: - self.activity.coordinates_label.set_text("%s: %d %s: %d %s: %d" % ( - _("xcor"), x, _("ycor"), y, _("heading"), h)) + self.activity.coordinates_label.set_text("%s: %d %s: %d %s: %d" % \ + (_("xcor"), x, _("ycor"), y, _("heading"), h)) self.activity.coordinates_label.show() elif self.interactive_mode: - self.win.set_title("%s — %s: %d %s: %d %s: %d" % (_("Turtle Art"), - _("xcor"), x, _("ycor"), y, _("heading"), h)) + self.win.set_title("%s — %s: %d %s: %d %s: %d" % \ + (_("Turtle Art"), _("xcor"), x, _("ycor"), y, _("heading"), h)) - def showlabel(self, shp, label = ''): + def showlabel(self, shp, label=''): """ Display a message on a status block """ if not self.interactive_mode: _logger.debug(label) @@ -2369,17 +2369,17 @@ class TurtleArtWindow(): self.status_spr.set_label(str(label)) self.status_spr.set_layer(STATUS_LAYER) if shp == 'info': - self.status_spr.move((PALETTE_WIDTH, self.height-400)) + self.status_spr.move((PALETTE_WIDTH, self.height - 400)) else: - self.status_spr.move((PALETTE_WIDTH, self.height-200)) + self.status_spr.move((PALETTE_WIDTH, self.height - 200)) 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) + w *= (self.canvas.width - x) + h *= (self.canvas.height - y) dx *= w dy *= h return(w, h, x, y, dx, dy) @@ -2387,7 +2387,7 @@ class TurtleArtWindow(): def save_for_upload(self, _file_name): """ Grab the current canvas and save it for upload """ if _file_name[-3:] == '.ta': - _file_name = _file_name[0:-3] + _file_name = _file_name[0: -3] data_to_file(self.assemble_data_to_save(), _file_name + '.ta') save_picture(self.canvas, _file_name + '.png') ta_file = _file_name + '.ta' @@ -2413,12 +2413,12 @@ class TurtleArtWindow(): if len(name) == 0: filename = "ta.svg" else: - filename = name+".svg" + filename = name + ".svg" else: if len(name) == 0: filename = "ta.png" else: - filename = name+".png" + filename = name + ".png" datapath = get_path(self.activity, 'instance') elif len(name) == 0: name = "ta" @@ -2436,9 +2436,9 @@ class TurtleArtWindow(): else: datapath = os.getcwd() if svg: - filename = name+".svg" + filename = name + ".svg" else: - filename = name+".png" + filename = name + ".png" if filename is None: return @@ -2457,8 +2457,8 @@ class TurtleArtWindow(): if self.running_sugar: dsobject = datastore.create() if len(name) == 0: - dsobject.metadata['title'] = "%s %s" % ( - self.activity.metadata['title'], _("image")) + dsobject.metadata['title'] = "%s %s" % \ + (self.activity.metadata['title'], _("image")) else: dsobject.metadata['title'] = name dsobject.metadata['icon-color'] = profile.get_color().to_string() @@ -2509,7 +2509,7 @@ 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) def _calc_w_h(self, name, spr): """ Calculate new image size """ @@ -2519,13 +2519,13 @@ class TurtleArtWindow(): return target_w, target_h image_w = self.media_shapes[name].get_width() image_h = self.media_shapes[name].get_height() - scale_factor = float(target_w)/image_w + scale_factor = float(target_w) / image_w new_w = target_w - new_h = image_h*scale_factor + new_h = image_h * scale_factor if new_h > target_h: - scale_factor = float(target_h)/new_h + scale_factor = float(target_h) / new_h new_h = target_h - new_w = target_w*scale_factor + new_w = target_w * scale_factor return int(new_w), int(new_h) def _proto_skin(self, name, n, i): |