Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrafael <rafael@rafael.dirakx>2010-02-19 20:40:56 (GMT)
committer rafael <rafael@rafael.dirakx>2010-02-19 20:40:56 (GMT)
commit11fc91a50249436c39fee3e12d73528ab80f3ab3 (patch)
tree9f91cb4810d645936b26157b019df5ea392dcd3f
parent408aa90d52bda7f126e395f5a0c9ec191878becc (diff)
Adding arduino modificationsHEADmaster
-rw-r--r--taarduino.py50
-rw-r--r--talogo.py2227
-rw-r--r--tawindow.py3343
3 files changed, 1910 insertions, 3710 deletions
diff --git a/taarduino.py b/taarduino.py
new file mode 100644
index 0000000..f6b6474
--- /dev/null
+++ b/taarduino.py
@@ -0,0 +1,50 @@
+import firmata
+
+class TAArduino(object):
+ def __init__(self, dev='/dev/ttyUSB0', baud=115200):
+ object.__init__(self)
+ self._dev = dev
+ self._baud = baud
+ self._arduino = None # Do not initialize this now
+
+ self.HIGH = firmata.HIGH
+ self.LOW = firmata.LOW
+ self.INPUT = firmata.INPUT
+ self.OUTPUT = firmata.OUTPUT
+ self.PWM = firmata.PWM
+ self.SERVO = firmata.SERVO
+
+ def _check_init(self):
+ if self._arduino is None:
+ self._arduino = firmata.Arduino(port = self._dev, \
+ baudrate=self._baud)
+ self._arduino.parse()
+
+ def delay(self, secs):
+ # Do not use this. The firmata module uses time.sleep() to
+ # implement this, which breaks gtk+ (unresponsive window)
+ self._check_init()
+ self._arduino.delay(secs)
+
+ def pin_mode(self, pin, mode):
+ self._check_init()
+ self._arduino.pin_mode(int(pin), mode)
+
+ def analog_write(self, pin, value):
+ self._check_init()
+ self._arduino.analog_write(int(pin), int(value))
+
+ def digital_write(self, pin, value):
+ self._check_init()
+ self._arduino.digital_write(int(pin), value)
+
+ def analog_read(self, pin):
+ self._check_init()
+ self._arduino.parse() #XXX: Not sure why I have to do this here.
+ return self._arduino.analog_read(int(pin))
+
+ def digital_read(self, pin):
+ self._check_init()
+ return self._arduino.digital_read(int(pin))
+
+
diff --git a/talogo.py b/talogo.py
index 64177a8..3275ce3 100644
--- a/talogo.py
+++ b/talogo.py
@@ -1,7 +1,5 @@
-# -*- coding: utf-8 -*-
#Copyright (c) 2007-8, Playful Invention Company.
-#Copyright (c) 2008-10, Walter Bender
-#Copyright (c) 2008-10, Raúl Gutiérrez Segalés
+#Copyright (c) 2008-9, Walter Bender
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
@@ -21,13 +19,13 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
-import gtk
+import re
+from time import *
import gobject
-from time import clock
-from math import sqrt
-from random import uniform
from operator import isNumberType
+import random
import audioop
+from math import *
import subprocess
from UserDict import UserDict
try:
@@ -35,26 +33,27 @@ try:
except:
pass
-from taconstants import PALETTES, PALETTE_NAMES, BOX_STYLE
-from tagplay import play_audio, play_movie_from_file, stop_media
-from tajail import myfunc, myfunc_import
-from tautils import get_pixbuf_from_journal, movie_media_type,\
- audio_media_type, round_int
-from gettext import gettext as _
-
class noKeyError(UserDict):
__missing__=lambda x,y: 0
+class taLogo: pass
+
+from taturtle import *
+from tagplay import *
+from tajail import *
+
+from gettext import gettext as _
+
+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
+ def __str__(self): return self.name
+ def __repr__(self): return '#'+self.name
class logoerror(Exception):
def __init__(self, value):
@@ -62,1244 +61,1050 @@ class logoerror(Exception):
def __str__(self):
return repr(self.value)
-"""
-Utility functions
-"""
-
-'''
-The strategy for mixing numbers and strings is to first try
-converting the string to a float; then if the string is a single
-character, try converting it to an ord; finally, just treat it as a
-string. Numbers appended to strings are first trreated as ints, then
-floats.
-'''
-def convert(x, fn, try_ord=True):
- try:
- return fn(x)
- except ValueError:
- if try_ord:
- xx, flag = chr_to_ord(x)
- if flag:
- return fn(xx)
- return x
-
-def numtype(x):
- if type(x) == int:
- return True
- if type(x) == float:
- return True
- if type(x) == ord:
- return True
- return False
-
-def strtype(x):
- if type(x) == str:
- return True
- if type(x) == unicode:
- return True
- return False
-
-def str_to_num(x):
- xx = convert(x, float)
- if type(xx) is float:
- return xx
+def run_blocks(lc, spr, blocks, run_flag):
+ # user-defined stacks
+ for x in lc.stacks.keys():
+ lc.stacks[x]= None
+ # two built-in stacks
+ 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(lc,i))
+ if i.proto.name=='hat2':
+ lc.stacks['stack2']= readline(lc,blocks_to_code(lc,i))
+ if i.proto.name=='hat':
+ if (i.connections[1]!=None):
+ text=i.connections[1].label
+ lc.stacks['stack3'+text]= readline(lc,blocks_to_code(lc,i))
+ code = blocks_to_code(lc,spr)
+ if run_flag == True:
+ print code
+ setup_cmd(lc, code)
+ else: return code
+
+def blocks_to_code(lc,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:
- xx, xflag = chr_to_ord(x)
- if xflag:
- return xx
+ if spr.proto.name=='number':
+ try:
+ code.append(float(spr.label))
+ except:
+ code.append(float(ord(spr.label[0])))
+ elif spr.proto.name=='string' or spr.proto.name=='title':
+ if type(spr.label) == float or type(spr.label) == int:
+ if int(spr.label) == spr.label:
+ spr.label = int(spr.label)
+ code.append('#s'+str(spr.label))
+ else:
+ code.append('#s'+spr.label)
+ elif spr.proto.name=='journal':
+ if spr.ds_id != None:
+ code.append('#smedia_'+str(spr.ds_id))
+ else:
+ code.append('#smedia_None')
+ elif spr.proto.name=='descriptionoff' or \
+ spr.proto.name=='descriptionon':
+ if spr.ds_id != None:
+ code.append('#sdescr_'+str(spr.ds_id))
+ else:
+ code.append('#sdescr_None')
+ elif spr.proto.name=='audiooff' or spr.proto.name=='audio':
+ if spr.ds_id != None:
+ code.append('#saudio_'+str(spr.ds_id))
+ else:
+ code.append('#saudio_None')
else:
- raise logoerror("#syntaxerror")
-
-def chr_to_ord(x):
- if strtype(x) and len(x) == 1:
- try:
- return ord(x[0]), True
- except ValueError:
- return x, False
- return x, False
-
-def taand(x, y):
- return x&y
-
-def taor(x, y):
- return x|y
+ return ['%nothing%']
+ 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(lc,b))
+ elif spr.proto.docks[i][0] not in \
+ ['flow', 'numend', 'stringend', 'mediaend', \
+ 'audioend', '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[0:2] == "#s": res.append(token[2:])
+ elif token == '[': res.append(readline(lc,line))
+ elif token == ']': return res
+ else: res.append(intern(lc, token))
+ return res
+
+def setup_cmd(lc, str):
+ setlayer(lc.tw.turtle.spr,100)
+ lc.procstop=False
+ list = readline(lc, str)
+ lc.step = start_eval(lc, list)
+
+def start_eval(lc, list):
+ icall(lc, evline, list); yield True
+ # turn off stop icon when execution is finished
+ if hasattr(lc.tw,"activity"):
+ lc.tw.activity.stop_button.set_icon("stopitoff")
+ yield False
-def careful_divide(x, y):
+def evline(lc, list):
+ oldiline = lc.iline
+ lc.iline = list[:]
+ lc.arglist = None
+ while lc.iline:
+ if lc.tw.step_time > 0:
+ setlayer(lc.tw.turtle.spr,630)
+ endtime = millis()+an_int(lc,lc.tw.step_time)*100
+ while millis()<endtime:
+ yield True
+ setlayer(lc.tw.turtle.spr,100)
+ 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(str(lc.iresult))
+ lc.iline = oldiline
+ ireturn(lc)
+ display_coordinates(lc.tw)
+ 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):
+ debug_trace(lc, token)
+ undefined_check(lc, token)
+ oldcfun, oldarglist = lc.cfun, lc.arglist
+ lc.cfun, lc.arglist = token, []
+ if token.nargs==None: raise logoerror("#noinput")
+ 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 debug_trace(lc, token):
+ if lc.trace:
+ if token.name in ['forward', 'right', 'back', 'left', 'seth', 'setxy', \
+ 'arc', 'heading', 'xcor', 'ycor']:
+ my_string = token.name +\
+ "\nxcor= " + str(int(lc.tw.turtle.xcor)) +\
+ "\nycor= " + str(int(lc.tw.turtle.ycor)) +\
+ "\nheading= " + str(int(lc.tw.turtle.heading)) +\
+ "\nscale= " + str(lc.scale)
+ elif token.name in ['penup', 'pendown', 'setcolor', 'setshade', \
+ 'settextcolor', 'settextsize', 'shade', 'color', \
+ 'fillscreen', 'pensize']:
+ if lc.tw.turtle.pendown:
+ penstatus = "\npen down"
+ else:
+ penstatus = "\npen up"
+ my_string = token.name + penstatus +\
+ "\ncolor= " + str(int(lc.tw.turtle.color)) +\
+ "\nshade= " + str(lc.tw.turtle.shade) +\
+ "\npen size= " + str(lc.tw.turtle.pensize)
+ else:
+ my_string = token.name + "\nblocks status:\n"
+ for k,v in lc.boxes.iteritems():
+ tmp = k +":" + str(v) + "\n"
+ my_string += tmp
+ shp = 'info'
+ setshape(lc.tw.status_spr, lc.tw.status_shapes[shp])
+ setlabel(lc.tw.status_spr, _(my_string))
+ setlayer(lc.tw.status_spr, 710)
+ return
+
+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("#noinput")
+
+def prim_wait(lc,time):
+ setlayer(lc.tw.turtle.spr,630)
+ endtime = millis()+an_int(lc,time*1000)
+ while millis()<endtime:
+ yield True
+ setlayer(lc.tw.turtle.spr,100)
+ ireturn(lc); yield True
+
+def prim_repeat(lc, num, list):
+ num = an_int(lc, num)
+ for i in range(num):
+ icall(lc, evline, list[:]); yield True
+ if lc.procstop: break
+ ireturn(lc); yield True
+
+def prim_forever(lc, list):
+ while True:
+ icall(lc,evline, list[:]); yield True
+ if lc.procstop: break
+ ireturn(lc); yield True
+
+def prim_if(lc, bool, list):
+ if bool: icall(lc, evline, list[:]); yield True
+ ireturn(lc); yield True
+
+def prim_ifelse(lc, bool, list1,list2):
+ if bool: ijmp(lc, evline, list1[:]); yield True
+ else: ijmp(lc, evline, list2[:]); yield True
+
+def prim_opar(lc,val):
+ lc.iline.pop(0)
+ return val
+
+def prim_define(name, body):
+ if type(name) != symtype: name = intern(name)
+ name.nargs, name.fcn = 0, body
+ name.rprim = True
+
+def prim_stack(lc,stri):
+ if (not lc.stacks.has_key('stack3'+stri)) or \
+ lc.stacks['stack3'+stri]==None: raise logoerror("#nostack")
+ icall(lc, evline, lc.stacks['stack3'+stri][:]); yield True
+ lc.procstop = False
+ ireturn(lc); yield True
+
+def prim_stack1(lc):
+ if lc.stacks['stack1']==None: raise logoerror("#nostack")
+ icall(lc, evline, lc.stacks['stack1'][:]); yield True
+ lc.procstop = False
+ ireturn(lc); yield True
+
+def prim_stack2(lc):
+ if lc.stacks['stack2']==None: raise logoerror("#nostack")
+ icall(lc, evline, lc.stacks['stack2'][:]); yield True
+ lc.procstop = False
+ ireturn(lc); yield True
+
+def prim_stopstack(lc):
+ lc.procstop = True
+
+def careful_divide(x,y):
try:
+ if y==0: return 0
return x/y
- except ZeroDivisionError:
- raise logoerror("#zerodivide")
- except TypeError:
- try:
- return str_to_num(x) / str_to_num(y)
- except ZeroDivisionError:
- raise logoerror("#zerodivide")
- except ValueError:
- raise logoerror("#syntaxerror")
+ except:
+ return 0
+
+def ufuncall(body):
+ ijmp(evline, body); yield True
+
+def an_int(lc, n):
+ if type(n) == int:
+ return n
+ elif type(n) == float:
+ return int(n)
+ elif type(n) == str:
+ return int(ord(n[0]))
+ else:
+ raise logoerror("%s doesn't like %s as input" \
+ % (lc.cfun.name, str(n)))
-def taequal(x, y):
+def defprim(lc, name, args, fcn, rprim=False):
+ sym = intern(lc, name)
+ sym.nargs, sym.fcn = args,fcn
+ sym.rprim = rprim
+
+def taequal(x,y):
try:
return float(x)==float(y)
- except TypeError:
- typex, typey = False, False
- if strtype(x):
- typex = True
- if strtype(y):
- typey = True
- if typex and typey:
- return x == y
- try:
- return str_to_num(x) == str_to_num(y)
- except ValueError:
- raise logoerror("#syntaxerror")
+ except:
+ if type(x) == str or type(x) == unicode:
+ xx = ord(x[0])
+ else:
+ xx = x
+ if type(y) == str or type(y) == unicode:
+ yy = ord(y[0])
+ else:
+ yy = y
+ return xx==yy
-def taless(x, y):
+def taless(x,y):
try:
return float(x)<float(y)
- except ValueError:
- typex, typey = False, False
- if strtype(x):
- typex = True
- if strtype(y):
- typey = True
- if typex and typey:
- return x < y
- try:
- return str_to_num(x) < str_to_num(y)
- except TypeError:
- raise logoerror("#syntaxerror")
-
-def tamore(x, y):
- return taless(y, x)
-
-def taplus(x, y):
- if numtype(x) and numtype(y):
- return(x+y)
- else:
- if numtype(x):
- xx = str(round_int(x))
+ except:
+ if type(x) == str or type(x) == unicode:
+ xx = ord(x[0])
else:
xx = x
- if numtype(y):
- yy = str(round_int(y))
+ if type(y) == str or type(y) == unicode:
+ yy = ord(y[0])
else:
yy = y
- return(xx+yy)
-
-def taminus(x, y):
- if numtype(x) and numtype(y):
- return(x-y)
- try:
- return str_to_num(x) - str_to_num(y)
- except TypeError:
- raise logoerror("#syntaxerror")
-
-def taproduct(x, y):
- if numtype(x) and numtype(y):
- return(x*y)
+ return xx<yy
+
+def tamore(x,y):
+ return taless(y,x)
+
+def taplus(x,y):
+ if (type(x) == int or type(x) == float) and \
+ (type(y) == int or type(y) == float):
+ return(x+y)
+ else:
+ return(str(x) + str(y))
+
+def taminus(x,y):
try:
- return str_to_num(x) * str_to_num(y)
- except TypeError:
+ return(x-y)
+ except:
raise logoerror("#syntaxerror")
-def tamod(x, y):
- if numtype(x) and numtype(y):
- return(x%y)
+def taproduct(x,y):
try:
- return str_to_num(x) % str_to_num(y)
- except TypeError:
- raise logoerror("#syntaxerror")
- except ValueError:
+ return(x*y)
+ except:
raise logoerror("#syntaxerror")
-
-def tasqrt(x):
- if numtype(x):
- if x < 0:
- raise logoerror("#negroot")
- return sqrt(x)
+
+def tamod(x,y):
try:
- return sqrt(str_to_num(x))
- except ValueError:
- raise logoerror("#negroot")
- except TypeError:
+ return(x%y)
+ except:
raise logoerror("#syntaxerror")
-def tarandom(x, y):
- if numtype(x) and numtype(y):
- return(int(uniform(x,y)))
- xx, xflag = chr_to_ord(x)
- yy, yflag = chr_to_ord(y)
- print xx, xflag, yy, yflag
- if xflag and yflag:
- return chr(int(uniform(xx,yy)))
- if not xflag:
- xx = str_to_num(x)
- if not yflag:
- yy = str_to_num(y)
+def tasqrt(x):
try:
- return(int(uniform(xx,yy)))
- except TypeError:
+ return sqrt(x)
+ except:
raise logoerror("#syntaxerror")
def identity(x):
return(x)
-
-"""
-Stop_logo is called from the Stop button on the toolbar
-"""
-def stop_logo(tw):
- tw.step_time = 0
- tw.lc.step = just_stop()
- tw.turtles.show_all()
-
-def just_stop():
- yield False
-def millis():
- return int(clock()*1000)
-
-"""
-A class for parsing Logo Code
-"""
-class LogoCode:
- def __init__(self, tw):
-
- self.tw = tw
- self.oblist = {}
-
- DEFPRIM = {
- '(':[1, lambda self, x: self.prim_opar(x)],
- 'and':[2, lambda self,x,y: taand(x,y)],
- 'arc':[2, lambda self, x, y: self.tw.canvas.arc(x, y)],
- 'back':[1, lambda self,x: self.tw.canvas.forward(-x)],
- 'blue':[0, lambda self: 70],
- 'bpos':[0, lambda self: -self.tw.canvas.height/(self.tw.coord_scale*2)],
- 'boty':[0, lambda self: self.tw.bottomy],
- 'box1':[0, lambda self: self.boxes['box1']],
- 'box':[1, lambda self,x: self.box(x)],
- 'box2':[0, lambda self: self.boxes['box2']],
- 'bullet':[1, self.prim_bullet, True],
- 'bulletlist':[1, self.prim_list, True],
- 'clean':[0, lambda self: self.prim_clear()],
- 'clearheap':[0, lambda self: self.empty_heap()],
- 'color':[0, lambda self: self.tw.canvas.color],
- 'comment':[1, lambda self,x: self.prim_print(x, True)],
- 'container':[1, lambda self,x: x],
- 'cyan':[0, lambda self: 50],
- 'define':[2, self.prim_define],
- 'division':[2, lambda self,x,y: careful_divide(x,y)],
- 'equal?':[2, lambda self,x,y: taequal(x,y)],
- 'fillscreen':[2, lambda self, x, y: self.tw.canvas.fillscreen(x, y)],
- 'forever':[1, self.prim_forever, True],
- 'forward':[1, lambda self, x: self.tw.canvas.forward(x)],
- 'fullscreen':[0, lambda self: self.tw.set_fullscreen()],
- 'greater?':[2, lambda self,x,y: tamore(x,y)],
- 'green':[0, lambda self: 30],
- 'heading':[0, lambda self: self.tw.canvas.heading],
- 'hideblocks':[0, lambda self: self.tw.hideblocks()],
- 'hres':[0, lambda self: self.tw.canvas.width/self.tw.coord_scale],
- 'id':[1, lambda self,x: identity(x)],
- 'if':[2, self.prim_if, True],
- 'ifelse':[3, self.prim_ifelse, True],
- 'insertimage':[1, lambda self,x: self.insert_image(x, False)],
- 'kbinput':[0, lambda self: self.prim_kbinput()],
- 'keyboard':[0, lambda self: self.keyboard],
- 'left':[1, lambda self,x: self.tw.canvas.right(-x)],
- 'leftx':[0, lambda self: self.tw.leftx],
- 'lpos':[0, lambda self: -self.tw.canvas.width/(self.tw.coord_scale*2)],
- 'less?':[2, lambda self,x,y: taless(x,y)],
- 'minus':[2, lambda self,x,y: taminus(x,y)],
- 'mod':[2, lambda self,x,y: tamod(x,y)],
- 'myfunc':[1, self.prim_myfunc, True],
- 'myfunction':[1, lambda self, x: self.myfunction(x)],
- 'nop':[0, lambda self: None],
- 'nop1':[0, lambda self: None],
- 'nop2':[0, lambda self: None],
- 'nop3':[1, lambda self,x: None],
- 'not':[1, lambda self,x:not x],
- 'orange':[0, lambda self: 10],
- 'or':[2, lambda self,x,y: taor(x,y)],
- 'pendown':[0, lambda self: self.tw.canvas.setpen(True)],
- 'pensize':[0, lambda self: self.tw.canvas.pensize],
- 'penup':[0, lambda self: self.tw.canvas.setpen(False)],
- 'plus':[2, lambda self,x,y: taplus(x,y)],
- 'pop':[0, lambda self: self.prim_pop()],
- 'print':[1, lambda self,x: self.prim_print(x, False)],
- 'printheap':[0, lambda self: self.prim_print_heap()],
- 'product':[2, lambda self,x,y: taproduct(x,y)],
- 'purple':[0, lambda self: 90],
- 'push':[1, lambda self,x: self.prim_push(x)],
- 'random':[2, lambda self,x,y: tarandom(x,y)],
- 'red':[0, lambda self: 0],
- 'repeat':[2, self.prim_repeat, True],
- 'right':[1, lambda self, x: self.tw.canvas.right(x)],
- 'rightx':[0, lambda self: self.tw.rightx],
- 'rpos':[0, lambda self: self.tw.canvas.width/(self.tw.coord_scale*2)],
- 'savepix':[1, lambda self, x: self.save_picture(x)],
- 'scale':[0, lambda self: self.scale],
- 'setcolor':[1, lambda self, x: self.tw.canvas.setcolor(x)],
- 'seth':[1, lambda self, x: self.tw.canvas.seth(x)],
- 'setpensize':[1, lambda self, x: self.tw.canvas.setpensize(x)],
- 'setscale':[1, lambda self,x: self.set_scale(x)],
- 'setshade':[1, lambda self, x: self.tw.canvas.setshade(x)],
- 'settextcolor':[1, lambda self, x: self.tw.canvas.settextcolor(x)],
- 'settextsize':[1, lambda self, x: self.tw.canvas.settextsize(x)],
- 'setxy':[2, lambda self, x, y: self.tw.canvas.setxy(x, y)],
- 'shade':[0, lambda self: self.tw.canvas.shade],
- 'show':[1, lambda self, x: self.show(x, True)],
- 'showaligned':[1,lambda self, x: self.show(x, False)],
- 'showblocks':[0, lambda self: self.tw.showblocks()],
- 'sound':[1, lambda self,x: self.play_sound(x)],
- 'sqrt':[1, lambda self,x: tasqrt(x)],
- 'stack1':[0, self.prim_stack1, True],
- 'stack':[1, self.prim_stack, True],
- 'stack2':[0, self.prim_stack2, True],
- 'start':[0, lambda self: self.prim_start()],
- 'stopstack':[0, lambda self: self.prim_stopstack()],
- 'storeinbox1':[1, lambda self,x: self.prim_setbox('box1', None ,x)],
- 'storeinbox2':[1, lambda self,x: self.prim_setbox('box2', None, x)],
- 'storeinbox':[2, lambda self,x,y: self.prim_setbox('box3', x, y)],
- 't1x1':[2, lambda self,x,y: self.show_template1x1(x, y)],
- 't1x1a':[2, lambda self,x,y: self.show_template1x1a(x, y)],
- 't1x2':[3, lambda self,x,y,z: self.show_template1x2(x, y, z)],
- 't2x1':[3, lambda self,x,y,z: self.show_template2x1(x, y, z)],
- 't2x2':[5, lambda self,x,y,z,a,b: self.show_template2x2(x, y, z, a, b)],
- 'textcolor':[0, lambda self: self.tw.canvas.textcolor],
- 'textsize':[0, lambda self: self.tw.textsize],
- 'titlex':[0, lambda self: self.tw.titlex],
- 'titley':[0, lambda self: self.tw.titley],
- 'topy':[0, lambda self: self.tw.topy],
- 'tpos':[0, lambda self: self.tw.canvas.height/(self.tw.coord_scale*2)],
- 'turtle':[1, lambda self, x: self.tw.canvas.set_turtle(x)],
- 'userdefined':[1, lambda self,x: self.prim_myblock(x)],
- 'video':[1, lambda self,x: self.play_movie(x)],
- 'vres':[0, lambda self: self.tw.canvas.height/self.tw.coord_scale],
- 'wait':[1, self.prim_wait, True],
- 'write':[2, lambda self, x,y: self.write(self, x,y)],
- 'xcor':[0, lambda self: self.tw.canvas.xcor/self.tw.coord_scale],
- 'ycor':[0, lambda self: self.tw.canvas.ycor/self.tw.coord_scale],
- 'yellow':[0, lambda self: 20]}
-
- for p in iter(DEFPRIM):
- if len(DEFPRIM[p]) == 2:
- self.defprim(p, DEFPRIM[p][0], DEFPRIM[p][1])
- else:
- self.defprim(p, DEFPRIM[p][0], DEFPRIM[p][1], DEFPRIM[p][2])
-
- self.symtype = type(self.intern('print'))
- self.listtype = type([])
- self.symnothing = self.intern('%nothing%')
- self.symopar = self.intern('(')
- self.iline = None
- self.cfun = None
- self.arglist = None
- self.ufun = None
- self.procstop = False
- self.running = False
- self.istack = []
- self.stacks = {}
- self.boxes = {'box1': 0, 'box2': 0}
- self.heap = []
-
- self.keyboard = 0
- self.trace = 0
- self.gplay = None
- self.ag = None
- self.title_height = int((self.tw.canvas.height/20)*self.tw.scale)
- self.body_height = int((self.tw.canvas.height/40)*self.tw.scale)
- self.bullet_height = int((self.tw.canvas.height/30)*self.tw.scale)
-
- self.scale = 33
-
- """
- Define the primitives associated with the blocks
- """
- def defprim(self, name, args, fcn, rprim=False):
- sym = self.intern(name)
- sym.nargs, sym.fcn = args, fcn
- sym.rprim = rprim
-
- """
- Add any new objects to the symbol list.
- """
- def intern(self, str):
- if str in self.oblist:
- return self.oblist[str]
- sym = symbol(str)
- self.oblist[str] = sym
- return sym
-
- """
- Given a block to run...
- """
- def run_blocks(self, blk, blocks, run_flag):
- for k in self.stacks.keys():
- self.stacks[k] = None
- self.stacks['stack1'] = None
- self.stacks['stack2'] = None
-
- for b in blocks:
- b.unhighlight()
- if b.name == 'hat1':
- code = self.blocks_to_code(b)
- self.stacks['stack1'] = self.readline(code)
- if b.name=='hat2':
- code = self.blocks_to_code(b)
- self.stacks['stack2'] = self.readline(code)
- if b.name == 'hat':
- if b.connections[1] is not None:
- code = self.blocks_to_code(b)
- x = b.connections[1].values[0]
- if type(convert(x, float, False)) == type(float):
- if int(float(x)) == x:
- x = int(x)
- self.stacks['stack3'+str(x)] = self.readline(code)
-
- code = self.blocks_to_code(blk)
- if run_flag is True:
- print "running code: %s" % (code)
- self.setup_cmd(code)
- else:
- return code
-
- """
- Convert a stack of blocks to pseudocode.
- Maintains a parallel datastructure for backpointers to blocks.
- """
- def blocks_to_code(self, blk):
- if blk is None:
- return ['%nothing%', '%nothing%']
- code = []
- dock = blk.docks[0]
- if len(dock)>4: # There could be a '(', ')', '[' or ']'.
- code.append(dock[4])
- if blk.primitive is not None: # make a tuple (prim, blk)
- code.append((blk.primitive, self.tw.block_list.list.index(blk)))
- elif len(blk.values)>0: # Extract the value from content blocks.
- if blk.name=='number':
- try:
- code.append(float(blk.values[0]))
- except ValueError:
- code.append(float(ord(blk.values[0][0])))
- elif blk.name=='string' or blk.name=='title':
- if type(blk.values[0]) == float or type(blk.values[0]) == int:
- if int(blk.values[0]) == blk.values[0]:
- blk.values[0] = int(blk.values[0])
- code.append('#s'+str(blk.values[0]))
- else:
- code.append('#s'+blk.values[0])
- elif blk.name=='journal':
- if blk.values[0] is not None:
- code.append('#smedia_'+str(blk.values[0]))
- else:
- code.append('#smedia_None')
- elif blk.name=='description':
- if blk.values[0] is not None:
- code.append('#sdescr_'+str(blk.values[0]))
- else:
- code.append('#sdescr_None')
- elif blk.name=='audio':
- if blk.values[0] is not None:
- code.append('#saudio_'+str(blk.values[0]))
- else:
- code.append('#saudio_None')
- else:
- return ['%nothing%']
- else:
- return ['%nothing%']
- for i in range(1, len(blk.connections)):
- b = blk.connections[i]
- dock = blk.docks[i]
- if len(dock)>4: # There could be a '(', ')', '[' or ']'.
- for c in dock[4]:
- code.append(c)
- if b is not None:
- code.extend(self.blocks_to_code(b))
- elif blk.docks[i][0] not in ['flow', 'unavailable']:
- code.append('%nothing%')
- return code
+# recenter the canvas when the start block is clicked
+def start_stack(lc):
+ if hasattr(lc.tw,'activity'):
+ lc.tw.activity.recenter()
+
+def lcNew(tw):
+ lc = taLogo()
+ lc.tw = tw
+ lc.oblist = {}
+
+ # math primitives
+ defprim(lc,'print', 1, lambda lc,x: status_print(lc,x))
+ defprim(lc,'+', None, lambda lc,x,y:x+y)
+ defprim(lc,'plus', 2, lambda lc,x,y:taplus(x,y))
+ defprim(lc,'-', None, lambda lc,x,y:x-y)
+ defprim(lc,'minus', 2, lambda lc,x,y:taminus(x,y))
+ defprim(lc,'*', None, lambda lc,x,y:x*y)
+ defprim(lc,'product', 2, lambda lc,x,y:taproduct(x,y))
+ defprim(lc,'/', None, lambda lc,x,y:careful_divide(x,y))
+ defprim(lc,'division', 2, lambda lc,x,y:careful_divide(x,y))
+ defprim(lc,'random', 2, lambda lc,x,y: int(random.uniform(x,y)))
+ defprim(lc,'greater?', 2, lambda lc,x,y: tamore(x,y))
+ defprim(lc,'less?', 2, lambda lc,x,y: taless(x,y))
+ defprim(lc,'equal?', 2, lambda lc,x,y: taequal(x,y))
+ defprim(lc,'and', None, lambda lc,x,y:x&y)
+ defprim(lc,'or', None, lambda lc,x,y:x|y)
+ defprim(lc,'not', 1, lambda lc,x:not x)
+ defprim(lc,'%', None, lambda lc,x,y:x%y)
+ defprim(lc,'mod', 2, lambda lc,x,y:tamod(x,y))
+ defprim(lc,'sqrt', 1, lambda lc,x: sqrt(x))
+ defprim(lc,'id',1, lambda lc,x: identity(x))
- """
- Execute the psuedocode.
- """
- def setup_cmd(self, str):
- self.tw.active_turtle.hide() # Hide the turtle while we are running.
- self.procstop = False
- list = self.readline(str)
- self.step = self.start_eval(list)
-
- """
- Convert the pseudocode into a list of commands.
- The block associated with the command is stored as the second element
- in a tuple, e.g., (#forward, 16)
- """
- def readline(self, line):
- res = []
- while line:
- token = line.pop(0)
- bindex = None
- if type(token) == tuple:
- (token, bindex) = token
- 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[0:2] == "#s":
- res.append(token[2:])
- elif token == '[':
- res.append(self.readline(line))
- elif token == ']':
- return res
- elif bindex is None or type(bindex) is not int:
- res.append(self.intern(token))
- else:
- res.append((self.intern(token), bindex))
- return res
-
- """
- Step through the list.
- """
- def start_eval(self, list):
- if self.tw.running_sugar:
- self.tw.activity.stop_button.set_icon("stopiton")
- self.running = True
- self.icall(self.evline, list)
- yield True
- if self.tw.running_sugar:
- self.tw.activity.stop_button.set_icon("stopitoff")
- yield False
- self.running = False
-
- """
- Add a function and its arguments to the program stack.
- """
- def icall(self, fcn, *args):
- self.istack.append(self.step)
- self.step = fcn(*(args))
-
- """
- Evaluate a line of code from the list.
- """
- def evline(self, list):
- oldiline = self.iline
- self.iline = list[:]
- self.arglist = None
- while self.iline:
- token = self.iline[0]
- bindex = None
- if type(token) == tuple:
- (token, bindex) = self.iline[0]
-
- # If the blocks are visible, highlight the current block.
- if not self.tw.hide and bindex is not None:
- self.tw.block_list.list[bindex].highlight()
-
- # In debugging modes, we pause between steps and show the turtle.
- if self.tw.step_time > 0:
- self.tw.active_turtle.show()
- endtime = millis()+self.an_int(self.tw.step_time)*100
- while millis()<endtime:
- yield True
- self.tw.active_turtle.hide()
-
- # 'Stand-alone' booleans are handled here.
- if token == self.symopar:
- token = self.iline[1]
- if type(token) == tuple:
- (token, bindex) = self.iline[1]
-
- # Process the token and any arguments.
- self.icall(self.eval)
- yield True
-
- # Time to unhighlight the current block.
- if not self.tw.hide and bindex is not None:
- self.tw.block_list.list[bindex].unhighlight()
-
- if self.procstop:
- break
- if self.iresult == None:
- continue
-
- if bindex is not None:
- self.tw.block_list.list[bindex].highlight()
- raise logoerror(str(self.iresult))
- self.iline = oldiline
- self.ireturn()
- if self.tw.hide is False:
- self.tw.display_coordinates()
- yield True
-
- """
- Evaluate the next token on the line of code we are processing.
- """
- def eval(self):
- token = self.iline.pop(0)
- bindex = None
- if type(token) == tuple:
- (token, bindex) = token
-
- # Either we are processing a symbol or a value.
- if type(token) == self.symtype:
- # We highlight blocks here in case an error occurs...
- if not self.tw.hide and bindex is not None:
- self.tw.block_list.list[bindex].highlight()
- self.icall(self.evalsym, token)
- yield True
- # and unhighlight if everything was OK.
- if not self.tw.hide and bindex is not None:
- self.tw.block_list.list[bindex].unhighlight()
- res = self.iresult
- else:
- res = token
+ # keyboard, sensor, and misc. primitives
+ defprim(lc,'kbinput', 0, lambda lc: kbinput(lc))
+ defprim(lc,'keyboard', 0, lambda lc: lc.keyboard)
+ defprim(lc,'userdefined', 1, lambda lc,x: loadmyblock(lc,x))
+ defprim(lc,'myfunc', 2, lambda lc,f,x: callmyfunc(lc, f, x))
+ defprim(lc,'hres', 0, lambda lc: lc.tw.turtle.width/lc.tw.coord_scale)
+ defprim(lc,'vres', 0, lambda lc: lc.tw.turtle.height/lc.tw.coord_scale)
+ defprim(lc,'leftpos', 0, lambda lc: \
+ -(lc.tw.turtle.width/(lc.tw.coord_scale*2)))
+ defprim(lc,'toppos', 0, lambda lc: \
+ lc.tw.turtle.height/(lc.tw.coord_scale*2))
+ defprim(lc,'rightpos', 0, lambda lc: \
+ lc.tw.turtle.width/(lc.tw.coord_scale*2))
+ defprim(lc,'bottompos', 0, lambda lc: \
+ -(lc.tw.turtle.height/(lc.tw.coord_scale*2)))
+
+ # turtle primitives
+ defprim(lc,'clean', 0, lambda lc: clear(lc))
+ defprim(lc,'forward', 1, lambda lc, x: forward(lc.tw.turtle, x))
+ defprim(lc,'back', 1, lambda lc,x: forward(lc.tw.turtle,-x))
+ defprim(lc,'seth', 1, lambda lc, x: seth(lc.tw.turtle, x))
+ defprim(lc,'right', 1, lambda lc, x: right(lc.tw.turtle, x))
+ defprim(lc,'left', 1, lambda lc,x: right(lc.tw.turtle,-x))
+ defprim(lc,'heading', 0, lambda lc: lc.tw.turtle.heading)
+ defprim(lc,'setxy', 2, lambda lc, x, y: setxy(lc.tw.turtle, x, y))
+ defprim(lc,'show',1,lambda lc, x: show(lc, x, True))
+ defprim(lc,'setscale', 1, lambda lc,x: set_scale(lc, x))
+ defprim(lc,'scale', 0, lambda lc: lc.scale)
+ defprim(lc,'write',2,lambda lc, x,y: write(lc, x,y))
+ defprim(lc,'insertimage', 1, lambda lc,x: insert_image(lc, x, False))
+ defprim(lc,'arc', 2, lambda lc, x, y: arc(lc.tw.turtle, x, y))
+ defprim(lc,'xcor', 0, lambda lc: lc.tw.turtle.xcor/lc.tw.coord_scale)
+ defprim(lc,'ycor', 0, lambda lc: lc.tw.turtle.ycor/lc.tw.coord_scale)
+
+ # pen primitives
+ defprim(lc,'pendown', 0, lambda lc: setpen(lc.tw.turtle, True))
+ defprim(lc,'penup', 0, lambda lc: setpen(lc.tw.turtle, False))
+ defprim(lc,'(', 1, lambda lc, x: prim_opar(lc,x))
+ defprim(lc,'setcolor', 1, lambda lc, x: setcolor(lc.tw.turtle, x))
+ defprim(lc,'settextcolor', 1, lambda lc, x: settextcolor(lc.tw.turtle, x))
+ defprim(lc,'settextsize', 1, lambda lc, x: settextsize(lc.tw.turtle, x))
+ defprim(lc,'setshade', 1, lambda lc, x: setshade(lc.tw.turtle, x))
+ defprim(lc,'setpensize', 1, lambda lc, x: setpensize(lc.tw.turtle, x))
+ defprim(lc,'fillscreen', 2, lambda lc, x, y: \
+ fillscreen(lc.tw.turtle, x, y))
+ defprim(lc,'color', 0, lambda lc: lc.tw.turtle.color)
+ defprim(lc,'shade', 0, lambda lc: lc.tw.turtle.shade)
+ defprim(lc,'pensize', 0, lambda lc: lc.tw.turtle.pensize)
+ defprim(lc,'textcolor', 0, lambda lc: lc.tw.turtle.textcolor)
+ defprim(lc,'textsize', 0, lambda lc: lc.tw.textsize)
+ defprim(lc,'red', 0, lambda lc: 0)
+ defprim(lc,'orange', 0, lambda lc: 10)
+ defprim(lc,'yellow', 0, lambda lc: 20)
+ defprim(lc,'green', 0, lambda lc: 30)
+ defprim(lc,'cyan', 0, lambda lc: 50)
+ defprim(lc,'blue', 0, lambda lc: 70)
+ defprim(lc,'purple', 0, lambda lc: 90)
+
+ # flow primitives
+ defprim(lc,'wait', 1, prim_wait, True)
+ defprim(lc,'repeat', 2, prim_repeat, True)
+ defprim(lc,'forever', 1, prim_forever, True)
+ defprim(lc,'if', 2, prim_if, True)
+ defprim(lc,'ifelse', 3, prim_ifelse, True)
+ defprim(lc,'stopstack', 0, prim_stopstack)
+
+ # blocks primitives
+ defprim(lc,'stack1', 0, prim_stack1, True)
+ defprim(lc,'stack2', 0, prim_stack2, True)
+ defprim(lc,'stack', 1, prim_stack, True)
+ defprim(lc,'box1', 0, lambda lc: lc.boxes['box1'])
+ defprim(lc,'box2', 0, lambda lc: lc.boxes['box2'])
+ defprim(lc,'box', 1, lambda lc,x: box(lc,x))
+ defprim(lc,'storeinbox1', 1, lambda lc,x: setbox(lc, 'box1',x))
+ defprim(lc,'storeinbox2', 1, lambda lc,x: setbox(lc, 'box2',x))
+ defprim(lc,'storeinbox', 2, lambda lc,x,y: setbox(lc, 'box3'+str(x),y))
+ defprim(lc,'push', 1, lambda lc,x: push_heap(lc,x))
+ defprim(lc,'pop', 0, lambda lc: pop_heap(lc))
+ defprim(lc,'heap', 0, lambda lc: heap_print(lc))
+ defprim(lc,'emptyheap', 0, lambda lc: empty_heap(lc))
+ defprim(lc,'start', 0, lambda lc: start_stack(lc))
+ 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,'nop3', 1, lambda lc,x: None)
+
+ # templates primitives
+ defprim(lc,'container', 1, lambda lc,x: x)
+ defprim(lc,'tp1', 2, lambda lc,x,y: show_template1(lc, x, y))
+ defprim(lc,'tp8', 2, lambda lc,x,y: show_template8(lc, x, y))
+ defprim(lc,'tp6', 3, lambda lc,x,y,z: show_template6(lc, x, y, z))
+ defprim(lc,'tp3', 8, lambda lc,x,y,z,a,b,c,d,e: \
+ show_template3(lc, x, y, z, a, b, c, d, e))
+ defprim(lc,'sound', 1, lambda lc,x: play_sound(lc, x))
+ defprim(lc,'video', 1, lambda lc,x: play_movie(lc, x))
+ defprim(lc,'tp2', 3, lambda lc,x,y,z: \
+ show_template2(lc, x, y, z))
+ defprim(lc,'tp7', 5, lambda lc,x,y,z,a,b: \
+ show_template7(lc, x, y, z, a, b))
+ defprim(lc,'hideblocks', 0, lambda lc: hideblocks(lc))
+
+ # arduino primitives
+ defprim(lc,'delay', 1, prim_wait, True)
+ defprim(lc,'setpinmode', 2, lambda lc, x, y: lc.tw.arduino.pin_mode(x, y))
+ defprim(lc,'analogwrite', 2, lambda lc, x, y: \
+ lc.tw.arduino.analog_write(x, y))
+ defprim(lc,'digitalwrite', 2, lambda lc, x, y: \
+ lc.tw.arduino.digital_write(x, y))
+ defprim(lc,'analogread', 1, lambda lc, x: lc.tw.arduino.analog_read(x))
+ defprim(lc,'digitalread', 1, lambda lc, x: lc.tw.arduino.digital_read(x))
+ defprim(lc,'high', 0, lambda lc: lc.tw.arduino.HIGH)
+ defprim(lc,'low', 0, lambda lc: lc.tw.arduino.LOW)
+ defprim(lc,'input', 0, lambda lc: lc.tw.arduino.INPUT)
+ defprim(lc,'output', 0, lambda lc: lc.tw.arduino.OUTPUT)
+ defprim(lc,'pwm', 0, lambda lc: lc.tw.arduino.PWM)
+ defprim(lc,'servo', 0, lambda lc: lc.tw.arduino.SERVO)
+
+ lc.symtype = type(intern(lc, 'print'))
+ lc.listtype = type([])
+ lc.symnothing = intern(lc, '%nothing%')
+ lc.symopar = intern(lc, '(')
+
+ lc.istack = []
+ lc.stacks = {}
+ # lc.boxes = noKeyError({'box1': 0, 'box2': 0})
+ lc.boxes = {'box1': 0, 'box2': 0}
+ lc.heap = []
+ lc.keyboard = 0
+ lc.trace = 0 # flag for enabling debug output via showlabel
+ lc.gplay = None
+ lc.ag = None
+ lc.nobox = ""
+ lc.title_height = int((lc.tw.turtle.height/30)*lc.tw.scale)
+ lc.body_height = int((lc.tw.turtle.height/60)*lc.tw.scale)
+ lc.bullet_height = int((lc.tw.turtle.height/45)*lc.tw.scale)
+
+ lc.iline, lc.cfun, lc.arglist, lc.ufun = None, None, None, None
+
+ # this dictionary is used to define the relative size and postion of
+ # template elements (w, h, x, y, dx, dy, dx1, dy1...)
+ lc.templates = {
+ 'tp1': (0.5, 0.5, 0.0625, 0.125, 1.05, 0),
+ 'tp2': (0.5, 0.5, 0.0625, 0.125, 1.05, 1.05),
+ 'tp3': (1, 1, 0.0625, 0.125, 0, 0.1),
+ 'tp6': (0.45, 0.45, 0.0625, 0.125, 1.05, 1.05),
+ 'tp7': (0.45, 0.45, 0.0625, 0.125, 1.05, 1.05),
+ 'tp8': (0.9, 0.9, 0.0625, 0.125, 0, 0),
+ 'insertimage': (0.333, 0.333)
+ }
+ lc.scale = 33
+
+ return lc
+
+def display_coordinates(tw):
+ if hasattr(tw, "activity"):
+ if hasattr(tw.activity, "coordinates_label"):
+ x = round_int(tw.turtle.xcor/tw.coord_scale)
+ y = round_int(tw.turtle.ycor/tw.coord_scale)
+ h = round_int(tw.turtle.heading)
+ tw.activity.coordinates_label.set_text(_("xcor") + " = " + \
+ str(x) + " " + \
+ _("ycor") + " = " + \
+ str(y) + " " + \
+ _("heading") + " = " + \
+ str(h))
+ tw.activity.coordinates_label.show()
+
+def round_int(n):
+ if int(float(n)) == n:
+ return int(n)
+ else:
+ nn = int(float(n+0.05)*10)/10.
+ if int(float(nn)) == nn:
+ return int(nn)
+ return nn
- self.ireturn(res)
- yield True
+def box(lc,x):
+ try:
+ return lc.boxes['box3'+str(x)]
+ except:
+ lc.nobox = str(x)
+ raise logoerror("#emptybox")
+
+def loadmyblock(lc,x):
+ # execute code inported from the Journal
+ if lc.tw.myblock != None:
+ y = myfunc_import(lc, lc.tw.myblock, x)
+ else:
+ raise logoerror("#nocode")
+ return
- """
- Process primitive associated with symbol token
- """
- def evalsym(self, token):
- self.debug_trace(token)
- self.undefined_check(token)
- oldcfun, oldarglist = self.cfun, self.arglist
- self.cfun, self.arglist = token, []
-
- if token.nargs == None:
- raise logoerror("#noinput")
- for i in range(token.nargs):
- self.no_args_check()
- self.icall(self.eval)
- yield True
- self.arglist.append(self.iresult)
- if self.cfun.rprim:
- if type(self.cfun.fcn) == self.listtype:
- self.icall(self.ufuncall, self.cfun.fcn)
- yield True
- else:
- self.icall(self.cfun.fcn, *self.arglist)
- yield True
- result = None
- else:
- result = self.cfun.fcn(self, *self.arglist)
- self.cfun, self.arglist = oldcfun, oldarglist
- if self.arglist is not None and result == None:
- raise logoerror("%s didn't output to %s (arglist %s, result %s)" % \
- (oldcfun.name, self.cfun.name, str(self.arglist), str(result)))
- self.ireturn(result)
- yield True
+def callmyfunc(lc, f, x):
+ y = myfunc(lc, f, x)
+ if y is None:
+ raise logoerror("#syntaxerror")
+ stop_logo(lc.tw)
+ else:
+ return y
- def ufuncall(self, body):
- ijmp(self.evline, body)
- yield True
-
- def doevalstep(self):
- starttime = millis()
+def show_picture(lc, media, x, y, w, h):
+ if media == "" or media[6:] == "":
+ # raise logoerror("#nomedia")
+ pass
+ elif media[6:] != "None":
try:
- while (millis()-starttime)<120:
- try:
- if self.step is not None:
- self.step.next()
- else:
- return False
- except StopIteration:
- self.tw.turtles.show_all()
- return False
- except logoerror, e:
- self.tw.showlabel('syntaxerror', str(e)[1:-1])
- self.tw.turtles.show_all()
- return False
- return True
-
- def ireturn(self, res=None):
- self.step = self.istack.pop()
- self.iresult = res
-
- def ijmp(self, fcn, *args):
- self.step = fcn(*(args))
-
- def debug_trace(self, token):
- if self.trace:
- if token.name in PALETTES[PALETTE_NAMES.index('turtle')]:
- my_string = "%s\n%s=%d\n%s=%d\n%s=%d\n%s=%d" %\
- (token.name, _('xcor'), int(self.tw.canvas.xcor),
- _('ycor'), int(self.tw.canvas.ycor), _('heading'),
- int(self.tw.canvas.heading), _('scale'), int(self.scale))
- elif token.name in PALETTES[PALETTE_NAMES.index('pen')]:
- if self.tw.canvas.pendown:
- penstatus = _('pen down')
- else:
- penstatus = _('pen up')
- my_string = "%s\n%s\n%s=%d\n%s=%d\n%s=%.1f" %\
- (token.name, penstatus, _('color'),
- int(self.tw.canvas.color), _('shade'),
- int(self.tw.canvas.shade), _('pen size'),
- self.tw.canvas.pensize)
- else:
- my_string = "%s\n%s:\n" % (token.name, _('box'))
- for k, v in self.boxes.iteritems():
- tmp = k +":" + str(v) + "\n"
- my_string += tmp
- self.tw.showlabel('info',my_string)
- return
-
- def undefined_check(self, token):
- if token.fcn is not None:
- return False
- if token.name == '%nothing%':
- errormsg = ''
+ dsobject = datastore.get(media[6:])
+ except:
+ raise logoerror("#nomedia")
+ # check to see if it is a movie
+ # print dsobject.file_path
+ # print "object has file suffix of: " + dsobject.file_path[-4:]
+ if dsobject.file_path[-4:] == '.ogv' or \
+ dsobject.file_path[-4:] == '.vob' or \
+ dsobject.file_path[-4:] == '.mp4' or \
+ dsobject.file_path[-4:] == '.wmv' or \
+ dsobject.file_path[-4:] == '.mov':
+ # print "playing movie x:" + str(x) + " y:" + str(y) + " w:" + \
+ # str(w) + " h:" + str(h)
+ play_dsobject(lc, dsobject, int(x), int(y), int(w), int(h))
else:
- errormsg = "%s %s" % (_("I don't know how to"), _(token.name))
- raise logoerror(errormsg)
-
- def no_args_check(self):
- if self.iline and self.iline[0] is not self.symnothing:
- return
- raise logoerror("#noinput")
-
- #
- # Primitives
- #
-
- def prim_clear(self):
- stop_media(self)
- self.tw.canvas.clearscreen()
-
- def prim_start(self):
- if self.tw.running_sugar:
- self.tw.activity.recenter()
-
- def prim_wait(self, time):
- self.tw.active_turtle.show()
- endtime = millis()+self.an_int(time*1000)
- while millis()<endtime:
- yield True
- self.tw.active_turtle.hide()
- self.ireturn()
- yield True
-
- def prim_repeat(self, num, list):
- num = self.an_int(num)
- for i in range(num):
- self.icall(self.evline, list[:])
- yield True
- if self.procstop:
- break
- self.ireturn()
- yield True
+ pixbuf = get_pixbuf_from_journal(dsobject, int(w), int(h))
+ if pixbuf != None:
+ draw_pixbuf(lc.tw.turtle, pixbuf, 0, 0, int(x), int(y), \
+ int(w), int(h))
+ dsobject.destroy()
- def prim_bullet(self, list): # Depreciated block style
- self.show_bullets(list)
- self.ireturn()
- yield True
+def get_pixbuf_from_journal(dsobject,w,h):
+ try:
+ pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(dsobject.file_path, \
+ int(w),int(h))
+ except:
+ try:
+ # print "Trying preview..."
+ pixbufloader = \
+ gtk.gdk.pixbuf_loader_new_with_mime_type('image/png')
+ pixbufloader.set_size(min(300,int(w)),min(225,int(h)))
+ pixbufloader.write(dsobject.metadata['preview'])
+ pixbufloader.close()
+ pixbuf = pixbufloader.get_pixbuf()
+ except:
+ # print "No preview"
+ pixbuf = None
+ return pixbuf
- def prim_list(self, list):
- self.show_list(list)
- self.ireturn()
- yield True
+def show_description(lc, media, x, y, w, h):
+ if media == "" or media[6:] == "":
+ # raise logoerror("#nomedia")
+ pass
+ elif media[6:] != "None":
+ try:
+ dsobject = datastore.get(media[6:])
+ draw_text(lc.tw.turtle, \
+ dsobject.metadata['description'],int(x),int(y), \
+ lc.body_height, int(w))
+ dsobject.destroy()
+ except:
+ print "no description?"
+
+def draw_title(lc,title,x,y):
+ draw_text(lc.tw.turtle,title,int(x),int(y),lc.title_height, \
+ lc.tw.turtle.width-x)
+
+def calc_position(lc,t):
+ w,h,x,y,dx,dy = lc.templates[t]
+ x *= lc.tw.turtle.width
+ y *= lc.tw.turtle.height
+ w *= (lc.tw.turtle.width-x)
+ h *= (lc.tw.turtle.height-y)
+ dx *= w
+ dy *= h
+ return(w,h,x,y,dx,dy)
+
+# title, one image, and description
+def show_template1(lc, title, media):
+ w,h,xo,yo,dx,dy = calc_position(lc,'tp1')
+ x = -(lc.tw.turtle.width/2)+xo
+ y = lc.tw.turtle.height/2
+ setxy(lc.tw.turtle, x, y)
+ # save the text size so we can restore it later
+ save_text_size = lc.tw.textsize
+ # set title text
+ settextsize(lc.tw.turtle, lc.title_height)
+ show(lc,title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (lc.tw.turtle.height - lc.title_height*2) \
+ / lc.tw.turtle.height
+ set_scale(lc,myscale)
+ # set body text size
+ settextsize(lc.tw.turtle, lc.body_height)
+ # render media object
+ y -= int(lc.title_height*2*lc.tw.lead) # leave some space below the title
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media)
+ x = 0
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media.replace("media_","descr_"))
+ # restore text size
+ settextsize(lc.tw.turtle, save_text_size)
+
+# title, two images (horizontal), two descriptions
+def show_template2(lc, title, media1, media2):
+ w,h,xo,yo,dx,dy = calc_position(lc,'tp2')
+ x = -(lc.tw.turtle.width/2)+xo
+ y = lc.tw.turtle.height/2
+ setxy(lc.tw.turtle, x, y)
+ # save the text size so we can restore it later
+ save_text_size = lc.tw.textsize
+ # set title text
+ settextsize(lc.tw.turtle, lc.title_height)
+ show(lc,title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (lc.tw.turtle.height - lc.title_height*2)/lc.tw.turtle.height
+ set_scale(lc,myscale)
+ # set body text size
+ settextsize(lc.tw.turtle, lc.body_height)
+ # render four quadrents
+ y -= int(lc.title_height*2*lc.tw.lead) # leave some space below the title
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media1)
+ x = 0
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media2)
+ y = -lc.title_height
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media2.replace("media_","descr_"))
+ x = -(lc.tw.turtle.width/2)+xo
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media1.replace("media_","descr_"))
+ # restore text size
+ settextsize(lc.tw.turtle, save_text_size)
+
+# title and seven bullets
+def show_template3(lc, title, s1, s2, s3, s4, s5, s6, s7):
+ w,h,xo,yo,dx,dy = calc_position(lc,'tp3')
+ x = -(lc.tw.turtle.width/2)+xo
+ y = lc.tw.turtle.height/2
+ setxy(lc.tw.turtle, x, y)
+ # save the text size so we can restore it later
+ save_text_size = lc.tw.textsize
+ # set title text
+ settextsize(lc.tw.turtle, lc.title_height)
+ show(lc,title)
+ # set body text size
+ settextsize(lc.tw.turtle, lc.bullet_height)
+ y -= int(lc.title_height*2*lc.tw.lead) # leave some space below the title
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s1)
+ y -= int(lc.bullet_height*2*lc.tw.lead)
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s2)
+ y -= int(lc.bullet_height*2*lc.tw.lead)
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s3)
+ y -= int(lc.bullet_height*2*lc.tw.lead)
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s4)
+ y -= int(lc.bullet_height*2*lc.tw.lead)
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s5)
+ y -= int(lc.bullet_height*2*lc.tw.lead)
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s6)
+ y -= int(lc.bullet_height*2*lc.tw.lead)
+ setxy(lc.tw.turtle, x, y)
+ show(lc, s7)
+ # restore text size
+ settextsize(lc.tw.turtle, save_text_size)
+
+# title, two images (vertical), two desciptions
+def show_template6(lc, title, media1, media2):
+ w,h,xo,yo,dx,dy = calc_position(lc,'tp6')
+ x = -(lc.tw.turtle.width/2)+xo
+ y = lc.tw.turtle.height/2
+ setxy(lc.tw.turtle, x, y)
+ # save the text size so we can restore it later
+ save_text_size = lc.tw.textsize
+ # set title text
+ settextsize(lc.tw.turtle, lc.title_height)
+ show(lc,title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (lc.tw.turtle.height - lc.title_height*2)/lc.tw.turtle.height
+ set_scale(lc,myscale)
+ # set body text size
+ settextsize(lc.tw.turtle, lc.body_height)
+ # render four quadrents
+ y -= int(lc.title_height*2*lc.tw.lead) # leave some space below the title
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media1)
+ x = 0
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media1.replace("media_","descr_"))
+ y = -lc.title_height
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media2.replace("media_","descr_"))
+ x = -(lc.tw.turtle.width/2)+xo
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media2)
+ # restore text size
+ settextsize(lc.tw.turtle, save_text_size)
+
+# title and four images
+def show_template7(lc, title, media1, media2, media3, media4):
+ w,h,xo,yo,dx,dy = calc_position(lc,'tp7')
+ x = -(lc.tw.turtle.width/2)+xo
+ y = lc.tw.turtle.height/2
+ setxy(lc.tw.turtle, x, y)
+ # save the text size so we can restore it later
+ save_text_size = lc.tw.textsize
+ # set title text
+ settextsize(lc.tw.turtle, lc.title_height)
+ show(lc,title)
+ # calculate and set scale for media blocks
+ myscale = 45 * (lc.tw.turtle.height - lc.title_height*2)/lc.tw.turtle.height
+ set_scale(lc,myscale)
+ # set body text size
+ settextsize(lc.tw.turtle, lc.body_height)
+ # render four quadrents
+ y -= int(lc.title_height*2*lc.tw.lead) # leave some space below the title
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media1)
+ x = 0
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media2)
+ y = -lc.title_height
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media4)
+ x = -(lc.tw.turtle.width/2)+xo
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media3)
+ # restore text size
+ settextsize(lc.tw.turtle, save_text_size)
+
+# title, one media object
+def show_template8(lc, title, media1):
+ w,h,xo,yo,dx,dy = calc_position(lc,'tp7')
+ x = -(lc.tw.turtle.width/2)+xo
+ y = lc.tw.turtle.height/2
+ setxy(lc.tw.turtle, x, y)
+ # save the text size so we can restore it later
+ save_text_size = lc.tw.textsize
+ # set title text
+ settextsize(lc.tw.turtle, lc.title_height)
+ show(lc,title)
+ # calculate and set scale for media blocks
+ myscale = 90 * (lc.tw.turtle.height - lc.title_height*2) \
+ / lc.tw.turtle.height
+ set_scale(lc,myscale)
+ # set body text size
+ settextsize(lc.tw.turtle, lc.body_height)
+ # render media object
+ y -= int(lc.title_height*2*lc.tw.lead) # leave some space below the title
+ setxy(lc.tw.turtle, x, y)
+ show(lc, media1)
+ # restore text size
+ settextsize(lc.tw.turtle, save_text_size)
+
+# image only (at current x,y)
+def insert_image(lc, media, center):
+ w = (lc.tw.turtle.width * lc.scale)/100
+ h = (lc.tw.turtle.height * lc.scale)/100
+ # convert from Turtle coordinates to screen coordinates
+ x = lc.tw.turtle.width/2+int(lc.tw.turtle.xcor)
+ y = lc.tw.turtle.height/2-int(lc.tw.turtle.ycor)
+ if center == True:
+ x -= w/2
+ y -= h/2
+ if media[0:5] == 'media':
+ show_picture(lc, media, x, y, w, h)
+
+# description text only (at current x,y)
+def insert_desc(lc, media):
+ w = (lc.tw.turtle.width * lc.scale)/100
+ h = (lc.tw.turtle.height * lc.scale)/100
+ # convert from Turtle coordinates to screen coordinates
+ x = lc.tw.turtle.width/2+int(lc.tw.turtle.xcor)
+ y = lc.tw.turtle.height/2-int(lc.tw.turtle.ycor)
+ if media[0:5] == 'descr':
+ show_description(lc, media, x, y, w, h)
+
+def set_scale(lc, x):
+ lc.scale = x
+
+# need to fix export logo to map show to write
+def show(lc, string, center=False):
+ # convert from Turtle coordinates to screen coordinates
+ x = lc.tw.turtle.width/2+int(lc.tw.turtle.xcor)
+ y = lc.tw.turtle.height/2-int(lc.tw.turtle.ycor)
+ if type(string) == str or type(string) == unicode:
+ if string == "media_None":
+ pass
+ elif string[0:6] == 'media_':
+ insert_image(lc, string, center)
+ elif string[0:6] == 'descr_':
+ insert_desc(lc, string)
+ elif string[0:6] == 'audio_':
+ play_sound(lc, string)
+ else:
+ if center == True:
+ y -= lc.tw.textsize
+ draw_text(lc.tw.turtle,string,x,y,lc.tw.textsize,lc.tw.turtle.width-x)
+ elif type(string) == float or type(string) == int:
+ string = round_int(string)
+ if center == True:
+ y -= lc.tw.textsize
+ draw_text(lc.tw.turtle,string,x,y,lc.tw.textsize,lc.tw.turtle.width-x)
+
+# audio only
+def play_sound(lc, audio):
+ play_audio(lc, audio)
+
+def clear(lc):
+ stop_media(lc)
+ clearscreen(lc.tw.turtle)
+
+def write(lc, string, fsize):
+ # convert from Turtle coordinates to screen coordinates
+ x = lc.tw.turtle.width/2+int(lc.tw.turtle.xcor)
+ y = lc.tw.turtle.height/2-int(lc.tw.turtle.ycor)
+ draw_text(lc.tw.turtle,string,x,y-15,int(fsize),lc.tw.turtle.width)
+
+def hideblocks(lc):
+ from tawindow import hideshow_button
+ lc.tw.hide = False # force hide
+ hideshow_button(lc.tw)
+ for i in lc.tw.selbuttons:
+ hide(i)
+ if hasattr(lc.tw,"activity"):
+ lc.tw.activity.do_hide()
+
+def doevalstep(lc):
+ starttime = millis()
+ try:
+ while (millis()-starttime)<120:
+ try:
+ lc.step.next()
+ except StopIteration:
+ setlayer(lc.tw.turtle.spr,630)
+ return False
+ except logoerror, e:
+ showlabel(lc, str(e)[1:-1])
+ setlayer(lc.tw.turtle.spr,630)
+ return False
+ return True
+
+def icall(lc, fcn, *args):
+ lc.istack.append(lc.step)
+ lc.step = fcn(lc, *(args))
+
+def ireturn(lc, res=None):
+ lc.step = lc.istack.pop()
+ lc.iresult = res
+
+def ijmp(lc, fcn, *args):
+ lc.step = fcn(lc,*(args))
+
+def heap_print(lc):
+ showlabel(lc,lc.heap)
+
+def status_print(lc,n):
+ if type(n) == str or type(n) == unicode:
+ # show title for Journal entries
+ if n[0:6] == 'media_':
+ try:
+ dsobject = datastore.get(n[6:])
+ showlabel(lc, dsobject.metadata['title'])
+ dsobject.destroy()
+ except:
+ showlabel(lc,n)
+ else:
+ showlabel(lc,n)
+ elif type(n) == int:
+ showlabel(lc,n)
+ else:
+ showlabel(lc, round_int(n))
- def prim_myfunc(self, list):
- new_list = [self.intern('myfunction')]
- new_list.append(list)
- self.icall(self.evline, new_list)
- yield True
- self.ireturn()
- yield True
+def kbinput(lc):
+ if len(lc.tw.keypress) == 1:
+ lc.keyboard = ord(lc.tw.keypress[0])
+ else:
+ try:
+ lc.keyboard = {'Escape': 27, 'space': 32, ' ': 32, 'Return': 13, \
+ 'KP_Up': 2, 'KP_Down': 4, 'KP_Left': 1, \
+ 'KP_Right': 3,}[lc.tw.keypress]
+ except:
+ lc.keyboard = 0
+ lc.tw.keypress = ""
+
+def showlabel(lc,label):
+ if label=='#nostack':
+ shp = 'nostack'
+ label=''
+ elif label=='#noinput':
+ shp = 'noinput'
+ label=''
+ elif label=='#emptyheap':
+ shp = 'emptyheap'
+ label=''
+ elif label=='#emptybox':
+ shp = 'emptybox'
+ label=' '+lc.nobox
+ elif label=='#nomedia':
+ shp = 'nomedia'
+ label=''
+ elif label=='#nocode':
+ shp = 'nocode'
+ label=''
+ elif label=='#syntaxerror':
+ shp = 'syntaxerror'
+ label=''
+ elif label=='#overflowerror':
+ shp = 'overflowerror'
+ label=''
+ else:
+ shp = 'status'
+ setshape(lc.tw.status_spr, lc.tw.status_shapes[shp])
+ setlabel(lc.tw.status_spr, label)
+ setlayer(lc.tw.status_spr, 710)
- def myfunction(self, list):
- y = myfunc(list[0], list[1:])
- if y == None:
- raise logoerror("#syntaxerror")
- stop_logo(self.tw)
- else:
- return y
-
- def prim_forever(self, list):
- while True:
- self.icall(self.evline, list[:])
- yield True
- if self.procstop:
- break
- self.ireturn()
- yield True
+def stop_logo(tw):
+ tw.step_time = 0
+ tw.lc.step = just_stop()
- def prim_if(self, bool, list):
- if bool:
- self.icall(self.evline, list[:])
- yield True
- self.ireturn()
- yield True
+def just_stop(): yield False
- def prim_ifelse(self, bool, list1, list2):
- if bool:
- self.ijmp(self.evline, list1[:])
- yield True
- else:
- self.ijmp(self.evline, list2[:])
- yield True
-
- def prim_opar(self, val):
- self.iline.pop(0)
- return val
-
- def prim_define(self, name, body):
- if type(name) is not symtype:
- name = self.intern(name)
- name.nargs, name.fcn = 0, body
- name.rprim = True
-
- def prim_stack(self, x):
- if type(convert(x, float, False)) == type(float):
- if int(float(x)) == x:
- x = int(x)
- if (not self.stacks.has_key('stack3'+str(x))) or\
- self.stacks['stack3'+str(x)] is None:
- raise logoerror("#nostack")
- self.icall(self.evline, self.stacks['stack3'+str(x)][:])
- yield True
- self.procstop = False
- self.ireturn()
- yield True
+def setbox(lc, name,val): lc.boxes[name]=val
- def prim_stack1(self):
- if self.stacks['stack1'] is None:
- raise logoerror("#nostack")
- self.icall(self.evline, self.stacks['stack1'][:])
- yield True
- self.procstop = False
- self.ireturn()
- yield True
-
- def prim_stack2(self):
- if self.stacks['stack2'] is None:
- raise logoerror("#nostack")
- self.icall(self.evline, self.stacks['stack2'][:])
- yield True
- self.procstop = False
- self.ireturn()
- yield True
+def push_heap(lc,val): lc.heap.append(val)
- def prim_stopstack(self):
- self.procstop = True
-
- def prim_print_heap(self):
- self.tw.showlabel('status', self.heap)
-
- def an_int(self, n):
- if type(n) == int:
- return n
- elif type(n) == float:
- return int(n)
- elif type(n) == str:
- return int(ord(n[0]))
- else:
- raise logoerror("%s doesn't like %s as input" \
- % (self.cfun.name, str(n)))
+def pop_heap(lc):
+ try: return lc.heap.pop(-1)
+ except: raise logoerror ("#emptyheap")
- def box(self, x):
- if type(convert(x, float, False)) == float:
- if int(float(x)) == x:
- x = int(x)
- try:
- return self.boxes['box3'+str(x)]
- except:
- raise logoerror("#emptybox")
-
- def prim_myblock(self, x):
- if self.tw.myblock is not None:
- try:
- y = myfunc_import(self, self.tw.myblock, x)
- except:
- raise logoerror("#nocode")
- else:
- raise logoerror("#nocode")
- return
-
- def prim_print(self, n, flag):
- if flag and (self.tw.hide or self.tw.step_time == 0):
- return
- if type(n) == str or type(n) == unicode:
- if n[0:6] == 'media_':
- try:
- if self.tw.running_sugar:
- dsobject = datastore.get(n[6:])
- self.tw.showlabel('status', dsobject.metadata['title'])
- dsobject.destroy()
- else:
- self.tw.showlabel('status', n[6:])
- except:
- self.tw.showlabel('status', n)
- else:
- self.tw.showlabel('status', n)
- elif type(n) == int:
- self.tw.showlabel('status', n)
- else:
- self.tw.showlabel('status', round_int(n))
-
- def prim_kbinput(self):
- if len(self.tw.keypress) == 1:
- self.keyboard = ord(self.tw.keypress[0])
- else:
- try:
- self.keyboard = {'Escape': 27, 'space': 32, ' ': 32,
- 'Return': 13, \
- 'KP_Up': 2, 'KP_Down': 4, 'KP_Left': 1, \
- 'KP_Right': 3,}[self.tw.keypress]
- except:
- self.keyboard = 0
- self.tw.keypress = ""
+def empty_heap(lc): lc.heap = []
- def prim_setbox(self, name, x, val):
- if x is None:
- self.boxes[name]=val
- else:
- if type(convert(x, float, False)) == type(float):
- if int(float(x)) == x:
- x = int(x)
- self.boxes[name+str(x)]=val
+def tyo(n): print n
- def prim_push(self, val):
- self.heap.append(val)
+def millis(): return int(clock()*1000)
- def prim_pop(self):
- try:
- return self.heap.pop(-1)
- except:
- raise logoerror ("#emptyheap")
-
- def empty_heap(self):
- self.heap = []
-
- def save_picture(self, name):
- self.tw.save_as_image(name)
-
- def show_list(self, sarray):
- x = self.tw.canvas.xcor/self.tw.coord_scale
- y = self.tw.canvas.ycor/self.tw.coord_scale
- for s in sarray:
- self.tw.canvas.setxy(x, y)
- self.show(s)
- y -= int(self.bullet_height*2*self.tw.lead)
-
- def set_scale(self, x):
- self.scale = x
-
- # need to fix export logo to map show to write
- def show(self, string, center=False):
- # convert from Turtle coordinates to screen coordinates
- x = self.tw.canvas.width/2+int(self.tw.canvas.xcor)
- y = self.tw.canvas.height/2-int(self.tw.canvas.ycor)
- if type(string) == str or type(string) == unicode:
- if string == "media_None":
- pass
- elif string[0:6] == 'media_':
- self.insert_image(string, center)
- elif string[0:6] == 'descr_':
- self.insert_desc(string)
- elif string[0:6] == 'audio_':
- self.play_sound(string)
- else:
- if center is True:
- y -= self.tw.textsize
- self.tw.canvas.draw_text(string,x,y,self.tw.textsize,
- self.tw.canvas.width-x)
- elif type(string) == float or type(string) == int:
- string = round_int(string)
- if center is True:
- y -= self.tw.textsize
- self.tw.canvas.draw_text(string, x, y, self.tw.textsize,
- self.tw.canvas.width-x)
-
- def play_sound(self, audio):
- if audio == "" or audio[6:] == "":
- raise logoerror("#nomedia")
- if self.tw.running_sugar:
- if audio[6:] != "None":
- try:
- dsobject = datastore.get(audio[6:])
- play_audio(self, dsobject.file_path)
- except:
- print "Couldn't open id: " + str(audio[6:])
- else:
- play_audio(self, audio[6:])
- def show_picture(self, media, x, y, w, h):
- if media == "" or media[6:] == "":
- pass
- elif media[6:] is not "None":
- pixbuf = None
- if self.tw.running_sugar:
- try:
- dsobject = datastore.get(media[6:])
- if movie_media_type(dsobject.file_path):
- play_movie_from_file(self, dsobject.file_path,
- int(x), int(y), int(w), int(h))
- else:
- pixbuf = get_pixbuf_from_journal(dsobject,
- int(w), int(h))
- dsobject.destroy()
- except:
- # Maybe it is a pathname instead.
- try:
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
- media[6:], int(w), int(h))
- except:
- self.tw.showlabel('nojournal', media[6:])
- print "Couldn't open Journal object %s" % (media[6:])
- else:
- try:
- if movie_media_type(media):
- play_movie_from_file(self, media[6:], int(x), int(y),
- int(w), int(h))
- else:
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
- media[6:], int(w), int(h))
- except:
- self.tw.showlabel('nofile', media[6:])
- print "Couldn't open media object %s" % (media[6:])
- if pixbuf is not None:
- self.tw.canvas.draw_pixbuf(pixbuf, 0, 0, int(x), int(y),
- int(w), int(h))
-
- def show_description(self, media, x, y, w, h):
- if media == "" or media[6:] == "":
- return
- elif media[6:] is not "None":
- text = None
- if self.tw.running_sugar:
- try:
- dsobject = datastore.get(media[6:])
- text = str(dsobject.metadata['description'])
- dsobject.destroy()
- except:
- print "no description in %s" % (media[6:])
- else:
- try:
- f = open(media[6:], 'r')
- text = f.read()
- f.close()
- except:
- print "no text in %s?" % (media[6:])
- if text is not None:
- print "text: %s" % (text)
- self.tw.canvas.draw_text(text, int(x), int(y),
- self.body_height, int(w))
-
- def draw_title(self, title, x, y):
- self.tw.canvas.draw_text(title,int(x),int(y),self.title_height,
- self.tw.canvas.width-x)
- # image only (at current x,y)
- def insert_image(self, media, center):
- w = (self.tw.canvas.width * self.scale)/100
- h = (self.tw.canvas.height * self.scale)/100
- # convert from Turtle coordinates to screen coordinates
- x = self.tw.canvas.width/2+int(self.tw.canvas.xcor)
- y = self.tw.canvas.height/2-int(self.tw.canvas.ycor)
- if center is True:
- x -= w/2
- y -= h/2
- if media[0:5] == 'media':
- self.show_picture(media, x, y, w, h)
-
- # description text only (at current x,y)
- def insert_desc(self, media):
- w = (self.tw.canvas.width * self.scale)/100
- h = (self.tw.canvas.height * self.scale)/100
- # convert from Turtle coordinates to screen coordinates
- x = self.tw.canvas.width/2+int(self.tw.canvas.xcor)
- y = self.tw.canvas.height/2-int(self.tw.canvas.ycor)
- if media[0:5] == 'descr':
- self.show_description(media, x, y, w, h)
-
- """
- Depreciated block methods
- """
- # title, one image, and description
- def show_template1x1(self, title, media):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t1x1')
- x = -(self.tw.canvas.width/2)+xo
- y = self.tw.canvas.height/2
- self.tw.canvas.setxy(x, y)
- # save the text size so we can restore it later
- save_text_size = self.tw.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self.show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height*2) \
- / self.tw.canvas.height
- self.set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render media object
- # leave some space below the title
- y -= int(self.title_height*2*self.tw.lead)
- self.tw.canvas.setxy(x, y)
- self.show(media)
- if self.tw.running_sugar:
- x = 0
- self.tw.canvas.setxy(x, y)
- self.show(media.replace("media_","descr_"))
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- # title, two images (horizontal), two descriptions
- def show_template2x1(self, title, media1, media2):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t2x1')
- x = -(self.tw.canvas.width/2)+xo
- y = self.tw.canvas.height/2
- self.tw.canvas.setxy(x, y)
- # save the text size so we can restore it later
- save_text_size = self.tw.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self.show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height*2)/\
- self.tw.canvas.height
- self.set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render four quadrents
- # leave some space below the title
- y -= int(self.title_height*2*self.tw.lead)
- self.tw.canvas.setxy(x, y)
- self.show(media1)
- x = 0
- self.tw.canvas.setxy(x, y)
- self.show(media2)
- y = -self.title_height
- if self.tw.running_sugar:
- self.tw.canvas.setxy(x, y)
- self.show(media2.replace("media_","descr_"))
- x = -(self.tw.canvas.width/2)+xo
- self.tw.canvas.setxy(x, y)
- self.show(media1.replace("media_","descr_"))
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- # title and varible number of bullets
- def show_bullets(self, sarray):
- w,h,xo,yo,dx,dy = self.tw.calc_position('bullet')
- x = -(self.tw.canvas.width/2)+xo
- y = self.tw.canvas.height/2
- self.tw.canvas.setxy(x, y)
- # save the text size so we can restore it later
- save_text_size = self.tw.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self.show(sarray[0])
- # set body text size
- self.tw.canvas.settextsize(self.bullet_height)
- # leave some space below the title
- y -= int(self.title_height*2*self.tw.lead)
- for s in sarray[1:]:
- self.tw.canvas.setxy(x, y)
- self.show(s)
- y -= int(self.bullet_height*2*self.tw.lead)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- # title, two images (vertical), two desciptions
- def show_template1x2(self, title, media1, media2):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t1x2')
- x = -(self.tw.canvas.width/2)+xo
- y = self.tw.canvas.height/2
- self.tw.canvas.setxy(x, y)
- # save the text size so we can restore it later
- save_text_size = self.tw.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self.show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height*2)/\
- self.tw.canvas.height
- self.set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render four quadrents
- # leave some space below the title
- y -= int(self.title_height*2*self.tw.lead)
- self.tw.canvas.setxy(x, y)
- self.show(media1)
- if self.tw.running_sugar:
- x = 0
- self.tw.canvas.setxy(x, y)
- self.show(media1.replace("media_","descr_"))
- y = -self.title_height
- self.tw.canvas.setxy(x, y)
- self.show(media2.replace("media_","descr_"))
- x = -(self.tw.canvas.width/2)+xo
- self.tw.canvas.setxy(x, y)
- self.show(media2)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- # title and four images
- def show_template2x2(self, title, media1, media2, media3, media4):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t2x2')
- x = -(self.tw.canvas.width/2)+xo
- y = self.tw.canvas.height/2
- self.tw.canvas.setxy(x, y)
- # save the text size so we can restore it later
- save_text_size = self.tw.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self.show(title)
- # calculate and set scale for media blocks
- myscale = 45 * (self.tw.canvas.height - self.title_height*2)/\
- self.tw.canvas.height
- self.set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render four quadrents
- # leave some space below the title
- y -= int(self.title_height*2*self.tw.lead)
- self.tw.canvas.setxy(x, y)
- self.show(media1)
- x = 0
- self.tw.canvas.setxy(x, y)
- self.show(media2)
- y = -self.title_height
- self.tw.canvas.setxy(x, y)
- self.show(media4)
- x = -(self.tw.canvas.width/2)+xo
- self.tw.canvas.setxy(x, y)
- self.show(media3)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- # title, one media object
- def show_template1x1a(self, title, media1):
- w,h,xo,yo,dx,dy = self.tw.calc_position('t1x1a')
- x = -(self.tw.canvas.width/2)+xo
- y = self.tw.canvas.height/2
- self.tw.canvas.setxy(x, y)
- # save the text size so we can restore it later
- save_text_size = self.tw.textsize
- # set title text
- self.tw.canvas.settextsize(self.title_height)
- self.show(title)
- # calculate and set scale for media blocks
- myscale = 90 * (self.tw.canvas.height - self.title_height*2) /\
- self.tw.canvas.height
- self.set_scale(myscale)
- # set body text size
- self.tw.canvas.settextsize(self.body_height)
- # render media object
- # leave some space below the title
- y -= int(self.title_height*2*self.tw.lead)
- self.tw.canvas.setxy(x, y)
- self.show(media1)
- # restore text size
- self.tw.canvas.settextsize(save_text_size)
-
- def write(self, string, fsize):
- # convert from Turtle coordinates to screen coordinates
- x = self.tw.canvas.width/2+int(self.tw.canvas.xcor)
- y = self.tw.canvas.height/2-int(self.tw.canvas.ycor)
- self.tw.canvas.draw_text(string,x,y-15,int(fsize),self.tw.canvas.width)
diff --git a/tawindow.py b/tawindow.py
index f33d8b6..c626fb9 100644
--- a/tawindow.py
+++ b/tawindow.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#Copyright (c) 2007, Playful Invention Company
-#Copyright (c) 2008-10, Walter Bender
-#Copyright (c) 2009-10 Raúl Gutiérrez Segalés
+#Copyright (c) 2008-9, Walter Bender
+#Copyright (c) 2009, Raúl Gutiérrez Segalés
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
@@ -21,13 +21,6 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
-
-# TODO:
-# - better comments!
-# - many methods could have their logic simplified!
-# - verbose flag should be in the scope of the object instance
-
-
import pygtk
pygtk.require('2.0')
import gtk
@@ -36,2540 +29,892 @@ import gobject
import os
import os.path
import time
+
+# Import from Journal for these blocks
+importblocks = ['audiooff', 'descriptionoff','journal']
+
+class taWindow: pass
+
from math import atan2, pi
DEGTOR = 2*pi/360
-from gettext import gettext as _
+from taarduino import *
+from tasetup import *
+from tasprites import *
+from talogo import *
+from taturtle import *
+from taproject import *
try:
from sugar.graphics.objectchooser import ObjectChooser
- from sugar.datastore import datastore
- from sugar import profile
-except ImportError:
+except:
pass
-from taconstants import *
-from talogo import LogoCode, stop_logo, convert, str_to_num
-from tacanvas import TurtleGraphics
-from tablock import Blocks, Block
-from taturtle import Turtles, Turtle
-from tautils import magnitude, get_load_name, get_save_name, data_from_file,\
- data_to_file, round_int, get_id, get_pixbuf_from_journal,\
- movie_media_type, audio_media_type, image_media_type,\
- save_picture, calc_image_size
-from tasprite_factory import SVG, svg_str_to_pixbuf, svg_from_file
-from sprites import Sprites, Sprite
-
-"""
-Dock tests
-"""
-
-def numeric_arg(value):
- if type(convert(value, float)) is float:
- return True
- return False
-
-def zero_arg(value):
- if numeric_arg(value):
- if convert(value, float) == 0:
- return True
- return False
-
-def neg_arg(value):
- if numeric_arg(value):
- if convert(value, float) < 0:
- return True
- return False
-
-"""
-TurtleArt Window class abstraction
-"""
-class TurtleArtWindow():
-
- # Time out for triggering help
- timeout_tag = [0]
-
- def __init__(self, win, path, lang, parent=None, mycolors=None):
- self._setup_initial_values(win, path, lang, parent, mycolors)
- self._setup_misc()
- self._show_toolbar_palette(0, False)
-
- def _setup_initial_values(self, win, path, lang, parent, mycolors):
- self.window = win
- self.path = os.path.join(path, 'images')
- self.load_save_folder = os.path.join(path, 'samples')
- self.save_folder = None
- self.save_file_name = None
- self.window.set_flags(gtk.CAN_FOCUS)
- self.width = gtk.gdk.screen_width()
- self.height = gtk.gdk.screen_height()
- if parent is not None:
- parent.show_all()
- self.running_sugar = True
- else:
- self.window.show_all()
- self.running_sugar = False
- self._setup_events()
- self.keypress = ""
- self.keyvalue = 0
- self.dead_key = ""
- self.area = self.window.window
- self.gc = self.area.new_gc()
- if self._OLPC_XO_1():
- self.lead = 1.0
- self.scale = 0.67
- else:
- self.lead = 1.0
- self.scale = 1.0
- self.block_scale = BLOCK_SCALE
- self.trash_scale = 0.5
- self.cm = self.gc.get_colormap()
- self.rgb = [255,0,0]
- self.bgcolor = self.cm.alloc_color('#fff8de')
- self.msgcolor = self.cm.alloc_color('black')
- self.fgcolor = self.cm.alloc_color('red')
- self.textcolor = self.cm.alloc_color('blue')
- self.textsize = 32
- self.myblock = None
- self.nop = 'nop'
- self.loaded = 0
- self.step_time = 0
- self.hide = False
- self.palette = True
- self.coord_scale = 1
- self.buddies = []
- self.saved_string = ''
- self.dx = 0
- self.dy = 0
- self.media_shapes = {}
- self.cartesian = False
- self.polar = False
- self.overlay_shapes = {}
- self.status_spr = None
- self.status_shapes = {}
- self.toolbar_spr = None
- self.palette_sprs = []
- self.palettes = []
- self.palette_button = []
- self.orientation = 0
- self.trash_index = PALETTE_NAMES.index('trash')
- self.trash_stack = []
- self.selected_palette = None
- self.previous_palette = None
- self.selectors = []
- self.selected_selector = None
- self.previous_selector = None
- self.selector_shapes = []
- self.selected_blk = None
- self.selected_spr = None
- self.drag_group = None
- self.drag_turtle = 'move', 0, 0
- self.drag_pos = 0, 0
- self.block_list = Blocks(self.scale)
- self.sprite_list = Sprites(self.window, self.area, self.gc)
- self.turtles = Turtles(self.sprite_list)
- if mycolors == None:
- Turtle(self.turtles, 1)
- else:
- Turtle(self.turtles, 1, mycolors.split(','))
- self.active_turtle = self.turtles.get_turtle(1)
- self.selected_turtle = None
- self.canvas = TurtleGraphics(self, self.width, self.height)
- self.titlex = -(self.canvas.width*TITLEXY[0])/(self.coord_scale*2)
- self.leftx = -(self.canvas.width*TITLEXY[0])/(self.coord_scale*2)
- self.rightx = 0
- self.titley = (self.canvas.height*TITLEXY[1])/(self.coord_scale*2)
- self.topy = (self.canvas.height*(TITLEXY[1]-0.125))/(self.coord_scale*2)
- self.bottomy = 0
- self.lc = LogoCode(self)
-
- """
- Register the events we listen to.
- """
- def _setup_events(self):
- self.window.add_events(gtk.gdk.BUTTON_PRESS_MASK)
- self.window.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
- self.window.add_events(gtk.gdk.POINTER_MOTION_MASK)
- self.window.add_events(gtk.gdk.KEY_PRESS_MASK)
- self.window.connect("expose-event", self._expose_cb)
- self.window.connect("button-press-event", self._buttonpress_cb)
- self.window.connect("button-release-event", self._buttonrelease_cb)
- self.window.connect("motion-notify-event", self._move_cb)
- self.window.connect("key_press_event", self._keypress_cb)
-
- """
- Misc. sprites for status, overlays, etc.
- """
- def _setup_misc(self):
- # media blocks get positioned into other blocks
- for name in MEDIA_SHAPES:
- if name[0:7] == 'journal' and not self.running_sugar:
- filename = 'file'+name[7:]
- else:
- filename = name
- self.media_shapes[name] = \
- svg_str_to_pixbuf(svg_from_file("%s/%s.svg" % (
- self.path, filename)))
-
- for i, name in enumerate(STATUS_SHAPES):
- self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file(
- "%s/%s.svg" % (self.path, name)))
- self.status_spr = Sprite(self.sprite_list, 0, self.height-200,
- self.status_shapes['status'])
- self.status_spr.hide()
- self.status_spr.type = 'status'
-
- for name in OVERLAY_SHAPES:
- self.overlay_shapes[name] = Sprite(self.sprite_list,
- int(self.width/2-600), int(self.height/2-450),
- svg_str_to_pixbuf(svg_from_file(
- "%s/%s.svg" % (self.path, name))))
- self.overlay_shapes[name].hide()
- self.overlay_shapes[name].type = 'overlay'
-
- """
- Is a chattube available for sharing?
- """
- def _sharing(self):
- if self.running_sugar and hasattr(self.activity, 'chattube') and\
- self.activity.chattube is not None:
- return True
- return False
+from tahoverhelp import *
+from gettext import gettext as _
- """
- Is the an OLPC XO-1?
- """
- def _OLPC_XO_1(self):
- return os.path.exists('/etc/olpc-release') or \
- os.path.exists('/sys/power/olpc-pm')
-
- """
- Repaint
- """
- def _expose_cb(self, win, event):
- self.sprite_list.redraw_sprites()
+# dead key dictionaries
+dead_grave = {'A':192,'E':200,'I':204,'O':210,'U':217,'a':224,'e':232,'i':236,\
+ 'o':242,'u':249}
+dead_acute = {'A':193,'E':201,'I':205,'O':211,'U':218,'a':225,'e':233,'i':237,\
+ 'o':243,'u':250}
+dead_circumflex = {'A':194,'E':202,'I':206,'O':212,'U':219,'a':226,'e':234,\
+ 'i':238,'o':244,'u':251}
+dead_tilde = {'A':195,'O':211,'N':209,'U':360,'a':227,'o':245,'n':241,'u':361}
+dead_diaeresis = {'A':196,'E':203,'I':207,'O':211,'U':218,'a':228,'e':235,\
+ 'i':239,'o':245,'u':252}
+dead_abovering = {'A':197,'a':229}
+
+# Time out for triggering help
+timeout_tag = [0]
+
+
+#
+# Setup
+#
+
+def twNew(win, path, lang, parent=None):
+ tw = taWindow()
+ tw.window = win
+ tw.path = os.path.join(path,'images')
+ tw.path_lang = os.path.join(path,'images',lang)
+ tw.path_en = os.path.join(path,'images/en') # en as fallback
+ tw.load_save_folder = os.path.join(path,'samples')
+ tw.save_folder = None
+ tw.save_file_name = None
+ win.set_flags(gtk.CAN_FOCUS)
+ tw.width = gtk.gdk.screen_width()
+ tw.height = gtk.gdk.screen_height()
+ # starting from command line
+ if parent is None:
+ win.show_all()
+ # starting from Sugar
+ else:
+ parent.show_all()
+ win.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ win.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
+ win.add_events(gtk.gdk.POINTER_MOTION_MASK)
+ win.add_events(gtk.gdk.KEY_PRESS_MASK)
+ win.connect("expose-event", expose_cb, tw)
+ win.connect("button-press-event", buttonpress_cb, tw)
+ win.connect("button-release-event", buttonrelease_cb, tw)
+ win.connect("motion-notify-event", move_cb, tw)
+ win.connect("key_press_event", keypress_cb, tw)
+ tw.keypress = ""
+ tw.keyvalue = 0
+ tw.dead_key = ""
+ tw.area = win.window
+ tw.gc = tw.area.new_gc()
+ # on an OLPC-XO-1, there is a scaling factor
+ if os.path.exists('/etc/olpc-release') or \
+ os.path.exists('/sys/power/olpc-pm'):
+ tw.lead = 1.6
+ tw.scale = 1.0
+ else:
+ tw.lead = 1.0
+ tw.scale = 1.6
+ tw.cm = tw.gc.get_colormap()
+ tw.rgb = [255,0,0]
+ tw.bgcolor = tw.cm.alloc_color('#fff8de')
+ tw.msgcolor = tw.cm.alloc_color('black')
+ tw.fgcolor = tw.cm.alloc_color('red')
+ tw.textcolor = tw.cm.alloc_color('blue')
+ tw.textsize = 32
+ tw.sprites = []
+ tw.selected_block = None
+ tw.draggroup = None
+ prep_selectors(tw)
+ tw.myblock = None
+ tw.nop = 'nop'
+ tw.loaded = 0
+ for s in selectors:
+ setup_selectors(tw,s)
+ setup_misc(tw)
+ tw.step_time = 0
+ tw.hide = False
+ tw.palette = True
+ select_category(tw, tw.selbuttons[0])
+ tw.coord_scale = 1
+ tw.turtle = tNew(tw,tw.width,tw.height)
+ tw.lc = lcNew(tw)
+ tw.buddies = []
+ tw.dx = 0
+ tw.dy = 0
+ tw.cartesian = False
+ tw.polar = False
+ tw.spr = None # "currently selected spr"
+ tw.arduino = TAArduino()
+ return tw
+
+#
+# Button Press
+#
+
+def buttonpress_cb(win, event, tw):
+ win.grab_focus()
+ x, y = xy(event)
+ button_press(tw, event.get_state()&gtk.gdk.CONTROL_MASK, x, y)
+ # if sharing, send button press
+ if hasattr(tw, 'activity') and \
+ hasattr(tw.activity, 'chattube') and tw.activity.chattube is not None:
+ # print "sending button pressed"
+ if event.get_state()&gtk.gdk.CONTROL_MASK is True:
+ tw.activity._send_event("p:"+str(x)+":"+str(y)+":"+'T')
+ else:
+ tw.activity._send_event("p:"+str(x)+":"+str(y)+":"+'F')
+ return True
+
+def button_press(tw, mask, x, y, verbose=False):
+ if verbose:
+ print "processing remote button press: " + str(x) + " " + str(y)
+ tw.block_operation = 'click'
+ if tw.selected_block!=None:
+ unselect(tw)
+ else:
+ setlayer(tw.status_spr,400)
+ spr = findsprite(tw,(x,y))
+ tw.x, tw.y = x,y
+ tw.dx = 0
+ tw.dy = 0
+ if spr is None:
return True
-
-
- """
- Eraser_button (Always hide status block when clearing the screen.)
- """
- def eraser_button(self):
- if self.status_spr is not None:
- self.status_spr.hide()
- self.lc.prim_clear()
- self.display_coordinates()
-
- """
- Run turtle!
- """
- def run_button(self, time):
- if self.running_sugar:
- self.activity.recenter()
- # Look for a 'start' block
- for blk in self.just_blocks():
- if self._find_start_stack(blk):
- self.step_time = time
- print "running stack starting from %s" % (blk.name)
- self._run_stack(blk)
- return
- # If there is no 'start' block, run stacks that aren't 'def action'
- for blk in self.just_blocks():
- if self._find_block_to_run(blk):
- self.step_time = time
- print "running stack starting from %s" % (blk.name)
- self._run_stack(blk)
+ if spr.type == "canvas":
+ return True
+ elif spr.type == 'selbutton':
+ select_category(tw,spr)
+ elif spr.type == 'category':
+ block_selector_pressed(tw,x,y)
+ elif spr.type == 'block':
+ block_pressed(tw,mask,x,y,spr)
+ elif spr.type == 'turtle':
+ turtle_pressed(tw,x,y)
+ tw.spr = spr
+
+def block_selector_pressed(tw,x,y):
+ proto = get_proto_from_category(tw,x,y)
+ if proto==None:
return
+ if proto is not 'hide':
+ new_block_from_category(tw,proto,x,y)
+ else:
+ hideshow_palette(tw,False)
+
+def hideshow_palette(tw,state):
+ if state is False:
+ tw.palette == False
+ if hasattr(tw,'activity'):
+ # Use new toolbar design
+ tw.activity.do_hidepalette()
+ hide_palette(tw)
+ else:
+ tw.palette == True
+ if hasattr(tw,'activity'):
+ # Use new toolbar design
+ tw.activity.do_showpalette()
+ show_palette(tw)
+
+def show_palette(tw):
+ for i in tw.selbuttons: setlayer(i,800)
+ select_category(tw,tw.selbuttons[0])
+ tw.palette = True
+
+def hide_palette(tw):
+ for i in tw.selbuttons: hide(i)
+ setshape(tw.category_spr, tw.hidden_palette_icon)
+ tw.palette = False
+
+def get_proto_from_category(tw,x,y):
+ dx,dy = x-tw.category_spr.x, y-tw.category_spr.y,
+ pixel = getpixel(tw.current_category.mask,dx,dy)
+ index = ((pixel%256)>>3)-1
+ if index==0:
+ return 'hide'
+ index-=1
+ if index>len(tw.current_category.blockprotos):
+ return None
+ return tw.current_category.blockprotos[index]
- """
- Stop button
- """
- def stop_button(self):
- stop_logo(self)
-
- """
- Change the icon for user-defined blocks after Python code is loaded.
- """
- def set_userdefined(self):
- for blk in self.just_blocks():
- if blk.name == 'nop':
- x, y = self._calc_image_offset('pythonon', blk.spr)
- blk.set_image(self.media_shapes['pythonon'], x, y)
- self._resize_skin(blk)
- self.nop = 'pythonloaded'
-
- """
- Enter fulscreen mode
- """
- def set_fullscreen(self):
- if self.running_sugar:
- self.activity.fullscreen()
- self.activity.recenter()
-
- """
- Hide/show button
- """
- def hideshow_button(self):
- if self.hide is False:
- for blk in self.just_blocks():
- blk.spr.hide()
- self.hide_palette()
- self.hide = True
- else:
- for blk in self.just_blocks():
- if blk.status != 'collapsed':
- blk.spr.set_layer(BLOCK_LAYER)
- self.show_palette()
- self.hide = False
- self.canvas.canvas.inval()
-
- """
- Hide or show palette
- """
- def hideshow_palette(self, state):
- if state is False:
- self.palette == False
- if self.running_sugar:
- self.activity.do_hidepalette()
- self.hide_palette()
- else:
- self.palette == True
- if self.running_sugar:
- self.activity.do_showpalette()
- self.show_palette()
-
- """
- Show palette
- """
- def show_palette(self, n=0):
- self._show_toolbar_palette(n)
- self.palette_button[self.orientation].set_layer(TAB_LAYER)
- self.toolbar_spr.set_layer(CATEGORY_LAYER)
- self.palette = True
-
- """
- Hide the palette.
- """
- def hide_palette(self):
- self._hide_toolbar_palette()
- self.palette_button[self.orientation].hide()
- self.toolbar_spr.hide()
- self.palette = False
-
- """
- Callback from 'hide blocks' block
- """
- def hideblocks(self):
- self.hide = False
- self.hideshow_button()
- if self.running_sugar:
- self.activity.do_hide()
-
- """
- Callback from 'show blocks' block
- """
- def showblocks(self):
- self.hide = True
- self.hideshow_button()
- if self.running_sugar:
- self.activity.do_show()
-
- """
- Resize all of the blocks
- """
- def resize_blocks(self):
- # We need to restore collapsed stacks before resizing.
- for b in self.just_blocks():
- if b.status == 'collapsed':
- bot = self._find_sandwich_bottom(b)
- if self._collapsed(bot):
- dy = bot.values[0]
- self._restore_stack(self._find_sandwich_top(b))
- bot.values[0] = dy
-
- # Do the resizing.
- for b in self.just_blocks():
- b.rescale(self.block_scale)
- for b in self.just_blocks():
- self._adjust_dock_positions(b)
-
- # Re-collapsed stacks after resizing.
- for b in self.just_blocks():
- if self._collapsed(b):
- self._collapse_stack(self._find_sandwich_top(b))
- for b in self.just_blocks():
- if b.name == 'sandwichtop':
- self._grow_stack_arm(b)
-
- # Resize the skins on some blocks: media content and Python
- for b in self.just_blocks():
- if b.name in BLOCKS_WITH_SKIN:
- self._resize_skin(b)
-
- """
- Show the toolbar palettes, creating them on init_only
- """
- def _show_toolbar_palette(self, n, init_only=False):
- # Create the selectors the first time through.
- if self.selectors == []:
- svg = SVG()
- x, y = 50, 0
- for i, name in enumerate(PALETTE_NAMES):
- a = svg_str_to_pixbuf(svg_from_file("%s/%soff.svg" % (
- self.path, name)))
- b = svg_str_to_pixbuf(svg_from_file("%s/%son.svg" % (
- self.path, name)))
- self.selector_shapes.append([a,b])
- self.selectors.append(Sprite(self.sprite_list, x, y, a))
- self.selectors[i].type = 'selector'
- self.selectors[i].name = name
- self.selectors[i].set_layer(TAB_LAYER)
- w, h = self.selectors[i].get_dimensions()
- x += int(w)
- self.palette_sprs.append([None,None])
-
- # Create the palette orientation button
- self.palette_button.append(Sprite(self.sprite_list, 0, ICON_SIZE,
- svg_str_to_pixbuf(svg_from_file(
- "%s/palettehorizontal.svg" %(self.path)))))
- self.palette_button.append(Sprite(self.sprite_list, 0, ICON_SIZE,
- svg_str_to_pixbuf(svg_from_file(
- "%s/palettevertical.svg" % (self.path)))))
- self.palette_button[0].name = 'orientation'
- self.palette_button[1].name = 'orientation'
- self.palette_button[0].type = 'palette'
- self.palette_button[1].type = 'palette'
- self.palette_button[self.orientation].set_layer(TAB_LAYER)
- self.palette_button[1-self.orientation].hide()
- # Create the toolbar background
- self.toolbar_spr = Sprite(self.sprite_list, 0, 0,
- svg_str_to_pixbuf(svg.toolbar(self.width, ICON_SIZE)))
- self.toolbar_spr.type = 'toolbar'
- self.toolbar_spr.set_layer(CATEGORY_LAYER)
-
- # Create the empty palettes
- if len(self.palettes) == 0:
- for i in range(len(PALETTES)):
- self.palettes.append([]);
-
- if init_only is True:
- return
+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)
- # Hide the previously displayed palette
- self._hide_previous_palette()
-
- self.selected_palette = n
- self.previous_palette = self.selected_palette
- self.selected_selector = self.selectors[n]
-
- # Make sure all of the selectors are visible.
- self.selectors[n].set_shape(self.selector_shapes[n][1])
- for i in range(len(PALETTES)):
- self.selectors[i].set_layer(TAB_LAYER)
-
- # Show the palette with the current orientation.
- if self.palette_sprs[n][self.orientation] is not None:
- self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER)
-
- if self.palettes[n] == []:
- # Create 'proto' blocks for each palette entry
- for i, name in enumerate(PALETTES[n]):
- self.palettes[n].append(Block(self.block_list,
- self.sprite_list, name,
- 0, 0, 'proto', [], PALETTE_SCALE))
- self.palettes[n][i].spr.set_layer(TAB_LAYER)
- self.palettes[n][i].unhighlight()
-
- # Some proto blocks get a skin.
- if name in BOX_STYLE_MEDIA:
- self._proto_skin(name+'small', n, i)
- elif name[:8] == 'template':
- self._proto_skin(name[8:], n, i)
- elif name[:7] == 'picture':
- self._proto_skin(name[7:], n, i)
- elif name == 'nop':
- self._proto_skin('pythonsmall', n, i)
-
- self._layout_palette(n)
- for blk in self.palettes[n]:
- blk.spr.set_layer(TAB_LAYER)
- if n == PALETTE_NAMES.index('trash'):
- for blk in self.trash_stack:
- for b in self._find_group(blk):
- if b.status != 'collapsed':
- b.spr.set_layer(TAB_LAYER)
-
- """
- Hide the toolbar palettes
- """
- def _hide_toolbar_palette(self):
- self._hide_previous_palette()
- # Hide the selectors
- for i in range(len(PALETTES)):
- self.selectors[i].hide()
- self.selected_palette = None
- self.previous_palette = None
-
- """
- Hide just the previously viewed toolbar palette
- """
- def _hide_previous_palette(self):
- # Hide previous palette
- if self.previous_palette is not None:
- for i in range(len(PALETTES[self.previous_palette])):
- self.palettes[self.previous_palette][i].spr.hide()
- self.palette_sprs[self.previous_palette][
- self.orientation].hide()
- self.selectors[self.previous_palette].set_shape(
- self.selector_shapes[self.previous_palette][0])
- if self.previous_palette == PALETTE_NAMES.index('trash'):
- for b in self.trash_stack:
- for bb in self._find_group(b):
- bb.spr.hide()
-
- """
- Position prototypes in a horizontal palette.
- """
- def _horizontal_layout(self, x, y, blocks):
- _max_w = 0
- for b in blocks:
- _w, _h = self._width_and_height(b)
- if y+_h > PALETTE_HEIGHT+ICON_SIZE:
- x += int(_max_w+5)
- y = ICON_SIZE+5
- _max_w = 0
- (_bx, _by) = b.spr.get_xy()
- _dx = x-_bx
- _dy = y-_by
- for g in self._find_group(b):
- g.spr.move_relative((int(_dx), int(_dy)))
- y += int(_h+5)
- if _w > _max_w:
- _max_w = _w
- return x, y, _max_w
-
- """
- Position prototypes in a vertical palette.
- """
- def _vertical_layout(self, x, y, blocks):
- _row = []
- _row_w = 0
- _max_h = 0
- for _b in blocks:
- _w, _h = self._width_and_height(_b)
- if x+_w > PALETTE_WIDTH:
- # Recenter row.
- _dx = int((PALETTE_WIDTH-_row_w)/2)
- for _r in _row:
- for _g in self._find_group(_r):
- _g.spr.move_relative((_dx, 0))
- _row = []
- _row_w = 0
- x = 5
- y += int(_max_h+5)
- _max_h = 0
- _row.append(_b)
- _row_w += (5+_w)
- (_bx, _by) = _b.spr.get_xy()
- _dx = int(x-_bx)
- _dy = int(y-_by)
- for _g in self._find_group(_b):
- _g.spr.move_relative((_dx, _dy))
- x += int(_w+5)
- if _h > _max_h:
- _max_h = _h
- # Recenter last row.
- _dx = int((PALETTE_WIDTH-_row_w)/2)
- for _r in _row:
- for _g in self._find_group(_r):
- _g.spr.move_relative((_dx, 0))
- return x, y, _max_h
-
- """
- Layout prototypes in a palette.
- """
- def _layout_palette(self, n):
- if n is not None:
- if self.orientation == 0:
- _x, _y = 20, ICON_SIZE+5
- _x, _y, _max = self._horizontal_layout(_x, _y, self.palettes[n])
- if n == PALETTE_NAMES.index('trash'):
- _x, _y, _max = self._horizontal_layout(_x+_max, _y,
- self.trash_stack)
- _w = _x+_max+25
- if self.palette_sprs[n][self.orientation] is None:
- svg = SVG()
- self.palette_sprs[n][self.orientation] = Sprite(
- self.sprite_list, 0, ICON_SIZE,
- svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT)))
- self.palette_sprs[n][self.orientation].type = 'category'
- if n == PALETTE_NAMES.index('trash'):
- svg = SVG()
- self.palette_sprs[n][self.orientation].set_shape(
- svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT)))
- else:
- _x, _y = 5, ICON_SIZE+15
- _x, _y, _max = self._vertical_layout(_x, _y, self.palettes[n])
- if n == PALETTE_NAMES.index('trash'):
- _x, _y, _max = self._vertical_layout(_x, _y+_max,
- self.trash_stack)
- _h = _y+_max+25-ICON_SIZE
- if self.palette_sprs[n][self.orientation] is None:
- svg = SVG()
- self.palette_sprs[n][self.orientation] =\
- Sprite(self.sprite_list, 0, ICON_SIZE,
- svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h)))
- self.palette_sprs[n][self.orientation].type = 'category'
- if n == PALETTE_NAMES.index('trash'):
- svg = SVG()
- self.palette_sprs[n][self.orientation].set_shape(
- svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h)))
- self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER)
-
- """
- Button press
- """
- def _buttonpress_cb(self, win, event):
- self.window.grab_focus()
- x, y = self._xy(event)
- self.button_press(event.get_state()&gtk.gdk.CONTROL_MASK, x, y)
- if self._sharing():
- if event.get_state()&gtk.gdk.CONTROL_MASK is True:
- self.activity._send_event("p:%d:%d:T" % (x, y))
- else:
- self.activity._send_event("p:%d:%d:F" % (x, y))
+def new_block_from_category(tw,proto,x,y):
+ if proto is None:
return True
-
- def button_press(self, mask, x, y, verbose=False):
- if verbose:
- print "processing remote button press: %d, %d" % (x, y)
- self.block_operation = 'click'
-
- # Unselect things that may have been selected earlier
- if self.selected_blk is not None:
- self._unselect_block()
- self.selected_turtle = None
- # Always hide the status layer on a click
- if self.status_spr is not None:
- self.status_spr.hide()
-
- # Find out what was clicked
- spr = self.sprite_list.find_sprite((x,y))
- self.dx = 0
- self.dy = 0
- if spr is None:
- return True
- self.selected_spr = spr
-
- # From the sprite at x, y, look for a corresponding block
- blk = self.block_list.spr_to_block(spr)
- if blk is not None:
- if blk.type == 'block':
- self.selected_blk = blk
- self._block_pressed(mask, x, y, blk)
- elif blk.type == 'trash':
- self._restore_from_trash(self.find_top_block(blk))
- elif blk.type == 'proto':
- if blk.name == 'restoreall':
- self._restore_all_from_trash()
- elif blk.name == 'restore':
- self._restore_latest_from_trash()
- elif blk.name == 'empty':
- self._empty_trash()
- elif MACROS.has_key(blk.name):
- self._new_macro(blk.name, x+20, y+20)
- else:
- blk.highlight()
- self._new_block(blk.name, x, y)
- blk.unhighlight()
- return True
-
- # Next, look for a turtle
- t = self.turtles.spr_to_turtle(spr)
- if t is not None:
- self.selected_turtle = t
- self.canvas.set_turtle(self.turtles.get_turtle_key(t))
- self._turtle_pressed(x, y)
- return True
-
- # Finally, check for anything else
- if hasattr(spr, 'type'):
- if spr.type == "canvas":
- pass
- # spr.set_layer(CANVAS_LAYER)
- elif spr.type == 'selector':
- self._select_category(spr)
- elif spr.type == 'category':
- if self._hide_button_hit(spr, x, y):
- self.hideshow_palette(False)
- elif spr.type == 'palette':
- self.orientation = 1-self.orientation
- self.palette_button[self.orientation].set_layer(TAB_LAYER)
- self.palette_button[1-self.orientation].hide()
- self.palette_sprs[self.selected_palette][
- 1-self.orientation].hide()
- self._layout_palette(self.selected_palette)
- self.show_palette(self.selected_palette)
- return True
-
- """
- Select a category from the toolbar.
- """
- def _select_category(self, spr):
- i = self.selectors.index(spr)
- spr.set_shape(self.selector_shapes[i][1])
- if self.selected_selector is not None:
- j = self.selectors.index(self.selected_selector)
- if i == j:
- return
- self.selected_selector.set_shape(self.selector_shapes[j][0])
- self.previous_selector = self.selected_selector
- self.selected_selector = spr
- self.show_palette(i)
-
- """
- Put a group of blocks into the trash.
- """
- def _put_in_trash(self, blk, x=0, y=0):
- self.trash_stack.append(blk)
- group = self._find_group(blk)
- for b in group:
- if b.status == 'collapsed':
- # Collapsed stacks are restored for rescaling
- # and then recollapsed after they are moved to the trash.
- bot = self._find_sandwich_bottom(b)
- if self._collapsed(bot):
- dy = bot.values[0]
- self._restore_stack(self._find_sandwich_top(b))
- bot.values[0] = dy
- b.type = 'trash'
- b.rescale(self.trash_scale)
- blk.spr.move((x,y))
- for b in group:
- self._adjust_dock_positions(b)
-
- # Re-collapsing any stacks we had restored for scaling
- for b in group:
- if self._collapsed(b):
- self._collapse_stack(self._find_sandwich_top(b))
-
- # And resize any skins.
- for b in group:
- if b.name in BLOCKS_WITH_SKIN:
- self._resize_skin(b)
-
- self.show_palette(PALETTE_NAMES.index('trash'))
-
- """
- Restore all the blocks in the trash can
- """
- def _restore_all_from_trash(self):
- for b in self.block_list.list:
- if b.type == 'trash':
- self._restore_from_trash(b)
-
- """
- Restore latest blocks from the trash can
- """
- def _restore_latest_from_trash(self):
- if len(self.trash_stack) == 0:
- return
- self._restore_from_trash(self.trash_stack[len(self.trash_stack)-1])
-
- def _restore_from_trash(self, blk):
- group = self._find_group(blk)
- for b in group:
- b.rescale(self.block_scale)
- b.spr.set_layer(BLOCK_LAYER)
- x,y = b.spr.get_xy()
- if self.orientation == 0:
- b.spr.move((x,y+PALETTE_HEIGHT+ICON_SIZE))
- else:
- b.spr.move((x+PALETTE_WIDTH,y))
- b.type = 'block'
- for b in group:
- self._adjust_dock_positions(b)
- # If the stack had been collapsed before going into the trash,
- # collapse it again now.
- for b in group:
- if self._collapsed(b):
- self._collapse_stack(self._find_sandwich_top(b))
- # And resize any skins.
- for b in group:
- if b.name in BLOCKS_WITH_SKIN:
- self._resize_skin(b)
-
- self.trash_stack.remove(blk)
-
- """
- Permanently remove blocks in the trash can
- """
- def _empty_trash(self):
- for b in self.block_list.list:
- if b.type == 'trash':
- b.type = 'deleted'
- b.spr.hide()
- self.trash_stack = []
-
- """
- Is x,y over the trash can?
- """
- def _in_the_trash(self, x, y):
- if self.selected_palette == self.trash_index and \
- self.palette_sprs[self.trash_index][self.orientation].hit((x,y)):
- return True
- return False
-
- """
- Block pressed
- """
- def _block_pressed(self, mask, x, y, blk):
- if blk is not None:
- blk.highlight()
- self._disconnect(blk)
- self.drag_group = self._find_group(blk)
- (sx, sy) = blk.spr.get_xy()
- self.drag_pos = x-sx, y-sy
- for blk in self.drag_group:
- if blk.status != 'collapsed':
- blk.spr.set_layer(TOP_LAYER)
- self.saved_string = blk.spr.labels[0]
-
- """
- Unselect block
- """
- def _unselect_block(self):
- # After unselecting a 'number' block, we need to check its value
- if self.selected_blk.name == 'number':
- self._number_check()
- elif self.selected_blk.name == 'string':
- self._string_check()
- self.selected_blk.unhighlight()
- self.selected_blk = None
-
- """
- Make a new block.
- """
- def _new_block(self, name, x, y):
- if name in CONTENT_BLOCKS:
- newblk = Block(self.block_list, self.sprite_list, name, x-20, y-20,
- 'block', DEFAULTS[name], self.block_scale)
- else:
- newblk = Block(self.block_list, self.sprite_list, name, x-20, y-20,
- 'block', [], self.block_scale)
-
- # Add a 'skin' to some blocks
- if name == 'nop':
- if self.nop == 'pythonloaded':
- self._block_skin('pythonon', newblk)
- else:
- self._block_skin('pythonoff', newblk)
- elif name in BOX_STYLE_MEDIA:
- self._block_skin(name+'off', newblk)
-
- newspr = newblk.spr
- newspr.set_layer(TOP_LAYER)
- self.drag_pos = 20, 20
- newblk.connections = [None]*len(newblk.docks)
- if DEFAULTS.has_key(newblk.name):
- for i, argvalue in enumerate(DEFAULTS[newblk.name]):
- # skip the first dock position since it is always a connector
- dock = newblk.docks[i+1]
- argname = dock[0]
- if argname == 'unavailable':
- continue
- if argname == 'media':
- argname = 'journal'
- elif argname == 'number' and\
- (type(argvalue) is str or type(argvalue) is unicode):
- argname = 'string'
- elif argname == 'bool':
- argname = argvalue
- elif argname == 'flow':
- argname = argvalue
- (sx, sy) = newspr.get_xy()
- if argname is not None:
- if argname in CONTENT_BLOCKS:
- argblk = Block(self.block_list, self.sprite_list,
- argname, 0, 0, 'block', [argvalue],
- self.block_scale)
- else:
- argblk = Block(self.block_list, self.sprite_list,
- argname, 0, 0, 'block', [],
- self.block_scale)
- argdock = argblk.docks[0]
- nx, ny = sx+dock[2]-argdock[2], sy+dock[3]-argdock[3]
- if argname == 'journal':
- self._block_skin('journaloff', argblk)
- argblk.spr.move((nx, ny))
- argblk.spr.set_layer(TOP_LAYER)
- argblk.connections = [newblk, None]
- newblk.connections[i+1] = argblk
- self.drag_group = self._find_group(newblk)
- self.block_operation = 'new'
-
- """
- Create a "macro" (predefined stack of blocks)
- """
- def _new_macro(self, name, x, y):
- macro = MACROS[name]
- macro[0][2] = x
- macro[0][3] = y
- top = self.process_data(macro)
- self.block_operation = 'new'
- self._check_collapsibles(top)
- self.drag_group = self._find_group(top)
-
- """
- Process data (from a macro, a file, or the clipboard) into blocks.
- """
- def process_data(self, data):
- # Create the blocks (or turtle).
- blocks = []
- for b in data:
- if self._found_a_turtle(b) is False:
- blk = self.load_block(b)
- blocks.append(blk)
-
- # Make the connections.
- for i in range(len(blocks)):
- cons=[]
- # Normally, it is simply a matter of copying the connections.
- if blocks[i].connections == None:
- for c in data[i][4]:
- if c is None:
- cons.append(None)
- else:
- cons.append(blocks[c])
- elif blocks[i].connections == 'check':
- # Corner case to convert old-style boolean and arithmetic blocks
- cons.append(None) # Add an extra connection.
- for c in data[i][4]:
- if c is None:
- cons.append(None)
- else:
- cons.append(blocks[c])
- # If the boolean op was connected, readjust the plumbing.
- if blocks[i].name in BOOLEAN_STYLE:
- if data[i][4][0] is not None:
- c = data[i][4][0]
- cons[0] = blocks[data[c][4][0]]
- c0 = data[c][4][0]
- for j, cj in enumerate(data[c0][4]):
- if cj == c:
- blocks[c0].connections[j] = blocks[i]
- if c<i:
- blocks[c].connections[0] = blocks[i]
- blocks[c].connections[3] = None
- else:
- # Connection was to a block we haven't seen yet.
- print "WARNING: dock check couldn't see the future"
- else:
- if data[i][4][0] is not None:
- c = data[i][4][0]
- cons[0] = blocks[data[c][4][0]]
- c0 = data[c][4][0]
- for j, cj in enumerate(data[c0][4]):
- if cj == c:
- blocks[c0].connections[j] = blocks[i]
- if c<i:
- blocks[c].connections[0] = blocks[i]
- blocks[c].connections[1] = None
- else:
- # Connection was to a block we haven't seen yet.
- print "WARNING: dock check couldn't see the future"
+ # load alternative image of nop block if python code is loaded
+ if proto.name == 'nop' and tw.nop == 'pythonloaded':
+ newspr = sprNew(tw,x-20,y-20,tw.media_shapes['pythonloaded'])
+ else:
+ newspr = sprNew(tw,x-20,y-20,proto.image)
+ setlayer(newspr,2000)
+ tw.dragpos = 20,20
+ newspr.type = 'block'
+ newspr.proto = proto
+ if tw.defdict.has_key(newspr.proto.name):
+ newspr.label=tw.defdict[newspr.proto.name]
+ newspr.connections = [None]*len(proto.docks)
+ for i in range(len(proto.defaults)):
+ dock = proto.docks[i+1]
+ argproto = tw.protodict[tw.valdict[dock[0]]]
+ argdock = argproto.docks[0]
+ nx,ny = newspr.x+dock[2]-argdock[2],newspr.y+dock[3]-argdock[3]
+ argspr = sprNew(tw,nx,ny,argproto.image)
+ argspr.type = 'block'
+ argspr.proto = argproto
+ argspr.label = str(proto.defaults[i])
+ setlayer(argspr,2000)
+ argspr.connections = [newspr,None]
+ newspr.connections[i+1] = argspr
+ tw.draggroup = findgroup(newspr)
+ tw.block_operation = 'new'
+
+def block_pressed(tw,mask,x,y,spr):
+ if spr is not None:
+ tw.draggroup = findgroup(spr)
+ for b in tw.draggroup: setlayer(b,2000)
+ if spr.connections[0] != None and spr.proto.name == 'lock':
+ b = find_top_block(spr)
+ tw.dragpos = x-b.x,y-b.y
+ else:
+ tw.dragpos = x-spr.x,y-spr.y
+ disconnect(spr)
+
+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):
+ x,y = xy(event)
+ mouse_move(tw, x, y)
+ return True
+
+def mouse_move(tw, x, y, verbose=False, mdx=0, mdy=0):
+ if verbose:
+ print "processing remote mouse move: " + str(x) + " " + str(y)
+ if tw.draggroup is None:
+ # popup help from RGS
+ spr = findsprite(tw,(x,y))
+ if spr and spr.type == 'category':
+ proto = get_proto_from_category(tw,x,y)
+ if proto and proto!='hide':
+ if timeout_tag[0] == 0:
+ timeout_tag[0] = showPopup(proto.name,tw)
+ tw.spr = spr
+ return
else:
- print "WARNING: unknown connection state %s" %\
- (str(blocks[i].connections))
- blocks[i].connections = cons[:]
-
- # Block sizes and shapes may have changed.
- for b in blocks:
- self._adjust_dock_positions(b)
-
- # Look for any stacks that need to be collapsed.
- for b in blocks:
- if self._collapsed(b):
- self._collapse_stack(self._find_sandwich_top(b))
- return blocks[0]
-
- """
- Adjust the dock x,y positions
- """
- def _adjust_dock_positions(self, blk):
- (sx, sy) = blk.spr.get_xy()
- for i, c in enumerate(blk.connections):
- if i>0 and c is not None:
- bdock = blk.docks[i]
- for j in range(len(c.docks)):
- if c.connections[j] == blk:
- cdock = c.docks[j]
- nx, ny = sx+bdock[2]-cdock[2], sy+bdock[3]-cdock[3]
- c.spr.move((nx, ny))
- self._adjust_dock_positions(c)
-
- """
- Turtle pressed
- """
- def _turtle_pressed(self, x, y):
- (tx, ty) = self.selected_turtle.get_xy()
- dx, dy = x-tx-30, y-ty-30
- if dx*dx+dy*dy > 200:
- self.drag_turtle = ('turn',
- self.canvas.heading-atan2(dy,dx)/DEGTOR, 0)
- else:
- self.drag_turtle = ('move', x-tx, y-ty)
-
- """
- Mouse move
- """
- def _move_cb(self, win, event):
- x, y = self._xy(event)
- self._mouse_move(x, y)
- return True
-
- def _mouse_move(self, x, y, verbose=False, mdx=0, mdy=0):
- if verbose:
- print "processing remote mouse move: %d, %d" % (x, y)
-
- self.block_operation = 'move'
- # First, check to see if we are dragging or rotating a turtle.
- if self.selected_turtle is not None:
- dtype, dragx, dragy = self.drag_turtle
- (sx, sy) = self.selected_turtle.get_xy()
- if dtype == 'move':
- if mdx != 0 or mdy != 0:
- dx, dy = mdx, mdy
- else:
- dx, dy = x-dragx-sx, y-dragy-sy
- self.selected_turtle.move((sx+dx, sy+dy))
- else:
- if mdx != 0 or mdy != 0:
- dx, dy = mdx, mdy
- else:
- dx, dy = x-sx-30, y-sy-30
- self.canvas.seth(int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10)
- # If we are hoving, show popup help.
- elif self.drag_group is None:
- self._show_popup(x, y)
- return
- # If we have a stack of blocks selected, move them.
- elif self.drag_group[0] is not None:
- blk = self.drag_group[0]
- # Don't move a bottom blk is the stack is collapsed
- if self._collapsed(blk):
- return
-
- self.selected_spr = blk.spr
- dragx, dragy = self.drag_pos
- if mdx != 0 or mdy != 0:
- dx, dy = mdx, mdy
- else:
- (sx,sy) = blk.spr.get_xy()
- dx, dy = x-dragx-sx, y-dragy-sy
-
- # Take no action if there was a move of 0,0.
- if dx == 0 and dy == 0:
- return
- self.drag_group = self._find_group(blk)
-
- # Prevent blocks from ending up with a negative x...
- for b in self.drag_group:
- (bx, by) = b.spr.get_xy()
- if bx+dx < 0:
- dx += -(bx+dx)
- # ...or under the palette.
- if self.selected_palette is not None and\
- self.selected_palette != self.trash_index:
- w, h = self.palette_sprs[self.selected_palette][
- self.orientation].get_dimensions()
- if self.orientation == 0:
- if bx < w and by+dy < ICON_SIZE+PALETTE_HEIGHT:
- dy += -(by+dy)+ICON_SIZE+PALETTE_HEIGHT
- else:
- if by < h+ICON_SIZE and bx+dx < PALETTE_WIDTH:
- dx += -(bx+dx)+PALETTE_WIDTH
-
- # Move the stack.
- for b in self.drag_group:
- (bx, by) = b.spr.get_xy()
- b.spr.move((bx+dx, by+dy))
- if mdx != 0 or mdy != 0:
- dx, dy = 0, 0
- else:
- self.dx += dx
- self.dy += dy
-
- """
- Let's help our users by displaying a little help.
- """
- def _show_popup(self, x, y):
- spr = self.sprite_list.find_sprite((x,y))
- blk = self.block_list.spr_to_block(spr)
- if spr and blk is not None:
- if self.timeout_tag[0] == 0:
- self.timeout_tag[0] = self._do_show_popup(blk.name)
- self.selected_spr = spr
+ if timeout_tag[0] > 0:
+ try:
+ gobject.source_remove(timeout_tag[0])
+ timeout_tag[0] = 0
+ except:
+ timeout_tag[0] = 0
+ elif spr and spr.type == 'selbutton':
+ if timeout_tag[0] == 0:
+ timeout_tag[0] = showPopup(spr.name,tw)
+ tw.spr = spr
else:
- if self.timeout_tag[0] > 0:
+ if timeout_tag[0] > 0:
try:
- gobject.source_remove(self.timeout_tag[0])
- self.timeout_tag[0] = 0
+ gobject.source_remove(timeout_tag[0])
+ timeout_tag[0] = 0
except:
- self.timeout_tag[0] = 0
- elif spr and hasattr(spr,'type') and (spr.type == 'selector' or\
- spr.type == 'palette'):
- if self.timeout_tag[0] == 0:
- self.timeout_tag[0] = self._do_show_popup(spr.name)
- self.selected_spr = spr
+ timeout_tag[0] = 0
+ elif spr and spr.type == 'block':
+ if timeout_tag[0] == 0:
+ timeout_tag[0] = showPopup(spr.proto.name,tw)
+ tw.spr = spr
else:
- if self.timeout_tag[0] > 0:
+ if timeout_tag[0] > 0:
try:
- gobject.source_remove(self.timeout_tag[0])
- self.timeout_tag[0] = 0
+ gobject.source_remove(timeout_tag[0])
+ timeout_tag[0] = 0
except:
- self.timeout_tag[0] = 0
+ timeout_tag[0] = 0
else:
- if self.timeout_tag[0] > 0:
+ if timeout_tag[0] > 0:
try:
- gobject.source_remove(self.timeout_tag[0])
- self.timeout_tag[0] = 0
+ gobject.source_remove(timeout_tag[0])
+ timeout_tag[0] = 0
except:
- self.timeout_tag[0] = 0
-
- """
- Fetch the help text and display it.
- """
- def _do_show_popup(self, block_name):
- if SPECIAL_NAMES.has_key(block_name):
- block_name_s = SPECIAL_NAMES[block_name]
- elif BLOCK_NAMES.has_key(block_name):
- block_name_s = BLOCK_NAMES[block_name][0]
- else:
- block_name_s = _(block_name)
- if HELP_STRINGS.has_key(block_name):
- label = block_name_s + ": " + HELP_STRINGS[block_name]
- else:
- label = block_name_s
- if self.running_sugar:
- self.activity.hover_help_label.set_text(label)
- self.activity.hover_help_label.show()
+ timeout_tag[0] = 0
+ return
+ tw.block_operation = 'move'
+ spr = tw.draggroup[0]
+ if spr.type == 'block':
+ tw.spr = spr
+ dragx, dragy = tw.dragpos
+ if mdx != 0 or mdy != 0:
+ dx,dy = mdx,mdy
else:
- self.win.set_title(_("Turtle Art") + " — " + label)
- return 0
-
- """
- Button release
- """
- def _buttonrelease_cb(self, win, event):
- x, y = self._xy(event)
- self.button_release(x, y)
- if self._sharing():
- self.activity._send_event("r:"+str(x)+":"+str(y))
- return True
-
- def button_release(self, x, y, verbose=False):
- if self.dx != 0 or self.dy != 0:
- if self._sharing():
- if verbose:
- print "processing move: %d %d" % (self.dx, self.dy)
- self.activity._send_event("m:%d:%d" % (self.dx, self.dy))
- self.dx = 0
- self.dy = 0
- if verbose:
- print "processing remote button release: %d, %d" % (x, y)
-
- # We may have been moving the turtle
- if self.selected_turtle is not None:
- (tx, ty) = self.selected_turtle.get_xy()
- (cx, cy) = self.canvas.canvas.get_xy()
- self.canvas.xcor = tx-self.canvas.canvas._width/2+30-cx
- self.canvas.ycor = self.canvas.canvas._height/2-ty-30+cy
- self.canvas.move_turtle()
- if self.running_sugar:
- self.display_coordinates()
- self.selected_turtle = None
- return
-
- # If we don't have a group of blocks, then there is nothing to do.
- if self.drag_group == None:
- return
-
- blk = self.drag_group[0]
- # Remove blocks by dragging them onto the trash palette.
- if self.block_operation=='move' and self._in_the_trash(x, y):
- self._put_in_trash(blk, x, y)
- self.drag_group = None
- return
-
- # Pull a stack of new blocks off of the category palette.
- if self.block_operation=='new':
- for b in self.drag_group:
- (bx, by) = b.spr.get_xy()
- if self.orientation == 0:
- b.spr.move((bx+20, by+PALETTE_HEIGHT+ICON_SIZE))
- else:
- b.spr.move((bx+PALETTE_WIDTH, by+20))
-
- # Look to see if we can dock the current stack.
- self._snap_to_dock()
- self._check_collapsibles(blk)
- for b in self.drag_group:
- if b.status != 'collapsed':
- b.spr.set_layer(BLOCK_LAYER)
- self.drag_group = None
-
- # Find the block we clicked on and process it.
- if self.block_operation=='click':
- self._click_block(x, y)
-
- """
- Click block
- """
- def _click_block(self, x, y):
- blk = self.block_list.spr_to_block(self.selected_spr)
- if blk is None:
+ dx,dy = x-dragx-spr.x,y-dragy-spr.y
+ # skip if there was a move of 0,0
+ if dx == 0 and dy == 0:
return
- self.selected_blk = blk
- if blk.name=='number' or blk.name=='string':
- self.saved_string = blk.spr.labels[0]
- blk.spr.labels[0] += CURSOR
- elif blk.name in BOX_STYLE_MEDIA:
- self._import_from_journal(self.selected_blk)
- elif blk.name=='identity2' or blk.name=='hspace':
- group = self._find_group(blk)
- if self._hide_button_hit(blk.spr, x, y):
- dx = blk.reset_x()
- elif self._show_button_hit(blk.spr, x, y):
- dx = 20
- blk.expand_in_x(dx)
- for b in group:
- if b != blk:
- b.spr.move_relative((dx*blk.scale, 0))
- elif blk.name=='vspace':
- group = self._find_group(blk)
- if self._hide_button_hit(blk.spr, x, y):
- dy = blk.reset_y()
- elif self._show_button_hit(blk.spr, x, y):
- dy = 20
- blk.expand_in_y(dy)
- else:
- dy = 0
- for b in group:
- if b != blk:
- b.spr.move_relative((0, dy*blk.scale))
- self._grow_stack_arm(self._find_sandwich_top(blk))
- elif blk.name in EXPANDABLE:
- if self._show_button_hit(blk.spr, x, y):
- n = len(blk.connections)
- group = self._find_group(blk.connections[n-1])
- if blk.name == 'myfunc' and n == 4:
- blk.spr.labels[1] = 'f(x,y)'
- blk.spr.labels[2] = ' '
- if blk.name == 'myfunc' and n == 5:
- blk.spr.labels[1] = 'f(x,y,z)'
- dy = blk.add_arg(False)
- else:
- dy = blk.add_arg()
- for b in group:
- b.spr.move_relative((0, dy))
- blk.connections.append(blk.connections[n-1])
- argname = blk.docks[n-1][0]
- argvalue = DEFAULTS[blk.name][len(DEFAULTS[blk.name])-1]
- argblk = Block(self.block_list, self.sprite_list, argname,
- 0, 0, 'block', [argvalue], self.block_scale)
- argdock = argblk.docks[0]
- (bx, by) = blk.spr.get_xy()
- nx = bx+blk.docks[n-1][2]-argdock[2]
- ny = by+blk.docks[n-1][3]-argdock[3]
- argblk.spr.move((nx, ny))
- argblk.spr.set_layer(TOP_LAYER)
- argblk.connections = [blk, None]
- blk.connections[n-1] = argblk
- self._grow_stack_arm(self._find_sandwich_top(blk))
- else:
- self._run_stack(blk)
- elif blk.name in COLLAPSIBLE:
- top = self._find_sandwich_top(blk)
- if self._collapsed(blk):
- self._restore_stack(top)
- elif top is not None:
- self._collapse_stack(top)
- elif blk.name=='nop' and self.myblock==None:
- self._import_py()
+ # drag entire stack if moving lock block
+ if spr.proto.name == 'lock':
+ tw.draggroup = findgroup(find_top_block(spr))
else:
- self._run_stack(blk)
-
- """
- Collapsible stacks live between 'sandwichtop' and 'sandwichbottom' blocks
- What follows are a number of utilities for managing collapsible stacks.
- Alas, corner-cases abound.
- """
-
- """
- From the top, find and restore any collapsible stacks on forks.
- """
- def _uncollapse_forks(self, top, looping=False):
- if top == None:
- return
- if looping and top.name == 'sandwichtop':
- self._restore_stack(top)
- return
- if len(top.connections) == 0:
- return
- b = top.connections[len(top.connections)-1]
- while b is not None:
- if b.name in COLLAPSIBLE:
- return
- if b.name == 'sandwichtop':
- self._restore_stack(b)
- return
- # Follow a fork
- if b.name in ['repeat', 'if', 'ifelse', 'forever', 'while']:
- top = self._find_sandwich_top_below(
- b.connections[len(b.connections)-2])
- if top is not None:
- self._uncollapse_forks(top, True)
- if b.name == 'ifelse':
- top = self._find_sandwich_top_below(
- b.connections[len(b.connections)-3])
- if top is not None:
- self._uncollapse_forks(top, True)
- b = b.connections[len(b.connections)-1]
- return
-
- """
- Find the sandwich top above this block.
- """
- def _find_sandwich_top(self, blk):
- # Always follow the main branch of a flow: the first connection.
- b = blk.connections[0]
- while b is not None:
- if b.name in COLLAPSIBLE:
- return None
- if b.name in ['repeat', 'if', 'ifelse', 'forever', 'while']:
- if blk != b.connections[len(b.connections)-1]:
- return None
- if b.name == 'sandwichtop':
- return b
- blk = b
- b = b.connections[0]
- return None
-
- """
- Find the sandwich bottom below this block.
- """
- def _find_sandwich_bottom(self, blk):
- # Always follow the main branch of a flow: the last connection.
- b = blk.connections[len(blk.connections)-1]
- while b is not None:
- if b.name == 'sandwichtop':
- return None
- if b.name in COLLAPSIBLE:
- return b
- b = b.connections[len(b.connections)-1]
- return None
-
- """
- Find the sandwich top below this block.
- """
- def _find_sandwich_top_below(self, blk):
- if blk.name == 'sandwichtop':
- return blk
- # Always follow the main branch of a flow: the last connection.
- b = blk.connections[len(blk.connections)-1]
- while b is not None:
- if b.name == 'sandwichtop':
- return b
- b = b.connections[len(b.connections)-1]
- return None
-
- """
- Hide all the blocks between the sandwich top and sandwich bottom.
- """
- def _collapse_stack(self, top):
- # First uncollapse any nested stacks
- self._uncollapse_forks(top)
- hit_bottom = False
- bot = self._find_sandwich_bottom(top)
- group = self._find_group(top.connections[len(top.connections)-1])
- for b in group:
- if not hit_bottom and b == bot:
- hit_bottom = True
-
- # Replace 'sandwichbottom' shape with 'sandwichcollapsed' shape
- if len(b.values) == 0:
- b.values.append(1)
- else:
- b.values[0] = 1
- olddx = b.docks[1][2]
- olddy = b.docks[1][3]
- b.name = 'sandwichcollapsed'
- b.svg.set_show(True)
- b.svg.set_hide(False)
- b._dx = 0
- b._ey = 0
- b.spr.set_label(_('click to open'))
- b.resize()
-
- # Redock to sandwich top in group
- you = self._find_sandwich_top(b)
- (yx, yy) = you.spr.get_xy()
- yd = you.docks[len(you.docks)-1]
- (bx, by) = b.spr.get_xy()
- dx = yx+yd[2]-b.docks[0][2]-bx
- dy = yy+yd[3]-b.docks[0][3]-by
- b.spr.move_relative((dx, dy))
-
- # Since the shapes have changed, the dock positions have too.
- newdx = b.docks[1][2]
- newdy = b.docks[1][3]
- dx += newdx-olddx
- dy += newdy-olddy
+ tw.draggroup = findgroup(spr)
+ # check to see if any block ends up with a negative x
+ for b in tw.draggroup:
+ if b.x+dx < 0:
+ dx += -(b.x+dx)
+ # move the stack
+ 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':
+ if mdx != 0 or mdy != 0:
+ dx,dy = mdx,mdy
else:
- if not hit_bottom:
- b.spr.set_layer(HIDE_LAYER)
- b.status = 'collapsed'
- else:
- b.spr.move_relative((dx, dy))
- self._reset_stack_arm(top)
-
- """
- Restore all the blocks between the sandwich top and sandwich bottom.
- """
- def _restore_stack(self, top):
- group = self._find_group(top.connections[len(top.connections)-1])
- hit_bottom = False
- bot = self._find_sandwich_bottom(top)
- for b in group:
- if not hit_bottom and b == bot:
- hit_bottom = True
- if len(b.values) == 0:
- b.values.append(0)
- else:
- b.values[0] = 0
- olddx = b.docks[1][2]
- olddy = b.docks[1][3]
- # Replace 'sandwichcollapsed' shape with 'sandwichbottom' shape
- b.name = 'sandwichbottom'
- b.spr.set_label(' ')
- b.svg.set_show(False)
- b.svg.set_hide(True)
- b.refresh()
-
- # Redock to previous block in group
- you = b.connections[0]
- (yx, yy) = you.spr.get_xy()
- yd = you.docks[len(you.docks)-1]
- (bx, by) = b.spr.get_xy()
- dx = yx+yd[2]-b.docks[0][2]-bx
- dy = yy+yd[3]-b.docks[0][3]-by
- b.spr.move_relative((dx, dy))
-
- # Since the shapes have changed, the dock positions have too.
- newdx = b.docks[1][2]
- newdy = b.docks[1][3]
- dx += newdx-olddx
- dy += newdy-olddy
+ dx,dy = x-dragx-spr.x,y-dragy-spr.y
+ move(spr, (spr.x+dx, spr.y+dy))
+ else:
+ if mdx != 0 or mdy != 0:
+ dx,dy = mdx,mdy
else:
- if not hit_bottom:
- b.spr.set_layer(BLOCK_LAYER)
- b.status = None
- else:
- b.spr.move_relative((dx, dy))
- self._grow_stack_arm(top)
-
- """
- When we undock, retract the 'arm' that extends down from 'sandwichtop'.
- """
- def _reset_stack_arm(self, top):
- if top is not None and top.name == 'sandwichtop':
- if top.ey > 0:
- top.reset_y()
-
- """
- When we dock, grow an 'arm' the length of the stack from 'sandwichtop'.
- """
- def _grow_stack_arm(self, top):
- if top is not None and top.name == 'sandwichtop':
- bot = self._find_sandwich_bottom(top)
- if bot is None:
- return
- if top.ey > 0:
- top.reset_y()
- (tx, ty) = top.spr.get_xy()
- (tw, th) = top.spr.get_dimensions()
- (bx, by) = bot.spr.get_xy()
- dy = by-(ty+th)
- if dy > 0:
- top.expand_in_y(dy/top.scale)
-
- """
- Check the state of collapsible blocks upon change in dock state.
- """
- def _check_collapsibles(self, blk):
- group = self._find_group(blk)
- for b in group:
- if b.name in COLLAPSIBLE:
- if self._collapsed(b):
- b.svg.set_show(True)
- b.svg.set_hide(False)
- self._reset_stack_arm(self._find_sandwich_top(b))
- elif self._collapsible(b):
- b.svg.set_hide(True)
- b.svg.set_show(False)
- self._grow_stack_arm(self._find_sandwich_top(b))
+ dx,dy = x-spr.x-30,y-spr.y-30
+ seth(tw.turtle, int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10)
+ if mdx != 0 or mdy != 0:
+ dx,dy = 0,0
+ else:
+ tw.dx += dx
+ tw.dy += dy
+
+#
+# Button release
+#
+
+def buttonrelease_cb(win, event, tw):
+ x,y = xy(event)
+ button_release(tw, x, y)
+ if hasattr(tw, 'activity') and \
+ hasattr(tw.activity, 'chattube') and tw.activity.chattube is not None:
+ # print "sending release button"
+ tw.activity._send_event("r:"+str(x)+":"+str(y))
+ return True
+
+def button_release(tw, x, y, verbose=False):
+ if tw.dx != 0 or tw.dy != 0:
+ if hasattr(tw, 'activity') and \
+ hasattr(tw.activity, 'chattube') and \
+ tw.activity.chattube is not None:
+ if verbose:
+ print "processing move: " + str(tw.dx) + " " + str(tw.dy)
+ tw.activity._send_event("m:"+str(tw.dx)+":"+str(tw.dy))
+ tw.dx = 0
+ tw.dy = 0
+ if verbose:
+ print "processing remote button release: " + str(x) + " " + str(y)
+ if tw.draggroup == None:
+ return
+ spr = tw.draggroup[0]
+ 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)
+ display_coordinates(tw)
+ tw.draggroup = None
+ return
+ if tw.block_operation=='move' and hit(tw.category_spr, (x,y)):
+ for b in tw.draggroup: hide(b)
+ tw.draggroup = None
+ return
+ if tw.block_operation=='new':
+ for b in tw.draggroup:
+ move(b, (b.x+200, b.y))
+ snap_to_dock(tw)
+ for b in tw.draggroup: setlayer(b,650)
+ tw.draggroup = None
+ if tw.block_operation=='click':
+ if tw.spr.proto.name=='number':
+ tw.selected_block = spr
+ move(tw.select_mask, (spr.x-5,spr.y-5))
+ setlayer(tw.select_mask, 660)
+ tw.firstkey = True
+ elif tw.defdict.has_key(spr.proto.name):
+ tw.selected_block = spr
+ if tw.spr.proto.name=='string':
+ move(tw.select_mask_string, (spr.x-5,spr.y-5))
+ setlayer(tw.select_mask_string, 660)
+ tw.firstkey = True
+ elif tw.spr.proto.name in importblocks:
+ import_from_journal(tw, spr)
+ elif tw.spr.proto.name=='nop' and tw.myblock==None:
+ tw.activity.import_py()
+ else: run_stack(tw, spr)
+
+def import_from_journal(tw, spr):
+ if hasattr(tw,"activity"):
+ chooser = ObjectChooser('Choose image', None,\
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
+ try:
+ result = chooser.run()
+ if result == gtk.RESPONSE_ACCEPT:
+ dsobject = chooser.get_selected_object()
+ # change block graphic to indicate that object is "loaded"
+ if spr.proto.name == 'journal':
+ load_image(tw, dsobject, spr)
+ elif spr.proto.name == 'audiooff':
+ setimage(spr,tw.media_shapes['audioon'])
else:
- b.svg.set_hide(False)
- b.svg.set_show(False)
- # Ouch: When you tear off the sandwich bottom, you
- # no longer have access to the group with the sandwich top
- # so check them all.
- for bb in self.just_blocks():
- if bb.name == 'sandwichtop':
- if self._find_sandwich_bottom(bb) is None:
- self._reset_stack_arm(bb)
- b.refresh()
-
- """
- Is this stack collapsed?
- """
- def _collapsed(self, blk):
- if blk is not None and blk.name in COLLAPSIBLE and\
- len(blk.values) == 1 and blk.values[0] != 0:
- return True
- return False
-
- """
- Can this stack be collapsed?
- """
- def _collapsible(self, blk):
- if blk is None or blk.name not in COLLAPSIBLE:
- return False
- if self._find_sandwich_top(blk) is None:
- return False
- return True
-
- """
- Run a stack of blocks.
- """
- def _run_stack(self, blk):
- if blk is None:
- return
- self.lc.ag = None
- top = self.find_top_block(blk)
- self.lc.run_blocks(top, self.just_blocks(), True)
- gobject.idle_add(self.lc.doevalstep)
-
- """
- Did the sprite's hide (contract) button get hit?
- """
- def _hide_button_hit(self, spr, x, y):
- r,g,b,a = spr.get_pixel((x, y))
- if (r == 255 and g == 0) or g == 255:
- return True
- else:
- return False
-
- """
- Did the sprite's show (expand) button get hit?
- """
- def _show_button_hit(self, spr, x, y):
- r,g,b,a = spr.get_pixel((x, y))
- if g == 254:
- return True
- else:
- return False
-
- """
- Snap a block to the dock of another block.
- """
- def _snap_to_dock(self):
- my_block = self.drag_group[0]
- d = 200
- for my_dockn in range(len(my_block.docks)):
- for i, your_block in enumerate(self.just_blocks()):
- # don't link to a block to which you're already connected
- if your_block in self.drag_group:
+ setimage(spr, tw.media_shapes['decson'])
+ spr.ds_id = dsobject.object_id
+ dsobject.destroy()
+ finally:
+ chooser.destroy()
+ del chooser
+ else:
+ print "Journal Object Chooser unavailable from outside of Sugar"
+
+# Replace Journal block graphic with preview image
+def load_image(tw, picture, spr):
+ from talogo import get_pixbuf_from_journal
+ pixbuf = get_pixbuf_from_journal(picture,spr.width,spr.height)
+ if pixbuf is not None:
+ setimage(spr, pixbuf)
+ else:
+ setimage(spr, tw.media_shapes['texton'])
+
+# change the icon for user-defined blocks after Python code is loaded
+def set_userdefined(tw):
+ list = tw.sprites[:]
+ for spr in list:
+ if hasattr(spr,'proto') and spr.proto.name == 'nop':
+ setimage(spr,tw.media_shapes['pythonloaded'])
+ tw.nop = 'pythonloaded'
+
+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
- # check each dock of your_block for a possible connection
- for your_dockn in range(len(your_block.docks)):
- this_xy = self._dock_dx_dy(your_block, your_dockn,
- my_block, my_dockn)
- if magnitude(this_xy) > d:
- continue
- d = magnitude(this_xy)
- best_xy = this_xy
- best_you = your_block
- best_your_dockn = your_dockn
- best_my_dockn = my_dockn
- if d<200:
- if self._arithmetic_check(my_block, best_you, best_my_dockn,
- best_your_dockn) is False:
- return
- for blk in self.drag_group:
- (sx, sy) = blk.spr.get_xy()
- blk.spr.move((sx+best_xy[0], sy+best_xy[1]))
-
- # If there was already a block docked there, move it to the trash.
- blk_in_dock = best_you.connections[best_your_dockn]
- if blk_in_dock is not None:
- blk_in_dock.connections[0] = None
- self._put_in_trash(blk_in_dock)
-
- best_you.connections[best_your_dockn] = my_block
- if my_block.connections is not None:
- my_block.connections[best_my_dockn] = best_you
-
- """
- Additional docking check for arithmetic blocks: dock strings only if they
- convert to numbers. Also, avoid /0 and root(-1)
- """
- def _arithmetic_check(self, b1, b2, d1, d2):
- if b1 == None or b2 == None:
- return True
- if b1.name in ['sqrt', 'number', 'string'] and\
- b2.name in ['sqrt', 'number', 'string']:
- if b1.name == 'number' or b1.name == 'string':
- if not numeric_arg(b1.values[0]) or neg_arg(b1.values[0]):
- return False
- elif b2.name == 'number' or b2.name == 'string':
- if not numeric_arg(b2.values[0]) or neg_arg(b2.values[0]):
- return False
- elif b1.name in ['division2', 'number', 'string'] and\
- b2.name in ['division2', 'number', 'string']:
- if b1.name == 'number' or b1.name == 'string':
- if not numeric_arg(b1.values[0]):
- return False
- if d2 == 2 and zero_arg(b1.values[0]):
- return False
- elif b2.name == 'number' or b2.name == 'string':
- if not numeric_arg(b2.values[0]):
- return False
- if d1 == 2 and zero_arg(b2.values[0]):
- return False
- elif b1.name in ['product2', 'minus2', 'random', 'remainder2',
- 'string'] and\
- b2.name in ['product2', 'minus2', 'random', 'remainder2',
- 'string']:
- if b1.name == 'string':
- if not numeric_arg(b1.values[0]):
- return False
- elif b1.name == 'string':
- if not numeric_arg(b2.values[0]):
- return False
- elif b1.name in ['greater2', 'less2'] and b2.name == 'string':
- # Non-numeric stings are OK if only both args are strings;
- # Lots of test conditions...
- if d1 == 1 and b1.connections[2] is not None:
- if b1.connections[2].name == 'number':
- if not numeric_arg(b2.values[0]):
- return False
- elif d1 == 2 and b1.connections[1] is not None:
- if b1.connections[1].name == 'number':
- if not numeric_arg(b2.values[0]):
- return False
- elif b2.name in ['greater2', 'less2'] and b1.name == 'string':
- if d2 == 1 and b2.connections[2] is not None:
- if b2.connections[2].name == 'number':
- if not numeric_arg(b1.values[0]):
- return False
- elif d2 == 2 and b2.connections[1] is not None:
- if b2.connections[1].name == 'number':
- if not numeric_arg(b1.values[0]):
- return False
- elif b1.name in ['greater2', 'less2'] and b2.name == 'number':
- if d1 == 1 and b1.connections[2] is not None:
- if b1.connections[2].name == 'string':
- if not numeric_arg(b1.connections[2].values[0]):
- return False
- elif d1 == 2 and b1.connections[1] is not None:
- if b1.connections[1].name == 'string':
- if not numeric_arg(b1.connections[1].values[0]):
- return False
- elif b2.name in ['greater2', 'less2'] and b1.name == 'number':
- if d2 == 1 and b2.connections[2] is not None:
- if b2.connections[2].name == 'string':
- if not numeric_arg(b2.connections[2].values[0]):
- return False
- elif d2 == 2 and b2.connections[1] is not None:
- if b2.connections[1].name == 'string':
- if not numeric_arg(b2.connections[1].values[0]):
- return False
- return True
-
- """
- Import a file from the Sugar Journal
- """
- def _import_from_journal(self, blk):
- if self.running_sugar:
- chooser = ObjectChooser('Choose image', None,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- try:
- result = chooser.run()
- if result == gtk.RESPONSE_ACCEPT:
- dsobject = chooser.get_selected_object()
- self._update_media_icon(blk, dsobject, dsobject.object_id)
- dsobject.destroy()
- finally:
- chooser.destroy()
- del chooser
- else:
- fname, self.load_save_folder = \
- get_load_name('.*', self.load_save_folder)
- if fname is None:
- return
- self._update_media_icon(blk, fname)
-
- """
- Update the icon on a 'loaded' media block.
- """
- def _update_media_icon(self, blk, name, value=''):
- if blk.name == 'journal':
- self._load_image_thumb(name, blk)
- elif blk.name == 'audio':
- self._block_skin('audioon', blk)
- else:
- self._block_skin('descriptionon', blk)
- if value == '':
- value = name
- if len(blk.values)>0:
- blk.values[0] = value
- else:
- blk.values.append(value)
- blk.spr.set_label(' ')
-
- """
- Replace icon with a preview image.
- """
- def _load_image_thumb(self, picture, blk):
- pixbuf = None
- self._block_skin('descriptionon', blk)
-
- if self.running_sugar:
- w, h = calc_image_size(blk.spr)
- pixbuf = get_pixbuf_from_journal(picture, w, h)
- else:
- if movie_media_type(picture):
- self._block_skin('journalon', blk)
- elif audio_media_type(picture):
- self._block_skin('audioon', blk)
- blk.name = 'audio'
- elif image_media_type(picture):
- w, h = calc_image_size(blk.spr)
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(picture, w, h)
- else:
- blk.name = 'description'
- if pixbuf is not None:
- x, y = self._calc_image_offset('', blk.spr)
- blk.set_image(pixbuf, x, y)
- self._resize_skin(blk)
-
- """
- Disconnect block from stack above it.
- """
- def _disconnect(self, blk):
- if blk.connections[0]==None:
- return
- if self._collapsed(blk):
- return
- blk2=blk.connections[0]
- blk2.connections[blk2.connections.index(blk)] = None
- blk.connections[0] = None
-
- """
- Find the distance between the dock points of two blocks.
- """
- def _dock_dx_dy(self, block1, dock1n, block2, dock2n):
- dock1 = block1.docks[dock1n]
- dock2 = block2.docks[dock2n]
- d1type, d1dir, d1x, d1y = dock1[0:4]
- d2type, d2dir, d2x, d2y = dock2[0:4]
- if block1 == block2:
+ 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 d1dir == d2dir:
+ if block2.connections[dock2n] != None:
return (100,100)
- if (d2type is not 'number') or (dock2n is not 0):
- if block1.connections is not None and \
- dock1n < len(block1.connections) and \
- block1.connections[dock1n] is not None:
- return (100,100)
- if block2.connections is not None and \
- dock2n < len(block2.connections) and \
- block2.connections[dock2n] is not None:
- return (100,100)
- if d1type != d2type:
- if block1.name in STRING_OR_NUMBER_ARGS:
- if d2type == 'number' or d2type == 'string':
+ if block1==block2: return (100,100)
+ if d1type!=d2type:
+ # some blocks can take strings or nums
+ if block1.proto.name in ('write', 'plus2', 'equal', 'less', 'greater', \
+ 'template1', 'template2', 'template3', \
+ 'template4', 'template6', 'template7', 'nop', \
+ 'print', 'stack'):
+ if block1.proto.name == 'write' and d1type == 'string':
+ if d2type == 'num' or d2type == 'string':
pass
- elif block1.name in CONTENT_ARGS:
- if d2type in CONTENT_BLOCKS:
+ else:
+ if d2type == 'num' or d2type == 'string':
pass
- else:
- return (100,100)
- (b1x, b1y) = block1.spr.get_xy()
- (b2x, b2y) = block2.spr.get_xy()
- return ((b1x+d1x)-(b2x+d2x), (b1y+d1y)-(b2y+d2y))
-
-
- """
- Keyboard
- """
- def _keypress_cb(self, area, event):
- keyname = gtk.gdk.keyval_name(event.keyval)
- keyunicode = gtk.gdk.keyval_to_unicode(event.keyval)
-
- if event.get_state()&gtk.gdk.MOD1_MASK:
- alt_mask = True
- alt_flag = 'T'
+ # some blocks can take strings, nums, or Journal
+ elif block1.proto.name in ('show', 'push', 'storein', 'storeinbox1', \
+ 'storeinbox2'):
+ if d2type == 'num' or d2type == 'string' or d2type == 'journal':
+ pass
+ # some blocks can take media, audio, movies, of descriptions
+ elif block1.proto.name in ('containter'):
+ if d1type == 'audiooff' or d1type == 'journal':
+ pass
else:
- alt_mask = False
- alt_flag = 'F'
- results = self._key_press(alt_mask, keyname, keyunicode)
- if keyname is not None and self._sharing():
- self.activity._send_event("k:%s:%s:%s" % (alt_flag, keyname,
- str(keyunicode)))
+ 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):
+ redrawsprites(tw)
+ return True
+
+#
+# Keyboard
+#
+
+def keypress_cb(area, event, tw):
+ keyname = gtk.gdk.keyval_name(event.keyval)
+# keyunicode = unichr(gtk.gdk.keyval_to_unicode(event.keyval)).replace("\x00","")
+ keyunicode = gtk.gdk.keyval_to_unicode(event.keyval)
+# print keyname
+# if keyunicode > 0:
+# print unichr(keyunicode)
+
+ if event.get_state()&gtk.gdk.MOD1_MASK:
+ alt_mask = True
+ else:
+ alt_mask = False
+ results = key_press(tw, alt_mask, keyname, keyunicode)
+ if keyname is not None and hasattr(tw,"activity") and \
+ hasattr(tw.activity, 'chattube') and tw.activity.chattube is not None:
+ # print "key press"
+ if alt_mask:
+ tw.activity._send_event("k:"+'T'+":"+keyname+":"+str(keyunicode))
+ else:
+ tw.activity._send_event("k:"+'F'+":"+keyname+":"+str(keyunicode))
+ return keyname
+'''
+ if len(keyname)>1:
+ # print "(" + keyunicode.encode("utf-8") + ")"
return keyname
-
- def _key_press(self, alt_mask, keyname, keyunicode, verbose=False):
- if keyname is None:
- return False
- if verbose:
- print "processing remote key press: %s" % (keyname)
-
- self.keypress = keyname
-
- # First, process Alt keys.
- if alt_mask is True and self.selected_blk==None:
- if keyname=="i" and self._sharing():
- self.activity.waiting_for_blocks = True
- self.activity._send_event("i") # request sync for sharing
- elif keyname=="p":
- self.hideshow_button()
- elif keyname=='q':
- exit()
- return True
- # Process keyboard input for 'number' blocks
- if self.selected_blk is not None and\
- self.selected_blk.name == 'number':
- self._process_numeric_input(keyname)
- return True
- # Process keyboard input for 'string' blocks
- elif self.selected_blk is not None and\
- self.selected_blk.name == 'string':
- self.process_alphanumeric_input(keyname, keyunicode)
- if self.selected_blk is not None:
- self.selected_blk.resize()
- return True
- # Otherwise, use keyboard input to move blocks or turtles
- else:
- self._process_keyboard_commands(keyname)
- if self.selected_blk is None:
- return False
-
- '''
- Make sure numeric input is valid.
- '''
- def _process_numeric_input(self, keyname):
- oldnum = self.selected_blk.spr.labels[0].replace(CURSOR,'')
- if len(oldnum) == 0:
- oldnum = '0'
- if keyname == 'minus':
- if oldnum == '0':
- newnum = '-'
- elif oldnum[0] != '-':
- newnum = '-' + oldnum
- else:
- newnum = oldnum
- elif keyname == 'period' and '.' not in oldnum:
- newnum = oldnum + '.'
- elif keyname == 'BackSpace':
- if len(oldnum) > 0:
+ else:
+ # print "[" + keyunicode.encode("utf-8") + "]"
+ return keyunicode.encode("utf-8")
+'''
+def key_press(tw, alt_mask, keyname, keyunicode, verbose=False):
+ if keyname is None:
+ return False
+ if verbose:
+ print "processing remote key press: " + keyname
+ tw.keypress = keyname
+ if alt_mask is True and tw.selected_block==None:
+ if keyname=="i" and hasattr(tw, 'activity'):
+ tw.activity.waiting_for_blocks = True
+ tw.activity._send_event("i") # request sync for sharing
+ elif keyname=="p":
+ hideshow_button(tw)
+ elif keyname=='q':
+ exit()
+ return True
+ if tw.selected_block is not None and \
+ tw.selected_block.proto.name == 'number':
+ if keyname in ['minus', 'period']:
+ keyname = {'minus': '-', 'period': '.'}[keyname]
+ oldnum = tw.selected_block.label
+ selblock=tw.selected_block.proto
+ if keyname == 'BackSpace':
+ if len(oldnum) > 1:
newnum = oldnum[:len(oldnum)-1]
else:
newnum = ''
- elif keyname in ['0','1','2','3','4','5','6','7','8','9']:
- if oldnum == '0':
- newnum = keyname
+ setlabel(tw.selected_block, selblock.check(newnum,oldnum))
+ if len(newnum) > 0:
+ tw.firstkey = False
else:
- newnum = oldnum + keyname
- elif keyname == 'Return':
- self._unselect_block()
- return
- else:
- newnum = oldnum
- if newnum == '.':
- newnum = '0.'
- if len(newnum) > 0 and newnum != '-':
- try:
- float(newnum)
- except ValueError,e:
- newnum = oldnum
- self.selected_blk.spr.set_label(newnum + CURSOR)
-
- """
- Make sure alphanumeric input is properly parsed.
- """
- def process_alphanumeric_input(self, keyname, keyunicode):
- if len(self.selected_blk.spr.labels[0]) > 0:
- c = self.selected_blk.spr.labels[0].count(CURSOR)
- if c == 0:
- oldleft = self.selected_blk.spr.labels[0]
- oldright = ''
- elif len(self.selected_blk.spr.labels[0]) == 1:
- oldleft = ''
- oldright = ''
- else:
- try: # Why are getting a ValueError on occasion?
- oldleft, oldright =\
- self.selected_blk.spr.labels[0].split(CURSOR)
- except ValueError:
- print "[%s]" % self.selected_blk.spr.labels[0]
- oldleft = self.selected_blk.spr.labels[0]
- oldright = ''
- else:
- oldleft = ''
- oldright = ''
- newleft = oldleft
- if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock',\
- 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift']:
- keyname = ''
- keyunicode = 0
- # Hack until I sort out input and unicode and dead keys,
- if keyname[0:5] == 'dead_':
- self.dead_key = keyname
- keyname = ''
- keyunicode = 0
- if keyname in WHITE_SPACE:
- keyunicode = 32
- if keyname == 'BackSpace':
- if len(oldleft) > 1:
- newleft = oldleft[:len(oldleft)-1]
- else:
- newleft = ''
- elif keyname == 'Home':
- oldright = oldleft+oldright
- newleft = ''
- elif keyname == 'Left':
- if len(oldleft) > 0:
- oldright = oldleft[len(oldleft)-1:]+oldright
- newleft = oldleft[:len(oldleft)-1]
- elif keyname == 'Right':
- if len(oldright) > 0:
- newleft = oldleft + oldright[0]
- oldright = oldright[1:]
- elif keyname == 'End':
- newleft = oldleft+oldright
- oldright = ''
- elif keyname == 'Return' or keyname == 'Down':
- self._unselect_block()
- return
- elif keyname == 'Up' or keyname == 'Escape': # Restore previous state
- self.selected_blk.spr.set_label(self.saved_string)
- self._unselect_block()
- return
- else:
- if self.dead_key is not '':
- keyunicode =\
- DEAD_DICTS[DEAD_KEYS.index(self.dead_key[5:])][keyname]
- self.dead_key = ''
- if keyunicode > 0:
- if unichr(keyunicode) is not '\x00':
- newleft = oldleft+unichr(keyunicode)
- else:
- newleft = oldleft
- elif keyunicode == -1: # clipboard text
- newleft = oldleft+keyname
- self.selected_blk.spr.set_label("%s%s%s" % (newleft, CURSOR, oldright))
-
- """
- Use the keyboard to move blocks and turtle
- """
- def _process_keyboard_commands(self, keyname):
- mov_dict = {'KP_Up':[0,10],'j':[0,10],'Up':[0,10],
- 'KP_Down':[0,-10],'k':[0,-10],'Down':[0,-10],
- 'KP_Left':[-10,0],'h':[-10,0],'Left':[-10,0],
- 'KP_Right':[10,0],'l':[10,0],'Right':[10,0],
- 'KP_Page_Down':[0,0], 'KP_Page_Up':[0,0], 'KP_End':[0,0],
- 'KP_Home':[-1,-1],'Return':[-1,-1], 'Esc':[0,0]}
- if not mov_dict.has_key(keyname):
- return
- if keyname == 'KP_End':
- self.run_button(0)
- elif self.selected_spr is not None:
- blk = self.block_list.spr_to_block(self.selected_spr)
- tur = self.turtles.spr_to_turtle(self.selected_spr)
- if not self.lc.running and blk is not None:
- if keyname == 'Return' or keyname == 'KP_Page_Up':
- (x, y) = blk.spr.get_xy()
- self._click_block(x, y)
- elif keyname == 'KP_Page_Down':
- if self.drag_group == None:
- self.drag_group = self._find_group(blk)
- for b in self.drag_group: b.spr.hide()
- self.drag_group = None
- else:
- self._jog_block(blk, mov_dict[keyname][0],
- mov_dict[keyname][1])
- elif tur is not None:
- self._jog_turtle(mov_dict[keyname][0], mov_dict[keyname][1])
- return True
-
- """
- Jog turtle
- """
- def _jog_turtle(self, dx, dy):
- if dx == -1 and dy == -1:
- self.canvas.xcor = 0
- self.canvas.ycor = 0
- else:
- self.canvas.xcor += dx
- self.canvas.ycor += dy
- self.canvas.move_turtle()
- self.display_coordinates()
- self.selected_turtle = None
-
- """
- Jog block
- """
- def _jog_block(self, blk, dx, dy):
- if self._collapsed(blk):
- return
- self.drag_group = self._find_group(blk)
- # check to see if any block ends up with a negative x
- for blk in self.drag_group:
- (sx, sy) = blk.spr.get_xy()
- if sx+dx < 0:
- dx += -(sx+dx)
- # move the stack
- for blk in self.drag_group:
- (sx, sy) = blk.spr.get_xy()
- blk.spr.move((sx+dx, sy-dy))
- self._snap_to_dock()
- self.drag_group = None
-
- """
- Make sure a 'number' block contains a number.
- """
- def _number_check(self):
- n = self.selected_blk.spr.labels[0].replace(CURSOR,'')
- if n in ['-', '.', '-.']:
- n = 0
- if n is not None:
- try:
- f = float(n)
- if f > 1000000:
- n = 1
- self.showlabel("#overflowerror")
- elif f < -1000000:
- n = -1
- self.showlabel("#overflowerror")
- except ValueError:
- n = 0
- self.showlabel("#notanumber")
- else:
- n = 0
- self.selected_blk.spr.set_label(n)
- self.selected_blk.values[0] = n
-
- def _string_check(self):
- s = self.selected_blk.spr.labels[0].replace(CURSOR,'')
- self.selected_blk.spr.set_label(s)
- self.selected_blk.values[0] = s
-
- """
- Load Python code from a file
- """
- def load_python_code(self):
- fname, self.load_save_folder = get_load_name('.py',
- self.load_save_folder)
- if fname==None:
- return
- f = open(fname, 'r')
- self.myblock = f.read()
- f.close()
-
- """
- Import Python code into a block
- """
- def _import_py(self):
- if self.running_sugar:
- self.activity.import_py()
- else:
- self.load_python_code()
- self.set_userdefined()
-
- """
- Start a new project
- """
- def new_project(self):
- stop_logo(self)
- # Put current project in the trash.
- while len(self.just_blocks()) > 0:
- b = self.just_blocks()[0]
- top = self.find_top_block(b)
- self._put_in_trash(top)
- self.canvas.clearscreen()
- self.save_file_name = None
-
- """
- Load a project from a file
- """
- def load_files(self, ta_file, create_new_project=True):
- if create_new_project is True:
- self.new_project()
- top = self.process_data(data_from_file(ta_file))
- self._check_collapsibles(top)
-
- def load_file(self, create_new_project=True):
- fname, self.load_save_folder = get_load_name('.ta',
- self.load_save_folder)
- if fname==None:
- return
- if fname[-3:] == '.ta':
- fname=fname[0:-3]
- self.load_files(fname+'.ta', create_new_project)
- if create_new_project is True:
- self.save_file_name = os.path.basename(fname)
-
- """
- Turtles are either [-1, 'turtle', ...] or [-1, ['turtle', key], ...]
- """
- def _found_a_turtle(self, b):
- if b[1] == 'turtle':
- self.load_turtle(b)
+ tw.firstkey = True
+ if len(keyname)>1:
return True
- elif type(b[1]) == list and b[1][0] == 'turtle':
- self.load_turtle(b, b[1][1])
+ else: # gtk.keysyms.Left ...
+ if keyname in ['Escape', 'Return', 'KP_Page_Up',
+ 'Up', 'Down', 'Left', 'Right', 'KP_Home', 'KP_End',
+ 'KP_Up', 'KP_Down', 'KP_Left', 'KP_Right',
+ 'KP_Page_Down']:
+ # move blocks (except number and text blocks only with arrows)
+ # or click with Return
+ if keyname == 'KP_End':
+ run_button(tw, 0)
+ elif tw.spr is not None:
+ if tw.spr.type == 'turtle': # jog turtle with arrow keys
+ if keyname == 'KP_Up' or keyname == 'Up':
+ jog_turtle(tw,0,10)
+ elif keyname == 'KP_Down' or keyname == 'Down':
+ jog_turtle(tw,0,-10)
+ elif keyname == 'KP_Left' or keyname == 'Left':
+ jog_turtle(tw,-10,0)
+ elif keyname == 'KP_Right' or keyname == 'Right':
+ jog_turtle(tw,10,0)
+ elif keyname == 'KP_Home':
+ jog_turtle(tw,-1,-1)
+ elif tw.spr.type == 'block':
+ if keyname == 'Return' or keyname == 'KP_Page_Up':
+ click_block(tw)
+ elif keyname == 'KP_Up' or keyname == 'Up':
+ jog_block(tw,0,10)
+ elif keyname == 'KP_Down' or keyname == 'Down':
+ jog_block(tw,0,-10)
+ elif keyname == 'KP_Left' or keyname == 'Left':
+ jog_block(tw,-10,0)
+ elif keyname == 'KP_Right' or keyname == 'Right':
+ jog_block(tw,10,0)
+ elif keyname == 'KP_Page_Down':
+ if tw.draggroup == None:
+ tw.draggroup = findgroup(tw.spr)
+ for b in tw.draggroup: hide(b)
+ tw.draggroup = None
+ elif tw.spr.type == 'selbutton':
+ if keyname == 'Return' or keyname == 'KP_Page_Up':
+ select_category(tw,tw.spr)
+ elif tw.spr.type == 'category':
+ if keyname == 'Return' or keyname == 'KP_Page_Up':
+ (x,y) = tw.window.get_pointer()
+ block_selector_pressed(tw,x,y)
+ for b in tw.draggroup:
+ move(b, (b.x+200, b.y))
+ tw.draggroup = None
return True
- elif type(b[1]) == tuple:
- btype, key = b[1]
- if btype == 'turtle':
- self.load_turtle(b, key)
- return True
+ if tw.selected_block is None:
return False
-
- """
- Restore a turtle from its saved state
- """
- def load_turtle(self, b, key=1):
- id, name, xcor, ycor, heading, color, shade, pensize = b
- self.canvas.set_turtle(key)
- self.canvas.setxy(xcor, ycor)
- self.canvas.seth(heading)
- self.canvas.setcolor(color)
- self.canvas.setshade(shade)
- self.canvas.setpensize(pensize)
-
- """
- Restore individual blocks from saved state
- """
- def load_block(self, b):
- # A block is saved as: (i, (btype, value), x, y, (c0,... cn))
- # The x,y position is saved/loaded for backward compatibility
- btype, value = b[1], None
- if type(btype) == tuple:
- btype, value = btype
- elif type(btype) == list:
- btype, value = btype[0], btype[1]
- if btype in CONTENT_BLOCKS or btype in COLLAPSIBLE:
- if btype == 'number':
- try:
- values = [int(value)]
- except ValueError:
- values = [float(value)]
- elif btype in COLLAPSIBLE:
- if value is not None:
- values = [int(value)]
- else:
- values = []
+ if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', \
+ 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift']:
+ keyname = ''
+ keyunicode = 0
+ # Hack until I sort out input and unicode + dead keys
+ if keyname[0:5] == 'dead_':
+ tw.dead_key = keyname
+ keyname = ''
+ keyunicode = 0
+ if keyname == 'Tab':
+ keyunicode = 32 # substitute a space for a tab
+ oldnum = tw.selected_block.label
+ selblock=tw.selected_block.proto
+ if keyname == 'BackSpace':
+ if len(oldnum) > 1:
+ newnum = oldnum[:len(oldnum)-1]
+ else:
+ newnum = ''
+ setlabel(tw.selected_block, selblock.check(newnum,oldnum))
+ if len(newnum) > 0:
+ tw.firstkey = False
+ else:
+ tw.firstkey = True
+ elif keyname is not '':
+ # Hack until I sort out input and unicode + dead keys
+ if tw.dead_key == 'dead_grave':
+ keyunicode = dead_grave[keyname]
+ elif tw.dead_key == 'dead_acute':
+ keyunicode = dead_acute[keyname]
+ elif tw.dead_key == 'dead_circumflex':
+ keyunicode = dead_circumflex[keyname]
+ elif tw.dead_key == 'dead_tilde':
+ keyunicode = dead_tilde[keyname]
+ elif tw.dead_key == 'dead_diaeresis':
+ keyunicode = dead_diaeresis[keyname]
+ elif tw.dead_key == 'dead_abovering':
+ keyunicode = dead_abovering[keyname]
+ tw.dead_key = ""
+ if tw.firstkey:
+ newnum = selblock.check(unichr(keyunicode), \
+ tw.defdict[selblock.name])
+ elif keyunicode > 0:
+ if unichr(keyunicode) is not '\x00':
+ newnum = oldnum+unichr(keyunicode)
else:
- values = [value]
- else:
- values = []
-
- if btype in OLD_DOCK:
- check_dock = True
+ newnum = oldnum
else:
- check_dock = False
- if OLD_NAMES.has_key(btype):
- btype = OLD_NAMES[btype]
- blk = Block(self.block_list, self.sprite_list,
- btype, b[2]+self.canvas.cx, b[3]+self.canvas.cy, 'block',
- values, self.block_scale)
- # Some blocks get transformed.
- if btype == 'nop':
- if self.nop == 'pythonloaded':
- self._block_skin('pythonon', blk)
- else:
- self._block_skin('pythonoff', blk)
- elif btype in EXPANDABLE:
- if btype == 'vspace':
- if value is not None:
- blk.expand_in_y(value)
- elif btype == 'hspace' or btype == 'identity2':
- if value is not None:
- blk.expand_in_x(value)
- elif btype == 'templatelist' or btype == 'list':
- for i in range(len(b[4])-4):
- dy = blk.add_arg()
- elif btype in BOX_STYLE_MEDIA:
- if len(blk.values) == 0 or blk.values[0] == 'None' or\
- blk.values[0] == None:
- self._block_skin(btype+'off', blk)
- elif btype == 'audio' or btype == 'description':
- self._block_skin(btype+'on', blk)
- elif self.running_sugar:
- try:
- dsobject = datastore.get(blk.values[0])
- if not movie_media_type(dsobject.file_path[-4:]):
- w, h, = calc_image_size(blk.spr)
- pixbuf = get_pixbuf_from_journal(dsobject, w, h)
- if pixbuf is not None:
- x, y = self._calc_image_offset('', blk.spr)
- blk.set_image(pixbuf, x, y)
- else:
- self._block_skin('journalon', blk)
- dsobject.destroy()
- except:
- try:
- w, h, = calc_image_size(blk.spr)
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
- blk.values[0], w, h)
- x, y = self._calc_image_offset('', blk.spr)
- blk.set_image(pixbuf, x, y)
- except:
- print "Warning: Couldn't open dsobject (%s)" %\
- (blk.values[0])
- self._block_skin('journaloff', blk)
- else:
- if not movie_media_type(blk.values[0][-4:]):
- try:
- w, h, = calc_image_size(blk.spr)
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
- blk.values[0], w, h)
- x, y = self._calc_image_offset('', blk.spr)
- blk.set_image(pixbuf, x, y)
- except:
- self._block_skin('journaloff', blk)
- else:
- self._block_skin('journalon', blk)
- blk.spr.set_label(' ')
- blk.resize()
-
- blk.spr.set_layer(BLOCK_LAYER)
- if check_dock is True:
- blk.connections = 'check'
- return blk
-
- """
- Start a new project with a 'start' brick
- """
- def load_start(self):
- top = self.process_data([[0, "start", PALETTE_WIDTH+20,
- ICON_SIZE+PALETTE_HEIGHT+20, [None, None]]])
-
- """
- Start a project to a file
- """
- def save_file(self):
- if self.save_folder is not None:
- self.load_save_folder = self.save_folder
- fname, self.load_save_folder = get_save_name('.ta',
- self.load_save_folder,
- self.save_file_name)
- if fname is None:
+ newnum = ""
+ setlabel(tw.selected_block, selblock.check(newnum,oldnum))
+ tw.firstkey = False
+ return True
+
+def unselect(tw):
+ if tw.selected_block.label in ['-', '.', '-.']:
+ setlabel(tw.selected_block,'0')
+
+ # put an upper and lower bound on numbers to prevent OverflowError
+ if tw.selected_block.proto.name == 'number' and \
+ tw.selected_block.label is not None:
+ try:
+ i = float(tw.selected_block.label)
+ if i > 1000000:
+ setlabel(tw.selected_block,'1')
+ showlabel(tw.lc,"#overflowerror")
+ elif i < -1000000:
+ setlabel(tw.selected_block,'-1')
+ showlabel(tw.lc,"#overflowerror")
+ except ValueError:
+ pass
+
+ hide(tw.select_mask)
+ hide(tw.select_mask_string)
+ tw.selected_block = None
+
+def jog_turtle(tw,dx,dy):
+ if dx == -1 and dy == -1:
+ tw.turtle.xcor = 0
+ tw.turtle.ycor = 0
+ else:
+ tw.turtle.xcor += dx
+ tw.turtle.ycor += dy
+ move_turtle(tw.turtle)
+ display_coordinates(tw)
+ tw.draggroup = None
+
+def jog_block(tw,dx,dy):
+ # drag entire stack if moving lock block
+ if tw.spr.proto.name == 'lock':
+ tw.draggroup = findgroup(find_top_block(tw.spr))
+ else:
+ tw.draggroup = findgroup(tw.spr)
+ # check to see if any block ends up with a negative x
+ for b in tw.draggroup:
+ if b.x+dx < 0:
+ dx += -(b.x+dx)
+ # move the stack
+ for b in tw.draggroup:
+ move(b,(b.x+dx, b.y-dy))
+ snap_to_dock(tw)
+ tw.draggroup = None
+
+def click_block(tw):
+ if tw.spr.proto.name=='number':
+ tw.selected_block = tw.spr
+ move(tw.select_mask, (tw.spr.x-5,tw.spr.y-5))
+ setlayer(tw.select_mask, 660)
+ tw.firstkey = True
+ elif tw.defdict.has_key(tw.spr.proto.name):
+ tw.selected_block = tw.spr
+ if tw.spr.proto.name=='string':
+ move(tw.select_mask_string, (tw.spr.x-5,tw.spr.y-5))
+ setlayer(tw.select_mask_string, 660)
+ tw.firstkey = True
+ elif tw.spr.proto.name in importblocks:
+ import_from_journal(tw, tw.spr)
+ elif tw.spr.proto.name=='nop' and tw.myblock==None:
+ tw.activity.import_py()
+ else: run_stack(tw, tw.spr)
+
+#
+# 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):
+ tw.lc.ag = None
+ top = find_top_block(spr)
+ run_blocks(tw.lc, top, blocks(tw), True)
+ 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):
+ b = spr
+ while b.connections[0]!=None:
+ b=b.connections[0]
+ return b
+
+def runtool(tw, spr, cmd, *args):
+ cmd(*(args))
+
+def eraser_button(tw):
+ # hide status block
+ setlayer(tw.status_spr,400)
+ clear(tw.lc)
+ display_coordinates(tw)
+
+def stop_button(tw):
+ stop_logo(tw)
+
+def run_button(tw, time):
+ print "you better run, turtle, run!!"
+ # look for the start block
+ for b in blocks(tw):
+ if find_start_stack(tw, b):
+ tw.step_time = time
+ if hasattr(tw,'activity'):
+ tw.activity.recenter()
+ run_stack(tw, b)
return
- if fname[-3:]=='.ta':
- fname=fname[0:-3]
- data = self.assemble_data_to_save()
- data_to_file(data, fname+'.ta')
- self.save_file_name = os.path.basename(fname)
-
- """
- Pack the project (or stack) into a data stream to be serialized
- """
- def assemble_data_to_save(self, save_turtle=True, save_project=True):
- data = []
- blks = []
-
- if save_project is True:
- blks = self.just_blocks()
- else:
- blks = self._find_group(self.find_top_block(self.selected_blk))
-
- for i, b in enumerate(blks):
- b.id = i
- for b in blks:
- if b.name in CONTENT_BLOCKS or b.name in COLLAPSIBLE:
- if len(b.values)>0:
- name = (b.name, b.values[0])
- else:
- name = (b.name)
- elif b.name in EXPANDABLE:
- ex, ey = b.get_expand_x_y()
- if ex > 0:
- name = (b.name, ex)
- elif ey > 0:
- name = (b.name, ey)
- else:
- name = (b.name, 0)
- else:
- name = (b.name)
- if hasattr(b, 'connections'):
- connections = [get_id(c) for c in b.connections]
- else:
- connections = None
- (sx, sy) = b.spr.get_xy()
- # Add a slight offset for copy/paste
- if save_project is False:
- sx+=20
- sy+=20
- data.append((b.id, name, sx-self.canvas.cx, sy-self.canvas.cy,
- connections))
- if save_turtle is True:
- for k in iter(self.turtles.dict):
- self.canvas.set_turtle(k)
- data.append((-1,['turtle', k],
- self.canvas.xcor, self.canvas.ycor,
- self.canvas.heading,
- self.canvas.color, self.canvas.shade,
- self.canvas.pensize))
- return data
-
- """
- Display the coordinates of the current turtle on the toolbar
- """
- def display_coordinates(self):
- x = round_int(self.canvas.xcor/self.coord_scale)
- y = round_int(self.canvas.ycor/self.coord_scale)
- h = round_int(self.canvas.heading)
- if self.running_sugar:
- self.activity.coordinates_label.set_text("%s: %d %s: %d %s: %d" % (
- _("xcor"), x, _("ycor"), y, _("heading"), h))
- self.activity.coordinates_label.show()
- else:
- self.win.set_title("%s — %s: %d %s: %d %s: %d" % (_("Turtle Art"),
- _("xcor"), x, _("ycor"), y, _("heading"), h))
-
- """
- Display a message on a status block
- """
- def showlabel(self, shp, label=''):
- if shp == 'syntaxerror' and str(label) != '':
- if self.status_shapes.has_key(str(label)[1:]):
- shp = str(label)[1:]
- label = ''
- else:
- shp = 'status'
- elif shp[0] == '#':
- shp = shp[1:]
- label = ''
- if shp=='notanumber':
- shp = 'overflowerror'
- self.status_spr.set_shape(self.status_shapes[shp])
- self.status_spr.set_label(str(label))
- self.status_spr.set_layer(STATUS_LAYER)
- if shp == 'info':
- self.status_spr.move((PALETTE_WIDTH, self.height-300))
- else:
- self.status_spr.move((PALETTE_WIDTH, self.height-200))
-
- """
- Relative placement of portfolio objects (used by depreciated blocks)
- """
- def calc_position(self, t):
- w,h,x,y,dx,dy = TEMPLATES[t]
- x *= self.canvas.width
- y *= self.canvas.height
- w *= (self.canvas.width-x)
- h *= (self.canvas.height-y)
- dx *= w
- dy *= h
- return(w,h,x,y,dx,dy)
-
- """
- Grab the current canvas and save it.
- """
- def save_as_image(self, name=""):
- if len(name) == 0:
- filename = "ta.png"
- else:
- filename = name+".png"
+ # no start block, so run a stack that isn't a hat
+ for b in blocks(tw):
+ if find_block_to_run(tw, b):
+ print "running " + b.proto.name
+ tw.step_time = time
+ run_stack(tw, b)
+ return
+
+def hideshow_button(tw):
+ if tw.hide is False:
+ for b in blocks(tw): setlayer(b,100)
+ hide_palette(tw)
+ hide(tw.select_mask)
+ hide(tw.select_mask_string)
+ tw.hide = True
+ else:
+ for b in blocks(tw): setlayer(b,650)
+ show_palette(tw)
+ tw.hide = False
+ inval(tw.turtle.canvas)
+
+# find start stack
+def find_start_stack(tw, spr):
+ top = find_top_block(spr)
+ if spr.proto.name == 'start':
+ return True
+ else:
+ return False
- if self.running_sugar:
- datapath = os.path.join(self.activity.get_activity_root(),
- "instance")
- else:
- datapath = os.getcwd()
- file_path = os.path.join(datapath, filename)
- save_picture(self.canvas, file_path)
-
- if self.running_sugar:
- dsobject = datastore.create()
- if len(name) == 0:
- dsobject.metadata['title'] = "%s %s" % (self.metadata['title'],
- _("image"))
- else:
- dsobject.metadata['title'] = name
- dsobject.metadata['icon-color'] = profile.get_color().to_string()
- dsobject.metadata['mime_type'] = 'image/png'
- dsobject.set_file_path(file_path)
- datastore.write(dsobject)
- dsobject.destroy()
-
- """
- Where is the mouse event?
- """
- def _xy(self, event):
- return map(int, event.get_coords())
-
- """
- Utilities related to finding blocks in stacks.
- """
-
- """
- Find a stack to run (any stack without a 'def action'on the top).
- """
- def _find_block_to_run(self, blk):
- top = self.find_top_block(blk)
- if blk == top and blk.name[0:3] is not 'def':
- return True
- else:
- return False
-
- """
- Find the top block in a stack.
- """
- def find_top_block(self, blk):
- if len(blk.connections) == 0:
- return blk
- while blk.connections[0] is not None:
- blk = blk.connections[0]
- return blk
-
- """
- Find a stack with a 'start' block on top.
- """
- def _find_start_stack(self, blk):
- top = self.find_top_block(blk)
- if top.name == 'start':
- return True
- else:
- return False
-
- """
- Find the connected group of block in a stack.
- """
- def _find_group(self, blk):
- if blk is None:
- return []
- group=[blk]
- if blk.connections is not None:
- for blk2 in blk.connections[1:]:
- if blk2 is not None:
- group.extend(self._find_group(blk2))
- return group
-
- """
- Filter out 'proto', 'trash', and 'deleted' blocks
- """
- def just_blocks(self):
- just_blocks_list = []
- for b in self.block_list.list:
- if b.type == 'block':
- just_blocks_list.append(b)
- return just_blocks_list
-
- """
- What are the width and height of a stack?
- """
- def _width_and_height(self, blk):
- minx = 10000
- miny = 10000
- maxx = -10000
- maxy = -10000
- for b in self._find_group(blk):
- (x, y) = b.spr.get_xy()
- w, h = b.spr.get_dimensions()
- if x<minx:
- minx = x
- if y<miny:
- miny = y
- if x+w>maxx:
- maxx = x+w
- if y+h>maxy:
- maxy = y+h
- return(maxx-minx, maxy-miny)
-
- """
- Utilities related to putting a image 'skin' on a block
- """
-
- """
- Calculate the postion for placing an image onto a sprite.
- """
- def _calc_image_offset(self, name, spr, iw=0, ih=0):
- _l, _t = spr.label_left_top()
- if name == '':
- return _l, _t
- _w = spr.label_safe_width()
- _h = spr.label_safe_height()
- if iw == 0:
- iw = self.media_shapes[name].get_width()
- ih = self.media_shapes[name].get_height()
- return int(_l+(_w-iw)/2), int(_t+(_h-ih)/2)
-
- """
- Calculate new image size
- """
- def _calc_w_h(self, name, spr):
- target_w = spr.label_safe_width()
- target_h = spr.label_safe_height()
- if name == '':
- return target_w, target_h
- image_w = self.media_shapes[name].get_width()
- image_h = self.media_shapes[name].get_height()
- if image_w > target_w or image_h > target_h:
- scale_factor = float(target_w)/image_w
- new_w = target_w
- new_h = image_h*scale_factor
- if new_h > target_h:
- scale_factor = float(target_h)/new_h
- new_h = target_h
- new_w = target_w*scale_factor
- return int(new_w), int(new_h)
- return int(target_w), int(target_h)
-
- """
- Utility for calculating proto skin images
- """
- def _proto_skin(self, name, n, i):
- x, y = self._calc_image_offset(name, self.palettes[n][i].spr)
- self.palettes[n][i].spr.set_image(self.media_shapes[name], 1, x, y)
-
- """
- Some blocks get a skin
- """
- def _block_skin(self, name, blk):
- x, y = self._calc_image_offset(name, blk.spr)
- blk.set_image(self.media_shapes[name], x, y)
- self._resize_skin(blk)
-
- """
- Resize the 'skin' when block scale changes.
- """
- def _resize_skin(self, b):
- if b.name == 'nop':
- w, h = self._calc_w_h('pythonoff', b.spr)
- x, y = self._calc_image_offset('pythonoff', b.spr, w, h)
- elif b.name == 'journal':
- if len(b.values) == 1 and b.values[0] is not None:
- w, h = self._calc_w_h('', b.spr)
- x, y = self._calc_image_offset('journaloff', b.spr, w, h)
- else:
- w, h = self._calc_w_h('journaloff', b.spr)
- x, y = self._calc_image_offset('journaloff', b.spr, w, h)
- else:
- w, h = self._calc_w_h('descriptionoff', b.spr)
- x, y = self._calc_image_offset('descriptionoff', b.spr, w, h)
- b.scale_image(x, y, w, h)
+# find a stack to run (any stack without a hat)
+def find_block_to_run(tw, spr):
+ top = find_top_block(spr)
+ if spr == top and spr.proto.name[0:3] != 'hat':
+ return True
+ else:
+ return False
+
+def blocks(tw):
+ return [spr for spr in tw.sprites if spr.type == 'block']
+
+def xy(event):
+ return map(int, event.get_coords())
+
+def showPopup(block_name,tw):
+ if blocks_dict.has_key(block_name):
+ block_name_s = _(blocks_dict[block_name])
+ else:
+ block_name_s = _(block_name)
+ if hover_dict.has_key(block_name):
+ label = block_name_s + ": " + hover_dict[block_name]
+ else:
+ label = block_name_s
+ if hasattr(tw, "activity"):
+ tw.activity.hover_help_label.set_text(label)
+ tw.activity.hover_help_label.show()
+ elif hasattr(tw, "win"):
+ tw.win.set_title(_("Turtle Art") + " — " + label)
+ return 0