Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sprites.py420
-rw-r--r--tablock.py865
-rw-r--r--tacanvas.py596
-rw-r--r--taconstants.py1065
-rw-r--r--taexporthtml.py147
-rw-r--r--taexportlogo.py353
-rw-r--r--tagplay.py176
-rw-r--r--tajail.py69
-rw-r--r--tamyblock.py245
-rwxr-xr-xtasprite_factory.py1117
-rw-r--r--taturtle.py209
-rw-r--r--tautils.py705
-rw-r--r--tawindow.py2336
13 files changed, 0 insertions, 8303 deletions
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("<svg>...some svg code...</svg>")
-
- # 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("<svg>...some svg code...</svg>")
-
- # 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': "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " + \
- "Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n",
- 'html': ("<html>\n", "</html>\n"),
- 'html_svg': ("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n",
- "</html>\n"),
- 'head': ("<head>\n<!-- Created by Turtle Art -->\n", "</head>\n"),
- 'meta': "<meta http-equiv=\"content-type\" content=\"text/html; " + \
- "charset=UTF-8\"/>\n",
- 'title': ("<title>", "</title>\n"),
- 'style': ("<style type=\"text/css\">\n<!--\n", "-->\n</style>\n"),
- 'body': ("<body>\n", "\n</body>\n"),
- 'div': ("<div>\n", "</div>\n"),
- 'slide': ("\n<a name=\"slide", "\"></a>\n"),
- 'h1': ("<h1>", "</h1>\n"),
- 'table': ("<table cellpadding=\"10\">\n", "</table>\n"),
- 'tr': ("<tr>\n", "</tr>\n"),
- 'td': ("<td valign=\"top\" width=\"400\" height=\"300\">\n",
- "\n</td>\n"),
- 'img': ("<img width=\"400\" height=\"300\" alt=\"Image\" " + \
- "src=\"file://", ".png\" />\n"),
- 'img2': ("<img alt=\"Image\" src=\"image", ".png\" />\n"),
- 'img3': ("<img alt=\"Image\" src=\"file://", "\" />\n"),
- 'ul': ("<table>\n", "</table>\n"),
- 'li': ("<tr><td>", "</td></tr>\n") }
-
- comment = "<!--\n\
-<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" [\n\
- <!ENTITY ns_svg \"http://www.w3.org/2000/svg\">\n\
- <!ENTITY ns_xlink \"http://www.w3.org/1999/xlink\">\n\
-]>\n\
--->\n"
- if self.embed_images == True:
- self.html_glue['img'] = ("<img width=\"400\" height=\"300\" alt="+ \
- "\"Image\" src=\"data:image/png;base64,\n",
- " \"/>\n")
- self.html_glue['img2'] = ("<img alt=\"Image\" src=\"data:image/png;"+ \
- "base64,\n", " \"/>\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" % (" <path d=\"M 27.5 48.3 ",
- "C 26.9 48.3 26.4 48.2 25.9 48.2 L 27.2 50.5 L 28.6 48.2 ",
- "C 28.2 48.2 27.9 48.3 27.5 48.3 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke,
- "\" />\n")
- svg +="%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 40.2 11.7 ",
- "C 38.0 11.7 36.2 13.3 35.8 15.3 ",
- "C 37.7 16.7 39.3 18.4 40.5 20.5 ",
- "C 42.8 20.4 44.6 18.5 44.6 16.2 ",
- "C 44.6 13.7 42.6 11.7 40.2 11.7 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n")
- svg +="%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 40.7 39.9 ",
- "C 39.5 42.1 37.9 44.0 35.9 45.4 ",
- "C 36.4 47.3 38.1 48.7 40.2 48.7 ",
- "C 42.6 48.7 44.6 46.7 44.6 44.3 ",
- "C 44.6 42.0 42.9 40.2 40.7 39.9 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n")
- svg +="%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 14.3 39.9 ",
- "C 12.0 40.1 10.2 42.0 10.2 44.3 ",
- "C 10.2 46.7 12.2 48.7 14.7 48.7 ",
- "C 16.7 48.7 18.5 47.3 18.9 45.4 ",
- "C 17.1 43.9 15.5 42.1 14.3 39.9 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n")
- svg +="%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 19.0 15.4 ",
- "C 18.7 13.3 16.9 11.7 14.7 11.7 ",
- "C 12.2 11.7 10.2 13.7 10.2 16.2 ",
- "C 10.2 18.5 12.1 20.5 14.5 20.6 ",
- "C 15.7 18.5 17.2 16.8 19.0 15.4 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n")
- svg +="%s%s%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 27.5 12.6 ",
- "C 29.4 12.6 31.2 13.0 32.9 13.7 ",
- "C 33.7 12.6 34.1 11.3 34.1 9.9 ",
- "C 34.1 6.2 31.1 3.2 27.4 3.2 ",
- "C 23.7 3.2 20.7 6.2 20.7 9.9 ",
- "C 20.7 11.3 21.2 12.7 22.0 13.7 ",
- "C 23.7 13.0 25.5 12.6 27.5 12.6 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n")
- svg +="%s%s%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 43.1 30.4 ",
- "C 43.1 35.2 41.5 39.7 38.5 43.0 ",
- "C 35.6 46.4 31.6 48.3 27.5 48.3 ",
- "C 23.4 48.3 19.4 46.4 16.5 43.0 ",
- "C 13.5 39.7 11.9 35.2 11.9 30.4 ",
- "C 11.9 20.6 18.9 12.6 27.5 12.6 ",
- "C 36.1 12.6 43.1 20.6 43.1 30.4 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n")
- svg +="%s%s%s%s%s" % (" <path d=\"M 25.9 33.8 L 24.3 29.1 ",
- "L 27.5 26.5 L 31.1 29.2 L 29.6 33.8 Z\" stroke_width=\"3.5\" ",
- "fill=\"", self._stroke, ";\" stroke=\"none\" />\n")
- svg +="%s%s%s%s%s%s" % (" <path d=\"M 27.5 41.6 ",
- "C 23.5 41.4 22.0 39.5 22.0 39.5 L 25.5 35.4 L 30.0 35.5 ",
- "L 33.1 39.7 C 33.1 39.7 30.2 41.7 27.5 41.6 Z\" ",
- "stroke_width=\"3.5\" fill=\"", self._stroke,
- ";\" stroke=\"none\" />\n")
- svg +="%s%s%s%s%s%s" % (" <path d=\"M 18.5 33.8 ",
- "C 17.6 30.9 18.6 27.0 18.6 27.0 L 22.6 29.1 L 24.1 33.8 ",
- "L 20.5 38.0 C 20.5 38.0 19.1 36.0 18.4 33.8 Z\" ",
- "stroke_width=\"3.5\" fill=\"", self._stroke,
- ";\" stroke=\"none\" />\n")
- svg +="%s%s%s%s%s%s" % (" <path d=\"M 19.5 25.1 ",
- "C 19.5 25.1 20.0 23.2 22.5 21.3 ",
- "C 24.7 19.7 27.0 19.6 27.0 19.6 L 26.9 24.6 L 23.4 27.3 ",
- "L 19.5 25.1 Z\" stroke_width=\"3.5\" fill=\"", self._stroke,
- ";\" stroke=\"none\" />\n")
- svg +="%s%s%s%s%s%s" % (" <path d=\"M 32.1 27.8 L 28.6 25.0 ",
- "L 29 19.8 C 29 19.8 30.8 19.7 33.0 21.4 ",
- "C 35.2 23.2 36.3 26.4 36.3 26.4 L 32.1 27.8 Z\" ",
- "stroke_width=\"3.5\" fill=\"", self._stroke,
- ";\" stroke=\"none\" />\n")
- svg +="%s%s%s%s%s%s" % (" <path d=\"M 31.3 34.0 L 32.6 29.6 ",
- "L 36.8 28.0 C 36.8 28.0 37.5 30.7 36.8 33.7 ",
- "C 36.2 36.0 34.7 38.1 34.7 38.1 L 31.3 34.0 Z\" ",
- "stroke_width=\"3.5\" fill=\"", self._stroke,
- ";\" stroke=\"none\" />\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" % (
- "<svg\n",
- " xmlns:svg=\"http://www.w3.org/2000/svg\"\n",
- " xmlns=\"http://www.w3.org/2000/svg\"\n",
- " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n",
- " version=\"1.1\"\n",
- " width=\"", self._width, "\"\n",
- " height=\"", self._height, "\">\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" % (
- " <defs>\n <linearGradient\n id=\"linearGradient1234\">\n",
- " <stop\n style=\"stop-color:#ffffff;stop-opacity:1;\"\n",
- " offset=\"0\" />\n",
- " <stop\n style=\"stop-color:", self._fill,
- ";stop-opacity:1;\"\n",
- " offset=\"1\" />\n",
- " </linearGradient>\n",
- " <linearGradient\n xlink:href=\"#linearGradient1234\"\n",
- " id=\"linearGradient5678\"\n",
- " x1=\"0\"\n",
- " y1=\"", self._height/2.0, "\"\n",
- " x2=\"", self._width/self._scale, "\"\n",
- " y2=\"", self._height/2.0, "\"\n",
- " gradientUnits=\"userSpaceOnUse\" />\n </defs>\n")
- else:
- return ""
-
- def _transform(self, center):
- if self._orientation != 0:
- orientation = "<g\ntransform = \"rotate(%.1f %.1f %.1f)\">\n" % (
- self._orientation, self._width/2.0, self._height/2.0)
- else:
- orientation = ""
- if center:
- return "<g\ntransform=\"translate(%.1f, %.1f)\">\n" % (
- -self._min_x, -self._min_y)
- else:
- return "<g\ntransform=\"scale(%.1f, %.1f)\">\n%s" % (
- self._scale, self._scale, orientation )
-
- def footer(self):
- if self._orientation != 0:
- return " </g>\n</g>\n</svg>\n"
- else:
- return " </g>\n</svg>\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" % (
- "<text style=\"font-size:", size, "px;fill:", self._stroke,
- ";font-family:Sans\">\n <tspan x=\"", x, "\" y=\"", y,
- "\" style=\"font-size:", size, "px;fill:", self._stroke, "\">",
- string, "</tspan>\n </text>\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" % (
- "<image x=\"", x, "\" y=\"", y,
- "\" width=\"", w, "\" height=\"", h,
- "\" xlink:href=\"file://", path, "\"/>\n")
- else:
- return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % (
- "<image x=\"", x, "\" y=\"", y,
- "\" width=\"", w, "\" height=\"", h,
- "\" xlink:href=\"data:image/png;base64,", image_data, "\"/>\n")
-
-
- def _circle(self, r, cx, cy):
- return "%s%s%s%s%s%f%s%f%s%f%s" % ("<circle style=\"fill:",
- self._fill, ";stroke:", self._stroke, ";\" r=\"", r, "\" cx=\"",
- cx, "\" cy=\"", cy, "\" />\n")
-
- def _rect(self, w, h, x, y):
- return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("<rect style=\"fill:",
- self._fill, ";stroke:", self._stroke, ";\" width=\"", w,
- "\" height=\"", h,"\" x=\"", x, "\" y=\"", y, "\" />\n")
-
- def background(self, fill):
- return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("<rect style=\"fill:",
- fill, ";stroke:", fill, ";\" width=\"", self._max_x-self._min_x,
- "\" height=\"", self._max_y-self._min_y,"\" x=\"",
- self._min_x, "\" y=\"", self._min_y, "\" />\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 " <path d=\"m%.1f %.1f " % (x, y)
-
- def _close_path(self):
- return "z\"\n"
-
- def _hide_dot(self, noscale=False):
- _saved_fill, _saved_stroke = self._fill, self._stroke
- self._fill, self._stroke = "#FF0000", "#FF0000"
- svg = "</g>/n<g>/n"
- if noscale:
- scale = 2.0
- else:
- scale = self._scale
- scale2 = scale/2
- svg += self._circle(self._dot_radius*scale2, self._hide_x*scale,
- self._hide_y*scale)
- self._fill, self._stroke = "#FFFFFF", "#FFFFFF"
- svg += self._rect(10*scale2, 2*scale2, self._hide_x*scale-5*scale2,
- self._hide_y*scale-scale+scale2)
- self._fill, self._stroke = _saved_fill, _saved_stroke
- return svg
-
- def _show_dot(self, noscale=False):
- _saved_fill, _saved_stroke = self._fill, self._stroke
- self._fill, self._stroke = "#00FE00", "#00FE00"
- svg = "</g>/n<g>/n"
- if noscale:
- scale = 2.0
- else:
- scale = self._scale
- scale2 = scale/2
- svg += self._circle(self._dot_radius*scale2, self._show_x*scale,
- self._show_y*scale)
- self._fill, self._stroke = "#FEFEFE", "#FEFEFE"
- svg += self._rect(10*scale2, 2*scale2, self._show_x*scale-5*scale2,
- self._show_y*scale-scale+scale2)
- svg += self._rect(2*scale2, 10*scale2, self._show_x*scale-scale+scale2,
- self._show_y*scale-5*scale2)
- self._fill, self._stroke = _saved_fill, _saved_stroke
- return svg
-
- def _do_slot(self):
- if self._slot is True:
- self.docks.append((int(self._x*self._scale),
- int(self._y*self._scale)))
- return "%s%s%s" % (
- self._rline_to(0, self._slot_y),
- self._rline_to(self._slot_x, 0),
- self._rline_to(0, -self._slot_y))
- elif self._cap is True:
- return "%s%s" % (
- self._rline_to(self._slot_x/2.0, -self._slot_y*2.0),
- self._rline_to(self._slot_x/2.0, self._slot_y*2.0))
- else:
- return self._rline_to(self._slot_x, 0)
-
- def _do_tail(self):
- if self._outie is True:
- return self._rline_to(-self._slot_x, 0)
- else:
- return "%s%s" % (
- self._rline_to(-self._slot_x/2.0, self._slot_y*2.0),
- self._rline_to(-self._slot_x/2.0, -self._slot_y*2.0))
-
- def _do_tab(self):
- s = "%s%s%s%s%s" % (
- self._rline_to(-self._stroke_width, 0),
- self._rline_to(0, self._slot_y),
- self._rline_to(-self._slot_x+2*self._stroke_width, 0),
- self._rline_to(0, -self._slot_y),
- self._rline_to(-self._stroke_width, 0))
- self.docks.append((int(self._x*self._scale),
- int((self._y+self._stroke_width)*self._scale)))
- return s
-
- def _do_innie(self):
- self.docks.append((int((self._x+self._stroke_width)*self._scale),
- int((self._y+self._innie_y2)*self._scale)))
- if self.margins[2] == 0:
- self.margins[1] = int((self._y-self._innie_y1)*self._scale)
- self.margins[2] = int((self._x-self._innie_x1-self._innie_x2-\
- self._stroke_width*2)*self._scale)
- self.margins[3] =\
- int((self._y+self._innie_y2+self._innie_y1)*self._scale)
- return "%s%s%s%s%s%s%s" % (
- self._rline_to(-self._innie_x1, 0),
- self._rline_to(0, -self._innie_y1),
- self._rline_to(-self._innie_x2, 0),
- self._rline_to(0, self._innie_y2+2*self._innie_y1),
- self._rline_to(self._innie_x2, 0),
- self._rline_to(0, -self._innie_y1),
- self._rline_to(self._innie_x1, 0))
-
- def _do_reverse_innie(self):
- self.docks.append((int((self._x+self._stroke_width)*self._scale),
- int((self._y)*self._scale)))
- return "%s%s%s%s%s%s%s" % (
- self._rline_to(-self._innie_x1, 0),
- self._rline_to(0, self._innie_y1),
- self._rline_to(-self._innie_x2, 0),
- self._rline_to(0, -self._innie_y2-2*self._innie_y1),
- self._rline_to(self._innie_x2, 0),
- self._rline_to(0, self._innie_y1),
- self._rline_to(self._innie_x1, 0))
-
- def _do_outie(self):
- if self._outie is not True:
- return self._rline_to(0, -self._innie_y2)
- self.docks.append((int(self._x*self._scale), int(self._y*self._scale)))
- return "%s%s%s%s%s%s%s%s%s" % (
- self._rline_to(0, -self._stroke_width),
- self._rline_to(-self._innie_x1-2*self._stroke_width, 0),
- self._rline_to(0, self._innie_y1),
- self._rline_to(-self._innie_x2+2*self._stroke_width, 0),
- self._rline_to(0,
- -self._innie_y2-2*self._innie_y1+2*self._stroke_width),
- self._rline_to(self._innie_x2-2*self._stroke_width, 0),
- self._rline_to(0, self._innie_y1),
- self._rline_to(self._innie_x1+2*self._stroke_width, 0),
- self._rline_to(0, -self._stroke_width))
-
- def _do_porch(self, flag=True):
- if flag:
- return "%s%s%s" % (
- self._rline_to(0, self._porch_y+self._innie_y1),
- self._rline_to(self._porch_x-self._radius, 0),
- self._corner(1, 1))
- else:
- return "%s%s%s" % (
- self._rline_to(0,
- self._porch_y-self._innie_y1+self._stroke_width),
- self._rline_to(self._porch_x-self._radius, 0),
- self._corner(1, 1))
-
- def _start_boolean(self, xoffset, yoffset):
- svg = self.new_path(xoffset, yoffset)
- self._radius -= self._stroke_width
- self.docks.append((int(self._x*self._scale), int(self._y*self._scale)))
- svg += self._rarc_to(1, -1)
- self._radius += self._stroke_width
- return svg + self._rline_to(self._stroke_width, 0)
-
- def _do_boolean(self):
- self.docks.append(
- (int((self._x-self._radius+self._stroke_width)*self._scale),
- int((self._y+self._radius)*self._scale)))
- self.margins[2] =\
- int((self._x-self._radius-self._stroke_width)*self._scale)
- return self._rarc_to(-1, 1, 90, 0, 0) + self._rarc_to(1, 1, 90, 0, 0)
-
- def _end_boolean(self):
- svg = self._rline_to(-self._radius*1.5,0)
- svg += self._rline_to(0, -self._stroke_width)
- svg += self._rline_to(-self._stroke_width, 0)
- self._radius -= self._stroke_width
- svg += self._rarc_to(-1, -1)
- self._radius += self._stroke_width
- svg += self._close_path()
- self.calc_w_h()
- svg += self.style()
- return svg + self.footer()
-
- def calc_w_h(self, add_stroke_width=True):
- if add_stroke_width:
- self._width = (self._max_x-self._min_x+self._stroke_width)*\
- self._scale
- else:
- self._width = (self._max_x-self._min_x)*self._scale
- if self.margins[2] == 0:
- self.margins[2] = int((self._stroke_width+0.5)*self._scale)
- else:
- self.margins[2] = int(self._width - self.margins[2])
- if add_stroke_width:
- self._height = (self._max_y-self._min_y+self._stroke_width)*\
- self._scale
- else:
- self._height = (self._max_y-self._min_y)*self._scale
- if self.margins[3] == 0:
- if self._tab:
- self.margins[3] =\
- int((self._slot_y+self._stroke_width+0.5)*self._scale)
- else:
- self.margins[3] =\
- int((self._slot_y*2+self._stroke_width+0.5)*self._scale)
- else:
- self.margins[3] = int(self._height - self.margins[3])
-
- def _calculate_x_y(self):
- 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.margins[1] = int(self._stroke_width+0.5)
- if self._outie is True:
- x += self._innie_x1+self._innie_x2
- self.margins[0] += self._innie_x1+self._innie_x2
- if self._cap is True:
- y += self._slot_y*2.0
- self.margins[1] += self._slot_y*2.0
- elif self._slot is True:
- self.margins[1] += self._slot_y
- self.margins[0] *= self._scale
- self.margins[1] *= self._scale
- return(x, y)
-
-#
-# Command-line tools for testing
-#
-
-def open_file(datapath, filename):
- return file(os.path.join(datapath, filename), "w")
-
-def close_file(f):
- f.close()
-
-def generator(datapath):
-
- svg0 = SVG()
- f = open_file(datapath, "basic.svg")
- svg0.set_scale(2)
- svg0.set_tab(True)
- svg0.set_slot(True)
- svg0.set_no_arm(True)
- svg_str = svg0.sandwich_top()
- f.write(svg_str)
- close_file(f)
-
- """
- svgt = SVG()
- svgt.set_orientation(180)
- f = open_file(datapath, "turtle180.svg")
- svg_str = svgt.turtle(["#FF0000","#00FF00"])
- f.write(svg_str)
- close_file(f)
-
-
- svg2 = SVG()
- f = open_file(datapath, "box-test.svg")
- svg2.set_scale(1)
- svg2.expand(40,0)
- svg2.set_colors(["#FFA000","#A08000"])
- svg2.set_gradiant(True)
- svg_str = svg2.basic_box()
- f.write(svg_str)
- close_file(f)
-
- svg2 = SVG()
- f = open_file(datapath, "box-test2.svg")
- svg2.set_scale(4)
- svg2.expand(40,0)
- svg2.set_colors(["#FFA000","#A08000"])
- svg2.set_gradiant(True)
- svg_str = svg2.basic_box()
- f.write(svg_str)
- close_file(f)
-
- svg3 = SVG()
- f = open_file(datapath, "compare-text.svg")
- svg3.set_scale(1)
- svg3.set_colors(["#0000FF","#0000A0"])
- svg3.set_gradiant(True)
- # svg3.set_porch(True)
- svg_str = svg3.boolean_compare()
- f.write(svg_str)
- close_file(f)
-
- svg4 = SVG()
- f = open_file(datapath, "and-or-test.svg")
- svg4.set_scale(1)
- svg4.set_colors(["#00FFFF","#00A0A0"])
- svg4.set_gradiant(True)
- svg_str = svg4.boolean_and_or()
- f.write(svg_str)
- close_file(f)
-
- svg5 = SVG()
- f = open_file(datapath, "nor-test.svg")
- svg5.set_scale(1)
- svg5.set_colors(["#FF00FF","#A000A0"])
- svg5.set_gradiant(True)
- svg_str = svg5.boolean_not()
- f.write(svg_str)
- close_file(f)
- """
-
-def main():
- return 0
-
-if __name__ == "__main__":
- generator(os.path.abspath('.'))
- main()
-
-
-#
-# Load pixbuf from SVG string
-#
-def svg_str_to_pixbuf(svg_string):
- pl = gtk.gdk.PixbufLoader('svg')
- pl.write(svg_string)
- pl.close()
- pixbuf = pl.get_pixbuf()
- return pixbuf
-
-
-#
-# Read SVG string from a file
-#
-def svg_from_file(pathname):
- f = file(pathname, 'r')
- svg = f.read()
- f.close()
- return(svg)
-
diff --git a/taturtle.py b/taturtle.py
deleted file mode 100644
index 23344e2..0000000
--- a/taturtle.py
+++ /dev/null
@@ -1,209 +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.
-
-from taconstants import TURTLE_LAYER
-from tasprite_factory import SVG, svg_str_to_pixbuf
-from sprites import Sprite
-
-def generate_turtle_pixbufs(colors):
- """ Generate pixbufs for generic turtles """
- shapes = []
- svg = SVG()
- svg.set_scale(1.0)
- for i in range(36):
- svg.set_orientation(i*10)
- shapes.append(svg_str_to_pixbuf(svg.turtle(colors)))
- return shapes
-
-#
-# A class for the list of blocks and everything they share in common
-#
-class Turtles:
- def __init__(self, sprite_list):
- """ Class to hold turtles """
- self.dict = dict()
- self.sprite_list = sprite_list
- self.default_pixbufs = []
-
- def get_turtle(self, k, append=False, colors=None):
- """ Find a turtle """
- if self.dict.has_key(k):
- return self.dict[k]
- elif append is False:
- return None
- else:
- if colors == None:
- Turtle(self, k)
- else:
- Turtle(self, k, colors.split(','))
- return self.dict[k]
-
- def get_turtle_key(self, turtle):
- """ Find a turtle's name """
- for k in iter(self.dict):
- if self.dict[k] == turtle:
- return k
- return None
-
- def turtle_count(self):
- """ How many turtles are there? """
- return(len(self.dict))
-
- def add_to_dict(self, k, turtle):
- """ Add a new turtle """
- self.dict[k] = turtle
-
- def remove_from_dict(self, k):
- """ Delete a turtle """
- if self.dict.has_key(k):
- del(self.dict[k])
-
- def show_all(self):
- """ Make all turtles visible """
- for k in iter(self.dict):
- self.dict[k].show()
-
- #
- # sprite utilities
- #
- def spr_to_turtle(self, spr):
- """ Find the turtle that corresponds to sprite spr. """
- for k in iter(self.dict):
- if spr == self.dict[k].spr:
- return self.dict[k]
- return None
-
- def get_pixbufs(self):
- """ Get the pixbufs for the default turtle shapes. """
- if self.default_pixbufs == []:
- self.default_pixbufs = generate_turtle_pixbufs(
- ["#008000", "#00A000"])
- return(self.default_pixbufs)
-
-#
-# A class for the individual turtles
-#
-class Turtle:
- def __init__(self, turtles, key, colors=None):
- """ The turtle is not a block, just a sprite with an orientation """
- self.x = 0
- self.y = 0
- self.hidden = False
- self.shapes = []
- self.type = 'turtle'
- self.heading = 0
- self.pen_shade = 50
- self.pen_color = 0
- self.pen_gray = 100
- self.pen_size = 5
- self.pen_state = True
-
- if colors is None:
- self.shapes = turtles.get_pixbufs()
- else:
- self.colors = colors[:]
- self.shapes = generate_turtle_pixbufs(self.colors)
-
- if turtles.sprite_list is not None:
- self.spr = Sprite(turtles.sprite_list, 0, 0, self.shapes[0])
- else:
- self.spr = None
- turtles.add_to_dict(key, self)
-
- def set_heading(self, heading):
- """ Set the turtle heading (and shape: one per 10 degrees) """
- self.heading = heading
- i = (int(self.heading+5)%360)/10
- if self.hidden is False and self.spr is not None:
- try:
- self.spr.set_shape(self.shapes[i])
- except IndexError:
- self.spr.set_shape(self.shapes[0])
- print "Turtle shape IndexError %f -> %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()&gtk.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()&gtk.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)