Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TurtleArt/tabasics.py1199
-rw-r--r--TurtleArt/taconstants.py755
-rw-r--r--TurtleArt/talogo.py894
-rw-r--r--TurtleArt/taprimitive.py39
-rw-r--r--TurtleArt/tawindow.py20
-rw-r--r--TurtleArtActivity.py87
-rw-r--r--plugins/turtle_blocks_plugin.py1202
7 files changed, 2546 insertions, 1650 deletions
diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py
new file mode 100644
index 0000000..7d29f5e
--- /dev/null
+++ b/TurtleArt/tabasics.py
@@ -0,0 +1,1199 @@
+# -*- coding: utf-8 -*-
+#Copyright (c) 2011, 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, you could
+simply add a block of code to this file or to turtle_block_plugin.py,
+which contains additional blocks. (Even better, write your own plugin!!)
+
+For example, if we want to add a new turtle command, 'uturn', we'd
+make the following changes:
+
+ b = Primitive('uturn')
+ b.set_palette('turtle') # the palette to place it in
+ b.set_style('basic-style') # the block style
+ b.set_label(_('u-turn')) # the label that will appear on the block
+ b.set_prim_name('uturn') # an intern name for the primitive
+ b.set_help(_('turns the turtle 180 degrees')) # a help message
+
+ # def_prim takes 3 arguments: the primitive name, the number of
+ # of arguments, 0 in this case, and the function to call.
+ # We are using a special method, 'set', that will update the label
+ # of the heading block as well as the heading itself. _prim_set
+ # also takes arguments: the name of the block whose label needs to
+ # be updated, the function call to change the value, and the new
+ # value, in the case, the current heading + 180
+ self.tw.lc._def_prim('uturn', 0,
+ lambda self, x: PLUGIN_DICTIONARY['set'](
+ 'heading', self.tw.canvas.seth, self.tw.canvas.heading + 180))
+ b.add_prim()
+
+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:
+ p = Palette('turtle', ["#00FF00", "#00A000"]) # assign name and colors
+ p.set_help(_('Palette of turtle commands')) # and a help message
+ p.add_palette()
+
+However you will have to 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 time import time
+from math import sqrt
+from random import uniform
+
+from gettext import gettext as _
+
+from taprimitive import Palette, Primitive
+from talogo import PLUGIN_DICTIONARY, VALUE_BLOCKS, logoerror
+from taconstants import DEFAULT_SCALE, CONSTANTS, BLACK, WHITE
+from tautils import convert, chr_to_ord, round_int, strtype
+
+
+def _num_type(x):
+ """ Is x a number type? """
+ if type(x) == int:
+ return True
+ if type(x) == float:
+ return True
+ if type(x) == ord:
+ return True
+ return False
+
+def _millisecond():
+ """ Current time in milliseconds """
+ return time() * 1000
+
+
+class Palettes():
+ """ a class for storing the palettes of blocks """
+
+ def __init__(self, parent):
+ self.tw = parent
+
+ p = Palette('turtle', ["#00FF00", "#00A000"])
+ p.set_help(_('Palette of turtle commands'))
+ p.add_palette()
+ self._turtle_palette()
+
+ p = Palette('pen', ["#00FFFF", "#00A0A0"])
+ p.set_help(_('Palette of pen commands'))
+ p.add_palette()
+ self._pen_palette()
+
+ p = Palette('colors', ["#00FFFF", "#00A0A0"])
+ p.set_help(_('Palette of pen colors'))
+ p.add_palette()
+ self._color_palette()
+
+ p = Palette('numbers', ["#FF00FF", "#A000A0"])
+ p.set_help(_('Palette of numeric operators'))
+ p.add_palette()
+ self._numbers_palette()
+
+ p = Palette('flow', ["#FFC000", "#A08000"])
+ p.set_help(_('Palette of flow operators'))
+ p.add_palette()
+ self._flow_palette()
+
+ p = Palette('blocks', ["#FFFF00", "#A0A000"])
+ p.set_help(_('Palette of variable blocks'))
+ p.add_palette()
+ self._blocks_palette()
+
+ p = Palette('trash', ["#FFFF00", "#A0A000"])
+ p.add_palette()
+ self._trash_palette()
+
+ # Palette definitions
+
+ def _turtle_palette(self):
+ b = Primitive('forward')
+ b.set_palette('turtle')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('forward'))
+ b.set_prim_name('forward')
+ b.set_default(100)
+ b.set_help(_('moves turtle forward'))
+ PLUGIN_DICTIONARY['move'] = self._prim_move
+ self.tw.lc._def_prim('forward', 1,
+ lambda self, x: PLUGIN_DICTIONARY['move'](
+ self.tw.canvas.forward, x))
+ b.add_prim()
+
+ b = Primitive('back')
+ b.set_palette('turtle')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('back'))
+ b.set_prim_name('back')
+ b.set_default(100)
+ b.set_help(_('moves turtle backward'))
+ self.tw.lc._def_prim('back', 1,
+ lambda self, x: PLUGIN_DICTIONARY['move'](
+ self.tw.canvas.forward, -x))
+ b.add_prim()
+
+ b = Primitive('clean')
+ b.set_palette('turtle')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('clean'))
+ b.set_prim_name('clean')
+ b.set_help(_('clears the screen and reset the turtle'))
+ PLUGIN_DICTIONARY['clean'] = self._prim_clear
+ self.tw.lc._def_prim('clean', 0,
+ lambda self: PLUGIN_DICTIONARY['clean']())
+ b.add_prim()
+
+ b = Primitive('left')
+ b.set_palette('turtle')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('left'))
+ b.set_prim_name('left')
+ b.set_default(90)
+ b.set_help(_('turns turtle counterclockwise (angle in degrees'))
+ PLUGIN_DICTIONARY['right'] = self._prim_right
+ self.tw.lc._def_prim('right', 1,
+ lambda self, x: PLUGIN_DICTIONARY['right'](-x))
+ b.add_prim()
+
+ b = Primitive('right')
+ b.set_palette('turtle')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('right'))
+ b.set_prim_name('right')
+ b.set_default(90)
+ b.set_help(_('turns turtle clockwise (angle in degrees'))
+ self.tw.lc._def_prim('right', 1,
+ lambda self, x: PLUGIN_DICTIONARY['right'](x))
+ b.add_prim()
+
+ b = Primitive('arc')
+ b.set_palette('turtle')
+ b.set_style('basic-style-2arg')
+ b.set_label([_('arc'), _('angle'), _('radius')])
+ b.set_prim_name('arc')
+ b.set_default([90, 100])
+ b.set_help(_('moves turtle along an arc'))
+ PLUGIN_DICTIONARY['arc'] = self._prim_arc
+ self.tw.lc._def_prim('arc', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['arc'](
+ self.tw.canvas.arc, x, y))
+ b.add_prim()
+
+ b = Primitive('setxy2')
+ b.set_palette('turtle')
+ b.set_style('basic-style-2arg')
+ b.set_label([_('set xy'), _('x'), _('y')])
+ b.set_prim_name('setxy2')
+ b.set_default([0, 0])
+ b.set_help(_('moves turtle to position xcor, ycor; (0, 0) is in the center of the screen.'))
+ self.tw.lc._def_prim('setxy2', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['move'](
+ self.tw.canvas.setxy, x, y))
+ b.add_prim()
+
+ b = Primitive('setxy') # Depreciated
+ b.set_style('basic-style-2arg')
+ b.set_label([_('set xy'), _('x'), _('y')])
+ b.set_prim_name('setxy')
+ b.set_default([0, 0])
+ b.set_help(_('moves turtle to position xcor, ycor; (0, 0) is in the center of the screen.'))
+ self.tw.lc._def_prim('setxy', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['move'](
+ self.tw.canvas.setxy, x, y, pendown=False))
+ b.add_prim()
+
+ b = Primitive('seth')
+ b.set_palette('turtle')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set heading'))
+ b.set_prim_name('seth')
+ b.set_default(0)
+ b.set_help(_('sets the heading of the turtle (0 is towards the top of the screen.'))
+ PLUGIN_DICTIONARY['set'] = self._prim_set
+ self.tw.lc._def_prim('seth', 1,
+ lambda self, x: PLUGIN_DICTIONARY['set'](
+ 'heading', self.tw.canvas.seth, x))
+ b.add_prim()
+
+ b = Primitive('xcor')
+ b.set_palette('turtle')
+ b.set_style('box-style')
+ b.set_label(_('xcor'))
+ b.set_help(_('holds current x-coordinate value of the turtle (can be used in place of a number block'))
+ b.set_value_block(True)
+ b.set_prim_name('xcor')
+ self.tw.lc._def_prim(
+ 'xcor', 0, lambda self: self.tw.canvas.xcor / self.tw.coord_scale)
+ b.add_prim()
+
+ b = Primitive('ycor')
+ b.set_palette('turtle')
+ b.set_style('box-style')
+ b.set_label(_('ycor'))
+ b.set_help(_('holds current y-coordinate value of the turtle (can be used in place of a number block'))
+ b.set_value_block(True)
+ b.set_prim_name('ycor')
+ self.tw.lc._def_prim(
+ 'ycor', 0, lambda self: self.tw.canvas.ycor / self.tw.coord_scale)
+ b.add_prim()
+
+ b = Primitive('heading')
+ b.set_palette('turtle')
+ b.set_style('box-style')
+ b.set_label(_('heading'))
+ b.set_help(_('holds current heading value of the turtle (can be used in place of a number block'))
+ b.set_value_block(True)
+ b.set_prim_name('heading')
+ self.tw.lc._def_prim(
+ 'heading', 0, lambda self: self.tw.canvas.heading)
+ b.add_prim()
+
+ def _pen_palette(self):
+ b = Primitive('penup')
+ b.set_palette('pen')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('pen up'))
+ b.set_prim_name('penup')
+ b.set_help(_('Turtle will not draw when moved.'))
+ self.tw.lc._def_prim('penup', 0,
+ lambda self: self.tw.canvas.setpen(False))
+ b.add_prim()
+
+ b = Primitive('pendown')
+ b.set_palette('pen')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('pen down'))
+ b.set_prim_name('pendown')
+ b.set_help(_('Turtle will draw when moved.'))
+ self.tw.lc._def_prim('pendown', 0,
+ lambda self: self.tw.canvas.setpen(True))
+ b.add_prim()
+
+ b = Primitive('setpensize')
+ b.set_palette('pen')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set pen size'))
+ b.set_prim_name('setpensize')
+ b.set_default(5)
+ b.set_help(_('sets size of the line drawn by the turtle'))
+ self.tw.lc._def_prim('setpensize', 1,
+ lambda self, x: PLUGIN_DICTIONARY['set'](
+ 'pensize', self.tw.canvas.setpensize, x))
+ b.add_prim()
+
+ b = Primitive('fillscreen')
+ b.set_palette('pen')
+ b.set_style('basic-style-2arg')
+ b.set_label([_('fill screen'), _('color'), _('shade')])
+ b.set_prim_name('fillscreen')
+ b.set_default([60, 80])
+ b.set_help(_('fills the background with (color, shade)'))
+ self.tw.lc._def_prim('fillscreen', 2,
+ lambda self, x, y: self.tw.canvas.fillscreen(x, y))
+ b.add_prim()
+
+ b = Primitive('pensize')
+ b.set_palette('pen')
+ b.set_style('box-style')
+ b.set_label(_('pen size'))
+ b.set_help(_('holds current pen size (can be used in place of a number block)'))
+ b.set_value_block(True)
+ b.set_prim_name('pensize')
+ self.tw.lc._def_prim('pensize', 0, lambda self: self.tw.canvas.pensize)
+ b.add_prim()
+
+ b = Primitive('startfill')
+ b.set_palette('pen')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('start fill'))
+ b.set_prim_name('startfill')
+ b.set_help(_('starts filled polygon (used with end fill block)'))
+ self.tw.lc._def_prim('startfill', 0,
+ lambda self: self.tw.canvas.start_fill())
+ b.add_prim()
+
+ b = Primitive('stopfill')
+ b.set_palette('pen')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('end fill'))
+ b.set_prim_name('stopfill')
+ b.set_help(_('completes filled polygon (used with start fill block)'))
+ self.tw.lc._def_prim('stopfill', 0,
+ lambda self: self.tw.canvas.stop_fill())
+ b.add_prim()
+
+ def _color_palette(self):
+ b = Primitive('setcolor')
+ b.set_palette('colors')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set color'))
+ b.set_prim_name('setcolor')
+ b.set_default(0)
+ b.set_help(_('sets color of the line drawn by the turtle'))
+ self.tw.lc._def_prim('setcolor', 1,
+ lambda self, x: PLUGIN_DICTIONARY['set'](
+ 'color', self.tw.canvas.setcolor, x))
+ b.add_prim()
+
+ b = Primitive('settextcolor') # depreciated
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set text color'))
+ b.set_prim_name('settextcolor')
+ b.set_default(0)
+ b.set_help(_('sets color of text drawn by the turtle'))
+ self.tw.lc._def_prim('settextcolor', 1,
+ lambda self, x: self.tw.canvas.settextcolor(x))
+ b.add_prim()
+
+ b = Primitive('setshade')
+ b.set_palette('colors')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set shade'))
+ b.set_prim_name('setshade')
+ b.set_default(50)
+ b.set_help(_('sets shade of the line drawn by the turtle'))
+ self.tw.lc._def_prim('setshade', 1,
+ lambda self, x: PLUGIN_DICTIONARY['set'](
+ 'shade', self.tw.canvas.setshade, x))
+ b.add_prim()
+
+ b = Primitive('setgray')
+ b.set_palette('colors')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set gray'))
+ b.set_prim_name('setgray')
+ b.set_default(100)
+ b.set_help(_('sets gray level of the line drawn by the turtle'))
+ self.tw.lc._def_prim('setgray', 1,
+ lambda self, x: PLUGIN_DICTIONARY['set'](
+ 'gray', self.tw.canvas.setgray, x))
+ b.add_prim()
+
+ b = Primitive('color')
+ b.set_palette('colors')
+ b.set_style('box-style')
+ b.set_label(_('color'))
+ b.set_help(_('holds current pen color (can be used in place of a number block)'))
+ b.set_value_block(True)
+ b.set_prim_name('color')
+ self.tw.lc._def_prim('color', 0, lambda self: self.tw.canvas.color)
+ b.add_prim()
+
+ b = Primitive('shade')
+ b.set_palette('colors')
+ b.set_style('box-style')
+ b.set_label(_('shade'))
+ b.set_help(_('holds current pen shade'))
+ b.set_value_block(True)
+ b.set_prim_name('shade')
+ self.tw.lc._def_prim('shade', 0, lambda self: self.tw.canvas.shade)
+ b.add_prim()
+
+ b = Primitive('gray')
+ b.set_palette('colors')
+ b.set_style('box-style')
+ b.set_label(_('gray'))
+ b.set_help(_('holds current gray level (can be used in place of a number block)'))
+ b.set_value_block(True)
+ b.set_prim_name('gray')
+ self.tw.lc._def_prim('gray', 0, lambda self: self.tw.canvas.gray)
+ b.add_prim()
+
+ self._make_constant('red', 'colors', CONSTANTS['red'])
+ self._make_constant('orange', 'colors', CONSTANTS['orange'])
+ self._make_constant('yellow', 'colors', CONSTANTS['yellow'])
+ self._make_constant('green', 'colors', CONSTANTS['green'])
+ self._make_constant('cyan', 'colors', CONSTANTS['cyan'])
+ self._make_constant('blue', 'colors', CONSTANTS['blue'])
+ self._make_constant('purple', 'colors', CONSTANTS['purple'])
+ self._make_constant('white', 'colors', WHITE)
+ self._make_constant('black', 'colors', BLACK)
+
+ def _numbers_palette(self):
+ b = Primitive('plus2')
+ b.set_palette('numbers')
+ b.set_style('number-style')
+ b.set_label('+')
+ b.set_special_name(_('plus'))
+ b.set_prim_name('plus')
+ b.set_help(_('adds two alphanumeric inputs'))
+ PLUGIN_DICTIONARY['plus'] = self._prim_plus
+ self.tw.lc._def_prim(
+ 'plus', 2, lambda self, x, y: PLUGIN_DICTIONARY['plus'](x, y))
+ b.add_prim()
+
+ b = Primitive('minus2')
+ b.set_palette('numbers')
+ b.set_style('number-style-porch')
+ b.set_label('–')
+ b.set_special_name(_('minus'))
+ b.set_prim_name('minus')
+ b.set_help(_('subtracts bottom numeric input from top numeric input'))
+ PLUGIN_DICTIONARY['minus'] = self._prim_minus
+ self.tw.lc._def_prim(
+ 'minus', 2, lambda self, x, y: PLUGIN_DICTIONARY['minus'](x, y))
+ b.add_prim()
+
+ b = Primitive('product2')
+ b.set_palette('numbers')
+ b.set_style('number-style')
+ b.set_label('×')
+ b.set_special_name(_('multiply'))
+ b.set_prim_name('product')
+ b.set_help(_('multiplies two numeric inputs'))
+ PLUGIN_DICTIONARY['product'] = self._prim_product
+ self.tw.lc._def_prim(
+ 'product', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['product'](x, y))
+ b.add_prim()
+
+ b = Primitive('division2')
+ b.set_palette('numbers')
+ b.set_style('number-style-porch')
+ b.set_label('/')
+ b.set_special_name(_('divide'))
+ b.set_prim_name('division')
+ b.set_help(_('divides top numeric input (numerator) by bottom numeric input (denominator)'))
+ PLUGIN_DICTIONARY['division'] = self._prim_careful_divide
+ self.tw.lc._def_prim(
+ 'division', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['division'](x, y))
+ b.add_prim()
+
+ b = Primitive('identity2')
+ b.set_palette('numbers')
+ b.set_style('number-style-1strarg')
+ b.set_label('←')
+ b.set_special_name(_('identity'))
+ b.set_prim_name('id')
+ b.set_help(_('identity operator used for extending blocks'))
+ PLUGIN_DICTIONARY['id'] = self._prim_identity
+ self.tw.lc._def_prim('id', 1,
+ lambda self, x: PLUGIN_DICTIONARY['id'](x))
+ b.add_prim()
+
+ b = Primitive('remainder2')
+ b.set_palette('numbers')
+ b.set_style('number-style-porch')
+ b.set_label(_('mod'))
+ b.set_special_name(_('mod'))
+ b.set_prim_name('remainder')
+ b.set_help(_('modular (remainder) operator'))
+ PLUGIN_DICTIONARY['remainder'] = self._prim_mod
+ self.tw.lc._def_prim('remainder', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['remainder'](x, y))
+ b.add_prim()
+
+ b = Primitive('sqrt')
+ b.set_palette('numbers')
+ b.set_style('number-style-1arg')
+ b.set_label(_('√'))
+ b.set_special_name(_('square root'))
+ b.set_prim_name('sqrt')
+ b.set_help(_('calculates square root'))
+ PLUGIN_DICTIONARY['sqrt'] = self._prim_sqrt
+ self.tw.lc._def_prim('sqrt', 1,
+ lambda self, x: PLUGIN_DICTIONARY['sqrt'](x))
+ b.add_prim()
+
+ b = Primitive('random')
+ b.set_palette('numbers')
+ b.set_style('number-style-block')
+ b.set_label([_('random'), _('min'), _('max')])
+ b.set_default([0, 100])
+ b.set_prim_name('random')
+ b.set_help(_('returns random number between minimum (top) and maximum (bottom) values'))
+ PLUGIN_DICTIONARY['random'] = self._prim_random
+ self.tw.lc._def_prim(
+ 'random', 2, lambda self, x, y: PLUGIN_DICTIONARY['random'](x, y))
+ b.add_prim()
+
+ b = Primitive('number')
+ b.set_palette('numbers')
+ b.set_style('box-style')
+ b.set_label('100')
+ b.set_default(100)
+ b.set_special_name(_('number'))
+ b.set_help('used as numeric input in mathematic operators')
+ b.add_prim()
+
+ b = Primitive('greater2')
+ b.set_palette('numbers')
+ b.set_style('compare-porch-style')
+ b.set_label('>')
+ b.set_special_name(_('greater than'))
+ b.set_prim_name('greater?')
+ b.set_help(_('logical greater-than operator'))
+ PLUGIN_DICTIONARY['more'] = self._prim_more
+ self.tw.lc._def_prim(
+ 'greater?', 2, lambda self, x, y: PLUGIN_DICTIONARY['more'](x, y))
+ b.add_prim()
+
+ b = Primitive('less2')
+ b.set_palette('numbers')
+ b.set_style('compare-porch-style')
+ b.set_label('<')
+ b.set_special_name(_('less than'))
+ b.set_prim_name('less?')
+ b.set_help(_('logical less-than operator'))
+ PLUGIN_DICTIONARY['less'] = self._prim_less
+ self.tw.lc._def_prim(
+ 'less?', 2, lambda self, x, y: PLUGIN_DICTIONARY['less'](x, y))
+ b.add_prim()
+
+ b = Primitive('equal2')
+ b.set_palette('numbers')
+ b.set_style('compare-style')
+ b.set_label('=')
+ b.set_special_name(_('equal'))
+ b.set_prim_name('equal?')
+ b.set_help(_('logical equal-to operator'))
+ PLUGIN_DICTIONARY['equal'] = self._prim_equal
+ self.tw.lc._def_prim(
+ 'equal?', 2, lambda self, x, y: PLUGIN_DICTIONARY['equal'](x, y))
+ b.add_prim()
+
+ b = Primitive('not')
+ b.set_palette('numbers')
+ b.set_style('not-style')
+ b.set_label(_('not'))
+ b.set_prim_name('not')
+ b.set_help(_('logical NOT operator'))
+ self.tw.lc._def_prim('not', 1, lambda self, x: not x)
+ b.add_prim()
+
+ b = Primitive('and2')
+ b.set_palette('numbers')
+ b.set_style('boolean-style')
+ b.set_label(_('and'))
+ b.set_prim_name('and')
+ b.set_special_name(_('and'))
+ b.set_help(_('logical AND operator'))
+ self.tw.lc._def_prim('not', 2, lambda self, x, y: x & y)
+ b.add_prim()
+
+ b = Primitive('or2')
+ b.set_palette('numbers')
+ b.set_style('boolean-style')
+ b.set_label(_('or'))
+ b.set_prim_name('or')
+ b.set_special_name(_('or'))
+ b.set_help(_('logical OR operator'))
+ self.tw.lc._def_prim('not', 2, lambda self, x, y: x | y)
+ b.add_prim()
+
+ def _flow_palette(self):
+ b = Primitive('wait')
+ b.set_palette('flow')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('wait'))
+ b.set_prim_name('wait')
+ b.set_default(1)
+ b.set_help(_('pauses program execution a specified number of seconds'))
+ PLUGIN_DICTIONARY['wait'] = self._prim_wait
+ self.tw.lc._def_prim('wait', 1, PLUGIN_DICTIONARY['wait'], True)
+ b.add_prim()
+
+ b = Primitive('forever')
+ b.set_palette('flow')
+ b.set_style('flow-style')
+ b.set_label(_('forever'))
+ b.set_prim_name('forever')
+ b.set_default([None, 'vspace'])
+ b.set_help(_('loops forever'))
+ PLUGIN_DICTIONARY['forever'] = self._prim_forever
+ self.tw.lc._def_prim('forever', 1, PLUGIN_DICTIONARY['forever'], True)
+ b.add_prim()
+
+ b = Primitive('repeat')
+ b.set_palette('flow')
+ b.set_style('flow-style-1arg')
+ b.set_label([' ', _('repeat')])
+ b.set_prim_name('repeat')
+ b.set_default([4, None, 'vspace'])
+ b.set_special_name(_('repeat'))
+ b.set_help(_('loops specified number of times'))
+ PLUGIN_DICTIONARY['repeat'] = self._prim_repeat
+ self.tw.lc._def_prim('repeat', 2, PLUGIN_DICTIONARY['repeat'], True)
+ b.add_prim()
+
+ b = Primitive('if')
+ b.set_palette('flow')
+ b.set_style('flow-style-boolean')
+ b.set_label([' ', _('if'), _('then')])
+ b.set_prim_name('if')
+ b.set_default([None, None, 'vspace'])
+ b.set_special_name(_('if then'))
+ b.set_help(_('if-then operator that uses boolean operators from Numbers palette'))
+ PLUGIN_DICTIONARY['if'] = self._prim_if
+ self.tw.lc._def_prim('if', 2, PLUGIN_DICTIONARY['if'], True)
+ b.add_prim()
+
+ b = Primitive('ifelse')
+ b.set_palette('flow')
+ b.set_style('flow-style-else')
+ b.set_label([' ', _('if'), _('then else')])
+ b.set_prim_name('ifelse')
+ b.set_default([None, 'vspace', None, 'vspace'])
+ b.set_special_name(_('if then else'))
+ b.set_help(_('if-then-else operator that uses boolean operators from Numbers palette'))
+ PLUGIN_DICTIONARY['ifelse'] = self._prim_ifelse
+ self.tw.lc._def_prim('ifelse', 3, PLUGIN_DICTIONARY['ifelse'], True)
+ b.add_prim()
+
+ b = Primitive('hspace')
+ b.set_palette('flow')
+ b.set_style('flow-style-tail')
+ b.set_label(' ')
+ b.set_prim_name('nop')
+ b.set_special_name(_('horizontal space'))
+ b.set_help(_('jogs stack right'))
+ self.tw.lc._def_prim('nop', 0, lambda self: None)
+ b.add_prim()
+
+ b = Primitive('vspace')
+ b.set_palette('flow')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(' ')
+ b.set_prim_name('nop')
+ b.set_special_name(_('vertical space'))
+ b.set_help(_('jogs stack down'))
+ self.tw.lc._def_prim('nop', 0, lambda self: None)
+ b.add_prim()
+
+ b = Primitive('stopstack')
+ b.set_palette('flow')
+ b.set_style('basic-style-tail')
+ b.set_label(_('stop action'))
+ b.set_prim_name('stopstack')
+ b.set_help(_('stops current action'))
+ PLUGIN_DICTIONARY['stopstack'] = self._prim_stopstack
+ self.tw.lc._def_prim('stopstack', 0,
+ lambda self: PLUGIN_DICTIONARY['stopstack']())
+ b.add_prim()
+
+ def _blocks_palette(self):
+ b = Primitive('start')
+ b.set_palette('blocks')
+ b.set_style('basic-style-head')
+ b.set_label(_('start'))
+ b.set_prim_name('start')
+ b.set_help(_('connects action to toolbar run buttons'))
+ PLUGIN_DICTIONARY['start'] = self._prim_start
+ self.tw.lc._def_prim('start', 0,
+ lambda self: PLUGIN_DICTIONARY['start']())
+ b.add_prim()
+
+ b = Primitive('storeinbox1')
+ b.set_palette('blocks')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('store in box 1'))
+ b.set_prim_name('storeinbox1')
+ b.set_default(100)
+ b.set_help(_('stores numeric value in Variable 1'))
+ PLUGIN_DICTIONARY['setbox'] = self._prim_setbox
+ self.tw.lc._def_prim('storeinbox1', 1,
+ lambda self, x: PLUGIN_DICTIONARY['setbox'](
+ 'box1', None, x))
+ b.add_prim()
+
+ b = Primitive('storeinbox2')
+ b.set_palette('blocks')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('store in box 2'))
+ b.set_prim_name('storeinbox2')
+ b.set_default(100)
+ b.set_help(_('stores numeric value in Variable 2'))
+ self.tw.lc._def_prim('storeinbox2', 1,
+ lambda self, x: PLUGIN_DICTIONARY['setbox'](
+ 'box2', None, x))
+ b.add_prim()
+
+ b = Primitive('string')
+ b.set_palette('blocks')
+ b.set_style('box-style')
+ b.set_label(_('text'))
+ b.set_default(_('text'))
+ b.set_special_name('')
+ b.set_help('string value')
+ b.add_prim()
+
+ b = Primitive('box1')
+ b.set_palette('blocks')
+ b.set_style('box-style')
+ b.set_label(_('box 1'))
+ b.set_prim_name('box1')
+ b.set_help('Variable 1 (numeric value)')
+ b.set_value_block(True)
+ self.tw.lc._def_prim('box1', 0, lambda self: self.tw.lc.boxes['box1'])
+ b.add_prim()
+
+ b = Primitive('box2')
+ b.set_palette('blocks')
+ b.set_style('box-style')
+ b.set_label(_('box 2'))
+ b.set_prim_name('box2')
+ b.set_help('Variable 2 (numeric value)')
+ b.set_value_block(True)
+ self.tw.lc._def_prim('box2', 0, lambda self: self.tw.lc.boxes['box2'])
+ b.add_prim()
+
+ b = Primitive('box')
+ b.set_palette('blocks')
+ b.set_style('number-style-1strarg')
+ b.set_label(_('box'))
+ b.set_prim_name('box')
+ b.set_default(_('my box'))
+ b.set_help('named variable (numeric value)')
+ PLUGIN_DICTIONARY['box'] = self._prim_box
+ self.tw.lc._def_prim('box', 1,
+ lambda self, x: PLUGIN_DICTONARY['box'](x))
+ b.add_prim()
+
+ b = Primitive('storein')
+ b.set_palette('blocks')
+ b.set_style('basic-style-2arg')
+ b.set_label([_('store in'), _('box'), _('value')])
+ b.set_prim_name('storeinbox')
+ b.set_default([_('my box'), 100])
+ b.set_help(_('stores numeric value in named variable'))
+ self.tw.lc._def_prim('storeinbox', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['setbox'](
+ 'box3', x, y))
+ b.add_prim()
+
+ b = Primitive('hat')
+ b.set_palette('blocks')
+ b.set_style('basic-style-head-1arg')
+ b.set_label(_('action'))
+ b.set_prim_name('nop3')
+ b.set_default(_('action'))
+ b.set_help(_('top of nameable action stack'))
+ self.tw.lc._def_prim('nop3', 1, lambda self, x: None)
+ b.add_prim()
+
+ b = Primitive('hat1')
+ b.set_palette('blocks')
+ b.set_style('basic-style-head')
+ b.set_label(_('action 1'))
+ b.set_prim_name('nop1')
+ b.set_default(_('action 1'))
+ b.set_help(_('top of Action 1 stack'))
+ self.tw.lc._def_prim('nop1', 0, lambda self: None)
+ b.add_prim()
+
+ b = Primitive('hat2')
+ b.set_palette('blocks')
+ b.set_style('basic-style-head')
+ b.set_label(_('action 2'))
+ b.set_prim_name('nop2')
+ b.set_default(_('action 2'))
+ b.set_help(_('top of Action 2 stack'))
+ self.tw.lc._def_prim('nop2', 0, lambda self: None)
+ b.add_prim()
+
+ b = Primitive('stack')
+ b.set_palette('blocks')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('action'))
+ b.set_prim_name('stack')
+ b.set_default(_('action'))
+ b.set_help(_('invokes named action stack'))
+ PLUGIN_DICTIONARY['stack'] = self._prim_stack
+ self.tw.lc._def_prim('stack', 1, PLUGIN_DICTIONARY['stack'], True)
+ b.add_prim()
+
+ b = Primitive('stack1')
+ b.set_palette('blocks')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('action 1'))
+ b.set_prim_name('stack1')
+ b.set_default(_('action 1'))
+ b.set_help(_('invokes Action 1 stack'))
+ PLUGIN_DICTIONARY['stack1'] = self._prim_stack1
+ self.tw.lc._def_prim('stack1', 0, PLUGIN_DICTIONARY['stack1'], True)
+ b.add_prim()
+
+ b = Primitive('stack2')
+ b.set_palette('blocks')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('action 2'))
+ b.set_prim_name('stack2')
+ b.set_default(_('action 2'))
+ b.set_help(_('invokes Action 2 stack'))
+ PLUGIN_DICTIONARY['stack2'] = self._prim_stack2
+ self.tw.lc._def_prim('stack2', 0, PLUGIN_DICTIONARY['stack2'], True)
+ b.add_prim()
+
+ def _trash_palette(self):
+ b = Primitive('empty')
+ b.set_palette('trash')
+ b.set_style('basic-style-tail')
+ b.set_label(_('empty trash'))
+ b.set_help(_("permanently deletes items in trash"))
+ b.add_prim()
+
+ b = Primitive('restoreall')
+ b.set_palette('trash')
+ b.set_style('basic-style-head')
+ b.set_label(_('restore all'))
+ b.set_help(_("restore all blocks from trash"))
+ b.add_prim()
+
+ # Block primitives
+
+ def _prim_arc(self, cmd, value1, value2):
+ """ Turtle draws an arc of degree, radius """
+ cmd(float(value1), float(value2))
+ self.tw.lc.update_label_value(
+ 'xcor', self.tw.canvas.xcor / self.tw.coord_scale)
+ self.tw.lc.update_label_value(
+ 'ycor', self.tw.canvas.ycor / self.tw.coord_scale)
+ self.tw.lc.update_label_value('heading', self.tw.canvas.heading)
+ if len(self.lc.tw.value_blocks['see']) > 0:
+ self.lc.tw.see()
+
+ def _prim_box(self, x):
+ """ Retrieve value from named box """
+ if type(convert(x, float, False)) == float:
+ if int(float(x)) == x:
+ x = int(x)
+ try:
+ return self.tw.lc.boxes['box3' + str(x)]
+ except KeyError:
+ raise logoerror("#emptybox")
+
+ def _prim_clear(self):
+ """ Clear screen """
+ if self.tw.gst_available:
+ from tagplay import stop_media
+ # stop_media(self) # TODO: gplay variable
+ self.tw.canvas.clearscreen()
+ self.tw.lc.scale = DEFAULT_SCALE # TODO: move to lc method
+ self.tw.lc.hidden_turtle = None
+ self.tw.lc._start_time = time()
+ for name in VALUE_BLOCKS:
+ self.tw.lc.update_label_value(name)
+
+ def _prim_forever(self, blklist):
+ """ Do list forever """
+ while True:
+ self.tw.lc._icall(self.tw.lc._evline, blklist[:])
+ yield True
+ if self.tw.lc.procstop:
+ break
+ self.tw.lc._ireturn()
+ yield True
+
+ def _prim_if(self, boolean, blklist):
+ """ If bool, do list """
+ if boolean:
+ self.tw.lc._icall(self.tw.lc._evline, blklist[:])
+ yield True
+ self.tw.lc._ireturn()
+ yield True
+
+ def _prim_ifelse(self, boolean, list1, list2):
+ """ If bool, do list1, else do list2 """
+ if boolean:
+ self.tw.lc._ijmp(self.tw.lc._evline, list1[:])
+ yield True
+ else:
+ self.tw.lc._ijmp(self.tw.lc._evline, list2[:])
+ yield True
+
+ def _prim_move(self, cmd, value1, value2=None, pendown=True):
+ """ Turtle moves by method specified in value1 """
+ if value2 is None:
+ cmd(value1)
+ else:
+ cmd(float(value1), float(value2), pendown=pendown)
+ self.tw.lc.update_label_value('xcor',
+ self.tw.canvas.xcor / self.tw.coord_scale)
+ self.tw.lc.update_label_value('ycor',
+ self.tw.canvas.ycor / self.tw.coord_scale)
+ if len(self.tw.lc.value_blocks['see']) > 0:
+ self.tw.lc.see()
+
+ def _prim_repeat(self, num, blklist):
+ """ Repeat list num times. """
+ num = self.tw.lc._int(num)
+ for i in range(num):
+ self.tw.lc._icall(self.tw.lc._evline, blklist[:])
+ yield True
+ if self.tw.lc.procstop:
+ break
+ self.tw.lc._ireturn()
+ yield True
+
+ def _prim_right(self, value):
+ """ Turtle rotates clockwise """
+ self.tw.canvas.right(float(value))
+ self.tw.lc.update_label_value('heading', self.tw.canvas.heading)
+
+ def _prim_set(self, name, cmd, value=None):
+ """ Set a value and update the associated value blocks """
+ if value is not None:
+ cmd(value)
+ self.tw.lc.update_label_value(name, value)
+
+ def _prim_setbox(self, name, x, val):
+ """ Define value of named box """
+ if x is not None:
+ if type(convert(x, float, False)) == float:
+ if int(float(x)) == x:
+ x = int(x)
+ self.tw.lc.boxes[name + str(x)] = val
+ return
+
+ self.tw.lc.boxes[name] = val
+ self.tw.lc.update_label_value(name, val)
+
+ def _prim_stack(self, x):
+ """ Process a named stack """
+ if type(convert(x, float, False)) == float:
+ if int(float(x)) == x:
+ x = int(x)
+ if 'stack3' + str(x) not in self.tw.lc.stacks or \
+ self.tw.lc.stacks['stack3' + str(x)] is None:
+ raise logoerror("#nostack")
+ self.tw.lc._icall(self.tw.lc._evline,
+ self.tw.lc.stacks['stack3' + str(x)][:])
+ yield True
+ self.tw.lc.procstop = False
+ self.tw.lc._ireturn()
+ yield True
+
+ def _prim_stack1(self):
+ """ Process Stack 1 """
+ if self.tw.lc.stacks['stack1'] is None:
+ raise logoerror("#nostack")
+ self.tw.lc._icall(self.tw.lc._evline,
+ self.tw.lc.stacks['stack1'][:])
+ yield True
+ self.tw.lc.procstop = False
+ self.tw.lc._ireturn()
+ yield True
+
+ def _prim_stack2(self):
+ """ Process Stack 2 """
+ if self.tw.lc.stacks['stack2'] is None:
+ raise logoerror("#nostack")
+ self.tw.lc._icall(self.tw.lc._evline, self.tw.lc.stacks['stack2'][:])
+ yield True
+ self.tw.lc.procstop = False
+ self.tw.lc._ireturn()
+ yield True
+
+ def _prim_start(self):
+ """ Start block: recenter """
+ if self.tw.running_sugar:
+ self.tw.activity.recenter()
+
+ def _prim_stopstack(self):
+ """ Stop execution of a stack """
+ self.tw.lc.procstop = True
+
+ def _prim_wait(self, time):
+ """ Show the turtle while we wait """
+ self.tw.active_turtle.show()
+ endtime = _millisecond() + time * 1000.
+ while _millisecond() < endtime:
+ yield True
+ self.tw.active_turtle.hide()
+ self.tw.lc._ireturn()
+ yield True
+
+ # Math primitivies
+
+ def _prim_careful_divide(self, x, y):
+ """ Raise error on divide by zero """
+ try:
+ return x / y
+ except ZeroDivisionError:
+ raise logoerror("#zerodivide")
+ except TypeError:
+ try:
+ return self._string_to_num(x) / self._string_to_num(y)
+ except ZeroDivisionError:
+ raise logoerror("#zerodivide")
+ except ValueError:
+ raise logoerror("#syntaxerror")
+ except TypeError:
+ raise logoerror("#notanumber")
+
+ def _prim_equal(self, x, y):
+ """ Numeric and logical equal """
+ try:
+ return float(x) == float(y)
+ except TypeError:
+ typex, typey = False, False
+ if strtype(x):
+ typex = True
+ if strtype(y):
+ typey = True
+ if typex and typey:
+ return x == y
+ try:
+ return self._string_to_num(x) == self._string_to_num(y)
+ except ValueError:
+ raise logoerror("#syntaxerror")
+
+ def _prim_less(self, x, y):
+ """ Compare numbers and strings """
+ try:
+ return float(x) < float(y)
+ except ValueError:
+ typex, typey = False, False
+ if strtype(x):
+ typex = True
+ if strtype(y):
+ typey = True
+ if typex and typey:
+ return x < y
+ try:
+ return self._string_to_num(x) < self._string_to_num(y)
+ except TypeError:
+ raise logoerror("#notanumber")
+
+ def _prim_more(self, x, y):
+ """ Compare numbers and strings """
+ return self._prim_less(y, x)
+
+ def _prim_plus(self, x, y):
+ """ Add numbers, concat strings """
+ if _num_type(x) and _num_type(y):
+ return(x + y)
+ else:
+ if _num_type(x):
+ xx = str(round_int(x))
+ else:
+ xx = str(x)
+ if _num_type(y):
+ yy = str(round_int(y))
+ else:
+ yy = str(y)
+ return(xx + yy)
+
+ def _prim_minus(self, x, y):
+ """ Numerical subtraction """
+ if _num_type(x) and _num_type(y):
+ return(x - y)
+ try:
+ return self._string_to_num(x) - self._string_to_num(y)
+ except TypeError:
+ raise logoerror("#notanumber")
+
+ def _prim_product(self, x, y):
+ """ Numerical multiplication """
+ if _num_type(x) and _num_type(y):
+ return(x * y)
+ try:
+ return self._string_to_num(x) * self._string_to_num(y)
+ except TypeError:
+ raise logoerror("#notanumber")
+
+ def _prim_mod(self, x, y):
+ """ Numerical mod """
+ if _num_type(x) and _num_type(y):
+ return(x % y)
+ try:
+ return self._string_to_num(x) % self._string_to_num(y)
+ except TypeError:
+ raise logoerror("#notanumber")
+ except ValueError:
+ raise logoerror("#syntaxerror")
+
+ def _prim_sqrt(self, x):
+ """ Square root """
+ if _num_type(x):
+ if x < 0:
+ raise logoerror("#negroot")
+ return sqrt(x)
+ try:
+ return sqrt(self._string_to_num(x))
+ except ValueError:
+ raise logoerror("#negroot")
+ except TypeError:
+ raise logoerror("#notanumber")
+
+ def _prim_random(self, x, y):
+ """ Random integer """
+ if _num_type(x) and _num_type(y):
+ return(int(round(uniform(x, y), 0)))
+ xx, xflag = chr_to_ord(x)
+ yy, yflag = chr_to_ord(y)
+ if xflag and yflag:
+ return chr(int(round(uniform(xx, yy), 0)))
+ if not xflag:
+ xx = self._string_to_num(x)
+ if not yflag:
+ yy = self._string_to_num(y)
+ try:
+ return(int(round(uniform(xx, yy), 0)))
+ except TypeError:
+ raise logoerror("#notanumber")
+
+ def _prim_identity(self, x):
+ """ Identity function """
+ return(x)
+
+ # Utilities
+
+ def _string_to_num(self, x):
+ """ Try to comvert a string to a number """
+ if type(x) is float:
+ return(x)
+ if type(x) is int:
+ return(x)
+ if type(x) is ord:
+ return(int(x))
+ xx = convert(x.replace(self.tw.decimal_point, '.'), float)
+ if type(xx) is float:
+ return xx
+ else:
+ xx, xflag = chr_to_ord(x)
+ if xflag:
+ return xx
+ else:
+ raise logoerror("#syntaxerror")
+
+ def _make_constant(self, block_name, palette_name, constant):
+ """ Factory for constant blocks """
+ b = Primitive(block_name)
+ b.set_palette(palette_name)
+ b.set_style('box-style')
+ b.set_label(_(block_name))
+ b.set_prim_name(block_name)
+ self.tw.lc._def_prim(block_name, 0, lambda self: constant)
+ b.add_prim()
diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py
index 80738fa..bbff803 100644
--- a/TurtleArt/taconstants.py
+++ b/TurtleArt/taconstants.py
@@ -19,79 +19,6 @@
#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 _
#
@@ -112,47 +39,11 @@ TOP_LAYER = 1000
# Block-palette categories
#
-PALETTE_NAMES = ['turtle', 'pen', 'colors', 'numbers', 'flow', 'blocks',
- 'media', 'sensor', 'extras', 'portfolio', 'trash']
-
-PALETTES = [['forward', 'back', 'clean', 'left', 'right',
- 'arc', 'setxy2', 'seth', 'xcor', 'ycor', 'heading'],
- ['penup', 'pendown', 'setpensize', 'fillscreen', 'pensize',
- 'startfill', 'stopfill'],
- ['setcolor', 'setshade', 'setgray', 'color', 'shade', 'gray',
- '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'],
- ['start', 'storeinbox1', 'storeinbox2', 'string', 'box1', 'box2',
- 'box', 'storein', 'hat', 'hat1', 'hat2', 'stack', 'stack1',
- 'stack2'],
- ['journal', 'audio', 'video', 'description', 'string',
- 'show', 'setscale', 'savepix', 'savesvg', 'scale', 'mediawait'],
- ['kbinput', 'keyboard', 'readpixel', 'see', 'time'],
- ['push', 'printheap', 'clearheap', 'pop', 'comment', 'print',
- 'myfunc1arg', 'userdefined', 'cartesian', 'polar', 'addturtle',
- 'reskin', 'sandwichtop_no_label', 'sandwichbottom'],
- ['hideblocks', 'showblocks', 'fullscreen', 'picturelist',
- 'picture1x1a', 'picture1x1', 'picture2x2', 'picture2x1',
- 'picture1x2', 'leftpos', 'bottompos', 'width', 'rightpos',
- 'toppos', 'height'],
- ['empty', 'restoreall']]
-
-#
-# Block-style attributes
-#
-
-COLORS = [["#00FF00", "#00A000"], ["#00FFFF", "#00A0A0"],
- ["#00FFFF", "#00A0A0"], ["#FF00FF", "#A000A0"],
- ["#FFC000", "#A08000"], ["#FFFF00", "#A0A000"],
- ["#A0FF00", "#A0A000"], ["#FF6060", "#A06060"],
- ["#FF0000", "#A00000"], ["#6060FF", "#6060A0"],
- ["#FFFF00", "#A0A000"]]
+PALETTE_NAMES = []
+PALETTES = []
+COLORS = []
+# Special-case some block colors
BOX_COLORS = {'red': ["#FF0000", "#A00000"],
'orange': ["#FFD000", "#AA8000"],
'yellow': ["#FFFF00", "#A0A000"],
@@ -194,59 +85,47 @@ UNKNOWN = 'unknown'
#
# Block-style definitions
#
-BASIC_STYLE_HEAD = ['start', 'hat1', 'hat2', 'restore', 'restoreall']
-BASIC_STYLE_HEAD_1ARG = ['hat']
-BASIC_STYLE_TAIL = ['stopstack', 'empty']
+# TODO: define depreciated blocks
+BASIC_STYLE_HEAD = []
+BASIC_STYLE_HEAD_1ARG = []
+BASIC_STYLE_TAIL = []
BASIC_STYLE = []
-BASIC_STYLE_EXTENDED_VERTICAL = ['clean', 'penup', 'pendown', 'stack1',
- 'stack2', 'hideblocks', 'showblocks', 'clearheap', 'printheap', 'kbinput',
- 'fullscreen', 'cartesian', 'polar', 'startfill', 'mediawait',
- 'stopfill', 'readpixel', 'vspace']
-INVISIBLE = ['sandwichcollapsed']
-BASIC_STYLE_EXTENDED = ['picturelist', 'picture1x1', 'picture2x2',
- 'picture2x1', 'picture1x2', 'picture1x1a']
-BASIC_STYLE_1ARG = ['forward', 'back', 'left', 'right', 'seth', 'show',
- 'setscale', 'setpensize', 'setcolor', 'setshade', 'print', 'showaligned',
- 'settextsize', 'settextcolor', 'print', 'wait', 'storeinbox1', 'savepix',
- 'storeinbox2', 'wait', 'stack', 'push', 'nop', 'addturtle', 'comment',
- 'image', 'savesvg', 'setgray', 'skin', 'reskin']
-BASIC_STYLE_VAR_ARG = ['userdefined', 'userdefined2args', 'userdefined3args']
+BASIC_STYLE_EXTENDED_VERTICAL = []
+INVISIBLE = []
+BASIC_STYLE_EXTENDED = []
+BASIC_STYLE_1ARG = ['settextsize', 'settextcolor', 'nop']
+BASIC_STYLE_VAR_ARG = []
BULLET_STYLE = ['templatelist', 'list']
-BASIC_STYLE_2ARG = ['arc', 'setxy', 'setxy2', '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',
- 'gray', 'see', 'time']
-BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video']
-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 = ['equal2']
-COMPARE_PORCH_STYLE = ['greater2', 'less2']
-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 = ['sandwichtop_no_arm']
-COLLAPSIBLE_TOP_NO_LABEL = ['sandwichtop_no_label']
-COLLAPSIBLE_TOP_NO_ARM_NO_LABEL = ['sandwichtop_no_arm_no_label']
-COLLAPSIBLE_BOTTOM = ['sandwichbottom']
+BASIC_STYLE_2ARG = []
+BOX_STYLE = ['textsize']
+BOX_STYLE_MEDIA = []
+NUMBER_STYLE = ['myfunc']
+NUMBER_STYLE_VAR_ARG = []
+NUMBER_STYLE_BLOCK = []
+NUMBER_STYLE_PORCH = []
+NUMBER_STYLE_1ARG = []
+NUMBER_STYLE_1STRARG = []
+COMPARE_STYLE = []
+COMPARE_PORCH_STYLE = []
+BOOLEAN_STYLE = []
+NOT_STYLE = []
+FLOW_STYLE = []
+FLOW_STYLE_TAIL = []
+FLOW_STYLE_1ARG = []
+FLOW_STYLE_BOOLEAN = []
+FLOW_STYLE_WHILE = []
+FLOW_STYLE_ELSE = []
+COLLAPSIBLE_TOP = []
+COLLAPSIBLE_TOP_NO_ARM = []
+COLLAPSIBLE_TOP_NO_LABEL = []
+COLLAPSIBLE_TOP_NO_ARM_NO_LABEL = []
+COLLAPSIBLE_BOTTOM = []
# Depreciated block styles
-PORTFOLIO_STYLE_2x2 = ['template2x2']
-PORTFOLIO_STYLE_1x1 = ['template1x1', 'template1x1a']
-PORTFOLIO_STYLE_2x1 = ['template2x1']
-PORTFOLIO_STYLE_1x2 = ['template1x2']
+PORTFOLIO_STYLE_2x2 = []
+PORTFOLIO_STYLE_1x1 = []
+PORTFOLIO_STYLE_2x1 = []
+PORTFOLIO_STYLE_1x2 = []
BLOCK_STYLES = {'basic-style-head': BASIC_STYLE_HEAD,
'basic-style-head-1arg': BASIC_STYLE_HEAD_1ARG,
@@ -291,11 +170,12 @@ BLOCK_STYLES = {'basic-style-head': BASIC_STYLE_HEAD,
#
# Blocks that are expandable
#
+EXPANDABLE_STYLE = ['boolean-style', 'compare-porch-style', 'compare-style',
+ 'number-style-porch', 'number-style', 'basic-style-2arg']
+
EXPANDABLE = ['vspace', 'hspace', 'identity2']
-EXPANDABLE_BLOCKS = ['plus2', 'minus2', 'division2', 'remainder2', 'product2',
- 'random', 'equal2', 'greater2', 'less2', 'and2', 'or2',
- 'arc', 'setxy', 'setxy2', 'fillscreen', 'storein', 'write']
+EXPANDABLE_BLOCKS = []
EXPANDABLE_ARGS = ['templatelist', 'list', 'myfunc1arg', 'myfunc2arg',
'myfunc3arg', 'userdefined', 'userdefined2args',
@@ -337,376 +217,30 @@ CONSTANTS = {'leftpos': None, 'toppos': None, 'rightpos': None,
# Block-name dictionary used for labels
#
BLOCK_NAMES = {
- 'addturtle': [_('turtle')],
- 'and2': [_('and')],
- 'arc': [_('arc'), _('angle'), _('radius')],
- 'audio': [' '],
- 'back': [_('back')],
- 'black': [_('black')],
- 'blocks': [_('blocks')],
- 'blue': [_('blue')],
- 'bottompos': [_('bottom')],
- 'bottomy': [_('picture bottom')],
- 'box': [_('box')],
- 'box1': [_('box 1')],
- 'box2': [_('box 2')],
- 'cartesian': [_('Cartesian')],
- 'clean': [_(' clean ')],
- 'clearheap': [_('empty heap')],
- 'color': [_('color')],
- 'colors': [_('colors')],
- 'comment': [_('comment')],
- 'cyan': [_('cyan')],
- 'decription': [' '],
- 'division2': ['/'],
- 'empty': [_('empty trash')],
- 'equal2': ['='],
- 'extras': [_('extras')],
- 'fillscreen': [_('fill screen'), _('color'), _('shade')],
- 'flow': [_('flow')],
- 'forever': [_('forever')],
- 'forward': [_('forward')],
- 'fullscreen': [_('full screen')],
- 'gray': [_('gray')],
- 'greater2': ['>'],
- 'green': [_('green')],
- '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'],
- 'mediawait': [_('media wait')],
- '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'],
- 'numbers': [_('numbers')],
- 'orange': [_('orange')],
- 'or2': [_('or')],
- 'pen': [_('pen')],
- 'pendown': [_('pen down')],
- 'pensize': [_('pen size')],
- 'penup': [_('pen up')],
- 'picturelist': [' '],
- 'picture1x1': [' '],
- 'picture1x1a': [' '],
- 'picture2x2': [' '],
- 'picture2x1': [' '],
- 'picture1x2': [' '],
- 'pitch': [_('pitch')],
- 'plus2': ['+'],
- 'polar': [_('polar')],
- 'pop': [_('pop')],
- 'portfolio': [_('portfolio')],
- 'printheap': [_('show heap')],
- 'print': [_('print')],
- 'product2': ['×'],
- 'purple': [_('purple')],
- 'push': [_('push')],
- 'random': [_('random'), _('min'), _('max')],
- 'readpixel': [_('read pixel')],
- 'red': [_('red')],
- 'remainder2': [_('mod')],
- 'repeat': [' ', _('repeat')],
- 'reskin': [_('turtle shell')],
- 'resistance': [_('resistance')],
- 'restore': [_('restore last')],
- 'restoreall': [_('restore all')],
- 'right': [_('right')],
- 'rightpos': [_('right')],
- 'rightx': [_('picture right')],
- 'savepix': [_('save picture')],
- 'savesvg': [_('save SVG')],
- 'sandwichbottom': [' ', ' '],
- 'sandwichcollapsed': [' '],
- 'sandwichtop': [_('top of stack')],
- 'sandwichtop_no_arm': [_('top of stack')],
- 'sandwichtop_no_label': [' ', ' '],
- 'sandwichtop_no_arm_no_label': [' ', _('click to open')],
- 'scale': [_('scale')],
- 'see': [_('turtle sees')],
- 'sensor': [_('sensors')],
- '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')],
- 'setxy2': [_('set xy'), _('x'), _('y')],
- 'shade': [_('shade')],
- 'show': [_('show')],
- 'showblocks': [_('show blocks')],
- 'showaligned': [_('show aligned')],
- 'skin': [_('turtle shell')],
- 'sound': [_('sound')],
- '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')],
- 'time': [_('time')],
- 'titlex': [_('title x')],
- 'titley': [_('title y')],
- 'toppos': [_('top')],
- 'topy': [_('picture top')],
- 'trash': [_('trash')],
- 'turtle': [_('turtle')],
- 'until': [_('until')],
- 'userdefined': [_(' ')],
- 'userdefined2args': [_(' ')],
- 'userdefined3args': [_(' ')],
- 'video': [' '],
- 'voltage': [_('voltage')],
- 'volume': [_('volume')],
- 'vspace': [' '],
- 'wait': [_('wait')],
- 'while': [_('while')],
- 'while2': [_('while')],
- 'white': [_('white')],
- 'width': [_('width')],
- 'write': [_('write')],
- 'xcor': [_('xcor')],
- 'ycor': [_('ycor')],
- 'yellow': [_('yellow')]}
+ 'textsize': [_('text size')]}
#
# Logo primitives
#
-
+# TODO: check hats (nop1, 2, 3), setxy
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',
- 'mediawait': 'mediawait',
- 'minus2': 'minus',
'myfunc': 'myfunction',
- 'myfunc1arg': 'myfunction',
- 'myfunc2arg': 'myfunction2',
- 'myfunc3arg': 'myfunction3',
'nop': 'userdefined',
- 'not': 'not',
- 'orange': 'orange',
- 'or2': 'or',
- 'pendown': 'pendown',
- 'pensize': 'pensize',
- 'penup': 'penup',
- 'plus2': 'plus',
- 'polar': 'polar',
- 'pop': 'pop',
- 'printheap': 'printheap',
- 'print': 'print',
- 'product2': 'product',
- 'purple': 'purple',
- 'push': 'push',
- 'random': 'random',
- 'red': 'red',
- 'readpixel': 'readpixel',
- 'remainder2': 'mod',
- 'repeat': 'repeat',
- 'right': 'right',
- 'rightpos': 'rpos',
- 'rightx': 'rightx',
- 'sandwichtop': 'comment',
- 'sandwichtop_no_arm': 'comment',
- 'sandwichtop_no_label': 'nop',
- 'sandwichtop_no_arm_no_label': 'nop',
- 'sandwichbottom': 'nop',
- 'sandwichcollapsed': 'nop',
- 'savepix': 'savepix',
- 'savesvg': 'savesvg',
- 'see': 'see',
- 'scale': 'scale',
- 'setcolor': 'setcolor',
- 'setgray': 'setgray',
- 'seth': 'seth',
- 'setpensize': 'setpensize',
- 'setscale': 'setscale',
- 'setshade': 'setshade',
'settextsize': 'settextsize',
- 'settextcolor': 'settextcolor',
- 'setxy': 'setxy',
- 'setxy2': 'setxy2',
- 'shade': 'shade',
- 'show': 'show',
- 'showblocks': 'showblocks',
- 'showaligned': 'showaligned',
- 'skin': 'skin',
- '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',
- 'time': 'time',
- 'titlex': 'titlex',
- 'titley': 'titley',
- 'toppos': 'tpos',
- 'topy': 'topy',
- 'userdefined': 'userdefined',
- 'userdefined2args': 'userdefined2',
- 'userdefined3args': 'userdefined3',
- 'vspace': 'nop',
- 'wait': 'wait',
- 'while2': 'while',
- 'white': 'white',
- 'width': 'hres',
- 'write': 'write',
- 'xcor': 'xcor',
- 'ycor': 'ycor',
- 'yellow': 'yellow'}
+ 'textsize': 'textsize'}
#
# 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')],
- 'sandwichtop_no_arm': [_('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],
- 'setxy2': [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],
- 'video': [None],
- 'wait': [1],
- 'write': [_('text'), 32]}
+ 'nop': [100]}
#
# Blocks that can interchange strings and numbers for their arguments
@@ -763,7 +297,7 @@ OLD_NAMES = {'product': 'product2', 'storeinbox': 'storein', 'minus': 'minus2',
'template1': 'template1x1', 'template2': 'template2x1',
'template6': 'template1x2', 'template7': 'template2x2',
'template4': 'template1x1a', 'hres': 'width', 'vres': 'height',
- 'sandwichtop2': 'sandwichtop'}
+ 'sandwichtop2': 'sandwichtop', 'image': 'show'}
#
# Define the relative size and postion of media objects
@@ -786,215 +320,30 @@ TEMPLATES = {'t1x1': (0.5, 0.5, 0.0625, 0.125, 1.05, 0),
# Names for blocks without names for popup help
#
SPECIAL_NAMES = {
- 'and2': _('and'),
- 'audio': _('audio'),
- 'description': _('description'),
- 'division2': _('divide'),
- 'equal2': _('equal'),
- 'greater2': _('greater than'),
- 'hspace': _('horizontal space'),
- 'identity2': _('identity'),
- 'if': _('if then'),
- 'ifelse': _('if then else'),
- 'journal': _('journal'),
- 'less2': _('less than'),
- 'or2': _('or'),
- 'minus2': _('minus'),
- 'nop': _('Python code'),
- 'number': _('number'),
- 'plus2': _('plus'),
- 'product2': _('multiply'),
- 'remainder2': _('mod'),
- 'repeat': _('repeat'),
- 'sandwichtop_no_label': _('top of a collapsible stack'),
- 'sandwichbottom': _('bottom of a collapsible stack'),
- 'sensors': _('sensors'),
- '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'),
- 'userdefined': _('Python block'),
- 'userdefined2args': _('Python block'),
- 'userdefined3args': _('Python block'),
- 'video': _('video'),
- 'vspace': _('vertical space')}
+ 'textsize': _('text size')}
#
# 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"),
- 'media': _("Palette of media objects"),
- 'mediawait': _("wait for current video or audio to complete"),
- '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"),
- 'or2': _("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"),
- '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"),
- 'readpixel': _("RGB color under the turtle is pushed to the stack"),
- 'remainder2': _("modular (remainder) operator"),
- 'repeat': _("loops specified number of times"),
- 'resistance': _("sensor input resistance"),
- 'reskin': _("put a custom 'shell' on the turtle"),
- '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"),
- 'sandwichtop_no_label': _("top of a collapsed stack"),
- 'sandwichtop_no_arm': _("top of a collapsible stack"),
- 'sandwichtop_no_arm_no_label': _("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"),
- 'see': _('returns the color that the turtle "sees"'),
- 'sensor': _("Palette of sensor blocks"),
- '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."),
- 'setxy2': _("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"),
- 'skin': _("put a custom 'shell' on the turtle"),
- '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)"),
- 'time': _("elapsed time (in seconds) since program started"),
- '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"),
- 'video': _("Sugar Journal video object"),
- 'voltage': _("sensor voltage"),
- '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)")}
+ "holds current text size (can be used in place of a number block)")}
#
# 'dead key' Unicode dictionaries
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index 8674fb3..4092536 100644
--- a/TurtleArt/talogo.py
+++ b/TurtleArt/talogo.py
@@ -36,9 +36,8 @@ try:
except ImportError:
pass
-from taconstants import TAB_LAYER, BLACK, WHITE, DEFAULT_SCALE, ICON_SIZE, \
- BLOCK_NAMES, CONSTANTS, PREFIX_DICTIONARY
-from tajail import myfunc, myfunc_import
+from taconstants import TAB_LAYER, DEFAULT_SCALE, BLOCK_NAMES, \
+ PREFIX_DICTIONARY, CONSTANTS, BLACK, WHITE
from tautils import get_pixbuf_from_journal, convert, data_from_file, \
text_media_type, round_int, chr_to_ord, strtype, get_path, debug_output
@@ -46,8 +45,7 @@ from util.RtfParser import RtfTextOnly
from gettext import gettext as _
-VALUE_BLOCKS = ['box1', 'box2', 'color', 'shade', 'gray', 'scale', 'pensize',
- 'heading', 'xcor', 'ycor', 'pop', 'time', 'keyboard', 'see']
+VALUE_BLOCKS = []
MEDIA_BLOCKS_DICTIONARY = {} # new media blocks get added here
PLUGIN_DICTIONARY = {} # new block primitives get added here
@@ -81,184 +79,6 @@ class logoerror(Exception):
# Utility functions
-
-def _num_type(x):
- """ Is x a number type? """
- if type(x) == int:
- return True
- if type(x) == float:
- return True
- if type(x) == ord:
- return True
- return False
-
-
-def _string_to_num(x):
- """ Try to comvert a string to a number """
- xx = convert(x.replace(self.tw.decimal_point, '.'), float)
- if type(xx) is float:
- return xx
- else:
- xx, xflag = chr_to_ord(x)
- if xflag:
- return xx
- else:
- raise logoerror("#syntaxerror")
-
-
-def _and(x, y):
- """ Logical and """
- return x & y
-
-
-def _or(x, y):
- """ Logical or """
- return x | y
-
-
-def _careful_divide(x, y):
- """ Raise error on divide by zero """
- try:
- return x / y
- except ZeroDivisionError:
- raise logoerror("#zerodivide")
- except TypeError:
- try:
- return _string_to_num(x) / _string_to_num(y)
- except ZeroDivisionError:
- raise logoerror("#zerodivide")
- except ValueError:
- raise logoerror("#syntaxerror")
- except TypeError:
- raise logoerror("#notanumber")
-
-
-def _equal(x, y):
- """ Numeric and logical equal """
- try:
- return float(x) == float(y)
- except TypeError:
- typex, typey = False, False
- if strtype(x):
- typex = True
- if strtype(y):
- typey = True
- if typex and typey:
- return x == y
- try:
- return _string_to_num(x) == _string_to_num(y)
- except ValueError:
- raise logoerror("#syntaxerror")
-
-
-def _less(x, y):
- """ Compare numbers and strings """
- try:
- return float(x) < float(y)
- except ValueError:
- typex, typey = False, False
- if strtype(x):
- typex = True
- if strtype(y):
- typey = True
- if typex and typey:
- return x < y
- try:
- return _string_to_num(x) < _string_to_num(y)
- except TypeError:
- raise logoerror("#notanumber")
-
-
-def _more(x, y):
- """ Compare numbers and strings """
- return _less(y, x)
-
-
-def _plus(x, y):
- """ Add numbers, concat strings """
- if _num_type(x) and _num_type(y):
- return(x + y)
- else:
- if _num_type(x):
- xx = str(round_int(x))
- else:
- xx = str(x)
- if _num_type(y):
- yy = str(round_int(y))
- else:
- yy = str(y)
- return(xx + yy)
-
-
-def _minus(x, y):
- """ Numerical subtraction """
- if _num_type(x) and _num_type(y):
- return(x - y)
- try:
- return _string_to_num(x) - _string_to_num(y)
- except TypeError:
- raise logoerror("#notanumber")
-
-
-def _product(x, y):
- """ Numerical multiplication """
- if _num_type(x) and _num_type(y):
- return(x * y)
- try:
- return _string_to_num(x) * _string_to_num(y)
- except TypeError:
- raise logoerror("#notanumber")
-
-
-def _mod(x, y):
- """ Numerical mod """
- if _num_type(x) and _num_type(y):
- return(x % y)
- try:
- return _string_to_num(x) % _string_to_num(y)
- except TypeError:
- raise logoerror("#notanumber")
- except ValueError:
- raise logoerror("#syntaxerror")
-
-
-def _sqrt(x):
- """ Square root """
- if _num_type(x):
- if x < 0:
- raise logoerror("#negroot")
- return sqrt(x)
- try:
- return sqrt(_string_to_num(x))
- except ValueError:
- raise logoerror("#negroot")
- except TypeError:
- raise logoerror("#notanumber")
-
-
-def _random(x, y):
- """ Random integer """
- if _num_type(x) and _num_type(y):
- return(int(round(uniform(x, y), 0)))
- xx, xflag = chr_to_ord(x)
- yy, yflag = chr_to_ord(y)
- if xflag and yflag:
- return chr(int(round(uniform(xx, yy), 0)))
- if not xflag:
- xx = _string_to_num(x)
- if not yflag:
- yy = _string_to_num(y)
- try:
- return(int(round(uniform(xx, yy), 0)))
- except TypeError:
- raise logoerror("#notanumber")
-
-
-def _identity(x):
- """ Identity function """
- return(x)
-
-
def _just_stop():
""" yield False to stop stack """
yield False
@@ -280,149 +100,17 @@ class LogoCode:
# TODO: remove plugin blocks
DEFPRIM = {
'(': [1, lambda self, x: self._prim_opar(x)],
- 'and': [2, lambda self, x, y: _and(x, y)],
- 'arc': [2, lambda self, x, y: self._prim_arc(self.tw.canvas.arc, x,
- y)],
- 'audio': [1, lambda self, x: self._play_sound(x)],
- 'back': [1, lambda self, x: self._prim_move(self.tw.canvas.forward,
- -x)],
- 'black': [0, lambda self: BLACK],
- 'blue': [0, lambda self: CONSTANTS['blue']],
- 'bpos': [0, lambda self: CONSTANTS['bottompos']],
- 'boty': [0, lambda self: CONSTANTS['bottomy']],
- 'box1': [0, lambda self: self.boxes['box1']],
- 'box': [1, lambda self, x: self._box(x)],
- 'box2': [0, lambda self: self.boxes['box2']],
'bullet': [1, self._prim_bullet, True],
'bulletlist': [1, self._prim_list, True],
- 'cartesian': [0, lambda self: self.tw.set_cartesian(True)],
- 'clean': [0, lambda self: self.prim_clear()],
- 'clearheap': [0, lambda self: self._empty_heap()],
- 'color': [0, lambda self: self.tw.canvas.color],
- 'gray': [0, lambda self: self.tw.canvas.gray],
- 'comment': [1, lambda self, x: self._prim_print(x, True)],
'container': [1, lambda self, x: x],
- 'cyan': [0, lambda self: CONSTANTS['cyan']],
'define': [2, self._prim_define],
- 'division': [2, lambda self, x, y: _careful_divide(x, y)],
- 'equal?': [2, lambda self, x, y: _equal(x, y)],
- 'fillscreen': [2, lambda self, x, y: self.tw.canvas.fillscreen(x, y)],
- 'forever': [1, self._prim_forever, True],
- 'forward': [1, lambda self, x: self._prim_move(self.tw.canvas.forward,
- x)],
- 'fullscreen': [0, lambda self: self.tw.set_fullscreen()],
- 'greater?': [2, lambda self, x, y: _more(x, y)],
- 'green': [0, lambda self: CONSTANTS['green']],
- 'heading': [0, lambda self: self.tw.canvas.heading],
- 'hideblocks': [0, lambda self: self.tw.hideblocks()],
- 'hres': [0, lambda self: CONSTANTS['width']],
- 'id': [1, lambda self, x: _identity(x)],
- 'if': [2, self._prim_if, True],
- 'ifelse': [3, self._prim_ifelse, True],
'insertimage': [1, lambda self, x: self._insert_image(False,
filepath=x)],
- 'kbinput': [0, lambda self: self._prim_kbinput()],
- 'keyboard': [0, lambda self: self.keyboard],
- 'left': [1, lambda self, x: self._prim_right(-x)],
- 'leftx': [0, lambda self: CONSTANTS['leftx']],
- 'lpos': [0, lambda self: CONSTANTS['leftpos']],
- 'less?': [2, lambda self, x, y: _less(x, y)],
- 'mediawait': [0, self._media_wait, True],
- 'minus': [2, lambda self, x, y: _minus(x, y)],
- 'mod': [2, lambda self, x, y: _mod(x, y)],
- 'myfunction': [2, lambda self, f, x: self._myfunction(f, [x])],
- 'myfunction2': [3, lambda self, f, x, y: self._myfunction(f, [x, y])],
- 'myfunction3': [4, lambda self, f, x, y, z: self._myfunction(
- f, [x, y, z])],
'nop': [0, lambda self: None],
- 'nop1': [0, lambda self: None],
- 'nop2': [0, lambda self: None],
- 'nop3': [1, lambda self, x: None],
- 'not': [1, lambda self, x: not x],
- 'orange': [0, lambda self: CONSTANTS['orange']],
- 'or': [2, lambda self, x, y: _or(x, y)],
- 'pendown': [0, lambda self: self.tw.canvas.setpen(True)],
- 'pensize': [0, lambda self: self.tw.canvas.pensize],
- 'penup': [0, lambda self: self.tw.canvas.setpen(False)],
- 'plus': [2, lambda self, x, y: _plus(x, y)],
- 'polar': [0, lambda self: self.tw.set_polar(True)],
- 'pop': [0, lambda self: self._prim_pop()],
- 'print': [1, lambda self, x: self._prim_print(x, False)],
- 'printheap': [0, lambda self: self._prim_print_heap()],
- 'product': [2, lambda self, x, y: _product(x, y)],
- 'purple': [0, lambda self: CONSTANTS['purple']],
- 'push': [1, lambda self, x: self._prim_push(x)],
- 'random': [2, lambda self, x, y: _random(x, y)],
- 'readpixel': [0, lambda self: self._read_pixel()],
- 'red': [0, lambda self: CONSTANTS['red']],
- 'repeat': [2, self._prim_repeat, True],
- 'right': [1, lambda self, x: self._prim_right(x)],
- 'rightx': [0, lambda self: CONSTANTS['rightx']],
- 'rpos': [0, lambda self: CONSTANTS['rightpos']],
- 'savepix': [1, lambda self, x: self._save_picture(x)],
- 'savesvg': [1, lambda self, x: self._save_svg(x)],
- 'scale': [0, lambda self: self.scale],
- 'see': [0, lambda self: self.see()],
- 'setcolor': [1, lambda self, x: self._prim_set('color',
- self.tw.canvas.setcolor, x)],
- 'setgray': [1, lambda self, x: self._prim_set('gray',
- self.tw.canvas.setgray, x)],
- 'seth': [1, lambda self, x: self._prim_set('heading',
- self.tw.canvas.seth, x)],
- 'setpensize': [1, lambda self, x: self._prim_set('pensize',
- self.tw.canvas.setpensize, x)],
- 'setscale': [1, lambda self, x: self._prim_set('scale',
- self._set_scale, x)],
- 'setshade': [1, lambda self, x: self._prim_set('shade',
- self.tw.canvas.setshade, x)],
'settextcolor': [1, lambda self, x: self.tw.canvas.settextcolor(x)],
'settextsize': [1, lambda self, x: self.tw.canvas.settextsize(x)],
- 'setxy2': [2, lambda self, x, y: self._prim_move(self.tw.canvas.setxy,
- x, y)],
- 'setxy': [2, lambda self, x, y: self._prim_move(self.tw.canvas.setxy,
- x, y, pendown=False)],
- 'shade': [0, lambda self: self.tw.canvas.shade],
- 'show': [1, lambda self, x: self._show(x, True)],
- 'showaligned': [1, lambda self, x: self._show(x, False)],
- 'showblocks': [0, lambda self: self.tw.showblocks()],
- 'skin': [1, lambda self, x: self._reskin(x)],
- 'sqrt': [1, lambda self, x: _sqrt(x)],
- 'stack1': [0, self._prim_stack1, True],
- 'stack': [1, self._prim_stack, True],
- 'stack2': [0, self._prim_stack2, True],
- 'start': [0, lambda self: self._prim_start()],
- 'startfill': [0, lambda self: self.tw.canvas.start_fill()],
- 'stopfill': [0, lambda self: self.tw.canvas.stop_fill()],
- 'stopstack': [0, lambda self: self._prim_stopstack()],
- 'storeinbox1': [1, lambda self, x: self._prim_setbox('box1', None, x)],
- 'storeinbox2': [1, lambda self, x: self._prim_setbox('box2', None, x)],
- 'storeinbox': [2, lambda self, x, y: self._prim_setbox('box3', x, y)],
- 't1x1': [2, lambda self, x, y: self._show_template1x1(x, y)],
- 't1x1a': [2, lambda self, x, y: self._show_template1x1a(x, y)],
- 't1x2': [3, lambda self, x, y, z: self._show_template1x2(x, y, z)],
- 't2x1': [3, lambda self, x, y, z: self._show_template2x1(x, y, z)],
- 't2x2': [5, lambda self, x, y, z, a, b: self._show_template2x2(
- x, y, z, a, b)],
'textcolor': [0, lambda self: self.tw.canvas.textcolor],
- 'textsize': [0, lambda self: self.tw.textsize],
- 'time': [0, lambda self: self._elapsed_time()],
- 'titlex': [0, lambda self: CONSTANTS['titlex']],
- 'titley': [0, lambda self: CONSTANTS['titley']],
- 'topy': [0, lambda self: CONSTANTS['topy']],
- 'tpos': [0, lambda self: CONSTANTS['toppos']],
- 'turtle': [1, lambda self, x: self.tw.canvas.set_turtle(x)],
- 'userdefined': [1, lambda self, x: self._prim_myblock([x])],
- 'userdefined2': [2, lambda self, x, y: self._prim_myblock([x, y])],
- 'userdefined3': [3, lambda self, x, y,
- z: self._prim_myblock([x, y, z])],
- 'video': [1, lambda self, x: self._play_video(x)],
- 'vres': [0, lambda self: CONSTANTS['height']],
- 'wait': [1, self._prim_wait, True],
- 'white': [0, lambda self: WHITE],
- 'write': [2, lambda self, x, y: self._write(self, x, y)],
- 'xcor': [0, lambda self: self.tw.canvas.xcor / self.tw.coord_scale],
- 'ycor': [0, lambda self: self.tw.canvas.ycor / self.tw.coord_scale],
- 'yellow': [0, lambda self: CONSTANTS['yellow']]}
+ 'textsize': [0, lambda self: self.tw.textsize]}
for p in iter(DEFPRIM):
if len(DEFPRIM[p]) == 2:
@@ -811,47 +499,6 @@ class LogoCode:
# Primitives
#
- def prim_clear(self):
- """ Clear screen """
- if self.tw.gst_available:
- from tagplay import stop_media
- stop_media(self)
- self.tw.canvas.clearscreen()
- self.scale = DEFAULT_SCALE
- # Note: users find this "feature" confusing
- # self.tw.set_polar(False)
- # self.tw.set_cartesian(False)
- self.hidden_turtle = None
- self._start_time = time()
- for name in VALUE_BLOCKS:
- self.update_label_value(name)
-
- def _prim_start(self):
- """ Start block: recenter """
- if self.tw.running_sugar:
- self.tw.activity.recenter()
-
- def _prim_wait(self, time):
- """ Show the turtle while we wait """
- self.tw.active_turtle.show()
- endtime = _millisecond() + time * 1000.
- while _millisecond() < endtime:
- yield True
- self.tw.active_turtle.hide()
- self._ireturn()
- yield True
-
- def _prim_repeat(self, num, blklist):
- """ Repeat list num times. """
- num = self._int(num)
- for i in range(num):
- self._icall(self._evline, blklist[:])
- yield True
- if self.procstop:
- break
- self._ireturn()
- yield True
-
def _prim_bullet(self, blklist):
""" Depreciated bullet-list block style """
self._show_bullets(blklist)
@@ -864,75 +511,6 @@ class LogoCode:
self._ireturn()
yield True
- def _myfunction(self, f, x):
- """ Programmable block """
- try:
- y = myfunc(f, x)
- if str(y) == 'nan':
- debug_output('Python function returned NAN',
- self.tw.running_sugar)
- self.stop_logo()
- raise logoerror("#notanumber")
- else:
- return y
- except ZeroDivisionError:
- self.stop_logo()
- raise logoerror("#zerodivide")
- except ValueError, e:
- self.stop_logo()
- raise logoerror('#' + str(e))
- except SyntaxError, e:
- self.stop_logo()
- raise logoerror('#' + str(e))
- except NameError, e:
- self.stop_logo()
- raise logoerror('#' + str(e))
- except OverflowError:
- self.stop_logo()
- raise logoerror("#overflowerror")
- except TypeError:
- self.stop_logo()
- raise logoerror("#notanumber")
-
- def _prim_forever(self, blklist):
- """ Do list forever """
- while True:
- self._icall(self._evline, blklist[:])
- yield True
- if self.procstop:
- break
- self._ireturn()
- yield True
-
- '''
- def _prim_while(self, list1, list2):
- list = [self._intern('if')]
- for i in list1:
- list.append(i)
- list.append(list2)
- while self._icall(self._evline, list[:]):
- yield True
- self._ireturn()
- yield True
- '''
-
- def _prim_if(self, boolean, blklist):
- """ If bool, do list """
- if boolean:
- self._icall(self._evline, blklist[:])
- yield True
- self._ireturn()
- yield True
-
- def _prim_ifelse(self, boolean, list1, list2):
- """ If bool, do list1, else do list2 """
- if boolean:
- self._ijmp(self._evline, list1[:])
- yield True
- else:
- self._ijmp(self._evline, list2[:])
- yield True
-
def _prim_opar(self, val):
self.iline.pop(0)
return val
@@ -978,14 +556,6 @@ class LogoCode:
self._ireturn()
yield True
- def _prim_stopstack(self):
- """ Stop execution of a stack """
- self.procstop = True
-
- def _prim_print_heap(self):
- """ Display contents of heap """
- self.tw.showlabel('status', str(self.heap) + ' ')
-
def _int(self, n):
""" Raise an error if n doesn't convert to int. """
if type(n) == int:
@@ -998,68 +568,6 @@ class LogoCode:
raise logoerror("%s %s %s %s" \
% (self.cfun.name, _("doesn't like"), str(n), _("as input")))
- def _box(self, x):
- """ Retrieve value from named box """
- if type(convert(x, float, False)) == float:
- if int(float(x)) == x:
- x = int(x)
- try:
- return self.boxes['box3' + str(x)]
- except KeyError:
- raise logoerror("#emptybox")
-
- def _prim_myblock(self, x):
- """ Run Python code imported from Journal """
- if self.bindex is not None and self.bindex in self.tw.myblock:
- try:
- if len(x) == 1:
- myfunc_import(self, self.tw.myblock[self.bindex], x[0])
- else:
- myfunc_import(self, self.tw.myblock[self.bindex], x)
- except:
- raise logoerror("#syntaxerror")
-
- def _prim_print(self, n, flag):
- """ Print object n """
- if flag and (self.tw.hide or self.tw.step_time == 0):
- return
- if type(n) == str or type(n) == unicode:
- if n[0:6] == 'media_' and \
- n[6:].lower not in MEDIA_BLOCKS_DICTIONARY:
- try:
- if self.tw.running_sugar:
- try:
- dsobject = datastore.get(n[6:])
- except:
- debug_output("Couldn't open %s" % (n[6:]),
- self.tw.running_sugar)
- self.tw.showlabel('status', dsobject.metadata['title'])
- dsobject.destroy()
- else:
- self.tw.showlabel('status', n[6:])
- except IOError:
- self.tw.showlabel('status', n)
- else:
- self.tw.showlabel('status', n)
- elif type(n) == int:
- self.tw.showlabel('status', n)
- else:
- self.tw.showlabel('status',
- str(round_int(n)).replace('.', self.tw.decimal_point))
-
- def _prim_kbinput(self):
- """ Query keyboard """
- if len(self.tw.keypress) == 1:
- self.keyboard = ord(self.tw.keypress[0])
- else:
- try:
- self.keyboard = {'Escape': 27, 'space': 32, ' ': 32,
- 'Return': 13, 'KP_Up': 2, 'KP_Down': 4,
- 'KP_Left': 1, 'KP_Right': 3}[self.tw.keypress]
- except KeyError:
- self.keyboard = 0
- self.update_label_value('keyboard', self.keyboard)
- self.tw.keypress = ''
def find_value_blocks(self):
""" Find any value blocks that may need label updates """
@@ -1087,69 +595,6 @@ class LogoCode:
block.spr.set_label(BLOCK_NAMES[name][0] + ' = ' + valstring)
block.resize()
- def _prim_set(self, name, cmd, value=None):
- """ Set a value and update the associated value blocks """
- if value is not None:
- cmd(value)
- self.update_label_value(name, value)
-
- def _prim_right(self, value):
- """ Turtle rotates clockwise """
- self.tw.canvas.right(float(value))
- self.update_label_value('heading', self.tw.canvas.heading)
-
- def _prim_move(self, cmd, value1, value2=None, pendown=True):
- """ Turtle moves by method specified in value1 """
- if value2 is None:
- cmd(value1)
- else:
- cmd(float(value1), float(value2), pendown=pendown)
- self.update_label_value('xcor',
- self.tw.canvas.xcor / self.tw.coord_scale)
- self.update_label_value('ycor',
- self.tw.canvas.ycor / self.tw.coord_scale)
- if len(self.value_blocks['see']) > 0:
- self.see()
-
- def _prim_arc(self, cmd, value1, value2):
- """ Turtle draws an arc of degree, radius """
- cmd(float(value1), float(value2))
- self.update_label_value('xcor',
- self.tw.canvas.xcor / self.tw.coord_scale)
- self.update_label_value('ycor',
- self.tw.canvas.ycor / self.tw.coord_scale)
- self.update_label_value('heading', self.tw.canvas.heading)
- if len(self.value_blocks['see']) > 0:
- self.see()
-
- def _prim_setbox(self, name, x, val):
- """ Define value of named box """
- if x is not None:
- if type(convert(x, float, False)) == float:
- if int(float(x)) == x:
- x = int(x)
- self.boxes[name + str(x)] = val
- return
-
- self.boxes[name] = val
- self.update_label_value(name, val)
-
- def _prim_push(self, val):
- """ Push value onto FILO """
- self.heap.append(val)
- self.update_label_value('pop', val)
-
- def _prim_pop(self):
- """ Pop value off of FILO """
- if len(self.heap) == 0:
- raise logoerror("#emptyheap")
- else:
- if len(self.heap) == 1:
- self.update_label_value('pop')
- else:
- self.update_label_value('pop', self.heap[-2])
- return self.heap.pop(-1)
-
def push_file_data_to_heap(self, dsobject):
""" push contents of a data store object (assuming json encoding) """
data = data_from_file(dsobject.file_path)
@@ -1158,19 +603,6 @@ class LogoCode:
self.heap.append(val)
self.update_label_value('pop', self.heap[-1])
- def _empty_heap(self):
- """ Empty FILO """
- self.heap = []
-
- def _save_picture(self, name):
- """ Save canvas to file as PNG """
- self.tw.save_as_image(name)
-
- def _save_svg(self, name):
- """ Save SVG to file """
- self.tw.canvas.svg_close()
- self.tw.save_as_image(name, True)
-
def _show_list(self, sarray):
""" Display list of media objects """
x = self.tw.canvas.xcor / self.tw.coord_scale
@@ -1180,47 +612,6 @@ class LogoCode:
self._show(s)
y -= int(self.tw.canvas.textsize * self.tw.lead)
- def _set_scale(self, x):
- """ Set scale used by media object display """
- self.scale = x
-
- def _reskin(self, media):
- """ Reskin the turtle with an image from a file """
- scale = int(ICON_SIZE * float(self.scale) / DEFAULT_SCALE)
- if scale < 1:
- return
- self.filepath = None
- dsobject = None
- if os.path.exists(media[6:]): # is it a path?
- self.filepath = media[6:]
- elif self.tw.running_sugar: # is it a datastore object?
- try:
- dsobject = datastore.get(media[6:])
- except:
- debug_output("Couldn't open skin %s" % (media[6:]),
- self.tw.running_sugar)
- if dsobject is not None:
- self.filepath = dsobject.file_path
- if self.filepath == None:
- self.tw.showlabel('nojournal', self.filepath)
- return
- pixbuf = None
- try:
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.filepath, scale,
- scale)
- except:
- self.tw.showlabel('nojournal', self.filepath)
- debug_output("Couldn't open skin %s" % (self.filepath),
- self.tw.running_sugar)
- if pixbuf is not None:
- self.tw.active_turtle.set_shapes([pixbuf])
- pen_state = self.tw.active_turtle.get_pen_state()
- if pen_state:
- self.tw.canvas.setpen(False)
- self.tw.canvas.forward(0)
- if pen_state:
- self.tw.canvas.setpen(True)
-
def _x(self):
""" Convert screen coordinates to turtle coordinates """
return int(self.tw.canvas.width / 2) + int(self.tw.canvas.xcor)
@@ -1237,73 +628,6 @@ class LogoCode:
""" Convert screen coordinates to turtle coordinates """
return int((self.tw.canvas.height * self.scale) / 100.)
- def _show(self, string, center=False):
- """ Show is the general-purpose media-rendering block. """
- if type(string) == str or type(string) == unicode:
- if string in ['media_', 'descr_', 'audio_', 'video_',
- 'media_None', 'descr_None', 'audio_None',
- 'video_None']:
- pass
- elif string[0:6] in ['media_', 'descr_', 'audio_', 'video_']:
- self.filepath = None
- self.dsobject = None
- print string[6:], MEDIA_BLOCKS_DICTIONARY
- if string[6:].lower() in MEDIA_BLOCKS_DICTIONARY:
- MEDIA_BLOCKS_DICTIONARY[string[6:].lower()]()
- elif os.path.exists(string[6:]): # is it a path?
- self.filepath = string[6:]
- elif self.tw.running_sugar: # is it a datastore object?
- try:
- self.dsobject = datastore.get(string[6:])
- except:
- debug_output("Couldn't find dsobject %s" % (
- string[6:]), self.tw.running_sugar)
- if self.dsobject is not None:
- self.filepath = self.dsobject.file_path
- if self.filepath == None:
- if self.dsobject is not None:
- self.tw.showlabel('nojournal',
- self.dsobject.metadata['title'])
- else:
- self.tw.showlabel('nojournal', string[6:])
- debug_output("Couldn't open %s" % (string[6:]),
- self.tw.running_sugar)
- elif string[0:6] == 'media_':
- self._insert_image(center)
- elif string[0:6] == 'descr_':
- mimetype = None
- if self.dsobject is not None and \
- 'mime_type' in self.dsobject.metadata:
- mimetype = self.dsobject.metadata['mime_type']
- description = None
- if self.dsobject is not None and \
- 'description' in self.dsobject.metadata:
- description = self.dsobject.metadata['description']
- self._insert_desc(mimetype, description)
- elif string[0:6] == 'audio_':
- self._play_sound()
- elif string[0:6] == 'video_':
- self._play_video()
- if self.dsobject is not None:
- self.dsobject.destroy()
- else: # assume it is text to display
- x, y = self._x(), self._y()
- if center:
- y -= self.tw.canvas.textsize
- self.tw.canvas.draw_text(string, x, y,
- int(self.tw.canvas.textsize * \
- self.scale / 100.),
- self.tw.canvas.width - x)
- elif type(string) == float or type(string) == int:
- string = round_int(string)
- x, y = self._x(), self._y()
- if center:
- y -= self.tw.canvas.textsize
- self.tw.canvas.draw_text(string, x, y,
- int(self.tw.canvas.textsize * \
- self.scale / 100.),
- self.tw.canvas.width - x)
-
def _insert_image(self, center=False, filepath=None):
""" Image only (at current x, y) """
if filepath is not None:
@@ -1393,213 +717,3 @@ class LogoCode:
from tagplay import play_movie_from_file
play_movie_from_file(self, self.filepath, self._x(), self._y(),
w, h)
-
- def _elapsed_time(self):
- """ Number of seconds since program execution has started or
- clean (prim_clear) block encountered """
- elapsed_time = int(time() - self._start_time)
- self.update_label_value('time', elapsed_time)
- return elapsed_time
-
- def see(self):
- """ Read r, g, b from the canvas and return a corresponding palette
- color """
- r, g, b, a = self.tw.canvas.get_pixel()
- color_index = self.tw.canvas.get_color_index(r, g, b)
- self.update_label_value('see', color_index)
- return color_index
-
- def _read_pixel(self):
- """ Read r, g, b, a from the canvas and push b, g, r to the stack """
- r, g, b, a = self.tw.canvas.get_pixel()
- self.heap.append(b)
- self.heap.append(g)
- self.heap.append(r)
- # Depreciated block methods
-
- def _show_template1x1(self, title, media):
- """ title, one image, and description """
- xo = self.tw.calc_position('t1x1')[2]
- x = -(self.tw.canvas.width / 2) + xo
- y = self.tw.canvas.height / 2
- self.tw.canvas.setxy(x, y, pendown=False)
- # save the text size so we can restore it later
- save_text_size = self.tw.canvas.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self._show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height * 2) \
- / self.tw.canvas.height
- self._set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render media object
- # leave some space below the title
- y -= int(self.title_height * 2 * self.tw.lead)
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media)
- if self.tw.running_sugar:
- x = 0
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media.replace('media_', 'descr_'))
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def _show_template2x1(self, title, media1, media2):
- """ title, two images (horizontal), two descriptions """
- xo = self.tw.calc_position('t2x1')[2]
- x = -(self.tw.canvas.width / 2) + xo
- y = self.tw.canvas.height / 2
- self.tw.canvas.setxy(x, y, pendown=False)
- # save the text size so we can restore it later
- save_text_size = self.tw.canvas.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self._show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \
- self.tw.canvas.height
- self._set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render four quadrents
- # leave some space below the title
- y -= int(self.title_height * 2 * self.tw.lead)
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media1)
- x = 0
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media2)
- y = -self.title_height
- if self.tw.running_sugar:
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media2.replace('media_', 'descr_'))
- x = -(self.tw.canvas.width / 2) + xo
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media1.replace('media_', 'descr_'))
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def _show_bullets(self, sarray):
- """ title and varible number of bullets """
- xo = self.tw.calc_position('bullet')[2]
- x = -(self.tw.canvas.width / 2) + xo
- y = self.tw.canvas.height / 2
- self.tw.canvas.setxy(x, y, pendown=False)
- # save the text size so we can restore it later
- save_text_size = self.tw.canvas.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self._show(sarray[0])
- # set body text size
- self.tw.canvas.settextsize(self.bullet_height)
- # leave some space below the title
- y -= int(self.title_height * 2 * self.tw.lead)
- for s in sarray[1:]:
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(s)
- y -= int(self.bullet_height * 2 * self.tw.lead)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def _show_template1x2(self, title, media1, media2):
- """ title, two images (vertical), two desciptions """
- xo = self.tw.calc_position('t1x2')[2]
- x = -(self.tw.canvas.width / 2) + xo
- y = self.tw.canvas.height / 2
- self.tw.canvas.setxy(x, y, pendown=False)
- # save the text size so we can restore it later
- save_text_size = self.tw.canvas.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self._show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \
- self.tw.canvas.height
- self._set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render four quadrents
- # leave some space below the title
- y -= int(self.title_height * 2 * self.tw.lead)
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media1)
- if self.tw.running_sugar:
- x = 0
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media1.replace('media_', 'descr_'))
- y = -self.title_height
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media2.replace('media_', 'descr_'))
- x = -(self.tw.canvas.width / 2) + xo
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media2)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def _show_template2x2(self, title, media1, media2, media3, media4):
- """ title and four images """
- xo = self.tw.calc_position('t2x2')[2]
- x = -(self.tw.canvas.width / 2) + xo
- y = self.tw.canvas.height / 2
- self.tw.canvas.setxy(x, y, pendown=False)
- # save the text size so we can restore it later
- save_text_size = self.tw.canvas.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self._show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \
- self.tw.canvas.height
- self._set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render four quadrents
- # leave some space below the title
- y -= int(self.title_height * 2 * self.tw.lead)
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media1)
- x = 0
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media2)
- y = -self.title_height
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media4)
- x = -(self.tw.canvas.width / 2) + xo
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media3)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def _show_template1x1a(self, title, media1):
- """ title, one media object """
- xo = self.tw.calc_position('t1x1a')[2]
- x = -(self.tw.canvas.width / 2) + xo
- y = self.tw.canvas.height / 2
- self.tw.canvas.setxy(x, y, pendown=False)
- # save the text size so we can restore it later
- save_text_size = self.tw.canvas.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self._show(title)
- # calculate and set scale for media blocks
- myscale = 90 * (self.tw.canvas.height - self.title_height * 2) / \
- self.tw.canvas.height
- self._set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render media object
- # leave some space below the title
- y -= int(self.title_height * 2 * self.tw.lead)
- self.tw.canvas.setxy(x, y, pendown=False)
- self._show(media1)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def _write(self, string, fsize):
- """ Write string at size """
- x = self.tw.canvas.width / 2 + int(self.tw.canvas.xcor)
- y = self.tw.canvas.height / 2 - int(self.tw.canvas.ycor)
- self.tw.canvas.draw_text(string, x, y - 15, int(fsize),
- self.tw.canvas.width)
diff --git a/TurtleArt/taprimitive.py b/TurtleArt/taprimitive.py
index 4be5172..75a1efd 100644
--- a/TurtleArt/taprimitive.py
+++ b/TurtleArt/taprimitive.py
@@ -21,7 +21,7 @@
from taconstants import BLOCK_STYLES, BLOCK_NAMES, HELP_STRINGS, PALETTES, \
PALETTE_NAMES, CONTENT_BLOCKS, PRIMITIVES, DEFAULTS, SPECIAL_NAMES, \
- COLORS
+ COLORS, EXPANDABLE_STYLE, EXPANDABLE_BLOCKS
from talogo import VALUE_BLOCKS
from tautils import debug_output
@@ -29,12 +29,13 @@ from tautils import debug_output
class Palette():
""" a class for defining new palettes """
- def __init__(self, name, colors=["#00FF00", "#00A000"]):
+ def __init__(self, name, colors=["#00FF00", "#00A000"], position=None):
self._name = name
+ self._special_name = name
self._colors = colors
self._help = None
- def add_palette(self):
+ def add_palette(self, position=None):
if self._name is None:
debug_output('You must specify a name for your palette')
return
@@ -44,12 +45,20 @@ class Palette():
i = PALETTE_NAMES.index('trash')
else:
i = len(PALETTE_NAMES)
- PALETTE_NAMES.insert(i, self._name)
- PALETTES.insert(i, [])
- COLORS.insert(i, self._colors)
+
+ if position is not None and type(position) is int and position < i:
+ i = position
+
+ if self._name not in PALETTE_NAMES:
+ PALETTE_NAMES.insert(i, self._name)
+ PALETTES.insert(i, [])
+ COLORS.insert(i, self._colors)
+ else:
+ # debug_output('Palette %s already defined' % (self._name))
+ return
# Special name entry is needed for help hover mechanism
- SPECIAL_NAMES[self._name] = self._name
+ SPECIAL_NAMES[self._name] = self._special_name
if self._help is not None:
HELP_STRINGS[self._name] = self._help
else:
@@ -58,6 +67,8 @@ class Palette():
def set_help(self, help):
self._help = help
+ def set_special_name(self, name):
+ self._special_name = name
class Primitive():
""" a class for defining new block primitives """
@@ -74,7 +85,7 @@ class Primitive():
self._value_block = False
self._content_block = False
- def add_prim(self):
+ def add_prim(self, position=None):
if self._name is None:
debug_output('You must specify a name for your block')
return
@@ -89,7 +100,14 @@ class Primitive():
BLOCK_NAMES[self._name] = self._label
if self._palette is not None:
- PALETTES[PALETTE_NAMES.index(self._palette)].append(self._name)
+ i = PALETTE_NAMES.index(self._palette)
+ if position is not None and type(position) is int and \
+ position < len(PALETTES[i]):
+ PALETTES[i].insert(position, self._name)
+ else:
+ PALETTES[i].append(self._name)
+ if position is not None:
+ debug_output('Ignoring position (%s)' % (str(position)))
if self._help is not None:
HELP_STRINGS[self._name] = self._help
@@ -111,6 +129,9 @@ class Primitive():
if self._special_name is not None:
SPECIAL_NAMES[self._name] = self._special_name
+ if self._style in EXPANDABLE_STYLE:
+ EXPANDABLE_BLOCKS.append(self._name)
+
def set_value_block(self, value=True):
self._value_block = value
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index 42a3a5d..e35b8f7 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -196,7 +196,6 @@ class TurtleArtWindow():
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
@@ -256,6 +255,9 @@ class TurtleArtWindow():
self._init_plugins()
self.lc = LogoCode(self)
+
+ from tabasics import Palettes
+ p = Palettes(self)
self._setup_plugins()
if self.interactive_mode:
@@ -713,7 +715,7 @@ class TurtleArtWindow():
self._layout_palette(n)
for blk in self.palettes[n]:
blk.spr.set_layer(TAB_LAYER)
- if n == self.trash_index:
+ if n == PALETTE_NAMES.index('trash'):
for blk in self.trash_stack:
for gblk in find_group(blk):
if gblk.status != 'collapsed':
@@ -721,6 +723,8 @@ class TurtleArtWindow():
def _hide_toolbar_palette(self):
""" Hide the toolbar palettes """
+ print self.activity.palette_buttons
+ print self.selected_palette
self._hide_previous_palette()
if self.activity is None or not self.activity.new_sugar_system:
# Hide the selectors
@@ -747,7 +751,7 @@ class TurtleArtWindow():
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:
+ if self.previous_palette == PALETTE_NAMES.index('trash'):
for blk in self.trash_stack:
for gblk in find_group(blk):
gblk.spr.hide()
@@ -813,7 +817,7 @@ class TurtleArtWindow():
_x, _y = 20, self.toolbar_offset + 5
_x, _y, _max = self._horizontal_layout(_x, _y,
self.palettes[n])
- if n == self.trash_index:
+ if n == PALETTE_NAMES.index('trash'):
_x, _y, _max = self._horizontal_layout(_x + _max, _y,
self.trash_stack)
_w = _x + _max + 25
@@ -1038,8 +1042,8 @@ class TurtleArtWindow():
if gblk.name in BLOCKS_WITH_SKIN:
self._resize_skin(gblk)
- # self.show_palette(self.trash_index)
- if self.selected_palette != self.trash_index:
+ # self.show_palette(PALETTE_NAMES.index('trash'))
+ if self.selected_palette != PALETTE_NAMES.index('trash'):
for gblk in group:
gblk.spr.hide()
@@ -1091,8 +1095,8 @@ class TurtleArtWindow():
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)):
+ if self.selected_palette == PALETTE_NAMES.index('trash') and \
+ self.palette_sprs[PALETTE_NAMES.index('trash')][self.orientation].hit((x, y)):
return True
"""
if self.selected_palette is not None and \
diff --git a/TurtleArtActivity.py b/TurtleArtActivity.py
index aa8d5bd..5087c53 100644
--- a/TurtleArtActivity.py
+++ b/TurtleArtActivity.py
@@ -71,6 +71,7 @@ class TurtleArtActivity(activity.Activity):
self._check_ver_change(datapath)
self._setup_canvas(canvas)
+ self._setup_palette_toolbar()
self._setup_sharing()
@@ -448,7 +449,7 @@ class TurtleArtActivity(activity.Activity):
if self.new_sugar_system:
# Use 0.86 toolbar design
# Create toolbox and secondary toolbars
- toolbox = ToolbarBox()
+ self._toolbox = ToolbarBox()
activity_toolbar_button = ActivityToolbarButton(self)
@@ -460,9 +461,9 @@ class TurtleArtActivity(activity.Activity):
view_toolbar_button = ToolbarButton(label=_('View'),
page=view_toolbar,
icon_name='toolbar-view')
- palette_toolbar = gtk.Toolbar()
- palette_toolbar_button = ToolbarButton(page=palette_toolbar,
- icon_name='palette')
+ self._palette_toolbar = gtk.Toolbar()
+ self._palette_toolbar_button = ToolbarButton(
+ page=self._palette_toolbar, icon_name='palette')
help_toolbar = gtk.Toolbar()
help_toolbar_button = ToolbarButton(label=_("Help"),
page=help_toolbar,
@@ -471,50 +472,51 @@ class TurtleArtActivity(activity.Activity):
journal_toolbar = gtk.Toolbar()
journal_toolbar_button = ToolbarButton(page=journal_toolbar,
icon_name='activity-journal')
+
# Add the toolbars and buttons to the toolbox
activity_toolbar_button.show()
- toolbox.toolbar.insert(activity_toolbar_button, -1)
+ self._toolbox.toolbar.insert(activity_toolbar_button, -1)
edit_toolbar_button.show()
- toolbox.toolbar.insert(edit_toolbar_button, -1)
+ self._toolbox.toolbar.insert(edit_toolbar_button, -1)
journal_toolbar_button.show()
- toolbox.toolbar.insert(journal_toolbar_button, -1)
+ self._toolbox.toolbar.insert(journal_toolbar_button, -1)
view_toolbar_button.show()
- toolbox.toolbar.insert(view_toolbar_button, -1)
- palette_toolbar_button.show()
- toolbox.toolbar.insert(palette_toolbar_button, -1)
+ self._toolbox.toolbar.insert(view_toolbar_button, -1)
+ self._palette_toolbar_button.show()
+ self._toolbox.toolbar.insert(self._palette_toolbar_button, -1)
help_toolbar_button.show()
- toolbox.toolbar.insert(help_toolbar_button, -1)
+ self._toolbox.toolbar.insert(help_toolbar_button, -1)
- self._add_separator(toolbox.toolbar)
+ self._add_separator(self._toolbox.toolbar)
- self._make_project_buttons(toolbox.toolbar)
+ self._make_project_buttons(self._toolbox.toolbar)
- self._add_separator(toolbox.toolbar, True)
+ self._add_separator(self._toolbox.toolbar, True)
stop_button = StopButton(self)
stop_button.props.accelerator = '<Ctrl>Q'
- toolbox.toolbar.insert(stop_button, -1)
+ self._toolbox.toolbar.insert(stop_button, -1)
stop_button.show()
else:
# Use pre-0.86 toolbar design
- toolbox = activity.ActivityToolbox(self)
- self.set_toolbox(toolbox)
+ self._toolbox = activity.ActivityToolbox(self)
+ self.set_toolbox(self._toolbox)
project_toolbar = gtk.Toolbar()
- toolbox.add_toolbar(_('Project'), project_toolbar)
+ self._toolbox.add_toolbar(_('Project'), project_toolbar)
view_toolbar = gtk.Toolbar()
- toolbox.add_toolbar(_('View'), view_toolbar)
+ self._toolbox.add_toolbar(_('View'), view_toolbar)
view_toolbar_button = view_toolbar
edit_toolbar = gtk.Toolbar()
- toolbox.add_toolbar(_('Edit'), edit_toolbar)
+ self._toolbox.add_toolbar(_('Edit'), edit_toolbar)
edit_toolbar_button = edit_toolbar
journal_toolbar = gtk.Toolbar()
- toolbox.add_toolbar(_('Import/Export'), journal_toolbar)
+ self._toolbox.add_toolbar(_('Import/Export'), journal_toolbar)
journal_toolbar_button = journal_toolbar
help_toolbar = gtk.Toolbar()
- toolbox.add_toolbar(_('Help'), help_toolbar)
+ self._toolbox.add_toolbar(_('Help'), help_toolbar)
help_toolbar_button = help_toolbar
self._make_palette_buttons(project_toolbar, palette_button=True)
@@ -575,6 +577,24 @@ class TurtleArtActivity(activity.Activity):
_("Move the cursor over the orange palette for help."),
help_toolbar, gtk.gdk.screen_width() - 2 * ICON_SIZE)
+ # Setup palette toolbar only AFTER initializing the plugins
+ # self._setup_palette_toolbar()
+
+ edit_toolbar.show()
+ view_toolbar.show()
+ help_toolbar.show()
+ self._toolbox.show()
+
+ if self.new_sugar_system:
+ # Hack as a workaround for #2050
+ edit_toolbar_button.set_expanded(True)
+ edit_toolbar_button.set_expanded(False)
+
+ self._palette_toolbar_button.set_expanded(True)
+ else:
+ self._toolbox.set_current_toolbar(1)
+
+ def _setup_palette_toolbar(self):
# The palette toolbar is only used with 0.86+
if self.new_sugar_system:
self.palette_buttons = []
@@ -585,27 +605,14 @@ class TurtleArtActivity(activity.Activity):
suffix = 'on'
self.palette_buttons.append(self._add_button(name + suffix,
HELP_STRINGS[name], self.do_palette_buttons_cb,
- palette_toolbar_button, None, i))
- self._add_separator(palette_toolbar, True)
-
- self._make_palette_buttons(palette_toolbar_button)
+ self._palette_toolbar_button, None, i))
+ self._add_separator(self._palette_toolbar, True)
- self.set_toolbar_box(toolbox)
- palette_toolbar.show()
+ self._make_palette_buttons(self._palette_toolbar_button)
- edit_toolbar.show()
- view_toolbar.show()
- help_toolbar.show()
- toolbox.show()
+ self.set_toolbar_box(self._toolbox)
+ self._palette_toolbar.show()
- if self.new_sugar_system:
- # Hack as a workaround for #2050
- edit_toolbar_button.set_expanded(True)
- edit_toolbar_button.set_expanded(False)
-
- palette_toolbar_button.set_expanded(True)
- else:
- toolbox.set_current_toolbar(1)
def _make_palette_buttons(self, toolbar, palette_button=False):
""" Creates the palette and block buttons for both toolbar types"""
diff --git a/plugins/turtle_blocks_plugin.py b/plugins/turtle_blocks_plugin.py
new file mode 100644
index 0000000..c7199f2
--- /dev/null
+++ b/plugins/turtle_blocks_plugin.py
@@ -0,0 +1,1202 @@
+# -*- coding: utf-8 -*-
+#Copyright (c) 2011, 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 time import time
+import os.path
+from gettext import gettext as _
+
+try:
+ from sugar.datastore import datastore
+except ImportError:
+ pass
+
+from plugin import Plugin
+from TurtleArt.taprimitive import Palette, Primitive
+from TurtleArt.talogo import PLUGIN_DICTIONARY, logoerror, \
+ MEDIA_BLOCKS_DICTIONARY
+from TurtleArt.taconstants import DEFAULT_SCALE, CONSTANTS, BLACK, WHITE, \
+ ICON_SIZE
+from TurtleArt.tautils import convert, round_int, debug_output
+from TurtleArt.tajail import myfunc, myfunc_import
+
+# TODO: add expandibles to taprimitives
+# fix position problem
+
+
+def _num_type(x):
+ """ Is x a number type? """
+ if type(x) == int:
+ return True
+ if type(x) == float:
+ return True
+ if type(x) == ord:
+ return True
+ return False
+
+
+def _string_to_num(x):
+ """ Try to comvert a string to a number """
+ xx = convert(x.replace(self.tw.decimal_point, '.'), float)
+ if type(xx) is float:
+ return xx
+ else:
+ xx, xflag = chr_to_ord(x)
+ if xflag:
+ return xx
+ else:
+ raise logoerror("#syntaxerror")
+
+
+def _millisecond():
+ """ Current time in milliseconds """
+ return time() * 1000
+
+
+class Turtle_blocks_plugin(Plugin):
+ """ a class for defining the extra palettes that distinguish Turtle Blocks
+ from Turtle Art """
+
+ def __init__(self, parent):
+ self.tw = parent
+
+ def setup(self):
+ # set up Turtle Block palettes
+ self._flow_palette()
+
+ p = Palette('media', ["#A0FF00", "#80A000"])
+ p.set_help(_('Palette of media objects'))
+ p.add_palette()
+ self._media_palette()
+
+ p = Palette('sensor', ["#FF6060", "#A06060"])
+ p.set_help(_('Palette of sensor blocks'))
+ p.add_palette()
+ self._sensor_palette()
+
+ p = Palette('extras', ["#FF0000", "#A00000"])
+ p.set_help(_('Palette of extra options'))
+ p.add_palette()
+ self._extras_palette()
+
+ p = Palette('portfolio', ["#0606FF", "#0606A0"])
+ p.set_help(_('Palette of presentation templates'))
+ p.add_palette()
+ self._portfolio_palette()
+
+ def start(self):
+ pass
+
+ def stop(self):
+ pass
+
+ def goto_background(self):
+ pass
+
+ def return_to_foreground(self):
+ pass
+
+ def quit(self):
+ pass
+
+ # Palette definitions
+
+ def _flow_palette(self):
+ b = Primitive('while') # macro
+ b.set_palette('flow')
+ b.set_style('flow-style-boolean')
+ b.set_label(_('while'))
+ b.set_help(_('do-while-True operator that uses boolean operators from Numbers palette'))
+ b.add_prim()
+
+ b = Primitive('until') # macro
+ b.set_palette('flow')
+ b.set_style('flow-style-boolean')
+ b.set_label(_('until'))
+ b.set_help(_('do-until-True operator that uses boolean operators from Numbers palette'))
+ b.add_prim()
+
+ def _media_palette(self):
+ b = Primitive('journal')
+ b.set_palette('media')
+ b.set_style('box-style-media')
+ b.set_label(' ')
+ b.set_special_name(_('journal'))
+ b.set_default(None)
+ b.set_help(_('Sugar Journal media object'))
+ b.add_prim()
+
+ b = Primitive('audio')
+ b.set_palette('media')
+ b.set_style('box-style-media')
+ b.set_label(' ')
+ b.set_special_name(_('audio'))
+ b.set_default(None)
+ b.set_help(_('Sugar Journal audio object'))
+ b.add_prim()
+
+ b = Primitive('video')
+ b.set_palette('media')
+ b.set_style('box-style-media')
+ b.set_label(' ')
+ b.set_special_name(_('video'))
+ b.set_default(None)
+ b.set_help(_('Sugar Journal video object'))
+ b.add_prim()
+
+ b = Primitive('description')
+ b.set_palette('media')
+ b.set_style('box-style-media')
+ b.set_label(' ')
+ b.set_special_name(_('description'))
+ b.set_default(None)
+ b.set_help(_('Sugar Journal description field'))
+ b.add_prim()
+
+ b = Primitive('string')
+ b.set_palette('media')
+ b.set_style('box-style')
+ b.set_label(_('text'))
+ b.set_default(_('text'))
+ b.set_special_name('')
+ b.set_help('string value')
+ b.add_prim()
+
+ b = Primitive('show')
+ b.set_palette('media')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('show'))
+ b.set_default(_('text'))
+ b.set_prim_name('show')
+ b.set_help(_('draws text or show media from the Journal'))
+ PLUGIN_DICTIONARY['show'] = self._prim_show
+ self.tw.lc._def_prim('show', 1,
+ lambda self, x: PLUGIN_DICTIONARY['show'](x, True))
+ b.add_prim()
+
+ b = Primitive('showaligned')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('show aligned'))
+ b.set_default(_('text'))
+ b.set_prim_name('showaligned')
+ b.set_help(_('draws text or show media from the Journal'))
+ self.tw.lc._def_prim('showaligned', 1,
+ lambda self, x: PLUGIN_DICTIONARY['show'](x, False))
+ b.add_prim()
+
+ b = Primitive('setscale')
+ b.set_palette('media')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('set scale'))
+ b.set_prim_name('setscale')
+ b.set_default(33)
+ b.set_help(_('sets the scale of media'))
+ PLUGIN_DICTIONARY['setscale'] = self._prim_setscale
+ self.tw.lc._def_prim('setscale', 1,
+ lambda self, x: PLUGIN_DICTIONARY['setscale'](x))
+
+ b.add_prim()
+
+ b = Primitive('savepix')
+ b.set_palette('media')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('save picture'))
+ b.set_prim_name('savepix')
+ b.set_default(_('picture name'))
+ b.set_help(_('saves a picture to the Sugar Journal'))
+ PLUGIN_DICTIONARY['savepix'] = self._prim_save_picture
+ self.tw.lc._def_prim('savepix', 1,
+ lambda self, x: PLUGIN_DICTIONARY['savepix'](x))
+ b.add_prim()
+
+ b = Primitive('savesvg')
+ b.set_palette('media')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('save SVG'))
+ b.set_prim_name('savesvg')
+ b.set_default(_('picture name'))
+ b.set_help(_('saves turtle graphics as an SVG file in the Sugar Journal'))
+ PLUGIN_DICTIONARY['savesvg'] = self._prim_save_svg
+ self.tw.lc._def_prim('savesvg', 1,
+ lambda self, x: PLUGIN_DICTIONARY['savesvg'](x))
+ b.add_prim()
+
+ b = Primitive('scale')
+ b.set_palette('media')
+ b.set_style('box-style')
+ b.set_label(_('scale'))
+ b.set_prim_name('scale')
+ b.set_value_block(True)
+ b.set_help(_('holds current scale value'))
+ self.tw.lc._def_prim('scale', 0, lambda self: self.tw.lc.scale)
+ b.add_prim()
+
+ b = Primitive('mediawait')
+ b.set_palette('media')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('media wait'))
+ b.set_prim_name('mediawait')
+ b.set_help(_('wait for current video or audio to complete'))
+ self.tw.lc._def_prim('mediawait', 0, self.tw.lc._media_wait, True)
+ b.add_prim()
+
+ def _sensor_palette(self):
+ b = Primitive('kbinput')
+ b.set_palette('sensor')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('query keyboard'))
+ b.set_prim_name('kbinput')
+ b.set_help(_('query for keyboard input (results stored in keyboard block)'))
+ PLUGIN_DICTIONARY['kbinput'] = self._prim_kbinput
+ self.tw.lc._def_prim('kbinput', 0,
+ lambda self: PLUGIN_DICTIONARY['kbinput']())
+ b.add_prim()
+
+ b = Primitive('keyboard')
+ b.set_palette('sensor')
+ b.set_style('box-style')
+ b.set_label(_('keyboard'))
+ b.set_prim_name('keyboard')
+ b.set_value_block(True)
+ b.set_help(_('holds results of query-keyboard block'))
+ self.tw.lc._def_prim('keyboard', 0, lambda self: self.tw.lc.keyboard)
+ b.add_prim()
+
+ b = Primitive('readpixel')
+ b.set_palette('sensor')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('read pixel'))
+ b.set_prim_name('readpixel')
+ b.set_help(_('RGB color under the turtle is pushed to the stack'))
+ PLUGIN_DICTIONARY['readpixel'] = self._prim_readpixel
+ self.tw.lc._def_prim('readpixel', 0,
+ lambda self: PLUGIN_DICTIONARY['readpixel']())
+ b.add_prim()
+
+ b = Primitive('see')
+ b.set_palette('sensor')
+ b.set_style('box-style')
+ b.set_label(_('turtle sees'))
+ b.set_prim_name('see')
+ b.set_help(_('returns the color that the turtle "sees"'))
+ b.set_value_block(True)
+ PLUGIN_DICTIONARY['see'] = self._prim_see
+ self.tw.lc._def_prim('see', 0,
+ lambda self: PLUGIN_DICTIONARY['see']())
+ b.add_prim()
+
+ b = Primitive('time')
+ b.set_palette('sensor')
+ b.set_style('box-style')
+ b.set_label(_('time'))
+ b.set_prim_name('time')
+ b.set_value_block(True)
+ b.set_help(_('elapsed time (in seconds) since program started'))
+ PLUGIN_DICTIONARY['time'] = self._prim_time
+ self.tw.lc._def_prim('time', 0,
+ lambda self: PLUGIN_DICTIONARY['time']())
+ b.add_prim()
+
+ def _extras_palette(self):
+ b = Primitive('push')
+ b.set_palette('extras')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('push'))
+ b.set_prim_name('push')
+ b.set_help(_('pushes value onto FILO (first-in last-out heap)'))
+ PLUGIN_DICTIONARY['push'] = self._prim_push
+ self.tw.lc._def_prim('push', 1,
+ lambda self, x: PLUGIN_DICTIONARY['push'](x))
+ b.add_prim()
+
+ b = Primitive('printheap')
+ b.set_palette('extras')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('show heap'))
+ b.set_prim_name('printheap')
+ b.set_help(_('shows values in FILO (first-in last-out heap)'))
+ PLUGIN_DICTIONARY['printheap'] = self._prim_printheap
+ self.tw.lc._def_prim('printheap', 0,
+ lambda self: PLUGIN_DICTIONARY['printheap']())
+ b.add_prim()
+
+ b = Primitive('clearheap')
+ b.set_palette('extras')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('empty heap'))
+ b.set_prim_name('clearheap')
+ b.set_help(_('emptys FILO (first-in-last-out heap)'))
+ PLUGIN_DICTIONARY['clearheap'] = self._prim_emptyheap
+ self.tw.lc._def_prim('clearheap', 0,
+ lambda self: PLUGIN_DICTIONARY['clearheap']())
+ b.add_prim()
+
+ b = Primitive('pop')
+ b.set_palette('extras')
+ b.set_style('box-style')
+ b.set_label(_('pop'))
+ b.set_prim_name('pop')
+ b.set_value_block(True)
+ b.set_help(_('pops value off FILO (first-in last-out heap)'))
+ PLUGIN_DICTIONARY['pop'] = self._prim_pop
+ self.tw.lc._def_prim('pop', 0,
+ lambda self: PLUGIN_DICTIONARY['pop']())
+ b.add_prim()
+
+ b = Primitive('comment')
+ b.set_palette('extras')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('comment'))
+ b.set_prim_name('comment')
+ b.set_default(_('comment'))
+ b.set_help(_('places a comment in your code'))
+ PLUGIN_DICTIONARY['print'] = self._prim_print
+ self.tw.lc._def_prim('comment', 1,
+ lambda self, x: PLUGIN_DICTIONARY['print'](x, True))
+ b.add_prim()
+
+ b = Primitive('print')
+ b.set_palette('extras')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('print'))
+ b.set_prim_name('print')
+ b.set_help(_('prints value in status block at bottom of the screen'))
+ self.tw.lc._def_prim('print', 1,
+ lambda self, x: PLUGIN_DICTIONARY['print'](x, False))
+ b.add_prim()
+
+ b = Primitive('myfunc1arg')
+ b.set_palette('extras')
+ b.set_style('number-style-var-arg')
+ b.set_label([_('Python'), 'f(x)', 'x'])
+ b.set_prim_name('myfunction')
+ b.set_default(['x', 100])
+ b.set_help(_('a programmable block: used to add advanced single-variable math equations, e.g., sin(x)'))
+ PLUGIN_DICTIONARY['myfunction'] = self._prim_myfunction
+ self.tw.lc._def_prim('myfunction', 2,
+ lambda self, f, x: PLUGIN_DICTIONARY['myfunction'](f, [x]))
+ b.add_prim()
+
+ b = Primitive('myfunc2arg')
+ b.set_style('number-style-var-arg')
+ b.set_label([_('Python'), 'f(x,y)', 'x'])
+ b.set_prim_name('myfunction2')
+ b.set_default(['x+y', 100, 100])
+ b.set_help(_('a programmable block: used to add advanced multi-variable math equations, e.g., sqrt(x*x+y*y)'))
+ self.tw.lc._def_prim('myfunction2', 3,
+ lambda self, f, x: PLUGIN_DICTIONARY['myfunction'](f, [x, y]))
+ b.add_prim()
+
+ b = Primitive('myfunc3arg')
+ b.set_style('number-style-var-arg')
+ b.set_label([_('Python'), 'f(x,y,z)', 'x'])
+ b.set_prim_name('myfunction3')
+ b.set_default(['x+y+z', 100, 100, 100])
+ b.set_help(_('a programmable block: used to add advanced multi-variable math equations, e.g., sin(x+y+z)'))
+ self.tw.lc._def_prim('myfunction3', 4,
+ lambda self, f, x, y, z: PLUGIN_DICTIONARY['myfunction'](
+ f, [x, y, z]))
+ b.add_prim()
+
+ b = Primitive('userdefined')
+ b.set_palette('extras')
+ b.set_style('basic-style-var-arg')
+ b.set_label(' ')
+ b.set_prim_name('userdefined')
+ b.set_special_name(_('Python block'))
+ b.set_default(100)
+ b.set_help(_('runs code found in the tamyblock.py module found in the Journal'))
+ PLUGIN_DICTIONARY['userdefined'] = self._prim_myblock
+ self.tw.lc._def_prim('userdefined', 1,
+ lambda self, x: PLUGIN_DICTIONARY['userdefined']([x]))
+ b.add_prim()
+
+ b = Primitive('userdefined2')
+ b.set_style('basic-style-var-arg')
+ b.set_label(' ')
+ b.set_prim_name('userdefined')
+ b.set_special_name(_('Python block'))
+ b.set_default([100, 100])
+ b.set_help(_('runs code found in the tamyblock.py module found in the Journal'))
+ self.tw.lc._def_prim('userdefined2', 2,
+ lambda self, x, y: PLUGIN_DICTIONARY['userdefined']([x, y]))
+ b.add_prim()
+
+ b = Primitive('userdefined3')
+ b.set_style('basic-style-var-arg')
+ b.set_label(' ')
+ b.set_prim_name('userdefined')
+ b.set_special_name(_('Python block'))
+ b.set_default([100, 100, 100])
+ b.set_help(_('runs code found in the tamyblock.py module found in the Journal'))
+ self.tw.lc._def_prim('userdefined3', 3,
+ lambda self, x, y, z: PLUGIN_DICTIONARY['userdefined']([x, y, z]))
+ b.add_prim()
+
+ b = Primitive('cartesian')
+ b.set_palette('extras')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('Cartesian'))
+ b.set_prim_name('cartesian')
+ b.set_help(_('displays Cartesian coordinates'))
+ self.tw.lc._def_prim('cartesian', 0,
+ lambda self: self.tw.set_cartesian(True))
+ b.add_prim()
+
+ b = Primitive('polar')
+ b.set_palette('extras')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('polar'))
+ b.set_prim_name('polar')
+ b.set_help(_('displays polar coordinates'))
+ self.tw.lc._def_prim('polar', 0,
+ lambda self: self.tw.set_polar(True))
+ b.add_prim()
+
+ b = Primitive('addturtle')
+ b.set_palette('extras')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('turtle'))
+ b.set_prim_name('turtle')
+ b.set_default(1)
+ b.set_help(_('chooses which turtle to command'))
+ self.tw.lc._def_prim('turtle', 1,
+ lambda self, x: self.tw.canvas.set_turtle(x))
+ b.add_prim()
+
+ b = Primitive('skin')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('turtle shell'))
+ b.set_prim_name('skin')
+ b.set_help(_("put a custom 'shell' on the turtle"))
+ PLUGIN_DICTIONARY['skin'] = self._prim_reskin
+ self.tw.lc._def_prim('skin', 1,
+ lambda self, x: PLUGIN_DICTIONARY['skin'](x))
+ b.add_prim()
+
+ b = Primitive('reskin') # macro
+ b.set_palette('extras')
+ b.set_style('basic-style-1arg')
+ b.set_label(_('turtle shell'))
+ b.set_help(_("put a custom 'shell' on the turtle"))
+ b.add_prim()
+
+ b = Primitive('sandwichtop_no_label')
+ b.set_palette('extras')
+ b.set_style('collapsible-top-no-label')
+ b.set_label([' ', ' '])
+ b.set_prim_name('nop')
+ b.set_help(_('top of a collapsed stack'))
+ b.add_prim()
+
+ b = Primitive('sandwichbottom')
+ b.set_palette('extras')
+ b.set_style('collapsible-bottom')
+ b.set_label([' ', ' '])
+ b.set_prim_name('nop')
+ b.set_help(_('bottom of a collapsed stack'))
+ b.add_prim()
+
+ b = Primitive('sandwichcollapsed')
+ b.set_style('invisible')
+ b.set_label(' ')
+ b.set_prim_name('nop')
+ b.set_help(_('bottom block in a collapsed stack: click to open'))
+ b.add_prim()
+
+ b = Primitive('sandwichtop') # depreciated
+ b.set_style('collapsible-top')
+ b.set_label(_('top of stack'))
+ b.set_default(_('label'))
+ b.set_prim_name('comment')
+ b.set_help(_('top of stack'))
+ b.add_prim()
+
+ b = Primitive('sandwichtop_no_arm') # depreciated
+ b.set_style('collapsible-top-no-arm')
+ b.set_label(_('top of a collapsible stack'))
+ b.set_default(_('label'))
+ b.set_prim_name('comment')
+ b.set_help(_('top of stack'))
+ b.add_prim()
+
+ b = Primitive('sandwichtop_no_arm_no_label') # depreciated
+ b.set_style('collapsible-top-no-arm-no-label')
+ b.set_label([' ', _('click to open')])
+ b.set_prim_name('nop')
+ b.set_help(_('top of stack'))
+ b.add_prim()
+
+ def _portfolio_palette(self):
+ b = Primitive('hideblocks')
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('hide blocks'))
+ b.set_prim_name('hideblocks')
+ b.set_help(_('declutters canvas by hiding blocks'))
+ self.tw.lc._def_prim('hideblocks', 0, lambda self: self.tw.hideblocks())
+ b.add_prim()
+
+ b = Primitive('showblocks')
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('show blocks'))
+ b.set_prim_name('showblocks')
+ b.set_help(_('restores hidden blocks'))
+ self.tw.lc._def_prim('showblocks', 0, lambda self: self.tw.showblocks())
+ b.add_prim()
+
+ b = Primitive('fullscreen')
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended-vertical')
+ b.set_label(_('full screen'))
+ b.set_prim_name('fullscreen')
+ b.set_help(_('hides the Sugar toolbars'))
+ self.tw.lc._def_prim('fullscreen', 0,
+ lambda self: self.tw.set_fullscreen())
+ b.add_prim()
+
+ b = Primitive('picturelist') # macro
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended')
+ b.set_label(' ')
+ b.set_help(_('presentation template: list of bullets'))
+ b.add_prim()
+
+ b = Primitive('picture1x1a') # macro
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended')
+ b.set_label(' ')
+ b.set_help(_('presentation template: select Journal object (no description)'))
+ b.add_prim()
+
+ b = Primitive('picture1x1') # macro
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended')
+ b.set_label(' ')
+ b.set_help(_('presentation template: select Journal object (with description)'))
+ b.add_prim()
+
+ b = Primitive('picture2x2') # macro
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended')
+ b.set_label(' ')
+ b.set_help(_('presentation template: select four Journal objects'))
+ b.add_prim()
+
+ b = Primitive('picture2x1') # macro
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended')
+ b.set_label(' ')
+ b.set_help(_('presentation template: select two Journal objects'))
+ b.add_prim()
+
+ b = Primitive('picture1x2') # macro
+ b.set_palette('portfolio')
+ b.set_style('basic-style-extended')
+ b.set_label(' ')
+ b.set_help(_('presentation template: select two Journal objects'))
+ b.add_prim()
+
+ b = Primitive('leftpos')
+ b.set_palette('portfolio')
+ b.set_style('box-style')
+ b.set_label(_('left'))
+ b.set_prim_name('lpos')
+ b.set_help(_('xcor of left of screen'))
+ self.tw.lc._def_prim('lpos', 0, lambda self: CONSTANTS['leftpos'])
+ b.add_prim()
+
+ b = Primitive('bottompos')
+ b.set_palette('portfolio')
+ b.set_style('box-style')
+ b.set_label(_('bottom'))
+ b.set_prim_name('bpos')
+ b.set_help(_('ycor of bottom of screen'))
+ self.tw.lc._def_prim('bpos', 0, lambda self: CONSTANTS['bottompos'])
+ b.add_prim()
+
+ b = Primitive('width')
+ b.set_palette('portfolio')
+ b.set_style('box-style')
+ b.set_label(_('width'))
+ b.set_prim_name('hres')
+ b.set_help(_('the canvas width'))
+ self.tw.lc._def_prim('hres', 0, lambda self: CONSTANTS['width'])
+ b.add_prim()
+
+ b = Primitive('rightpos')
+ b.set_palette('portfolio')
+ b.set_style('box-style')
+ b.set_label(_('right'))
+ b.set_prim_name('rpos')
+ b.set_help(_('xcor of right of screen'))
+ self.tw.lc._def_prim('rpos', 0, lambda self: CONSTANTS['rightpos'])
+ b.add_prim()
+
+ b = Primitive('toppos')
+ b.set_palette('portfolio')
+ b.set_style('box-style')
+ b.set_label(_('top'))
+ b.set_prim_name('tpos')
+ b.set_help(_('ycor of top of screen'))
+ self.tw.lc._def_prim('tpos', 0, lambda self: CONSTANTS['toppos'])
+ b.add_prim()
+
+ b = Primitive('height')
+ b.set_palette('portfolio')
+ b.set_style('box-style')
+ b.set_label(_('height'))
+ b.set_prim_name('vres')
+ b.set_help(_('the canvas height'))
+ self.tw.lc._def_prim('vres', 0, lambda self: CONSTANTS['height'])
+ b.add_prim()
+
+ b = Primitive('titlex')
+ b.set_style('box-style')
+ b.set_label(_('title x'))
+ b.set_prim_name('titlex')
+ self.tw.lc._def_prim('titlex', 0, lambda self: CONSTANTS['titlex'])
+ b.add_prim()
+
+ b = Primitive('titley')
+ b.set_style('box-style')
+ b.set_label(_('title y'))
+ b.set_prim_name('titley')
+ self.tw.lc._def_prim('titley', 0, lambda self: CONSTANTS['titley'])
+ b.add_prim()
+
+ b = Primitive('leftx')
+ b.set_style('box-style')
+ b.set_label(_('left x'))
+ b.set_prim_name('leftx')
+ self.tw.lc._def_prim('leftx', 0, lambda self: CONSTANTS['leftx'])
+ b.add_prim()
+
+ b = Primitive('topy')
+ b.set_style('box-style')
+ b.set_label(_('top y'))
+ b.set_prim_name('topy')
+ self.tw.lc._def_prim('topy', 0, lambda self: CONSTANTS['topy'])
+ b.add_prim()
+
+ b = Primitive('rightx')
+ b.set_style('box-style')
+ b.set_label(_('right x'))
+ b.set_prim_name('rightx')
+ self.tw.lc._def_prim('rightx', 0, lambda self: CONSTANTS['rightx'])
+ b.add_prim()
+
+ b = Primitive('bottomy')
+ b.set_style('box-style')
+ b.set_label(_('bottom y'))
+ b.set_prim_name('bottomy')
+ self.tw.lc._def_prim('bottomy', 0, lambda self: CONSTANTS['bottomy'])
+ b.add_prim()
+
+ # Block primitives
+
+ def _prim_emptyheap(self):
+ """ Empty FILO """
+ self.tw.lc.heap = []
+
+ def _prim_kbinput(self):
+ """ Query keyboard """
+ if len(self.tw.keypress) == 1:
+ self.tw.lc.keyboard = ord(self.tw.keypress[0])
+ else:
+ try:
+ self.tw.lc.keyboard = {'Escape': 27, 'space': 32, ' ': 32,
+ 'Return': 13, 'KP_Up': 2, 'KP_Down': 4, 'KP_Left': 1,
+ 'KP_Right': 3}[self.tw.keypress]
+ except KeyError:
+ self.tw.lc.keyboard = 0
+ self.tw.lc.update_label_value('keyboard', self.tw.lc.keyboard)
+ self.tw.keypress = ''
+
+ def _prim_myblock(self, x):
+ """ Run Python code imported from Journal """
+ if self.tw.lc.bindex is not None and \
+ self.tw.lc.bindex in self.tw.myblock:
+ try:
+ if len(x) == 1:
+ myfunc_import(self, self.tw.myblock[self.tw.lc.bindex],
+ x[0])
+ else:
+ myfunc_import(self, self.tw.myblock[self.tw.lc.bindex], x)
+ except:
+ raise logoerror("#syntaxerror")
+
+ def _prim_myfunction(self, f, x):
+ """ Programmable block """
+ try:
+ y = myfunc(f, x)
+ if str(y) == 'nan':
+ debug_output('Python function returned NAN',
+ self.tw.running_sugar)
+ self.tw.lc.stop_logo()
+ raise logoerror("#notanumber")
+ else:
+ return y
+ except ZeroDivisionError:
+ self.tw.lc.stop_logo()
+ raise logoerror("#zerodivide")
+ except ValueError, e:
+ self.tw.lc.stop_logo()
+ raise logoerror('#' + str(e))
+ except SyntaxError, e:
+ self.tw.lc.stop_logo()
+ raise logoerror('#' + str(e))
+ except NameError, e:
+ self.tw.lc.stop_logo()
+ raise logoerror('#' + str(e))
+ except OverflowError:
+ self.tw.lc.stop_logo()
+ raise logoerror("#overflowerror")
+ except TypeError:
+ self.tw.lc.stop_logo()
+ raise logoerror("#notanumber")
+
+ def _prim_pop(self):
+ """ Pop value off of FILO """
+ if len(self.tw.lc.heap) == 0:
+ raise logoerror("#emptyheap")
+ else:
+ if len(self.tw.lc.heap) == 1:
+ self.tw.lc.update_label_value('pop')
+ else:
+ self.tw.lc.update_label_value('pop', self.tw.lc.heap[-2])
+ return self.tw.lc.heap.pop(-1)
+
+ def _prim_print(self, n, flag):
+ """ Print object n """
+ if flag and (self.tw.hide or self.tw.step_time == 0):
+ return
+ if type(n) == str or type(n) == unicode:
+ if n[0:6] == 'media_' and \
+ n[6:].lower not in MEDIA_BLOCKS_DICTIONARY:
+ try:
+ if self.tw.running_sugar:
+ try:
+ dsobject = datastore.get(n[6:])
+ except:
+ debug_output("Couldn't open %s" % (n[6:]),
+ self.tw.running_sugar)
+ self.tw.showlabel('status', dsobject.metadata['title'])
+ dsobject.destroy()
+ else:
+ self.tw.showlabel('status', n[6:])
+ except IOError:
+ self.tw.showlabel('status', n)
+ else:
+ self.tw.showlabel('status', n)
+ elif type(n) == int:
+ self.tw.showlabel('status', n)
+ else:
+ self.tw.showlabel('status',
+ str(round_int(n)).replace('.', self.tw.decimal_point))
+
+ def _prim_printheap(self):
+ """ Display contents of heap """
+ self.tw.showlabel('status', str(self.tw.lc.heap) + ' ')
+
+ def _prim_push(self, val):
+ """ Push value onto FILO """
+ self.tw.lc.heap.append(val)
+ self.tw.lc.update_label_value('pop', val)
+
+ def _prim_readpixel(self):
+ """ Read r, g, b, a from the canvas and push b, g, r to the stack """
+ r, g, b, a = self.tw.canvas.get_pixel()
+ self.tw.lc.heap.append(b)
+ self.tw.lc.heap.append(g)
+ self.tw.lc.heap.append(r)
+
+ def _prim_reskin(self, media):
+ """ Reskin the turtle with an image from a file """
+ scale = int(ICON_SIZE * float(self.tw.lc.scale) / DEFAULT_SCALE)
+ if scale < 1:
+ return
+ self.tw.lc.filepath = None
+ dsobject = None
+ if os.path.exists(media[6:]): # is it a path?
+ self.tw.lc.filepath = media[6:]
+ elif self.tw.running_sugar: # is it a datastore object?
+ try:
+ dsobject = datastore.get(media[6:])
+ except:
+ debug_output("Couldn't open skin %s" % (media[6:]),
+ self.tw.running_sugar)
+ if dsobject is not None:
+ self.tw.lc.filepath = dsobject.file_path
+ if self.tw.lc.filepath == None:
+ self.tw.showlabel('nojournal', self.tw.lc.filepath)
+ return
+ pixbuf = None
+ try:
+ print self.tw.lc.filepath, scale, scale
+ pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.tw.lc.filepath,
+ scale, scale)
+ except:
+ self.tw.showlabel('nojournal', self.tw.lc.filepath)
+ debug_output("Couldn't open skin %s" % (self.tw.lc.filepath),
+ self.tw.running_sugar)
+ if pixbuf is not None:
+ self.tw.active_turtle.set_shapes([pixbuf])
+ pen_state = self.tw.active_turtle.get_pen_state()
+ if pen_state:
+ self.tw.canvas.setpen(False)
+ self.tw.canvas.forward(0)
+ if pen_state:
+ self.tw.canvas.setpen(True)
+
+ def _prim_save_picture(self, name):
+ """ Save canvas to file as PNG """
+ self.tw.save_as_image(name)
+
+ def _prim_save_svg(self, name):
+ """ Save SVG to file """
+ self.tw.canvas.svg_close()
+ self.tw.save_as_image(name, True)
+
+ def _prim_see(self):
+ """ Read r, g, b from the canvas and return a corresponding palette
+ color """
+ r, g, b, a = self.tw.canvas.get_pixel()
+ color_index = self.tw.canvas.get_color_index(r, g, b)
+ self.tw.lc.update_label_value('see', color_index)
+ return color_index
+
+ def _prim_setscale(self, scale):
+ """ Set the scale used by the show block """
+ self.tw.lc.scale = scale
+ self.tw.lc.update_label_value('scale', scale)
+
+ def _prim_show(self, string, center=False):
+ """ Show is the general-purpose media-rendering block. """
+ if type(string) == str or type(string) == unicode:
+ if string in ['media_', 'descr_', 'audio_', 'video_',
+ 'media_None', 'descr_None', 'audio_None',
+ 'video_None']:
+ pass
+ elif string[0:6] in ['media_', 'descr_', 'audio_', 'video_']:
+ self.tw.lc.filepath = None
+ self.tw.lc.dsobject = None
+ print string[6:], MEDIA_BLOCKS_DICTIONARY
+ if string[6:].lower() in MEDIA_BLOCKS_DICTIONARY:
+ MEDIA_BLOCKS_DICTIONARY[string[6:].lower()]()
+ elif os.path.exists(string[6:]): # is it a path?
+ self.tw.lc.filepath = string[6:]
+ elif self.tw.running_sugar: # is it a datastore object?
+ try:
+ self.tw.lc.dsobject = datastore.get(string[6:])
+ except:
+ debug_output("Couldn't find dsobject %s" % (
+ string[6:]), self.tw.running_sugar)
+ if self.tw.lc.dsobject is not None:
+ self.tw.lc.filepath = self.tw.lc.dsobject.file_path
+ if self.tw.lc.filepath == None:
+ if self.tw.lc.dsobject is not None:
+ self.tw.showlabel('nojournal',
+ self.tw.lc.dsobject.metadata['title'])
+ else:
+ self.tw.showlabel('nojournal', string[6:])
+ debug_output("Couldn't open %s" % (string[6:]),
+ self.tw.running_sugar)
+ elif string[0:6] == 'media_':
+ self.tw.lc._insert_image(center)
+ elif string[0:6] == 'descr_':
+ mimetype = None
+ if self.tw.lc.dsobject is not None and \
+ 'mime_type' in self.tw.lc.dsobject.metadata:
+ mimetype = self.tw.lc.dsobject.metadata['mime_type']
+ description = None
+ if self.tw.lc.dsobject is not None and \
+ 'description' in self.tw.lc.dsobject.metadata:
+ description = self.tw.lc.dsobject.metadata['description']
+ self.tw.lc._insert_desc(mimetype, description)
+ elif string[0:6] == 'audio_':
+ self.tw.lc._play_sound()
+ elif string[0:6] == 'video_':
+ self.tw.lc._play_video()
+ if self.tw.lc.dsobject is not None:
+ self.tw.lc.dsobject.destroy()
+ else: # assume it is text to display
+ x, y = self.tw.lc._x(), self.tw.lc._y()
+ if center:
+ y -= self.tw.canvas.textsize
+ self.tw.canvas.draw_text(string, x, y,
+ int(self.tw.canvas.textsize * \
+ self.tw.lc.scale / 100.),
+ self.tw.canvas.width - x)
+ elif type(string) == float or type(string) == int:
+ string = round_int(string)
+ x, y = self.tw.lc._x(), self.tw.lc._y()
+ if center:
+ y -= self.tw.canvas.textsize
+ self.tw.canvas.draw_text(string, x, y,
+ int(self.tw.canvas.textsize * \
+ self.tw.lc.scale / 100.),
+ self.tw.canvas.width - x)
+
+ def _prim_time(self):
+ """ Number of seconds since program execution has started or
+ clean (prim_clear) block encountered """
+ elapsed_time = int(time() - self.tw.lc._start_time)
+ self.tw.lc.update_label_value('time', elapsed_time)
+ return elapsed_time
+
+ # Depreciated blocks
+
+ """
+PORTFOLIO_STYLE_2x2 = ['template2x2']
+PORTFOLIO_STYLE_1x1 = ['template1x1', 'template1x1a']
+PORTFOLIO_STYLE_2x1 = ['template2x1']
+PORTFOLIO_STYLE_1x2 = ['template1x2']
+ 'template1x1': [' '],
+ 'template1x1a': [' '],
+ 'template1x2': [' '],
+ 'template2x1': [' '],
+ 'template2x2': [' '],
+ 'templatelist': [' '],
+ 'template1x1': 't1x1',
+ 'template1x1a': 't1x1a',
+ 'template1x2': 't1x2',
+ 'template2x1': 't2x1',
+ 'template2x2': 't2x2',
+ 'templatelist': 'bullet',
+
+ 't1x1': [2, lambda self, x, y: self._show_template1x1(x, y)],
+ 't1x1a': [2, lambda self, x, y: self._show_template1x1a(x, y)],
+ 't1x2': [3, lambda self, x, y, z: self._show_template1x2(x, y, z)],
+ 't2x1': [3, lambda self, x, y, z: self._show_template2x1(x, y, z)],
+ 't2x2': [5, lambda self, x, y, z, a, b: self._show_template2x2(
+ x, y, z, a, b)],
+ 'write': [2, lambda self, x, y: self._write(self, x, y)]
+ 'template1x1': [_('Title'), 'None'],
+ 'template1x1a': [_('Title'), 'None'],
+ 'template1x2': [_('Title'), 'None', 'None'],
+ 'template2x1': [_('Title'), 'None', 'None'],
+ 'template2x2': [_('Title'), 'None', 'None', 'None', 'None'],
+ 'templatelist': [_('Title'), '∙ '],
+ 'write': [_('text'), 32]}
+
+ 'template1x1a': _('presentation 1x1'),
+ 'template1x2': _('presentation 1x2'),
+ 'template2x1': _('presentation 2x1'),
+ 'template2x2': _('presentation 2x2'),
+ 'templatelist': _('presentation bulleted list'),
+ '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"),
+ """
+
+ def _show_template1x1(self, title, media):
+ """ title, one image, and description """
+ xo = self.tw.calc_position('t1x1')[2]
+ x = -(self.tw.canvas.width / 2) + xo
+ y = self.tw.canvas.height / 2
+ self.tw.canvas.setxy(x, y, pendown=False)
+ # save the text size so we can restore it later
+ save_text_size = self.tw.canvas.textsize
+ # set title text
+ self.tw.canvas.settextsize(self.title_height)
+ self._prim_show(title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (self.tw.canvas.height - self.title_height * 2) \
+ / self.tw.canvas.height
+ self._prim_setscale(myscale)
+ # set body text size
+ self.tw.canvas.settextsize(self.body_height)
+ # render media object
+ # leave some space below the title
+ y -= int(self.title_height * 2 * self.tw.lead)
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media)
+ if self.tw.running_sugar:
+ x = 0
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media.replace('media_', 'descr_'))
+ # restore text size
+ self.tw.canvas.settextsize(save_text_size)
+
+ def _show_template2x1(self, title, media1, media2):
+ """ title, two images (horizontal), two descriptions """
+ xo = self.tw.calc_position('t2x1')[2]
+ x = -(self.tw.canvas.width / 2) + xo
+ y = self.tw.canvas.height / 2
+ self.tw.canvas.setxy(x, y, pendown=False)
+ # save the text size so we can restore it later
+ save_text_size = self.tw.canvas.textsize
+ # set title text
+ self.tw.canvas.settextsize(self.title_height)
+ self._prim_show(title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \
+ self.tw.canvas.height
+ self._prim_setscale(myscale)
+ # set body text size
+ self.tw.canvas.settextsize(self.body_height)
+ # render four quadrents
+ # leave some space below the title
+ y -= int(self.title_height * 2 * self.tw.lead)
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media1)
+ x = 0
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media2)
+ y = -self.title_height
+ if self.tw.running_sugar:
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media2.replace('media_', 'descr_'))
+ x = -(self.tw.canvas.width / 2) + xo
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media1.replace('media_', 'descr_'))
+ # restore text size
+ self.tw.canvas.settextsize(save_text_size)
+
+ def _show_bullets(self, sarray):
+ """ title and varible number of bullets """
+ xo = self.tw.calc_position('bullet')[2]
+ x = -(self.tw.canvas.width / 2) + xo
+ y = self.tw.canvas.height / 2
+ self.tw.canvas.setxy(x, y, pendown=False)
+ # save the text size so we can restore it later
+ save_text_size = self.tw.canvas.textsize
+ # set title text
+ self.tw.canvas.settextsize(self.title_height)
+ self._prim_show(sarray[0])
+ # set body text size
+ self.tw.canvas.settextsize(self.bullet_height)
+ # leave some space below the title
+ y -= int(self.title_height * 2 * self.tw.lead)
+ for s in sarray[1:]:
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(s)
+ y -= int(self.bullet_height * 2 * self.tw.lead)
+ # restore text size
+ self.tw.canvas.settextsize(save_text_size)
+
+ def _show_template1x2(self, title, media1, media2):
+ """ title, two images (vertical), two desciptions """
+ xo = self.tw.calc_position('t1x2')[2]
+ x = -(self.tw.canvas.width / 2) + xo
+ y = self.tw.canvas.height / 2
+ self.tw.canvas.setxy(x, y, pendown=False)
+ # save the text size so we can restore it later
+ save_text_size = self.tw.canvas.textsize
+ # set title text
+ self.tw.canvas.settextsize(self.title_height)
+ self._prim_show(title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \
+ self.tw.canvas.height
+ self._prim_setscale(myscale)
+ # set body text size
+ self.tw.canvas.settextsize(self.body_height)
+ # render four quadrents
+ # leave some space below the title
+ y -= int(self.title_height * 2 * self.tw.lead)
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media1)
+ if self.tw.running_sugar:
+ x = 0
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media1.replace('media_', 'descr_'))
+ y = -self.title_height
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media2.replace('media_', 'descr_'))
+ x = -(self.tw.canvas.width / 2) + xo
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media2)
+ # restore text size
+ self.tw.canvas.settextsize(save_text_size)
+
+ def _show_template2x2(self, title, media1, media2, media3, media4):
+ """ title and four images """
+ xo = self.tw.calc_position('t2x2')[2]
+ x = -(self.tw.canvas.width / 2) + xo
+ y = self.tw.canvas.height / 2
+ self.tw.canvas.setxy(x, y, pendown=False)
+ # save the text size so we can restore it later
+ save_text_size = self.tw.canvas.textsize
+ # set title text
+ self.tw.canvas.settextsize(self.title_height)
+ self._prim_show(title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (self.tw.canvas.height - self.title_height * 2) / \
+ self.tw.canvas.height
+ self._prim_setscale(myscale)
+ # set body text size
+ self.tw.canvas.settextsize(self.body_height)
+ # render four quadrents
+ # leave some space below the title
+ y -= int(self.title_height * 2 * self.tw.lead)
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media1)
+ x = 0
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media2)
+ y = -self.title_height
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media4)
+ x = -(self.tw.canvas.width / 2) + xo
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media3)
+ # restore text size
+ self.tw.canvas.settextsize(save_text_size)
+
+ def _show_template1x1a(self, title, media1):
+ """ title, one media object """
+ xo = self.tw.calc_position('t1x1a')[2]
+ x = -(self.tw.canvas.width / 2) + xo
+ y = self.tw.canvas.height / 2
+ self.tw.canvas.setxy(x, y, pendown=False)
+ # save the text size so we can restore it later
+ save_text_size = self.tw.canvas.textsize
+ # set title text
+ self.tw.canvas.settextsize(self.title_height)
+ self._prim_show(title)
+ # calculate and set scale for media blocks
+ myscale = 90 * (self.tw.canvas.height - self.title_height * 2) / \
+ self.tw.canvas.height
+ self._prim_setscale(myscale)
+ # set body text size
+ self.tw.canvas.settextsize(self.body_height)
+ # render media object
+ # leave some space below the title
+ y -= int(self.title_height * 2 * self.tw.lead)
+ self.tw.canvas.setxy(x, y, pendown=False)
+ self._prim_show(media1)
+ # restore text size
+ self.tw.canvas.settextsize(save_text_size)
+
+ def _write(self, string, fsize):
+ """ Write string at size """
+ x = self.tw.canvas.width / 2 + int(self.tw.canvas.xcor)
+ y = self.tw.canvas.height / 2 - int(self.tw.canvas.ycor)
+ self.tw.canvas.draw_text(string, x, y - 15, int(fsize),
+ self.tw.canvas.width)