From 1ef7063ca9bf97f80fb81ff77c9d17d0c4be71bf Mon Sep 17 00:00:00 2001 From: U-BRIAN-X60\Brian Silverman Date: Fri, 16 Nov 2007 20:54:29 +0000 Subject: multiple instances run properly --- diff --git a/MANIFEST b/MANIFEST index 78d97d0..1e3c821 100755 --- a/MANIFEST +++ b/MANIFEST @@ -1,13 +1,13 @@ -arrow.gif -logo.py masknumber.gif -sprites.py status.gif setup.py -ta.py +talogo.py +taproject.py +tasprites.py +tasetup.py +taturtle.py +tawindow.py TurtleArtActivity.py -turtle.py -turtlesetup.py icons/stock-open.svg flow/flowgroup.gif flow/flowmask.gif @@ -19,45 +19,14 @@ flow/repeat.gif flow/stopstack.gif flow/vspace.gif flow/wait.gif -myblocks/1input.gif -myblocks/1inputmask.gif -myblocks/2inputs.gif -myblocks/2inputsmask.gif -myblocks/3inputs.gif -myblocks/3inputsmask.gif -myblocks/boutput.gif -myblocks/boutputmask.gif myblocks/box1.gif myblocks/box2.gif -myblocks/global1.gif -myblocks/global1mask.gif -myblocks/global.gif -myblocks/globalmask.gif myblocks/hat1.gif myblocks/hat2.gif -myblocks/line.gif -myblocks/linemask.gif -myblocks/myblocksgroup.gif -myblocks/myblocksmask.gif -myblocks/mystuffbg.gif -myblocks/mystuffgroup.gif -myblocks/mystuffmask.gif -myblocks/opwith1ipb.gif -myblocks/opwith1ipbmask.gif -myblocks/opwith1ip.gif -myblocks/opwith1ipmask.gif -myblocks/output1.gif -myblocks/output1mask.gif -myblocks/output.gif -myblocks/outputmask.gif -myblocks/procedure.gif -myblocks/proceduremask.gif -myblocks/setglobal.gif -myblocks/setglobalmask.gif myblocks/stack1.gif myblocks/stack2.gif -myblocks/start.gif -myblocks/startmask.gif +myblocks/myblocksgroup.gif +myblocks/myblocksmask.gif myblocks/storeinbox1.gif myblocks/storeinbox2.gif numbers/and.gif @@ -139,9 +108,6 @@ toolbar/eraseroff.gif toolbar/eraseron.gif toolbar/hideshowoff.gif toolbar/hideshowon.gif -toolbar/project-.gif -toolbar/project.gif -toolbar/projectmask.gif toolbar/stopitoff.gif toolbar/stopiton.gif turtle/arc.gif @@ -191,5 +157,7 @@ samples/squares.png samples/squares.ta samples/squiral.png samples/squiral.ta +samples/sunrise.png +samples/sunrise.ta samples/xo-man.png samples/xo-man.ta diff --git a/NEWS b/NEWS new file mode 100755 index 0000000..eb5027d --- /dev/null +++ b/NEWS @@ -0,0 +1,3 @@ +5 + +* Multi instance happy diff --git a/TurtleArtActivity.py b/TurtleArtActivity.py index 6fc4b50..a892795 100755 --- a/TurtleArtActivity.py +++ b/TurtleArtActivity.py @@ -1,4 +1,4 @@ -import ta +import tawindow import pygtk pygtk.require('2.0') import gtk @@ -7,9 +7,22 @@ from socket import * import sys import gobject -serverHost = '192.168.1.101' +serverHost = '192.168.1.102' serverPort = 5647 +def debug_init(): + s = socket(AF_INET, SOCK_STREAM) # create a TCP socket + s.connect((serverHost, serverPort)) # connect to server on the port + sys.stdout = s.makefile() + sys.stderr = sys.stdout + gobject.timeout_add(100, debug_tick) + +def debug_tick(): + sys.stdout.flush() + return True + +#debug_init() + import sugar from sugar.activity import activity from sugar.activity import registry @@ -18,11 +31,9 @@ from sugar.datastore import datastore from sugar import profile from gettext import gettext as _ - class TurtleArtActivity(activity.Activity): def __init__(self, handle): super(TurtleArtActivity,self).__init__(handle) -# self.debug_init() self.gamename = 'turtleart' self.set_title("TurtleArt") @@ -35,19 +46,25 @@ class TurtleArtActivity(activity.Activity): toolbox._activity_toolbar.keep.connect('clicked', self._keep_clicked_cb) # patch - self.connect('destroy', self._cleanup_cb) - canvas = gtk.EventBox() sugar.graphics.window.Window.set_canvas(self, canvas) + toolbox._activity_toolbar.title.grab_focus() + toolbox._activity_toolbar.title.select_region(0,0) - ta.init(canvas, activity.get_bundle_path(),self) + self.tw = tawindow.twNew(canvas, activity.get_bundle_path(),self) + self.tw.activity = self + self.tw.window.grab_focus() + + toolbox._activity_toolbar._update_title_sid = True + toolbox._activity_toolbar.title.connect('focus-out-event', self.update_title_cb, toolbox) # patch if self._jobject and self._jobject.file_path: self.read_file(self._jobject.file_path) - def _cleanup_cb(self, data=None): - return + def update_title_cb(self, widget, event, toolbox): + toolbox._activity_toolbar._update_title_cb() + toolbox._activity_toolbar._update_title_sid = True def _keep_clicked_cb(self, button): self.jobject_new_patch() @@ -62,8 +79,8 @@ class TurtleArtActivity(activity.Activity): del pngfd, tafd try: - ta.save_data(tafile) - ta.save_pict(pngfile) + tawindow.save_data(self.tw,tafile) + tawindow.save_pict(self.tw,pngfile) tar_fd.add(tafile, "ta_code.ta") tar_fd.add(pngfile, "ta_image.png") @@ -83,22 +100,12 @@ class TurtleArtActivity(activity.Activity): try: # We'll get 'ta_code.ta' and 'ta_image.png' tar_fd.extractall(tmpdir) - ta.load_files(os.path.join(tmpdir, 'ta_code.ta'), os.path.join(tmpdir, 'ta_image.png')) + tawindow.load_files(self.tw, os.path.join(tmpdir, 'ta_code.ta'), os.path.join(tmpdir, 'ta_image.png')) finally: shutil.rmtree(tmpdir) tar_fd.close() - def debug_init(self): - s = socket(AF_INET, SOCK_STREAM) # create a TCP socket - s.connect((serverHost, serverPort)) # connect to server on the port - sys.stdout = s.makefile() - sys.stderr = sys.stdout - gobject.timeout_add(100, self.debug_tick) - - def debug_tick(self): - sys.stdout.flush() - return True def jobject_new_patch(self): oldj = self._jobject @@ -117,6 +124,15 @@ class TurtleArtActivity(activity.Activity): 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' + for jobject in jobjects[:-1]: + print jobject.object_id + datastore.delete(jobject.object_id) + + + class ProjectToolbar(gtk.Toolbar): def __init__(self, pc): gtk.Toolbar.__init__(self) @@ -131,6 +147,6 @@ class ProjectToolbar(gtk.Toolbar): def do_samples(self, button): - ta.load_file() + tawindow.load_file(self.activity.tw) # self.activity.jobject_new_patch() diff --git a/activity/activity.info b/activity/activity.info index 657c942..23d9be0 100755 --- a/activity/activity.info +++ b/activity/activity.info @@ -3,5 +3,5 @@ name = TurtleArt service_name = org.laptop.TurtleArtActivity class = TurtleArtActivity.TurtleArtActivity icon = activity-turtleart -activity_version = 4 +activity_version = 5 show_launcher = yes diff --git a/arrow.gif b/arrow.gif deleted file mode 100755 index 37640dc..0000000 --- a/arrow.gif +++ /dev/null Binary files differ diff --git a/icons/stock-open.svg b/icons/stock-open.svg new file mode 100755 index 0000000..463e91b --- /dev/null +++ b/icons/stock-open.svg @@ -0,0 +1,29 @@ + + + + + +]> + + + + + + + + + + + + + + + + + + diff --git a/logo.py b/logo.py deleted file mode 100755 index 1c4a460..0000000 --- a/logo.py +++ /dev/null @@ -1,361 +0,0 @@ -import re -from time import clock -from operator import isNumberType -import random - -oblist = {} - -iline = None -cfun = None -arglist = None - -istack = [] -iresult = None -step = None -procstop = False - -boxes = {'box1': 0, 'box2': 0} -stacks = {} - -utime_start = 0 - -class symbol: - - def __init__(self, name): - self.name = name - self.nargs = None - self.fcn = None - - def __str__(self): return self.name - def __repr__(self): return '#'+self.name - -class logoerror(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - - -def run_blocks(spr, blocks): - stacks['stack1'] = None - stacks['stack2'] = None - for i in blocks: - if i.proto.name=='hat1': stacks['stack1']= readline(blocks_to_code(i)) - if i.proto.name=='hat2': stacks['stack2']= readline(blocks_to_code(i)) - code = blocks_to_code(spr) - print code - setup_cmd(code) - -def blocks_to_code(spr): - if spr==None: return ['%nothing%'] - code = [] - dock = spr.proto.docks[0] - if len(dock)>4: code.append(dock[4]) - if spr.proto.primname != '': code.append(spr.proto.primname) - else: code.append(float(spr.label)) - for i in range(1,len(spr.connections)): - b = spr.connections[i] - dock = spr.proto.docks[i] - if len(dock)>4: - for c in dock[4]: code.append(c) - if b!=None: code.extend(blocks_to_code(b)) - elif spr.proto.docks[i][0] not in ['flow','numend','unavailable','logi-']: - code.append('%nothing%') - return code - -def intern(str): - if str in oblist: return oblist[str] - sym = symbol(str) - oblist[str] = sym - return sym - - -def parseline(str): - split = re.split(r"\s|([\[\]()])", str) - return [x for x in split if x and x != ""] - -def readline(line): - res = [] - while line: - token = line.pop(0) - if isNumberType(token): res.append(token) - elif token.isdigit(): res.append(float(token)) - elif token[0]=='-' and token[1:].isdigit(): res.append(-float(token[1:])) - elif token[0] == '"': res.append(token[1:]) - elif token == '[': res.append(readline(line)) - elif token == ']': return res - else: res.append(intern(token)) - return res - - -def setup_cmd(str): - global iline, step, procstop - stopsignon(); procstop=False - list = readline(str) - step = start_eval(list) - -def start_eval(list): - icall(evline, list); yield True - yield False - -def evline(list): - global cfun, arglist, iline - oldiline = iline - iline = list[:] - arglist = None - while iline: - token = iline[0] - if token==symopar: token=iline[1] - icall(eval); yield True - if procstop: break - if iresult==None: continue - raise logoerror("You don't say what to do with %s" % token) - iline = oldiline - ireturn(); yield True - -def eval(infixarg=False): - token = iline.pop(0) - if type(token) == symtype: - icall(evalsym, token); yield True - res = iresult - else: res = token - if not infixarg: - while infixnext(): - icall(evalinfix, res); yield True - res = iresult - ireturn(res); yield True - -def evalsym(token): - global cfun, arglist - undefined_check(token) - oldcfun, oldarglist = cfun, arglist - cfun, arglist = token, [] - for i in range(token.nargs): - no_args_check() - icall(eval); yield True - arglist.append(iresult) - if cfun.rprim: - if type(cfun.fcn)==listtype: icall(ufuncall, cfun.fcn); yield True - else: icall(cfun.fcn, *arglist); yield True - result = None - else: result = cfun.fcn(*arglist) - cfun, arglist = oldcfun, oldarglist - if arglist!=None and result==None: - raise logoerror("%s didn't output to %s" % (oldcfun.name, cfun.name)) - ireturn(result); yield True - -def evalinfix(firstarg): - global cfun, arglist - token = iline.pop(0) - oldcfun, oldarglist = cfun, arglist - cfun, arglist = token, [firstarg] - no_args_check() - icall(eval,True); yield True - arglist.append(iresult) - result = cfun.fcn(*arglist) - cfun, arglist = oldcfun, oldarglist - ireturn (result); yield True - -def infixnext(): - if len(iline)==0: return False - if type(iline[0])!=symtype: return False - return iline[0].name in ['+', '-', '*', '/','%','and','or'] - -def undefined_check(token): - if token.fcn != None: return False - raise logoerror("I don't know how to %s" % token.name) - - -def no_args_check(): - if iline and iline[0]!=symnothing : return - raise logoerror("Not enough inputs to %s" % cfun.name) - -def prim_wait(time): - turtle_spr.setlayer(630) - endtime = millis()+an_int(time)*100 - while millis()float(y)) - defprim('less?', 2, lambda x,y: float(x)self.x+self.width: return False - if yself.y+self.height: return False - if isinstance(self.image,gtk.gdk.Pixmap): return True - dx,dy = x-self.x, y-self.y - return ord(self.image.get_pixels()[(dy*self.width+dx)*4+3]) == 255 - - def draw_label1(self, label): - fd = pango.FontDescription('Sans') - fd.set_size(7*pango.SCALE) - pl = window.create_pango_layout(str(label)) - pl.set_font_description(fd) - swidth = pl.get_size()[0]/pango.SCALE - sheight = pl.get_size()[1]/pango.SCALE - centerx = self.x+self.width/2 - centery = self.y+self.height/2 - gc.set_foreground(black) - area.draw_layout(gc,centerx-swidth/2,centery-sheight/2,pl) - - def draw_label2(self, label): - fd = pango.FontDescription('Sans') - fd.set_size(9*pango.SCALE) - pl = window.create_pango_layout(str(label)) - pl.set_font_description(fd) - sheight = pl.get_size()[1]/pango.SCALE - centery = self.y+self.height/2 - gc.set_foreground(black) - area.draw_layout(gc,self.x+50,centery-sheight/2,pl) - - -def findsprite(pos): - list = sprites[:] - list.reverse() - for s in list: - if s.hit(pos): return s - return None - -def redrawsprites(): - for s in sprites: s.draw() - -def getpixel(image,x,y): - array = image.get_pixels() - offset = (y*image.get_width()+x)*4 - r,g,b,a = ord(array[offset]),ord(array[offset+1]),ord(array[offset+2]),ord(array[offset+3]) - return (a<<24)+(b<<16)+(g<<8)+r - -def setspritecontext(w,a,g): - global window,area,gc,black - window=w - area =a - gc = g - black = gc.get_colormap().alloc_color('black') - -def spritelist(): return sprites \ No newline at end of file diff --git a/ta.py b/ta.py deleted file mode 100755 index c7de44a..0000000 --- a/ta.py +++ /dev/null @@ -1,563 +0,0 @@ -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import os -import os.path -import pickle -from math import atan2, pi -import sys - -from sprites import * -from turtlesetup import * -import logo -import turtle - -from sugar.datastore import datastore - -WIDTH=1200 -HEIGHT=780 - -DEGTOR = 2*pi/360 - -gc = None -area = None -window = None -draggroup = None -dragpos = (0,0) -current_category = None -category_spr = None -bgcolor = None -block_operation = None -selected_block = None -select_mask = None -firstkey = False -turtlecanvas = None -status_spr = None -turtle_spr = None -hidden_palette_icon = None -selbuttons = None - -load_save_folder = None -save_file_name = None - -# -# Button Press -# - -def buttonpress_cb(win, event): - global draggroup, dragpos, block_operation, selected_block - window.grab_focus() - block_operation = 'click' - if selected_block!=None: unselect() - status_spr.setlayer(400) - pos = xy(event) - x,y = pos - spr = findsprite(pos) - if spr==None: return True - if spr.type == 'selbutton': - select_category(spr) - elif spr.type == 'tool': - tooldispatch(spr) - elif spr.type == 'category': - block_selector_pressed(x,y) - elif spr.type == 'block': - block_pressed(event,x,y,spr) - elif spr.type == 'turtle': - turtle_pressed(x,y) - return True - -def block_pressed(event,x,y,spr): - global draggroup, dragpos, block_operation - dragpos = x-spr.x,y-spr.y - draggroup = findgroup(spr) - for b in draggroup: - b.setlayer(2000) - disconnect(spr) - -def turtle_pressed(x,y): - global draggroup, dragpos, block_operation - dx,dy = x-turtle_spr.x-30,y-turtle_spr.y-30 - if dx*dx+dy*dy > 200: dragpos = ('turn', turtle.heading-atan2(dy,dx)/DEGTOR,0) - else: dragpos = ('move', x-turtle_spr.x,y-turtle_spr.y) - draggroup = [turtle_spr] - -def block_selector_pressed(x,y): - if category_spr.image==hidden_palette_icon: - for i in selbuttons: i.setlayer(800) - select_category(selbuttons[0]) - else: - proto = get_proto_from_category(x,y) - if proto==None: return - if proto!='hide': new_block_from_category(proto,x,y) - else: - for i in selbuttons: i.hide() - category_spr.setshape(hidden_palette_icon) - - -def new_block_from_category(proto,x,y): - global draggroup, dragpos, block_operation - block_operation = 'new' - if proto == None: return True - newspr = Sprite(x-20,y-20,proto.image) - newspr.setlayer(2000) - dragpos = 20,20 - newspr.type = 'block' - newspr.proto = proto - if newspr.proto.name == 'number': newspr.label=100 - newspr.connections = [None]*len(proto.docks) - for i in range(len(proto.defaults)): - dock = proto.docks[i+1] - numproto = blockproto('number') - numdock = numproto.docks[0] - nx,ny = newspr.x+dock[2]-numdock[2],newspr.y+dock[3]-numdock[3] - argspr = Sprite(nx,ny,numproto.image) - argspr.type = 'block' - argspr.proto = numproto - argspr.label = str(proto.defaults[i]) - argspr.setlayer(2000) - argspr.connections = [newspr,None] - newspr.connections[i+1] = argspr - draggroup = findgroup(newspr) - -def get_proto_from_category(x,y): -# if current_category.mask == None: return current_category.blockprotos[(y-100)/30] - dx,dy = x-category_spr.x, y-category_spr.y, - pixel = getpixel(current_category.mask,dx,dy) - index = ((pixel%256)>>3)-1 -# print hex(pixel),index - if index==0: return 'hide' - index-=1 - if index>len(current_category.blockprotos): return None - return current_category.blockprotos[index] - -def select_category(spr): - global current_category - if current_category != None: - current_category.setshape(current_category.offshape) - spr.setshape(spr.onshape) - current_category = spr - category_spr.setshape(spr.group) - -# -# Mouse move -# - -def move_cb(win, event): - global block_operation - if draggroup == None: return True - block_operation = 'move' - spr = draggroup[0] - x,y = xy(event) - if spr.type=='block': - dragx, dragy = dragpos - dx,dy = x-dragx-spr.x,y-dragy-spr.y - for b in draggroup: - b.move((b.x+dx, b.y+dy)) - elif spr.type=='turtle': - type,dragx,dragy = dragpos - if type == 'move': - dx,dy = x-dragx-spr.x,y-dragy-spr.y - spr.move((spr.x+dx, spr.y+dy)) - else: - dx,dy = x-spr.x-30,y-spr.y-30 - turtle.seth(int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10) - return True - - -# -# Button release -# - -def buttonrelease_cb(win, event): - global draggroup, selected_block,firstkey - if draggroup == None: return True - spr = draggroup[0] - x,y = xy(event) - if spr.type == 'turtle': - turtle.xcor = turtle_spr.x-turtlecanvas.x-turtle.width/2+30 - turtle.ycor = turtle.height/2-turtle_spr.y+turtlecanvas.y-30 - turtle.move_turtle() - draggroup = None - return True - if block_operation=='move' and category_spr.hit((x,y)): - for b in draggroup: b.hide() - draggroup = None - return True - snap_to_dock(draggroup) - for b in draggroup: b.setlayer(650) - draggroup = None - if block_operation=='click': - if spr.proto.name=='number': - selected_block = spr - select_mask.move((spr.x-6,spr.y-6)) - select_mask.setlayer(660) - firstkey = True - else: run_stack(spr) - return True - -def snap_to_dock(group): - d=200 - me = draggroup[0] - for mydockn in range(len(me.proto.docks)): - for you in blocks(): - if you in group: continue - for yourdockn in range(len(you.proto.docks)): - thisxy = dock_dx_dy(you,yourdockn,me,mydockn) - if magnitude(thisxy)>d: continue - d=magnitude(thisxy) - bestxy=thisxy - bestyou=you - bestyourdockn=yourdockn - bestmydockn=mydockn - if d<200: - for b in group: b.move((b.x+bestxy[0],b.y+bestxy[1])) - me.connections[bestmydockn]=bestyou - bestyou.connections[bestyourdockn]=me - -def dock_dx_dy(block1,dock1n,block2,dock2n): - if block1.connections[dock1n] != None: return (100,100) - if block2.connections[dock2n] != None: return (100,100) - dock1 = block1.proto.docks[dock1n] - dock2 = block2.proto.docks[dock2n] - d1type,d1dir,d1x,d1y=dock1[0:4] - d2type,d2dir,d2x,d2y=dock2[0:4] - if block1==block2: return (100,100) - if d1type!=d2type: return (100,100) - if d1dir==d2dir: return (100,100) - return (block1.x+d1x)-(block2.x+d2x),(block1.y+d1y)-(block2.y+d2y) - - -# -# Repaint -# - -def expose_cb(win, event): -# gc.set_foreground(bgcolor) -# area.draw_rectangle(gc, True, category_spr.x, 0, category_spr.width, HEIGHT) -# area.draw_rectangle(gc, True, 100, 100, 100, 100) - - redrawsprites() - return True - - -# -# Keyboard, new, load, save -# - -def keypress_cb(area, event): - global firstkey - keyname = gtk.gdk.keyval_name(event.keyval) -# print keyname - if (event.get_state()>k.gdk.CONTROL_MASK): - if keyname=="s": save_file() - if keyname=="k": clear_journal() - return True - if selected_block==None: return False - keyname = gtk.gdk.keyval_name(event.keyval) - if keyname in ['minus', 'period']: keyname = {'minus': '-', 'period': '.'}[keyname] - if len(keyname)>1: return True - oldnum = selected_block.label - if firstkey: newnum = numcheck(keyname,'0') - else: newnum = oldnum+keyname - selected_block.setlabel(numcheck(newnum,oldnum)) - firstkey = False - return True - -def numcheck(new, old): - if new in ['-', '.', '-.']: return new - if new=='.': return '0.' - try: float(new); return new - except ValueError,e : return old - -def unselect(): - global selected_block - if selected_block.label in ['-', '.', '-.']: select_block.setlabel('0') - select_mask.hide() - selected_block = None - -def new_project(): - global save_file_name - for b in blocks(): b.hide() - turtlecanvas.setlayer(600) - toolsprite('hideshow').setshape(toolsprs['hideshow'].offshape) - turtle.clearscreen() - save_file_name = None - -def load_file(): - '''Pop a load file dialog to allow the user to pick a .ta file to load. Guess that a .png file with the same name resides in the same directory and try to load that too.''' - global save_file_name - fname = get_load_name() - if fname==None: return - if fname[-3:]=='.ta': fname=fname[0:-3] - load_files(fname+'.ta', fname+'.png') - save_file_name = os.path.basename(fname) - -def load_files(ta_file, png_file=''): - '''Load the given TA code file and optional starting image as png file into a new project.''' - f = open(ta_file, "r") - data = pickle.load(f) - f.close() - new_project() - read_data(data) - try: - load_pict(png_file) - except: - '''the picture not loading is OK''' - print "load_files: picture didn't load" - pass - turtlecanvas.inval() - -def get_load_name(): - dialog = gtk.FileChooserDialog("Load...", None, - gtk.FILE_CHOOSER_ACTION_OPEN, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) - return do_dialog(dialog) - -def read_data(data): - blocks = [] - for b in data: - if b[1]=='turtle': load_turtle(b) - else: spr = load_spr(b); blocks.append(spr) - for i in range(len(blocks)): - cons=[] - for c in data[i][4]: - if c==None: cons.append(None) - else: cons.append(blocks[c]) - blocks[i].connections = cons - -def load_spr(b): - btype, label = b[1],None - if type(btype)==type((1,2)): btype, label = btype - proto = blockproto(btype) - spr = Sprite(b[2]+turtlecanvas.x,b[3]+turtlecanvas.y, proto.image) - spr.type = 'block' - spr.proto = proto - if label!=None: spr.label=label - spr.setlayer(650) - return spr - -def load_turtle(b): - id, name, xcor, ycor, heading, color, shade, pensize = b - turtle.setxy(xcor, ycor) - turtle.seth(heading) - turtle.setcolor(color) - turtle.setshade(shade) - turtle.setpensize(pensize) - -def load_pict(fname): - pict = gtk.gdk.pixbuf_new_from_file(fname) - turtlecanvas.image.draw_pixbuf(gc, pict, 0, 0, 0, 0) - -def save_file(): - '''Pop a save file dialog to allow the user to pick a filename to save their project. Also saves the current art as a .png file with the same name.''' - global save_file_name - fname = get_save_name() - if fname==None: return - if fname[-3:]=='.ta': fname=fname[0:-3] - save_data(fname+".ta") - save_pict(fname+".png") - save_file_name = os.path.basename(fname) - -def get_save_name(): - dialog = gtk.FileChooserDialog("Save..", None, - gtk.FILE_CHOOSER_ACTION_SAVE, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE, gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) - if save_file_name!=None: dialog.set_current_name(save_file_name+'.ta') - return do_dialog(dialog) - -def save_data(fname): - '''Writes the TurtleArt code to the given filename.''' - f = file(fname, "w") - bs = blocks() - data = [] - for i in range(len(bs)): bs[i].id=i - for b in bs: - name = b.proto.name - if name=='number': name=(name,b.label) - connections = [get_id(x) for x in b.connections] - data.append((b.id,name,b.x-turtlecanvas.x,b.y-turtlecanvas.y,connections)) - data.append((-1,'turtle', - turtle.xcor,turtle.ycor,turtle.heading, - turtle.color,turtle.shade,turtle.pensize)) - pickle.dump(data,f) - f.close() - -def save_pict(fname): - '''Writes the current art to the given filename.''' - tc = turtlecanvas - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, tc.width, tc.height) - pixbuf.get_from_drawable(tc.image, tc.image.get_colormap(), 0, 0, 0, 0, tc.width, tc.height) - pixbuf.save(fname, 'png') - -def get_id(x): - if x==None: return None - return x.id - -def do_dialog(dialog): - global load_save_folder - result = None - filter = gtk.FileFilter() - filter.add_pattern("*.ta") - filter.set_name("Turtle Art") - dialog.add_filter(filter) - dialog.set_current_folder(load_save_folder) - response = dialog.run() - if response == gtk.RESPONSE_OK: - result = dialog.get_filename() - load_save_folder = dialog.get_current_folder() - dialog.destroy() - return result - -def clear_journal(): - jobjects, total_count = datastore.find({'activity': 'org.laptop.TurtleArtActivity'}) - print 'found', total_count, 'entries' - for jobject in jobjects[:-1]: - print jobject.object_id - datastore.delete(jobject.object_id) - - -# -# Block utilities -# - -def run_stack(spr): - top = find_top_block(spr) - logo.run_blocks(top, blocks()) - gobject.idle_add(logo.doevalstep) - - -def disconnect(b): - if b.connections[0]==None: return - b2=b.connections[0] - b2.connections[b2.connections.index(b)] = None - b.connections[0] = None - - -def findgroup(b): - group=[b] - for b2 in b.connections[1:]: - if b2!=None: group.extend(findgroup(b2)) - return group - -def find_top_block(spr): - while spr.connections[0]!=None: spr=spr.connections[0] - return spr - -def magnitude(pos): - x,y = pos - return x*x+y*y - -def xy(event): return map(int, event.get_coords()) -def blocks(): return [spr for spr in spritelist() if spr.type == 'block'] - - -# -# Toolbar -# - -def tooldispatch(spr): - if spr.blocktype == 'hideshow': hideshow_blocks(spr) - elif spr.blocktype == 'eraser': runtool(spr,turtle.clearscreen) - elif spr.blocktype == 'stopit': logo.step = just_stop() - -def just_stop(): yield False - -def runtool(spr,cmd): - spr.setshape(spr.onshape) - cmd() - gobject.timeout_add(250,spr.setshape,spr.offshape) - -def hideshow_blocks(spr): - if spr.image==spr.offshape: - for b in blocks(): b.setlayer(100) - spr.setshape(spr.onshape) - else: - for b in blocks(): b.setlayer(650) - spr.setshape(spr.offshape) - turtlecanvas.inval() - - -# -# Startup -# - -def init(top_window, path, parentwindow=None): - global gc, area, category_spr, bgcolor,turtlecanvas, select_mask - global status_spr, turtle_spr, selbuttons, hidden_palette_icon - global base_path, load_save_folder, window - window = top_window - base_path = path - if parentwindow is None: - parentwindow = top_window - - # remove any children of the window that Sugar may have added - #for widget in window.get_children(): window.remove(widget) - - #window.set_title("TurteArt") - window.connect("destroy", lambda w: gtk.main_quit()) - window.set_flags(gtk.CAN_FOCUS) - window.set_size_request(WIDTH, HEIGHT) - window.add_events(gtk.gdk.BUTTON_PRESS_MASK) - window.add_events(gtk.gdk.BUTTON_RELEASE_MASK) - window.add_events(gtk.gdk.POINTER_MOTION_MASK) - window.add_events(gtk.gdk.KEY_PRESS_MASK) - window.connect("expose-event", expose_cb) - window.connect("button-press-event", buttonpress_cb) - window.connect("button-release-event", buttonrelease_cb) - window.connect("motion-notify-event", move_cb) - window.connect("key_press_event", keypress_cb) - window.show() - parentwindow.show_all() - area = window.window - cursor_pix = gtk.gdk.pixbuf_new_from_file(os.path.join(base_path, 'arrow.gif')) - cursor = gtk.gdk.Cursor(area.get_display(), cursor_pix, 10, 0) - area.set_cursor(cursor) - gc = area.new_gc() - - setspritecontext(window,area,gc) - cm = gc.get_colormap() - bgcolor = cm.alloc_color('#fff8de') - -# who = Sprite(0,0,gtk.gdk.pixbuf_new_from_file('fullscreen.gif')) -# who.type = 'bg' -# who.setlayer(700) - - - turtlecanvas = Sprite(0,0,gtk.gdk.Pixmap(area,WIDTH,HEIGHT,-1)) - turtlecanvas.type = 'canvas' - turtlecanvas.setlayer(600) - select_mask = Sprite(100,100,gtk.gdk.pixbuf_new_from_file(os.path.join(base_path, 'masknumber.gif'))) - select_mask.type = 'selectmask' - status_spr = Sprite(0,790,gtk.gdk.pixbuf_new_from_file(os.path.join(base_path, 'status.gif')),True) - status_spr.type = 'status' - status_spr.setlayer(400) - turtle.shapelist = [gtk.gdk.pixbuf_new_from_file(os.path.join(base_path, 'shapes','t'+str(i)+'.gif')) - for i in range(36)] - turtle_spr = Sprite(100,100,turtle.shapelist[0]) - turtle_spr.type = 'turtle' - turtle_spr.setlayer(630) - turtle.init(window,turtlecanvas, turtle_spr, bgcolor) - hidden_palette_icon = gtk.gdk.pixbuf_new_from_file(os.path.join(base_path, 'toolbar','blocks-.gif')) - category_spr, selbuttons, default_category = setup_selectors(base_path) -# select_category(default_category) - for i in selbuttons: i.hide() - category_spr.setshape(hidden_palette_icon) - setup_toolbar() - logo.turtle = turtle - logo.turtle_spr = turtle_spr - logo.stopsign = toolsprite('stopit') - logo.status = status_spr - logo.init() - load_save_folder = os.path.join(base_path,'samples') - -def main(): - win = gtk.Window(gtk.WINDOW_TOPLEVEL) - init(win, os.path.abspath('.')) - gtk.main() - return 0 - -if __name__ == "__main__": - main() diff --git a/talogo.py b/talogo.py new file mode 100755 index 0000000..3198608 --- /dev/null +++ b/talogo.py @@ -0,0 +1,342 @@ +import re +from time import clock +from operator import isNumberType +import random +class taLogo: pass + +from taturtle import * + +procstop = False + +class symbol: + + def __init__(self, name): + self.name = name + self.nargs = None + self.fcn = None + + def __str__(self): return self.name + def __repr__(self): return '#'+self.name + +class logoerror(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + + +def run_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)) + code = blocks_to_code(spr) + print code + setup_cmd(lc, code) + +def blocks_to_code(spr): + if spr==None: return ['%nothing%'] + code = [] + dock = spr.proto.docks[0] + if len(dock)>4: code.append(dock[4]) + if spr.proto.primname != '': code.append(spr.proto.primname) + else: code.append(float(spr.label)) + for i in range(1,len(spr.connections)): + b = spr.connections[i] + dock = spr.proto.docks[i] + if len(dock)>4: + for c in dock[4]: code.append(c) + if b!=None: code.extend(blocks_to_code(b)) + elif spr.proto.docks[i][0] not in ['flow','numend','unavailable','logi-']: + code.append('%nothing%') + return code + +def intern(lc, str): + if str in lc.oblist: return lc.oblist[str] + sym = symbol(str) + lc.oblist[str] = sym + return sym + + +def parseline(str): + split = re.split(r"\s|([\[\]()])", str) + return [x for x in split if x and x != ""] + +def readline(lc, line): + res = [] + while line: + token = line.pop(0) + if isNumberType(token): res.append(token) + elif token.isdigit(): res.append(float(token)) + elif token[0]=='-' and token[1:].isdigit(): res.append(-float(token[1:])) + elif token[0] == '"': res.append(token[1:]) + elif token == '[': res.append(readline(lc,line)) + elif token == ']': return res + else: res.append(intern(lc, token)) + return res + + +def setup_cmd(lc, str): + stopsignon(lc); lc.procstop=False + list = readline(lc, str) + lc.step = start_eval(lc, list) + +def start_eval(lc, list): + icall(lc, evline, list); yield True + yield False + +def evline(lc, list): + oldiline = lc.iline + lc.iline = list[:] + lc.arglist = None + while lc.iline: + token = lc.iline[0] + if token==lc.symopar: token=lc.iline[1] + icall(lc, eval); yield True + if lc.procstop: break + if lc.iresult==None: continue + raise logoerror("You don't say what to do with %s" % token) + lc.iline = oldiline + ireturn(lc); yield True + +def eval(lc, infixarg=False): + token = lc.iline.pop(0) + if type(token) == lc.symtype: + icall(lc, evalsym, token); yield True + res = lc.iresult + else: res = token + if not infixarg: + while infixnext(lc): + icall(lc, evalinfix, res); yield True + res = lc.iresult + ireturn(lc, res); yield True + +def evalsym(lc, token): + undefined_check(lc, token) + oldcfun, oldarglist = lc.cfun, lc.arglist + lc.cfun, lc.arglist = token, [] + for i in range(token.nargs): + no_args_check(lc) + icall(lc, eval); yield True + lc.arglist.append(lc.iresult) + if lc.cfun.rprim: + if type(lc.cfun.fcn)==lc.listtype: icall(lc, ufuncall, cfun.fcn); yield True + else: icall(lc, lc.cfun.fcn, *lc.arglist); yield True + result = None + else: result = lc.cfun.fcn(lc, *lc.arglist) + lc.cfun, lc.arglist = oldcfun, oldarglist + if lc.arglist!=None and result==None: + raise logoerror("%s didn't output to %s" % (oldcfun.name, lc.cfun.name)) + ireturn(lc, result); yield True + +def evalinfix(lc, firstarg): + token = lc.iline.pop(0) + oldcfun, oldarglist = lc.cfun, lc.arglist + lc.cfun, lc.arglist = token, [firstarg] + no_args_check(lc) + icall(lc, eval,True); yield True + lc.arglist.append(lc.iresult) + result = lc.cfun.fcn(lc,*lc.arglist) + lc.cfun, lc.arglist = oldcfun, oldarglist + ireturn (lc,result); yield True + +def infixnext(lc): + if len(lc.iline)==0: return False + if type(lc.iline[0])!=lc.symtype: return False + return lc.iline[0].name in ['+', '-', '*', '/','%','and','or'] + +def undefined_check(lc, token): + if token.fcn != None: return False + raise logoerror("I don't know how to %s" % token.name) + + +def no_args_check(lc): + if lc.iline and lc.iline[0]!=lc.symnothing : return + raise logoerror("Not enough inputs to %s" % lc.cfun.name) + +def prim_wait(lc,time): + setlayer(lc.tw.turtle.spr,630) + endtime = millis()+an_int(lc,time)*100 + while millis()float(y)) + defprim(lc,'less?', 2, lambda lc,x,y: float(x)spr.x+spr.width: return False + if yspr.y+spr.height: return False + if isinstance(spr.image,gtk.gdk.Pixmap): return True + dx,dy = x-spr.x, y-spr.y + return ord(spr.image.get_pixels()[(dy*spr.width+dx)*4+3]) == 255 + +def draw_label1(spr, label): + fd = pango.FontDescription('Sans') + fd.set_size(7*pango.SCALE) + pl = spr.tw.window.create_pango_layout(str(label)) + pl.set_font_description(fd) + swidth = pl.get_size()[0]/pango.SCALE + sheight = pl.get_size()[1]/pango.SCALE + centerx = spr.x+spr.width/2 + centery = spr.y+spr.height/2 + spr.tw.gc.set_foreground(spr.tw.textcolor) + spr.tw.area.draw_layout(spr.tw.gc,centerx-swidth/2,centery-sheight/2,pl) + +def draw_label2(spr, label): + fd = pango.FontDescription('Sans') + fd.set_size(9*pango.SCALE) + pl = spr.tw.window.create_pango_layout(str(label)) + pl.set_font_description(fd) + sheight = pl.get_size()[1]/pango.SCALE + centery = spr.y+spr.height/2 + spr.tw.gc.set_foreground(spr.tw.textcolor) + spr.tw.area.draw_layout(spr.tw.gc,spr.x+50,centery-sheight/2,pl) + + +def getpixel(image,x,y): + array = image.get_pixels() + offset = (y*image.get_width()+x)*4 + r,g,b,a = ord(array[offset]),ord(array[offset+1]),ord(array[offset+2]),ord(array[offset+3]) + return (a<<24)+(b<<16)+(g<<8)+r + + diff --git a/tasprites.pyc b/tasprites.pyc new file mode 100755 index 0000000..02a97eb --- /dev/null +++ b/tasprites.pyc Binary files differ diff --git a/taturtle.py b/taturtle.py new file mode 100755 index 0000000..a74940a --- /dev/null +++ b/taturtle.py @@ -0,0 +1,174 @@ +import gtk +from math import sin,cos,pi +class taTurtle: pass + +from tasprites import * +from tasetup import load_image + +colors = {} +DEGTOR = 2*pi/360 + +color_table = ( + 0xFF0000,0xFF0D00,0xFF1A00,0xFF2600,0xFF3300,0xFF4000,0xFF4D00,0xFF5900,0xFF6600,0xFF7300, + 0xFF8000,0xFF8C00,0xFF9900,0xFFA600,0xFFB300,0xFFBF00,0xFFCC00,0xFFD900,0xFFE600,0xFFF200, + 0xFFFF00,0xE6FF00,0xCCFF00,0xB3FF00,0x99FF00,0x80FF00,0x66FF00,0x4DFF00,0x33FF00,0x1AFF00, + 0x00FF00,0x00FF0D,0x00FF1A,0x00FF26,0x00FF33,0x00FF40,0x00FF4D,0x00FF59,0x00FF66,0x00FF73, + 0x00FF80,0x00FF8C,0x00FF99,0x00FFA6,0x00FFB3,0x00FFBF,0x00FFCC,0x00FFD9,0x00FFE6,0x00FFF2, + 0x00FFFF,0x00F2FF,0x00E6FF,0x00D9FF,0x00CCFF,0x00BFFF,0x00B3FF,0x00A6FF,0x0099FF,0x008CFF, + 0x0080FF,0x0073FF,0x0066FF,0x0059FF,0x004DFF,0x0040FF,0x0033FF,0x0026FF,0x001AFF,0x000DFF, + 0x0000FF,0x0D00FF,0x1A00FF,0x2600FF,0x3300FF,0x4000FF,0x4D00FF,0x5900FF,0x6600FF,0x7300FF, + 0x8000FF,0x8C00FF,0x9900FF,0xA600FF,0xB300FF,0xBF00FF,0xCC00FF,0xD900FF,0xE600FF,0xF200FF, + 0xFF00FF,0xFF00E6,0xFF00CC,0xFF00B3,0xFF0099,0xFF0080,0xFF0066,0xFF004D,0xFF0033,0xFF001A) + +def tNew(tw,w,h): + t = taTurtle() + t.tw, t.width, t.height = tw, w, h + t.canvas = sprNew(tw,0,0,gtk.gdk.Pixmap(tw.area,w,h,-1)) + t.canvas.type = 'canvas' + setlayer(t.canvas,600) + t.shapelist = [load_image(tw.path, 'shapes','t'+str(i)) for i in range(36)] + t.spr = sprNew(tw,100,100,t.shapelist[0]) + t.spr.type = 'turtle' + setlayer(t.spr, 630) + t.gc = t.canvas.image.new_gc() + t.shade = 0 + clearscreen(t) + return t + +def clearscreen(t): + t.xcor, t.ycor, t.heading = 0,0,0 + rect = gtk.gdk.Rectangle(0,0,t.width,t.height) + t.gc.set_foreground(t.tw.bgcolor) + t.canvas.image.draw_rectangle(t.gc, True, *rect) + invalt(t,0,0,t.width,t.height) + setpensize(t,5) + setcolor(t,0) + setshade(t,50) + t.pendown = True + move_turtle(t) + turn_turtle(t) + return None + +def forward(t, n): + t.gc.set_foreground(t.fgcolor) + oldx, oldy = t.xcor, t.ycor + t.xcor += n*sin(t.heading*DEGTOR) + t.ycor += n*cos(t.heading*DEGTOR) + if t.pendown: draw_line(t,oldx,oldy,t.xcor,t.ycor) + move_turtle(t) + return None + +def seth(t,n): + t.heading=n + t.heading%=360 + turn_turtle(t) + return None + +def right(t,n): + t.heading+=n + t.heading%=360 + turn_turtle(t) + return None + +def arc(t,a,r): + t.gc.set_foreground(t.fgcolor) + if a<0: larc(t,-a,r) + else: rarc(t,a,r) + move_turtle(t) + turn_turtle(t) + +def rarc(t,a,r): + if r<0: r=-r; a=-a + cx = t.xcor+r*cos(t.heading*DEGTOR) + cy = t.ycor-r*sin(t.heading*DEGTOR) + x,y,w,h=t.width/2+int(cx-r),t.height/2-int(cy+r),int(2*r),int(2*r) + t.canvas.image.draw_arc(t.gc,False,x,y,w,h,int(180-t.heading-a)*64,int(a)*64) + invalt(t,x-t.pensize/2-3,y-t.pensize/2-3,w+t.pensize+6,h+t.pensize+6) + right(t,a) + t.xcor=cx-r*cos(t.heading*DEGTOR) + t.ycor=cy+r*sin(t.heading*DEGTOR) + +def larc(t,a,r): + if r<0: r=-r; a=-a + cx = t.xcor-r*cos(t.heading*DEGTOR) + cy = t.ycor+r*sin(t.heading*DEGTOR) + x,y,w,h=t.width/2+int(cx-r),t.height/2-int(cy+r),int(2*r),int(2*r) + t.canvas.image.draw_arc(t.gc,False,x,y,w,h,int(360-t.heading)*64,int(a)*64) + invalt(t,x-t.pensize/2-3,y-t.pensize/2-3,w+t.pensize+6,h+t.pensize+6) + right(t,-a) + t.xcor=cx+r*cos(t.heading*DEGTOR) + t.ycor=cy-r*sin(t.heading*DEGTOR) + +def setxy(t,x,y): + t.xcor,t.ycor = x,y + move_turtle(t) + +def setpensize(t,ps): + t.pensize = ps + t.gc.set_line_attributes(int(t.pensize),gtk.gdk.LINE_SOLID,gtk.gdk.CAP_ROUND,gtk.gdk.JOIN_MITER) + return None + +def setcolor(t,c): + t.color = c + set_fgcolor(t) + return None + +def setshade(t,s): + t.shade = s + set_fgcolor(t) + return None + +def fillscreen(t,c,s): + oldc, olds = t.color,t.shade + setcolor(t,c); setshade(t,s) + rect = gtk.gdk.Rectangle(0,0,t.width,t.height) + t.gc.set_foreground(t.fgcolor) + t.canvas.image.draw_rectangle(t.gc, True, *rect) + invalt(t,0,0,t.width,t.height) + setcolor(t,oldc); setshade(t,olds) + return None + +def set_fgcolor(t): + sh = (wrap100(t.shade)-50)/50.0 + rgb = color_table[wrap100(t.color)] + r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 + r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) + t.fgcolor = t.tw.cm.alloc_color(r,g,b) + +def wrap100(n): + n = int(n) + n %= 200 + if n>99: n=199-n + return n + +def calc_shade(c,s): + if s<0: return int(c*(1+s*.8)) + return int(c+(65536-c)*s*.9) + +def setpen(t,bool): + t.pendown = bool + +def draw_line(t,x1,y1,x2,y2): + x1,y1 = t.width/2+int(x1), t.height/2-int(y1) + x2,y2 = t.width/2+int(x2), t.height/2-int(y2) + if x1>3)-1 + if index==0: return 'hide' + index-=1 + if index>len(tw.current_category.blockprotos): return None + return tw.current_category.blockprotos[index] + +def select_category(tw, spr): + if hasattr(tw, 'current_category'): + setshape(tw.current_category, tw.current_category.offshape) + setshape(spr, spr.onshape) + tw.current_category = spr + setshape(tw.category_spr,spr.group) + +def new_block_from_category(tw,proto,x,y): + tw.block_operation = 'new' + if proto == None: return True + newspr = sprNew(tw,x-20,y-20,proto.image) + setlayer(newspr,2000) + tw.dragpos = 20,20 + newspr.type = 'block' + newspr.proto = proto + if newspr.proto.name == 'number': newspr.label=100 + newspr.connections = [None]*len(proto.docks) + for i in range(len(proto.defaults)): + dock = proto.docks[i+1] + numproto = tw.protodict['number'] + numdock = numproto.docks[0] + nx,ny = newspr.x+dock[2]-numdock[2],newspr.y+dock[3]-numdock[3] + argspr = sprNew(tw,nx,ny,numproto.image) + argspr.type = 'block' + argspr.proto = numproto + argspr.label = str(proto.defaults[i]) + setlayer(argspr,2000) + argspr.connections = [newspr,None] + newspr.connections[i+1] = argspr + tw.draggroup = findgroup(newspr) + +def block_pressed(tw,event,x,y,spr): + if event.get_state()>k.gdk.CONTROL_MASK: + newspr = clone_stack(tw,x-spr.x-20,y-spr.y-20, spr) + tw.dragpos = x-newspr.x,y-newspr.y + tw.draggroup = findgroup(newspr) + else: + tw.dragpos = x-spr.x,y-spr.y + tw.draggroup = findgroup(spr) + for b in tw.draggroup: setlayer(b,2000) + disconnect(spr) + +def clone_stack(tw,dx,dy,spr): + newspr = sprNew(tw,spr.x+dx,spr.y+dy,spr.proto.image) + newspr.type = spr.type + newspr.proto = spr.proto + newspr.label = spr.label + newspr.connections = [None]*len(spr.proto.docks) + for i in range(1,len(spr.connections)): + if(spr.connections[i]==None): continue + clonearg=clone_stack(tw,dx,dy,spr.connections[i]) + newspr.connections[i]=clonearg + clonearg.connections[0]=newspr + setlayer(newspr,2000) + return newspr + +def turtle_pressed(tw,x,y): + dx,dy = x-tw.turtle.spr.x-30,y-tw.turtle.spr.y-30 + if dx*dx+dy*dy > 200: tw.dragpos = ('turn', tw.turtle.heading-atan2(dy,dx)/DEGTOR,0) + else: tw.dragpos = ('move', x-tw.turtle.spr.x,y-tw.turtle.spr.y) + tw.draggroup = [tw.turtle.spr] + + +# +# Mouse move +# + +def move_cb(win, event, tw): + if tw.draggroup == None: return True + tw.block_operation = 'move' + spr = tw.draggroup[0] + x,y = xy(event) + if spr.type=='block': + dragx, dragy = tw.dragpos + dx,dy = x-dragx-spr.x,y-dragy-spr.y + for b in tw.draggroup: + move(b,(b.x+dx, b.y+dy)) + elif spr.type=='turtle': + type,dragx,dragy = tw.dragpos + if type == 'move': + dx,dy = x-dragx-spr.x,y-dragy-spr.y + move(spr, (spr.x+dx, spr.y+dy)) + else: + dx,dy = x-spr.x-30,y-spr.y-30 + seth(tw.turtle, int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10) + return True + + +# +# Button release +# + +def buttonrelease_cb(win, event, tw): + if tw.draggroup == None: return True + spr = tw.draggroup[0] + x,y = xy(event) + if spr.type == 'turtle': + tw.turtle.xcor = tw.turtle.spr.x-tw.turtle.canvas.x-tw.turtle.canvas.width/2+30 + tw.turtle.ycor = tw.turtle.canvas.height/2-tw.turtle.spr.y+tw.turtle.canvas.y-30 + move_turtle(tw.turtle) + tw.draggroup = None + return True + if tw.block_operation=='move' and hit(tw.category_spr, (x,y)): + for b in tw.draggroup: hide(b) + tw.draggroup = None + return True + snap_to_dock(tw) + for b in tw.draggroup: setlayer(b,650) + tw.draggroup = None + if tw.block_operation=='click': + if spr.proto.name=='number': + tw.selected_block = spr + move(tw.select_mask, (spr.x-6,spr.y-6)) + setlayer(tw.select_mask, 660) + tw.firstkey = True + else: run_stack(tw, spr) + return True + +def snap_to_dock(tw): + d=200 + me = tw.draggroup[0] + for mydockn in range(len(me.proto.docks)): + for you in blocks(tw): + if you in tw.draggroup: continue + for yourdockn in range(len(you.proto.docks)): + thisxy = dock_dx_dy(you,yourdockn,me,mydockn) + if magnitude(thisxy)>d: continue + d=magnitude(thisxy) + bestxy=thisxy + bestyou=you + bestyourdockn=yourdockn + bestmydockn=mydockn + if d<200: + for b in tw.draggroup: move(b,(b.x+bestxy[0],b.y+bestxy[1])) + blockindock=bestyou.connections[bestyourdockn] + if blockindock!=None: + for b in findgroup(blockindock): hide(b) + bestyou.connections[bestyourdockn]=me + me.connections[bestmydockn]=bestyou + +def dock_dx_dy(block1,dock1n,block2,dock2n): + dock1 = block1.proto.docks[dock1n] + dock2 = block2.proto.docks[dock2n] + d1type,d1dir,d1x,d1y=dock1[0:4] + d2type,d2dir,d2x,d2y=dock2[0:4] + if (d2type!='num') or (dock2n!=0): + if block1.connections[dock1n] != None: return (100,100) + if block2.connections[dock2n] != None: return (100,100) + if block1==block2: return (100,100) + if d1type!=d2type: return (100,100) + if d1dir==d2dir: return (100,100) + return (block1.x+d1x)-(block2.x+d2x),(block1.y+d1y)-(block2.y+d2y) + +def magnitude(pos): + x,y = pos + return x*x+y*y + + +# +# Repaint +# + +def expose_cb(win, event, tw): +# tw.gc.set_foreground(tw.bgcolor) +# tw.area.draw_rectangle(tw.gc, True, 0, 0, WIDTH, HEIGHT) + redrawsprites(tw) + return True + + +# +# Keyboard +# + +def keypress_cb(area, event,tw): + keyname = gtk.gdk.keyval_name(event.keyval) +# print keyname + if (event.get_state()>k.gdk.CONTROL_MASK): + if keyname=="n": new_project(tw) + if keyname=="o": load_file(tw) + if keyname=="s": save_file(tw) + if keyname=="k": tw.activity.clear_journal() + return True + if tw.selected_block==None: return False + keyname = gtk.gdk.keyval_name(event.keyval) + if keyname in ['minus', 'period']: keyname = {'minus': '-', 'period': '.'}[keyname] + if len(keyname)>1: return True + oldnum = tw.selected_block.label + if tw.firstkey: newnum = numcheck(keyname,'0') + else: newnum = oldnum+keyname + setlabel(tw.selected_block, numcheck(newnum,oldnum)) + tw.firstkey = False + return True + +def numcheck(new, old): + if new in ['-', '.', '-.']: return new + if new=='.': return '0.' + try: float(new); return new + except ValueError,e : return old + +def unselect(tw): + if tw.selected_block.label in ['-', '.', '-.']: select_block.setlabel('0') + hide(tw.select_mask) + tw.selected_block = None + + +# +# Block utilities +# + +def disconnect(b): + if b.connections[0]==None: return + b2=b.connections[0] + b2.connections[b2.connections.index(b)] = None + b.connections[0] = None + +def run_stack(tw,spr): + top = find_top_block(spr) + run_blocks(tw.lc, top, blocks(tw)) + gobject.idle_add(doevalstep, tw.lc) + +def findgroup(b): + group=[b] + for b2 in b.connections[1:]: + if b2!=None: group.extend(findgroup(b2)) + return group + +def find_top_block(spr): + while spr.connections[0]!=None: spr=spr.connections[0] + return spr + + +def tooldispatch(tw, spr): + if spr.blocktype == 'hideshow': hideshow_blocks(tw,spr) + elif spr.blocktype == 'eraser': runtool(tw, spr, clearscreen, tw.turtle) + elif spr.blocktype == 'stopit': stop_logo(tw) + +def runtool(tw, spr, cmd, *args): + setshape(spr,spr.onshape) + cmd(*(args)) + gobject.timeout_add(250,setshape,spr,spr.offshape) + +def hideshow_blocks(tw,spr): + if spr.image==spr.offshape: + for b in blocks(tw): setlayer(b,100) + setshape(spr,spr.onshape) + else: + for b in blocks(tw): setlayer(b,650) + setshape(spr,spr.offshape) + inval(tw.turtle.canvas) + + +def blocks(tw): return [spr for spr in tw.sprites if spr.type == 'block'] +def xy(event): return map(int, event.get_coords()) + diff --git a/tawindow.pyc b/tawindow.pyc new file mode 100755 index 0000000..b18d858 --- /dev/null +++ b/tawindow.pyc Binary files differ diff --git a/toolbar/project-.gif b/toolbar/project-.gif deleted file mode 100755 index 4050808..0000000 --- a/toolbar/project-.gif +++ /dev/null Binary files differ diff --git a/toolbar/project.gif b/toolbar/project.gif deleted file mode 100755 index ff0fe4f..0000000 --- a/toolbar/project.gif +++ /dev/null Binary files differ diff --git a/toolbar/projectmask.gif b/toolbar/projectmask.gif deleted file mode 100755 index 8092284..0000000 --- a/toolbar/projectmask.gif +++ /dev/null Binary files differ diff --git a/turtle.py b/turtle.py deleted file mode 100755 index dc1b0b6..0000000 --- a/turtle.py +++ /dev/null @@ -1,195 +0,0 @@ -import gtk -from math import sin,cos,pi - -colors = {} -buffer = None -gc = None -window = None -width = 0 -height = 0 -sprite = None -cm = None -bgcolor = None -fgcolor = None -color = 0 -shade = 50 -pensize = 5 -pendown = True -turtle = None - -DEGTOR = 2*pi/360 - -xcor = 0 -ycor = 0 -heading = 0 - -color_table = ( - 0xFF0000,0xFF0D00,0xFF1A00,0xFF2600,0xFF3300,0xFF4000,0xFF4D00,0xFF5900,0xFF6600,0xFF7300, - 0xFF8000,0xFF8C00,0xFF9900,0xFFA600,0xFFB300,0xFFBF00,0xFFCC00,0xFFD900,0xFFE600,0xFFF200, - 0xFFFF00,0xE6FF00,0xCCFF00,0xB3FF00,0x99FF00,0x80FF00,0x66FF00,0x4DFF00,0x33FF00,0x1AFF00, - 0x00FF00,0x00FF0D,0x00FF1A,0x00FF26,0x00FF33,0x00FF40,0x00FF4D,0x00FF59,0x00FF66,0x00FF73, - 0x00FF80,0x00FF8C,0x00FF99,0x00FFA6,0x00FFB3,0x00FFBF,0x00FFCC,0x00FFD9,0x00FFE6,0x00FFF2, - 0x00FFFF,0x00F2FF,0x00E6FF,0x00D9FF,0x00CCFF,0x00BFFF,0x00B3FF,0x00A6FF,0x0099FF,0x008CFF, - 0x0080FF,0x0073FF,0x0066FF,0x0059FF,0x004DFF,0x0040FF,0x0033FF,0x0026FF,0x001AFF,0x000DFF, - 0x0000FF,0x0D00FF,0x1A00FF,0x2600FF,0x3300FF,0x4000FF,0x4D00FF,0x5900FF,0x6600FF,0x7300FF, - 0x8000FF,0x8C00FF,0x9900FF,0xA600FF,0xB300FF,0xBF00FF,0xCC00FF,0xD900FF,0xE600FF,0xF200FF, - 0xFF00FF,0xFF00E6,0xFF00CC,0xFF00B3,0xFF0099,0xFF0080,0xFF0066,0xFF004D,0xFF0033,0xFF001A) - -def init(win, spr, tspr, bg): - global buffer, gc, window, sprite, width, height, bgcolor, fgcolor, cm, turtle - window, sprite, buffer, turtle, bgcolor = win.window, spr, spr.image, tspr, bg - width, height = buffer.get_size() - gc = win.window.new_gc() - cm = gc.get_colormap() - gc = buffer.new_gc() - clearscreen() - -def clearscreen(): - global xcor,ycor,heading, pendown - xcor, ycor, heading = 0,0,0 - rect = gtk.gdk.Rectangle(0,0,width,height) - gc.set_foreground(bgcolor) - buffer.draw_rectangle(gc, True, *rect) - inval(0,0,width,height) - setpensize(5) - setcolor(0) - setshade(50) - pendown = True - move_turtle() - turn_turtle() - return None - -def forward(n): - global xcor,ycor - gc.set_foreground(fgcolor) - oldx, oldy = xcor, ycor - xcor += n*sin(heading*DEGTOR) - ycor += n*cos(heading*DEGTOR) - if pendown: draw_line(oldx,oldy,xcor,ycor) - move_turtle() - return None - -def seth(n): - global heading - heading=n - heading%=360 - turn_turtle() - return None - -def right(n): - global heading - heading+=n - heading%=360 - turn_turtle() - return None - -def arc(a,r): - gc.set_foreground(fgcolor) - if a<0: larc(-a,r) - else: rarc(a,r) - move_turtle() - turn_turtle() - -def rarc(a,r): - global xcor,ycor - if r<0: r=-r; a=-a - cx = xcor+r*cos(heading*DEGTOR) - cy = ycor-r*sin(heading*DEGTOR) - x,y,w,h=width/2+int(cx-r),height/2-int(cy+r),int(2*r),int(2*r) - buffer.draw_arc(gc,False,x,y,w,h,int(180-heading-a)*64,int(a)*64) - inval(x-pensize/2-3,y-pensize/2-3,w+pensize+6,h+pensize+6) - right(a) - xcor=cx-r*cos(heading*DEGTOR) - ycor=cy+r*sin(heading*DEGTOR) - -def larc(a,r): - global xcor,ycor - if r<0: r=-r; a=-a - cx = xcor-r*cos(heading*DEGTOR) - cy = ycor+r*sin(heading*DEGTOR) - x,y,w,h=width/2+int(cx-r),height/2-int(cy+r),int(2*r),int(2*r) - buffer.draw_arc(gc,False,x,y,w,h,int(360-heading)*64,int(a)*64) - inval(x-pensize/2-3,y-pensize/2-3,w+pensize+6,h+pensize+6) - right(-a) - xcor=cx+r*cos(heading*DEGTOR) - ycor=cy-r*sin(heading*DEGTOR) - -def setxy(x,y): - global xcor,ycor - xcor,ycor = x,y - move_turtle() - -def setpensize(ps): - global pensize - pensize = ps - gc.set_line_attributes(int(pensize),gtk.gdk.LINE_SOLID,gtk.gdk.CAP_ROUND,gtk.gdk.JOIN_MITER) - return None - -def setcolor(c): - global color - color = c - set_fgcolor() - return None - -def setshade(s): - global shade - shade = s - set_fgcolor() - return None - -def fillscreen(c,s): - oldc, olds = color,shade - setcolor(c); setshade(s) - rect = gtk.gdk.Rectangle(0,0,width,height) - gc.set_foreground(fgcolor) - buffer.draw_rectangle(gc, True, *rect) - inval(0,0,width,height) - setcolor(oldc); setshade(olds) - return None - -def set_fgcolor(): - global fgcolor - sh = (wrap100(shade)-50)/50.0 - rgb = color_table[wrap100(color)] - r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 - r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) - fgcolor = cm.alloc_color(r,g,b) - -def wrap100(n): - n = int(n) - n %= 200 - if n>99: n=199-n - return n - -def calc_shade(c,s): - if s<0: return int(c*(1+s*.8)) - return int(c+(65536-c)*s*.9) - -def setpen(bool): - global pendown - pendown = bool - -def draw_line(x1,y1,x2,y2): - x1,y1 = width/2+int(x1), height/2-int(y1) - x2,y2 = width/2+int(x2), height/2-int(y2) - if x1