Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--TurtleArtActivity.py234
-rw-r--r--activity/activity.info2
-rw-r--r--icons/UCB-save.svg135
-rw-r--r--talogo.py13
-rw-r--r--tasetup.py6
6 files changed, 386 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 14cb6eb..dc419ec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+24
+
+* add UCB logo export
+* check for conditions where image cache needs refreshing
+
23
* caching images
diff --git a/TurtleArtActivity.py b/TurtleArtActivity.py
index b5160a8..88dfa8b 100644
--- a/TurtleArtActivity.py
+++ b/TurtleArtActivity.py
@@ -19,6 +19,8 @@
#THE SOFTWARE.
import tawindow
+import talogo
+
import pygtk
pygtk.require('2.0')
import gtk
@@ -46,6 +48,7 @@ def debug_tick():
import sugar
from sugar.activity import activity
from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.menuitem import MenuItem
from sugar.datastore import datastore
from sugar import profile
from gettext import gettext as _
@@ -75,12 +78,33 @@ class TurtleArtActivity(activity.Activity):
toolbox._activity_toolbar.title.select_region(0,0)
tboxh = toolbox._activity_toolbar.size_request()[1]
+ version = os.environ['SUGAR_BUNDLE_VERSION']
+
lang = locale.getdefaultlocale()[0]
if not lang: lang = 'en'
lang = lang[0:2]
if not os.path.isdir(os.path.join(activity.get_bundle_path(),'images',lang)):
lang = 'en'
+ # test to see if lang or version has changed since last time
+ # if so, remove any old png files as they will need to be regenerated
+ filename = "version.dat"
+ versiondata = []
+
+ try:
+ FILE = open(os.path.join(activity.get_activity_root(),"data",filename),"r")
+ if FILE.readline() == lang + version:
+ print "the version data hasn't changed"
+ else:
+ print "out with the old version data",
+ os.system("rm " + os.path.join(activity.get_activity_root(),"data",'*.png'))
+ except:
+ print "writing new version data"
+ versiondata.append(lang + version)
+ FILE = open(os.path.join(activity.get_activity_root(),"data",filename),"w")
+ FILE.writelines(versiondata)
+ FILE.close()
+
self.tw = tawindow.twNew(canvas,activity.get_bundle_path(),lang,tboxh,self)
self.tw.activity = self
self.tw.window.grab_focus()
@@ -136,7 +160,6 @@ class TurtleArtActivity(activity.Activity):
shutil.rmtree(tmpdir)
tar_fd.close()
-
def jobject_new_patch(self):
oldj = self._jobject
self._jobject = datastore.create()
@@ -153,7 +176,6 @@ class TurtleArtActivity(activity.Activity):
reply_handler=self._internal_jobject_create_cb,
error_handler=self._internal_jobject_error_cb)
-
def clear_journal(self):
jobjects, total_count = datastore.find({'activity': 'org.laptop.TurtleArtActivity'})
print 'found', total_count, 'entries'
@@ -161,9 +183,8 @@ class TurtleArtActivity(activity.Activity):
print jobject.object_id
datastore.delete(jobject.object_id)
-
-
class ProjectToolbar(gtk.Toolbar):
+
def __init__(self, pc):
gtk.Toolbar.__init__(self)
self.activity = pc
@@ -175,8 +196,213 @@ class ProjectToolbar(gtk.Toolbar):
self.insert(self.sampb, -1)
self.sampb.show()
+ # UCB Logo save source button
+ self.savelogo = ToolButton( "UCB-save" )
+ self.savelogo.set_tooltip(_('UCB Logo'))
+ self.savelogo.props.sensitive = True
+ self.savelogo.connect('clicked', self.do_savelogo)
+ self.insert(self.savelogo, -1)
+ self.savelogo.show()
def do_samples(self, button):
tawindow.load_file(self.activity.tw)
# self.activity.jobject_new_patch()
+ def do_savelogo(self, button):
+ # write logo code out to datastore
+ print "saving logo code"
+ # grab code from stacks
+ logocode = self.save_logo(self.activity.tw)
+ if len(logocode) == 0:
+ return
+ filename = "logosession.lg"
+
+ # Create a datastore object
+ file_dsobject = datastore.create()
+
+ # Write any metadata (here we specifically set the title of the file and
+ # specify that this is a plain text file).
+ file_dsobject.metadata['title'] = filename
+ file_dsobject.metadata['mime_type'] = 'text/plain'
+ file_dsobject.metadata['icon-color'] = profile.get_color().to_string()
+
+ #Write the actual file to the data directory of this activity's root.
+ file_path = os.path.join(self.activity.get_activity_root(), 'instance', filename)
+ f = open(file_path, 'w')
+ try:
+ f.write(logocode)
+ finally:
+ f.close()
+
+ #Set the file_path in the datastore.
+ file_dsobject.set_file_path(file_path)
+
+ datastore.write(file_dsobject)
+ return
+
+ def save_logo(self, tw):
+ color_processing = "\
+to tasetpalette :i :r :g :b :myshade \r\
+make \"s ((:myshade - 50) / 50) \r\
+ifelse lessp :s 0 [ \r\
+make \"s (1 + (:s *0.8)) \r\
+make \"r (:r * :s) \r\
+make \"g (:g * :s) \r\
+make \"b (:b * :s) \r\
+] [ \
+make \"s (:s * 0.9) \r\
+make \"r (:r + ((100-:r) * :s)) \r\
+make \"g (:g + ((100-:g) * :s)) \r\
+make \"b (:b + ((100-:b) * :s)) \r\
+] \
+setpalette :i (list :r :g :b) \r\
+end \r\
+\
+to rgb :myi :mycolors :myshade \r\
+make \"myr first :mycolors \r\
+make \"mycolors butfirst :mycolors \r\
+make \"myg first :mycolors \r\
+make \"mycolors butfirst :mycolors \r\
+make \"myb first :mycolors \r\
+make \"mycolors butfirst :mycolors \r\
+tasetpalette :myi :myr :myg :myb :myshade \r\
+output :mycolors \r\
+end \r\
+\
+to processcolor :mycolors :myshade \r\
+if emptyp :mycolors [stop] \r\
+make \"i :i + 1 \r\
+processcolor (rgb :i :mycolors :myshade) :myshade \r\
+end \r\
+\
+to tasetshade :shade \r\
+make \"myshade modulo :shade 200 \r\
+if greaterp :myshade 99 [make \"myshade (199-:myshade)] \r\
+make \"i 7 \r\
+make \"mycolors :colors \r\
+processcolor :mycolors :myshade \r\
+end \r\
+\
+to tasetpencolor :c \r\
+make \"color (modulo (round :c) 100) \r\
+setpencolor :color + 8 \r\
+end \r\
+\
+make \"colors [ \
+100 0 0 100 5 0 100 10 0 100 15 0 100 20 0 100 25 0 100 30 0 100 35 0 100 40 0 100 45 0 \
+100 50 0 100 55 0 100 60 0 100 65 0 100 70 0 100 75 0 100 80 0 100 85 0 100 90 0 100 95 0 \
+100 100 0 90 100 0 80 100 0 70 100 0 60 100 0 50 100 0 40 100 0 30 100 0 20 100 0 10 100 0 \
+0 100 0 0 100 5 0 100 10 0 100 15 0 100 20 0 100 25 0 100 30 0 100 35 0 100 40 0 100 45 \
+0 100 50 0 100 55 0 100 60 0 100 65 0 100 70 0 100 75 0 100 80 0 100 85 0 100 90 0 100 95 \
+0 100 100 0 95 100 0 90 100 0 85 100 0 80 100 0 75 100 0 70 100 0 65 100 0 60 100 0 55 100 \
+0 50 100 0 45 100 0 40 100 0 35 100 0 30 100 0 25 100 0 20 100 0 15 100 0 10 100 0 5 100 \
+0 0 100 5 0 100 10 0 100 15 0 100 20 0 100 25 0 100 30 0 100 35 0 100 40 0 100 45 0 100 \
+50 0 100 55 0 100 60 0 100 65 0 100 70 0 100 75 0 100 80 0 100 85 0 100 90 0 100 95 0 100 \
+100 0 100 100 0 90 100 0 80 100 0 70 100 0 60 100 0 50 100 0 40 100 0 30 100 0 20 100 0 10] \r\
+make \"shade 50 \r\
+tasetshade :shade \r"
+
+ bs = tawindow.blocks(tw)
+ code = ""
+ random = 0
+ fillscreen = 0
+ setcolor = 0
+ setxy = 0
+ pensize = 0
+ tastack = 0
+ arc = 0
+ for b in bs:
+ this_stack = ""
+ data = self.walk_stack(tw, b)
+ # need to catch several special cases:
+ # stacks, random, setshade, et al.
+ stack = 0
+ for d in data:
+ if type(d) is float:
+ this_stack += str(d)
+ else:
+ # transalate some TA terms into UCB Logo
+ if d == "storeinbox1":
+ this_stack += "make \"box1"
+ elif d == "box1":
+ this_stack += ":box1"
+ elif d == "storeinbox2":
+ this_stack += "make \"box2"
+ elif d == "box2":
+ this_stack += ":box2"
+ elif d == "shade":
+ this_stack += ":shade"
+ elif d == "setshade":
+ setcolor = 1
+ this_stack += "tasetshade"
+ elif d == "color":
+ this_stack += "pencolor"
+ elif d == "nop":
+ this_stack += " "
+ elif d == "nop1":
+ this_stack += "to stack1\r"
+ stack = 1
+ elif d == "nop2":
+ this_stack += "to stack2\r"
+ stack = 1
+ elif d == "clean":
+ this_stack += "clearscreen"
+ elif d == "setxy":
+ setxy = 1
+ this_stack += "tasetxy"
+ elif d == "color":
+ this_stack += ":color"
+ elif d == "setcolor":
+ setcolor = 1
+ this_stack += "tasetpencolor"
+ elif d == "fillscreen":
+ fillscreen = 1
+ this_stack += "tasetbackground"
+ elif d == "random":
+ random = 1
+ this_stack += "tarandom"
+ elif d == "pensize":
+ pensize = 1
+ this_stack += "tapensize"
+ elif d == "arc":
+ arc = 1
+ this_stack += "taarc"
+ else:
+ this_stack += d
+ this_stack += " "
+ if stack:
+ stack = 0
+ # if it is not a stack, we need to add a "to ta#" label
+ elif len(data) > 0:
+ this_stack = "to ta" + str(tastack) + "\r" + this_stack
+ tastack += 1
+ if len(data) > 0:
+ code += this_stack
+ code += "\rend\r"
+ # need to define some procedures
+ if random: # to avoid negative numbers
+ code = "to tarandom :min :max\routput (random (:max - :min)) + :min\rend\r" + code
+ if fillscreen: # set shade than background color
+ code = "to tasetbackground :color :shade\rtasetshade :shade\rsetbackground :color\rend\r" + code
+ if setcolor: # load palette
+ code = color_processing + code
+ if pensize: # return only first argument
+ code = "to tapensize\routput first round pensize\rend\r" + code
+ if setxy: # swap args and round args
+ code = "to tasetxy :y :x\rpenup\rsetxy :x :y\rpendown\rend\r" + code
+ if arc:
+ c = (2 * math.pi)/360
+ code = "to taarc :a :r\rrepeat round :a [right 1 forward (" + str(c) + " * :r)]\rend\r" + code
+ code = "window\rsetscrunch 2 2\r" + code
+ print code
+ return code
+
+ def walk_stack(self, tw, spr):
+ top = tawindow.find_top_block(spr)
+ if spr == top:
+ # only walk the stack if the block is the top block
+ return talogo.walk_blocks(tw.lc, top, tawindow.blocks(tw))
+ else:
+ # not top of stack, then return empty list
+ return []
+
diff --git a/activity/activity.info b/activity/activity.info
index b172a47..9674034 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,6 +1,6 @@
[Activity]
name = Turtle Art
-activity_version = 23
+activity_version = 24
license = MIT
service_name = org.laptop.TurtleArtActivity
class = TurtleArtActivity.TurtleArtActivity
diff --git a/icons/UCB-save.svg b/icons/UCB-save.svg
new file mode 100644
index 0000000..08fb9e8
--- /dev/null
+++ b/icons/UCB-save.svg
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#ffffff">
+]>
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve">
+<g
+ transform="translate(-0.5507515,-1.7569535)">
+ <line
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="line3290"
+ y2="4.9169998"
+ y1="16.188"
+ x2="52.441002"
+ x1="41.169998" />
+ <polyline
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="polyline3292"
+ points="51.562,15.306 41.17,16.188 42.053,5.794" />
+</g>
+<g
+ transform="translate(-6,2)">
+ <polygon
+ points="10.932,6.088 31.874,6.088 43.818,18.027 43.818,48.914 10.932,48.914 10.932,6.088 "
+ id="polygon9"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3.5" />
+ <polyline
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3.5"
+ id="polyline11"
+ points="43.818,18.027 31.874,18.027 31.874,6.088" />
+
+ <path
+ d="M 27.379465,42.19975 C 27.102965,42.19975 26.829965,42.18225 26.560965,42.14975 L 27.254965,43.32425 L 27.938965,42.16775 C 27.753465,42.18275 27.568465,42.19975 27.379465,42.19975 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(0.5,0,0,0.5,13.630965,18.06025)"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
+ <path
+ d="M 40.16,11.726 C 37.996,11.726 36.202,13.281 35.817,15.333 C 37.676,16.678 39.274,18.448 40.492,20.541 C 42.777,20.369 44.586,18.48 44.586,16.151 C 44.586,13.707 42.604,11.726 40.16,11.726 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 40.713,39.887 C 39.489,42.119 37.853,44.018 35.916,45.443 C 36.437,47.307 38.129,48.682 40.16,48.682 C 42.603,48.682 44.586,46.702 44.586,44.258 C 44.586,42.003 42.893,40.162 40.713,39.887 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 14.273,39.871 C 12.02,40.077 10.249,41.95 10.249,44.258 C 10.249,46.701 12.229,48.682 14.673,48.682 C 16.737,48.682 18.457,47.262 18.945,45.35 C 17.062,43.934 15.47,42.061 14.273,39.871 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.026,15.437 C 18.683,13.334 16.872,11.726 14.673,11.726 C 12.229,11.726 10.249,13.707 10.249,16.15 C 10.249,18.532 12.135,20.46 14.494,20.556 C 15.68,18.513 17.226,16.772 19.026,15.437 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <path
+ d="M 27.379465,24.34175 C 28.333465,24.34175 29.243465,24.54725 30.088465,24.90575 C 30.458965,24.36775 30.677465,23.71725 30.677465,23.01425 C 30.677465,21.17075 29.182965,19.67575 27.338965,19.67575 C 25.495465,19.67575 24.000965,21.17075 24.000965,23.01425 C 24.000965,23.72825 24.226965,24.38875 24.608965,24.93125 C 25.470965,24.55675 26.402465,24.34175 27.379465,24.34175 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(0.5,0,0,0.5,13.630965,18.06025)"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
+ <path
+ d="M 43.102,30.421 C 43.102,35.1554 41.4568,39.7008 38.5314,43.0485 C 35.606,46.3963 31.6341,48.279 27.497,48.279 C 23.3599,48.279 19.388,46.3963 16.4626,43.0485 C 13.5372,39.7008 11.892,35.1554 11.892,30.421 C 11.892,20.6244 18.9364,12.563 27.497,12.563 C 36.0576,12.563 43.102,20.6244 43.102,30.421 z"
+ id="path2988"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ transform="matrix(0.5,0,0,0.5,13.630965,18.06025)"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
+ <path
+ d="M 25.875,33.75 L 24.333,29.125 L 27.497,26.538 L 31.112,29.164 L 29.625,33.833 L 25.875,33.75 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 27.501,41.551 C 23.533,41.391 21.958,39.542 21.958,39.542 L 25.528,35.379 L 29.993,35.547 L 33.125,39.667 C 33.125,39.667 30.235,41.661 27.501,41.551 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 18.453,33.843 C 17.604,30.875 18.625,26.959 18.625,26.959 L 22.625,29.126 L 24.118,33.755 L 20.536,37.988 C 20.536,37.987 19.071,35.998 18.453,33.843 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.458,25.125 C 19.458,25.125 19.958,23.167 22.497,21.303 C 24.734,19.66 26.962,19.583 26.962,19.583 L 26.925,24.564 L 23.404,27.314 L 19.458,25.125 z"
+ id="path2998"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.084,27.834 L 28.625,24.959 L 29,19.75 C 29,19.75 30.834,19.708 32.959,21.417 C 35.187,23.208 36.321,26.4 36.321,26.4 L 32.084,27.834 z"
+ fill="none"
+ stroke="&stroke_color;"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 31.292,34.042 L 32.605,29.578 L 36.792,28.042 C 36.792,28.042 37.469,30.705 36.75,33.709 C 36.21,35.965 34.666,38.07 34.666,38.07 L 31.292,34.042 z"
+ id="path3002"
+ style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</g>
+</svg>
diff --git a/talogo.py b/talogo.py
index c3e6c14..77a772a 100644
--- a/talogo.py
+++ b/talogo.py
@@ -45,7 +45,6 @@ class logoerror(Exception):
def __str__(self):
return repr(self.value)
-
def run_blocks(lc, spr, blocks):
lc.stacks['stack1'] = None
lc.stacks['stack2'] = None
@@ -56,6 +55,16 @@ def run_blocks(lc, spr, blocks):
print code
setup_cmd(lc, code)
+# walk through the blocks, but don't execute them
+# used by save Logo code
+def walk_blocks(lc, spr, blocks):
+ lc.stacks['stack1'] = None
+ lc.stacks['stack2'] = None
+ for i in blocks:
+ if i.proto.name=='hat1': lc.stacks['stack1']= readline(lc,blocks_to_code(i))
+ if i.proto.name=='hat2': lc.stacks['stack2']= readline(lc,blocks_to_code(i))
+ return blocks_to_code(spr)
+
def blocks_to_code(spr):
if spr==None: return ['%nothing%']
code = []
@@ -311,6 +320,8 @@ def lcNew(tw):
defprim(lc,'define', 2, prim_define)
defprim(lc,'nop', 0, lambda lc: None)
+ defprim(lc,'nop1', 0, lambda lc: None)
+ defprim(lc,'nop2', 0, lambda lc: None)
defprim(lc,'start', 0, lambda: None)
lc.symtype = type(intern(lc, 'print'))
diff --git a/tasetup.py b/tasetup.py
index 8609928..bdc0271 100644
--- a/tasetup.py
+++ b/tasetup.py
@@ -76,9 +76,9 @@ selectors = (
('hspace','nop','hspace'),
('vspace','nop','vspace'))),
('myblocks', 55,
- (('hat1','nop','start'),
+ (('hat1','nop1','start'),
('stack1','stack1','noarg'),
- ('hat2','nop','start'),
+ ('hat2','nop2','start'),
('stack2','stack2','noarg'),
('storeinbox1','storeinbox1','1arg'),
('box1','box1','num'),
@@ -191,9 +191,9 @@ def load_image(path, dir, file):
# first try to open the cached image
# if you fail, open the .svg file and cache the result
+ # gtk.gdk.pixbuf_new_from_file_at_size(filename, width, height)
try: return gtk.gdk.pixbuf_new_from_file(os.path.join(activity.get_activity_root(),"data",file+'.png'))
except:
foo = gtk.gdk.pixbuf_new_from_file(os.path.join(path,dir,file+'.svg'))
foo.save(os.path.join(activity.get_activity_root(),"data",file+'.png'), "png")
return foo
-