From 25e7097b3fbddcc140a081a5cf570d815c43c1d8 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 18 Aug 2010 18:16:39 +0000 Subject: removing files that were moved --- diff --git a/sprites.py b/sprites.py deleted file mode 100644 index ae5447d..0000000 --- a/sprites.py +++ /dev/null @@ -1,420 +0,0 @@ -# -*- coding: utf-8 -*- - -#Copyright (c) 2007-8, Playful Invention Company. -#Copyright (c) 2008-10 Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -""" - -sprites.py is a simple sprites library for managing graphics objects, -'sprites', on a canvas. It manages multiple sprites with methods such -as move, hide, set_layer, etc. - -There are two classes: - -class Sprites maintains a collection of sprites. -class Sprite manages individual sprites within the collection. - -Example usage: - # Import the classes into your program. - from sprites import Sprites Sprite - - # In your expose callback event handler, call refresh - def _expose_cb(self, win, event): - self.sprite_list.refresh(event) - return True - - # Create a new sprite collection for a gtk Drawing Area. - my_drawing_area = gtk.DrawingArea() - self.sprite_list = Sprites(my_drawing_area) - - # Create a "pixbuf" (in this example, from SVG). - my_pixbuf = svg_str_to_pixbuf("...some svg code...") - - # Create a sprite at position x1, y1. - my_sprite = sprites.Sprite(self.sprite_list, x1, y1, my_pixbuf) - - # Move the sprite to a new position. - my_sprite.move((x1+dx, y1+dy)) - - # Create another "pixbuf". - your_pixbuf = svg_str_to_pixbuf("...some svg code...") - - # Create a sprite at position x2, y2. - your_sprite = sprites.Sprite(self.sprite_list, x2, y2, my_pixbuf) - - # Assign the sprites to layers. - # In this example, your_sprite will be on top of my_sprite. - my_sprite.set_layer(100) - your_sprite.set_layer(200) - - # Now put my_sprite on top of your_sprite. - my_sprite.set_layer(300) - -# method for converting SVG to a gtk pixbuf -def svg_str_to_pixbuf(svg_string): - pl = gtk.gdk.PixbufLoader('svg') - pl.write(svg_string) - pl.close() - pixbuf = pl.get_pixbuf() - return pixbuf -""" - -import pygtk -pygtk.require('2.0') -import gtk -import pango - - -class Sprites: - """ A class for the list of sprites and everything they share in common """ - - def __init__(self, canvas, area=None, gc=None): - """ Initialize an empty array of sprites """ - self.canvas = canvas - if area == None: - self.area = self.canvas.window - self.gc = self.area.new_gc() - else: - self.area = area - self.gc = gc - self.cm = self.gc.get_colormap() - self.list = [] - - def get_sprite(self, i): - """ Return a sprint from the array """ - if i < 0 or i > len(self.list)-1: - return(None) - else: - return(self.list[i]) - - def length_of_list(self): - """ How many sprites are there? """ - return(len(self.list)) - - def append_to_list(self, spr): - """ Append a new sprite to the end of the list. """ - self.list.append(spr) - - def insert_in_list(self, spr, i): - """ Insert a sprite at position i. """ - if i < 0: - self.list.insert(0, spr) - elif i > len(self.list) - 1: - self.list.append(spr) - else: - self.list.insert(i, spr) - - def remove_from_list(self, spr): - """ Remove a sprite from the list. """ - if spr in self.list: - self.list.remove(spr) - - def find_sprite(self, pos): - """ Search based on (x, y) position. Return the 'top/first' one. """ - list = self.list[:] - list.reverse() - for spr in list: - if spr.hit(pos): - return spr - return None - - def refresh(self, event): - """ Handle expose event refresh """ - self.redraw_sprites(event.area) - - def redraw_sprites(self, area=None): - """ Redraw the sprites that intersect area. """ - for spr in self.list: - if area == None: - spr.draw() - else: - intersection = spr.rect.intersect(area) - if intersection.width > 0 or intersection.height > 0: - spr.draw() - - -class Sprite: - """ A class for the individual sprites """ - - def __init__(self, sprites, x, y, image): - """ Initialize an individual sprite """ - self._sprites = sprites - self.rect = gtk.gdk.Rectangle(int(x), int(y), 0, 0) - self._scale = [12] - self._rescale = [True] - self._horiz_align = ["center"] - self._vert_align = ["middle"] - self._fd = None - self._bold = False - self._italic = False - self._color = None - self._margins = [0, 0, 0, 0] - self.layer = 100 - self.labels = [] - self.images = [] - self._dx = [] # image offsets - self._dy = [] - self.set_image(image) - if self._sprites is not None: - self._sprites.append_to_list(self) - - def set_image(self, image, i=0, dx=0, dy=0): - """ Add an image to the sprite. """ - while len(self.images) < i + 1: - self.images.append(None) - self._dx.append(0) - self._dy.append(0) - self.images[i] = image - self._dx[i] = dx - self._dy[i] = dy - if isinstance(self.images[i], gtk.gdk.Pixbuf): - w = self.images[i].get_width() - h = self.images[i].get_height() - else: - w, h = self.images[i].get_size() - if i == 0: # Always reset width and height when base image changes. - self.rect.width = w + dx - self.rect.height = h + dy - else: - if w + dx > self.rect.width: - self.rect.width = w + dx - if h + dy > self.rect.height: - self.rect.height = h + dy - - def move(self, pos): - """ Move to new (x, y) position """ - self.inval() - self.rect.x, self.rect.y = int(pos[0]), int(pos[1]) - self.inval() - - def move_relative(self, pos): - """ Move to new (x+dx, y+dy) position """ - self.inval() - self.rect.x += int(pos[0]) - self.rect.y += int(pos[1]) - self.inval() - - def get_xy(self): - """ Return current (x, y) position """ - return (self.rect.x, self.rect.y) - - def get_dimensions(self): - """ Return current size """ - return (self.rect.width, self.rect.height) - - def get_layer(self): - """ Return current layer """ - return self.layer - - def set_shape(self, image, i=0): - """ Set the current image associated with the sprite """ - self.inval() - self.set_image(image, i) - self.inval() - - def set_layer(self, layer): - """ Set the layer for a sprite """ - if self._sprites is None: - return - self._sprites.remove_from_list(self) - self.layer = layer - for i in range(self._sprites.length_of_list()): - if layer < self._sprites.get_sprite(i).layer: - self._sprites.insert_in_list(self, i) - self.inval() - return - self._sprites.append_to_list(self) - self.inval() - - def set_label(self, new_label, i=0): - """ Set the label drawn on the sprite """ - self._extend_labels_array(i) - if type(new_label) is str or type(new_label) is unicode: - # pango doesn't like nulls - self.labels[i] = new_label.replace("\0", " ") - else: - self.labels[i] = str(new_label) - self.inval() - - def set_margins(self, l=0, t=0, r=0, b=0): - """ Set the margins for drawing the label """ - self._margins = [l, t, r, b] - - def _extend_labels_array(self, i): - """ Append to the labels attribute list """ - if self._fd is None: - self.set_font('Sans') - if self._color is None: - self._color = self._sprites.cm.alloc_color('black') - while len(self.labels) < i + 1: - self.labels.append(" ") - self._scale.append(self._scale[0]) - self._rescale.append(self._rescale[0]) - self._horiz_align.append(self._horiz_align[0]) - self._vert_align.append(self._vert_align[0]) - - def set_font(self, font): - """ Set the font for a label """ - self._fd = pango.FontDescription(font) - - def set_label_color(self, rgb): - """ Set the font color for a label """ - self._color = self._sprites.cm.alloc_color(rgb) - - def set_label_attributes(self, scale, rescale=True, horiz_align="center", - vert_align="middle", i=0): - """ Set the various label attributes """ - self._extend_labels_array(i) - self._scale[i] = scale - self._rescale[i] = rescale - self._horiz_align[i] = horiz_align - self._vert_align[i] = vert_align - - def hide(self): - """ Hide a sprite """ - if self._sprites is None: - return - self.inval() - self._sprites.remove_from_list(self) - - def inval(self): - """ Force a region redraw by gtk """ - if self._sprites is None: - return - self._sprites.area.invalidate_rect(self.rect, False) - - def draw(self): - """ Draw the sprite (and label) """ - if self._sprites is None: - return - for i, img in enumerate(self.images): - if isinstance(img, gtk.gdk.Pixbuf): - self._sprites.area.draw_pixbuf(self._sprites.gc, img, 0, 0, - self.rect.x + self._dx[i], - self.rect.y + self._dy[i]) - elif img is not None: - self._sprites.area.draw_drawable(self._sprites.gc, img, 0, 0, - self.rect.x + self._dx[i], - self.rect.y + self._dy[i], - -1, -1) - if len(self.labels) > 0: - self.draw_label() - - def hit(self, pos): - """ Is (x, y) on top of the sprite? """ - x, y = pos - if x < self.rect.x: - return False - if x > self.rect.x + self.rect.width: - return False - if y < self.rect.y: - return False - if y > self.rect.y + self.rect.height: - return False - return True - - def draw_label(self): - """ Draw the label based on its attributes """ - if self._sprites is None: - return - my_width = self.rect.width - self._margins[0] - self._margins[2] - if my_width < 0: - my_width = 0 - my_height = self.rect.height - self._margins[1] - self._margins[3] - for i in range(len(self.labels)): - pl = self._sprites.canvas.create_pango_layout(str(self.labels[i])) - self._fd.set_size(int(self._scale[i] * pango.SCALE)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - if w > my_width: - if self._rescale[i]: - self._fd.set_size( - int(self._scale[i] * pango.SCALE * my_width / w)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - else: - j = len(self.labels[i]) - 1 - while(w > my_width and j > 0): - pl = self._sprites.canvas.create_pango_layout( - "…" + self.labels[i][len(self.labels[i]) - j:]) - self._fd.set_size(int(self._scale[i] * pango.SCALE)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - j -= 1 - if self._horiz_align[i] == "center": - x = int(self.rect.x + self._margins[0] + (my_width - w) / 2) - elif self._horiz_align[i] == 'left': - x = int(self.rect.x + self._margins[0]) - else: # right - x = int(self.rect.x + self.rect.width - w - self._margins[2]) - h = pl.get_size()[1] / pango.SCALE - if self._vert_align[i] == "middle": - y = int(self.rect.y + self._margins[1] + (my_height - h) / 2) - elif self._vert_align[i] == "top": - y = int(self.rect.y + self._margins[1]) - else: # bottom - y = int(self.rect.y + self.rect.height - h - self._margins[3]) - self._sprites.gc.set_foreground(self._color) - self._sprites.area.draw_layout(self._sprites.gc, x, y, pl) - - def label_width(self): - """ Calculate the width of a label """ - max = 0 - for i in range(len(self.labels)): - pl = self._sprites.canvas.create_pango_layout(self.labels[i]) - self._fd.set_size(int(self._scale[i] * pango.SCALE)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - if w > max: - max = w - return max - - def label_safe_width(self): - """ Return maximum width for a label """ - return self.rect.width - self._margins[0] - self._margins[2] - - def label_safe_height(self): - """ Return maximum height for a label """ - return self.rect.height - self._margins[1] - self._margins[3] - - def label_left_top(self): - """ Return the upper-left corner of the label safe zone """ - return(self._margins[0], self._margins[1]) - - def get_pixel(self, pos, i=0): - """ Return the pixl at (x, y) """ - x, y = pos - x = x - self.rect.x - y = y - self.rect.y - if y > self.images[i].get_height() - 1: - return(-1, -1, -1, -1) - try: - array = self.images[i].get_pixels() - if array is not None: - offset = (y * self.images[i].get_width() + x) * 4 - r, g, b, a = ord(array[offset]), ord(array[offset + 1]),\ - ord(array[offset + 2]), ord(array[offset + 3]) - return(r, g, b, a) - else: - return(-1, -1, -1, -1) - except IndexError: - print "Index Error: %d %d" % (len(array), offset) - return(-1, -1, -1, -1) diff --git a/tablock.py b/tablock.py deleted file mode 100644 index 4923ecb..0000000 --- a/tablock.py +++ /dev/null @@ -1,865 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) 2010 Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import gtk -from taconstants import * -from tasprite_factory import SVG, svg_str_to_pixbuf -import sprites -from gettext import gettext as _ - -# -# A class for the list of blocks and everything they share in common -# -class Blocks: - def __init__(self, font_scale_factor = 1): - self.list = [] - self.font_scale_factor = font_scale_factor - - def get_block(self, i): - if i < 0 or i > len(self.list)-1: - return(None) - else: - return(self.list[i]) - - def length_of_list(self): - return(len(self.list)) - - def append_to_list(self,block): - self.list.append(block) - - def remove_from_list(self, block): - if block in self.list: - self.list.remove(block) - - def print_list(self, block_type=None): - for i, block in enumerate(self.list): - if block_type is None or block_type == block.type: - print "%d: %s" % (i, block.name) - - 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 - self.font_scale_factor = scale - - # - # sprite utilities - # - def spr_to_block(self, spr): - for b in self.list: - if spr == b.spr: - return b - return None - -# -# A class for the individual blocks -# -class Block: - def __init__(self, block_list, sprite_list, name, x, y, type='block', - values=[], scale=BLOCK_SCALE, colors=["#FF0000","#A00000"]): - self.spr = None - self.shapes = [None, None] - self.name = name - self.colors = colors - self.scale = scale - self.docks = None - self.connections = None - self.status = None - self.values = [] - self.primitive = None - self.type = type - self.dx = 0 - self.ex = 0 - self.ey = 0 - self._ei = 0 - self._font_size = [6.0, 4.5] - self._image = None - - if OLD_NAMES.has_key(self.name): - self.name = OLD_NAMES[self.name] - - for i in range(len(self._font_size)): - self._font_size[i] *= self.scale*block_list.font_scale_factor - - for v in (values): - self.values.append(v) - - self._new_block_from_factory(sprite_list, x, y) - - if PRIMITIVES.has_key(name): - self.primitive = PRIMITIVES[self.name] - - block_list.append_to_list(self) - - # We may want to highlight a block... - def highlight(self): - if self.spr is not None: - self.spr.set_shape(self.shapes[1]) - - # Or unhighlight it. - def unhighlight(self): - 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): - if not self.spr is not None: - return - 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): - if not self.spr is not 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): - if not self.spr is not None: - return - if self._image is not None: - 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): - if not self.spr is not None: - return - for i in range(len(self._font_size)): - self._font_size[i] /= self.scale - self.dx /= self.scale - self.ex /= self.scale - self.ey /= self.scale - self.scale = scale - for i in range(len(self._font_size)): - self._font_size[i] *= self.scale - self.dx *= self.scale - self.ex *= self.scale - self.ey *= self.scale - self._set_label_attributes() - self.svg.set_scale(self.scale) - self.refresh() - self.spr.draw() - - def refresh(self): - if not self.spr is not None: - return - self._make_block(self.svg) - 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): - if not self.spr is not None: - return - h = self.svg.get_height() - self._ei += 1 - if self.type == 'block' and keep_expanding: - self.svg.set_show(True) - else: - self.svg.set_show(False) - self.refresh() - return self.svg.get_height()-h - - # We may want to grow a block vertically. - def expand_in_y(self, dy): - if not self.spr is not None: - return - self.ey += dy - if self.type == 'block': - self.svg.set_hide(True) - self.svg.set_show(True) - else: - self.svg.set_hide(False) - self.svg.set_show(False) - self.refresh() - - # We may want to grow a block horizontally. - def expand_in_x(self, dx): - if not self.spr is not None: - return - self.ex += dx - if self.type == 'block': - self.svg.set_hide(True) - self.svg.set_show(True) - else: - self.svg.set_hide(False) - self.svg.set_show(False) - self.refresh() - - def reset_x(self): - if not self.spr is not None: - return 0 - dx = -self.ex - self.ex = 0 - self.svg.set_hide(False) - if self.type == 'block': - self.svg.set_show(True) - else: - self.svg.set_show(False) - self.refresh() - return dx - - def reset_y(self): - if not self.spr is not None: - return 0 - dy = -self.ey - self.ey = 0 - self.svg.set_hide(False) - if self.type == 'block': - self.svg.set_show(True) - else: # 'proto' - self.svg.set_show(False) - self.refresh() - return dy - - def get_expand_x_y(self): - if not self.spr is not None: - return(0, 0) - return (self.ex, self.ey) - - def _new_block_from_factory(self, sprite_list, x, y): - self.svg = SVG() - self.svg.set_scale(self.scale) - self.svg.set_gradiant(True) - self.svg.set_innie([False]) - self.svg.set_outie(False) - self.svg.set_tab(True) - self.svg.set_slot(True) - - if self.name in EXPANDABLE and self.type == 'block': - self.svg.set_show(True) - - self._make_block(self.svg) - if sprite_list is not None: - self.spr = sprites.Sprite(sprite_list, x, y, self.shapes[0]) - self._set_margins() - self._set_label_attributes() - - if (self.name == 'number' or self.name == 'string') and\ - len(self.values) > 0: - for i, v in enumerate(self.values): - if v is not None: - self._set_labels(i, str(v)) - elif BLOCK_NAMES.has_key(self.name): - for i, n in enumerate(BLOCK_NAMES[self.name]): - self._set_labels(i, n) - - # Make sure the labels fit. - if self.spr.label_width() > self.spr.label_safe_width(): - self.resize() - - def _set_margins(self): - self.spr.set_margins(self.svg.margins[0], self.svg.margins[1], - self.svg.margins[2], self.svg.margins[3]) - - def _set_label_attributes(self): - if self.name in CONTENT_BLOCKS: - n = len(self.values) - if n == 0: - n = 1 # Force a scale to be set, even if there is no value. - else: - 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) - elif i == 2: # bottom - 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) - - def _set_labels(self, i, label): - self.spr.set_label(label, i) - - def _make_block(self, svg): - self._left = 0 - self._top = 0 - self._right = 0 - self._bottom = 0 - self._set_colors(svg) - self.svg.set_stroke_width(STANDARD_STROKE_WIDTH) - self.svg.clear_docks() - if self.name in BASIC_STYLE: - self._make_basic_style(svg) - elif self.name in BASIC_STYLE_HEAD: - self._make_basic_style_head(svg) - elif self.name in BASIC_STYLE_EXTENDED: - self._make_basic_style(svg, 16) - elif self.name in BASIC_STYLE_HEAD_1ARG: - self._make_basic_style_head_1arg(svg) - elif self.name in BASIC_STYLE_TAIL: - self._make_basic_style_tail(svg) - elif self.name in BASIC_STYLE_1ARG: - self._make_basic_style_1arg(svg) - elif self.name in BASIC_STYLE_2ARG: - self._make_basic_style_2arg(svg) - elif self.name in BASIC_STYLE_VAR_ARG: - self._make_basic_style_var_arg(svg) - elif self.name in BULLET_STYLE: - self._make_bullet_style(svg) - elif self.name in BOX_STYLE: - self._make_box_style(svg) - elif self.name in BOX_STYLE_MEDIA: - self._make_media_style(svg) - elif self.name in NUMBER_STYLE: - self._make_number_style(svg) - elif self.name in NUMBER_STYLE_BLOCK: - self._make_number_style_block(svg) - elif self.name in NUMBER_STYLE_VAR_ARG: - self._make_number_style_var_arg(svg) - elif self.name in NUMBER_STYLE_1ARG: - self._make_number_style_1arg(svg) - elif self.name in NUMBER_STYLE_1STRARG: - self._make_number_style_1strarg(svg) - elif self.name in NUMBER_STYLE_PORCH: - self._make_number_style_porch(svg) - elif self.name in COMPARE_STYLE: - self._make_compare_style(svg) - elif self.name in BOOLEAN_STYLE: - self._make_boolean_style(svg) - elif self.name in NOT_STYLE: - self._make_not_style(svg) - elif self.name in FLOW_STYLE: - self._make_flow_style(svg) - elif self.name in FLOW_STYLE_TAIL: - self._make_flow_style_tail(svg) - elif self.name in FLOW_STYLE_1ARG: - self._make_flow_style_1arg(svg) - elif self.name in FLOW_STYLE_BOOLEAN: - self._make_flow_style_boolean(svg) - elif self.name in FLOW_STYLE_WHILE: - self._make_flow_style_while(svg) - elif self.name in FLOW_STYLE_ELSE: - self._make_flow_style_else(svg) - elif self.name in COLLAPSIBLE_TOP: - self._make_collapsible_style_top(svg) - elif self.name in COLLAPSIBLE_TOP_NO_ARM: - self._make_collapsible_style_top(svg, True) - elif self.name in COLLAPSIBLE_BOTTOM: - self._make_collapsible_style_bottom(svg) - elif self.name in PORTFOLIO_STYLE_2x2: - self._make_portfolio_style_2x2(svg) - elif self.name in PORTFOLIO_STYLE_2x1: - self._make_portfolio_style_2x1(svg) - elif self.name in PORTFOLIO_STYLE_1x1: - self._make_portfolio_style_1x1(svg) - elif self.name in PORTFOLIO_STYLE_1x2: - self._make_portfolio_style_1x2(svg) - else: - self._make_basic_style(svg) - print "WARNING: I don't know how to create a %s block" % (self.name) - - def _set_colors(self, svg): - if BOX_COLORS.has_key(self.name): - self.colors = BOX_COLORS[self.name] - else: - for p in range(len(PALETTES)): - if self.name in PALETTES[p]: - self.colors = COLORS[p] - self.svg.set_colors(self.colors) - - def _make_basic_style(self, svg, extension=0): - self.svg.expand(self.dx+self.ex+extension, self.ey+extension) - self._make_basic_block(svg) - 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.set_slot(False) - self.svg.set_cap(True) - self._make_basic_block(svg) - self.docks = [['unavailable', False, 0, 0], - ['flow', False, self.svg.docks[0][0], - 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.set_innie([True]) - self.svg.set_slot(False) - self.svg.set_cap(True) - self._make_basic_block(svg) - self.docks = [['unavailable', False, 0, 0], - ['string', False, 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_tail(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self.svg.set_tab(False) - self._make_basic_block(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['unavailable', False, 0, 0]] - - def _make_basic_style_1arg(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self.svg.set_innie([True]) - self._make_basic_block(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['flow', False, self.svg.docks[2][0], - 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._make_basic_block(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['number', False, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['flow', False, self.svg.docks[3][0], - self.svg.docks[3][1]]] - - def _make_basic_style_var_arg(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - innie = [True] - for i in range(self._ei): - innie.append(True) - self.svg.set_innie(innie) - self._make_basic_block(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['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]]) - - def _make_bullet_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - innie = [True, True] - for i in range(self._ei): - innie.append(True) - self.svg.set_innie(innie) - self._make_basic_block(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['string', False, self.svg.docks[1][0], - self.svg.docks[1][1], '['], - ['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], ']']) - - def _make_box_style(self, svg): - self.svg.expand(60+self.dx+self.ex, self.ey) - self._make_basic_box(svg) - 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._make_basic_box(svg) - 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.set_outie(True) - self.svg.set_tab(False) - self.svg.set_slot(False) - self._make_basic_block(svg) - """ - NOTE: The "outie" is added last, so the dock order in NUMBER_STYLE - blocks needs to be modified. - """ - self.docks = [['number', True, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['number', False, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]]] - - def _make_number_style_var_arg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - innie = [True] - 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_basic_block(svg) - 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]]) - 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.set_outie(True) - self.svg.set_tab(False) - self.svg.set_slot(False) - self._make_basic_block(svg) - self.docks = [['number', True, self.svg.docks[2][0], - self.svg.docks[2][1], '('], - ['number', False, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['unavailable', False, 0, 0, ')']] - - def _make_number_style_1arg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_innie([True]) - self.svg.set_outie(True) - self.svg.set_tab(False) - self.svg.set_slot(False) - self._make_basic_block(svg) - self.docks = [['number', True, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['number', False, self.svg.docks[0][0], - self.svg.docks[0][1]]] - - def _make_number_style_1strarg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_innie([True]) - self.svg.set_outie(True) - self.svg.set_tab(False) - self.svg.set_slot(False) - self._make_basic_block(svg) - self.docks = [['number', True, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['string', False, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['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.set_outie(True) - self.svg.set_tab(False) - self.svg.set_slot(False) - self.svg.set_porch(True) - self._make_basic_block(svg) - self.docks = [['number', True, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['number', False, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]]] - - def _make_compare_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self._make_boolean_compare(svg) - self.docks = [['bool', True, self.svg.docks[0][0], - self.svg.docks[0][1], '('], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['number', False, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['unavailable', False, 0, 0, ')']] - - def _make_boolean_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self._make_boolean_and_or(svg) - self.docks = [['bool', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['bool', False, self.svg.docks[1][0], - 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._make_boolean_not(svg) - self.docks = [['bool', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['bool', False, self.svg.docks[1][0], - self.svg.docks[1][1]]] - - def _make_flow_style(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(True) - self._make_basic_flow(svg) - 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], '['], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1], ']']] - - def _make_flow_style_tail(self, svg): - self.svg.expand(10+self.dx+self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(False) - self._make_basic_flow(svg) - 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_flow_style_1arg(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(True) - self.svg.set_innie([True]) - self._make_basic_flow(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1], '['], - ['flow', False, self.svg.docks[3][0], - self.svg.docks[3][1], ']']] - - def _make_flow_style_boolean(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(True) - self.svg.set_boolean(True) - self._make_basic_flow(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['bool', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1], '['], - ['flow', False, self.svg.docks[3][0], - self.svg.docks[3][1], ']']] - - def _make_flow_style_while(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(True) - self.svg.set_boolean(True) - self._make_basic_flow(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['bool', False, self.svg.docks[1][0], - self.svg.docks[1][1], '['], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1], ']['], - ['flow', False, self.svg.docks[3][0], - self.svg.docks[3][1], ']']] - - def _make_flow_style_else(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(True) - self.svg.set_else(True) - self.svg.set_boolean(True) - self._make_basic_flow(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['bool', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['flow', False, self.svg.docks[3][0], - self.svg.docks[3][1], '['], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1], ']['], - ['flow', False, self.svg.docks[4][0], - self.svg.docks[4][1], ']']] - - def _make_collapsible_style_top(self, svg, no_arm=False): - self.svg.expand(self.dx+self.ex, self.ey) - self.svg.set_no_arm(no_arm) - self._make_collapsible_top_block(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['number', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1]]] - - def _make_collapsible_style_bottom(self, svg): - self.svg.expand(self.dx+self.ex, self.ey) - self._make_collapsible_bottom_block(svg) - 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.set_slot(True) - self.svg.set_tab(True) - self.svg.set_innie([True, True, False, True]) - self._make_portfolio(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['string', False, self.svg.docks[6][0], - self.svg.docks[6][1]], - ['media', False, self.svg.docks[5][0], - self.svg.docks[5][1]], - ['media', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['media', False, self.svg.docks[4][0], - self.svg.docks[4][1]], - ['media', False, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['flow', False, self.svg.docks[3][0], - 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.set_slot(True) - self.svg.set_tab(True) - self.svg.set_innie([True, True]) - self._make_portfolio(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['string', False, self.svg.docks[4][0], - self.svg.docks[4][1]], - ['media', False, self.svg.docks[3][0], - self.svg.docks[3][1]], - ['media', False, self.svg.docks[1][0], - self.svg.docks[1][1]], - ['flow', False, self.svg.docks[2][0], - 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.set_slot(True) - self.svg.set_tab(True) - self.svg.set_innie([True, True, False, True]) - self.svg.set_draw_innies(False) - self._make_portfolio(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['string', False, self.svg.docks[4][0], - self.svg.docks[4][1]], - ['media', False, self.svg.docks[3][0], - self.svg.docks[3][1]], - ['media', False, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['flow', False, self.svg.docks[1][0], - 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.set_slot(True) - self.svg.set_tab(True) - self.svg.set_innie([True, True]) - self.svg.set_draw_innies(False) - self._make_portfolio(svg) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['string', False, self.svg.docks[3][0], - self.svg.docks[3][1]], - ['media', False, self.svg.docks[2][0], - self.svg.docks[2][1]], - ['flow', False, self.svg.docks[1][0], - self.svg.docks[1][1]]] - - def _make_basic_block(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.basic_block()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.basic_block()) - - def _make_collapsible_top_block(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.sandwich_top()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.sandwich_top()) - - def _make_collapsible_bottom_block(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.sandwich_bottom()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.sandwich_bottom()) - - def _make_basic_box(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.basic_box()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.basic_box()) - - def _make_portfolio(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.portfolio()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.portfolio()) - - def _make_basic_flow(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.basic_flow()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.basic_flow()) - - def _make_boolean_compare(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.boolean_compare()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.boolean_compare()) - - def _make_boolean_and_or(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.boolean_and_or()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.boolean_and_or()) - - def _make_boolean_not(self, svg): - self.shapes[0] = svg_str_to_pixbuf(self.svg.boolean_not()) - self.width = self.svg.get_width() - self.height = self.svg.get_height() - self.svg.set_stroke_width(SELECTED_STROKE_WIDTH) - self.svg.set_stroke_color(SELECTED_COLOR) - self.shapes[1] = svg_str_to_pixbuf(self.svg.boolean_not()) diff --git a/tacanvas.py b/tacanvas.py deleted file mode 100644 index 03f69fc..0000000 --- a/tacanvas.py +++ /dev/null @@ -1,596 +0,0 @@ -#Copyright (c) 2007-8, Playful Invention Company. -#Copyright (c) 2008-10, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import gtk -from math import sin, cos, pi -import pango -import cairo - -from sprites import Sprite -from tasprite_factory import SVG -from tautils import image_to_base64, data_to_string, round_int -from taconstants import CANVAS_LAYER, DEFAULT_TURTLE, BLACK, WHITE - -import logging -_logger = logging.getLogger('turtleart-activity') - - -def wrap100(n): - """ A variant on mod... 101 -> 99; 199 -> 1 """ - n = int(n) - n %= 200 - if n > 99: - n = 199 - n - return n - - -def calc_shade(c, s): - """ Convert a color to the current shade (lightness/darkness). """ - if s < 0: - return int(c * (1 + s * 0.8)) - return int(c + (65536 - c) * s * 0.9) - - -def calc_gray(c, g): - """ Gray is a psuedo saturation calculation. """ - if g == 100: - return c - return int(((c * g) + (32768 * (100 - g))) / 100) - -colors = {} -DEGTOR = 2 * pi / 360 - -color_table = ( - 0xFF0000, 0xFF0D00, 0xFF1A00, 0xFF2600, 0xFF3300, - 0xFF4000, 0xFF4D00, 0xFF5900, 0xFF6600, 0xFF7300, - 0xFF8000, 0xFF8C00, 0xFF9900, 0xFFA600, 0xFFB300, - 0xFFBF00, 0xFFCC00, 0xFFD900, 0xFFE600, 0xFFF200, - 0xFFFF00, 0xE6FF00, 0xCCFF00, 0xB3FF00, 0x99FF00, - 0x80FF00, 0x66FF00, 0x4DFF00, 0x33FF00, 0x1AFF00, - 0x00FF00, 0x00FF0D, 0x00FF1A, 0x00FF26, 0x00FF33, - 0x00FF40, 0x00FF4D, 0x00FF59, 0x00FF66, 0x00FF73, - 0x00FF80, 0x00FF8C, 0x00FF99, 0x00FFA6, 0x00FFB3, - 0x00FFBF, 0x00FFCC, 0x00FFD9, 0x00FFE6, 0x00FFF2, - 0x00FFFF, 0x00F2FF, 0x00E6FF, 0x00D9FF, 0x00CCFF, - 0x00BFFF, 0x00B3FF, 0x00A6FF, 0x0099FF, 0x008CFF, - 0x0080FF, 0x0073FF, 0x0066FF, 0x0059FF, 0x004DFF, - 0x0040FF, 0x0033FF, 0x0026FF, 0x001AFF, 0x000DFF, - 0x0000FF, 0x0D00FF, 0x1A00FF, 0x2600FF, 0x3300FF, - 0x4000FF, 0x4D00FF, 0x5900FF, 0x6600FF, 0x7300FF, - 0x8000FF, 0x8C00FF, 0x9900FF, 0xA600FF, 0xB300FF, - 0xBF00FF, 0xCC00FF, 0xD900FF, 0xE600FF, 0xF200FF, - 0xFF00FF, 0xFF00E6, 0xFF00CC, 0xFF00B3, 0xFF0099, - 0xFF0080, 0xFF0066, 0xFF004D, 0xFF0033, 0xFF001A) - - -class TurtleGraphics: - """ A class for the Turtle graphics canvas """ - - def __init__(self, tw, width, height): - """ Create a sprite to hold the canvas. """ - self.tw = tw - self.width = width - self.height = height - if self.tw.interactive_mode: - self.canvas = Sprite(tw.sprite_list, 0, 0, - gtk.gdk.Pixmap(self.tw.area, self.width, self.height, -1)) - else: - self.canvas = Sprite(None, 0, 0, self.tw.window) - self.canvas.set_layer(CANVAS_LAYER) - (self.cx, self.cy) = self.canvas.get_xy() - self.canvas.type = 'canvas' - self.gc = self.canvas.images[0].new_gc() - self.cm = self.gc.get_colormap() - self.fgrgb = [255, 0, 0] - self.fgcolor = self.cm.alloc_color('red') - self.bgrgb = [255, 248, 222] - self.bgcolor = self.cm.alloc_color('#fff8de') - self.textsize = 48 - self.textcolor = self.cm.alloc_color('blue') - self.tw.active_turtle.show() - self.shade = 0 - self.pendown = True - self.xcor = 0 - self.ycor = 0 - self.heading = 0 - self.pensize = 5 - self.tcolor = 0 - self.color = 0 - self.gray = 100 - self.fill = False - self.poly_points = [] - self.svg = SVG() - self.svg.set_fill_color('none') - self.tw.svg_string = '' - self.clearscreen(False) - - def start_fill(self): - """ Start accumulating points of a polygon to fill. """ - self.fill = True - self.poly_points = [] - - def stop_fill(self): - """ Fill the polygon. """ - self.fill = False - if len(self.poly_points) == 0: - return - minx = self.poly_points[0][0] - miny = self.poly_points[0][1] - maxx = minx - maxy = miny - for p in self.poly_points: - if p[0] < minx: - minx = p[0] - elif p[0] > maxx: - maxx = p[0] - if p[1] < miny: - miny = p[1] - elif p[1] > maxy: - maxy = p[1] - w = maxx - minx - h = maxy - miny - self.canvas.images[0].draw_polygon(self.gc, True, self.poly_points) - self.invalt(minx - self.pensize * self.tw.coord_scale / 2 - 3, - miny - self.pensize * self.tw.coord_scale / 2 - 3, - w + self.pensize * self.tw.coord_scale + 6, - h + self.pensize * self.tw.coord_scale + 6) - self.poly_points = [] - - def clearscreen(self, share=True): - """Clear the canvas and reset most graphics attributes to defaults.""" - rect = gtk.gdk.Rectangle(0, 0, self.width, self.height) - self.gc.set_foreground(self.bgcolor) - self.canvas.images[0].draw_rectangle(self.gc, True, *rect) - self.invalt(0, 0, self.width, self.height) - self.setpensize(5, share) - self.setgray(100, share) - self.setcolor(0, share) - self.settextcolor(70) - self.settextsize(48) - self.setshade(50, share) - self.setpen(True, share) - for turtle_key in iter(self.tw.turtles.dict): - self.set_turtle(turtle_key) - self.tw.active_turtle.set_color(0) - self.tw.active_turtle.set_shade(50) - self.tw.active_turtle.set_pen_size(5) - self.tw.active_turtle.set_pen_state(True) - self.seth(0, share) - self.setxy(0, 0, share) - self.set_turtle(DEFAULT_TURTLE) - self.tw.svg_string = '' - self.svg.reset_min_max() - self.fill = False - self.poly_points = [] - - def forward(self, n, share=True): - """ Move the turtle forward.""" - nn = n * self.tw.coord_scale - self.gc.set_foreground(self.fgcolor) - oldx, oldy = self.xcor, self.ycor - try: - self.xcor += nn * sin(self.heading * DEGTOR) - self.ycor += nn * cos(self.heading * DEGTOR) - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - if self.pendown: - self.draw_line(oldx, oldy, self.xcor, self.ycor) - self.move_turtle() - 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.line_to(self.xcor, - self.height / 2 - self.ycor) - self.tw.svg_string += "\"\n" - 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)]))) - - def seth(self, n, share=True): - """ Set the turtle heading. """ - try: - self.heading = n - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.heading %= 360 - self.turn_turtle() - if self.tw.sharing() and share: - self.tw.activity.send_event("r|%s" % \ - (data_to_string([self.tw.nick, round_int(self.heading)]))) - - def right(self, n, share=True): - """ Rotate turtle clockwise """ - try: - self.heading += n - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.heading %= 360 - self.turn_turtle() - if self.tw.sharing() and share: - self.tw.activity.send_event("r|%s" % \ - (data_to_string([self.tw.nick, round_int(self.heading)]))) - - def arc(self, a, r, share=True): - """ Draw an arc """ - self.gc.set_foreground(self.fgcolor) - rr = r * self.tw.coord_scale - try: - if a < 0: - self.larc(-a, rr) - else: - self.rarc(a, rr) - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.move_turtle() - if self.tw.sharing() and share: - self.tw.activity.send_event("a|%s" % \ - (data_to_string([self.tw.nick, [round_int(a), round_int(r)]]))) - - def rarc(self, a, r): - """ draw a clockwise arc """ - if r < 0: - r = -r - a = -a - s = 0 - else: - s = 1 - 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) - w = int(2 * r) - h = w - if self.pendown: - self.canvas.images[0].draw_arc(self.gc, False, x, y, w, h, - int(180 - self.heading - a) * 64, int(a) * 64) - self.invalt(x - self.pensize * self.tw.coord_scale / 2 - 3, - y - self.pensize * self.tw.coord_scale / 2 - 3, - w + self.pensize * self.tw.coord_scale + 6, - h + self.pensize * self.tw.coord_scale + 6) - self.right(a, False) - 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.arc_to(self.xcor, - self.height / 2 - self.ycor, - r, a, 0, s) - self.tw.svg_string += "\"\n" - self.tw.svg_string += self.svg.style() - - def larc(self, a, r): - """ draw a counter-clockwise arc """ - if r < 0: - r = -r - a = -a - s = 1 - else: - s = 0 - 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) - w = int(2 * r) - h = w - if self.pendown: - self.canvas.images[0].draw_arc(self.gc, False, x, y, w, h, - int(360 - self.heading) * 64, - int(a) * 64) - self.invalt(x - self.pensize * self.tw.coord_scale / 2 - 3, - y - self.pensize * self.tw.coord_scale / 2 - 3, - w + self.pensize * self.tw.coord_scale + 6, - h + self.pensize * self.tw.coord_scale + 6) - self.right(-a, False) - 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.arc_to(self.xcor, - self.height / 2-self.ycor, - r, a, 0, s) - self.tw.svg_string += "\"\n" - self.tw.svg_string += self.svg.style() - - def setxy(self, x, y, share=True): - """ Move turtle to position x,y """ - x *= self.tw.coord_scale - y *= self.tw.coord_scale - try: - self.xcor, self.ycor = x, y - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.move_turtle() - if self.tw.sharing() and share: - self.tw.activity.send_event("x|%s" % \ - (data_to_string([self.tw.nick, [round_int(x), round_int(y)]]))) - - def setpensize(self, ps, share=True): - """ Set the pen size """ - try: - if ps < 0: - ps = 0 - self.pensize = ps - except TypeError, ValueError: - _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), - 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: - self.tw.activity.send_event("w|%s" % \ - (data_to_string([self.tw.nick, round_int(ps)]))) - - def setcolor(self, c, share=True): - """ Set the pen color """ - try: - self.color = c - self.tcolor = c - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.tw.active_turtle.set_color(c) - self.set_fgcolor() - self.set_textcolor() - if self.tw.sharing() and share: - self.tw.activity.send_event("c|%s" % \ - (data_to_string([self.tw.nick, round_int(c)]))) - - def setgray(self, g, share=True): - """ Set the gray level """ - try: - self.gray = g - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - if self.gray < 0: - self.gray = 0 - if self.gray > 100: - self.gray = 100 - self.set_fgcolor() - self.set_textcolor() - self.tw.active_turtle.set_gray(self.gray) - if self.tw.sharing() and share: - self.tw.activity.send_event("g|%s" % \ - (data_to_string([self.tw.nick, round_int(self.gray)]))) - - def settextcolor(self, c): - """ Set the text color """ - try: - self.tcolor = c - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.set_textcolor() - - def settextsize(self, c): - """ Set the text size """ - try: - self.tw.textsize = c - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - - def setshade(self, s, share=True): - """ Set the color shade """ - try: - self.shade = s - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - self.tw.active_turtle.set_shade(s) - self.set_fgcolor() - self.set_textcolor() - if self.tw.sharing() and share: - self.tw.activity.send_event("s|%s" % \ - (data_to_string([self.tw.nick, round_int(s)]))) - - def fillscreen(self, c, s): - """ Fill screen with color/shade and reset to defaults """ - oldc, olds = self.color, self.shade - self.setcolor(c, False) - self.setshade(s, False) - rect = gtk.gdk.Rectangle(0, 0, self.width, self.height) - self.gc.set_foreground(self.fgcolor) - self.bgrgb = self.fgrgb[:] - self.canvas.images[0].draw_rectangle(self.gc, True, *rect) - self.invalt(0, 0, self.width, self.height) - self.setcolor(oldc, False) - self.setshade(olds, False) - self.tw.svg_string = '' - self.svg.reset_min_max() - self.fill = False - self.poly_points = [] - - def set_fgcolor(self): - """ Set the foreground color """ - if self.color == WHITE or self.shade == WHITE: - r = 0xFF00 - g = 0xFF00 - b = 0xFF00 - elif self.color == BLACK or self.shade == BLACK: - r = 0x0000 - g = 0x0000 - b = 0x0000 - else: - sh = (wrap100(self.shade) - 50) / 50.0 - rgb = color_table[wrap100(self.color)] - r = (rgb >> 8) & 0xff00 - r = calc_gray(r, self.gray) - r = calc_shade(r, sh) - g = rgb & 0xff00 - g = calc_gray(g, self.gray) - g = calc_shade(g, sh) - b = (rgb << 8) & 0xff00 - b = calc_gray(b, self.gray) - b = calc_shade(b, sh) - self.fgrgb = [r >> 8, g >> 8, b >> 8] - self.fgcolor = self.cm.alloc_color(r, g, b) - self.svg.set_stroke_color("#%02x%02x%02x" % (self.fgrgb[0], - self.fgrgb[1], - self.fgrgb[2])) - - def set_textcolor(self): - """ Set the text color """ - sh = (wrap100(self.shade) - 50) / 50.0 - rgb = color_table[wrap100(self.tcolor)] - r, g, b = (rgb >> 8) & 0xff00, rgb & 0xff00, (rgb << 8) & 0xff00 - r, g, b = calc_shade(r, sh), calc_shade(g, sh), calc_shade(b, sh) - self.tw.textcolor = self.cm.alloc_color(r, g, b) - - def setpen(self, bool, share=True): - """ Lower or raise the pen """ - self.pendown = bool - if self.tw.sharing() and share: - self.tw.activity.send_event("p|%s" % \ - (data_to_string([self.tw.nick, bool]))) - - def draw_pixbuf(self, pixbuf, a, b, x, y, w, h, path): - """ Draw a pixbuf """ - w *= self.tw.coord_scale - h *= self.tw.coord_scale - self.canvas.images[0].draw_pixbuf(self.gc, pixbuf, a, b, x, y) - self.invalt(x, y, w, h) - if self.tw.saving_svg: - 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)) - else: - self.tw.svg_string += self.svg.image(x - self.width / 2, - y, w, h, path) - - def draw_text(self, label, x, y, size, w): - """ Draw text """ - w *= self.tw.coord_scale - self.gc.set_foreground(self.tw.textcolor) - fd = pango.FontDescription('Sans') - try: - fd.set_size(int(size * self.tw.coord_scale) * pango.SCALE) - except TypeError, ValueError: - _logger.debug("bad value sent to %s" % (__name__)) - return - if self.tw.interactive_mode: - if type(label) == str or type(label) == unicode: - 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: - pl = self.tw.window.create_pango_layout(str(label)) - pl.set_font_description(fd) - pl.set_width(int(w) * pango.SCALE) - self.canvas.images[0].draw_layout(self.gc, int(x), int(y), pl) - w, h = pl.get_pixel_size() - self.invalt(x, y, w, h) - else: # pixmap doesn't support pango - 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] - context.set_source_rgb(0, 0, 0) - context.move_to(x, y + h) - context.show_text(message) - - if self.tw.saving_svg and self.pendown: - self.tw.svg_string += self.svg.text(x - self.width / 2, - y + size, - size, w, label) - - def draw_line(self, x1, y1, x2, y2): - """ Draw a line """ - x1, y1 = self.width / 2 + int(x1), self.height / 2 - int(y1) - x2, y2 = self.width / 2 + int(x2), self.height / 2 - int(y2) - if x1 < x2: - minx, maxx = x1, x2 - else: - minx, maxx = x2, x1 - if y1 < y2: - miny, maxy = y1, y2 - else: - miny, maxy = y2, y1 - w, h = maxx-minx, maxy-miny - self.canvas.images[0].draw_line(self.gc, x1, y1, x2, y2) - if self.fill and self.poly_points == []: - self.poly_points.append((x1, y1)) - if self.fill: - self.poly_points.append((x2, y2)) - self.invalt(minx - self.pensize * self.tw.coord_scale / 2 - 3, - miny - self.pensize * self.tw.coord_scale / 2 - 3, - w + self.pensize * self.tw.coord_scale + 6, - h + self.pensize * self.tw.coord_scale + 6) - - def turn_turtle(self): - """ Change the orientation of the turtle """ - self.tw.active_turtle.set_heading(self.heading) - - 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 - 28, self.cy + y - 30)) - - 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) - - def set_turtle(self, k, colors=None): - """ Select the current turtle and associated pen status """ - if not self.tw.turtles.dict.has_key(k): - # if it is a new turtle, start it in the center of the screen - self.tw.active_turtle = self.tw.turtles.get_turtle(k, True, colors) - self.seth(0, False) - self.setxy(0, 0, False) - self.tw.active_turtle.set_pen_state(True) - self.tw.active_turtle = self.tw.turtles.get_turtle(k, False) - tx, ty = self.tw.active_turtle.get_xy() - self.xcor = -self.width / 2 + tx + 28 - self.ycor = self.height / 2 - ty - 30 - 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) - self.setshade(self.tw.active_turtle.get_shade(), False) - self.setpensize(self.tw.active_turtle.get_pen_size(), False) - self.setpen(self.tw.active_turtle.get_pen_state(), False) - - def svg_close(self): - """ Close current SVG graphic """ - if self.tw.svg_string == '': - 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.bgrgb[0], self.bgrgb[1], self.bgrgb[2])), - self.tw.svg_string, self.svg.footer()) diff --git a/taconstants.py b/taconstants.py deleted file mode 100644 index fb4f191..0000000 --- a/taconstants.py +++ /dev/null @@ -1,1065 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) 2010, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -""" -This file contains the constants that by-in-large determine the -behavior of Turtle Art. Notably, the block palettes are defined -below. If you want to add a new block to Turtle Art, it is generally a -matter of modifying some tables below and then adding the primitive to -talogo.py. For example, if we want to add a new turtle command, -'uturn', we'd make the following changes: - -(1) We'd add 'uturn' to the PALETTES list of lists: - -PALETTES = [['forward', 'back', 'clean', 'left', 'right', 'uturn', 'show', - 'seth', 'setxy', 'heading', 'xcor', 'ycor', 'setscale', - 'arc', 'scale'], - ['penup','pendown', 'setpensize', 'fillscreen', 'pensize',... - -(2) Then we'd add it to one of the block-style definitions. Since it takes -no arguments, we'd add it here: - -BASIC_STYLE = ['clean', 'penup', 'pendown', 'stack1', 'stack2', 'vspace', - 'hideblocks', 'showblocks', 'clearheap', 'printheap', 'kbinput', 'uturn'] - -(3) Then we give it a name (Note the syntax _('string to be -translated') used by the language-internationalization system; also -note that the name is an array, as some blocks contain multiple -strings.): - -BLOCK_NAMES = { -... - 'uturn':[_('u-turn')], -... - } - -(4) and a help-menu entry: - -HELP_STRINGS = { -... - 'uturn':_('change the heading of the turtle 180 degrees'), -... - } - -(5) Next, we need to define it as a primitive for the Logo command -parser (generally just the same name): - -PRIMITIVES = { -... - 'uturn':'uturn', -... - } - -(6) Since there are no default arguments, we don't need to do anything -else here. But we do need to define the actual function in talogo.py - -DEFPRIM = { -... - 'uturn':[0, lambda self: self.tw.canvas.seth(self.tw.canvas.heading+180)], -... - } - -That's it. When you next run Turtle Art, you will have a 'uturn' block -on the Turtle Palette. - -Adding a new palette is simply a matter of: (1) adding an additional -entry to PALETTE_NAMES; (2) new list of blocks to PALETTES; and (3) an -additional entry in COLORS. However you will have to: (4) create icons -for the palette-selector buttons. These are kept in the icons -subdirectory. You need two icons: yourpalettenameoff.svg and -yourpalettenameon.svg, where yourpalettename is the same string as the -entry you added to the PALETTE_NAMES list. Note that the icons should -be the same size (55x55) as the others. This is the default icon size -for Sugar toolbars. - -""" - -from gettext import gettext as _ - -# -# Sprite layers -# - -HIDE_LAYER = 100 -CANVAS_LAYER = 500 -OVERLAY_LAYER = 525 -TURTLE_LAYER = 550 -BLOCK_LAYER = 600 -CATEGORY_LAYER = 700 -TAB_LAYER = 710 -STATUS_LAYER = 900 -TOP_LAYER = 1000 - -# -# Block-palette categories -# - -PALETTE_NAMES = ['turtle', 'pen', 'colors', 'numbers', 'flow', 'blocks', - 'extras', 'portfolio', 'trash'] - -PALETTES = [['clean', 'forward', 'back', 'show', 'left', 'right', - 'seth', 'setxy', 'heading', 'xcor', 'ycor', 'setscale', - 'arc', 'scale', 'leftpos', 'toppos', 'rightpos', - 'bottompos'], - ['penup','pendown', 'setpensize', 'fillscreen', 'pensize', - 'setcolor', 'setshade', 'setgray', 'color', 'shade', - 'gray', 'startfill', 'stopfill' ], - [ 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple', - 'white', 'black'], - ['plus2', 'minus2', 'product2', - 'division2', 'identity2', 'remainder2', 'sqrt', 'random', - 'number', 'greater2', 'less2', 'equal2', 'not', 'and2', 'or2'], - ['wait', 'forever', 'repeat', 'if', 'ifelse', 'while', 'until', - 'hspace', 'vspace', 'stopstack'], - ['hat1', 'stack1', 'hat', 'hat2', 'stack2', 'stack', - 'storeinbox1', 'storeinbox2', 'string', 'box1', 'box2', 'box', - 'storein', 'start'], - ['kbinput', 'push', 'printheap', 'keyboard', 'pop', 'clearheap', - 'myfunc1arg', 'userdefined', 'addturtle', 'comment', 'print', - 'cartesian', 'width', 'height', 'polar', 'sandwichtop', - 'sandwichbottom'], - ['journal', 'audio', 'description', 'hideblocks', 'showblocks', - 'fullscreen', 'savepix', 'savesvg', 'picturelist', - 'picture1x1a', 'picture1x1', 'picture2x2', 'picture2x1', - 'picture1x2'], - ['empty', 'restoreall']] - -# -# Block-style attributes -# - -COLORS = [["#00FF00","#00A000"], ["#00FFFF","#00A0A0"], ["#00FFFF","#00A0A0"], - ["#FF00FF","#A000A0"], ["#FFC000","#A08000"], ["#FFFF00","#A0A000"], - ["#FF0000","#A00000"], ["#0000FF","#0000A0"], ["#FFFF00","#A0A000"]] - -BOX_COLORS = {'red':["#FF0000","#A00000"],'orange':["#FFD000","#AA8000"], - 'yellow':["#FFFF00","#A0A000"],'green':["#00FF00","#008000"], - 'cyan':["#00FFFF","#00A0A0"],'blue':["#0000FF","#000080"], - 'purple':["#FF00FF","#A000A0"], 'white':["#FFFFFF", "#A0A0A0"], - 'black':["#000000", "#000000"]} - -# -# Misc. parameters -# -PALETTE_HEIGHT = 120 -PALETTE_WIDTH = 175 -SELECTOR_WIDTH = 55 -ICON_SIZE = 55 -SELECTED_COLOR = "#0000FF" -SELECTED_STROKE_WIDTH = 1.0 -STANDARD_STROKE_WIDTH = 1.0 -BLOCK_SCALE = 2.0 -PALETTE_SCALE = 1.5 -DEFAULT_TURTLE = 1 -HORIZONTAL_PALETTE = 0 -VERTICAL_PALETTE = 1 -BLACK = 0xFFFFFFFF -WHITE = 0xFFFFFFFE - -# -# Block-style definitions -# -BASIC_STYLE_HEAD = ['start', 'hat1', 'hat2', 'restore', 'restoreall'] -BASIC_STYLE_HEAD_1ARG = ['hat'] -BASIC_STYLE_TAIL = ['stopstack', 'empty'] -BASIC_STYLE = ['clean', 'penup', 'pendown', 'stack1', 'stack2', 'vspace', - 'hideblocks', 'showblocks', 'clearheap', 'printheap', 'kbinput', - 'fullscreen', 'sandwichcollapsed', 'cartesian', 'polar', 'startfill', - 'stopfill'] -BASIC_STYLE_EXTENDED = ['picturelist', 'picture1x1', 'picture2x2', - 'picture2x1', 'picture1x2', 'picture1x1a'] -BASIC_STYLE_1ARG = ['forward', 'back', 'left', 'right', 'seth', 'show', 'image', - 'setscale', 'setpensize', 'setcolor', 'setshade', 'print', 'showaligned', - 'settextsize', 'settextcolor', 'print', 'wait', 'storeinbox1', 'savepix', - 'storeinbox2', 'wait', 'stack', 'push', 'nop', 'addturtle', 'comment', - 'savesvg', 'setgray'] -BASIC_STYLE_VAR_ARG = ['userdefined', 'userdefined2args', 'userdefined3args'] -BULLET_STYLE = ['templatelist', 'list'] -BASIC_STYLE_2ARG = ['arc', 'setxy', 'fillscreen', 'storein', 'write'] -BOX_STYLE = ['number', 'xcor', 'ycor', 'heading', 'pensize', 'color', 'shade', - 'textcolor', 'textsize', 'box1', 'box2', 'string', 'leftpos', 'scale', - 'toppos', 'rightpos', 'bottompos', 'width', 'height', 'pop', 'keyboard', - 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple', 'white', - 'black', 'titlex', 'titley', 'leftx', 'topy', 'rightx', 'bottomy', - 'volume', 'pitch', 'voltage', 'resistance', 'gray'] -BOX_STYLE_MEDIA = ['description', 'audio', 'journal'] -NUMBER_STYLE = ['plus2', 'product2', 'myfunc'] -NUMBER_STYLE_VAR_ARG = ['myfunc1arg', 'myfunc2arg', 'myfunc3arg'] -NUMBER_STYLE_BLOCK = ['random'] -NUMBER_STYLE_PORCH = ['minus2', 'division2', 'remainder2'] -NUMBER_STYLE_1ARG = ['sqrt', 'identity2'] -NUMBER_STYLE_1STRARG = ['box'] -COMPARE_STYLE = ['greater2', 'less2', 'equal2'] -BOOLEAN_STYLE = ['and2', 'or2'] -NOT_STYLE = ['not'] -FLOW_STYLE = ['forever'] -FLOW_STYLE_TAIL = ['hspace'] -FLOW_STYLE_1ARG = ['repeat'] -FLOW_STYLE_BOOLEAN = ['if', 'while', 'until'] -FLOW_STYLE_WHILE = ['while2'] -FLOW_STYLE_ELSE = ['ifelse'] -COLLAPSIBLE_TOP = ['sandwichtop'] -COLLAPSIBLE_TOP_NO_ARM = ['sandwichtop2'] -COLLAPSIBLE_BOTTOM = ['sandwichbottom'] - -# Depreciated block styles -PORTFOLIO_STYLE_2x2 = ['template2x2'] -PORTFOLIO_STYLE_1x1 = ['template1x1', 'template1x1a'] -PORTFOLIO_STYLE_2x1 = ['template2x1'] -PORTFOLIO_STYLE_1x2 = ['template1x2'] - -# -# Blocks that are expandable -# -EXPANDABLE = ['vspace', 'hspace', 'templatelist', 'list', 'identity2', - 'myfunc1arg', 'myfunc2arg', 'myfunc3arg', 'userdefined', - 'userdefined2args', 'userdefined3args'] - -# -# Blocks that are 'collapsible' -# -COLLAPSIBLE = ['sandwichbottom', 'sandwichcollapsed'] - -# -# Depreciated block styles that need dock adjustments -# -OLD_DOCK = ['and', 'or', 'plus', 'minus', 'division', 'product', 'remainder'] - -# -# Blocks that contain media -# -CONTENT_BLOCKS = ['number', 'string', 'description', 'audio', 'journal'] - -# -# These blocks get a special skin -# -BLOCKS_WITH_SKIN = ['journal', 'audio', 'description', 'nop', 'userdefined', - 'userdefined2args', 'userdefined3args'] - -PYTHON_SKIN = ['nop', 'userdefined', 'userdefined2args', 'userdefined3args'] - -# -# Block-name dictionary used for labels -# -BLOCK_NAMES = { - 'addturtle':[_('turtle')], - 'and2':[_('and')], - 'arc':[_('arc'), _('angle'), _('radius')], - 'audio':[' '], - 'back':[_('back')], - 'black':[_('black')], - 'blue':[_('blue')+' = 70'], - 'bottompos':[_('bottom')], - 'bottomy':[_('picture bottom')], - 'box':[_('box')], - 'box1':[_('box 1')], - 'box2':[_('box 2')], - 'cartesian':[_('Cartesian')], - 'clean':[_(' clean ')], - 'clearheap':[_('empty heap')], - 'color':[_('color')], - 'comment':[_('comment')], - 'cyan':[_('cyan')+' = 50'], - 'decription':[' '], - 'division2':['/'], - 'empty':[_('empty trash')], - 'equal2':['='], - 'fillscreen':[_('fill screen'), _('color'), _('shade')], - 'forever':[_('forever')], - 'forward':[_('forward')], - 'fullscreen':[_('full screen')], - 'gray':[_('gray')], - 'greater2':[">"], - 'green':[_('green')+' = 30'], - 'hat':[_('action')], - 'hat1':[_('action 1')], - 'hat2':[_('action 2')], - 'heading':[_('heading')], - 'height':[_('height')], - 'hideblocks':[_('hide blocks')], - 'hspace':[' '], - 'identity2':['←'], - 'if':[' ', _('if'), _('then')], - 'ifelse':[' ', _('if'), _('then else')], - 'image':[_('show')], - 'journal':[' '], - 'kbinput':[_('query keyboard')], - 'keyboard':[_('keyboard')], - 'left':[_('left')], - 'leftpos':[_('left')], - 'leftx':[_('picture left')], - 'less2':['<'], - 'list':['list'], - 'minus2':['–'], - 'myfunc':[_('Python'), 'f(x)', 'x'], - 'myfunc1arg':[_('Python'), 'f(x)', 'x'], - 'myfunc2arg':[_('Python'), 'f(x,y)', ' '], - 'myfunc3arg':[_('Python'), 'f(x,y,z)', ' '], - 'nop':[_(' ')], - 'not':[_('not')], - 'number':['100'], - 'orange':[_('orange')+' = 10'], - 'or2':[_('or')], - 'pendown':[_('pen down')], - 'pensize':[_('pen size')], - 'penup':[_('pen up')], - 'picturelist':[' '], - 'picture1x1':[' '], - 'picture1x1a':[' '], - 'picture2x2':[' '], - 'picture2x1':[' '], - 'picture1x2':[' '], - 'pitch':[_('pitch')], - 'plus2':['+'], - 'polar':[_('polar')], - 'pop':[_('pop')], - 'printheap':[_('show heap')], - 'print':[_('print')], - 'product2':['×'], - 'purple':[_('purple')+' = 90'], - 'push':[_('push')], - 'random':[_('random'), _('min'), _('max')], - 'red':[_('red')+' = 0'], - 'remainder2':[_('mod')], - 'repeat':[' ',_('repeat')], - 'resistance':[_('resistance')], - 'restore':[_('restore last')], - 'restoreall':[_('restore all')], - 'right':[_('right')], - 'rightpos':[_('right')], - 'rightx':[_('picture right')], - 'savepix':[_('save picture')], - 'savesvg':[_('save SVG')], - 'sandwichbottom':[' '], - 'sandwichcollapsed':[_('click to open')], - 'sandwichtop':[_('top of stack')], - 'sandwichtop2':[_('top of stack')], - 'scale':[_('scale')], - 'setcolor':[_('set color')], - 'setgray':[_('set gray')], - 'seth':[_('set heading')], - 'setpensize':[_('set pen size')], - 'setscale':[_('set scale')], - 'setshade':[_('set shade')], - 'settextcolor':[_('set text color')], - 'settextsize':[_('set text size')], - 'setxy':[_('set xy'), _('x'), _('y')], - 'shade':[_('shade')], - 'show':[_('show')], - 'showblocks':[_('show blocks')], - 'showaligned':[_('show aligned')], - 'sqrt':['√'], - 'stack':[_('action')], - 'stack1':[_('action 1')], - 'stack2':[_('action 2')], - 'start':[_('start')], - 'startfill':[_('start fill')], - 'stopfill':[_('end fill')], - 'stopstack':[_('stop action')], - 'storein':[_('store in'), _('box'), _('value')], - 'storeinbox1':[_('store in box 1')], - 'storeinbox2':[_('store in box 2')], - 'string':[_('text')], - 'template1x1':[' '], - 'template1x1a':[' '], - 'template1x2':[' '], - 'template2x1':[' '], - 'template2x2':[' '], - 'templatelist':[' '], - 'textsize':[_('text size')], - 'titlex':[_('title x')], - 'titley':[_('title y')], - 'toppos':[_('top')], - 'topy':[_('picture top')], - 'turtle':[_('turtle')], - 'until':[_('until')], - 'userdefined':[_(' ')], - 'userdefined2args':[_(' ')], - 'userdefined3args':[_(' ')], - 'voltage':[_('voltage')], - 'volume':[_('volume')], - 'vspace':[' '], - 'wait':[_('wait')], - 'while':[_('while')], - 'while2':[_('while')], - 'white':[_('white')], - 'width':[_('width')], - 'write':[_('write')], - 'xcor':[_('xcor')], - 'ycor':[_('ycor')], - 'yellow':[_('yellow')+' = 20']} - -# -# Logo primitives -# - -PRIMITIVES = { - 'addturtle':'turtle', - 'and2':'and', - 'arc':'arc', - 'back':'back', - 'black':'black', - 'blue':'blue', - 'bottompos':'bpos', - 'bottomy':'boty', - 'box1':'box1', - 'box2':'box2', - 'box':'box', - 'cartesian':'cartesian', - 'clean':'clean', - 'clearheap':'clearheap', - 'color':'color', - 'comment':'comment', - 'cyan':'cyan', - 'division2':'division', - 'equal2':'equal?', - 'fillscreen':'fillscreen', - 'forever':'forever', - 'forward':'forward', - 'fullscreen':'fullscreen', - 'gray':'gray', - 'greater2':'greater?', - 'green':'green', - 'hat':'nop3', - 'hat1':'nop1', - 'hat2':'nop2', - 'heading':'heading', - 'height':'vres', - 'hideblocks':'hideblocks', - 'hspace':'nop', - 'identity2':'id', - 'if':'if', - 'ifelse':'ifelse', - 'image':'show', - 'kbinput':'kbinput', - 'keyboard':'keyboard', - 'left':'left', - 'leftpos':'lpos', - 'leftx':'leftx', - 'less2':'less?', - 'list':'bulletlist', - 'minus2':'minus', - 'myfunc':'myfunction', - 'myfunc1arg':'myfunction', - 'myfunc2arg':'myfunction2', - 'myfunc3arg':'myfunction3', - 'nop':'userdefined', - 'not':'not', - 'orange':'orange', - 'or2':'or', - 'pendown':'pendown', - 'pensize':'pensize', - 'penup':'penup', - 'pitch':'pitch', - 'plus2':'plus', - 'polar':'polar', - 'pop':'pop', - 'printheap':'printheap', - 'print':'print', - 'product2':'product', - 'purple':'purple', - 'push':'push', - 'random':'random', - 'red':'red', - 'remainder2':'mod', - 'repeat':'repeat', - 'resistance':'resistance', - 'right':'right', - 'rightpos':'rpos', - 'rightx':'rightx', - 'sandwichtop':'comment', - 'sandwichtop2':'comment', - 'sandwichbottom':'nop', - 'sandwichcollapsed':'nop', - 'savepix':'savepix', - 'savesvg':'savesvg', - 'scale':'scale', - 'setcolor':'setcolor', - 'setgray':'setgray', - 'seth':'seth', - 'setpensize':'setpensize', - 'setscale':'setscale', - 'setshade':'setshade', - 'settextsize':'settextsize', - 'settextcolor':'settextcolor', - 'setxy':'setxy', - 'shade':'shade', - 'show':'show', - 'showblocks':'showblocks', - 'showaligned':'showaligned', - 'sqrt':'sqrt', - 'stack':'stack', - 'stack1':'stack1', - 'stack2':'stack2', - 'start':'start', - 'startfill':'startfill', - 'stopfill':'stopfill', - 'stopstack':'stopstack', - 'storein':'storeinbox', - 'storeinbox1':'storeinbox1', - 'storeinbox2':'storeinbox2', - 'template1x1':'t1x1', - 'template1x1a':'t1x1a', - 'template1x2':'t1x2', - 'template2x1':'t2x1', - 'template2x2':'t2x2', - 'templatelist':'bullet', - 'textsize':'textsize', - 'titlex':'titlex', - 'titley':'titley', - 'toppos':'tpos', - 'topy':'topy', - 'userdefined':'userdefined', - 'userdefined2args':'userdefined2', - 'userdefined3args':'userdefined3', - 'voltage':'voltage', - 'volume':'volume', - 'vspace':'nop', - 'wait':'wait', - 'while2':'while', - 'white':'white', - 'width':'hres', - 'write':'write', - 'xcor':'xcor', - 'ycor':'ycor', - 'yellow':'yellow'} - -# -# block default values -# - -DEFAULTS = { - 'addturtle':[1], - 'arc':[90, 100], - 'audio':[None], - 'back':[100], - 'box':[_('my box')], - 'comment':[_('comment')], - 'description':[None], - 'fillscreen':[60, 80], - 'forever':[None, 'vspace'], - 'forward':[100], - 'hat':[_('action')], - 'if':[None, None, 'vspace'], - 'ifelse':[None, 'vspace', None, 'vspace'], - 'journal':[None], - 'left':[90], - 'list':['∙ ', '∙ '], - 'media':[None], - 'myfunc':['x', 100], - 'myfunc1arg':['x', 100], - 'myfunc2arg':['x+y', 100, 100], - 'myfunc3arg':['x+y+z', 100, 100, 100], - 'nop':[100], - 'number':[100], - 'random':[0, 100], - 'repeat':[4, None, 'vspace'], - 'right':[90], - 'sandwichtop':[_('label')], - 'sandwichtop2':[_('label')], - 'savepix':[_('picture name')], - 'savesvg':[_('picture name')], - 'setcolor':[0], - 'setgray':[100], - 'seth':[0], - 'setpensize':[5], - 'setscale':[33], - 'setshade':[50], - 'settextsize':[48], - 'settextcolor':[0], - 'setxy':[0, 0], - 'show':[_('text')], - 'showaligned':[_('text')], - 'stack':[_('action')], - 'storeinbox1':[100], - 'storeinbox2':[100], - 'storein':[_('my box'), 100], - 'string':[_('text')], - 'template1x1':[_('Title'), 'None'], - 'template1x1a':[_('Title'), 'None'], - 'template1x2':[_('Title'), 'None', 'None'], - 'template2x1':[_('Title'), 'None', 'None'], - 'template2x2':[_('Title'), 'None', 'None', 'None', 'None'], - 'templatelist':[_('Title'), '∙ '], - 'userdefined':[100], - 'userdefined2args':[100,100], - 'userdefined3args':[100,100,100], - 'wait':[1], - 'write':[_('text'), 32]} - -# -# Blocks that can interchange strings and numbers for their arguments -# -STRING_OR_NUMBER_ARGS = ['plus2', 'equal2', 'less2', 'greater2', 'box', - 'template1x1', 'template1x2', 'template2x1', 'list', - 'template2x2', 'template1x1a', 'templatelist', 'nop', - 'print', 'stack', 'hat', 'addturtle', 'myfunc', - 'myfunc1arg', 'myfunc2arg', 'myfunc3arg', 'comment', - 'sandwichtop', 'sandwichtop2', 'userdefined', - 'userdefined2args', 'userdefined3args', 'storein'] - -CONTENT_ARGS = ['show', 'showaligned', 'push', 'storein', 'storeinbox1', - 'storeinbox2'] - -# -# Status blocks -# - -MEDIA_SHAPES = ['audiooff', 'audioon', 'audiosmall', - 'journaloff', 'journalon', 'journalsmall', - 'descriptionoff', 'descriptionon', 'descriptionsmall', - 'pythonoff', 'pythonon', 'pythonsmall', - 'list', '1x1', '1x1a', '2x1', '1x2', '2x2'] - -OVERLAY_SHAPES = ['Cartesian', 'Cartesian_labeled', 'polar'] - -STATUS_SHAPES = ['status', 'info', 'nostack', 'noinput', 'emptyheap', - 'emptybox', 'nomedia', 'nocode', 'overflowerror', 'negroot', - 'syntaxerror', 'nofile', 'nojournal', 'zerodivide'] - -# -# Emulate Sugar toolbar when running from outside of Sugar -# -TOOLBAR_SHAPES = ['hideshowoff', 'eraseron', 'run-fastoff', - 'run-slowoff', 'debugoff', 'stopiton'] - -# -# Legacy names -# -OLD_NAMES = {'product':'product2', 'storeinbox':'storein', 'minus':'minus2', - 'division':'division2', 'plus':'plus2', 'and':'and2', 'or':'or2', - 'less':'less2', 'greater':'greater2', 'equal':'equal2', - 'remainder':'remainder2', 'identity':'identity2', - 'division':'division2', 'audiooff':'audio', 'endfill':'stopfill', - 'descriptionoff':'description','template3':'templatelist', - 'template1':'template1x1', 'template2':'template2x1', - 'template6':'template1x2', 'template7':'template2x2', - 'template4':'template1x1a', 'hres':'width', 'vres':'height' } - -# -# Define the relative size and postion of media objects -# (w, h, x, y, dx, dy) -# -TITLEXY = (0.9375, 0.875) - -# -# Relative placement of portfolio objects (used by depreciated blocks) -# -TEMPLATES = {'t1x1': (0.5, 0.5, 0.0625, 0.125, 1.05, 0), - 't2z1': (0.5, 0.5, 0.0625, 0.125, 1.05, 1.05), - 't1x2': (0.45, 0.45, 0.0625, 0.125, 1.05, 1.05), - 't2x2': (0.45, 0.45, 0.0625, 0.125, 1.05, 1.05), - 't1x1a': (0.9, 0.9, 0.0625, 0.125, 0, 0), - 'bullet': (1, 1, 0.0625, 0.125, 0, 0.1), - 'insertimage': (0.333, 0.333)} - -# -# Names for blocks without names for popup help -# -SPECIAL_NAMES = { - 'audio':_('audio'), - 'division2':_('divide'), - 'equal2':_('equal'), - 'greater2':_('greater than'), - 'hspace':_('horizontal space'), - 'identity2':_('identity'), - 'if':_('if then'), - 'ifelse':_('if then else'), - 'journal':_('journal'), - 'less2':_('less than'), - 'minus2':_('minus'), - 'nop':_('Python code'), - 'number':_('number'), - 'plus2':_('plus'), - 'product2':_('multiply'), - 'sqrt':_('square root'), - 'template1x1':_('presentation 1x1'), - 'template1x1a':_('presentation 1x1'), - 'template1x2':_('presentation 1x2'), - 'template2x1':_('presentation 2x1'), - 'template2x2':_('presentation 2x2'), - 'templatelist':_('presentation bulleted list'), - 'textsize':_('text size'), - 'vspace':_('vertical space')} - -# -# Help messages -# -HELP_STRINGS = { - 'addturtle':_("chooses which turtle to command"), - 'and2':_("logical AND operator"), - 'arc':_("moves turtle along an arc"), - 'audio':_("Sugar Journal audio object"), - 'back':_("moves turtle backward"), - 'blocks':_("Palette of variable blocks"), - 'bottompos':_("ycor of bottom of screen"), - 'box1':_("Variable 1 (numeric value)"), - 'box2':_("Variable 2 (numeric value)"), - 'box':_("named variable (numeric value)"), - 'cartesian':_("displays Cartesian coordinates"), - 'clean':_("clears the screen and reset the turtle"), - 'clearheap':_("emptys FILO (first-in-last-out heap)"), - 'color':_("holds current pen color (can be used in place of a number block)"), - 'colors':_("Palette of pen colors"), - 'comment':_("places a comment in your code"), - 'debugoff':_("Debug"), - 'description':_("Sugar Journal description field"), - 'division2':_("divides top numeric input (numerator) by bottom numeric input (denominator)"), - 'empty':_("permanently deletes items in trash"), - 'eraseron':_("Clean"), - 'equal2':_("logical equal-to operator"), - 'extras':_("Palette of extra options"), - 'fillscreen':_("fills the background with (color, shade)"), - 'flow':_("Palette of flow operators"), - 'forever':_("loops forever"), - 'forward':_("moves turtle forward"), - 'fullscreen':_("hides the Sugar toolbars"), - 'gray':_("holds current gray level (can be used in place of a number block)"), - 'greater2':_("logical greater-than operator"), - 'hat1':_("top of Action 1 stack"), - 'hat2':_("top of Action 2 stack"), - 'hat':_("top of nameable action stack"), - 'heading':_("holds current heading value of the turtle (can be used in place of a number block)"), - 'height':_("the canvas height"), - 'hideblocks':_("declutters canvas by hiding blocks"), - 'hideshowoff':_("Hide blocks"), - 'hspace':_("jogs stack right"), - 'identity2':_("identity operator used for extending blocks"), - 'ifelse':_("if-then-else operator that uses boolean operators from Numbers palette"), - 'if':_("if-then operator that uses boolean operators from Numbers palette"), - 'journal':_("Sugar Journal media object"), - 'kbinput':_("query for keyboard input (results stored in keyboard block)"), - 'keyboard':_("holds results of query-keyboard block"), - 'leftpos':_("xcor of left of screen"), - 'left':_("turns turtle counterclockwise (angle in degrees)"), - 'less2':_("logical less-than operator"), - 'minus2':_("subtracts bottom numeric input from top numeric input"), - 'myfunc':_("a programmable block: used to add advanced math equations, e.g., sin(x)"), - 'myfunc1arg':_("a programmable block: used to add advanced single-variable math equations, e.g., sin(x)"), - 'myfunc2arg':_("a programmable block: used to add advanced multi-variable math equations, e.g., sqrt(x*x+y*y)"), - 'myfunc3arg':_("a programmable block: used to add advanced multi-variable math equations, e.g., sin(x+y+z)"), - 'next':_('displays next palette'), - 'nop':_("runs code found in the tamyblock.py module found in the Journal"), - 'not':_("logical NOT operator"), - 'numbers':_("Palette of numeric operators"), - 'number':_("used as numeric input in mathematic operators"), - 'or':_("logical OR operator"), - 'orientation':_("changes the orientation of the palette of blocks"), - 'pendown':_("Turtle will draw when moved."), - 'pen':_("Palette of pen commands"), - 'pensize':_("holds current pen size (can be used in place of a number block)"), - 'penup':_("Turtle will not draw when moved."), - 'picture1x1':_("presentation template: select Journal object (with description)"), - 'picture1x1a':_("presentation template: select Journal object (no description)"), - 'picture1x2':_("presentation template: select two Journal objects"), - 'picture2x1':_("presentation template: select two Journal objects"), - 'picture2x2':_("presentation template: select four Journal objects"), - 'picturelist':_("presentation template: list of bullets"), - 'pitch':_('microphone input pitch'), - 'plus2':_("adds two alphanumeric inputs"), - 'polar':_("displays polar coordinates"), - 'pop':_("pops value off FILO (first-in last-out heap)"), - 'portfolio':_("Palette of presentation templates"), - 'print':_("prints value in status block at bottom of the screen"), - 'printheap':_("shows values in FILO (first-in last-out heap)"), - 'product2':_("multiplies two numeric inputs"), - 'push':_("pushes value onto FILO (first-in last-out heap)"), - 'random':_("returns random number between minimum (top) and maximum (bottom) values"), - 'remainder2':_("modular (remainder) operator"), - 'repeat':_("loops specified number of times"), - 'resistance':_("sensor input resistance"), - 'restore':_("restores most recent blocks from trash"), - 'restoreall':_("restore all blocks from trash"), - 'rightpos':_("xcor of right of screen"), - 'right':_("turns turtle clockwise (angle in degrees)"), - 'run-fastoff':_("Run"), - 'run-slowoff':_("Step"), - 'sandwichbottom':_("bottom block in a collapsibe stack: click to collapse"), - 'sandwichcollapsed':_("bottom block in a collapsed stack: click to open"), - 'sandwichtop':_("top of a collapsible stack"), - 'sandwichtop2':_("top of a collapsed stack"), - 'savepix':_("saves a picture to the Sugar Journal"), - 'savesvg':_("saves turtle graphics as an SVG file in the Sugar Journal"), - 'scale':_("holds current scale value"), - 'setcolor':_("sets color of the line drawn by the turtle"), - 'setgray':_("sets gray level of the line drawn by the turtle"), - 'seth':_("sets the heading of the turtle (0 is towards the top of the screen.)"), - 'setpensize':_("sets size of the line drawn by the turtle"), - 'setscale':_("sets the scale of media"), - 'setshade':_("sets shade of the line drawn by the turtle"), - 'settextcolor':_("sets color of text drawn by the turtle"), - 'settextsize':_("sets size of text drawn by turtle"), - 'setxy':_("moves turtle to position xcor, ycor; (0, 0) is in the center of the screen."), - 'shade':_("holds current pen shade"), - 'show':_("draws text or show media from the Journal"), - 'showblocks':_("restores hidden blocks"), - 'sqrt':_("calculates square root"), - 'stack1':_("invokes Action 1 stack"), - 'stack2':_("invokes Action 2 stack"), - 'stack':_("invokes named action stack"), - 'start':_("connects action to toolbar run buttons"), - 'startfill':_("starts filled polygon (used with end fill block)"), - 'stopfill':_("completes filled polygon (used with start fill block)"), - 'stopiton':_("Stop turtle"), - 'stopstack':_("stops current action"), - 'storeinbox1':_("stores numeric value in Variable 1"), - 'storeinbox2':_("stores numeric value in Variable 2"), - 'storein':_("stores numeric value in named variable"), - 'string':_("string value"), - 'template1x1':_("presentation template: select Journal object (with description)"), - 'template1x1a':_("presentation template: select Journal object (no description)"), - 'template1x2':_("presentation template: select two Journal objects"), - 'template2x1':_("presentation template: select two Journal objects"), - 'template2x2':_("presentation template: select four Journal objects"), - 'templatelist':_("presentation template: list of bullets"), - 'textcolor':_("holds current text color (can be used in place of a number block)"), - 'textsize':_("holds current text size (can be used in place of a number block)"), - 'toppos':_("ycor of top of screen"), - 'trash':_("Trashcan"), - 'turtle':_("Palette of turtle commands"), - 'until':_("do-until-True operator that uses boolean operators from Numbers palette"), - 'userdefined':_("runs code found in the tamyblock.py module found in the Journal"), - 'userdefined2args':_("runs code found in the tamyblock.py module found in the Journal"), - 'userdefined3args':_("runs code found in the tamyblock.py module found in the Journal"), - 'voltage':_("sensor voltage"), - 'volume':_("microphone input volume"), - 'vspace':_("jogs stack down"), - 'wait':_("pauses program execution a specified number of seconds"), - 'while':_("do-while-True operator that uses boolean operators from Numbers palette"), - 'width':_("the canvas width"), - 'xcor':_("holds current x-coordinate value of the turtle (can be used in place of a number block)"), - 'ycor':_("holds current y-coordinate value of the turtle (can be used in place of a number block)")} - -# -# 'dead key' Unicode dictionaries -# - -DEAD_KEYS = ['grave','acute','circumflex','tilde','diaeresis','abovering'] -DEAD_DICTS = [{'A':192,'E':200,'I':204,'O':210,'U':217,'a':224,'e':232,'i':236, - 'o':242,'u':249}, - {'A':193,'E':201,'I':205,'O':211,'U':218,'a':225,'e':233,'i':237, - 'o':243,'u':250}, - {'A':194,'E':202,'I':206,'O':212,'U':219,'a':226,'e':234, - 'i':238,'o':244,'u':251}, - {'A':195,'O':211,'N':209,'U':360,'a':227,'o':245,'n':241,'u':361}, - {'A':196,'E':203,'I':207,'O':211,'U':218,'a':228,'e':235, - 'i':239,'o':245,'u':252}, - {'A':197,'a':229}] -NOISE_KEYS = ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', 'Pause', - 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift', 'KP_Divide', - 'Escape', 'Return', 'KP_Page_Up', 'Up', 'Down', 'Menu', - 'Left', 'Right', 'KP_Home', 'KP_End', 'KP_Up', 'Super_L', - 'KP_Down', 'KP_Left', 'KP_Right', 'KP_Page_Down', 'Scroll_Lock', - 'Page_Down', 'Page_Up'] -WHITE_SPACE = ['space','Tab'] - -CURSOR = '█' -RETURN = '⏎' - - -# -# Macros (groups of blocks) -# -MACROS = { - 'until': - [[0, 'forever', 0, 0, [None, 2, 1]], - [1, 'vspace', 0, 0, [0, None]], - [2, 'ifelse', 0, 0, [0, None, 3, None, None]], - [3, 'vspace', 0, 0, [2, 4]], - [4, 'stopstack', 0, 0, [3, None]]], - 'while': - [[0, 'forever', 0, 0, [None, 2, 1]], - [1, 'vspace', 0, 0, [0, None]], - [2, 'ifelse', 0, 0, [0, None, 3, 4, None]], - [3, 'vspace', 0, 0, [2, None]], - [4, 'stopstack', 0, 0, [2, None]]], - 'kbinput': - [[0, 'forever', 0, 0, [None, 1, None]], - [1, 'kbinput', 0, 0, [0, 2]], - [2, 'vspace', 0, 0, [1, 3]], - [3, 'if', 0, 0, [2, 4, 7, 8]], - [4, 'greater2', 0, 0, [3, 5, 6, None]], - [5, 'keyboard', 0, 0, [4, None]], - [6, ['number', '0'], 0, 0, [4, None]], - [7, 'stopstack', 0, 0, [3, None]], - [8, 'vspace', 0, 0, [3, 9]], - [9, 'wait', 0, 0, [8, 10, None]], - [10, ['number', '1'], 0, 0, [9, None]]], - 'picturelist': - [[0, 'sandwichtop', 0, 0, [None, 1, 2]], - [1, ['string', _('bulleted list')], 0, 0, [0, None]], - [2, 'setxy', 0, 0, [0, 3, 4, 5]], - [3, 'titlex', 0, 0, [2, None]], - [4, 'titley', 0, 0, [2, None]], - [5, 'setscale', 0, 0, [2, 6, 7]], - [6, ['number', '100'], 0, 0, [5, None]], - [7, 'show', 0, 0, [5, 8, 9]], - [8, ['string',_('Title')], 0, 0, [7, None]], - [9, 'setxy', 0, 0, [7, 10, 11, 12]], - [10, 'leftx', 0, 0, [9, None]], - [11, 'topy', 0, 0, [9, None]], - [12, 'setscale', 0, 0, [9, 13, 14]], - [13, ['number', '67'], 0, 0, [12, None]], - [14, 'list', 0, 0, [12, 15, 16, 17]], - [15, ['string','∙ '], 0, 0, [14, None]], - [16, ['string','∙ '], 0, 0, [14, None]], - [17, 'sandwichbottom', 0, 0, [14, None]]], - 'picture1x1a': - [[0, 'sandwichtop', 0, 0, [None, 1, 2]], - [1, ['string', _('picture')], 0, 0, [0, None]], - [2, 'setxy', 0, 0, [0, 3, 4, 5]], - [3, 'titlex', 0, 0, [2, None]], - [4, 'titley', 0, 0, [2, None]], - [5, 'setscale', 0, 0, [2, 6, 7]], - [6, ['number', '100'], 0, 0, [5, None]], - [7, 'show', 0, 0, [5, 8, 9]], - [8, ['string',_('Title')], 0, 0, [7, None]], - [9, 'setscale', 0, 0, [7, 10, 11]], - [10, ['number', '90'], 0, 0, [9, None]], - [11, 'setxy', 0, 0, [9, 12, 13, 14]], - [12, 'leftx', 0, 0, [11, None]], - [13, 'topy', 0, 0, [11, None]], - [14, 'showaligned', 0, 0, [11, 15, 16]], - [15, 'journal', 0, 0, [14, None]], - [16, 'sandwichbottom', 0, 0, [14, None]]], - 'picture2x2': - [[0, 'sandwichtop', 0, 0, [None, 1, 2]], - [1, ['string', _('2×2 pictures')], 0, 0, [0, None]], - [2, 'setxy', 0, 0, [0, 3, 4, 5]], - [3, 'titlex', 0, 0, [2, None]], - [4, 'titley', 0, 0, [2, None]], - [5, 'setscale', 0, 0, [2, 6, 7]], - [6, ['number', '100'], 0, 0, [5, None]], - [7, 'show', 0, 0, [5, 8, 9]], - [8, ['string',_('Title')], 0, 0, [7, None]], - [9, 'setscale', 0, 0, [7, 10, 11]], - [10, ['number', '35'], 0, 0, [9, None]], - [11, 'setxy', 0, 0, [9, 12, 13, 14]], - [12, 'leftx', 0, 0, [11, None]], - [13, 'topy', 0, 0, [11, None]], - [14, 'showaligned', 0, 0, [11, 15, 16]], - [15, 'journal', 0, 0, [14, None]], - [16, 'setxy', 0, 0, [14, 17, 18, 19]], - [17, 'rightx', 0, 0, [16, None]], - [18, 'topy', 0, 0, [16, None]], - [19, 'showaligned', 0, 0, [16, 20, 21]], - [20, 'journal', 0, 0, [19, None]], - [21, 'setxy', 0, 0, [19, 22, 23, 24]], - [22, 'leftx', 0, 0, [21, None]], - [23, 'bottomy', 0, 0, [21, None]], - [24, 'showaligned', 0, 0, [21, 25, 26]], - [25, 'journal', 0, 0, [24, None]], - [26, 'setxy', 0, 0, [24, 27, 28, 29]], - [27, 'rightx', 0, 0, [26, None]], - [28, 'bottomy', 0, 0, [26, None]], - [29, 'showaligned', 0, 0, [26, 30, 31]], - [30, 'journal', 0, 0, [29, None]], - [31, 'sandwichbottom', 0, 0, [29, None]]], - 'picture2x1': - [[0, 'sandwichtop', 0, 0, [None, 1, 2]], - [1, ['string', _('2×1 pictures')], 0, 0, [0, None]], - [2, 'setxy', 0, 0, [0, 3, 4, 5]], - [3, 'titlex', 0, 0, [2, None]], - [4, 'titley', 0, 0, [2, None]], - [5, 'setscale', 0, 0, [2, 6, 7]], - [6, ['number', '100'], 0, 0, [5, None]], - [7, 'show', 0, 0, [5, 8, 9]], - [8, ['string',_('Title')], 0, 0, [7, None]], - [9, 'setscale', 0, 0, [7, 10, 11]], - [10, ['number', '35'], 0, 0, [9, None]], - [11, 'setxy', 0, 0, [9, 12, 13, 14]], - [12, 'leftx', 0, 0, [11, None]], - [13, 'topy', 0, 0, [11, None]], - [14, 'showaligned', 0, 0, [11, 15, 16]], - [15, 'journal', 0, 0, [14, None]], - [16, 'setxy', 0, 0, [14, 17, 18, 19]], - [17, 'leftx', 0, 0, [16, None]], - [18, 'bottomy', 0, 0, [16, None]], - [19, 'showaligned', 0, 0, [16, 20, 21]], - [20, 'description', 0, 0, [19, None]], - [21, 'setxy', 0, 0, [19, 22, 23, 24]], - [22, 'rightx', 0, 0, [21, None]], - [23, 'topy', 0, 0, [21, None]], - [24, 'showaligned', 0, 0, [21, 25, 26]], - [25, 'journal', 0, 0, [24, None]], - [26, 'setxy', 0, 0, [24, 27, 28, 29]], - [27, 'rightx', 0, 0, [26, None]], - [28, 'bottomy', 0, 0, [26, None]], - [29, 'showaligned', 0, 0, [26, 30, 31]], - [30, 'description', 0, 0, [29, None]], - [31, 'sandwichbottom', 0, 0, [29, None]]], - 'picture1x2': - [[0, 'sandwichtop', 0, 0, [None, 1, 2]], - [1, ['string', _('1×2 pictures')], 0, 0, [0, None]], - [2, 'setxy', 0, 0, [0, 3, 4, 5]], - [3, 'titlex', 0, 0, [2, None]], - [4, 'titley', 0, 0, [2, None]], - [5, 'setscale', 0, 0, [2, 6, 7]], - [6, ['number', '100'], 0, 0, [5, None]], - [7, 'show', 0, 0, [5, 8, 9]], - [8, ['string',_('Title')], 0, 0, [7, None]], - [9, 'setscale', 0, 0, [7, 10, 11]], - [10, ['number', '35'], 0, 0, [9, None]], - [11, 'setxy', 0, 0, [9, 12, 13, 14]], - [12, 'leftx', 0, 0, [11, None]], - [13, 'topy', 0, 0, [11, None]], - [14, 'showaligned', 0, 0, [11, 15, 16]], - [15, 'journal', 0, 0, [14, None]], - [16, 'setxy', 0, 0, [14, 17, 18, 19]], - [17, 'rightx', 0, 0, [16, None]], - [18, 'topy', 0, 0, [16, None]], - [19, 'showaligned', 0, 0, [16, 20, 21]], - [20, 'description', 0, 0, [19, None]], - [21, 'setxy', 0, 0, [19, 22, 23, 24]], - [22, 'leftx', 0, 0, [21, None]], - [23, 'bottomy', 0, 0, [21, None]], - [24, 'showaligned', 0, 0, [21, 25, 26]], - [25, 'journal', 0, 0, [24, None]], - [26, 'setxy', 0, 0, [24, 27, 28, 29]], - [27, 'rightx', 0, 0, [26, None]], - [28, 'bottomy', 0, 0, [26, None]], - [29, 'showaligned', 0, 0, [26, 30, 31]], - [30, 'description', 0, 0, [29, None]], - [31, 'sandwichbottom', 0, 0, [29, None]]], - 'picture1x1': - [[0, 'sandwichtop', 0, 0, [None, 1, 2]], - [1, ['string', _('1×1 pictures')], 0, 0, [0, None]], - [2, 'setxy', 0, 0, [0, 3, 4, 5]], - [3, 'titlex', 0, 0, [2, None]], - [4, 'titley', 0, 0, [2, None]], - [5, 'setscale', 0, 0, [2, 6, 7]], - [6, ['number', '100'], 0, 0, [5, None]], - [7, 'show', 0, 0, [5, 8, 9]], - [8, ['string',_('Title')], 0, 0, [7, None]], - [9, 'setscale', 0, 0, [7, 10, 11]], - [10, ['number', '35'], 0, 0, [9, None]], - [11, 'setxy', 0, 0, [9, 12, 13, 14]], - [12, 'leftx', 0, 0, [11, None]], - [13, 'topy', 0, 0, [11, None]], - [14, 'showaligned', 0, 0, [11, 15, 16]], - [15, 'journal', 0, 0, [14, None]], - [16, 'setxy', 0, 0, [14, 17, 18, 19]], - [17, 'rightx', 0, 0, [16, None]], - [18, 'topy', 0, 0, [16, None]], - [19, 'showaligned', 0, 0, [16, 20, 21]], - [20, 'description', 0, 0, [19, None]], - [21, 'sandwichbottom', 0, 0, [19, None]]], - } diff --git a/taexporthtml.py b/taexporthtml.py deleted file mode 100644 index 47577f0..0000000 --- a/taexporthtml.py +++ /dev/null @@ -1,147 +0,0 @@ -#Copyright (c) 2008-9, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import pygtk -pygtk.require('2.0') -import gtk -import os.path -from tautils import data_to_string, save_picture, image_to_base64 -from gettext import gettext as _ -from cgi import escape - -def save_html(self, tw, embed_flag=True): - """ Either: Save canvas and code or pictures to HTML """ - self.embed_images = embed_flag - - # A dictionary to define the HTML wrappers around template elements - self.html_glue = { - 'doctype': "\n", - 'html': ("\n", "\n"), - 'html_svg': ("\n", - "\n"), - 'head': ("\n\n", "\n"), - 'meta': "\n", - 'title': ("", "\n"), - 'style': ("\n"), - 'body': ("\n", "\n\n"), - 'div': ("
\n", "
\n"), - 'slide': ("\n\n"), - 'h1': ("

", "

\n"), - 'table': ("\n", "
\n"), - 'tr': ("\n", "\n"), - 'td': ("\n", - "\n\n"), - 'img': ("\"Image\"\n"), - 'img2': ("\"Image\"\n"), - 'img3': ("\"Image\"\n"), - 'ul': ("\n", "
\n"), - 'li': ("", "\n") } - - comment = "\n" - if self.embed_images == True: - self.html_glue['img'] = ("+ \
-                                 \n") - self.html_glue['img2'] = ("\"Image\"\n") - - """ - If there are saved_pictures, put them into a .html; otherwise, save a - screendump and the turtle project code. - """ - code = "" - if len(tw.saved_pictures) > 0: - for i, p in enumerate(tw.saved_pictures): - code += self.html_glue['slide'][0] + str(i) - code += self.html_glue['slide'][1] + \ - self.html_glue['div'][0] + \ - self.html_glue['h1'][0] - if self.embed_images == True: - f = open(p, "r") - imgdata = f.read() - f.close() - if p.endswith(('.svg')): - tmp = imgdata - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(p) - imgdata = image_to_base64(pixbuf, tw.activity) - tmp = self.html_glue['img2'][0] - tmp += imgdata - tmp += self.html_glue['img2'][1] - else: - if p.endswith(('.svg')): - f = open(p, "r") - imgdata = f.read() - f.close() - tmp = imgdata - else: - tmp = self.html_glue['img3'][0] - tmp += p - tmp += self.html_glue['img3'][1] - code += tmp + \ - self.html_glue['h1'][1] + \ - self.html_glue['div'][1] - else: - if self.embed_images == True: - imgdata = image_to_base64(save_picture(self.tw.canvas), tw.activity) - else: - imgdata = os.path.join(self.tw.load_save_folder, 'image') - self.tw.save_as_image(imgdata) - code += (self.html_glue['img'][0] + imgdata + \ - self.html_glue['img'][1]) - code += self.html_glue['div'][0] - code += escape(data_to_string(tw.assemble_data_to_save(False, True))) - code += self.html_glue['div'][1] - - if tw.running_sugar: - title = _("Turtle Art") + " " + tw.activity.metadata['title'] - else: - title = _("Turtle Art") - - header = self.html_glue['doctype'] + \ - self.html_glue['html'][0] - style = self.html_glue['style'][0] + \ - self.html_glue['style'][1] - if len(tw.saved_pictures) > 0: - if tw.saved_pictures[0].endswith(('.svg')): - header = self.html_glue['html_svg'][0] - style = comment - - code = header + \ - self.html_glue['head'][0] + \ - self.html_glue['meta'] + \ - self.html_glue['title'][0] + \ - title + \ - self.html_glue['title'][1] + \ - style + \ - self.html_glue['head'][1] + \ - self.html_glue['body'][0] + \ - code + \ - self.html_glue['body'][1] + \ - self.html_glue['html'][1] - return code diff --git a/taexportlogo.py b/taexportlogo.py deleted file mode 100644 index 7fde81c..0000000 --- a/taexportlogo.py +++ /dev/null @@ -1,353 +0,0 @@ -#Copyright (c) 2008-10, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -IGNORE = ["hideblocks", "showblocks", "fullscreen", "polar", "cartesian", - "sandwichbottom", "id"] - -import math -from tautils import walk_stack -try: - from sugar.datastore import datastore -except: - pass - -def save_logo(tw): - """ We need to set up the Turtle Art color palette and color processing. """ - color_processing = "\ -to tasetpalette :i :r :g :b :myshade \r\ -make \"s ((:myshade - 50) / 50) \r\ -ifelse lessp :s 0 [ \r\ -make \"s (1 + (:s *0.8)) \r\ -make \"r (:r * :s) \r\ -make \"g (:g * :s) \r\ -make \"b (:b * :s) \r\ -] [ \ -make \"s (:s * 0.9) \r\ -make \"r (:r + ((99-:r) * :s)) \r\ -make \"g (:g + ((99-:g) * :s)) \r\ -make \"b (:b + ((99-:b) * :s)) \r\ -] \ -setpalette :i (list :r :g :b) \r\ -end \r\ -\ -to rgb :myi :mycolors :myshade \r\ -make \"myr first :mycolors \r\ -make \"mycolors butfirst :mycolors \r\ -make \"myg first :mycolors \r\ -make \"mycolors butfirst :mycolors \r\ -make \"myb first :mycolors \r\ -make \"mycolors butfirst :mycolors \r\ -tasetpalette :myi :myr :myg :myb :myshade \r\ -output :mycolors \r\ -end \r\ -\ -to processcolor :mycolors :myshade \r\ -if emptyp :mycolors [stop] \r\ -make \"i :i + 1 \r\ -processcolor (rgb :i :mycolors :myshade) :myshade \r\ -end \r\ -\ -to tasetshade :shade \r\ -make \"myshade modulo :shade 200 \r\ -if greaterp :myshade 99 [make \"myshade (199-:myshade)] \r\ -make \"i 7 \r\ -make \"mycolors :colors \r\ -processcolor :mycolors :myshade \r\ -end \r\ -\ -to tasetpencolor :c \r\ -make \"color (modulo (round :c) 100) \r\ -setpencolor :color + 8 \r\ -end \r\ -\ -make \"colors [ \ -99 0 0 99 5 0 99 10 0 99 15 0 99 20 0 \ -99 25 0 99 30 0 99 35 0 99 40 0 99 45 0 \ -99 50 0 99 55 0 99 60 0 99 65 0 99 70 0 \ -99 75 0 99 80 0 99 85 0 99 90 0 99 95 0 \ -99 99 0 90 99 0 80 99 0 70 99 0 60 99 0 \ -50 99 0 40 99 0 30 99 0 20 99 0 10 99 0 \ - 0 99 0 0 99 5 0 99 10 0 99 15 0 99 20 \ - 0 99 25 0 99 30 0 99 35 0 99 40 0 99 45 \ - 0 99 50 0 99 55 0 99 60 0 99 65 0 99 70 \ - 0 99 75 0 99 80 0 99 85 0 99 90 0 99 95 \ - 0 99 99 0 95 99 0 90 99 0 85 99 0 80 99 \ - 0 75 99 0 70 99 0 65 99 0 60 99 0 55 99 \ - 0 50 99 0 45 99 0 40 99 0 35 99 0 30 99 \ - 0 25 99 0 20 99 0 15 99 0 10 99 0 5 99 \ - 0 0 99 5 0 99 10 0 99 15 0 99 20 0 99 \ -25 0 99 30 0 99 35 0 99 40 0 99 45 0 99 \ -50 0 99 55 0 99 60 0 99 65 0 99 70 0 99 \ -75 0 99 80 0 99 85 0 99 90 0 99 95 0 99 \ -99 0 99 99 0 90 99 0 80 99 0 70 99 0 60 \ -99 0 50 99 0 40 99 0 30 99 0 20 99 0 10] \r\ -make \"shade 50 \r\ -tasetshade :shade \r" - - bs = tw.just_blocks() - code = "" - stack_count = 0 - show = 0 - - # These flags are used to trigger the prepending of additional procedures. - random = False - fillscreen = False - setcolor = False - setxy = False - pensize = False - setpensize = False - arc = False - heap = False - write = False - minus = False - division = False - image = False - - """ - Walk through the code, substituting UCB Logo for Turtle Art primitives. - """ - for b in bs: - this_stack = "" - data = walk_stack(tw, b) - # We need to catch several special cases: stacks, random, etc. - stack = False - namedstack = False - namedbox = False - refstack = False - refbox = False - myvar = "" - for d in data: - if type(d) == type((1, 2)): - (d, b) = d - if type(d) is float: - if namedbox: - myvar += str(d) - myvar += " " - elif write: - this_stack += "labelsize " - this_stack += str(d) - write = False - else: - this_stack += str(d) - elif show == 2: - # Use title for Journal objects - if d[0:8] == '#smedia_': - try: - dsobject = datastore.get(d[8:]) - this_stack += dsobject.metadata['title'] - dsobject.destroy() - except: - this_stack += str(d) - else: - this_stack += str(d) - show = 0 - else: - # Translate some Turtle Art primitives into UCB Logo - if namedstack: - this_stack += "to " - this_stack += d[2:].replace(" ","_") - this_stack += "\r" - stack = True - namedstack = False - elif namedbox: - if d[0:2] == "#s": - this_stack += "make \"" - this_stack += d[2:].replace(" ","_") - this_stack += " " - this_stack += myvar - namedbox = False - myvar = "" - else: - myvar += d - elif refstack: - this_stack += d[2:].replace(" ","_") - this_stack += " " - refstack = False - elif refbox: - this_stack += ":" - this_stack += d[2:].replace(" ","_") - refbox = False - elif d == "stack": - refstack = True - elif d == "box": - refbox = True - elif d == "storeinbox": - namedbox = True - elif d == "storeinbox1": - this_stack += "make \"box1" - elif d == "box1": - this_stack += ":box1" - elif d == "storeinbox2": - this_stack += "make \"box2" - elif d == "box2": - this_stack += ":box2" - elif d == "shade": - this_stack += ":shade" - elif d == "setshade": - setcolor = True - this_stack += "tasetshade" - elif d == "color": - this_stack += "pencolor" - elif d == "nop": - this_stack += " " - elif d == "start": - this_stack += "to start\r" - stack = True - elif d == "nop1": - this_stack += "to stack1\r" - stack = True - elif d == "nop2": - this_stack += "to stack2\r" - stack = True - elif d == "nop3": - namedstack = True - elif d == "stopstack": - this_stack += "stop" - elif d == "clean": - this_stack += "clearscreen" - elif d == "setxy": - setxy = True - this_stack += "tasetxy" - elif d == "color": - this_stack += ":color" - elif d == "plus": - this_stack += "sum" - elif d == "setcolor": - setcolor = True - this_stack += "tasetpencolor" - elif d == "fillscreen": - fillscreen = True - setcolor = True - this_stack += "tasetbackground" - elif d == "random": - random = True - this_stack += "tarandom" - elif d == "pensize": - pensize = True - this_stack += "tapensize" - elif d == "setpensize": - setpensize = True - this_stack += "tasetpensize" - elif d == "arc": - arc = True - this_stack += "taarc" - elif d == "pop": - heap = True - this_stack += "tapop" - elif d == "push": - heap = True - this_stack += "tapush" - elif d == "heap": - heap = True - this_stack += "taprintheap" - elif d == "emptyheap": - heap = True - this_stack += "taclearheap" - elif d == "kbinput": - this_stack += "make \"keyboard readchar" - elif d == "keyboard": - this_stack += ":keyboard" - elif d == 'insertimage': - image = True - elif image: - # Skip this arg - image = 2 - elif image == 2: - # Skip this arg - image = False - elif d[0:2] == "#s": - # output single characters as a string - if len(d[2:]): - this_stack += "\"" - this_stack += d[2:] - # make a sentence out of everything else - else: - this_stack += "sentence " - this_stack += d[2:].replace("\s"," \"") - this_stack += "\r" - elif d == "write": - this_stack += "label" - write = True - elif d == 'show' or d == 'showaligned': - this_stack += "label" - show = 1 - elif d == "minus2": - this_stack += "taminus" - minus = True - elif d == "division": - this_stack += "quotient" - elif d == "lpos": - this_stack += str(-tw.canvas.width/(tw.coord_scale*2)) - elif d == "rpos": - this_stack += str(tw.canvas.width/(tw.coord_scale*2)) - elif d == "bpos": - this_stack += str(-tw.canvas.height/(tw.coord_scale*2)) - elif d == "tpos": - this_stack += str(tw.canvas.height/(tw.coord_scale*2)) - elif d in IGNORE: - this_stack += " " - elif show == 1 and d[0:2] == "#s": - this_stack += d[2:] - # We don't handle depreciated 'template' blocks - else: - this_stack += d - this_stack += " " - if stack: - stack = False - # if it is not a stack, we need to add a "to ta#" label - elif len(data) > 0: - this_stack = "to ta" + str(stack_count) + "\r" + this_stack - stack_count += 1 - if len(data) > 0: - code += this_stack - code += "\rend\r" - - # We need to define some additional procedures. - if minus: # Logo minus only takes one argument. - code = "to taminus :y :x\routput sum :x minus :y\rend\r" + code - if random: # to avoid negative numbers - code = "to tarandom :min :max\r" + \ - "output (random (:max - :min)) + :min\rend\r" + code - if fillscreen: # Set shade than background color - code = "to tasetbackground :color :shade\r" + \ - "tasetshade :shade\rsetbackground :color\rend\r" + code - if setcolor: # Load the Turtle Art color palette. - code = color_processing + code - if setpensize: # Set int of pensize - code = "to tasetpensize :a\rsetpensize round :a\rend\r" + code - if pensize: # Return only the first argument. - code = "to tapensize\routput first round pensize\rend\r" + code - if setxy: # Swap and round arguments - code = "to tasetxy :x :y\rpenup\rsetxy :x :y\rpendown\rend\r" + code - if arc: # Turtle Art 'arc' needs to be redefined. - c = (2 * math.pi)/360 - code = "to taarc :a :r\rrepeat round :a [right 1 forward (" + \ - str(c) + " * :r)]\rend\r" + code - if heap: # Add psuedo 'push' and 'pop' - code = "to tapush :foo\rmake \"taheap fput :foo :taheap\rend\r" + \ - "to tapop\rif emptyp :taheap [stop]\rmake \"tmp first :taheap\r" + \ - "make \"taheap butfirst :taheap\routput :tmp\rend\r" + \ - "to taclearheap\rmake \"taheap []\rend\r" + \ - "to taprintheap \rprint :taheap\rend\r" + \ - "make \"taheap []\r" + code - code = "window\r" + code - return code - - diff --git a/tagplay.py b/tagplay.py deleted file mode 100644 index 5c86f62..0000000 --- a/tagplay.py +++ /dev/null @@ -1,176 +0,0 @@ -#Copyright (c) 2009, Walter Bender (on behalf of Sugar Labs) - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -""" -Video and audio playback - -Based on code snippets from -http://wiki.sugarlabs.org/go/Development_Team/Almanac/GStreamer -""" -import gtk -import pygtk -pygtk.require('2.0') -import pygst -pygst.require('0.10') -import gst -import gst.interfaces -import gobject -gobject.threads_init() - -try: - from sugar.datastore import datastore -except ImportError: - pass - -class Gplay: - - def __init__(self): - self.window = None - self.playing = False - - self.player = gst.element_factory_make("playbin", "playbin") - xis = gst.element_factory_make("xvimagesink", "xvimagesink") - self.player.set_property("video-sink", xis) - bus = self.player.get_bus() - bus.enable_sync_message_emission() - bus.add_signal_watch() - self.SYNC_ID = bus.connect('sync-message::element', \ - self._onSyncMessageCb) - - def _onSyncMessageCb(self, bus, message): - if message.structure is None: - return True - if message.structure.get_name() == 'prepare-xwindow-id': - if self.window is None: - return True - self.window.set_sink(message.src) - message.src.set_property('force-aspect-ratio', True) - return True - - def setFile(self, path): - uri = "file://" + str(path) - if (self.player.get_property('uri') == uri): - self.seek(gst.SECOND*0) - return - - self.player.set_state(gst.STATE_READY) - self.player.set_property('uri', uri) - ext = uri[len(uri)-3:] - if (ext == "jpg"): - self.pause() - else: - self.play() - - def queryPosition(self): - #"Returns a (position, duration) tuple" - try: - position, format = self.player.query_position(gst.FORMAT_TIME) - except: - position = gst.CLOCK_TIME_NONE - - try: - duration, format = self.player.query_duration(gst.FORMAT_TIME) - except: - duration = gst.CLOCK_TIME_NONE - return (position, duration) - - def seek(self, time): - event = gst.event_new_seek(1.0,\ - gst.FORMAT_TIME,\ - gst.SEEK_FLAG_FLUSH|gst.SEEK_FLAG_ACCURATE,\ - gst.SEEK_TYPE_SET,\ - time,\ - gst.SEEK_TYPE_NONE, 0) - res = self.player.send_event(event) - if res: - self.player.set_new_stream_time(0L) - - def pause(self): - self.playing = False - self.player.set_state(gst.STATE_PAUSED) - - def play(self): - self.playing = True - self.player.set_state(gst.STATE_PLAYING) - - def stop(self): - self.playing = False - self.player.set_state(gst.STATE_NULL) - # self.nextMovie() - - def get_state(self, timeout=1): - return self.player.get_state(timeout=timeout) - - def is_playing(self): - return self.playing - -class PlayVideoWindow(gtk.Window): - def __init__(self): - gtk.Window.__init__(self) - self.imagesink = None - self.unset_flags(gtk.DOUBLE_BUFFERED) - self.set_flags(gtk.APP_PAINTABLE) - - def set_sink(self, sink): - if (self.imagesink != None): - assert self.window.xid - self.imagesink = None - del self.imagesink - - self.imagesink = sink - if self.window is not None: - self.imagesink.set_xwindow_id(self.window.xid) - -def play_audio(lc, filepath): - print "loading audio id: " + filepath - if lc.gplay == None: - lc.gplay = Gplay() - lc.gplay.setFile("file:///" + filepath) - -def play_movie_from_file(lc, filepath, x, y, w, h): - if lc.gplay == None: - lc.gplay = Gplay() - # wait for current movie to stop playing - if lc.gplay.is_playing: - print "already playing..." - lc.gplay.setFile("file:///" + filepath) - if lc.gplay.window == None: - gplayWin = PlayVideoWindow() - lc.gplay.window = gplayWin - gplayWin.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - gplayWin.set_decorated(False) - if lc.tw.running_sugar: - gplayWin.set_transient_for(lc.tw.activity) - # y position is too high for some reason (toolbox?) adding offset - gplayWin.move(x, y+108) - gplayWin.resize(w, h) - gplayWin.show_all() - - -def stop_media(lc): - if lc.gplay == None: - return - lc.gplay.stop() - if lc.gplay.window != None: - # We need to destroy the video window - # print dir(lc.gplay.window) - lc.gplay.window.destroy() - lc.gplay = None - diff --git a/tajail.py b/tajail.py deleted file mode 100644 index 091557b..0000000 --- a/tajail.py +++ /dev/null @@ -1,69 +0,0 @@ -#Copyright (c) 2009-10, Walter Bender (on behalf of Sugar Labs) - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -# A naive approach to running myfunc in a jail -import logging -_logger = logging.getLogger('turtleart-activity') -import traceback -from time import * -from math import * -try: - from numpy import * -except ImportError: - _logger.error("could not import numpy") - -def myfunc(f, args): - # check to make sure no import calls are made - if len(args) == 1: - myf = "def f(x): return " + f.replace("import","") - userdefined = {} - try: - exec myf in globals(), userdefined - return userdefined.values()[0](args[0]) - except: - traceback.print_exc() - return None - elif len(args) == 2: - myf = "def f(x,y): return " + f.replace("import","") - userdefined = {} - try: - exec myf in globals(), userdefined - return userdefined.values()[0](args[0],args[1]) - except: - traceback.print_exc() - return None - elif len(args) == 3: - myf = "def f(x,y,z): return " + f.replace("import","") - userdefined = {} - try: - exec myf in globals(), userdefined - return userdefined.values()[0](args[0],args[1],args[2]) - except: - traceback.print_exc() - return None - -def myfunc_import(lc, f, x): - userdefined = {} - try: - exec f in globals(), userdefined - return userdefined['myblock'](lc, x) - except: - traceback.print_exc() - return None diff --git a/tamyblock.py b/tamyblock.py deleted file mode 100644 index 308ff42..0000000 --- a/tamyblock.py +++ /dev/null @@ -1,245 +0,0 @@ -#Copyright (c) 2009-10, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -# -# This procedure is invoked when the user-definable block on the "extras" -# palette is selected. Some examples of how to use this block are included -# below. Try uncommenting an example or write your own Python code. -# -# To uncomment code, remove the '# ' in the Python code. Take care to preserve -# the proper indentations. -# -# -# NOTES: -# -# Turtle Art is created in object oriented Python code. This is based -# around the definition of classes and the creation of object(s) which -# are instance(s) of that class. These objects then have properties and -# methods which are defined by their class. -# -# See http://docs.python.org/tutorial/classes.html for a description of -# classes in Python. -# -# Class Defined in Instance Created in -# TurtleArtWindow tawindow.py tw TurtleArtActivity.py -# LogoCode talogo.py lc tawindow.py -# TurtleGraphics tacanvas.py canvas tawindow.py -# Turtles, Turtle taturtle.py turtles tawindow.py, -# tacanvas.py -# Blocks, Block tablock.py block_list tawindow.py -# -# -# Class TurtleArtWindow -- useful properties and methods (from within -# tamyblock.py, lc.tw is the class instance) -# -# Methods and data attributes Example -# set_fullscreen(self) lc.tw.set_fullscreen() -# Note: Hides the Sugar toolbar -# set_cartesian(self, flag) lc.tw.set_cartesian(True) -# Note: True will make the overlay visible; -# False will make it invisible -# set_polar(self, flag) lc.tw.set_polar(True) -# Note: True will make the overlay visible; -# False will make it invisible -# hideshow_button(self, flag) lc.tw.hideshow_button() -# Note: Toggles visibility of blocks and palettes -# self.active_turtle lc.tw.active_turtle -# Note: The active turtle instance -# -# -# Class TurtleGraphics -- useful properties and methods (from within -# tamyblock.py, lc.tw.canvas is the class instance) -# -# Methods and data attributes Example -# clearscreen(self) lc.tw.canvas.clearscreen() -# Note: Clears the screen and resets all turtle and -# pen attributes to default values -# setpen(self, flag) lc.tw.canvas.setpen(True) -# Note: True will set the pen "down", enabling drawing; -# False will set the pen "up" -# forward(self, n) lc.tw.canvas.forward(100) -# Note: Move the turtle forward 100 units -# arc(self, a, r) lc.tw.canvas.arc(120, 50) -# Note: Move the turtle along an arc of 120 degrees -# (clockwise) and radius of 50 units -# setheading(self, a) lc.tw.canvas.setheading(180) -# Note: Set the turtle heading to 180 -# (towards the bottom of the screen) -# self.heading lc.tw.canvas.heading -# Note: The current heading -# setpensize(self, n) lc.tw.canvas.setpensize(25) -# Note: Set the turtle pensize to 25 units -# self.pensize lc.tw.canvas.pensize -# Note: The current pensize -# setcolor(self, c) lc.tw.canvas.color(70) -# Note: Set the pen color to 70 (blue) -# self.color lc.tw.canvas.color -# Note: The current pen color -# setshade(self, s) lc.tw.canvas.shade(50) -# Note: Set the pen shade to 50 -# self.shade lc.tw.canvas.shade -# Note: The current pen shade -# fillscreen(self, c, s) lc.tw.canvas.fillscreen(70, 90) -# Note: Fill the screen with color 70, shade 90 (light blue) -# setxy(self, x, y) lc.tw.canvas.setxy(100,100) -# Note: Move the turtle to position (100, 100) -# self.xcor lc.tw.canvas.xcor -# Note: The current x coordinate of the turtle -# (scaled to current units) -# self.ycor lc.tw.canvas.ycor -# Note: The current y coordinate of the turtle -# (scaled to current units) -# self.set_turtle(name) lc.tw.canvas.set_turtle(1) -# Note: Set the current turtle to turtle '1' -# -# -# Other useful Python functions -# Module Example -# from math import pow pow(2,3) returns 2 to the 3rd power -# Note: See http://docs.python.org/library/math.html -# from math import sin, pi sin(45*pi/180) returns sin of 45 (0.707) -# Note: See http://docs.python.org/library/math.html -# from time import localtime localtime().tm_hour returns the current hour -# Note: See http://docs.python.org/library/time.html -# lc.heap.append(data) adds data to the heap -# Note: See http://docs.python.org/tutorial/datastructures.html -# data = lc.heap.pop(-1) pops data off the heap -# Note: See http://docs.python.org/tutorial/datastructures.html -# - -def myblock(lc, x): - - ########################################################################### - # - # Set rgb color - # - ########################################################################### - - # r = int(x[0]) - # while r < 0: - # r += 256 - # while r > 255: - # r -= 256 - # g = int(x[1]) - # while g < 0: - # g += 256 - # while g > 255: - # g -= 256 - # b = int(x[2]) - # while b < 0: - # b += 256 - # while b > 255: - # b -= 256 - # rgb = "#%02x%02x%02x" % (r,g,b) - # lc.tw.canvas.fgcolor = lc.tw.canvas.cm.alloc_color(rgb) - # return - - ########################################################################### - # - # Draw a dotted line of length x. - # - ########################################################################### - - try: # make sure x is a number - x = float(x) - except ValueError: - return - if lc.tw.canvas.pendown: - dist = 0 - while dist+lc.tw.canvas.pensize < x: # repeat drawing dots - lc.tw.canvas.setpen(True) - lc.tw.canvas.forward(1) - lc.tw.canvas.setpen(False) - lc.tw.canvas.forward((lc.tw.canvas.pensize*2)-1) - dist += (lc.tw.canvas.pensize*2) - lc.tw.canvas.forward(x-dist) # make sure we have moved exactly x - lc.tw.canvas.setpen(True) - else: - lc.tw.canvas.forward(x) - return - - ########################################################################### - # - # Push an uppercase version of a string onto the heap. - # Use a 'pop' block to use the new string. - # - ########################################################################### - - # if type(x) != str: - # X = str(x).upper() - # else: - # X = x.upper() - # lc.heap.append(X) - # return - - ########################################################################### - # - # Push hours, minutes, seconds onto the FILO. - # Use three 'pop' blocks to retrieve these values. - # Note: because we use a FILO (first in, last out heap), - # the first value you will pop will be seconds. - # - ########################################################################### - - # lc.heap.append(localtime().tm_hour) - # lc.heap.append(localtime().tm_min) - # lc.heap.append(localtime().tm_sec) - # return - - ########################################################################### - # - # Add a third dimension (gray) to the color model. - # - ########################################################################### - - # val = 0.3 * lc.tw.rgb[0] + 0.6 * lc.tw.rgb[1] + 0.1 * lc.tw.rgb[2] - # if x != 100: - # x = int(x)%100 - # r = int((val*(100-x) + lc.tw.rgb[0]*x)/100) - # g = int((val*(100-x) + lc.tw.rgb[1]*x)/100) - # b = int((val*(100-x) + lc.tw.rgb[2]*x)/100) - # reallocate current color - # rgb = "#%02x%02x%02x" % (r,g,b) - # lc.tw.canvas.fgcolor = lc.tw.canvas.cm.alloc_color(rgb) - # return - - ########################################################################### - # - # Save an image named x to the Sugar Journal. - # - ########################################################################### - - # lc.tw.save_as_image(str(x)) - # return - - ########################################################################### - # - # Push mouse event to stack - # - ########################################################################### - - # if lc.tw.mouse_flag == 1: - # lc.heap.append(lc.tw.mouse_y) - # lc.heap.append(lc.tw.mouse_x) - # lc.heap.append(1) # mouse event - # lc.tw.mouseflag = 0 - # else: - # lc.heap.append(0) # no mouse event - # return diff --git a/tasprite_factory.py b/tasprite_factory.py deleted file mode 100755 index 073f9f5..0000000 --- a/tasprite_factory.py +++ /dev/null @@ -1,1117 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#Copyright (c) 2009,10 Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import pygtk -pygtk.require('2.0') -import gtk -import os -from gettext import gettext as _ - -class SVG: - def __init__(self): - self._x = 0 - self._y = 0 - self._min_x = 10000 - self._min_y = 10000 - self._max_x = -10000 - self._max_y = -10000 - self._width = 0 - self._height = 0 - self.docks = [] - self._scale = 1 - self._orientation = 0 - self._radius = 8 - self._stroke_width = 1 - self._innie = [False] - self._outie = False - self._innie_x1 = (9-self._stroke_width)/2 - self._innie_y1 = 3 - self._innie_x2 = (9-self._stroke_width)/2 - self._innie_y2 = (9-self._stroke_width)/2 - self._innie_spacer = 9 - self._slot = True - self._cap = False - self._tab = True - self._bool = False - self._slot_x = 10 - self._slot_y = 2 - self._porch = False - self._porch_x = self._innie_x1+self._innie_x2+4*self._stroke_width - # self._porch_y = self._innie_y1+self._innie_y2+4*self._stroke_width - self._porch_y = self._innie_y2 - self._expand_x = 0 - self._expand_y = 0 - self._no_arm = False - self._else = False - self._draw_innies = True - self._hide = False - self._show = False - self._show_x = 0 - self._show_y = 0 - self._hide_x = 0 - self._hide_y = 0 - self._dot_radius = 8 - self._fill = "#00FF00" - self._stroke = "#00A000" - self._gradiant = False - self.margins = [0, 0, 0, 0] - - def basic_block(self): - self.reset_min_max() - (x, y) = self._calculate_x_y() - self.margins[2] = 0 - self.margins[3] = 0 - svg = self.new_path(x, y) - svg += self._corner(1, -1) - svg += self._do_slot() - svg += self._rline_to(self._expand_x, 0) - xx = self._x - svg += self._corner(1, 1) - for i in range(len(self._innie)): - if self._innie[i] is True: - svg += self._do_innie() - if i==0 and self._porch is True: - svg += self._do_porch(False) - elif len(self._innie)-1 > i: - svg += self._rline_to(0, 2*self._innie_y2+self._innie_spacer) - svg += self._rline_to(0, self._expand_y) - svg += self._corner(-1, 1) - svg += self.line_to(xx, self._y) - svg += self._rline_to(-self._expand_x, 0) - if self._tab: - svg += self._do_tab() - else: - svg += self._do_tail() - svg += self._corner(-1, -1) - svg += self._rline_to(0, -self._expand_y) - if True in self._innie: - svg += self.line_to(x, self._radius+self._innie_y2+\ - self._stroke_width/2.0) - svg += self._do_outie() - self.calc_w_h() - svg += self._close_path() - svg += self.style() - if self._show is True: - svg += self._show_dot() - if self._hide is True: - svg += self._hide_dot() - - svg += self.footer() - return self.header() + svg - - def basic_flow(self): - self.reset_min_max() - (x, y) = self._calculate_x_y() - self.margins[2] = 0 - self.margins[3] = 0 - svg = self.new_path(x, y) - svg += self._corner(1, -1) - svg += self._do_slot() - xx = self._x - svg += self._rline_to(self._expand_x, 0) - if self._bool: - svg += self._corner(1, 1, 90, 0, 1, True, False) - elif True in self._innie: - svg += self._corner(1, 1) - for i in range(len(self._innie)): - if self._innie[i] is True: - svg += self._do_innie() - svg += self._rline_to(0, self._innie_spacer) - else: - self.margins[2] =\ - int((self._x-self._stroke_width+0.5)*self._scale) - if self._bool is True: - svg += self._rline_to(0,self._radius/2.0) - svg += self._do_boolean() - svg += self._rline_to(0,self._stroke_width) - if self._else: - svg += self._rline_to(self._radius*3+self._slot_x*2, 0) - else: - svg += self._rline_to(self._radius+self._slot_x, 0) - hh = self._x - svg += self._corner(1, 1) - svg += self._rline_to(-self._radius,0) - if self._else: - svg += self._do_tab() - svg += self._rline_to(-self._radius*2, 0) - svg += self._do_tab() - svg += self._inverse_corner(-1, 1, 90, 0, 0, True, False) - svg += self._rline_to(0, self._expand_y) - svg += self._corner(-1, 1, 90, 0, 1, False, True) - svg += self.line_to(xx, self._y) - if self._tab: - svg += self._do_tab() - else: - svg += self._do_tail() - svg += self._corner(-1, -1) - svg += self._rline_to(0, -self._expand_y) - if True in self._innie: - svg += self.line_to(x, self._radius+self._innie_y2+\ - self._stroke_width) - svg += self._close_path() - self.calc_w_h() - svg += self.style() - if self._hide is True: - svg += self._hide_dot() - if self._show is True: - svg += self._show_dot() - svg += self.footer() - return self.header() + svg - - def portfolio(self): - self.reset_min_max() - (x, y) = self._calculate_x_y() - self.margins[0] = int(x+2*self._stroke_width+0.5) - self.margins[1] = int(y+self._stroke_width+0.5+self._slot_y) - self.margins[2] = 0 - self.margins[3] = 0 - x += self._innie_x1+self._innie_x2 - svg = self.new_path(x, y) - svg += self._corner(1, -1) - svg += self._do_slot() - xx = self._x - svg += self._rline_to(self._expand_x, 0) - svg += self._corner(1, 1) - svg += self._rline_to(0, self._expand_y) - for i in range(len(self._innie)): - if self._innie[i] is True and i > 0 and self._draw_innies: - svg += self._do_innie() - svg += self._rline_to(0, 2*self._innie_y2+self._innie_spacer) - else: - svg += self._rline_to(0, 2*self._innie_y2+self._innie_spacer) - svg += self._corner(-1, 1) - svg += self.line_to(xx, self._y) - svg += self._do_tab() - svg += self._corner(-1, -1) - for i in range(len(self._innie)): - if self._innie[len(self._innie)-i-1] is True: - svg += self._rline_to(0, -2*self._innie_y2-self._innie_spacer) - svg += self._do_reverse_innie() - else: - svg += self._rline_to(0, -2*self._innie_y2-self._innie_spacer) - svg += self._close_path() - self.calc_w_h() - svg += self.style() - svg += self.footer() - return self.header() + svg - - def basic_box(self): - self.reset_min_max() - self.set_outie(True) - x = self._stroke_width/2.0+self._innie_x1+self._innie_x2 - self.margins[0] = int((x+self._stroke_width+0.5)*self._scale) - self.margins[1] = int((self._stroke_width+0.5)*self._scale) - self.margins[2] = 0 - self.margins[3] = 0 - svg = self.new_path(x, self._stroke_width/2.0) - svg += self._rline_to(self._expand_x, 0) - svg += self._rline_to(0, 2*self._radius+self._innie_y2+self._expand_y) - svg += self._rline_to(-self._expand_x, 0) - svg += self.line_to(x, self._radius+self._innie_y2+\ - self._stroke_width/2.0) - svg += self._do_outie() - svg += self._close_path() - self.calc_w_h() - svg += self.style() - svg += self.footer() - return self.header() + svg - - def boolean_and_or(self): - self.reset_min_max() - svg = self._start_boolean(self._stroke_width/2.0, - self._radius*5.5+self._stroke_width/2.0+\ - self._innie_y2+self._innie_spacer) - svg += self._rline_to(0,-self._radius*3.5-self._innie_y2-\ - self._innie_spacer-self._stroke_width) - svg += self._rarc_to(1, -1) - svg += self._rline_to(self._radius/2.0+self._expand_x, 0) - xx = self._x - svg += self._rline_to(0,self._radius/2.0) - svg += self._do_boolean() - svg += self._rline_to(0,self._radius*1.5+self._innie_y2+\ - self._innie_spacer) - svg += self._do_boolean() - svg += self._rline_to(0,self._radius/2.0) - svg += self.line_to(xx, self._y) - svg += self._rline_to(-self._expand_x, 0) - svg += self._end_boolean() - self.margins[0] = int((self._radius+self._stroke_width+0.5)*self._scale) - self.margins[1] = int(self._stroke_width*self._scale) - self.margins[2] = int(self._stroke_width*self._scale) - self.margins[3] = int(self._stroke_width*self._scale) - return self.header() + svg - - def boolean_not(self): - self.reset_min_max() - svg = self._start_boolean(self._stroke_width/2.0, - self._radius*2.0+self._stroke_width/2.0) - svg += self._rline_to(0,-self._stroke_width) - svg += self._rarc_to(1, -1) - svg += self._rline_to(self._radius/2.0+self._expand_x, 0) - xx = self._x - svg += self._rline_to(0,self._radius/2.0) - svg += self._do_boolean() - svg += self._rline_to(0,self._radius/2.0) - svg += self.line_to(xx, self._y) - svg += self._rline_to(-self._expand_x, 0) - svg += self._end_boolean() - self.margins[0] = int((self._radius+self._stroke_width+0.5)*self._scale) - self.margins[1] = int(self._stroke_width*self._scale) - self.margins[2] = int((self._radius+self._stroke_width+0.5)*self._scale) - self.margins[3] = int(self._stroke_width*self._scale) - return self.header() + svg - - def boolean_compare(self): - self.reset_min_max() - yoffset = self._radius*2+2*self._innie_y2+\ - self._innie_spacer+self._stroke_width/2.0 - if self._porch is True: - yoffset += self._porch_y - svg = self._start_boolean(self._stroke_width/2.0, yoffset) - yoffset = -2*self._innie_y2-self._innie_spacer-self._stroke_width - if self._porch is True: - yoffset -= self._porch_y - svg += self._rline_to(0, yoffset) - svg += self._rarc_to(1, -1) - svg += self._rline_to(self._radius/2.0+self._expand_x, 0) - svg += self._rline_to(0,self._radius) - xx = self._x - svg += self._do_innie() - if self._porch is True: - svg += self._do_porch() - else: - svg += self._rline_to(0, 2*self._innie_y2+self._innie_spacer) - svg += self._do_innie() - svg += self._rline_to(0, self._radius) - svg += self.line_to(xx, self._y) - svg += self._rline_to(-self._expand_x, 0) - svg += self._end_boolean() - self.margins[0] = int((self._radius+self._stroke_width)*self._scale) - self.margins[1] = int(self._stroke_width*self._scale) - self.margins[2] = int(self._stroke_width*self._scale) - self.margins[3] = int(self._stroke_width*self._scale) - return self.header() + svg - - def turtle(self, colors): - self.reset_min_max() - self._fill, self._stroke = colors[0], colors[1] - svg = "%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s" % (" \n") - svg +="%s%s%s%s%s%s" % (" \n") - self._width, self._height = 55, 55 - svg += self.footer() - return self.header() + svg - - def palette(self, width, height): - self.reset_min_max() - self._width, self._height = width, height - self._fill, self._stroke = "#FFD000", "none" - svg = self._rect(width, height, 0, 0) - self._hide_x = (width-self._radius*1.5)/2 - self._hide_y = (height-self._radius*1.5)/2 - svg += self._hide_dot(True) - svg += self.footer() - return self.header() + svg - - def toolbar(self, width, height): - self.reset_min_max() - self._width, self._height = width, height - self._fill, self._stroke = "#282828", "none" - svg = self._rect(width, height, 0, 0) - svg += self.footer() - return self.header() + svg - - def sandwich_top(self): - self.reset_min_max() - x = self._stroke_width/2.0 - y = self._stroke_width/2.0+self._radius - self.margins[0] = int((x+self._stroke_width+0.5)*self._scale) - self.margins[1] = int((self._stroke_width+0.5)*self._scale) - self.margins[2] = 0 - self.margins[3] = 0 - svg = self.new_path(x, y) - svg += self._corner(1, -1) - svg += self._rline_to(self._radius+self._stroke_width, 0) - svg += self._do_slot() - svg += self._rline_to(self._expand_x, 0) - xx = self._x - svg += self._corner(1, 1) - svg += self._do_innie() - svg += self._corner(-1, 1) - svg += self.line_to(xx, self._y) - svg += self._rline_to(-self._expand_x, 0) - svg += self._do_tab() - if self._no_arm: - svg += self._rline_to(-self._radius-self._stroke_width, 0) - svg += self._corner(-1, -1) - else: - svg += self._inverse_corner(-1, 1, 90, 0, 0) - svg += self._rline_to(0, self._expand_y) - svg += self._rline_to(-self._radius, 0) - svg += self._close_path() - self.calc_w_h() - svg += self.style() - svg += self.footer() - return self.header() + svg - - def sandwich_bottom(self): - self.reset_min_max() - x = self._stroke_width/2.0 - y = self._stroke_width/2.0 - self.margins[0] = int((x+self._stroke_width+0.5)*self._scale) - self.margins[1] = int((self._stroke_width+0.5)*self._scale) - self.margins[2] = 0 - self.margins[3] = 0 - svg = self.new_path(x, y) - svg += self._rline_to(self._radius, 0) - svg += self._rline_to(0, self._expand_y) - svg += self._inverse_corner(1, 1, 90, 0, 0) - svg += self._do_slot() - svg += self._rline_to(self._radius, 0) - svg += self._corner(-1, 1) - svg += self._do_tab() - svg += self._rline_to(-self._radius-self._stroke_width,0) - svg += self._corner(-1, -1) - svg += self._close_path() - self.calc_w_h() - svg += self.style() - self._hide_x = x + self._radius/2 - self._hide_y = y + self._radius/2 - if self._hide is True: - svg += self._hide_dot() - if self._show is True: - svg += self._show_dot() - svg += self.footer() - return self.header() + svg - - # - # Utility methods - # - def set_draw_innies(self, flag=True): - self._draw_innies = flag - - def set_hide(self, flag=False): - self._hide = flag - - def set_show(self, flag=False): - self._show = flag - - def get_width(self): - return self._width - - def get_height(self): - return self._height - - def get_innie_width(self): - return (self._innie_x1+self._innie_x2)*self._scale - - def get_slot_depth(self): - return self._slot_y*self._scale - - def clear_docks(self): - self.docks = [] - - def set_scale(self, scale=1): - self._scale = scale - - def set_orientation(self, orientation=0): - self._orientation = orientation - - def expand(self, w=0, h=0): - self._expand_x = w - self._expand_y = h - - def set_stroke_width(self, stroke_width=1.5): - self._stroke_width = stroke_width - self._calc_porch_params() - - def set_colors(self, colors=["#00FF00","#00A000"]): - self._fill = colors[0] - self._stroke = colors[1] - - def set_fill_color(self, color="#00FF00"): - self._fill = color - - def set_stroke_color(self, color="#00A000"): - self._stroke = color - - def set_gradiant(self, flag=False): - self._gradiant = flag - - def set_innie(self, innie_array=[False]): - self._innie = innie_array - - def set_outie(self, flag=False): - self._outie = flag - - def set_slot(self, flag=True): - self._slot = flag - if self._slot is True: - self._cap = False - - def set_cap(self, flag=False): - self._cap = flag - if self._cap is True: - self._slot = False - - def set_tab(self, flag=True): - self._tab = flag - - def set_porch(self, flag=False): - self._porch = flag - - def set_boolean(self, flag=False): - self._bool = flag - - def set_else(self, flag=False): - self._else = flag - - def set_no_arm(self, flag=True): - self._no_arm = flag - - def reset_min_max(self): - self._min_x = 10000 - self._min_y = 10000 - self._max_x = -10000 - self._max_y = -10000 - - # - # Exotic methods - # - - def set_radius(self, radius=8): - self._radius = radius - - def set_innie_params(self, x1=4, y1=3, x2=4, y2=4): - self._innie_x1 = x1 - self._innie_y1 = y1 - self._innie_x2 = x2 - self._innie_y2 = y2 - self._calc_porch_params() - - def set_innie_spacer(self, innie_spacer = 0): - self._innie_spacer = innie_spacer - - def set_slot_params(self, x=12, y=4): - self._slot_x = x - self._slot_y = y - - def _calc_porch_params(self): - self._porch_x = self._innie_x1+self._innie_x2+4*self._stroke_width - self._porch_y = self._innie_y1+self._innie_y2+4*self._stroke_width - - # - # SVG helper methods - # - def header(self, center=False): - return "%s%s%s%s%s%s%.1f%s%s%.1f%s%s%s" % ( - "\n", - self._defs(), - self._transform(center)) - - def _defs(self): - if self._gradiant is True: - return "%s%s%s%s%s%s%s%s%s%s%s%s%.1f%s%s%.1f%s%s%.1f%s%s" % ( - " \n \n", - " \n", - " \n", - " \n", - " \n \n") - else: - return "" - - def _transform(self, center): - if self._orientation != 0: - orientation = "\n" % ( - self._orientation, self._width/2.0, self._height/2.0) - else: - orientation = "" - if center: - return "\n" % ( - -self._min_x, -self._min_y) - else: - return "\n%s" % ( - self._scale, self._scale, orientation ) - - def footer(self): - if self._orientation != 0: - return " \n\n\n" - else: - return " \n\n" - - def style(self): - if self._gradiant is True: - fill = "url(#linearGradient5678)" - else: - fill = self._fill - return "%s%s;%s%s;%s%.1f;%s%s" % ( - " style=\"fill:",fill, - "fill-opacity:1;stroke:",self._stroke, - "stroke-width:",self._stroke_width, - "stroke-linecap:round;", - "stroke-opacity:1;\" />\n") - - def text(self, x, y, size, width, string): - self._x = x - self._y = y - self._check_min_max() - self._x = x+width - self._y = y-size - self._check_min_max() - return " %s%.1f%s%s%s%.1f%s%.1f%s%.1f%s%s%s%s%s" % ( - "\n ", - string, "\n \n") - - def image(self, x, y, w, h, path, image_data=None): - self._x = x - self._y = y - self._check_min_max() - self._x = x+w - self._y = y+h - self._check_min_max() - if image_data == None: - return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % ( - "\n") - else: - return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % ( - "\n") - - - def _circle(self, r, cx, cy): - return "%s%s%s%s%s%f%s%f%s%f%s" % ("\n") - - def _rect(self, w, h, x, y): - return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("\n") - - def background(self, fill): - return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("\n") - - def _check_min_max(self): - if self._x < self._min_x: - self._min_x = self._x - if self._y < self._min_y: - self._min_y = self._y - if self._x > self._max_x: - self._max_x = self._x - if self._y > self._max_y: - self._max_y = self._y - - def line_to(self, x, y): - self._check_min_max() - if self._x == x and self._y == y: - return "" - else: - self._x = x - self._y = y - self._check_min_max() - return "L %.1f %.1f " % (x, y) - - def _rline_to(self, dx, dy): - if dx == 0 and dy == 0: - return "" - else: - return self.line_to(self._x+dx, self._y+dy) - - def arc_to(self, x, y, r, a=90, l=0, s=1): - self._check_min_max() - if r == 0: - return self.line_to(x, y) - else: - self._x = x - self._y = y - self._check_min_max() - return "A %.1f %.1f %.1f %d %d %.1f %.1f " % ( - r, r, a, l, s, x, y) - - def _rarc_to(self, sign_x, sign_y, a=90, l=0, s=1): - if self._radius == 0: - return "" - else: - x = self._x + sign_x*self._radius - y = self._y + sign_y*self._radius - return self.arc_to(x, y, self._radius, a, l, s) - - def _inverse_corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, - end=True): - r2 = self._stroke_width+self._radius/2.0 - if start: - if sign_x*sign_y == -1: - svg_str =self._rline_to(sign_x*(r2-self._stroke_width), 0) - else: - svg_str =self._rline_to(0, sign_y*+(r2-self._stroke_width)) - x = self._x + sign_x*r2 - y = self._y + sign_y*r2 - svg_str += self.arc_to(x, y, r2, a, l, s) - if end: - if sign_x*sign_y == -1: - svg_str +=self._rline_to(0, sign_y*(r2-self._stroke_width)) - else: - svg_str +=self._rline_to(sign_x*(r2-self._stroke_width), 0) - return svg_str - - def _corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, end=True): - svg_str = "" - if sign_x == 1 and sign_y == -1: - self._hide_x = self._x + self._radius/2 - self._hide_y = self._y - self._radius/2 - if sign_x == -1 and sign_y == 1: - self._show_x = self._x - self._radius/2 - self._show_y = self._y + self._radius/2 - if True in self._innie: - self._show_x -= (self._innie_x1+self._innie_x2) - self._show_y -= (self._innie_y1+self._innie_y2) - if self._radius > 0: - r2 = self._radius/2.0 - if start: - if sign_x*sign_y == 1: - svg_str +=self._rline_to(sign_x*r2, 0) - else: - svg_str +=self._rline_to(0, sign_y*r2) - x = self._x + sign_x*r2 - y = self._y + sign_y*r2 - svg_str += self.arc_to(x, y, r2, a, l, s) - if end: - if sign_x*sign_y == 1: - svg_str +=self._rline_to(0, sign_y*r2) - else: - svg_str +=self._rline_to(sign_x*r2, 0) - return svg_str - - def new_path(self, x, y): - """ - self._min_x = x - self._min_y = y - self._max_x = x - self._max_y = y - """ - self._x = x - self._y = y - return " %d" % (heading, i) - - def set_color(self, color): - """ Set the pen color for this turtle. """ - self.pen_color = color - - def set_gray(self, gray): - """ Set the pen gray level for this turtle. """ - self.pen_gray = gray - - def set_shade(self, shade): - """ Set the pen shade for this turtle. """ - self.pen_shade = shade - - def set_pen_size(self, pen_size): - """ Set the pen size for this turtle. """ - self.pen_size = pen_size - - def set_pen_state(self, pen_state): - """ Set the pen state (down==True) for this turtle. """ - self.pen_state = pen_state - - def hide(self): - """ Hide the turtle. """ - if self.spr is not None: - self.spr.hide() - self.hidden = True - - def show(self): - """ Show the turtle. """ - if self.spr is not None: - self.spr.set_layer(TURTLE_LAYER) - self.hidden = False - self.move((self.x, self.y)) - self.set_heading(self.heading) - - def move(self, pos): - """ Move the turtle. """ - self.x, self.y = pos[0], pos[1] - if self.hidden is False and self.spr is not None: - self.spr.move(pos) - return(self.x, self.y) - - def get_xy(self): - """ Return the turtle's x, y coordinates. """ - return(self.x, self.y) - - def get_heading(self): - """ Return the turtle's heading. """ - return(self.heading) - - def get_color(self): - """ Return the turtle's color. """ - return(self.pen_color) - - def get_gray(self): - """ Return the turtle's gray level. """ - return(self.pen_gray) - - def get_shade(self): - """ Return the turtle's shade. """ - return(self.pen_shade) - - def get_pen_size(self): - """ Return the turtle's pen size. """ - return(self.pen_size) - - def get_pen_state(self): - """ Return the turtle's pen state. """ - return(self.pen_state) diff --git a/tautils.py b/tautils.py deleted file mode 100644 index e7888ea..0000000 --- a/tautils.py +++ /dev/null @@ -1,705 +0,0 @@ -#Copyright (c) 2007-8, Playful Invention Company. -#Copyright (c) 2008-10, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import gtk -import pickle -import subprocess -try: - OLD_SUGAR_SYSTEM = False - import json - json.dumps - from json import load as jload - from json import dump as jdump -except (ImportError, AttributeError): - try: - import simplejson as json - from simplejson import load as jload - from simplejson import dump as jdump - except: - OLD_SUGAR_SYSTEM = True -from taconstants import STRING_OR_NUMBER_ARGS, HIDE_LAYER, CONTENT_ARGS, \ - COLLAPSIBLE, BLOCK_LAYER, CONTENT_BLOCKS -from StringIO import StringIO -import os.path -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): - try: - return fn(x) - except ValueError: - if try_ord: - xx, flag = chr_to_ord(x) - if flag: - 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: - try: - return ord(x[0]), True - except ValueError: - return x, False - return x, False - -def strtype(x): - """ Is x a string type? """ - if type(x) == str: - return True - if type(x) == unicode: - return True - return False - -def magnitude(pos): - """ Calculate the magnitude of the distance between to blocks. """ - x, y = pos - return x*x+y*y - -def json_load(text): - """ Load JSON data using what ever resources are available. """ - if OLD_SUGAR_SYSTEM is True: - _listdata = json.read(text) - else: - # strip out leading and trailing whitespace, nulls, and newlines - text = text.lstrip() - 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) - -def _tuplify(tup): - """ Convert to tuples """ - if type(tup) is not list: - 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: - return json.write(data) - else: - _io = StringIO() - 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)) - _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)) - _dialog.set_default_response(gtk.RESPONSE_OK) - if save_file_name is not None: - _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") - try: - _data = pickle.load(file_handle) - except: - # Rewind necessary because of failed pickle.load attempt - file_handle.seek(0) - _text = file_handle.read() - _data = data_from_string(_text) - file_handle.close() - return _data - -def data_from_string(text): - """ JSON load data from a string. """ - return json_load(text) - -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) - -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.set_name("Turtle Art") - dialog.add_filter(file_filter) - dialog.set_current_folder(load_save_folder) - _response = dialog.run() - if _response == gtk.RESPONSE_OK: - _result = dialog.get_filename() - load_save_folder = dialog.get_current_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, - canvas.height) - _pixbuf.get_from_drawable(canvas.canvas.images[0], - canvas.canvas.images[0].get_colormap(), - 0, 0, 0, 0, canvas.width, canvas.height) - if 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: - _pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(dsobject.file_path, - int(w), int(h)) - except: - try: - _pixbufloader = \ - gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - _pixbufloader.set_size(min(300, int(w)), min(225, int(h))) - _pixbufloader.write(dsobject.metadata['preview']) - _pixbufloader.close() - _pixbuf = _pixbufloader.get_pixbuf() - except: - _pixbuf = None - return _pixbuf - -def get_path(activity, subpath ): - """ Find a Rainbow-approved place for temporary files. """ - try: - return(os.path.join(activity.get_activity_root(), subpath)) - except: - # Early versions of Sugar didn't support get_activity_root() - 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') - if pixbuf != None: - pixbuf.save(_file_name, "png") - _base64 = os.path.join(get_path(activity, 'instance'), 'base64tmp') - _cmd = "base64 <" + _file_name + " >" + _base64 - subprocess.check_call(_cmd, shell=True) - _file_handle = open(_base64, 'r') - _data = _file_handle.read() - _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): - """ 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: - float(num) - except TypeError: - _logger.debug("error trying to convert %s to number" % (str(num))) - raise pythonerror("#syntaxerror") - - if int(float(num)) == num: - return int(num) - else: - if float(num)<0: - _nn = int((float(num)-0.005)*100)/100. - else: - _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 spr.label_safe_width(), spr.label_safe_height() - - - -# 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 == 'sandwichtop': - 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 == 'sandwichtop': - _bot = find_sandwich_bottom(top) - if _bot is None: - return - if top.ey > 0: - top.reset_y() - _ty = top.spr.get_xy()[1] - _th = top.spr.get_dimensions()[1] - _by = _bot.spr.get_xy()[1] - _dy = _by-(_ty + _th) - if _dy > 0: - 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. - _blk = blk.connections[0] - while _blk is not None: - if _blk.name in COLLAPSIBLE: - return None - if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while']: - if blk != _blk.connections[len(_blk.connections) - 1]: - return None - if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': - return _blk - blk = _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. - _blk = blk.connections[len(blk.connections) - 1] - while _blk is not None: - if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': - return None - if _blk.name in COLLAPSIBLE: - return _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 == 'sandwichtop' or blk.name == 'sandwichtop2': - return blk - # Always follow the main branch of a flow: the last connection. - _blk = blk.connections[len(blk.connections) - 1] - while _blk is not None: - if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': - return _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]) - _hit_bottom = False - _bot = find_sandwich_bottom(top) - for _blk in _group: - if not _hit_bottom and _blk == _bot: - _hit_bottom = True - if len(_blk.values) == 0: - _blk.values.append(0) - else: - _blk.values[0] = 0 - _olddx = _blk.docks[1][2] - _olddy = _blk.docks[1][3] - # Replace 'sandwichcollapsed' shape with 'sandwichbottom' shape - _blk.name = 'sandwichbottom' - _blk.spr.set_label(' ') - _blk.svg.set_show(False) - _blk.svg.set_hide(True) - _blk.refresh() - # Redock to previous block in group - _you = _blk.connections[0] - (_yx, _yy) = _you.spr.get_xy() - _yd = _you.docks[len(_you.docks) - 1] - (_bx, _by) = _blk.spr.get_xy() - _dx = _yx + _yd[2] - _blk.docks[0][2] - _bx - _dy = _yy + _yd[3] - _blk.docks[0][3] - _by - _blk.spr.move_relative((_dx, _dy)) - # Since the shapes have changed, the dock positions have too. - _newdx = _blk.docks[1][2] - _newdy = _blk.docks[1][3] - _dx += _newdx - _olddx - _dy += _newdy - _olddy - else: - if not _hit_bottom: - _blk.spr.set_layer(BLOCK_LAYER) - _blk.status = None - else: - _blk.spr.move_relative((_dx, _dy)) - # Add 'sandwichtop' arm - top.name = 'sandwichtop' - 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: - return - if looping and top.name == 'sandwichtop' or top.name == 'sandwichtop2': - restore_stack(top) - return - if len(top.connections) == 0: - return - _blk = top.connections[len(top.connections) - 1] - while _blk is not None: - if _blk.name in COLLAPSIBLE: - return - if _blk.name == 'sandwichtop' or _blk.name == 'sandwichtop2': - restore_stack(_blk) - return - # Follow a fork - if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while', 'until']: - top = find_sandwich_top_below( - _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]) - 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 - if top == None or top.spr == None: - return - uncollapse_forks(top) - _hit_bottom = False - _bot = find_sandwich_bottom(top) - _group = find_group(top.connections[len(top.connections) - 1]) - for _blk in _group: - if not _hit_bottom and _blk == _bot: - _hit_bottom = True - # Replace 'sandwichbottom' shape with 'sandwichcollapsed' shape - if len(_blk.values) == 0: - _blk.values.append(1) - else: - _blk.values[0] = 1 - _olddx = _blk.docks[1][2] - _olddy = _blk.docks[1][3] - _blk.name = 'sandwichcollapsed' - _blk.svg.set_show(True) - _blk.svg.set_hide(False) - _blk._dx = 0 - _blk._ey = 0 - _blk.spr.set_label(' ') - _blk.resize() - _blk.spr.set_label(_('click to open')) - _blk.resize() - # Redock to sandwich top in group - _you = find_sandwich_top(_blk) - (_yx, _yy) = _you.spr.get_xy() - _yd = _you.docks[len(_you.docks) - 1] - (_bx, _by) = _blk.spr.get_xy() - _dx = _yx + _yd[2] - _blk.docks[0][2] - _bx - _dy = _yy + _yd[3] - _blk.docks[0][3] - _by - _blk.spr.move_relative((_dx, _dy)) - # Since the shapes have changed, the dock positions have too. - _newdx = _blk.docks[1][2] - _newdy = _blk.docks[1][3] - _dx += _newdx - _olddx - _dy += _newdy - _olddy - else: - if not _hit_bottom: - _blk.spr.set_layer(HIDE_LAYER) - _blk.status = 'collapsed' - else: - _blk.spr.move_relative((_dx, _dy)) - # Remove 'sandwichtop' arm - top.name = 'sandwichtop2' - top.refresh() - -def collapsed(blk): - """ Is this stack collapsed? """ - if blk is not None and blk.name in COLLAPSIBLE and\ - len(blk.values) == 1 and blk.values[0] != 0: - return True - return False - -def collapsible(blk): - """ Can this stack be collapsed? """ - if blk is None or blk.name not in COLLAPSIBLE: - return False - if find_sandwich_top(blk) is None: - 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)) - if (_red == 255 and _green == 0) or _green == 255: - return True - 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)) - if _green == 254: - return True - 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): - if convert(value, float) == 0: - return True - return False - -def neg_arg(value): - """ Dock test: looking for a negative argument """ - if numeric_arg(value): - if convert(value, float) < 0: - 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] - _dock2 = block2.docks[dock2n] - _d1type, _d1dir, _d1x, _d1y = _dock1[0:4] - _d2type, _d2dir, _d2x, _d2y = _dock2[0:4] - if block1 == block2: - return (100, 100) - if _d1dir == _d2dir: - return (100, 100) - if (_d2type is not 'number') or (dock2n is not 0): - if block1.connections is not None and \ - dock1n < len(block1.connections) and \ - block1.connections[dock1n] is not None: - return (100, 100) - if block2.connections is not None and \ - dock2n < len(block2.connections) and \ - block2.connections[dock2n] is not None: - return (100, 100) - if _d1type != _d2type: - if block1.name in STRING_OR_NUMBER_ARGS: - if _d2type == 'number' or _d2type == 'string': - pass - elif block1.name in CONTENT_ARGS: - if _d2type in CONTENT_BLOCKS: - pass - else: - return (100, 100) - (_b1x, _b1y) = block1.spr.get_xy() - (_b2x, _b2y) = block2.spr.get_xy() - return ((_b1x + _d1x) - (_b2x + _d2x), (_b1y + _d1y) - (_b2y + _d2y)) - -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: - return True - if blk1.name in ['sqrt', 'number', 'string'] and\ - blk2.name in ['sqrt', 'number', 'string']: - if blk1.name == 'number' or blk1.name == 'string': - if not numeric_arg(blk1.values[0]) or neg_arg(blk1.values[0]): - return False - elif blk2.name == 'number' or blk2.name == 'string': - if not numeric_arg(blk2.values[0]) or neg_arg(blk2.values[0]): - return False - elif blk1.name in ['division2', 'number', 'string'] and\ - blk2.name in ['division2', 'number', 'string']: - if blk1.name == 'number' or blk1.name == 'string': - if not numeric_arg(blk1.values[0]): - return False - if dock2 == 2 and zero_arg(blk1.values[0]): - return False - elif blk2.name == 'number' or blk2.name == 'string': - if not numeric_arg(blk2.values[0]): - return False - if dock1 == 2 and zero_arg(blk2.values[0]): - return False - elif blk1.name in ['product2', 'minus2', 'random', 'remainder2', - 'string'] and\ - blk2.name in ['product2', 'minus2', 'random', 'remainder2', - 'string']: - if blk1.name == 'string': - if not numeric_arg(blk1.values[0]): - return False - elif blk1.name == 'string': - if not numeric_arg(blk2.values[0]): - return False - elif blk1.name in ['greater2', 'less2'] and blk2.name == 'string': - # Non-numeric stings are OK if only both args are strings; - # Lots of test conditions... - if dock1 == 1 and blk1.connections[2] is not None: - if blk1.connections[2].name == 'number': - if not numeric_arg(blk2.values[0]): - return False - elif dock1 == 2 and blk1.connections[1] is not None: - if blk1.connections[1].name == 'number': - if not numeric_arg(blk2.values[0]): - return False - elif blk2.name in ['greater2', 'less2'] and blk1.name == 'string': - if dock2 == 1 and blk2.connections[2] is not None: - if blk2.connections[2].name == 'number': - if not numeric_arg(blk1.values[0]): - return False - elif dock2 == 2 and blk2.connections[1] is not None: - if blk2.connections[1].name == 'number': - if not numeric_arg(blk1.values[0]): - return False - elif blk1.name in ['greater2', 'less2'] and blk2.name == 'number': - if dock1 == 1 and blk1.connections[2] is not None: - if blk1.connections[2].name == 'string': - if not numeric_arg(blk1.connections[2].values[0]): - return False - elif dock1 == 2 and blk1.connections[1] is not None: - if blk1.connections[1].name == 'string': - if not numeric_arg(blk1.connections[1].values[0]): - return False - elif blk2.name in ['greater2', 'less2'] and blk1.name == 'number': - if dock2 == 1 and blk2.connections[2] is not None: - if blk2.connections[2].name == 'string': - if not numeric_arg(blk2.connections[2].values[0]): - return False - elif dock2 == 2 and blk2.connections[1] is not None: - if blk2.connections[1].name == 'string': - if not numeric_arg(blk2.connections[1].values[0]): - return False - return True - -def xy(event): - """ Where is the mouse event? """ - return map(int, event.get_coords()) - -""" -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) - if blk == _top and blk.name[0:3] is not 'def': - return True - else: - return False - -def find_top_block(blk): - """ Find the top block in a stack. """ - if blk is None: - return None - if len(blk.connections) == 0: - return blk - while blk.connections[0] is not None: - blk = blk.connections[0] - return blk - -def find_start_stack(blk): - """ Find a stack with a 'start' block on top. """ - if blk is None: - return False - if find_top_block(blk).name == 'start': - return True - else: - return False - -def find_group(blk): - """ Find the connected group of block in a stack. """ - if blk is None: - return [] - _group = [blk] - if blk.connections is not None: - for _blk2 in blk.connections[1:]: - if _blk2 is not None: - _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: - return - _group = find_group(blk) - for _gblk in _group: - if _gblk.name == 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) - if blk == top: - code = tw.lc.run_blocks(top, tw.block_list.list, False) - return code - else: - return [] diff --git a/tawindow.py b/tawindow.py deleted file mode 100644 index 3d62a3f..0000000 --- a/tawindow.py +++ /dev/null @@ -1,2336 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) 2007, Playful Invention Company -#Copyright (c) 2008-10, Walter Bender -#Copyright (c) 2009-10 Raúl Gutiérrez Segalés - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import os -import os.path -from math import atan2, pi -DEGTOR = 2*pi/360 -from gettext import gettext as _ - -try: - from sugar.graphics.objectchooser import ObjectChooser - from sugar.datastore import datastore - from sugar import profile -except ImportError: - pass - -from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ - PALETTE_NAMES, TITLEXY, MEDIA_SHAPES, STATUS_SHAPES, \ - OVERLAY_SHAPES, TOOLBAR_SHAPES, TAB_LAYER, \ - 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, \ - DEAD_DICTS, DEAD_KEYS, TEMPLATES, PYTHON_SKIN, \ - PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK, OLD_NAMES, \ - BOOLEAN_STYLE, BLOCK_NAMES -from talogo import LogoCode, stop_logo -from tacanvas import TurtleGraphics -from tablock import Blocks, Block -from taturtle import Turtles, Turtle -from tautils import magnitude, get_load_name, get_save_name, data_from_file, \ - data_to_file, round_int, get_id, get_pixbuf_from_journal, \ - movie_media_type, audio_media_type, image_media_type, \ - save_picture, save_svg, calc_image_size, get_path, \ - reset_stack_arm, grow_stack_arm, find_sandwich_top, \ - find_sandwich_bottom, restore_stack, collapse_stack, \ - collapsed, collapsible, hide_button_hit, show_button_hit, \ - arithmetic_check, xy, find_block_to_run, find_top_block, \ - find_start_stack, find_group, find_blk_below, olpc_xo_1, \ - dock_dx_dy, data_to_string -from tasprite_factory import SVG, svg_str_to_pixbuf, svg_from_file -from sprites import Sprites, Sprite - -import logging -_logger = logging.getLogger('turtleart-activity') - -class TurtleArtWindow(): - """ TurtleArt Window class abstraction """ - timeout_tag = [0] - - def __init__(self, win, path, parent=None, mycolors=None): - self._loaded_project = "" - self.win = None - self.parent = parent - if type(win) == gtk.DrawingArea: - self.interactive_mode = True - self.window = win - self.window.set_flags(gtk.CAN_FOCUS) - if self.parent is not None: - self.parent.show_all() - self.running_sugar = True - else: - self.window.show_all() - self.running_sugar = False - self.area = self.window.window - self.gc = self.area.new_gc() - self._setup_events() - elif type(win) == gtk.gdk.Pixmap: - self.interactive_mode = False - self.window = win - self.running_sugar = False - self.gc = self.window.new_gc() - else: - _logger.debug("bad win type %s" % (type(win))) - - if self.running_sugar: - self.activity = parent - self.nick = profile.get_nick_name() - else: - self.activity = None - self.nick = None - - self.path = path - self.load_save_folder = os.path.join(path, 'samples') - self.save_folder = None - self.save_file_name = None - self.width = gtk.gdk.screen_width() - self.height = gtk.gdk.screen_height() - - self.keypress = "" - self.keyvalue = 0 - self.dead_key = "" - self.mouse_flag = 0 - self.mouse_x = 0 - self.mouse_y = 0 - - self.orientation = HORIZONTAL_PALETTE - if olpc_xo_1(): - self.lead = 1.0 - self.scale = 0.67 - if self.running_sugar and not self.activity.new_sugar_system: - self.orientation = VERTICAL_PALETTE - else: - self.lead = 1.0 - self.scale = 1.0 - self.block_scale = BLOCK_SCALE - self.trash_scale = 0.5 - self.myblock = None - self.nop = 'nop' - self.loaded = 0 - self.step_time = 0 - self.hide = False - self.palette = True - self.coord_scale = 1 - self.buddies = [] - self.saved_string = '' - self.dx = 0 - self.dy = 0 - self.media_shapes = {} - self.cartesian = False - self.polar = False - self.overlay_shapes = {} - self.toolbar_shapes = {} - self.toolbar_offset = 0 - self.status_spr = None - self.status_shapes = {} - self.toolbar_spr = None - self.palette_sprs = [] - self.palettes = [] - self.palette_button = [] - self.trash_index = PALETTE_NAMES.index('trash') - self.trash_stack = [] - self.selected_palette = None - self.previous_palette = None - self.selectors = [] - self.selected_selector = None - self.previous_selector = None - self.selector_shapes = [] - self.selected_blk = None - self.selected_spr = None - self.drag_group = None - self.drag_turtle = 'move', 0, 0 - self.drag_pos = 0, 0 - self.paste_offset = 20 - self.block_list = Blocks(self.scale) - if self.interactive_mode: - self.sprite_list = Sprites(self.window, self.area, self.gc) - else: - self.sprite_list = None # Sprites(self.window, None, self.gc) - self.turtles = Turtles(self.sprite_list) - if mycolors == None: - Turtle(self.turtles, 1) - else: - Turtle(self.turtles, 1, mycolors.split(',')) - self.active_turtle = self.turtles.get_turtle(1) - self.saving_svg = False - self.svg_string = '' - self.selected_turtle = None - self.canvas = TurtleGraphics(self, self.width, self.height) - self.titlex = -(self.canvas.width*TITLEXY[0])/(self.coord_scale*2) - self.leftx = -(self.canvas.width*TITLEXY[0])/(self.coord_scale*2) - self.rightx = 0 - self.titley = (self.canvas.height*TITLEXY[1])/(self.coord_scale*2) - self.topy = (self.canvas.height*(TITLEXY[1]-0.125))/(self.coord_scale*2) - self.bottomy = 0 - self.lc = LogoCode(self) - self.saved_pictures = [] - - if self.interactive_mode: - self._setup_misc() - self._show_toolbar_palette(0, False) - self.block_operation = '' - - def _setup_events(self): - """ Register the events we listen to. """ - self.window.add_events(gtk.gdk.BUTTON_PRESS_MASK) - self.window.add_events(gtk.gdk.BUTTON_RELEASE_MASK) - self.window.add_events(gtk.gdk.POINTER_MOTION_MASK) - self.window.add_events(gtk.gdk.KEY_PRESS_MASK) - self.window.connect("expose-event", self._expose_cb) - self.window.connect("button-press-event", self._buttonpress_cb) - self.window.connect("button-release-event", self._buttonrelease_cb) - self.window.connect("motion-notify-event", self._move_cb) - self.window.connect("key_press_event", self._keypress_cb) - - def _setup_misc(self): - """ Misc. sprites for status, overlays, etc. """ - # media blocks get positioned into other blocks - for _name in MEDIA_SHAPES: - if _name[0:7] == 'journal' and not self.running_sugar: - file_name = 'file'+_name[7:] - else: - file_name = _name - self.media_shapes[_name] = svg_str_to_pixbuf(svg_from_file( - "%s/images/%s.svg" % (self.path, file_name))) - - 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_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), - 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) - for i, _name in enumerate(TOOLBAR_SHAPES): - self.toolbar_shapes[_name] = Sprite(self.sprite_list, - i*55+offset, 0, - svg_str_to_pixbuf( - svg_from_file("%s/icons/%s.svg" % (self.path, _name)))) - self.toolbar_shapes[_name].set_layer(TAB_LAYER) - self.toolbar_shapes[_name].name = _name - self.toolbar_shapes[_name].type = 'toolbar' - self.toolbar_shapes['stopiton'].hide() - - def sharing(self): - """ Is a chattube available for share? """ - if self.running_sugar and hasattr(self.activity, 'chattube') and\ - self.activity.chattube is not None: - return True - return False - - def is_project_empty(self): - """ Check to see if project has any blocks in use """ - return len(self.just_blocks()) == 1 - - def _expose_cb(self, win, event): - """ Repaint """ - self.sprite_list.refresh(event) - # self.canvas.cr_expose(event) - return True - - def eraser_button(self): - """ Eraser_button (hide status block when clearing the screen.) """ - if self.status_spr is not None: - self.status_spr.hide() - self.lc.prim_clear() - self.display_coordinates() - - def run_button(self, time): - """ Run turtle! """ - if self.running_sugar: - self.activity.recenter() - # Look for a 'start' block - for blk in self.just_blocks(): - if find_start_stack(blk): - self.step_time = time - print "running stack starting from %s" % (blk.name) - self._run_stack(blk) - return - # If there is no 'start' block, run stacks that aren't 'def action' - for blk in self.just_blocks(): - if find_block_to_run(blk): - self.step_time = time - print "running stack starting from %s" % (blk.name) - self._run_stack(blk) - return - - def stop_button(self): - """ Stop button """ - stop_logo(self) - - def set_userdefined(self): - """ Change icon for user-defined blocks after Python code is loaded. """ - for blk in self.just_blocks(): - if blk.name in PYTHON_SKIN: - x, y = self._calc_image_offset('pythonon', blk.spr) - blk.set_image(self.media_shapes['pythonon'], x, y) - self._resize_skin(blk) - self.nop = 'pythonloaded' - - def set_fullscreen(self): - """ Enter fullscreen mode """ - if self.running_sugar: - self.activity.fullscreen() - self.activity.recenter() - - def set_cartesian(self, flag): - """ Turn on/off Cartesian coordinates """ - if flag: - if self.coord_scale == 1: - self.overlay_shapes['Cartesian_labeled'].set_layer( - OVERLAY_LAYER) - else: - self.overlay_shapes['Cartesian'].set_layer(OVERLAY_LAYER) - self.cartesian = True - else: - if self.coord_scale == 1: - self.overlay_shapes['Cartesian_labeled'].hide() - else: - self.overlay_shapes['Cartesian'].hide() - self.cartesian = False - - def set_polar(self, flag): - """ Turn on/off polar coordinates """ - if flag: - self.overlay_shapes['polar'].set_layer(OVERLAY_LAYER) - self.polar = True - else: - self.overlay_shapes['polar'].hide() - self.polar = False - - def update_overlay_position(self, widget, event): - """ Reposition the overlays when window size changes """ - self.width = event.width - self.height = event.height - for _name in OVERLAY_SHAPES: - shape = self.overlay_shapes[_name] - showing = False - if shape in shape._sprites.list: - shape.hide() - showing = True - self.overlay_shapes[_name] = Sprite(self.sprite_list, - int(self.width / 2 - 600), - int(self.height / 2 - 450), - svg_str_to_pixbuf( - svg_from_file("%s/images/%s.svg" % (self.path, _name)))) - if showing: - self.overlay_shapes[_name].set_layer(OVERLAY_LAYER) - else: - self.overlay_shapes[_name].hide() - self.overlay_shapes[_name].type = 'overlay' - self.cartesian = False - self.polar = False - self.canvas.width = self.width - self.canvas.height = self.height - self.canvas.move_turtle() - - def hideshow_button(self): - """ Hide/show button """ - if not self.hide: - for blk in self.just_blocks(): - blk.spr.hide() - self.hide_palette() - self.hide = True - else: - for blk in self.just_blocks(): - if blk.status != 'collapsed': - blk.spr.set_layer(BLOCK_LAYER) - self.show_palette() - if self.activity is not None and self.activity.new_sugar_system: - self.activity.palette_buttons[0].set_icon( - PALETTE_NAMES[0] + 'on') - self.hide = False - self.canvas.canvas.inval() - - def hideshow_palette(self, state): - """ Hide or show palette """ - if not state: - self.palette = False - if self.running_sugar: - self.activity.do_hidepalette() - self.hide_palette() - else: - self.palette = True - if self.running_sugar: - self.activity.do_showpalette() - self.show_palette() - - def show_palette(self, n=0): - """ Show palette """ - self._show_toolbar_palette(n) - self.palette_button[self.orientation].set_layer(TAB_LAYER) - self.palette_button[2].set_layer(TAB_LAYER) - if self.activity is None or not self.activity.new_sugar_system: - self.toolbar_spr.set_layer(CATEGORY_LAYER) - self.palette = True - - def hide_palette(self): - """ Hide the palette. """ - self._hide_toolbar_palette() - self.palette_button[self.orientation].hide() - self.palette_button[2].hide() - if self.activity is None or not self.activity.new_sugar_system: - self.toolbar_spr.hide() - self.palette = False - - def hideblocks(self): - """ Callback from 'hide blocks' block """ - if not self.interactive_mode: - return - self.hide = False - self.hideshow_button() - if self.running_sugar: - self.activity.do_hide() - - def showblocks(self): - """ Callback from 'show blocks' block """ - if not self.interactive_mode: - return - self.hide = True - self.hideshow_button() - if self.running_sugar: - self.activity.do_show() - - def resize_blocks(self, blocks=None): - """ Resize blocks or if blocks is None, all of the blocks """ - if blocks is None: - blocks = self.just_blocks() - - # We need to restore collapsed stacks before resizing. - for blk in blocks: - if blk.status == 'collapsed': - bot = find_sandwich_bottom(blk) - if collapsed(bot): - dy = bot.values[0] - restore_stack(find_sandwich_top(blk)) - bot.values[0] = dy - - # Do the resizing. - for blk in blocks: - blk.rescale(self.block_scale) - for blk in blocks: - self._adjust_dock_positions(blk) - - # Re-collapsed stacks after resizing. - for blk in blocks: - if collapsed(blk): - collapse_stack(find_sandwich_top(blk)) - for blk in blocks: - if blk.name == 'sandwichtop': - grow_stack_arm(blk) - - # Resize the skins on some blocks: media content and Python - for blk in blocks: - if blk.name in BLOCKS_WITH_SKIN: - self._resize_skin(blk) - - def _show_toolbar_palette(self, n, init_only=False): - """ Show the toolbar palettes, creating them on init_only """ - if (self.activity is None or not self.activity.new_sugar_system) and\ - self.selectors == []: - # Create the selectors - svg = SVG() - x, y = 50, 0 - for i, name in enumerate(PALETTE_NAMES): - a = svg_str_to_pixbuf(svg_from_file("%s/icons/%soff.svg" % ( - self.path, name))) - b = svg_str_to_pixbuf(svg_from_file("%s/icons/%son.svg" % ( - self.path, name))) - self.selector_shapes.append([a, b]) - self.selectors.append(Sprite(self.sprite_list, x, y, a)) - self.selectors[i].type = 'selector' - self.selectors[i].name = name - self.selectors[i].set_layer(TAB_LAYER) - w = self.selectors[i].get_dimensions()[0] - x += int(w) - - # Create the toolbar background - self.toolbar_offset = ICON_SIZE - self.toolbar_spr = Sprite(self.sprite_list, 0, 0, - svg_str_to_pixbuf(svg.toolbar(self.width, ICON_SIZE))) - self.toolbar_spr.type = 'toolbar' - self.toolbar_spr.set_layer(CATEGORY_LAYER) - - - if self.palette_sprs == []: - # Create the empty palettes - if len(self.palettes) == 0: - for i in range(len(PALETTES)): - self.palettes.append([]) - - # Create empty palette backgrounds - for i in PALETTE_NAMES: - self.palette_sprs.append([None, None]) - - # 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.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.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() - - # 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.palette_button[2].name = _('next') - self.palette_button[2].type = 'palette' - self.palette_button[2].set_layer(TAB_LAYER) - - if init_only: - return - - # Hide the previously displayed palette - self._hide_previous_palette() - - self.selected_palette = n - self.previous_palette = self.selected_palette - - if self.activity is None or not self.activity.new_sugar_system: - self.selected_selector = self.selectors[n] - # Make sure all of the selectors are visible. - self.selectors[n].set_shape(self.selector_shapes[n][1]) - for i in range(len(PALETTES)): - self.selectors[i].set_layer(TAB_LAYER) - - # Show the palette with the current orientation. - if self.palette_sprs[n][self.orientation] is not None: - self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) - - if self.palettes[n] == []: - # 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.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) - elif name[:8] == 'template': - self._proto_skin(name[8:], n, i) - elif name[:7] == 'picture': - self._proto_skin(name[7:], n, i) - elif name in PYTHON_SKIN: - self._proto_skin('pythonsmall', n, i) - - self._layout_palette(n) - for blk in self.palettes[n]: - blk.spr.set_layer(TAB_LAYER) - if n == self.trash_index: - for blk in self.trash_stack: - for gblk in find_group(blk): - if gblk.status != 'collapsed': - gblk.spr.set_layer(TAB_LAYER) - - def _hide_toolbar_palette(self): - """ Hide the toolbar palettes """ - self._hide_previous_palette() - if self.activity is None or not self.activity.new_sugar_system: - # Hide the selectors - for i in range(len(PALETTES)): - self.selectors[i].hide() - elif self.selected_palette is not None: - self.activity.palette_buttons[self.selected_palette].set_icon( - PALETTE_NAMES[self.selected_palette] + 'off') - self.selected_palette = None - self.previous_palette = None - - def _hide_previous_palette(self): - """ 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])): - self.palettes[self.previous_palette][i].spr.hide() - self.palette_sprs[self.previous_palette][ - self.orientation].hide() - if self.activity is None or not self.activity.new_sugar_system: - self.selectors[self.previous_palette].set_shape( - self.selector_shapes[self.previous_palette][0]) - elif self.previous_palette is not None and \ - self.previous_palette != self.selected_palette: - self.activity.palette_buttons[self.previous_palette].set_icon( - PALETTE_NAMES[self.previous_palette] + 'off') - if self.previous_palette == self.trash_index: - for blk in self.trash_stack: - for gblk in find_group(blk): - gblk.spr.hide() - - def _horizontal_layout(self, x, y, blocks): - """ Position prototypes in a horizontal palette. """ - _max_w = 0 - for blk in blocks: - _w, _h = self._width_and_height(blk) - if y + _h > PALETTE_HEIGHT + self.toolbar_offset: - 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 - for g in find_group(blk): - g.spr.move_relative((int(_dx), int(_dy))) - y += int(_h+3) - if _w > _max_w: - _max_w = _w - return x, y, _max_w - - def _vertical_layout(self, x, y, blocks): - """ Position prototypes in a vertical palette. """ - _row = [] - _row_w = 0 - _max_h = 0 - for _b in blocks: - _w, _h = self._width_and_height(_b) - if x + _w > PALETTE_WIDTH: - # Recenter row. - _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) - _max_h = 0 - _row.append(_b) - _row_w += (4 + _w) - (_bx, _by) = _b.spr.get_xy() - _dx = int(x - _bx) - _dy = int(y - _by) - for _g in find_group(_b): - _g.spr.move_relative((_dx, _dy)) - x += int(_w + 4) - if _h > _max_h: - _max_h = _h - # Recenter last row. - _dx = int((PALETTE_WIDTH - _row_w)/2) - for _r in _row: - for _g in find_group(_r): - _g.spr.move_relative((_dx, 0)) - return x, y, _max_h - - def _layout_palette(self, n): - """ Layout prototypes in a palette. """ - 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]) - if n == self.trash_index: - _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: - svg = SVG() - self.palette_sprs[n][self.orientation] = Sprite( - self.sprite_list, 0, self.toolbar_offset, - svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT))) - self.palette_sprs[n][self.orientation].type = 'category' - if n == PALETTE_NAMES.index('trash'): - 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)) - else: - _x, _y = 5, self.toolbar_offset + 15 - _x, _y, _max = self._vertical_layout(_x, _y, self.palettes[n]) - if n == PALETTE_NAMES.index('trash'): - _x, _y, _max = self._vertical_layout(_x, _y + _max, - self.trash_stack) - _h = _y + _max + 25 - self.toolbar_offset - if self.palette_sprs[n][self.orientation] is None: - svg = SVG() - self.palette_sprs[n][self.orientation] = \ - Sprite(self.sprite_list, 0, self.toolbar_offset, - svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h))) - self.palette_sprs[n][self.orientation].type = 'category' - if n == PALETTE_NAMES.index('trash'): - 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.toolbar_offset)) - self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) - - def _buttonpress_cb(self, win, event): - """ Button press """ - self.window.grab_focus() - x, y = xy(event) - self.mouse_flag = 1 - self.mouse_x = x - self.mouse_y = y - self.button_press(event.get_state()>k.gdk.CONTROL_MASK, x, y) - return True - - def button_press(self, mask, x, y, verbose=False): - if verbose: - print "processing remote button press: %d, %d" % (x, y) - self.block_operation = 'click' - - # Unselect things that may have been selected earlier - if self.selected_blk is not None: - self._unselect_block() - self.selected_turtle = None - # Always hide the status layer on a click - if self.status_spr is not None: - self.status_spr.hide() - - # Find out what was clicked - spr = self.sprite_list.find_sprite((x, y)) - self.dx = 0 - self.dy = 0 - if spr is None: - return True - self.selected_spr = spr - - # From the sprite at x, y, look for a corresponding block - blk = self.block_list.spr_to_block(spr) - if blk is not None: - if blk.type == 'block': - self.selected_blk = blk - self._block_pressed(x, y, blk) - elif blk.type == 'trash': - self._restore_from_trash(find_top_block(blk)) - elif blk.type == 'proto': - if blk.name == 'restoreall': - self._restore_all_from_trash() - elif blk.name == 'restore': - self._restore_latest_from_trash() - elif blk.name == 'empty': - self._empty_trash() - elif MACROS.has_key(blk.name): - self._new_macro(blk.name, x + 20, y + 20) - else: - blk.highlight() - self._new_block(blk.name, x, y) - blk.unhighlight() - return True - - # Next, look for a turtle - t = self.turtles.spr_to_turtle(spr) - if t is not None: - self.selected_turtle = t - self.canvas.set_turtle(self.turtles.get_turtle_key(t)) - self._turtle_pressed(x, y) - return True - - # Finally, check for anything else - if hasattr(spr, 'type'): - if spr.type == "canvas": - pass - # spr.set_layer(CANVAS_LAYER) - elif spr.type == 'selector': - self._select_category(spr) - elif spr.type == 'category': - if hide_button_hit(spr, x, y): - self.hideshow_palette(False) - elif spr.type == 'palette': - if spr.name == _('next'): - i = self.selected_palette + 1 - if i == len(PALETTE_NAMES): - i = 0 - if self.activity is None or \ - not self.activity.new_sugar_system: - self._select_category(self.selectors[i]) - else: - if self.selected_palette is not None: - self.activity.palette_buttons[ - self.selected_palette].set_icon( - PALETTE_NAMES[self.selected_palette] + 'off') - self.activity.palette_buttons[i].set_icon( - 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() - self._layout_palette(self.selected_palette) - self.show_palette(self.selected_palette) - elif spr.type == 'toolbar': - self._select_toolbar_button(spr) - return True - - def _select_category(self, spr): - """ Select a category from the toolbar (old Sugar systems only). """ - i = self.selectors.index(spr) - spr.set_shape(self.selector_shapes[i][1]) - if self.selected_selector is not None: - j = self.selectors.index(self.selected_selector) - if i == j: - return - self.selected_selector.set_shape(self.selector_shapes[j][0]) - self.previous_selector = self.selected_selector - self.selected_selector = spr - self.show_palette(i) - - def _select_toolbar_button(self, spr): - """ Select a toolbar button (Used when not running Sugar). """ - if not hasattr(spr, 'name'): - return - if spr.name == 'run-fastoff': - self.lc.trace = 0 - self.run_button(0) - elif spr.name == 'run-slowoff': - self.lc.trace = 0 - self.run_button(3) - elif spr.name == 'debugoff': - self.lc.trace = 1 - self.run_button(6) - elif spr.name == 'stopiton': - self.stop_button() - self.toolbar_shapes['stopiton'].hide() - elif spr.name == 'eraseron': - self.eraser_button() - elif spr.name == 'hideshowoff': - self.hideshow_button() - - def _put_in_trash(self, blk, x=0, y=0): - """ Put a group of blocks into the trash. """ - self.trash_stack.append(blk) - group = find_group(blk) - for gblk in group: - if gblk.status == 'collapsed': - # Collapsed stacks are restored for rescaling - # and then recollapsed after they are moved to the trash. - bot = find_sandwich_bottom(gblk) - if collapsed(bot): - dy = bot.values[0] - restore_stack(find_sandwich_top(gblk)) - bot.values[0] = dy - gblk.type = 'trash' - gblk.rescale(self.trash_scale) - blk.spr.move((x, y)) - for gblk in group: - self._adjust_dock_positions(gblk) - - # Re-collapsing any stacks we had restored for scaling - for gblk in group: - if collapsed(gblk): - collapse_stack(find_sandwich_top(gblk)) - - # And resize any skins. - 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: - gblk.spr.hide() - - def _restore_all_from_trash(self): - """ Restore all the blocks in the trash can. """ - for blk in self.block_list.list: - if blk.type == 'trash': - self._restore_from_trash(blk) - - def _restore_latest_from_trash(self): - """ Restore most recent blocks from the trash can. """ - if len(self.trash_stack) == 0: - return - self._restore_from_trash(self.trash_stack[len(self.trash_stack) - 1]) - - def _restore_from_trash(self, blk): - group = find_group(blk) - for gblk in group: - gblk.rescale(self.block_scale) - gblk.spr.set_layer(BLOCK_LAYER) - x, y = gblk.spr.get_xy() - if self.orientation == 0: - gblk.spr.move((x, y + PALETTE_HEIGHT + self.toolbar_offset)) - else: - gblk.spr.move((x + PALETTE_WIDTH, y)) - gblk.type = 'block' - for gblk in group: - self._adjust_dock_positions(gblk) - # If the stack had been collapsed before going into the trash, - # collapse it again now. - for gblk in group: - if collapsed(gblk): - collapse_stack(find_sandwich_top(gblk)) - # And resize any skins. - for gblk in group: - if gblk.name in BLOCKS_WITH_SKIN: - self._resize_skin(gblk) - - self.trash_stack.remove(blk) - - def _empty_trash(self): - """ Permanently remove all blocks presently in the trash can. """ - for blk in self.block_list.list: - if blk.type == 'trash': - blk.type = 'deleted' - blk.spr.hide() - self.trash_stack = [] - - def _in_the_trash(self, x, y): - """ Is x, y over the trash can? """ - """ - if self.selected_palette == self.trash_index and \ - self.palette_sprs[self.trash_index][self.orientation].hit((x, y)): - return True - """ - if self.selected_palette is not None and\ - self.palette_sprs[self.selected_palette][self.orientation].hit( - (x, y)): - return True - return False - - def _block_pressed(self, x, y, blk): - """ Block pressed """ - if blk is not None: - blk.highlight() - self._disconnect(blk) - self.drag_group = find_group(blk) - (sx, sy) = blk.spr.get_xy() - self.drag_pos = x-sx, y-sy - for blk in self.drag_group: - if blk.status != 'collapsed': - blk.spr.set_layer(TOP_LAYER) - self.saved_string = blk.spr.labels[0] - - def _unselect_block(self): - """ Unselect block """ - # After unselecting a 'number' block, we need to check its value - if self.selected_blk.name == 'number': - self._number_check() - elif self.selected_blk.name == 'string': - self._string_check() - self.selected_blk.unhighlight() - self.selected_blk = None - - def _new_block(self, name, x, y): - """ Make a new block. """ - if name in CONTENT_BLOCKS: - newblk = Block(self.block_list, self.sprite_list, name, x - 20, - y - 20, 'block', DEFAULTS[name], self.block_scale) - else: - newblk = Block(self.block_list, self.sprite_list, name, x - 20, - y - 20, 'block', [], self.block_scale) - - # Add a 'skin' to some blocks - if name in PYTHON_SKIN: - if self.nop == 'pythonloaded': - self._block_skin('pythonon', newblk) - else: - self._block_skin('pythonoff', newblk) - elif name in BOX_STYLE_MEDIA: - 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) - if DEFAULTS.has_key(newblk.name): - for i, argvalue in enumerate(DEFAULTS[newblk.name]): - # skip the first dock position since it is always a connector - dock = newblk.docks[i + 1] - argname = dock[0] - if argname == 'unavailable': - continue - if argname == 'media': - argname = 'journal' - elif argname == 'number' and \ - (type(argvalue) is str or type(argvalue) is unicode): - argname = 'string' - elif argname == 'bool': - argname = argvalue - elif argname == 'flow': - argname = argvalue - (sx, sy) = newspr.get_xy() - if argname is not None: - if argname in CONTENT_BLOCKS: - argblk = Block(self.block_list, self.sprite_list, - argname, 0, 0, 'block', [argvalue], - self.block_scale) - else: - argblk = Block(self.block_list, self.sprite_list, - argname, 0, 0, 'block', [], - self.block_scale) - argdock = argblk.docks[0] - nx = sx + dock[2] - argdock[2] - ny = sy + dock[3] - argdock[3] - if argname == 'journal': - self._block_skin('journaloff', argblk) - argblk.spr.move((nx, ny)) - argblk.spr.set_layer(TOP_LAYER) - argblk.connections = [newblk, None] - newblk.connections[i + 1] = argblk - self.drag_group = find_group(newblk) - self.block_operation = 'new' - - def _new_macro(self, name, x, y): - """ Create a "macro" (predefined stack of blocks). """ - macro = MACROS[name] - macro[0][2] = x - macro[0][3] = y - top = self.process_data(macro) - self.block_operation = 'new' - self._check_collapsibles(top) - self.drag_group = find_group(top) - - def process_data(self, block_data, offset=0): - """ Process block_data (from a macro, a file, or the clipboard). """ - if offset != 0: - _logger.debug("offset is %d" % (offset)) - # Create the blocks (or turtle). - blocks = [] - for blk in block_data: - if not self._found_a_turtle(blk): - blocks.append(self.load_block(blk, offset)) - - # Make the connections. - for i in range(len(blocks)): - cons = [] - # Normally, it is simply a matter of copying the connections. - if blocks[i].connections == None: - for c in block_data[i][4]: - if c is None: - cons.append(None) - else: - cons.append(blocks[c]) - elif blocks[i].connections == 'check': - # Corner case to 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: - cons.append(None) - else: - cons.append(blocks[c]) - # If the boolean op was connected, readjust the plumbing. - if blocks[i].name in BOOLEAN_STYLE: - if block_data[i][4][0] is not None: - c = block_data[i][4][0] - cons[0] = blocks[block_data[c][4][0]] - c0 = block_data[c][4][0] - for j, cj in enumerate(block_data[c0][4]): - if cj == c: - blocks[c0].connections[j] = blocks[i] - if c < i: - blocks[c].connections[0] = blocks[i] - blocks[c].connections[3] = None - else: - # Connection was to a block we haven't seen yet. - print "WARNING: dock check couldn't see the future" - else: - if block_data[i][4][0] is not None: - c = block_data[i][4][0] - cons[0] = blocks[block_data[c][4][0]] - c0 = block_data[c][4][0] - for j, cj in enumerate(block_data[c0][4]): - if cj == c: - blocks[c0].connections[j] = blocks[i] - if c < i: - blocks[c].connections[0] = blocks[i] - blocks[c].connections[1] = None - else: - # Connection was to a block we haven't seen yet. - print "WARNING: dock check couldn't see the future" - else: - print "WARNING: unknown connection state %s" % \ - (str(blocks[i].connections)) - blocks[i].connections = cons[:] - - # Block sizes and shapes may have changed. - for blk in blocks: - self._adjust_dock_positions(blk) - - # Look for any stacks that need to be collapsed or sandwiched - for blk in blocks: - if collapsed(blk): - collapse_stack(find_sandwich_top(blk)) - elif blk.name == 'sandwichbottom' and collapsible(blk): - blk.svg.set_hide(True) - blk.svg.set_show(False) - blk.refresh() - grow_stack_arm(find_sandwich_top(blk)) - - # Resize blocks to current scale - self.resize_blocks(blocks) - - if len(blocks) > 0: - return blocks[0] - else: - return None - - def _adjust_dock_positions(self, blk): - """ Adjust the dock x, y positions """ - if not self.interactive_mode: - return - (sx, sy) = blk.spr.get_xy() - for i, c in enumerate(blk.connections): - if i > 0 and c is not None: - bdock = blk.docks[i] - for j in range(len(c.docks)): - if c.connections[j] == blk: - cdock = c.docks[j] - 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): - """ Turtle pressed """ - (tx, ty) = self.selected_turtle.get_xy() - dx = x - tx - 30 - dy = y - ty - 30 - if (dx * dx) + (dy * dy) > 200: - self.drag_turtle = ('turn', - self.canvas.heading - atan2(dy, dx)/DEGTOR, 0) - else: - self.drag_turtle = ('move', x - tx, y - ty) - - def _move_cb(self, win, event): - """ Mouse move """ - x, y = xy(event) - self._mouse_move(x, y) - return True - - def _mouse_move(self, x, y, verbose=False, mdx=0, mdy=0): - if verbose: - print "processing remote mouse move: %d, %d" % (x, y) - - self.block_operation = 'move' - # First, check to see if we are dragging or rotating a turtle. - if self.selected_turtle is not None: - dtype, dragx, dragy = self.drag_turtle - (sx, sy) = self.selected_turtle.get_xy() - if dtype == 'move': - if mdx != 0 or mdy != 0: - dx, dy = mdx, mdy - else: - dx = x - dragx - sx - dy = y - dragy - sy - self.selected_turtle.move((sx + dx, sy + dy)) - else: - if mdx != 0 or mdy != 0: - dx = mdx - dy = mdy - else: - dx = x - sx - 30 - dy = y - sy - 30 - 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: - self._show_popup(x, y) - return - # If we have a stack of blocks selected, move them. - elif self.drag_group[0] is not None: - blk = self.drag_group[0] - # Don't move a bottom blk is the stack is collapsed - if collapsed(blk): - return - - self.selected_spr = blk.spr - dragx, dragy = self.drag_pos - if mdx != 0 or mdy != 0: - dx = mdx - dy = mdy - else: - (sx, sy) = blk.spr.get_xy() - dx = x - dragx - sx - dy = y - dragy - sy - - # Take no action if there was a move of 0,0. - if dx == 0 and dy == 0: - return - self.drag_group = find_group(blk) - - # Prevent blocks from ending up with a negative x... - for gblk in self.drag_group: - (bx, by) = gblk.spr.get_xy() - if bx + dx < 0: - dx += -(bx + dx) - """ - # ...or under the palette. - if self.selected_palette is not None and\ - self.selected_palette != self.trash_index: - w, h = self.palette_sprs[self.selected_palette][ - self.orientation].get_dimensions() - if self.orientation == HORIZONTAL_PALETTE: - if bx < w and\ - by+dy < self.toolbar_offset+PALETTE_HEIGHT: - dy += -(by+dy)+self.toolbar_offset+PALETTE_HEIGHT - else: - if by < h+self.toolbar_offset and bx+dx < PALETTE_WIDTH: - dx += -(bx+dx)+PALETTE_WIDTH - """ - - # Move the stack. - for gblk in self.drag_group: - (bx, by) = gblk.spr.get_xy() - gblk.spr.move((bx + dx, by + dy)) - if mdx != 0 or mdy != 0: - dx = 0 - dy = 0 - else: - self.dx += dx - self.dy += dy - - def _show_popup(self, x, y): - """ Let's help our users by displaying a little help. """ - spr = self.sprite_list.find_sprite((x, y)) - blk = self.block_list.spr_to_block(spr) - if spr and blk is not None: - if self.timeout_tag[0] == 0: - self.timeout_tag[0] = self._do_show_popup(blk.name) - self.selected_spr = spr - else: - if self.timeout_tag[0] > 0: - try: - gobject.source_remove(self.timeout_tag[0]) - 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'): - if self.timeout_tag[0] == 0 and hasattr(spr, 'name'): - self.timeout_tag[0] = self._do_show_popup(spr.name) - self.selected_spr = spr - else: - if self.timeout_tag[0] > 0: - try: - gobject.source_remove(self.timeout_tag[0]) - self.timeout_tag[0] = 0 - except: - self.timeout_tag[0] = 0 - else: - if self.timeout_tag[0] > 0: - try: - gobject.source_remove(self.timeout_tag[0]) - self.timeout_tag[0] = 0 - except: - self.timeout_tag[0] = 0 - - def _do_show_popup(self, block_name): - """ Fetch the help text and display it. """ - if SPECIAL_NAMES.has_key(block_name): - block_name_s = SPECIAL_NAMES[block_name] - elif BLOCK_NAMES.has_key(block_name): - block_name_s = BLOCK_NAMES[block_name][0] - elif block_name in TOOLBAR_SHAPES: - block_name_s = '' - else: - block_name_s = _(block_name) - if HELP_STRINGS.has_key(block_name): - if block_name_s == '': - label = HELP_STRINGS[block_name] - else: - label = block_name_s + ": " + HELP_STRINGS[block_name] - else: - label = block_name_s - if self.running_sugar: - self.activity.hover_help_label.set_text(label) - self.activity.hover_help_label.show() - else: - if self.interactive_mode: - self.win.set_title(_("Turtle Art") + " — " + label) - return 0 - - def _buttonrelease_cb(self, win, event): - """ Button release """ - x, y = xy(event) - self.button_release(x, y) - return True - - def button_release(self, x, y, verbose=False): - # We may have been moving the turtle - if self.selected_turtle is not None: - (tx, ty) = self.selected_turtle.get_xy() - (cx, cy) = self.canvas.canvas.get_xy() - # self.canvas.xcor = tx - self.canvas.canvas._width/2 + 30 - cx - # self.canvas.ycor = self.canvas.canvas._height/2 - ty - 30 + cy - self.canvas.xcor = tx - self.canvas.width/2 + 30 - cx - self.canvas.ycor = self.canvas.height/2 - ty - 30 + cy - self.canvas.move_turtle() - if self.running_sugar: - self.display_coordinates() - self.selected_turtle = None - return - - # If we don't have a group of blocks, then there is nothing to do. - if self.drag_group == None: - return - - blk = self.drag_group[0] - # Remove blocks by dragging them onto the trash palette. - if self.block_operation == 'move' and self._in_the_trash(x, y): - self._put_in_trash(blk, x, y) - self.drag_group = None - return - - # Pull a stack of new blocks off of the category palette. - if self.block_operation == 'new': - 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)) - else: - gblk.spr.move((bx+PALETTE_WIDTH, by+20)) - - # Look to see if we can dock the current stack. - self._snap_to_dock() - self._check_collapsibles(blk) - for gblk in self.drag_group: - if gblk.status != 'collapsed': - gblk.spr.set_layer(BLOCK_LAYER) - self.drag_group = None - - # Find the block we clicked on and process it. - if self.block_operation == 'click': - self._click_block(x, y) - - def _click_block(self, x, y): - """ Click block """ - blk = self.block_list.spr_to_block(self.selected_spr) - if blk is None: - return - self.selected_blk = blk - if blk.name == 'number' or blk.name == 'string': - self.saved_string = blk.spr.labels[0] - blk.spr.labels[0] += CURSOR - elif blk.name in BOX_STYLE_MEDIA: - self._import_from_journal(self.selected_blk) - if blk.name == 'journal' and self.running_sugar: - self._load_description_block(blk) - elif blk.name == 'identity2' or blk.name == 'hspace': - group = find_group(blk) - if hide_button_hit(blk.spr, x, y): - dx = blk.reset_x() - elif show_button_hit(blk.spr, x, y): - dx = 20 - blk.expand_in_x(dx) - else: - dx = 0 - for gblk in group: - if gblk != blk: - gblk.spr.move_relative((dx * blk.scale, 0)) - elif blk.name == 'vspace': - group = find_group(blk) - if hide_button_hit(blk.spr, x, y): - dy = blk.reset_y() - elif show_button_hit(blk.spr, x, y): - dy = 20 - blk.expand_in_y(dy) - else: - dy = 0 - for gblk in group: - if gblk != blk: - gblk.spr.move_relative((0, dy * blk.scale)) - grow_stack_arm(find_sandwich_top(blk)) - elif blk.name in EXPANDABLE or blk.name == 'nop': - if show_button_hit(blk.spr, x, y): - n = len(blk.connections) - group = find_group(blk.connections[n-1]) - if blk.name == 'myfunc1arg': - blk.spr.labels[1] = 'f(x, y)' - blk.spr.labels[2] = ' ' - dy = blk.add_arg() - blk.primitive = 'myfunction2' - blk.name = 'myfunc2arg' - elif blk.name == 'myfunc2arg': - blk.spr.labels[1] = 'f(x, y, z)' - dy = blk.add_arg(False) - blk.primitive = 'myfunction3' - blk.name = 'myfunc3arg' - elif blk.name == 'userdefined': - dy = blk.add_arg() - blk.primitive = 'userdefined2' - blk.name = 'userdefined2args' - elif blk.name == 'userdefined2args': - dy = blk.add_arg(False) - blk.primitive = 'userdefined3' - blk.name = 'userdefined3args' - else: - 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] - argblk = Block(self.block_list, self.sprite_list, argname, - 0, 0, 'block', [argvalue], self.block_scale) - argdock = argblk.docks[0] - (bx, by) = blk.spr.get_xy() - nx = bx + blk.docks[n - 1][2] - argdock[2] - ny = by + blk.docks[n - 1][3] - argdock[3] - argblk.spr.move((nx, ny)) - argblk.spr.set_layer(TOP_LAYER) - argblk.connections = [blk, None] - blk.connections[n - 1] = argblk - grow_stack_arm(find_sandwich_top(blk)) - elif blk.name in PYTHON_SKIN and self.myblock == None: - self._import_py() - else: - self._run_stack(blk) - elif blk.name in COLLAPSIBLE: - top = find_sandwich_top(blk) - if collapsed(blk): - restore_stack(top) - elif top is not None: - collapse_stack(top) - else: - self._run_stack(blk) - - def _check_collapsibles(self, blk): - """ Check the state of collapsible blocks upon change in dock state. """ - group = find_group(blk) - for gblk in group: - if gblk.name in COLLAPSIBLE: - if collapsed(gblk): - gblk.svg.set_show(True) - gblk.svg.set_hide(False) - reset_stack_arm(find_sandwich_top(gblk)) - elif collapsible(gblk): - gblk.svg.set_hide(True) - gblk.svg.set_show(False) - grow_stack_arm(find_sandwich_top(gblk)) - else: - gblk.svg.set_hide(False) - gblk.svg.set_show(False) - # Ouch: When you tear off the sandwich bottom, you - # no longer have access to the group with the sandwich top - # so check them all. - for b in self.just_blocks(): - if b.name == 'sandwichtop': - if find_sandwich_bottom(b) is None: - reset_stack_arm(b) - gblk.refresh() - - def _run_stack(self, blk): - """ Run a stack of blocks. """ - if blk is None: - return - self.lc.ag = None - top = find_top_block(blk) - self.lc.run_blocks(top, self.just_blocks(), True) - if self.interactive_mode: - gobject.idle_add(self.lc.doevalstep) - else: - while self.lc.doevalstep(): - pass - - def _snap_to_dock(self): - """ Snap a block to the dock of another block. """ - my_block = self.drag_group[0] - d = 200 - for my_dockn in range(len(my_block.docks)): - for your_block in self.just_blocks(): - # don't link to a block to which you're already connected - if your_block in self.drag_group: - continue - # check each dock of your_block for a possible connection - for your_dockn in range(len(your_block.docks)): - this_xy = dock_dx_dy(your_block, your_dockn, - my_block, my_dockn) - if magnitude(this_xy) > d: - continue - d = magnitude(this_xy) - best_xy = this_xy - best_you = your_block - best_your_dockn = your_dockn - best_my_dockn = my_dockn - if d < 200: - if not arithmetic_check(my_block, best_you, best_my_dockn, - best_your_dockn): - return - for blk in self.drag_group: - (sx, sy) = blk.spr.get_xy() - blk.spr.move((sx + best_xy[0], sy + best_xy[1])) - - # If there was already a block docked there, move it to the trash. - blk_in_dock = best_you.connections[best_your_dockn] - if blk_in_dock is not None: - blk_in_dock.connections[0] = None - self._put_in_trash(blk_in_dock) - - best_you.connections[best_your_dockn] = my_block - if my_block.connections is not None: - my_block.connections[best_my_dockn] = best_you - - 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) - try: - result = chooser.run() - if result == gtk.RESPONSE_ACCEPT: - dsobject = chooser.get_selected_object() - self._update_media_icon(blk, dsobject, dsobject.object_id) - dsobject.destroy() - finally: - chooser.destroy() - del chooser - else: - 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 == None or blk.name != 'journal' or len(blk.values) == 0 or\ - blk.connections[0] is None: - return - _blk = blk.connections[0] - dblk = find_blk_below(_blk, 'description') - # Autoupdate the block if it is empty - if dblk != None and (len(dblk.values) == 0 or dblk.values[0] == None): - self._update_media_icon(dblk, None, blk.values[0]) - - def _update_media_icon(self, blk, name, value=''): - """ Update the icon on a 'loaded' media block. """ - if blk.name == 'journal': - self._load_image_thumb(name, blk) - elif blk.name == 'audio': - self._block_skin('audioon', blk) - else: - self._block_skin('descriptionon', blk) - if value == '': - value = name - if len(blk.values) > 0: - blk.values[0] = value - else: - blk.values.append(value) - blk.spr.set_label(' ') - - def _load_image_thumb(self, picture, blk): - """ Replace icon with a preview image. """ - pixbuf = None - self._block_skin('descriptionon', blk) - - if self.running_sugar: - w, h = calc_image_size(blk.spr) - pixbuf = get_pixbuf_from_journal(picture, w, h) - else: - if movie_media_type(picture): - self._block_skin('journalon', blk) - elif audio_media_type(picture): - self._block_skin('audioon', blk) - blk.name = 'audio' - elif image_media_type(picture): - w, h = calc_image_size(blk.spr) - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(picture, w, h) - else: - blk.name = 'description' - if pixbuf is not None: - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - self._resize_skin(blk) - - def _disconnect(self, blk): - """ Disconnect block from stack above it. """ - if blk.connections[0] == None: - return - if collapsed(blk): - return - blk2 = blk.connections[0] - blk2.connections[blk2.connections.index(blk)] = None - blk.connections[0] = None - - def _keypress_cb(self, area, event): - """ Keyboard """ - keyname = gtk.gdk.keyval_name(event.keyval) - keyunicode = gtk.gdk.keyval_to_unicode(event.keyval) - - if event.get_state()>k.gdk.MOD1_MASK: - alt_mask = True - alt_flag = 'T' - else: - alt_mask = False - alt_flag = 'F' - self._key_press(alt_mask, keyname, keyunicode) - return keyname - - def _key_press(self, alt_mask, keyname, keyunicode, verbose=False): - if keyname is None: - return False - if verbose: - print "processing remote key press: %s" % (keyname) - - self.keypress = keyname - - # First, process Alt keys. - if alt_mask and self.selected_blk is not None: - if keyname == "p": - self.hideshow_button() - elif keyname == 'q': - exit() - return True - # Process keyboard input for 'number' blocks - if self.selected_blk is not None and \ - self.selected_blk.name == 'number': - self._process_numeric_input(keyname) - return True - # Process keyboard input for 'string' blocks - elif self.selected_blk is not None and \ - self.selected_blk.name == 'string': - self.process_alphanumeric_input(keyname, keyunicode) - if self.selected_blk is not None: - self.selected_blk.resize() - return True - # Otherwise, use keyboard input to move blocks or turtles - else: - self._process_keyboard_commands(keyname) - if self.selected_blk is None: - return False - - def _process_numeric_input(self, keyname): - ''' Make sure numeric input is valid. ''' - oldnum = self.selected_blk.spr.labels[0].replace(CURSOR, '') - if len(oldnum) == 0: - oldnum = '0' - if keyname == 'minus': - if oldnum == '0': - newnum = '-' - elif oldnum[0] != '-': - newnum = '-' + oldnum - else: - newnum = oldnum - elif keyname == 'period' and '.' not in oldnum: - newnum = oldnum + '.' - elif keyname == 'BackSpace': - if len(oldnum) > 0: - newnum = oldnum[:len(oldnum)-1] - else: - newnum = '' - elif keyname in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: - if oldnum == '0': - newnum = keyname - else: - newnum = oldnum + keyname - elif keyname == 'Return': - self._unselect_block() - return - else: - newnum = oldnum - if newnum == '.': - newnum = '0.' - if len(newnum) > 0 and newnum != '-': - try: - float(newnum) - except ValueError, e: - newnum = oldnum - self.selected_blk.spr.set_label(newnum + CURSOR) - - 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) - if c == 0: - oldleft = self.selected_blk.spr.labels[0] - oldright = '' - elif len(self.selected_blk.spr.labels[0]) == 1: - oldleft = '' - oldright = '' - else: - try: # Why are getting a ValueError on occasion? - oldleft, oldright = \ - self.selected_blk.spr.labels[0].split(CURSOR) - except ValueError: - print "[%s]" % self.selected_blk.spr.labels[0] - oldleft = self.selected_blk.spr.labels[0] - oldright = '' - else: - oldleft = '' - oldright = '' - newleft = oldleft - if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', \ - 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift']: - keyname = '' - keyunicode = 0 - # Hack until I sort out input and unicode and dead keys, - if keyname[0:5] == 'dead_': - self.dead_key = keyname - keyname = '' - keyunicode = 0 - if keyname == 'space': - keyunicode = 32 - elif keyname == 'Tab': - keyunicode = 9 - if keyname == 'BackSpace': - if len(oldleft) > 1: - newleft = oldleft[:len(oldleft)-1] - else: - newleft = '' - elif keyname == 'Home': - oldright = oldleft+oldright - newleft = '' - elif keyname == 'Left': - if len(oldleft) > 0: - 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 - oldright = '' - elif keyname == 'Return': - newleft = oldleft+RETURN - elif keyname == 'Down': - self._unselect_block() - return - elif keyname == 'Up' or keyname == 'Escape': # Restore previous state - self.selected_blk.spr.set_label(self.saved_string) - self._unselect_block() - return - else: - if self.dead_key is not '': - keyunicode = \ - DEAD_DICTS[DEAD_KEYS.index(self.dead_key[5:])][keyname] - self.dead_key = '' - if keyunicode > 0: - if unichr(keyunicode) != '\x00': - newleft = oldleft+unichr(keyunicode) - else: - newleft = oldleft - elif keyunicode == -1: # clipboard text - if keyname == '\n': - newleft = oldleft+RETURN - else: - newleft = oldleft+keyname - self.selected_blk.spr.set_label("%s%s%s" % (newleft, CURSOR, oldright)) - - def _process_keyboard_commands(self, keyname): - """ Use the keyboard to move blocks and turtle """ - mov_dict = {'KP_Up':[0, 10], 'j':[0, 10], 'Up':[0, 10], - 'KP_Down':[0, -10], 'k':[0, -10], 'Down':[0, -10], - 'KP_Left':[-10, 0], 'h':[-10, 0], 'Left':[-10, 0], - 'KP_Right':[10, 0], 'l':[10, 0], 'Right':[10, 0], - 'KP_Page_Down':[0, 0], 'KP_Page_Up':[0, 0], 'KP_End':[0, 0], - 'KP_Home':[-1, -1], 'Return':[-1, -1], 'Esc':[0, 0]} - if not mov_dict.has_key(keyname): - return - if keyname == 'KP_End': - self.run_button(0) - elif self.selected_spr is not None: - blk = self.block_list.spr_to_block(self.selected_spr) - tur = self.turtles.spr_to_turtle(self.selected_spr) - if not self.lc.running and blk is not None: - if keyname == 'Return' or keyname == 'KP_Page_Up': - (x, y) = blk.spr.get_xy() - self._click_block(x, y) - elif keyname == 'KP_Page_Down': - if self.drag_group == None: - self.drag_group = find_group(blk) - for gblk in self.drag_group: - gblk.spr.hide() - self.drag_group = None - else: - self._jog_block(blk, mov_dict[keyname][0], - mov_dict[keyname][1]) - elif tur is not None: - self._jog_turtle(mov_dict[keyname][0], mov_dict[keyname][1]) - return True - - def _jog_turtle(self, dx, dy): - """ Jog turtle """ - if dx == -1 and dy == -1: - self.canvas.xcor = 0 - self.canvas.ycor = 0 - else: - self.canvas.xcor += dx - self.canvas.ycor += dy - self.canvas.move_turtle() - self.display_coordinates() - self.selected_turtle = None - - def _jog_block(self, blk, dx, dy): - """ Jog block """ - if collapsed(blk): - return - self.drag_group = find_group(blk) - # check to see if any block ends up with a negative x - for blk in self.drag_group: - (sx, sy) = blk.spr.get_xy() - if sx+dx < 0: - dx += -(sx + dx) - # move the stack - for blk in self.drag_group: - (sx, sy) = blk.spr.get_xy() - blk.spr.move((sx + dx, sy - dy)) - self._snap_to_dock() - self.drag_group = None - - def _number_check(self): - """ Make sure a 'number' block contains a number. """ - n = self.selected_blk.spr.labels[0].replace(CURSOR, '') - if n in ['-', '.', '-.']: - n = 0 - if n is not None: - try: - f = float(n) - if f > 1000000: - n = 1 - self.showlabel("#overflowerror") - elif f < -1000000: - n = -1 - self.showlabel("#overflowerror") - except ValueError: - n = 0 - self.showlabel("#notanumber") - else: - n = 0 - self.selected_blk.spr.set_label(n) - self.selected_blk.values[0] = n - - def _string_check(self): - s = self.selected_blk.spr.labels[0].replace(CURSOR, '') - self.selected_blk.spr.set_label(s) - self.selected_blk.values[0] = s.replace(RETURN, "\12") - - def load_python_code(self): - """ Load Python code from a file """ - fname, self.load_save_folder = get_load_name('.py', - self.load_save_folder) - if fname == None: - return - f = open(fname, 'r') - self.myblock = f.read() - f.close() - - def _import_py(self): - """ Import Python code into a block """ - if self.running_sugar: - self.activity.import_py() - else: - self.load_python_code() - self.set_userdefined() - - def new_project(self): - """ Start a new project """ - stop_logo(self) - self._loaded_project = "" - # Put current project in the trash. - while len(self.just_blocks()) > 0: - blk = self.just_blocks()[0] - top = find_top_block(blk) - 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 == "" - - def project_has_changed(self): - """ WARNING: order of JSON serialized data may have changed. """ - try: - f = open(self._loaded_project, 'r') - saved_project_data = f.read() - f.close() - except: - print "problem loading saved project data from %s" %\ - (self._loaded_project) - saved_project_data = "" - current_project_data = data_to_string(self.assemble_data_to_save()) - - return saved_project_data != current_project_data - - def load_files(self, ta_file, create_new_project=True): - """ Load a project from a file """ - if create_new_project: - 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 == None: - return - if _file_name[-3:] == '.ta': - _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: - self.activity.metadata['title'] = os.path.split(_file_name)[1] - - def _found_a_turtle(self, blk): - """ Either [-1, 'turtle', ...] or [-1, ['turtle', key], ...] """ - if blk[1] == 'turtle': - self.load_turtle(blk) - return True - elif type(blk[1]) == list and blk[1][0] == 'turtle': - self.load_turtle(blk, blk[1][1]) - return True - elif type(blk[1]) == tuple: - _btype, _key = blk[1] - if _btype == 'turtle': - self.load_turtle(blk, _key) - return True - return False - - def load_turtle(self, blk, key=1): - """ Restore a turtle from its saved state """ - tid, name, xcor, ycor, heading, color, shade, pensize = blk - self.canvas.set_turtle(key) - self.canvas.setxy(xcor, ycor) - self.canvas.seth(heading) - self.canvas.setcolor(color) - self.canvas.setshade(shade) - self.canvas.setpensize(pensize) - - def load_block(self, b, offset=0): - """ Restore individual blocks from saved state """ - # 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: - btype, value = btype - elif type(btype) == list: - btype, value = btype[0], btype[1] - if btype in CONTENT_BLOCKS or btype in COLLAPSIBLE: - if btype == 'number': - try: - values = [round_int(value)] - except ValueError: - values = [0] - elif btype in COLLAPSIBLE: - if value is not None: - values = [int(value)] - else: - values = [] - else: - values = [value] - else: - values = [] - - if btype in OLD_DOCK: - check_dock = True - else: - check_dock = False - if OLD_NAMES.has_key(btype): - btype = OLD_NAMES[btype] - blk = Block(self.block_list, self.sprite_list, btype, - b[2] + self.canvas.cx + offset, - b[3] + self.canvas.cy + offset, - 'block', values, self.block_scale) - # Some blocks get transformed. - if btype == 'string' and blk.spr is not None: - blk.spr.set_label(blk.values[0].replace('\n', RETURN)) - elif btype == 'start': # block size is saved in start block - if value is not None: - self.block_scale = value - elif btype in EXPANDABLE or btype == 'nop': - if btype == 'vspace': - if value is not None: - blk.expand_in_y(value) - elif btype == 'hspace' or btype == 'identity2': - if value is not None: - blk.expand_in_x(value) - elif btype == 'templatelist' or btype == 'list': - for i in range(len(b[4])-4): - blk.add_arg() - elif btype == 'myfunc2arg' or btype == 'myfunc3arg' or\ - btype == 'userdefined2args' or btype == 'userdefined3args': - blk.add_arg() - if btype == 'myfunc3arg' or btype == 'userdefined3args': - blk.add_arg(False) - if btype in PYTHON_SKIN: - if self.nop == 'pythonloaded': - self._block_skin('pythonon', blk) - 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\ - blk.values[0] == None: - self._block_skin(btype+'off', blk) - elif btype == 'audio' or btype == 'description': - self._block_skin(btype+'on', blk) - elif self.running_sugar: - try: - dsobject = datastore.get(blk.values[0]) - if not movie_media_type(dsobject.file_path[-4:]): - w, h, = calc_image_size(blk.spr) - pixbuf = get_pixbuf_from_journal(dsobject, w, h) - if pixbuf is not None: - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - else: - self._block_skin('journalon', blk) - dsobject.destroy() - except: - try: - w, h, = calc_image_size(blk.spr) - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( - blk.values[0], w, h) - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - except: - print "Warning: Couldn't open dsobject (%s)" % \ - (blk.values[0]) - self._block_skin('journaloff', blk) - else: - if not movie_media_type(blk.values[0][-4:]): - try: - w, h, = calc_image_size(blk.spr) - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( - blk.values[0], w, h) - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - except: - self._block_skin('journaloff', blk) - else: - self._block_skin('journalon', blk) - blk.spr.set_label(' ') - blk.resize() - - if self.interactive_mode: - blk.spr.set_layer(BLOCK_LAYER) - 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, - [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) - if _file_name is None: - return - if _file_name[-3:] == '.ta': - _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: - self.save_folder = self.load_save_folder - - def assemble_data_to_save(self, save_turtle=True, save_project=True): - """ Pack the project (or stack) into a data stream to be serialized """ - _data = [] - _blks = [] - - if save_project: - _blks = self.just_blocks() - else: - 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: - if _blk.name in CONTENT_BLOCKS or _blk.name in COLLAPSIBLE: - if len(_blk.values) > 0: - _name = (_blk.name, _blk.values[0]) - else: - _name = (_blk.name) - elif _blk.name in EXPANDABLE: - _ex, _ey = _blk.get_expand_x_y() - if _ex > 0: - _name = (_blk.name, _ex) - elif _ey > 0: - _name = (_blk.name, _ey) - else: - _name = (_blk.name, 0) - elif _blk.name == 'start': # save block_size in start block - _name = (_blk.name, self.block_scale) - else: - _name = (_blk.name) - if hasattr(_blk, 'connections'): - connections = [get_id(_cblk) for _cblk in _blk.connections] - else: - connections = None - (_sx, _sy) = _blk.spr.get_xy() - # Add a slight offset for copy/paste - if not save_project: - _sx += 20 - _sy += 20 - _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)) - 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) - 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.show() - elif self.interactive_mode: - self.win.set_title("%s — %s: %d %s: %d %s: %d" % (_("Turtle Art"), - _("xcor"), x, _("ycor"), y, _("heading"), h)) - - def showlabel(self, shp, label = ''): - """ Display a message on a status block """ - if not self.interactive_mode: - print label - return - if shp == 'syntaxerror' and str(label) != '': - if self.status_shapes.has_key(str(label)[1:]): - shp = str(label)[1:] - label = '' - else: - shp = 'status' - elif shp[0] == '#': - shp = shp[1:] - label = '' - if shp == 'notanumber': - shp = 'overflowerror' - self.status_spr.set_shape(self.status_shapes[shp]) - 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)) - else: - 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) - dx *= w - dy *= h - return(w, h, x, y, dx, dy) - - 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] - data_to_file(self.assemble_data_to_save(), _file_name + '.ta') - save_picture(self.canvas, _file_name + '.png') - ta_file = _file_name + '.ta' - image_file = _file_name + '.png' - return ta_file, image_file - - def save_as_image(self, name="", svg=False, pixbuf=None): - """ Grab the current canvas and save it. """ - - if not self.interactive_mode: - # print name - save_picture(self.canvas, name[:-3] + ".png") - return - """ - self.color_map = self.window.get_colormap() - new_pix = pixbuf.get_from_drawable(self.window, self.color_map, - 0, 0, 0, 0, - self.width, self.height) - new_pix.save(name[:-3] + ".png", "png") - """ - - if self.running_sugar: - if svg: - if len(name) == 0: - filename = "ta.svg" - else: - filename = name+".svg" - else: - if len(name) == 0: - filename = "ta.png" - else: - filename = name+".png" - datapath = get_path(self.activity, 'instance') - elif len(name) == 0: - name = "ta" - if self.save_folder is not None: - self.load_save_folder = self.save_folder - if svg: - filename, self.load_save_folder = get_save_name('.svg', - self.load_save_folder, - name) - else: - filename, self.load_save_folder = get_save_name('.png', - self.load_save_folder, - name) - datapath = self.load_save_folder - else: - datapath = os.getcwd() - if svg: - filename = name+".svg" - else: - filename = name+".png" - if filename is None: - return - - file_path = os.path.join(datapath, filename) - if svg: - if self.svg_string == '': - return - save_svg(self.svg_string, file_path) - self.svg_string = '' - else: - save_picture(self.canvas, file_path) - - # keep a log of the saved pictures for export to HTML - self.saved_pictures.append(file_path) - - if self.running_sugar: - dsobject = datastore.create() - if len(name) == 0: - dsobject.metadata['title'] = "%s %s" % ( - self.activity.metadata['title'], _("image")) - else: - dsobject.metadata['title'] = name - dsobject.metadata['icon-color'] = profile.get_color().to_string() - if svg: - dsobject.metadata['mime_type'] = 'image/svg+xml' - else: - dsobject.metadata['mime_type'] = 'image/png' - dsobject.set_file_path(file_path) - datastore.write(dsobject) - dsobject.destroy() - - def just_blocks(self): - """ Filter out 'proto', 'trash', and 'deleted' blocks """ - just_blocks_list = [] - for _blk in self.block_list.list: - if _blk.type == 'block': - just_blocks_list.append(_blk) - return just_blocks_list - - def _width_and_height(self, blk): - """ What are the width and height of a stack? """ - minx = 10000 - miny = 10000 - maxx = -10000 - maxy = -10000 - for gblk in find_group(blk): - (x, y) = gblk.spr.get_xy() - w, h = gblk.spr.get_dimensions() - if x < minx: - minx = x - if y < miny: - miny = y - if x + w > maxx: - maxx = x + w - if y + h > maxy: - maxy = y + h - return(maxx - minx, maxy - miny) - - # Utilities related to putting a image 'skin' on a block - - def _calc_image_offset(self, name, spr, iw=0, ih=0): - """ Calculate the postion for placing an image onto a sprite. """ - _l, _t = spr.label_left_top() - if name == '': - return _l, _t - _w = spr.label_safe_width() - _h = spr.label_safe_height() - 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) - - def _calc_w_h(self, name, spr): - """ Calculate new image size """ - target_w = spr.label_safe_width() - target_h = spr.label_safe_height() - if name == '': - 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 - new_w = target_w - new_h = image_h*scale_factor - if new_h > target_h: - scale_factor = float(target_h)/new_h - new_h = target_h - new_w = target_w*scale_factor - return int(new_w), int(new_h) - - def _proto_skin(self, name, n, i): - """ Utility for calculating proto skin images """ - x, y = self._calc_image_offset(name, self.palettes[n][i].spr) - self.palettes[n][i].spr.set_image(self.media_shapes[name], 1, x, y) - - def _block_skin(self, name, blk): - """ Some blocks get a skin """ - x, y = self._calc_image_offset(name, blk.spr) - blk.set_image(self.media_shapes[name], x, y) - self._resize_skin(blk) - - def _resize_skin(self, blk): - """ Resize the 'skin' when block scale changes. """ - if blk.name in PYTHON_SKIN: - w, h = self._calc_w_h('pythonoff', blk.spr) - x, y = self._calc_image_offset('pythonoff', blk.spr, w, h) - elif blk.name == 'journal': - if len(blk.values) == 1 and blk.values[0] is not None: - w, h = self._calc_w_h('', blk.spr) - x, y = self._calc_image_offset('journaloff', blk.spr, w, h) - else: - w, h = self._calc_w_h('journaloff', blk.spr) - x, y = self._calc_image_offset('journaloff', blk.spr, w, h) - else: - w, h = self._calc_w_h('descriptionoff', blk.spr) - x, y = self._calc_image_offset('descriptionoff', blk.spr, w, h) - blk.scale_image(x, y, w, h) -- cgit v0.9.1