Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TurtleArt/tabasics.py5
-rw-r--r--TurtleArt/tawindow.py34
-rw-r--r--icons/macrosoff.svg69
-rw-r--r--icons/macroson.svg70
-rwxr-xr-xturtleblocks.py43
5 files changed, 218 insertions, 3 deletions
diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py
index 81eba2d..0d88a9d 100644
--- a/TurtleArt/tabasics.py
+++ b/TurtleArt/tabasics.py
@@ -107,6 +107,11 @@ class Palettes():
self._blocks_palette()
+ palette = make_palette('macros',
+ colors=["#FFC000", "#A08000"],
+ help_string=\
+ _('Palette of user-defined operators'))
+
self._trash_palette()
# Palette definitions
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index 906a7d8..14c0190 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -40,7 +40,9 @@ except ImportError:
import os
import subprocess
+import errno
+from random import uniform
from math import atan2, pi
DEGTOR = 2 * pi / 360
@@ -68,7 +70,7 @@ from tautils import (magnitude, get_load_name, get_save_name, data_from_file,
calc_image_size, get_path, hide_button_hit, show_button_hit, chooser,
arithmetic_check, xy, find_block_to_run, find_top_block, journal_check,
find_group, find_blk_below, data_to_string, find_start_stack,
- get_hardware, debug_output, error_output, convert,
+ get_hardware, debug_output, error_output, convert, find_hat,
find_bot_block, restore_clamp, collapse_clamp, data_from_string,
increment_name, get_screen_dpi)
from tasprite_factory import (SVG, svg_str_to_pixbuf, svg_from_file)
@@ -142,6 +144,8 @@ class TurtleArtWindow():
self.mouse_y = 0
self.update_counter = 0
self.running_blocks = False
+ self.saving_macro = False
+ self.macros_path = ''
try:
locale.setlocale(locale.LC_NUMERIC, '')
@@ -1862,6 +1866,34 @@ before making changes to your Turtle Blocks program'))
for blk in self.drag_group:
if blk.status != 'collapsed':
blk.spr.set_layer(TOP_LAYER)
+ if self.saving_macro:
+ for blk in self.drag_group:
+ if blk.status != 'collapsed':
+ blk.highlight()
+ self.block_operation = 'copying'
+ data = self.assemble_data_to_save(False, False)
+ i = find_hat(data)
+ if i is not None and data[i][4][1] is not None:
+ try:
+ name = str(data[data[i][4][1]][1][1])
+ except:
+ name = 'macro%d' % (int(uniform(0, 10000)))
+ debug_output('saving macro %s' % (name),
+ self.running_sugar)
+ if not os.path.exists(self.macros_path):
+ try:
+ os.makedirs(self.macros_path)
+ except OSError, exc:
+ if exc.errno == errno.EEXIST:
+ pass
+ else:
+ raise
+ data_to_file(data, os.path.join(self.macros_path,
+ '%s.tb' % (name)))
+ self.parent.get_window().set_cursor(
+ gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
+ self.saving_macro = False
+
if self.running_sugar and \
(self.activity.copying or self.activity.sharing_blocks):
for blk in self.drag_group:
diff --git a/icons/macrosoff.svg b/icons/macrosoff.svg
new file mode 100644
index 0000000..7d9a28c
--- /dev/null
+++ b/icons/macrosoff.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2">
+ <metadata
+ id="metadata10">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs8" />
+ <rect
+ width="45"
+ height="45"
+ x="5"
+ y="5"
+ id="rect2990"
+ style="fill:#282828;fill-opacity:1;stroke:none" />
+ <g
+ id="g3789">
+ <path
+ d="m 15.719636,31.331478 0.114372,5.261133 11.437247,6.290486 L 27.5,29.387146"
+ id="path2463"
+ style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 27.728744,29.501519 0.05719,13.381578 11.723178,-7.548583 0,-4.689272 -5.947368,3.545548"
+ id="path2465"
+ style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 10.001012,27.328441 5.604251,-5.146761 -5.832996,-2.973684 12.123482,-7.091093 5.718623,3.316801 5.489879,-3.088056 12.123482,7.319838 -5.832996,2.401822 5.489878,5.032388 -11.322874,7.205466 -5.947369,-5.261134 -6.290485,5.261134 -11.322875,-6.976721 z"
+ id="path2459"
+ style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 16.40587,21.952935 27.156883,15.204959 38.937247,22.067308 27.614372,28.815283 16.40587,21.952935 z"
+ id="path2461"
+ style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="matrix(0.39620698,0,0,0.39620698,28.654032,26.094918)"
+ id="stock-xo_1_"
+ style="display:block">
+ <path
+ d="m 33.233,35.1 10.102,10.1 c 0.752,0.75 1.217,1.783 1.217,2.932 0,2.287 -1.855,4.143 -4.146,4.143 -1.145,0 -2.178,-0.463 -2.932,-1.211 l -10.102,-10.103 -10.1,10.1 c -0.75,0.75 -1.787,1.211 -2.934,1.211 -2.284,0 -4.143,-1.854 -4.143,-4.141 0,-1.146 0.465,-2.184 1.212,-2.934 L 21.511,35.095 11.409,24.995 c -0.747,-0.748 -1.212,-1.785 -1.212,-2.93 0,-2.289 1.854,-4.146 4.146,-4.146 1.143,0 2.18,0.465 2.93,1.214 L 27.372,29.235 37.474,19.132 c 0.754,-0.749 1.787,-1.214 2.934,-1.214 2.289,0 4.146,1.856 4.146,4.145 0,1.146 -0.467,2.18 -1.217,2.932 L 33.233,35.1 z"
+ id="path3076"
+ style="fill:#ffffff;stroke:#010101;stroke-width:3.5" />
+ <circle
+ cx="27.371"
+ cy="10.849"
+ r="8.1219997"
+ id="circle3078"
+ style="fill:#ffffff;stroke:#010101;stroke-width:3.5" />
+ </g>
+</svg>
diff --git a/icons/macroson.svg b/icons/macroson.svg
new file mode 100644
index 0000000..bb8852d
--- /dev/null
+++ b/icons/macroson.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2">
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs4" />
+ <rect
+ width="55"
+ height="55"
+ rx="0"
+ x="0"
+ y="0"
+ id="rect2839"
+ style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <g
+ id="g3788">
+ <path
+ d="m 15.719636,31.331478 0.114372,5.261133 11.437247,6.290486 L 27.5,29.387146"
+ id="path2463"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 27.728744,29.501519 0.05719,13.381578 11.723178,-7.548583 0,-4.689272 -5.947368,3.545548"
+ id="path2465"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 10.001012,27.328441 5.604251,-5.146761 -5.832996,-2.973684 12.123482,-7.091093 5.718623,3.316801 5.489879,-3.088056 12.123482,7.319838 -5.832996,2.401822 5.489878,5.032388 -11.322874,7.205466 -5.947369,-5.261134 -6.290485,5.261134 -11.322875,-6.976721 z"
+ id="path2459"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 16.40587,21.952935 27.156883,15.204959 38.937247,22.067308 27.614372,28.815283 16.40587,21.952935 z"
+ id="path2461"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="matrix(0.39620698,0,0,0.39620698,28.654032,26.094918)"
+ id="stock-xo_1_"
+ style="display:block">
+ <path
+ d="m 33.233,35.1 10.102,10.1 c 0.752,0.75 1.217,1.783 1.217,2.932 0,2.287 -1.855,4.143 -4.146,4.143 -1.145,0 -2.178,-0.463 -2.932,-1.211 l -10.102,-10.103 -10.1,10.1 c -0.75,0.75 -1.787,1.211 -2.934,1.211 -2.284,0 -4.143,-1.854 -4.143,-4.141 0,-1.146 0.465,-2.184 1.212,-2.934 L 21.511,35.095 11.409,24.995 c -0.747,-0.748 -1.212,-1.785 -1.212,-2.93 0,-2.289 1.854,-4.146 4.146,-4.146 1.143,0 2.18,0.465 2.93,1.214 L 27.372,29.235 37.474,19.132 c 0.754,-0.749 1.787,-1.214 2.934,-1.214 2.289,0 4.146,1.856 4.146,4.145 0,1.146 -0.467,2.18 -1.217,2.932 L 33.233,35.1 z"
+ id="path3076"
+ style="fill:#ffffff;stroke:#010101;stroke-width:3.5" />
+ <circle
+ cx="27.371"
+ cy="10.849"
+ r="8.1219997"
+ id="circle3078"
+ style="fill:#ffffff;stroke:#010101;stroke-width:3.5" />
+ </g>
+</svg>
diff --git a/turtleblocks.py b/turtleblocks.py
index ed2ebce..d8b256c 100755
--- a/turtleblocks.py
+++ b/turtleblocks.py
@@ -30,6 +30,7 @@ import getopt
import sys
import os
import os.path
+import glob
import cStringIO
import errno
import ConfigParser
@@ -48,10 +49,12 @@ sys.argv[1:] = [] # Execution of import gst cannot see '--help' or '-h'
import gettext
from TurtleArt.taconstants import (OVERLAY_LAYER, DEFAULT_TURTLE_COLORS,
- TAB_LAYER, SUFFIX)
-from TurtleArt.tautils import (data_to_string, data_from_string, get_save_name)
+ TAB_LAYER, SUFFIX, MACROS)
+from TurtleArt.tautils import (data_to_string, data_from_string, listify,
+ data_from_file, get_save_name, hat_on_top)
from TurtleArt.tawindow import TurtleArtWindow
from TurtleArt.taexportlogo import save_logo
+from TurtleArt.tapalette import make_palette
from util.menubuilder import MenuBuilder
@@ -63,6 +66,7 @@ class TurtleMain():
'/usr/local/share/sugar/activities/TurtleArt.activity'
_ICON_SUBPATH = 'images/turtle.png'
_GNOME_PLUGIN_SUBPATH = 'gnome_plugins'
+ _MACROS_SUBPATH = 'macros'
def __init__(self):
self._abspath = os.path.abspath('.')
@@ -105,6 +109,7 @@ class TurtleMain():
self._init_gnome_plugins()
self._setup_gtk()
self._build_window()
+ self._load_user_macros()
self._run_gnome_plugins()
self._start_gtk()
@@ -166,6 +171,37 @@ class TurtleMain():
if not exists(dpath):
makedirs(dpath)
+ def _load_user_macros(self):
+ ''' User-defined macros are saved as a json-encoded file;
+ these get loaded into a palette on startup '''
+ macros_path = os.path.join(self._execdirname, self._MACROS_SUBPATH)
+ self.tw.macros_path = macros_path
+ if os.path.exists(macros_path):
+ files = glob.glob(os.path.join(macros_path, '*.tb'))
+ print 'creating macros palette'
+ if len(files) > 0:
+ palette = make_palette('macros',
+ colors=["#FFC000", "#A08000"],
+ help_string=\
+_('Palette of user-defined operators'))
+
+ for tafile in files:
+ data = data_from_file(tafile)
+ name = os.path.basename(tafile)[:-3]
+ print 'loading macro %s' % (name)
+ MACROS['user-defined-' + name] = hat_on_top(listify(data))
+ palette.add_block('user-defined-' + name,
+ style='basic-style-extended-vertical',
+ label=name)
+
+ def _do_save_macro_cb(self, widget):
+ if self.saving_macro:
+ self.win.get_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
+ self.tw.saving_macro = False
+ else:
+ self.win.get_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1))
+ self.tw.saving_macro = True
+
def _start_gtk(self):
''' Get a main window set up. '''
self.win.connect('configure_event', self.tw.update_overlay_position)
@@ -216,6 +252,7 @@ class TurtleMain():
self.current_palette = 0
self.scale = 2.0
self.tw = None
+ self.saving_macro = False
self.init_complete = False
def _parse_command_line(self):
@@ -385,6 +422,8 @@ class TurtleMain():
menu = gtk.Menu()
MenuBuilder.make_menu_item(menu, _('Copy'), self._do_copy_cb)
MenuBuilder.make_menu_item(menu, _('Paste'), self._do_paste_cb)
+ MenuBuilder.make_menu_item(menu, _('Save stack'),
+ self._do_save_macro_cb)
edit_menu = MenuBuilder.make_sub_menu(menu, _('Edit'))
menu = gtk.Menu()