diff options
author | Walter Bender <walter@walter-laptop.(none)> | 2008-12-22 20:01:24 (GMT) |
---|---|---|
committer | Walter Bender <walter@walter-laptop.(none)> | 2008-12-22 20:01:24 (GMT) |
commit | f55fe02ea3bdf7b064bd5314c740495a95174a98 (patch) | |
tree | cb8c9a1d6fd1f1f0acf2ebbeb99631c7fcb4358d | |
parent | 5432fed0239df3c35b9ae659d85a05746a569c38 (diff) |
UCB logo export
Image cache check
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | TurtleArtActivity.py | 234 | ||||
-rw-r--r-- | activity/activity.info | 2 | ||||
-rw-r--r-- | icons/UCB-save.svg | 135 | ||||
-rw-r--r-- | talogo.py | 13 | ||||
-rw-r--r-- | tasetup.py | 6 |
6 files changed, 386 insertions, 9 deletions
@@ -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> @@ -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')) @@ -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 - |