"""
Startup script - the first script to be called.

Loads system slice and creates any missing dimkeys.
Assigns entry points for input/instance/refresh (etc) scripts.
Defines base applitude type, and makes applitude list.

"""

import fw,zz,xu,sys,cmath,cPickle

#Set the main caption
fw.setcaption(' Xanadu Space')

#Print startup message
#print 'Python starting up...',

#Load the system slice
zz.loadslice('slices\\0.db.zzz')

#Create missing dimkeys
d1 = zz.createdimkey('d.1')
d2 = zz.createdimkey('d.2')
d3 = zz.createdimkey('d.3')
d4 = zz.createdimkey('d.4')
dcontinuity = zz.createdimkey('d.continuity')
drepresents = zz.createdimkey('d.represents')
drepresentstype = zz.createdimkey('d.representstype')
dmastershape = zz.createdimkey('d.mastershape')
dsize = zz.createdimkey('d.size')
drelativesize = zz.createdimkey('d.relativesize')
dcolor = zz.createdimkey('d.color')
dsinglesided = zz.createdimkey('d.singlesided')
dpoints = zz.createdimkey('d.points')
dtext = zz.createdimkey('d.text')
dfont = zz.createdimkey('d.font')
dfontcolor = zz.createdimkey('d.fontcolor')
dfontsize = zz.createdimkey('d.fontsize')
dparentcenter = zz.createdimkey('d.parentcenter')
dparentrotate = zz.createdimkey('d.parentrotate')
dtranslate = zz.createdimkey('d.translate')
drotate = zz.createdimkey('d.rotate')
dcenter = zz.createdimkey('d.center')
dglobalmatrix = zz.createdimkey('d.globalmatrix')
dglobalrotate = zz.createdimkey('d.globalrotate')
dglobaltranslate = zz.createdimkey('d.globaltranslate')
dglobalsize = zz.createdimkey('d.globalsize')
dtexture = zz.createdimkey('d.texture')
dflowposition = zz.createdimkey('d.flowposition')
drelativeposition = zz.createdimkey('d.relativeposition')
dscreenposition = zz.createdimkey('d.screenposition')
dreverse = zz.createdimkey('d.reverse')
dcurrentposition = zz.createdimkey('d.currentposition')

#Set the main script handlers
fw.setinputscript(fw.loadcompile('scripts\\input.py'))
fw.setrefreshscript(fw.loadcompile('scripts\\update.py'))
fw.setshutdownscript(fw.loadcompile('scripts\\shutdown.py'))
fw.setnewinstancescript(fw.loadcompile('scripts\\instance.py'))
fw.setrebuildscript(fw.loadcompile('scripts\\build.py'))

#Load any slices passed at the command line
loadedslice = None
for arg in fw.args():
	loadedslice = zz.loadslice(arg)


##TODO remove test stuff ##

#shapetest = 'slab'
#slabstate = [0,0,0,0]
#lineup = 0

#fw.execute(fw.compile(fw.load('test.py')))
#OR
#fw.execute(fw.compile(zz.value(mycell)))

#Define some shortcut functions
def key(name):return fw.input('keyboard',0,'button',name)[0]
def joy(index,name):return fw.input('joystick',index,'axis',name)[0]
def mousechange(name):return fw.input('mouse',0,'axis',name)[1]
def mousebutton(name):return fw.input('mouse',0,'button',name)[0]


class Applitude:
	"""
	Generic applitude that defines a basic level of behaviour.
	"""
	
	def __init__(self):
		"""
		Default constructor adds applitude to end of stack and builds.
		"""
		self.depth = len(applitudes)
		self.prev = None
		if self.depth: self.prev = applitudes[-1]
		applitudes.append(self)
		self.tempslice = None
		print 'rebuildtest'
		fw.rebuild()
		self.restart()

	def __del__(self):
		"""
		Default destroctor destroys the temporary slice.
		"""
		if self.tempslice:
			zz.destroyslice(self.tempslice)

	def input(self):
		"""
		Override to respond to mouse, keyboard and joystick input.
		Call fw.lastinput() to get the input to process.
		
		Default implementation calls input() for previous applitude.
		"""
		if self.prev:self.prev.input()
	def refresh(self):
		"""
		Override to carry out action after every frame.
		Call fw.frametime() to get the time between the last two frames.
		
		Default implementation calls refresh() for previous applitude.
		"""
		if self.prev:self.prev.refresh()
	def instance(self):
		"""
		Override to respond to the launching of a new instance of floatingworld.
		This may be caused by an associated file being launched, or from the
		xu protocol being used from a webbrowser.
		Call fw.args() to get the arguments passed to the new instance.

		Default implementation calls instance() for previous applitude.
		"""
		if self.prev:self.prev.instance()
	def build(self):
		"""
		Override to create a new scenelist when the scene is refreshed.
		Call fw.updatescene() to set the new scene.
		
		Default implementation calls build() for previous applitude.
		"""
		if self.prev:self.prev.build()
	def restart(self):
		"""
		Override to specify behaviour to carry out on starting, or rejoining
		the applitude. Generally will involve resetting the camera position
		
		Default implementation does nothing.
		"""
		
		pass
	
#global applitudes stack
applitudes = list()


class BaseApplitude(Applitude):
	"""
	The base applitude is always at the base of the applitude stack, and defines
	the global behaviour of floating world
	"""

	def input(self):
		"""
		Handle global keyboard commands.
		"""

		#get input details
		devicetype, device, inputtype, input, value, letter = fw.lastinput()
		shift = key('left shift') or key('right shift')
		ctrl = key('left ctrl') or key('right ctrl')

		#if keyboard input
		if devicetype == 'keyboard' and value == 1:

			#if escape pressed then exit
			if input == 'escape':
				applitudes.pop()
				if len(applitudes)==0:
					fw.exit()
				else:
					applitudes[-1].restart()
					fw.rebuild()

			#if f10 is pressed then toggle between fullscreen and window
			elif input == 'f10':
				fw.togglefullscreen()

			#if the 'home' key is pressed cycle through 'fill', 'line' and 'point' render modes
			elif input == 'home':
				if fw.rendermode() == 'fill':   fw.setrendermode('line')
				elif fw.rendermode() == 'line': fw.setrendermode('point')
				else:                           fw.setrendermode('fill')

			#if 'r' is pressed, then reset camera position
			elif input == 'r':
				fw.movecamera()
				fw.rotatecamera()

		#chain up
		Applitude.input(self)

	def refresh(self):
		"""
		Handle standard 3D navigation.
		"""

		#get the time taken to render the previous frame
		t = fw.frametime()

		#carry out quake style WSAD movement (if not in input mode)
		fw.movecamera(t*(key('right')-key('left'))/20,0,t*(key('down')-key('up'))/20)

		#if right mouse button is held down, then carry out quake style mouse rotation
		if mousebutton('right'):
			fw.rotatecamera(mousechange(1)/15,mousechange(0)/15,0)

		#carry out dual stick style movement
		fw.movecamera(t*joy(0,0)/40,0,t*joy(0,1)/40)
		fw.movecamera(t*joy(1,0)/40,0,t*joy(1,1)/40)

		#carry out dual stick style rotation
		fw.rotatecamera(t*joy(0,2)/30,t*joy(0,3)/30,0)

		#chain up
		Applitude.refresh(self)

	def instance(self):
		"""
		Respond to a new instance by just printing the command line arguments
		"""

		#print
		print fw.args()

		#chain up
		Applitude.instance(self)




BaseApplitude()

class TestApplitude2(Applitude):
	def build(self):
		pass
	

class TestApplitude(Applitude):

	def build(self):
		
		#set the slice, delete if present, and recreate
		self.tempslice = ('','','Test Slice')
		zz.destroyslice(self.tempslice)
		zz.createslice(self.tempslice)


		#get first cell for scene
		scenestart = zz.createcell(self.tempslice,'scene')
		scene = scenestart
		
		"""
		#create a load of spheroids
		#(1000 spheroids * 6 patches * 200 vertices = 1.2 million vertices)
		#about 10x fill
		for x in range(0,10):
			for y in range(0,10):
				for z in range(0,10):
					scene = zz.insert(scene,'d.2','spheroid')
					zz.insert(scene,'d.size',10,10,10)
					zz.insert(scene,'d.color',x*0.1,y*0.1,z*0.1,0.4)
					zz.insert(scene,'d.translate',x*11,y*11,z*11)
		"""

		#create a slab with two tetroids
		slab1 = zz.createcell(self.tempslice,'slab')
		zz.insert(slab1,'d.size',10,0,1)
		tet1 = zz.insert(slab1,'d.flowposition','tetroid')
		zz.insert(tet1,'d.text','This is the first line of text that I am testing with.\n\n\n')
		tet2 = zz.insert(tet1,'d.2','tetroid')
		zz.insert(tet2,'d.text','This is the second line of text that I am testing with.\n\n\n')

		#create another slab with two tetroids
		slab2 = zz.createcell(self.tempslice,'slab')
		zz.insert(slab2,'d.size',10,0,1)
		tet3 = zz.insert(slab2,'d.flowposition','tetroid')
		zz.insert(tet3,'d.text','This is the first line of text that I am testing with which is a bit longer than the one I was using before.\n\n\n\n\n\n\n\n')
		tet4 = zz.insert(tet3,'d.2','tetroid')
		zz.insert(tet4,'d.text','This is the second line of text that I am testing with which is a bit longer than the one I was using before.\n\n\n\n\n')
		
		"""
		#add first slab to scene, centered about the origin
		zz.insert(scene,'d.2',slab1)
		zz.insert(slab1,'d.parentcenter',0.5,0.5)

		#add second slab to scene, so that second tetroid is to the right, and vertically
		#aligned with the top of the second tetroid of the first slab
		zz.insert(tet2,'d.relativeposition',tet4)
		zz.insert(tet4,'d.parentcenter',1,0,1)
		zz.insert(tet4,'d.center',0,0,1)
		zz.insert(tet4,'d.translate',2)
		zz.insert(tet4,'d.rotate',0,-45)
		zz.insert(tet4,'d.parentrotate',0,-45)
		"""
		
		#cuboidtest = zz.createcell(self.tempslice,'slab')
		#zz.insert(cuboidtest,'d.size',3,3,3)
		
		#add the first slab to the scene, centered about second tetroid
		#zz.insert(scenestart,'d.relativeposition',cuboidtest,tet4)
		zz.insert(scenestart,'d.relativeposition',tet3)

		#update scene
		fw.updatescene(scenestart)

		
class ScrippleApplitude(Applitude):
	
	def __init__(self):
		"""
		Create scene slice with some background objects in
		"""
		
		self.docslice = zz.createslice('','','scrippleslice')
		self.docstart = zz.createcell(self.docslice,0)
		self.coord = None

		#add background	to the scene	
		background = zz.insert(self.docstart,d2,'slab')
		zz.insert(background,dsize,10,10,1)
		zz.insert(background,dcolor,1,1,1,1)
		
		background = zz.insert(self.docstart,d2,'spheroid')
		zz.insert(background,dsize,10,10,10)
		zz.insert(background,dcolor,1,0,1,1)
		zz.insert(background,dtranslate,12,0,0)
		
		
		#add a mark to the slice
		zz.mark(self.docslice);
		
		Applitude.__init__(self)
		
	def build(self):
		"""
		Nothing to do here! Just set the same scene again.
		"""
				
		fw.updatescene(self.docstart)

	def refresh(self):
		"""
		If the left mouse button is held down, and the mouse has moved sufficiently,
		then add another line segment.		
		"""

	
		#ignore if not a start coordinate
		if not self.coord:
			Applitude.refresh(self)
			return
			
		
		#if coord under the cursor
		coord, cell, index = fw.hittest()
		if coord[2]:
			print coord[2]
			coord = (coord[0],coord[1],coord[2]+0.05)
			coord = fw.screentomodel(coord)
			
			#if the position has changed sufficiently
			diff = (self.coord[0]-coord[0],self.coord[1]-coord[1],self.coord[2]-coord[2])
			dist = diff[0]*diff[0]+diff[1]*diff[1]+diff[2]*diff[2]
			if dist > 0.01:
				
					#add a line to the scene
					line = zz.insert(self.docstart,d2,'line')
					start = zz.insert(self.docstart,d2,'point')
					end = zz.insert(self.docstart,d2,'point')
					zz.insert(line,dpoints,start,end)
					zz.insert(line,dcolor,0,0,0,1)
					zz.insert(start,dtranslate,self.coord[0],self.coord[1],self.coord[2])
					zz.insert(end,dtranslate,coord[0],coord[1],coord[2])
					fw.setsworphspeed(0)
					fw.rebuild()
					self.coord = coord
				

		Applitude.refresh(self)

	def input(self):
		
		#get input details
		devicetype, device, inputtype, input, value, letter = fw.lastinput()

		#print fw.lastinput()

		#on lmb
		if devicetype == 'mouse' and input == 0:
			
			#if down
			if value == 1:
				
				#get coordinate, convert to global, and store it
				coord, cell, index = fw.hittest()	
				if coord[2]:
					coord = (coord[0],coord[1],coord[2]+0.05)
					self.coord = fw.screentomodel(coord)
			
				#print coord, self.coord
			
			#if up
			else:
				
				#get coordinate, convert to global
				coord, cell, index = fw.hittest()
				
				#if there is a start and end coordinate
				if coord[2] and self.coord:				
					coord = (coord[0],coord[1],coord[2]+0.05)
					coord = fw.screentomodel(coord)								
					
					#add a line to the scene
					line = zz.insert(self.docstart,d2,'line')
					start = zz.insert(self.docstart,d2,'point')
					end = zz.insert(self.docstart,d2,'point')
					zz.insert(line,dpoints,start,end)
					zz.insert(line,dcolor,0,0,0,1)
					zz.insert(start,dtranslate,self.coord[0],self.coord[1],self.coord[2])
					zz.insert(end,dtranslate,coord[0],coord[1],coord[2])
					
					#add a mark to the slice
					zz.mark(self.docslice);

					#do quick rebuild
					fw.setsworphspeed(0)
					fw.rebuild()

				self.coord = None
				
			return
		
		
		#get main alt keys
		shift = key('left shift') or key('right shift')
		ctrl = key('left ctrl') or key('right ctrl')
		
		#if keyboard input
		if devicetype == 'keyboard' and value == 1:
			
			#if 'ctrl+z', then undo current slice
			if ctrl and input == 'z':
				self.docslice

				#undo action
				test = zz.undo(self.docslice)
				
				#if shift isn't held down, then keep undoing until a mark is found
				if not shift:
					test = zz.undo(self.docslice)
					while test and test[0] != 'mark':
						test = zz.undo(self.docslice);
				
				#update the scene
				fw.rebuild()
				return

			#if 'ctrl+y', then redo current slice
			elif ctrl and input == 'y':

				#redo action
				test = zz.redo(self.docslice)
				
				#if shift isn't held down, then keep redoing until a mark is found
				if not shift:
					test = zz.redo(self.docslice)
					while test and test[0] != 'mark':
						test = zz.redo(self.docslice);
				
				#update the scene
				fw.rebuild()
				return
			
			
		#chain up
		Applitude.input(self)


class MenuApplitude(Applitude):
	"""
	The main applitude is always at the base of the applitude stack, and defines
	the initial applitude that the user will be presented with.
	
	TODO: build creates simple menu.
	TODO: input deals with menu selection (cursors and mouse clicks).
	"""
	
	def __init__(self):
		
		#sounds
		self.buttonchangesound = 'click.wav'
		self.buttonclickedsound = 'click.wav'
	
		#buttons info
		self.buttons = []
		self.buttons.append(['ZigZag','ZZApplitude()'])
		self.buttons.append(['Xanadu Space (origin)','TranslitApplitude()'])
		self.buttons.append(['Xanadu Space (edit))','TranslitApplitude2()'])
		self.buttons.append(['Test','TestApplitude()'])
		self.buttons.append(['Test2','TestApplitude2()'])
		self.buttons.append(['Scribble','ScrippleApplitude()'])
		self.currentbutton = 0

		#chain up
		Applitude.__init__(self)

		
	def build(self):
		"""
		Build a simple menu
		"""

		#set the slice, delete if present, and recreate
		self.tempslice = ('','','Test Slice')
		zz.destroyslice(self.tempslice)
		zz.createslice(self.tempslice)
		
		#get first cell for scene
		scenestart = zz.createcell(self.tempslice,'scene')
		scene = scenestart
		
		#create a few slabs, each with a single tetroid
		index = 0
		for button in self.buttons:
			scene = zz.insert(scene,'d.relativeposition','slab')
			zz.insert(scene,'d.translate',0,0.5,0)
			zz.insert(scene,'d.parentcenter',0.5,1,0.5)
			zz.insert(scene,'d.center',0.5,0,0.5)
			zz.insert(scene,'d.representstype',button[0]+'button')
			zz.insert(scene,'d.text',button[0])
			if index == self.currentbutton:
				zz.insert(scene,'d.color',1,1,1,1)
				zz.insert(scene,'d.size',9,2.5)
			else:
				zz.insert(scene,'d.color',1,1,1,0.4)
				zz.insert(scene,'d.size',7,2)
			
			tet = zz.insert(scene,'d.flowposition','tetroid')
			zz.insert(tet,'d.text',button[0])
			zz.insert(tet,'d.representstype',button[0])
			zz.insert(tet,'d.color',0,0,0,0)

			index = index+1
			
		fw.updatescene(scenestart)


		"""
		#create a load of spheroids
		for x in range(0,10):
			for y in range(0,10):
				for z in range(0,10):
					scene = zz.insert(scene,'d.2','spheroid')
					zz.insert(scene,'d.size',10,10,10)
					zz.insert(scene,'d.color',x*0.1,y*0.1,z*0.1,0.3)
					zz.insert(scene,'d.translate',x*11,y*11,z*11)


		#update scene
		fw.updatescene(scenestart)
		"""
	def input(self):
		"""
		Handle mouse input.
		"""

		#ignore if not the current applitude
		if not self == applitudes[-1]:
			Applitude.input(self)
			return

		#get input details
		devicetype, device, inputtype, input, value, letter = fw.lastinput()
		shift = key('left shift') or key('right shift')
		ctrl = key('left ctrl') or key('right ctrl')

		#change currentbutton from cursor keys
		if devicetype == 'keyboard' and value == 1:
			if input == 'e':
				fw.playsound(self.buttonchangesound)
				self.currentbutton = (self.currentbutton - 1) % len(self.buttons)
				fw.rebuild()
				return
			if input == 'c':
				fw.playsound(self.buttonchangesound)
				self.currentbutton = (self.currentbutton + 1) % len(self.buttons)
				fw.rebuild()
				return
				
		#do action based on selected item
		if devicetype == 'mouse' and value == 1:
			#print fw.lastinput()
			if input == 0:
				
				#do a hittest to find shape
				coord, cell, index = fw.hittest()
				
				#get the contents of the cells text
				if cell:
					reps = zz.next(cell,'d.text')
					if reps:
						reps = zz.value(reps)

					#execute the corresponding command for the button
					for button in self.buttons:
						if button[0] == reps:
							fw.playsound(self.buttonclickedsound)
							fw.execute(fw.compile(button[1]))
				
		#chain up
		Applitude.input(self)


	
	def refresh(self):
		"""
		Determine mouse cursor drag direction if required.
		"""

		#ignore if not the current applitude
		if not self == applitudes[-1]:
			Applitude.refresh(self)
			return


		#get distance mouse has moved in frame
		mousex = fw.input('mouse',0,'axis',0)[1]
		mousey = fw.input('mouse',0,'axis',1)[1]
		
		#if any movement has occured
		if mousex or mousey:
			
			#do a hittest to find shape
			coord, cell, index = fw.hittest()
			
			#print coord
			
			#get the contents of the cells text
			if cell:
				reps = zz.next(cell,'d.text')
				if reps:
					reps = zz.value(reps)

				#execute the corresponding command for the button
				index = 0
				for button in self.buttons:
					if button[0] == reps:
						if not index == self.currentbutton:
							fw.playsound(self.buttonchangesound)
							self.currentbutton = index
							fw.rebuild()
					index = index+1
		"""							
			if cell:
				reps = zz.next(cell,'d.representstype')
				if reps:
					reps = zz.value(reps)
				if(reps=='firstbutton' or reps=='first'):
					if not self.currentbutton == 0:
						fw.playsound(self.buttonchangesound)
						self.currentbutton = 0
						fw.rebuild()
				if(reps=='secondbutton' or reps=='second'):
					if not self.currentbutton == 1:
						fw.playsound(self.buttonchangesound)
						self.currentbutton = 1
						fw.rebuild()
				if(reps=='thirdbutton' or reps=='third'):
					if not self.currentbutton == 2:
						fw.playsound(self.buttonchangesound)
						self.currentbutton = 2
						fw.rebuild()
		"""
		#block up and down from propagating
		#if key('up') or key('down'):
		#	return

		Applitude.refresh(self)

	def restart(self):
		"""
		Reposition the camera back to the origin
		"""
		pass
		#fw.movecamerasworph()
		#fw.rotatecamerasworph()
		
		
#add main applitude to next on the stack
MenuApplitude()


class ZZApplitude(Applitude):
	"""
	Generic zigzag applitude.
	
	Handles zigzag editing through mouse and keyboard commands.
	Builds generic zigzag scene.
	"""

	#set dims (x,y,z for left and right)
	dims = [[zz.dimkey('d.1'),zz.dimkey('d.2'),zz.dimkey('d.3')],[zz.dimkey('d.1'),zz.dimkey('d.2'),zz.dimkey('d.3')]]

	#set cursors (left and right)
	cursors = [('','','0.db',0),('','','0.db',0)]

	#set current cursor (left)
	currentcursor = 0
	
	#set input mode to 'navigate'
	inputmode = 0

	#set variables for determining mouse cursor drag-direction
	startpos = None
	startcell = None
	startdir = None
	startcheck = 0
	startscreen = (0,0,0)

	lasttime = 0

	#set slice name for temporary scene slice
	myslice = ('','','tempslice')

	def input(self):
		"""
		Respond to all zigzag keyboard and mouse commands.
		"""
		
		#if 1 seconds have elapsed since the last input, then add a marker to both slices (an undo/redo point)
		if self.lasttime == 0 or fw.time()-self.lasttime > 2000:
			zz.mark(self.cursors[0]);
			zz.mark(self.cursors[1]);
		self.lasttime = fw.time()
		
		#get input details
		devicetype, device, inputtype, input, value, letter = fw.lastinput()
		
		#get main alt keys
		shift = key('left shift') or key('right shift')
		ctrl = key('left ctrl') or key('right ctrl')

		#get other alt keys
		lctrl = key('left ctrl')
		lshift = key('left shift')
		lalt = key('left alt')
		nkey = key('n')
		delkey = key('delete')
		aposkey = key("'")
		bkey = key('b')
		hkey = key('h')
		xkey = key('x')

		#get the current prompt
		prompt = fw.prompt()
		promptval = prompt
		if promptval == '': promptval = 0

		#get the cursor based on shift
		cursor = 1
		if shift: cursor = 0

		#if keyboard input
		if devicetype == 'keyboard' and value == 1:
			
			#if 'ctrl+z', then undo current slice
			if ctrl and input == 'z':
				myslice = self.cursors[cursor]

				#undo action
				test = zz.undo(myslice)
				
				#if shift isn't held down, then keep undoing until a mark is found
				if not shift:
					test = zz.undo(myslice)
					while test and test[0] != 'mark':
						test = zz.undo(myslice);
				
				#update the scene
				fw.rebuild()
				return

			#if 'ctrl+y', then redo current slice
			elif ctrl and input == 'y':
				myslice = self.cursors[cursor]
				
				#redo action
				test = zz.redo(myslice)
				
				#if shift isn't held down, then keep redoing until a mark is found
				if not shift:
					test = zz.redo(myslice)
					while test and test[0] != 'mark':
						test = zz.redo(myslice);
				
				#update the scene
				fw.rebuild()
				return

			#if 'tab', then toggle input mode
			elif input == 'tab':
				self.inputmode = not self.inputmode
				#fw.setfocus(cursors[cursor], 0)
				return

			#if in textmode
			if self.inputmode == 1:
				
				#replace \r with \n
				if letter == '\r':letter = '\n'
				
				#replace ctrl+v with clipboard contents
				if input == 'v' and ctrl:letter = fw.clipboard()

				#get the focused cell, cursor index and cell content
				cell, index = fw.focus()
				content = zz.value(cell)

				#print input

				#handle 'left','right','backspace' and 'delete' keys
				if input == 'left':
					if index>0:
						index = index-1
				elif input == 'right':
					print cell, content
					if index<len(content):
						index = index+1
				elif input == 'backspace':
					if index>0:
						content = content[:index-1] + content[index:]
						index = index-1
						zz.setvalue(cell,content)
						fw.rebuild()
				elif input == 'delete':
					if index<len(content):
						content = content[:index] + content[index+1:]
						zz.setvalue(cell,content)
						fw.rebuild()


				#handle all other keys as inserts
				elif letter != '':
					content = content[:index] + letter + content[index:]
					index = index+len(letter)
					zz.setvalue(cell,content)
					fw.rebuild()

				#set the new cell value, focus it, and rebuild the scene
				zz.setvalue(cell,content)
				fw.setfocus(cell,int(index))

				return
				
			#if in flight mode
			else:
				
				#Enter numbers and key values at the console
				if input=='1' or input=='2' or input=='3' or input=='4' or input=='5' or input=='6' or input=='7' or input=='8' or input=='9' or input=='0':
					fw.setprompt(fw.prompt()+input)
				if input=='n' or input=='b' or input=="'" or input=="!" or input=="/" or input=='h' or input=='u' or input=='t':
					fw.setprompt(input)

				#get the cursor and dimension
				dir = None
				kcursor = None

				#try the right hand kblang cursor
				if input == 'l':
					dir = self.dims[1][0]
					kcursor = 1
				if input == 'j':
					dir = zz.reverse(self.dims[1][0])
					kcursor = 1
				if input == 'i':
					dir = zz.reverse(self.dims[1][1])
					kcursor = 1
				if input == ',':
					dir = self.dims[1][1]
					kcursor = 1
				if input == 'k' and not shift:
					dir = self.dims[1][2]
					kcursor = 1
				if input == 'k' and shift:
					dir = zz.reverse(self.dims[1][2])
					kcursor = 1

				#try the left hand kblang cursor
				if input == 'f':
					dir = self.dims[0][0]
					kcursor = 0
				if input == 's':
					dir = zz.reverse(self.dims[0][0])
					kcursor = 0
				if input == 'e':
					dir = zz.reverse(self.dims[0][1])
					kcursor = 0
				if input == 'c':
					dir = self.dims[0][1]
					kcursor = 0
				if input == 'd' and not shift:
					dir = self.dims[0][2]
					kcursor = 0
				if input == 'd' and shift:
					dir = zz.reverse(self.dims[0][2])
					kcursor = 0

				#if direction was entered
				if dir:

					print prompt

					#if 'n' then insert a new cell
					if prompt == 'n':
						print 'test'
						zz.mark(self.cursors[kcursor])
						zz.insert(self.cursors[kcursor],dir)
						zz.mark(self.cursors[kcursor])
						fw.rebuild()
						fw.setprompt('')

					#if 't' then create a clone of the left cell
					elif prompt == 't':
						zz.insert(self.cursors[kcursor],dir,zz.createclone(self.cursors[0]))
						fw.rebuild()
						fw.setprompt('')

					#if 'T' then create a clone of the right cell
					elif prompt == 'T':
						zz.insert(self.cursors[kcursor],dir,zz.createclone(self.cursors[1]))
						fw.rebuild()
						fw.setprompt('')

					#if 'b' then break a connection
					elif prompt == 'b':
						zz.brek(self.cursors[kcursor],dir)
						fw.rebuild()
						fw.setprompt('')

					#if 'h' then hop a cell
					elif prompt == 'h':
						hopped = zz.next(self.cursors[kcursor],dir)
						if hopped:
							zz.insert(hopped,dir,self.cursors[kcursor])
							fw.rebuild()
							fw.setprompt('')

					#if 'x' then remove cell from rank
					elif prompt == 'x':
						zz.remove(self.cursors[kcursor],dir)
						fw.rebuild()
						fw.setprompt('')

					#if 'u' then create new slice
					elif prompt == 'u':
						slicename = zz.value(self.cursors[kcursor])
						account = zz.account(self.cursors[kcursor])
						newslice = zz.createslice(account,slicename)
						newcell = zz.createcell(newslice)
						zz.insert(self.cursors[kcursor],dir,newcell)
						fw.rebuild()
						fw.setprompt('')

					#if '/' then connect cursors
					elif prompt == '/':
						zz.brek(self.cursors[kcursor],dir,self.cursors[not kcursor])
						fw.rebuild()
						fw.setprompt('')

					#if '1' then connect cursor culls if it won't break any connections
					elif prompt == '1':
						if (not zz.next(self.cursors[kcursor],dir)) and (not zz.next(self.cursors[not kcursor],zz.reverse(dir))):
							zz.brek(self.cursors[kcursor],dir,self.cursors[not kcursor])
							fw.setprompt('')
							fw.rebuild()

					#otherwise, get move cursor
					else:
						test = zz.next(self.cursors[kcursor],dir)
						if test:
							self.cursors[kcursor] = test
							self.currentcursor = kcursor
							fw.rebuild()
							
				#if no direction was entered
				else:

					#if 'delete' then carry out retreat sequence and destroy cell
					if input == 'delete':

						#carry out retreat sequence
						test = zz.next(self.cursors[cursor], self.dims[cursor][0])
						if not test:
							test = zz.next(self.cursors[cursor], zz.reverse(self.dims[cursor][0]))
							if not test:
								test = zz.next(self.cursors[cursor], self.dims[cursor][1])
								if not test:
									test = zz.next(self.cursors[cursor], zz.reverse(self.dims[cursor][1]))
									if not test:
										test = zz.next(self.cursors[cursor], self.dims[cursor][2])
										if not test:
											test = zz.next(self.cursors[cursor], zz.reverse(self.dims[cursor][2]))
											if not test:
												test = zz.cell(zz.slice(self.cursors[cursor]), 0)
						#destroy cell
						zz.destroycell(self.cursors[cursor])
						self.cursors[cursor] = test
						fw.rebuild()

					#on 'backspace', delete the last character of the prompt
					if input=='backspace':
						fw.setprompt(fw.prompt()[:-1])

					#on 'g', move to cell number in prompt
					elif input=='g':
						cell = self.cursors[cursor]
						newcell = zz.cell(zz.slice(cell), int(promptval))
						fw.setprompt('')
						if newcell:
							self.cursors[cursor] = newcell
							fw.rebuild()

					#on 'r', reset the camera position, and reset dimensions
					elif input == 'r':
						fw.movecamera()
						fw.rotatecamera()
						self.dims[cursor] = [zz.dimkey('d.1'),zz.dimkey('d.2'),zz.dimkey('d.3')]
						self.cursors[cursor] = ('','','0.db',0)
						fw.rebuild()

					#on 'space' rebuild the current scene list
					elif input == 'space':
						fw.rebuild()

					#on 'h' return cursor to home cell
					elif input == 'h':
						self.cursors[cursor] = ('','','0.db',0)
						fw.rebuild()

					#on '>' or '<' move one cursor to the other
					elif letter == '>':
						self.cursors[0] = self.cursors[1]
						fw.rebuild()
					elif letter == '<':
						self.cursors[1] = self.cursors[0]
						fw.rebuild()

					#on 'x', 'y' or 'z' change the dimension
					elif letter == 'x' or letter == 'y' or letter == 'z':

						#get the direction to search (based on ctrl)
						dirsearch = None
						if ctrl: dirsearch = '-d.2'
						else:    dirsearch = '+d.2'

						#get the dimension index (based on letter)
						dimindex = -1
						if input == 'x':  dimindex = 0
						elif input == 'y': dimindex = 1
						elif input == 'z': dimindex = 2

						#if dimension key pressed, the change dimension
						if dimindex != -1:
							self.dims[cursor][dimindex] = zz.next(self.dims[cursor][dimindex], dirsearch)
							fw.rebuild()
						
		"""	
		if devicetype == 'mouse' and input == 0 and value == 1:
			coord, cell, index = fw.hittest()
			restest = zz.clonehead(zz.next(cell,'d.represents'))
			print coord, cell, index, restest
		"""			
		
		#if the middle mouse button is pressed
		if devicetype == 'mouse' and input == 0 and value == 1:

			#do a hittest for the mouse cursor position
			coord, cell, index = fw.hittest()

			#store as start position
			self.startscreen = coord
			self.startcell = cell
			self.startdir = None
			self.startpos = fw.screentomodel(coord, cell)
			self.startcheck = 1
			self.startres = zz.clonehead(zz.next(self.startcell,'d.represents'))

			fw.setfocus(self.startres,int(index))

			print 'newtest:',coord, self.startres, index
			return

	    #if the middle mouse button is released
		elif devicetype == 'mouse' and input == 0 and value == 0:
			
			#do a hittest for the mouse cursor position
			coord, cell, index = fw.hittest()

			#print 'test:',cell,self.startcell, self.startdir

			#if there is a start cell, and there has been movement
			if self.startcell and self.startdir:
			
				#if new cell at endpoint, then join the two cells
				if cell:
					cell = zz.clonehead(zz.next(cell,'d.represents'))
					self.startcell = self.startres
					if zz.next(self.startcell, self.startdir) == cell:
						zz.brek(self.startcell, self.startdir)
					else:
						zz.brek(self.startcell, self.startdir, cell)

				#otherwise create a new cell in that direction
				else:
					
					startcell = zz.clonehead(zz.next(self.startcell,'d.represents'))
					zz.insert(self.startcell, self.startdir)
					#print 'test2:',startcell, index
				fw.rebuild()

			#otherwise move cursor to cell
			else:

				#if there is a represented cell
				rep = zz.clonehead(zz.next(cell,'d.represents'))
				if rep:

					reptype = zz.value(zz.clonehead(zz.next(cell,'d.representstype')))
					print 'reptype',reptype

					#set the appropriate cursor to this cell
					if reptype.find('left') != -1:
						if self.cursors[0] != rep:
							self.cursors[0] = rep
							fw.setfocus(rep,int(index))
							fw.rebuild()
					elif reptype.find('right') != -1:
						if self.cursors[1] != rep:
							self.cursors[1] = rep
							fw.setfocus(rep,int(index))
							fw.rebuild()
					
			return
		
		#chain up
		Applitude.input(self)

	def refresh(self):
		"""
		Determine mouse cursor drag direction if required.
		"""
		
		"""
		if mousebutton(0):
			coord, cell, index = fw.hittest()
			#restest = zz.clonehead(zz.next(cell,'d.represents'))
			#print coord, cell, index, restest
			print index
		Applitude.refresh(self)
		return
		"""
		
		#ignore if in text input mode
		if self.inputmode == 1:
			return
			
		
		#get distance mouse has moved since 'startscreen'
		mousex = fw.input('mouse',0,'axis',0)
		mousey = fw.input('mouse',0,'axis',1)
		test = (mousex[0]-self.startscreen[0])*(mousex[0]-self.startscreen[0]) + (mousey[0]-self.startscreen[1])*(mousey[0]-self.startscreen[1])

		#if distance is greater than 10 pixels, and not got a start direction yet
		if self.startcheck == 1 and (test > 100):
			self.startcheck = 0

			#calculate the local model coord for the screen cursor position projected the startscreen depth
			coord = (mousex[0], mousey[0],self.startscreen[2])
			newpos = fw.screentomodel(coord, self.startcell)

			#figure out which dimension we have moved in, and set as startdir
			stuff = list()
			stuff.append((self.startpos[0]-newpos[0],zz.reverse(self.dims[0][0])))
			stuff.append((newpos[0]-self.startpos[0],self.dims[0][0]))
			stuff.append((self.startpos[1]-newpos[1],self.dims[0][1]))
			stuff.append((newpos[1]-self.startpos[1],zz.reverse(self.dims[0][1])))
			stuff.append((self.startpos[2]-newpos[2],self.dims[0][2]))
			stuff.append((newpos[2]-self.startpos[2],zz.reverse(self.dims[0][2])))
			stuff.sort()
			self.startdir = stuff[-1][1]

	
		#chain up
		Applitude.refresh(self)



	def AddRelative(self, prev, next):
		"""
		Make next relative to prev.
		"""
		
		test = zz.next(prev,drelativeposition)
		if test:
			zz.insert(test,d2,next)
		else:
			zz.insert(prev,drelativeposition,next)


	def CreateVunit(self, stuff, cell, importance):
		"""
		Create and return a vunit for cell, and add to stuff.
		"""

		#if entry already exists
		if cell in stuff:
			slab2,importance2 = stuff[cell]

			#if entry is more important, then return nothing
			if importance2 < importance:
				return

			#otherwise kill the other one
			else:
				zz.setvalue(slab2,'ignore')
				#zz.insert(slab2,'d.size',20,20,1)

		#create new vunit and add to stuff
		vunit = zz.createcell(self.myslice)
		stuff[cell] = vunit, importance
		return vunit

	def CreateRow(self, imp, stuff, dim, styleneg, stylepos, neglength, poslength):
		"""
		Create a row (or column) of cells along dim, for each item in stuff,
		according to style information.
		"""

		for cell, things in tuple(stuff.iteritems()):
			main, importance = things

			count = 0
			lastvunit = main
			for next in zz.following(cell, dim, neglength):
				count = count+1
				vunit = self.CreateVunit(stuff, next,importance+imp+count)
				if not vunit:break
				self.AddRelative(lastvunit,vunit)
				#zz.append(vunit,'d.mastershape',zz.createclone(stylepos,self.myslice))
				
				fw.debug()
				zz.insert(vunit,dmastershape,zz.createclone(stylepos,self.myslice))
				

				
				lastvunit = vunit

			count = 0
			lastvunit = main
			for next in zz.following(cell, zz.reverse(dim), poslength):
				count = count+1
				vunit = self.CreateVunit(stuff, next,importance+imp+count)
				if not vunit:break
				self.AddRelative(lastvunit,vunit)
				#zz.append(vunit,'d.mastershape',zz.createclone(styleneg,self.myslice))
				
				fw.debug()
				zz.insert(vunit,dmastershape,zz.createclone(styleneg,self.myslice))

				
				lastvunit = vunit


	def CreateSlab(self, stuff,slabstyle,idstyle,spacerstyle,tetroidstyle,repappend=''):
		"""
		Create a slab for each item in stuff, according to style information
		"""

		for cell, things in stuff.iteritems():
			slab, importance = things

			#ignore if already generated
			if zz.value(slab) != '':continue
			zz.setvalue(slab,'slab')

			#zz.append(slab,'d.mastershape',zz.createclone(slabstyle,self.myslice))
			zz.insert(slab,dmastershape,zz.createclone(slabstyle,self.myslice))

			zz.insert(slab,drepresents,zz.createclone(cell,self.myslice))
			zz.insert(slab, drepresentstype, repappend)

			if zz.value(cell)[-4:] == '.jpg' or zz.value(cell)[-4:] == '.bmp':
				#zz.insert(slab, 'd.texture', zz.value(cell))
				zz.insert(slab, dtexture, 'thumbnails\\'+zz.value(cell))


			#add a tetroid to the slab with the cell content
			tetroid = zz.insert(slab, 'd.flowposition')
			zz.insert(tetroid, dmastershape, zz.createclone(tetroidstyle,self.myslice))
			zz.insert(tetroid, dtext, zz.createclone(cell, self.myslice))
			zz.insert(tetroid, drepresents, zz.createclone(cell, self.myslice))
			zz.insert(tetroid, drepresentstype, 'content'+repappend)
			#zz.insert(tetroid, 'd.font', zz.createclone(cell, self.myslice))

			if not zz.next(slab, drelativeposition):
				zz.insert(slab, drelativeposition)
			id = zz.insert(zz.next(slab, drelativeposition), 'd.2')
			zz.insert(id, dmastershape, zz.createclone(idstyle,self.myslice))
			zz.insert(id, dtext, str(cell))
			zz.insert(id, drepresents, zz.createclone(cell, self.myslice))
			zz.insert(id, drepresentstype, 'id'+repappend)
			zz.insert(id, dparentcenter, 0, 1, 1)
			zz.insert(id, dcenter, 0, 1, 0)
			zz.insert(id, dsize, 10, 10)
			zz.insert(id, dtranslate, 0, -0.2)

	def CreateConnector(self, main, stuff, dim, stylepos, styleposstub, styleneg, stylenegstub, styleline, stylelinestub,repappend=''):
		"""
		Create connectors between all cells in stuff connected along dim, according
		to given style information.
		"""

		#for each vunit
		for cell, things in stuff.iteritems():
			slab, importance = things

			#if there is a next cell along dim
			nextcell = zz.next(cell,dim)
			if nextcell:

				#count the number of cells until we reach one in the scene
				jump = 0
				while nextcell not in stuff:
					test = zz.next(nextcell,dim)
					if not test: break
					if test == cell: break
					nextcell = test
					jump = jump + 1

				point1 = None
				point2 = None

				#if there is a connection
				if nextcell in stuff:
					nextslab, nextimportance = stuff[nextcell]

					#create the appropriate points
					point1 = zz.createcell(self.myslice)
					zz.insert(point1,dmastershape,zz.createclone(stylepos,self.myslice))
					self.AddRelative(slab,point1)
					point2 = zz.createcell(self.myslice)
					zz.insert(point2,dmastershape,zz.createclone(styleneg,self.myslice))
					self.AddRelative(nextslab,point2)

				#otherwise
				else:
					nextcell = zz.next(cell,dim)

					#create stub points
					point1 = zz.createcell(self.myslice)
					zz.insert(point1,dmastershape,zz.createclone(stylepos,self.myslice))
					self.AddRelative(slab,point1)
					point2 = zz.createcell(self.myslice)
					zz.insert(point2,dmastershape,zz.createclone(styleposstub,self.myslice))
					self.AddRelative(slab,point2)

				#create line between the two points
				line = zz.insert(main,d2,'line')
				zz.insert(line,dpoints,point1,point2)

				#give distance connection a different color
				if jump:
					zz.insert(line,dmastershape,zz.createclone(stylelinestub,self.myslice))
				else:
					zz.insert(line,dmastershape,zz.createclone(styleline,self.myslice))

				#add represents information
				zz.insert(line,drepresents,zz.createclone(cell,self.myslice))
				zz.insert(line,drepresentstype,repappend+str(nextcell))

			#if there is a previous cell along dim
			prevcell = zz.next(cell,zz.reverse(dim))
			if prevcell:


				jump = 0
				while prevcell not in stuff:
					test = zz.next(prevcell,zz.reverse(dim))
					if not test: break
					if test == cell: break
					prevcell = test
					jump = jump + 1


				#if not shown
				if prevcell not in stuff:
					prevcell = zz.next(cell,zz.reverse(dim))

					#create two points
					point1 = zz.createcell(self.myslice)
					zz.insert(point1,dmastershape,zz.createclone(styleneg,self.myslice))
					self.AddRelative(slab,point1)

					point2 = zz.createcell(self.myslice)
					zz.insert(point2,dmastershape,zz.createclone(stylenegstub,self.myslice))
					self.AddRelative(slab,point2)

					#create line
					line = zz.insert(main,d2,'line')
					zz.insert(line,dmastershape, zz.createclone(stylelinestub,self.myslice))
					zz.insert(line,dpoints,point1,point2)
					zz.insert(line,drepresents,zz.createclone(prevcell,self.myslice))
					zz.insert(line,drepresentstype,repappend+str(cell))



	def makescene(self):
		"""
		Specify style information, and build the scene
		"""

		starttime = fw.time()

		#destroy and create style slice
		styleslice = ('','','style')
		zz.destroyslice(styleslice)
		zz.createslice(styleslice)

		#slab and tetroid style
		slabstyle = zz.createcell(styleslice)
		zz.setvalue(slabstyle,'slab')
		#zz.insert(slabstyle,'d.size',5,5,1)
		zz.insert(slabstyle,'d.size',5,5,1)
		
		#zz.insert(slabstyle,'d.color',1,1,1,0.5)
		zz.insert(slabstyle,'d.center',0.5,0.5,0.5)
		zz.insert(slabstyle,'d.parentcenter',0.5,0.5,0.5)

		idstyle = zz.createcell(styleslice)
		zz.setvalue(idstyle,'tetroid')
		#zz.insert(idstyle, 'd.representstype', 'id')
		zz.insert(idstyle,'d.fontcolor',0,0,1,1)
		zz.insert(idstyle,'d.font','Times New Roman')
		zz.insert(idstyle,'d.fontsize',0.8,0.8)
		zz.insert(idstyle,'d.color', 0, 0, 0, 0)
		#zz.insert(idstyle,'d.color',0.5,0.5,0.5,1)

		spacerstyle = zz.createcell(styleslice)
		zz.setvalue(spacerstyle,'spacer')
		zz.insert(spacerstyle,'d.size',0,1)

		tetroidstyle = zz.createcell(styleslice)
		zz.setvalue(tetroidstyle, 'tetroid')
		#zz.insert(tetroidstyle,'d.representstype','content')
		zz.insert(tetroidstyle,'d.fontcolor',0,0,0,1)
		zz.insert(tetroidstyle,'d.font','Arial')
		#zz.insert(tetroidstyle,'d.color', 0.9, 0.95, 0.95, 0.9)
		zz.insert(tetroidstyle,'d.color', 1, 1, 1, 1)

		selectedslabstyle = zz.createcell(styleslice)
		#zz.insert(selectedslabstyle,'d.mastershape',zz.createclone(slabstyle))
		zz.insert(selectedslabstyle,'d.color',1,0.7,0.7,1)
		zz.insert(selectedslabstyle,'d.size',5,5,1)
		#zz.insert(selectedslabstyle,'d.size',5*goldenratio,5*goldenratio,1)

		translucentslabstyle = zz.createcell(styleslice)
		zz.insert(translucentslabstyle,'d.mastershape',zz.createclone(slabstyle))
		zz.insert(translucentslabstyle,'d.color',0.1,0.1,0.1,0.3)

		#position style
		verticaltopstyle = zz.createcell(styleslice)
		#zz.insert(verticaltopstyle,'d.rotate',3)
		#zz.insert(verticaltopstyle,'d.parentrotate',3)
		zz.insert(verticaltopstyle,'d.translate',0.0,1)
		zz.insert(verticaltopstyle,'d.parentcenter',0.5,1)
		zz.insert(verticaltopstyle,'d.center',0.5,0)

		verticalbottomstyle = zz.createcell(styleslice)
		#zz.insert(verticalbottomstyle,'d.rotate',-3)
		#zz.insert(verticalbottomstyle,'d.parentrotate',-3)
		zz.insert(verticalbottomstyle,'d.translate',0.0,-1)
		zz.insert(verticalbottomstyle,'d.parentcenter',0.5,0)
		zz.insert(verticalbottomstyle,'d.center',0.5,1)

		horizontalrightstyle = zz.createcell(styleslice)
		#zz.insert(horizontalrightstyle,'d.rotate',0,-5)
		#zz.insert(horizontalrightstyle,'d.parentrotate',0,-5)
		zz.insert(horizontalrightstyle,'d.translate',1)
		zz.insert(horizontalrightstyle,'d.parentcenter',1,0.5,0)
		zz.insert(horizontalrightstyle,'d.center',0,0.5,0)

		horizontalleftstyle = zz.createcell(styleslice)
		#zz.insert(horizontalleftstyle,'d.rotate',0,-5)
		#zz.insert(horizontalleftstyle,'d.parentrotate',0,-5)
		zz.insert(horizontalleftstyle,'d.translate',-1)
		zz.insert(horizontalleftstyle,'d.parentcenter',0,0.5,0)
		zz.insert(horizontalleftstyle,'d.center',1,0.5,0)

		depthnearstyle = zz.createcell(styleslice)
		zz.insert(depthnearstyle,'d.translate',0,0,5)
		zz.insert(depthnearstyle,'d.parentcenter',0.5,0.5,0)
		zz.insert(depthnearstyle,'d.center',0.5,0.5,1)

		depthfarstyle = zz.createcell(styleslice)
		zz.insert(depthfarstyle,'d.translate',0,0,-5)
		zz.insert(depthfarstyle,'d.parentcenter',0.5,0.5,1)
		zz.insert(depthfarstyle,'d.center',0.5,0.5,0)

		diagposstyle = zz.createcell(styleslice)
		zz.insert(diagposstyle,'d.translate',0,5,5)
		zz.insert(diagposstyle,'d.parentcenter',0.0,0.0,1)
		zz.insert(diagposstyle,'d.center',1.0,1.0,1)

		diagnegstyle = zz.createcell(styleslice)
		zz.insert(diagnegstyle,'d.translate',0,-5,-5)
		zz.insert(diagnegstyle,'d.parentcenter',1.0,1.0,1)
		zz.insert(diagnegstyle,'d.center',1.0,1.0,1)

		#Connector style
		styleverticalpos = zz.createcell(styleslice)
		zz.insert(styleverticalpos,'d.parentcenter',0.5,1,0.5)

		styleverticalposstub = zz.createcell(styleslice)
		zz.insert(styleverticalposstub,'d.parentcenter',0.5,1,0.5)
		zz.insert(styleverticalposstub,'d.translate',0,-0.4,0)

		styleverticalneg = zz.createcell(styleslice)
		zz.insert(styleverticalneg,'d.parentcenter',0.5,0,0.5)

		styleverticalnegstub = zz.createcell(styleslice)
		zz.insert(styleverticalnegstub,'d.parentcenter',0.5,0,0.5)
		zz.insert(styleverticalnegstub,'d.translate',0,0.4,0)

		styleverticalline = zz.createcell(styleslice)
		zz.setvalue(styleverticalline,'line')
		zz.insert(styleverticalline,'d.color',0.5,0.5,1,1)

		styleverticallinestub = zz.createcell(styleslice)
		zz.setvalue(styleverticallinestub,'line')
		zz.insert(styleverticallinestub,'d.color',0.5,0.5,1,0.2)

		stylehorizontalpos = zz.createcell(styleslice)
		zz.insert(stylehorizontalpos,'d.parentcenter',1,0.5,0.5)

		stylehorizontalposstub = zz.createcell(styleslice)
		zz.insert(stylehorizontalposstub,'d.parentcenter',1,0.5,0.5)
		zz.insert(stylehorizontalposstub,'d.translate',0.4,0,0)

		stylehorizontalneg = zz.createcell(styleslice)
		zz.insert(stylehorizontalneg,'d.parentcenter',0,0.5,0.5)

		stylehorizontalnegstub = zz.createcell(styleslice)
		zz.insert(stylehorizontalnegstub,'d.parentcenter',0,0.5,0.5)
		zz.insert(stylehorizontalnegstub,'d.translate',-0.4,0,0)

		stylehorizontalline = zz.createcell(styleslice)
		zz.setvalue(stylehorizontalline,'line')
		zz.insert(stylehorizontalline,'d.color',0.5,1.0,0.5,1)

		stylehorizontallinestub = zz.createcell(styleslice)
		zz.setvalue(stylehorizontallinestub,'line')
		zz.insert(stylehorizontallinestub,'d.color',0.5,1.0,0.5,0.2)

		styledepthpos = zz.createcell(styleslice)
		zz.insert(styledepthpos,'d.parentcenter',0.5,0.5,1)

		styledepthposstub = zz.createcell(styleslice)
		zz.insert(styledepthposstub,'d.parentcenter',0.5,0.5,1)
		zz.insert(styledepthposstub,'d.translate',0,0,-0.4)

		styledepthneg = zz.createcell(styleslice)
		zz.insert(styledepthneg,'d.parentcenter',0.5,0.5,0)

		styledepthnegstub = zz.createcell(styleslice)
		zz.insert(styledepthnegstub,'d.parentcenter',0.5,0.5,0)
		zz.insert(styledepthnegstub,'d.translate',0,0,0.4)

		styledepthline = zz.createcell(styleslice)
		zz.setvalue(styledepthline,'line')
		zz.insert(styledepthline,'d.color',1.0,0.5,0.5,1)

		styledepthlinestub = zz.createcell(styleslice)
		zz.setvalue(styledepthlinestub,'line')
		zz.insert(styledepthlinestub,'d.color',1.0,0.5,0.5,0.2)



		#get focused cell (use home cell if no focused cell)
		cursor, index = fw.focus()
		if not cursor:cursor = ('','','0.db',0)

		#destroy and create scene slice
		zz.destroyslice(self.myslice)
		zz.createslice(self.myslice)

		#create cell in new slice
		main = zz.createcell(self.myslice)
		zz.insert(main,'d.translate',0,0,-40)

		#create all cells and connectors for left view
		stuff = dict()
		main0 = self.CreateVunit(stuff, self.cursors[0], 0.0)
		zz.insert(main0, 'd.translate', -28, 0, 0)
		self.CreateSlab(stuff,selectedslabstyle,idstyle,spacerstyle,tetroidstyle, 'left')
		
		"""
		x, y, z
		
		if no next or previous on x, push x to end
		if no next or previous on y, push y to end
		if no next or previous on z, push z to end
		"""
		if len(zz.rank(self.cursors[0],self.dims[0][0])) == 1:
			self.CreateRow(0000,stuff,self.dims[0][1],verticalbottomstyle,verticaltopstyle, -1, -1)
			self.CreateRow(1000,stuff,self.dims[0][0],horizontalleftstyle,horizontalrightstyle, 4, -1)
		else:
			self.CreateRow(0000,stuff,self.dims[0][0],horizontalleftstyle,horizontalrightstyle, 4, -1)
			self.CreateRow(1000,stuff,self.dims[0][1],verticalbottomstyle,verticaltopstyle, -1, -1)
		
		#self.CreateRow(0000,stuff,self.dims[0][0],horizontalleftstyle,horizontalrightstyle, 4, -1)
		#self.CreateRow(1000,stuff,self.dims[0][1],verticalbottomstyle,verticaltopstyle, -1, -1)
		self.CreateSlab(stuff,slabstyle,idstyle,spacerstyle,tetroidstyle, 'left')
		self.CreateRow(2000,stuff,self.dims[0][2],depthnearstyle,depthfarstyle, -1, -1)
		self.CreateSlab(stuff,slabstyle,idstyle,spacerstyle,tetroidstyle, 'left')
		self.CreateConnector(main, stuff, self.dims[0][0], stylehorizontalpos, stylehorizontalposstub, stylehorizontalneg, stylehorizontalnegstub, stylehorizontalline, stylehorizontallinestub, 'left')
		self.CreateConnector(main, stuff, self.dims[0][1], styleverticalpos, styleverticalposstub, styleverticalneg, styleverticalnegstub, styleverticalline, styleverticallinestub, 'left')
		self.CreateConnector(main, stuff, self.dims[0][2], styledepthpos, styledepthposstub, styledepthneg, styledepthnegstub, styledepthline, styledepthlinestub, 'left')


		#create dim arrows for left view
		test = zz.next(main0, 'd.relativeposition')
		if not test:test = zz.insert(main0, 'd.relativeposition')

		slabx = zz.insert(test, 'd.2', 'slab')
		zz.insert(slabx, 'd.translate', -17, -35, 1)
		zz.insert(slabx, 'd.size', 3, 3, 1);
		zz.insert(slabx, 'd.representstype', '00')
		tetx = zz.insert(slabx, 'd.flowposition', 'tetroid')
		zz.insert(tetx, 'd.text', zz.value(self.dims[0][0]))
		zz.insert(tetx, 'd.representstype', 'text00')

		slaby = zz.insert(test, 'd.2', 'slab')
		zz.insert(slaby, 'd.translate', -20, -32, 1)
		zz.insert(slaby, 'd.size', 3, 3, 1);
		zz.insert(slaby, 'd.representstype', '01')
		tety = zz.insert(slaby, 'd.flowposition', 'tetroid')
		zz.insert(tety, 'd.text', zz.value(self.dims[0][1]))
		zz.insert(tety, 'd.representstype', 'text01')

		slabz = zz.insert(test, 'd.2', 'slab')
		zz.insert(slabz, 'd.translate', -20, -35, 2)
		zz.insert(slabz, 'd.size', 3, 3, 1);
		zz.insert(slabz, 'd.representstype', '02')
		tetz = zz.insert(slabz, 'd.flowposition', 'tetroid')
		zz.insert(tetz, 'd.text', zz.value(self.dims[0][2]))
		zz.insert(tetz, 'd.representstype', 'text02')

		#now alter the accursed cells
		if self.cursors[0] in stuff:
			zz.insert(stuff[self.cursors[0]][0],'d.color',0.5,0.5,1,1)
		if self.cursors[1] in stuff:
			zz.insert(stuff[self.cursors[1]][0],'d.color',0.5,1,0.5,1)
		if self.cursors[0] in stuff and self.cursors[1] in stuff and self.cursors[0] == self.cursors[1]:
			zz.insert(stuff[self.cursors[1]][0],'d.color',0.5,1,1,1)


		#create all cells and connectors for right view
		stuff = dict()
		main1 = self.CreateVunit(stuff, self.cursors[1], 0.0)
		zz.insert(main1, 'd.translate', +28, 0, 0)
		self.CreateSlab(stuff,selectedslabstyle,idstyle,spacerstyle,tetroidstyle, 'right')
		self.CreateRow(0000,stuff,self.dims[1][1],verticalbottomstyle,verticaltopstyle, -1, -1)
		self.CreateRow(1000,stuff,self.dims[1][0],horizontalleftstyle,horizontalrightstyle, -1, 4)
		self.CreateSlab(stuff,slabstyle,idstyle,spacerstyle,tetroidstyle, 'right')
		self.CreateRow(2000,stuff,self.dims[1][2],depthnearstyle,depthfarstyle, -1, -1)
		self.CreateSlab(stuff,slabstyle,idstyle,spacerstyle,tetroidstyle, 'right')
		self.CreateConnector(main, stuff, self.dims[1][0], stylehorizontalpos, stylehorizontalposstub, stylehorizontalneg, stylehorizontalnegstub, stylehorizontalline, stylehorizontallinestub, 'right')
		self.CreateConnector(main, stuff, self.dims[1][1], styleverticalpos, styleverticalposstub, styleverticalneg, styleverticalnegstub, styleverticalline, styleverticallinestub, 'right')
		self.CreateConnector(main, stuff, self.dims[1][2], styledepthpos, styledepthposstub, styledepthneg, styledepthnegstub, styledepthline, styledepthlinestub, 'right')

		#create dim arrows for right view
		test = zz.next(main1, 'd.relativeposition')
		if not test:test = zz.insert(main1, 'd.relativeposition')

		slabx = zz.insert(test, 'd.2', 'slab')
		zz.insert(slabx, 'd.translate', -17, -35, 1)
		zz.insert(slabx, 'd.size', 3, 3, 1);
		zz.insert(slabx, 'd.representstype', '10')
		tetx = zz.insert(slabx, 'd.flowposition', 'tetroid')
		zz.insert(tetx, 'd.text', zz.value(self.dims[1][0]))
		zz.insert(tetx, 'd.representstype', 'text10')

		slaby = zz.insert(test, 'd.2', 'slab')
		zz.insert(slaby, 'd.translate', -20, -32, 1)
		zz.insert(slaby, 'd.size', 3, 3, 1);
		zz.insert(slaby, 'd.representstype', '11')
		tety = zz.insert(slaby, 'd.flowposition', 'tetroid')
		zz.insert(tety, 'd.text', zz.value(self.dims[1][1]))
		zz.insert(tety, 'd.representstype', 'text11')

		slabz = zz.insert(test, 'd.2', 'slab')
		zz.insert(slabz, 'd.translate', -20, -35, 2)
		zz.insert(slabz, 'd.size', 3, 3, 1);
		zz.insert(slabz, 'd.representstype', '12')
		tetz = zz.insert(slabz, 'd.flowposition', 'tetroid')
		zz.insert(tetz, 'd.text', zz.value(self.dims[1][2]))
		zz.insert(tetz, 'd.representstype', 'text12')

		#set the color of the two main cells
		#zz.insert(main0,'d.color',1,0.7,0.7,1)
		#zz.insert(main1,'d.color',0.7,0.7,1,1)
		

		#add the two main cells as relative position to main
		test = zz.insert(main, 'd.relativeposition', '')
		zz.insert(test, 'd.2', main0, main1)

		#now alter the accursed cells
		if self.cursors[0] in stuff:
			zz.insert(stuff[self.cursors[0]][0],'d.color',0.5,0.5,1,1)
		if self.cursors[1] in stuff:
			zz.insert(stuff[self.cursors[1]][0],'d.color',0.5,1,0.5,1)
		if self.cursors[0] in stuff and self.cursors[1] in stuff and self.cursors[0] == self.cursors[1]:
			zz.insert(stuff[self.cursors[1]][0],'d.color',0.5,1,1,1)
			
		#set as new scene
		fw.updatescene(main, 500)
		
		print 'scene size', len(zz.cells(self.myslice)), len(zz.cells(styleslice))
		
		print 'build time', fw.time() - starttime
		
	def build(self):
		"""
		Build a generic column-row dual zigzag view
		"""
		self.makescene()

		

#if a slice has been loaded, then show in left
if loadedslice:
	ZZApplitude.cursors[0] = zz.createcell(loadedslice,1)


#test
#ZZApplitude()



def transclude(strand1,text1,strand2,text2):

	#find index of text1 in strand1 and of text2 in strand2
	index1 = xu.value(strand1).find(text1)
	index2 = xu.value(strand2).find(text2)
	
	#error if either don't exist
	if index1 == -1 or index2 == -1:
		print 'WARNING! transclude function error!', text1, index1, text2, index2
		return
	
	#remove content from strand2
	xu.remove(strand2,index2,index2+len(text2))
	
	#insert transclusion into strand2
	xu.insert(strand2,index2,strand1+(index1,len(text1)))

def clink(type,strand1,text1,strand2,text2=''):
	
	#find index of text1 in strand1 and of text2 in strand2
	index1 = xu.value(strand1).find(text1)
	if text2 == '':index2 = 0
	else:index2 = xu.value(strand2).find(text2)
	
	#error if either don't exist
	if index1 == -1 or index2 == -1:
		print 'WARNING! clink function error!', text1, index1, text2, index2
		return
	
	#create clink
	clinky = xu.createclink(('','','Test EDL'), type)
	xu.addfrom(clinky, strand1+(index1,len(text1)))
	if text2 == '':xu.addto(clinky, strand2+(0,len(xu.value(strand2))))
	else:xu.addto(clinky, strand2+(index2,len(text2)))
	

class TranslitApplitude(Applitude):
	"""
	Generic translit applitude, that responds to input, and builds appropriate scene.
	"""
	
	#reference to a strand, and an index into the strand
	strandcursor = None
	strandcursorindex = 0
	myedl = ('','','Test EDL')
	myscroll = ('','','Test Permascroll')
	slabstate = [0,0,0,0]
	testcount = 0
	lineup = 0
	selectionchunks = []
	inputmode = 0
	lasttime = 0
	clinkcolours = {}

	currentclink = None
	currentstrand = None

	#slabstate[testcount]

	def __init__(self):
		
		#set clink colours
		self.clinkcolours['transclusion'] = [0,(1,0,0,0.2)]
		self.clinkcolours['resemblance'] = [0,(1,1,0,0.2)]
		self.clinkcolours['sticky note'] = [0,(1,0.64,0,0.2)]
		self.clinkcolours['comment'] = [0,(0,1,0,0.2)]
		self.clinkcolours['connection'] = [0,(0.7,0.7,1,0.2)]		
		self.clinkcolours['clash'] = [0,(0,0,1,0.2)]
		self.clinkcolours['pointer'] = [0,(0.29,0,0.51,0.2)]
		self.clinkcolours['correspondence'] = [0,(0.62,0.13,0.93,0.2)]
		self.clinkcolours['counterpart'] = [0,(0.62,0.13,0.93,0.2)]
		self.clinkcolours['disagreement'] = [0,(0.5,0.5,0.5,0.2)]
		
		#create an edl and permascroll
		xu.destroyedl(self.myedl)
		xu.createedl(self.myedl)
		xu.destroypermascroll(self.myscroll)
		xu.createpermascroll(self.myscroll)


		"""
		NelsonIntro.txt
		
		BenSiraLilith-cut.txt
		DarwinDescentCh1-cut.txt
		DeadOfNightRev-cut.txt
		GilgamishFlood-cut.txt
		K.JamesCreation-cut.txt
		K.JamesFlood-cut.txt
		LongBibleOrigins-cut.txt
		SchoolsBigBang-cut-FIX2.txt
		SchoolsSteadyState-cut.txt
		WpediaSteadyState-cut.txt
		"""

		#load in all demo texts (11)
		NelsonIntro = xu.createstrand(self.myedl)
		xu.insert(NelsonIntro,0,xu.append(self.myscroll,fw.load('texts\\demo\\NelsonIntro.txt')))
		BenSiraLilith = xu.createstrand(self.myedl)
		xu.insert(BenSiraLilith,0,xu.append(self.myscroll,fw.load('texts\\demo\\BenSiraLilith-cut.txt')))
		DarwinDescentCh1 = xu.createstrand(self.myedl)
		xu.insert(DarwinDescentCh1,0,xu.append(self.myscroll,fw.load('texts\\demo\\DarwinDescentCh1-cut.txt')))
		DeadOfNightRev = xu.createstrand(self.myedl)
		xu.insert(DeadOfNightRev,0,xu.append(self.myscroll,fw.load('texts\\demo\\DeadOfNightRev-cut.txt')))
		GilgamishFlood = xu.createstrand(self.myedl)
		xu.insert(GilgamishFlood,0,xu.append(self.myscroll,fw.load('texts\\demo\\GilgamishFlood-cut.txt')))
		KJamesCreation = xu.createstrand(self.myedl)
		xu.insert(KJamesCreation,0,xu.append(self.myscroll,fw.load('texts\\demo\\K.JamesCreation-cut.txt')))
		KJamesFlood = xu.createstrand(self.myedl)
		xu.insert(KJamesFlood,0,xu.append(self.myscroll,fw.load('texts\\demo\\K.JamesFlood-cut.txt')))
		LongBibleOrigins = xu.createstrand(self.myedl)
		xu.insert(LongBibleOrigins,0,xu.append(self.myscroll,fw.load('texts\\demo\\LongBibleOrigins-cut.txt')))
		SchoolsBigBang = xu.createstrand(self.myedl)
		xu.insert(SchoolsBigBang,0,xu.append(self.myscroll,fw.load('texts\\demo\\SchoolsBigBang-cut-FIX2.txt')))
		SchoolsSteadyState = xu.createstrand(self.myedl)
		xu.insert(SchoolsSteadyState,0,xu.append(self.myscroll,fw.load('texts\\demo\\SchoolsSteadyState-cut.txt')))
		WpediaSteadyState = xu.createstrand(self.myedl)
		xu.insert(WpediaSteadyState,0,xu.append(self.myscroll,fw.load('texts\\demo\\WpediaSteadyState-cut.txt')))

		#add all transclusions (13)
		#1
		transclude(BenSiraLilith,"""It is not good for man to be alone""", KJamesCreation, """It is not good that the man should be alone""")
		#8
		transclude(SchoolsBigBang,"""Fred Hoyle was unhappy about accepting a God given creation, and as an atheist attempted to develop a theory without such an intervention. This was to become the steady state theory.""",NelsonIntro,"""FRED HOYLE WAS UNHAPPY ABOUT ACCEPTING A GOD GIVEN CREATION, AND AS AN ATHEIST ATTEMPTED TO DEVELOP A THEORY WITHOUT SUCH AN INTERVENTION. THIS WAS TO BECOME THE STEADY STATE THEORY.""")
		#9
		transclude(WpediaSteadyState,"""The steady state theory of Bondi, Gold and Hoyle was inspired by the circular plot of the film Dead of Night they watched together""", NelsonIntro,"""THE STEADY STATE THEORY OF BONDI, GOLD AND HOYLE WAS INSPIRED BY THE CIRCULAR PLOT OF THE FILM DEAD OF NIGHT THEY WATCHED TOGETHER""")
		#10
		transclude(WpediaSteadyState,"""An aesthetically unattractive feature of the theory""" ,NelsonIntro, """AN AESTHETICALLY UNATTRACTIVE FEATURE OF THE THEORY""")
		#11
		transclude(WpediaSteadyState,"""alone among all cosmologies, the steady state model makes such definite predictions that it can be disproved even with the limited observational evidence at our disposal.""", NelsonIntro,"""ALONE AMONG ALL COSMOLOGIES, THE STEADY STATE MODEL MAKES SUCH DEFINITE PREDICTIONS THAT IT CAN BE DISPROVED EVEN WITH THE LIMITED OBSERVATIONAL EVIDENCE AT OUR DISPOSAL.""")
		#12
		transclude(WpediaSteadyState,"""Chaotic inflation theory has many similarities with steady state theory, although on a much larger scale than originally envisaged.""", NelsonIntro, """CHAOTIC INFLATION THEORY HAS MANY SIMILARITIES WITH STEADY STATE THEORY, ALTHOUGH ON A MUCH LARGER SCALE THAN ORIGINALLY ENVISAGED.""")
		#13
		transclude(DarwinDescentCh1,"""Thus we can understand how it has come to pass that man and all other vertebrate animals have been constructed on the same general model, why they pass through the same early stages of development, and why they retain certain rudiments in common.  Consequently we ought frankly to admit their community of descent:  to take any other view, is to admit that our own structure, and that of all the animals around us, is a mere snare laid to entrap our judgment.""", NelsonIntro,"""THUS WE CAN UNDERSTAND HOW IT HAS COME TO PASS THAT MAN AND ALL OTHER VERTEBRATE ANIMALS HAVE BEEN CONSTRUCTED ON THE SAME GENERAL MODEL, WHY THEY PASS THROUGH THE SAME EARLY STAGES OF DEVELOPMENT, AND WHY THEY RETAIN CERTAIN RUDIMENTS IN COMMON.  CONSEQUENTLY WE OUGHT FRANKLY TO ADMIT THEIR COMMUNITY OF DESCENT:  TO TAKE ANY OTHER VIEW, IS TO ADMIT THAT OUR OWN STRUCTURE, AND THAT OF ALL THE ANIMALS AROUND US, IS A MERE SNARE LAID TO ENTRAP OUR JUDGMENT.""")
		#14
		transclude(LongBibleOrigins,"""Bibles are the products of centuries of theological and political struggle.""",NelsonIntro,"""BIBLES ARE THE PRODUCTS OF CENTURIES OF THEOLOGICAL AND POLITICAL STRUGGLE.""")
		#15
		transclude(KJamesCreation,"""01:001:001 In the beginning God created the heaven and the earth.

01:001:002 And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.

01:001:003 And God said, Let there be light: and there was light.""", NelsonIntro, """01:001:001 IN THE BEGINNING GOD CREATED THE HEAVEN AND THE EARTH.
    
    01:001:002 AND THE EARTH WAS WITHOUT FORM, AND VOID; AND DARKNESS WAS UPON THE FACE OF THE DEEP. AND THE SPIRIT OF GOD MOVED UPON THE FACE OF THE WATERS.
    
    01:001:003 AND GOD SAID, LET THERE BE LIGHT: AND THERE WAS LIGHT.""")
		#16
		transclude(BenSiraLilith,"""Adam and Lilith immediately began to fight. She said, 'I will not lie below,' and he said, 'I will not lie beneath you, but only on top. For you are fit only to be in the bottom position, while I am to be the superior one.' Lilith responded, 'We are equal to each other inasmuch as we were both created from the earth.""",NelsonIntro,"""ADAM AND LILITH IMMEDIATELY BEGAN TO FIGHT. SHE SAID, 'I WILL NOT LIE BELOW,' AND HE SAID, 'I WILL NOT LIE BENEATH YOU, BUT ONLY ON TOP. FOR YOU ARE FIT ONLY TO BE IN THE BOTTOM POSITION, WHILE I AM TO BE THE SUPERIOR ONE.' LILITH RESPONDED, 'WE ARE EQUAL TO EACH OTHER INASMUCH AS WE WERE BOTH CREATED FROM THE EARTH.'""")
		#17
		transclude(WpediaSteadyState,"""chaotic inflation theory or eternal inflation which sometimes posits an infinite universe with neither beginning nor end in which inflation operates continuously, on a scale beyond the observable universe, to create the matter of the cosmos.""",NelsonIntro,"""CHAOTIC INFLATION THEORY OR ETERNAL INFLATION WHICH SOMETIMES POSITS AN INFINITE UNIVERSE WITH NEITHER BEGINNING NOR END IN WHICH INFLATION OPERATES CONTINUOUSLY, ON A SCALE BEYOND THE OBSERVABLE UNIVERSE, TO CREATE THE MATTER OF THE COSMOS.""")		
		#18
		transclude(SchoolsBigBang,"""as he was also an abbot of the Roman Catholic church argued that God had created 'a primeval atom' which had grown to become the Universe.""",NelsonIntro,"""AS HE WAS ALSO AN ABBOT OF THE ROMAN CATHOLIC CHURCH ARGUED THAT GOD HAD CREATED 'A PRIMEVAL ATOM' WHICH HAD GROWN TO BECOME THE UNIVERSE.""")
		#19
		transclude(SchoolsSteadyState,"""Hoyle approached the problem mathematically and tried to solve the problem of the creation of the matter seen all around us, which in the Big Bang theory is all created at the start. He proposed that the decrease in the density of the universe caused by its expansion is exactly balanced by the continuous creation of matter condensing into galaxies that take the place of the galaxies that have receded from the Milky Way, thereby maintaining forever the present appearance of the universe.""",NelsonIntro,"""HOYLE APPROACHED THE PROBLEM MATHEMATICALLY AND TRIED TO SOLVE THE PROBLEM OF THE CREATION OF THE MATTER SEEN ALL AROUND US, WHICH IN THE BIG BANG THEORY IS ALL CREATED AT THE START. HE PROPOSED THAT THE DECREASE IN THE DENSITY OF THE UNIVERSE CAUSED BY ITS EXPANSION IS EXACTLY BALANCED BY THE CONTINUOUS CREATION OF MATTER CONDENSING INTO GALAXIES THAT TAKE THE PLACE OF THE GALAXIES THAT HAVE RECEDED FROM THE MILKY WAY, THEREBY MAINTAINING FOREVER THE PRESENT APPEARANCE OF THE UNIVERSE.""")



		#add all clinks
		#2
		clink("clash",KJamesCreation,"""01:002:021 And the LORD God caused a deep sleep to fall upon Adam, and he slept: and he took one of his ribs, and closed up the flesh instead thereof;

01:002:022 And the rib, which the LORD God had taken from man, made he a woman, and brought her unto the man.

01:002:023 And Adam said, This is now bone of my bones, and flesh of my flesh: she shall be called Woman, because she was taken out of Man.""",BenSiraLilith,"""After God created Adam, who was alone, He said, 'It is not good for man to be alone'. He then created a woman for Adam, from the earth, as He had created Adam himself, and called her Lilith.""")
		#3
		clink("correspondence",GilgamishFlood,'''23. O man of Shurippak, son of Ubara-Tutu ().

24. Throw down the house, build a ship,

25. Forsake wealth, seek after life,

26. Abandon possessions, save thy life,

27. Carry grain of every kind into the ship.

28. The ship which thou shalt build,

29. The dimensions thereof shall be measured,

30. The breadth and the length thereof shall be the same.

31. ... the ocean, provide it with a roof."''', KJamesFlood, """01:006:013 And God said unto Noah, The end of all flesh is come before me; for the earth is filled with violence through them; and, behold, I will destroy them with the earth.

01:006:014 Make thee an ark of gopher wood; rooms shalt thou make in the ark, and shalt pitch it within and without with pitch.

01:006:015 And this is the fashion which thou shalt make it of: The length of the ark shall be three hundred cubits, the breadth of it fifty cubits, and the height of it thirty cubits.

01:006:016 A window shalt thou make to the ark, and in a cubit shalt thou finish it above; and the door of the ark shalt thou set in the side thereof; with lower, second, and third stories shalt thou make it.""")
		#4
		clink("correspondence",GilgamishFlood,'''81. With everything that I possessed I loaded it (i.e. the ship).

82. With everything that I possessed of silver I loaded it.

83. With everything that I possessed of gold I loaded it.

84. With all that I possessed of living grain I loaded it.

85. I made to go up into the ship all my family and kinsfolk, page 35

86. The cattle of the field, the beasts of the field, all handicraftsmen I made them go up into it.

87. The god Shamash had appointed me a time (saying)

88. The Power of Darkness will at eventide make a rain-flood to fall;

89. Then enter into the ship and shut thy door.''',KJamesFlood,'''01:007:006 And Noah was six hundred years old when the flood of waters was upon the earth.

01:007:007 And Noah went in, and his sons, and his wife, and his sons' wives with him, into the ark, because of the waters of the flood.

01:007:008 Of clean beasts, and of beasts that are not clean, and of fowls, and of every thing that creepeth upon the earth,

01:007:009 There went in two and two unto Noah into the ark, the male and the female, as God had commanded Noah.

01:007:010 And it came to pass after seven days, that the waters of the flood were upon the earth.''')
		#5
		clink("correspondence",GilgamishFlood,'''146. When the seventh day had come

147. I brought out a dove and let her go free.

148. The dove flew away and [then] came back;

149. Because she had no place to alight on she came back.

150. I brought out a swallow and let her go free.

151. The swallow flew away and [then] came back;

152. Because she had no place to alight on she came back.

153. I brought out a raven and let her go free.

154. The raven flew away, she saw the sinking waters.

155. She ate, she pecked in the ground, she croaked, she came not back.''',KJamesFlood,'''01:008:006 And it came to pass at the end of forty days, that Noah opened the window of the ark which he had made:

01:008:007 And he sent forth a raven, which went forth to and fro, until the waters were dried up from off the earth.

01:008:008 Also he sent forth a dove from him, to see if the waters were abated from off the face of the ground;

01:008:009 But the dove found no rest for the sole of her foot, and she returned unto him into the ark, for the waters were on the face of the whole earth: then he put forth his hand, and took her, and pulled her in unto him into the ark.

01:008:010 And he stayed yet other seven days; and again he sent forth the dove out of the ark;

01:008:011 And the dove came in to him in the evening; and, lo, in her mouth was an olive leaf pluckt off: so Noah knew that the waters were abated from off the earth.''')
		#6
		clink("clash",KJamesCreation,'''01:001:026 And God said, Let us make man in our image, after our likeness: and let them have dominion over the fish of the sea, and over the fowl of the air, and over the cattle, and over all the earth, and over every creeping thing that creepeth upon the earth.

01:001:027 So God created man in his own image, in the image of God created he him; male and female created he them.''',DarwinDescentCh1,'''we ought frankly to admit their community of descent:  to take any other view, is to admit that our own structure, and that of all the animals around us, is a mere snare laid to entrap our judgment.''')
		#7
		clink("pointer",WpediaSteadyState,'''the circular plot of the film Dead of Night they watched together''',DeadOfNightRev,'''But the horror's not over yet. Back at the cottage, Craig has remembered how his "nightmare of horror" ends, and it's something of a self-fulfilling prophecy. As he's besieged by visions from the stories he's just heard (including a fully mobile Hugo) he wakes up, only for the whole thing to start again...''')
		#20
		clink("pointer",NelsonIntro,'''The film "Dead of Night"''',DeadOfNightRev)
		#21
		clink("pointer",NelsonIntro,'''The Biblical account of the Flood (for instance, the King James version)''',KJamesFlood)
		#22
		clink("pointer",NelsonIntro,'''The Babylonian account of the Flood''', GilgamishFlood)
		#23
		clink("disagreement",NelsonIntro,'''few educated people accept the literal account of a Flood which covered the whole earth, with all the land species rescued in a boat''', KJamesFlood)
		#24
		clink("pointer",NelsonIntro,'''The notion of a God with particular interest in one species''',KJamesCreation)
		#25
		clink("disagreement",NelsonIntro,'''Few educated people accept the six-day, Adam-and-Eve account today.''',KJamesCreation)
		#26
		clink("resemblance",SchoolsSteadyState,'''An alternative theory to the Big Bang was proposed in 1948 by Hermann Bondi, Thomas Gold, and Sir Fred Hoyle It was called the steady-state theory.''',WpediaSteadyState,'''Chaotic inflation theory has many similarities with steady state theory, although on a much larger scale than originally envisaged.''')

		#stick notes
		#27
		#28

		"""
		#create several strands, with loaded in text
		mystrand1 = xu.createstrand(self.myedl)
		xu.insert(mystrand1,0,xu.append(self.myscroll,fw.load('texts\\Declaration of Independence.txt')))
		mystrand2 = xu.createstrand(self.myedl)
		xu.insert(mystrand2,0,xu.append(self.myscroll,fw.load('texts\\Virginia Bill of Rights.txt')))
		mystrand3 = xu.createstrand(self.myedl)
		xu.insert(mystrand3,0,xu.append(self.myscroll,fw.load('texts\\English Bill of Rights.txt')))
		mystrand4 = xu.createstrand(self.myedl)
		xu.insert(mystrand4,0,xu.append(self.myscroll,fw.load('texts\\Two Treatises of Government.txt')[:10000]))

		#create several clinks
		myclink1 = xu.createclink(self.myedl,'blue')
		xu.addfrom(myclink1,mystrand1+(535, 744-535))
		xu.addto(myclink1,mystrand2+(268, 617-268))
		myclink2 = xu.createclink(self.myedl,'blue')
		xu.addfrom(myclink2,mystrand2+(268, 617-268))
		xu.addto(myclink2,mystrand3+(9666, 9952-9666))
		myclink3 = xu.createclink(self.myedl,'blue')
		xu.addfrom(myclink3,mystrand3+(9666, 9952-9666))
		xu.addto(myclink3,mystrand4+(8923, 9504-8923))
		"""

		#create list of strands
		#strands = [mystrand1, mystrand2, mystrand3, mystrand4]
		#save the edl to disk
		#xu.saveedl(myedl)
		
		#chain up
		Applitude.__init__(self)

	def input(self):
		"""
		Respond to all translit keyboard and mouse commands.
		"""

		#if 1 seconds have elapsed since the last input, then add a marker to the edl (undo/redo point)
		if self.lasttime == 0 or fw.time()-self.lasttime > 2000:
			xu.mark(self.myedl);
		self.lasttime = fw.time()

		#get input details
		devicetype, device, inputtype, input, value, letter = fw.lastinput()
		shift = key('left shift') or key('right shift')
		ctrl = key('left ctrl') or key('right ctrl')

		if devicetype == 'keyboard' and value == 1 and input == 'tab':
			self.inputmode = not self.inputmode
			return

		#if in edit mode
		if self.inputmode == 1:

			#if keyboard input
			if devicetype == 'keyboard' and value == 1:

				#if 'ctrl+z', then undo current EDL
				if ctrl and input == 'z':
					#xu.undo(self.myedl)
					#fw.setsworphspeed(0)
					#fw.rebuild()
					
					myedl = self.myedl

					#undo action
					test = xu.undo(myedl)

					#if shift isn't held down, then keep undoing until a mark is found
					if not shift:
						test = xu.undo(myedl)
						while test and test[0] != 'mark':
							test = xu.undo(myedl);

					#update the scene
					fw.rebuild()
					return

				#if 'ctrl+y', then redo current edl
				elif ctrl and input == 'y':
					#xu.redo(self.myedl)
					#fw.setsworphspeed(0)
					#fw.rebuild()
					
					myedl = self.myedl

					#redo action
					test = xu.redo(myedl)

					#if shift isn't held down, then keep redoing until a mark is found
					if not shift:
						test = xu.redo(myedl)
						while test and test[0] != 'mark':
							test = xu.redo(myedl);

					#update the scene
					fw.rebuild()
					return

				#if 'ctrl+c', then copy select region to clipboard
				elif input == 'c' and ctrl:
					fw.setclipboard(xu.value(strandcursor))
					#fw.setsworphspeed(0)
					fw.rebuild()


				#if 'left' or 'right' cursor, then move text cursor
				elif input == 'left':
					if self.strandcursor and self.strandcursor[4]>0:
						self.strandcursor = self.strandcursor[:4]+(self.strandcursor[4]-1,)
						print self.strandcursor
						#fw.setsworphspeed(0)
						fw.rebuild()

				elif input == 'right':
					if self.strandcursor and self.strandcursor[4]<len(xu.value(self.strandcursor[:4])):
						self.strandcursor = strandcursor[:4]+(self.strandcursor[4]+1,)
						print self.strandcursor
						#fw.setsworphspeed(0)
						fw.rebuild()

				#if 'backspace' or 'delete' and a region is selected, then delete selection
				elif (input == 'backspace' or input == 'delete') and len(self.strandcursor) > 5 and self.strandcursor[5]:
					xu.remove(self.strandcursor[:4],self.strandcursor[4],self.strandcursor[4]+self.strandcursor[5])
					self.strandcursor = self.strandcursor[:5] + (0,)
					fw.setsworphspeed(0)
					fw.rebuild()


				#if 'backspace' or 'delete' then delete content
				elif input == 'backspace':
					if self.strandcursor and self.strandcursor[4]>0:
						xu.remove(self.strandcursor[:4],self.strandcursor[4]-1,self.strandcursor[4])
						self.strandcursor = self.strandcursor[:4]+(self.strandcursor[4]-1,)
						#fw.setsworphspeed(0)
						fw.rebuild()
				elif input == 'delete':
					if self.strandcursor and self.strandcursor[4]<len(xu.value(self.strandcursor[:4])):
						xu.remove(self.strandcursor[:4],self.strandcursor[4],self.strandcursor[4]+1)
						#fw.setsworphspeed(0)
						fw.rebuild()


				#otherwise insert content at strandcursor
				elif letter != '':
					if self.strandcursor:
						xu.createpermascroll(self.myscroll)
						xu.insert(self.strandcursor[:4],self.strandcursor[4],xu.append(self.myscroll,letter))
						self.strandcursor = self.strandcursor[:4]+(self.strandcursor[4]+1,)
						#fw.setsworphspeed(0)
						fw.rebuild()

				#update scene quickly
				#fw.setsworphspeed(0)
				#fw.rebuild()
				
		#if in normal mode
		else:
			
			#if keyboard input
			if devicetype == 'keyboard' and value == 1:
			
				#handle toglling the visibility of different transclusions and flinks
				if input == 'r':
					self.clinkcolours['transclusion'][0] = (1+self.clinkcolours['transclusion'][0])%2
					fw.rebuild()
					return
				elif input == 'o':
					self.clinkcolours['resemblance'][0] = (1+self.clinkcolours['resemblance'][0])%2
					fw.rebuild()
					return
				elif input == 'y':
					self.clinkcolours['sticky note'][0] = (1+self.clinkcolours['sticky note'][0])%2
					fw.rebuild()
					return
				elif input == 'g':
					self.clinkcolours['comment'][0] = (1+self.clinkcolours['comment'][0])%2
					fw.rebuild()
					return
				elif input == 'b':
					self.clinkcolours['connection'][0] = (1+self.clinkcolours['connection'][0])%2
					fw.rebuild()
					return
				elif input == 'k':
					self.clinkcolours['clash'][0] = (1+self.clinkcolours['clash'][0])%2
					fw.rebuild()
					return
				elif input == 'i':
					self.clinkcolours['pointer'][0] = (1+self.clinkcolours['pointer'][0])%2
					fw.rebuild()
					return
				elif input == 'p':
					self.clinkcolours['correspondence'][0] = (1+self.clinkcolours['correspondence'][0])%2
					self.clinkcolours['counterpart'][0] = (1+self.clinkcolours['counterpart'][0])%2
					fw.rebuild()
					return
					pass
				elif input == 'd':
					self.clinkcolours['disagreement'][0] = (1+self.clinkcolours['disagreement'][0])%2
					fw.rebuild()
					return
				elif input == 'a':
					set = self.clinkcolours['transclusion'][0]
					if set == 0:set = 1
					else: set = 0
					for name,val in self.clinkcolours.iteritems():
						self.clinkcolours[name][0] = set
					fw.rebuild()
					return


		#if a mouse button is pressed or released
		if devicetype == 'mouse' and inputtype == 'button' and input == 0 and value == 1:

			#do a hittest for the mouse cursor position
			coord, cell, index = fw.hittest()

			#get the represented strand
			rept = zz.clonehead(zz.next(cell,'d.representstype'))
			if rept:

				#try and unpickle it
				testout = None
				try:
					testout = cPickle.loads(zz.value(rept))
				except:
					pass

				#if it unpickled
				if testout:

					#if left mouse button down, then set as current strand cursor start and end position
					if value == 1 and input == 0:
						self.strandcursor = testout[:4] + (testout[4]+index,0)
						fw.setselect(zz.value(rept),index)
						#fw.setfocus(rept,index)

					#if left mouse button up
					if value == 0 and input == 0:

						#if it's the same strand, then change the end value
						if self.strandcursor and self.strandcursor[:4] == testout[:4]:
							self.strandcursor = self.strandcursor[:5] + (testout[4]+index-self.strandcursor[4],)
							fw.setselectend(zz.value(rept),index)
							if(self.strandcursor[5]<0):
								self.strandcursor = self.strandcursor[:4] + (self.strandcursor[4]+self.strandcursor[5], -self.strandcursor[5])

						#otherwise, set as current strand cursor start and end position
						else:
							self.strandcursor = self.strandcursor[:4] + (testout[4]+index,0)
							fw.setselect(zz.value(rept),index)

					#if middle button down, then selection at this position
					if value == 1 and input == 1 and self.strandcursor:
						xu.insert(testout, testout[4]+index, self.strandcursor)
						fw.setsworphspeed(0)
						fw.rebuild()
						
		#chain up
		Applitude.input(self)


	def MakeSlab(self, mystrand, things):

		#create slab vunit, white, fixed width, and represents the strand
		myslice = ('','','Test Slice')
		slab = zz.createcell(myslice, 'slab')
		zz.insert(slab, 'd.color', 1, 1, 1)
		zz.insert(slab, 'd.representstype', str(mystrand))
		zz.insert(slab, 'd.size', 30, 0, 1)
		zz.insert(slab, 'd.translate', 10)


		#add a first tetroid
		nexttetroid = zz.insert(slab, 'd.flowposition', 'tetroid')

		#print '\nTEST: ', xu.value(mystrand), '\n'

		#for each chunk in turn
		#print xu.strandchunks(mystrand)
		for strandchunk in xu.strandchunks(mystrand):

			#print xu.chunk(strandchunk)
			chunk = xu.chunk(strandchunk)



			#create and add tetroid
			nexttetroid = zz.insert(nexttetroid, 'd.2', 'tetroid')
			zz.insert(nexttetroid, 'd.text', xu.value(strandchunk))
			#zz.insert(nexttetroid, 'd.representstype', str(strandchunk))
			zz.insert(nexttetroid, 'd.representstype', cPickle.dumps(strandchunk))
			zz.insert(nexttetroid, 'd.color',0,0,0,0)
			#print str(strandchunk)

			#zz.insert(nexttetroid, 'd.represents', zz.createclone(cursors[0],myslice))
			#print strandchunk

			#get the number of bold and italic clinks
			bold = len(xu.fromclinks(chunk,'bold'))
			italic = len(xu.fromclinks(chunk,'italic'))

			#if bold then set color to red
			if bold: zz.insert(nexttetroid, 'd.color', 1, 0.95, 0.95, 1)

			#if italic then set text color to green
			if italic: zz.insert(nexttetroid, 'd.fontcolor', 0, 1, 0, 1)

			#if selected then set text color to blue
			if chunk in self.selectionchunks: zz.insert(nexttetroid, 'd.fontcolor', 0.9, 0, 0, 1)

			if not chunk in things:
				things[chunk] = []
			#print len(things[chunk])
			things[chunk].append(nexttetroid)
			#print len(things[chunk])



		#print xu.strandchunks(mystrand)

		return slab


	def build(self):
		
		starttime = fw.time()
		
		#fw.updatescene(zz.createcell(('','','tempslice'),'spheroid'))
		
		
		

		#create list for chunk information
		things = dict()

		#create slice for scene
		myslice = ('','','Test Slice')
		zz.destroyslice(myslice)
		zz.createslice(myslice)
		scene = zz.createcell(myslice)

		#create styles
		slabstyle = zz.createcell(myslice,'slab') 
		zz.insert(slabstyle, dparentcenter, 1, 0, 0)
		zz.insert(slabstyle, dcenter, 0, 0, 0)
		zz.insert(slabstyle, dparentrotate, 0, -1)
		zz.insert(slabstyle, drotate, 0, -1)

		lefttopstyle = zz.createcell(myslice,'point')
		zz.insert(lefttopstyle, dparentcenter, 1, 0)
		zz.insert(lefttopstyle, dtranslate, 0, 0, 0.2)
		
		leftbottomstyle = zz.createcell(myslice,'point')
		zz.insert(leftbottomstyle, dparentcenter, 1, 1)
		zz.insert(leftbottomstyle, dtranslate, 0, 0, 0.2)

		righttopstyle = zz.createcell(myslice,'point')
		zz.insert(righttopstyle, dparentcenter, 0, 0)
		zz.insert(righttopstyle, dtranslate, 0, 0, 0.2)
		
		rightbottomstyle = zz.createcell(myslice,'point')				
		zz.insert(rightbottomstyle, dparentcenter, 0, 1)
		zz.insert(rightbottomstyle, dtranslate, 0, 0, 0.2)
		
		#get edl
		myedl = ('','','Test EDL')

		#for each strand in the edl
		prev = None
		index = 0
		for strand in xu.strands(myedl):

			#make a slab for the strand
			slab = self.MakeSlab(strand, things)
			thisindex = index
			index = index+1
			
			#position it relatively to the previous strand (if any)...
			if prev:
				zz.insert(prev,drelativeposition,slab)
			else:
				zz.insert(scene,d2,slab)

			#...so that the strands curve
			zz.insert(slab, dmastershape, zz.createclone(slabstyle))
			prev = slab

			"""
			#position camera if in-front of slab3
			camera = zz.insert(slab,'d.relativeposition','camera')
			zz.insert(camera,'d.parentcenter',0.5,0.5,0)
			zz.insert(camera,'d.translate',0,0,20)
			"""


		#for each chunk (of all those displayed)
		for chunk, list in things.iteritems():

			if not zz.next(list[0],drelativeposition):
				zz.insert(list[0],drelativeposition)
			left = zz.next(list[0],drelativeposition)

			lefttop = zz.insert(left, d2)
			leftbottom = zz.insert(lefttop, d2)
			zz.insert(lefttop, dmastershape, zz.createclone(lefttopstyle))
			zz.insert(leftbottom, dmastershape, zz.createclone(leftbottomstyle))

			#display clinks
			for clink in xu.fromclinks(chunk):
				
				#if the clink type is disabled, then ignore it
				color = self.clinkcolours[xu.type(clink)]
				if color:
					if color[0]==1:
						print 'cancelling1!!!!'
						continue
				else:
					print 'error!!!'
				
				for next in xu.tochunks(clink):
					if next == chunk: continue
					if next not in things: continue

					nextlist = things[next]

					if not zz.next(nextlist[0],drelativeposition):
						zz.insert(nextlist[0],drelativeposition)
					right = zz.next(nextlist[0],drelativeposition)

					righttop = zz.insert(right, d2)
					rightbottom = zz.insert(righttop, d2)
					zz.insert(righttop, dmastershape, zz.createclone(righttopstyle))
					zz.insert(rightbottom, dmastershape, zz.createclone(rightbottomstyle))

					poly = zz.insert(scene, d2, 'trianglestrip')
					zz.insert(poly, dpoints, zz.createclone(lefttop), zz.createclone(leftbottom), zz.createclone(righttop), zz.createclone(rightbottom))

					zz.insert(poly, drepresentstype, str(next)+str(clink)+'clink')


			
					#if there is a corresponding colour for the clink type
					color = self.clinkcolours[xu.type(clink)]
					if color:
						color = color[1]
					
					if color:
						zz.insert(poly, dcolor, color[0], color[1], color[2], 0.2)

					#zz.insert(list[0], 'd.color', 0, 0, 1, 0.2)
					zz.insert(list[0], dcolor, color[0], color[1], color[2], 0.2)

					#zz.insert(nextlist[0], 'd.color', 0, 0, 1, 0.2)
					zz.insert(nextlist[0], dcolor, color[0], color[1], color[2], 0.2)

			#display transclusions
			if self.clinkcolours['transclusion'][0]==0:
				while len(list) > 1:
	
	
					zz.insert(list[0],dcolor,1,0,0,0.2)
					zz.insert(list[1],dcolor,1,0,0,0.2)
	
					#daisy chain them together
					if not zz.next(list[0],drelativeposition):
						zz.insert(list[0],drelativeposition)
					left = zz.next(list[0],drelativeposition)
	
					lefttop = zz.insert(left, d2)
					leftbottom = zz.insert(lefttop, d2)
					zz.insert(lefttop, dmastershape, zz.createclone(lefttopstyle))
					zz.insert(leftbottom, dmastershape, zz.createclone(leftbottomstyle))
	
					if not zz.next(list[1],drelativeposition):
						zz.insert(list[1],drelativeposition)
					right = zz.next(list[1],drelativeposition)
	
					righttop = zz.insert(right, d2)
					rightbottom = zz.insert(righttop, d2)
					zz.insert(righttop, dmastershape, zz.createclone(righttopstyle))
					zz.insert(rightbottom, dmastershape, zz.createclone(rightbottomstyle))

	
					poly = zz.insert(scene, d2, 'trianglestrip')
					zz.insert(poly, dpoints, lefttop, leftbottom, righttop, rightbottom)
					zz.insert(poly, dcolor, 1, 0, 0, 0.2)
					zz.insert(poly, drepresentstype, str(list[0])+'transclusion')
	
					list = list[1:]


		print myslice, scene, len(scene), scene[0], scene[1], scene[2], scene[3]
		
		fw.updatescene(scene)

		print 'update time',fw.time()-starttime
		
		
		
class TranslitApplitude2(Applitude):
	"""
	Generic translit applitude, that responds to input, and builds appropriate scene.
	"""
	
	#reference to a strand, and an index into the strand
	strandcursor = None
	strandcursorindex = 0
	myedl = ('','','Test EDL')
	myscroll = ('','','Test Permascroll')
	slabstate = [0,0,0,0]
	testcount = 0
	lineup = 0
	selectionchunks = []
	inputmode = 0
	lasttime = 0
	clinkcolours = {}

	currentchunk = None
	currentstrand = None

	#slabstate[testcount]

	def __init__(self):
		
		#set the input mode
		self.mode = 3
		
		#set clink colours
		self.clinkcolours['transclusion'] = [0,(1,0,0,0.2)]
		self.clinkcolours['resemblance'] = [0,(1,1,0,0.2)]
		self.clinkcolours['sticky note'] = [0,(1,0.64,0,0.2)]
		self.clinkcolours['comment'] = [0,(0,1,0,0.2)]
		self.clinkcolours['connection'] = [0,(0.7,0.7,1,0.2)]		
		self.clinkcolours['clash'] = [0,(0,0,1,0.2)]
		self.clinkcolours['pointer'] = [0,(0.29,0,0.51,0.2)]
		self.clinkcolours['correspondence'] = [0,(0.62,0.13,0.93,0.2)]
		self.clinkcolours['counterpart'] = [0,(0.62,0.13,0.93,0.2)]
		self.clinkcolours['disagreement'] = [0,(0.5,0.5,0.5,0.2)]
		
		#create an edl and permascroll
		xu.destroyedl(self.myedl)
		xu.createedl(self.myedl)
		xu.destroypermascroll(self.myscroll)
		xu.createpermascroll(self.myscroll)


		

		"""
		NelsonIntro.txt
		
		BenSiraLilith-cut.txt
		DarwinDescentCh1-cut.txt
		DeadOfNightRev-cut.txt
		GilgamishFlood-cut.txt
		K.JamesCreation-cut.txt
		K.JamesFlood-cut.txt
		LongBibleOrigins-cut.txt
		SchoolsBigBang-cut-FIX2.txt
		SchoolsSteadyState-cut.txt
		WpediaSteadyState-cut.txt
		"""

		#load in all demo texts (11)
		NelsonIntro = xu.createstrand(self.myedl)
		xu.insert(NelsonIntro,0,xu.append(self.myscroll,fw.load('texts\\demo\\NelsonIntro.txt')))
		BenSiraLilith = xu.createstrand(self.myedl)
		xu.insert(BenSiraLilith,0,xu.append(self.myscroll,fw.load('texts\\demo\\BenSiraLilith-cut.txt')))
		DarwinDescentCh1 = xu.createstrand(self.myedl)
		xu.insert(DarwinDescentCh1,0,xu.append(self.myscroll,fw.load('texts\\demo\\DarwinDescentCh1-cut.txt')))
		DeadOfNightRev = xu.createstrand(self.myedl)
		xu.insert(DeadOfNightRev,0,xu.append(self.myscroll,fw.load('texts\\demo\\DeadOfNightRev-cut.txt')))
		GilgamishFlood = xu.createstrand(self.myedl)
		xu.insert(GilgamishFlood,0,xu.append(self.myscroll,fw.load('texts\\demo\\GilgamishFlood-cut.txt')))
		KJamesCreation = xu.createstrand(self.myedl)
		xu.insert(KJamesCreation,0,xu.append(self.myscroll,fw.load('texts\\demo\\K.JamesCreation-cut.txt')))
		KJamesFlood = xu.createstrand(self.myedl)
		xu.insert(KJamesFlood,0,xu.append(self.myscroll,fw.load('texts\\demo\\K.JamesFlood-cut.txt')))
		LongBibleOrigins = xu.createstrand(self.myedl)
		xu.insert(LongBibleOrigins,0,xu.append(self.myscroll,fw.load('texts\\demo\\LongBibleOrigins-cut.txt')))
		SchoolsBigBang = xu.createstrand(self.myedl)
		xu.insert(SchoolsBigBang,0,xu.append(self.myscroll,fw.load('texts\\demo\\SchoolsBigBang-cut-FIX2.txt')))
		SchoolsSteadyState = xu.createstrand(self.myedl)
		xu.insert(SchoolsSteadyState,0,xu.append(self.myscroll,fw.load('texts\\demo\\SchoolsSteadyState-cut.txt')))
		WpediaSteadyState = xu.createstrand(self.myedl)
		xu.insert(WpediaSteadyState,0,xu.append(self.myscroll,fw.load('texts\\demo\\WpediaSteadyState-cut.txt')))

		#add all transclusions (13)
		#1
		transclude(BenSiraLilith,"""It is not good for man to be alone""", KJamesCreation, """It is not good that the man should be alone""")
		#8
		transclude(SchoolsBigBang,"""Fred Hoyle was unhappy about accepting a God given creation, and as an atheist attempted to develop a theory without such an intervention. This was to become the steady state theory.""",NelsonIntro,"""FRED HOYLE WAS UNHAPPY ABOUT ACCEPTING A GOD GIVEN CREATION, AND AS AN ATHEIST ATTEMPTED TO DEVELOP A THEORY WITHOUT SUCH AN INTERVENTION. THIS WAS TO BECOME THE STEADY STATE THEORY.""")
		#9
		transclude(WpediaSteadyState,"""The steady state theory of Bondi, Gold and Hoyle was inspired by the circular plot of the film Dead of Night they watched together""", NelsonIntro,"""THE STEADY STATE THEORY OF BONDI, GOLD AND HOYLE WAS INSPIRED BY THE CIRCULAR PLOT OF THE FILM DEAD OF NIGHT THEY WATCHED TOGETHER""")
		#10
		transclude(WpediaSteadyState,"""An aesthetically unattractive feature of the theory""" ,NelsonIntro, """AN AESTHETICALLY UNATTRACTIVE FEATURE OF THE THEORY""")
		#11
		transclude(WpediaSteadyState,"""alone among all cosmologies, the steady state model makes such definite predictions that it can be disproved even with the limited observational evidence at our disposal.""", NelsonIntro,"""ALONE AMONG ALL COSMOLOGIES, THE STEADY STATE MODEL MAKES SUCH DEFINITE PREDICTIONS THAT IT CAN BE DISPROVED EVEN WITH THE LIMITED OBSERVATIONAL EVIDENCE AT OUR DISPOSAL.""")
		#12
		transclude(WpediaSteadyState,"""Chaotic inflation theory has many similarities with steady state theory, although on a much larger scale than originally envisaged.""", NelsonIntro, """CHAOTIC INFLATION THEORY HAS MANY SIMILARITIES WITH STEADY STATE THEORY, ALTHOUGH ON A MUCH LARGER SCALE THAN ORIGINALLY ENVISAGED.""")
		#13
		transclude(DarwinDescentCh1,"""Thus we can understand how it has come to pass that man and all other vertebrate animals have been constructed on the same general model, why they pass through the same early stages of development, and why they retain certain rudiments in common.  Consequently we ought frankly to admit their community of descent:  to take any other view, is to admit that our own structure, and that of all the animals around us, is a mere snare laid to entrap our judgment.""", NelsonIntro,"""THUS WE CAN UNDERSTAND HOW IT HAS COME TO PASS THAT MAN AND ALL OTHER VERTEBRATE ANIMALS HAVE BEEN CONSTRUCTED ON THE SAME GENERAL MODEL, WHY THEY PASS THROUGH THE SAME EARLY STAGES OF DEVELOPMENT, AND WHY THEY RETAIN CERTAIN RUDIMENTS IN COMMON.  CONSEQUENTLY WE OUGHT FRANKLY TO ADMIT THEIR COMMUNITY OF DESCENT:  TO TAKE ANY OTHER VIEW, IS TO ADMIT THAT OUR OWN STRUCTURE, AND THAT OF ALL THE ANIMALS AROUND US, IS A MERE SNARE LAID TO ENTRAP OUR JUDGMENT.""")
		#14
		transclude(LongBibleOrigins,"""Bibles are the products of centuries of theological and political struggle.""",NelsonIntro,"""BIBLES ARE THE PRODUCTS OF CENTURIES OF THEOLOGICAL AND POLITICAL STRUGGLE.""")
		#15
		transclude(KJamesCreation,"""01:001:001 In the beginning God created the heaven and the earth.

01:001:002 And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.

01:001:003 And God said, Let there be light: and there was light.""", NelsonIntro, """01:001:001 IN THE BEGINNING GOD CREATED THE HEAVEN AND THE EARTH.
    
    01:001:002 AND THE EARTH WAS WITHOUT FORM, AND VOID; AND DARKNESS WAS UPON THE FACE OF THE DEEP. AND THE SPIRIT OF GOD MOVED UPON THE FACE OF THE WATERS.
    
    01:001:003 AND GOD SAID, LET THERE BE LIGHT: AND THERE WAS LIGHT.""")
		#16
		transclude(BenSiraLilith,"""Adam and Lilith immediately began to fight. She said, 'I will not lie below,' and he said, 'I will not lie beneath you, but only on top. For you are fit only to be in the bottom position, while I am to be the superior one.' Lilith responded, 'We are equal to each other inasmuch as we were both created from the earth.""",NelsonIntro,"""ADAM AND LILITH IMMEDIATELY BEGAN TO FIGHT. SHE SAID, 'I WILL NOT LIE BELOW,' AND HE SAID, 'I WILL NOT LIE BENEATH YOU, BUT ONLY ON TOP. FOR YOU ARE FIT ONLY TO BE IN THE BOTTOM POSITION, WHILE I AM TO BE THE SUPERIOR ONE.' LILITH RESPONDED, 'WE ARE EQUAL TO EACH OTHER INASMUCH AS WE WERE BOTH CREATED FROM THE EARTH.'""")
		#17
		transclude(WpediaSteadyState,"""chaotic inflation theory or eternal inflation which sometimes posits an infinite universe with neither beginning nor end in which inflation operates continuously, on a scale beyond the observable universe, to create the matter of the cosmos.""",NelsonIntro,"""CHAOTIC INFLATION THEORY OR ETERNAL INFLATION WHICH SOMETIMES POSITS AN INFINITE UNIVERSE WITH NEITHER BEGINNING NOR END IN WHICH INFLATION OPERATES CONTINUOUSLY, ON A SCALE BEYOND THE OBSERVABLE UNIVERSE, TO CREATE THE MATTER OF THE COSMOS.""")		
		#18
		transclude(SchoolsBigBang,"""as he was also an abbot of the Roman Catholic church argued that God had created 'a primeval atom' which had grown to become the Universe.""",NelsonIntro,"""AS HE WAS ALSO AN ABBOT OF THE ROMAN CATHOLIC CHURCH ARGUED THAT GOD HAD CREATED 'A PRIMEVAL ATOM' WHICH HAD GROWN TO BECOME THE UNIVERSE.""")
		#19
		transclude(SchoolsSteadyState,"""Hoyle approached the problem mathematically and tried to solve the problem of the creation of the matter seen all around us, which in the Big Bang theory is all created at the start. He proposed that the decrease in the density of the universe caused by its expansion is exactly balanced by the continuous creation of matter condensing into galaxies that take the place of the galaxies that have receded from the Milky Way, thereby maintaining forever the present appearance of the universe.""",NelsonIntro,"""HOYLE APPROACHED THE PROBLEM MATHEMATICALLY AND TRIED TO SOLVE THE PROBLEM OF THE CREATION OF THE MATTER SEEN ALL AROUND US, WHICH IN THE BIG BANG THEORY IS ALL CREATED AT THE START. HE PROPOSED THAT THE DECREASE IN THE DENSITY OF THE UNIVERSE CAUSED BY ITS EXPANSION IS EXACTLY BALANCED BY THE CONTINUOUS CREATION OF MATTER CONDENSING INTO GALAXIES THAT TAKE THE PLACE OF THE GALAXIES THAT HAVE RECEDED FROM THE MILKY WAY, THEREBY MAINTAINING FOREVER THE PRESENT APPEARANCE OF THE UNIVERSE.""")



		#add all clinks
		#2
		clink("clash",KJamesCreation,"""01:002:021 And the LORD God caused a deep sleep to fall upon Adam, and he slept: and he took one of his ribs, and closed up the flesh instead thereof;

01:002:022 And the rib, which the LORD God had taken from man, made he a woman, and brought her unto the man.

01:002:023 And Adam said, This is now bone of my bones, and flesh of my flesh: she shall be called Woman, because she was taken out of Man.""",BenSiraLilith,"""After God created Adam, who was alone, He said, 'It is not good for man to be alone'. He then created a woman for Adam, from the earth, as He had created Adam himself, and called her Lilith.""")
		#3
		clink("correspondence",GilgamishFlood,'''23. O man of Shurippak, son of Ubara-Tutu ().

24. Throw down the house, build a ship,

25. Forsake wealth, seek after life,

26. Abandon possessions, save thy life,

27. Carry grain of every kind into the ship.

28. The ship which thou shalt build,

29. The dimensions thereof shall be measured,

30. The breadth and the length thereof shall be the same.

31. ... the ocean, provide it with a roof."''', KJamesFlood, """01:006:013 And God said unto Noah, The end of all flesh is come before me; for the earth is filled with violence through them; and, behold, I will destroy them with the earth.

01:006:014 Make thee an ark of gopher wood; rooms shalt thou make in the ark, and shalt pitch it within and without with pitch.

01:006:015 And this is the fashion which thou shalt make it of: The length of the ark shall be three hundred cubits, the breadth of it fifty cubits, and the height of it thirty cubits.

01:006:016 A window shalt thou make to the ark, and in a cubit shalt thou finish it above; and the door of the ark shalt thou set in the side thereof; with lower, second, and third stories shalt thou make it.""")
		#4
		clink("correspondence",GilgamishFlood,'''81. With everything that I possessed I loaded it (i.e. the ship).

82. With everything that I possessed of silver I loaded it.

83. With everything that I possessed of gold I loaded it.

84. With all that I possessed of living grain I loaded it.

85. I made to go up into the ship all my family and kinsfolk, page 35

86. The cattle of the field, the beasts of the field, all handicraftsmen I made them go up into it.

87. The god Shamash had appointed me a time (saying)

88. The Power of Darkness will at eventide make a rain-flood to fall;

89. Then enter into the ship and shut thy door.''',KJamesFlood,'''01:007:006 And Noah was six hundred years old when the flood of waters was upon the earth.

01:007:007 And Noah went in, and his sons, and his wife, and his sons' wives with him, into the ark, because of the waters of the flood.

01:007:008 Of clean beasts, and of beasts that are not clean, and of fowls, and of every thing that creepeth upon the earth,

01:007:009 There went in two and two unto Noah into the ark, the male and the female, as God had commanded Noah.

01:007:010 And it came to pass after seven days, that the waters of the flood were upon the earth.''')
		#5
		clink("correspondence",GilgamishFlood,'''146. When the seventh day had come

147. I brought out a dove and let her go free.

148. The dove flew away and [then] came back;

149. Because she had no place to alight on she came back.

150. I brought out a swallow and let her go free.

151. The swallow flew away and [then] came back;

152. Because she had no place to alight on she came back.

153. I brought out a raven and let her go free.

154. The raven flew away, she saw the sinking waters.

155. She ate, she pecked in the ground, she croaked, she came not back.''',KJamesFlood,'''01:008:006 And it came to pass at the end of forty days, that Noah opened the window of the ark which he had made:

01:008:007 And he sent forth a raven, which went forth to and fro, until the waters were dried up from off the earth.

01:008:008 Also he sent forth a dove from him, to see if the waters were abated from off the face of the ground;

01:008:009 But the dove found no rest for the sole of her foot, and she returned unto him into the ark, for the waters were on the face of the whole earth: then he put forth his hand, and took her, and pulled her in unto him into the ark.

01:008:010 And he stayed yet other seven days; and again he sent forth the dove out of the ark;

01:008:011 And the dove came in to him in the evening; and, lo, in her mouth was an olive leaf pluckt off: so Noah knew that the waters were abated from off the earth.''')
		#6
		clink("clash",KJamesCreation,'''01:001:026 And God said, Let us make man in our image, after our likeness: and let them have dominion over the fish of the sea, and over the fowl of the air, and over the cattle, and over all the earth, and over every creeping thing that creepeth upon the earth.

01:001:027 So God created man in his own image, in the image of God created he him; male and female created he them.''',DarwinDescentCh1,'''we ought frankly to admit their community of descent:  to take any other view, is to admit that our own structure, and that of all the animals around us, is a mere snare laid to entrap our judgment.''')
		#7
		clink("pointer",WpediaSteadyState,'''the circular plot of the film Dead of Night they watched together''',DeadOfNightRev,'''But the horror's not over yet. Back at the cottage, Craig has remembered how his "nightmare of horror" ends, and it's something of a self-fulfilling prophecy. As he's besieged by visions from the stories he's just heard (including a fully mobile Hugo) he wakes up, only for the whole thing to start again...''')
		#20
		clink("pointer",NelsonIntro,'''The film "Dead of Night"''',DeadOfNightRev)
		#21
		clink("pointer",NelsonIntro,'''The Biblical account of the Flood (for instance, the King James version)''',KJamesFlood)
		#22
		clink("pointer",NelsonIntro,'''The Babylonian account of the Flood''', GilgamishFlood)
		#23
		clink("disagreement",NelsonIntro,'''few educated people accept the literal account of a Flood which covered the whole earth, with all the land species rescued in a boat''', KJamesFlood)
		#24
		clink("pointer",NelsonIntro,'''The notion of a God with particular interest in one species''',KJamesCreation)
		#25
		clink("disagreement",NelsonIntro,'''Few educated people accept the six-day, Adam-and-Eve account today.''',KJamesCreation)
		#26
		clink("resemblance",SchoolsSteadyState,'''An alternative theory to the Big Bang was proposed in 1948 by Hermann Bondi, Thomas Gold, and Sir Fred Hoyle It was called the steady-state theory.''',WpediaSteadyState,'''Chaotic inflation theory has many similarities with steady state theory, although on a much larger scale than originally envisaged.''')

		#stick notes
		#27
		#28

		"""
		#create several strands, with loaded in text
		mystrand1 = xu.createstrand(self.myedl)
		xu.insert(mystrand1,0,xu.append(self.myscroll,fw.load('texts\\Declaration of Independence.txt')))
		mystrand2 = xu.createstrand(self.myedl)
		xu.insert(mystrand2,0,xu.append(self.myscroll,fw.load('texts\\Virginia Bill of Rights.txt')))
		mystrand3 = xu.createstrand(self.myedl)
		xu.insert(mystrand3,0,xu.append(self.myscroll,fw.load('texts\\English Bill of Rights.txt')))
		mystrand4 = xu.createstrand(self.myedl)
		xu.insert(mystrand4,0,xu.append(self.myscroll,fw.load('texts\\Two Treatises of Government.txt')[:10000]))

		#create several clinks
		myclink1 = xu.createclink(self.myedl,'blue')
		xu.addfrom(myclink1,mystrand1+(535, 744-535))
		xu.addto(myclink1,mystrand2+(268, 617-268))
		myclink2 = xu.createclink(self.myedl,'blue')
		xu.addfrom(myclink2,mystrand2+(268, 617-268))
		xu.addto(myclink2,mystrand3+(9666, 9952-9666))
		myclink3 = xu.createclink(self.myedl,'blue')
		xu.addfrom(myclink3,mystrand3+(9666, 9952-9666))
		xu.addto(myclink3,mystrand4+(8923, 9504-8923))
		"""

		#create list of strands
		#strands = [mystrand1, mystrand2, mystrand3, mystrand4]
		#save the edl to disk
		#xu.saveedl(myedl)
	
	
		#set the current chunk as the first one in nelson intro	
		self.currentchunk = xu.chunks(NelsonIntro)[1]
		print self.currentchunk
		self.currentstrand = NelsonIntro

		#chain up
		Applitude.__init__(self)

	"""
	Convenience functions for getting relative chunks
	"""
	def prevchunk(self,thisstrand,thischunk):
		prevchunk = None
		for chunk in xu.chunks(thisstrand):
			if chunk == thischunk:
				return thisstrand,prevchunk
			prevchunk = chunk
		return None,None
	
	def nextchunk(self,thisstrand,thischunk):
		getnext = False
		for chunk in xu.chunks(thisstrand):
			if chunk == thischunk:
				getnext = True
			elif getnext:
				return thisstrand,chunk
		return None,None		
	
	def prevstrand(self,thisstrand,thischunk):
		
		prevstrand = None			
		for strandchunk in xu.strandchunks(thischunk):
			if xu.strand(strandchunk) == thisstrand:
				break
			prevstrand = xu.strand(strandchunk)
		if prevstrand:
			return prevstrand,thischunk			
		
		for clink in xu.toclinks(thischunk):
			for chunk in xu.fromchunks(clink):
				for strandchunk in xu.strandchunks(chunk):
					nextstrand = xu.strand(strandchunk)
					if not nextstrand == thisstrand:			
						return nextstrand,chunk
		
		return None,None	
	
		
	def nextstrand(self,thisstrand,thischunk):
		nextstrand = None
		getnext = False
		for strandchunk in xu.strandchunks(thischunk):
			if xu.strand(strandchunk) == thisstrand:
				getnext = True
			elif getnext:
				nextstrand = xu.strand(strandchunk)
				break
		if nextstrand:
			return nextstrand,thischunk
		
		for clink in xu.fromclinks(thischunk):
			for chunk in xu.tochunks(clink):
				for strandchunk in xu.strandchunks(chunk):					
					nextstrand = xu.strand(strandchunk)
					if not nextstrand == thisstrand:
						return nextstrand,chunk
		
		return None,None

	def interesting(self,thisstrand,thischunk):
		if len(xu.fromclinks(thischunk)):
			return True
		if len(xu.toclinks(thischunk)):
			return True
		if len(xu.strandchunks(thischunk))>1:
			return True
		return False

	def input(self):
		"""
		Respond to all translit keyboard and mouse commands.
		"""

		#if 1 seconds have elapsed since the last input, then add a marker to the edl (undo/redo point)
		if self.lasttime == 0 or fw.time()-self.lasttime > 2000:
			xu.mark(self.myedl);
		self.lasttime = fw.time()

		#get input details
		devicetype, device, inputtype, input, value, letter = fw.lastinput()
		shift = key('left shift') or key('right shift')
		ctrl = key('left ctrl') or key('right ctrl')

		if devicetype == 'keyboard' and value == 1 and input == 'tab':
			self.inputmode = not self.inputmode
			return

		#if in edit mode
		if self.inputmode == 1:

			#if keyboard input
			if devicetype == 'keyboard' and value == 1:

				#if 'ctrl+z', then undo current EDL
				if ctrl and input == 'z':
					#xu.undo(self.myedl)
					#fw.setsworphspeed(0)
					#fw.rebuild()
					
					myedl = self.myedl

					#undo action
					test = xu.undo(myedl)

					#if shift isn't held down, then keep undoing until a mark is found
					if not shift:
						test = xu.undo(myedl)
						while test and test[0] != 'mark':
							test = xu.undo(myedl);

					#update the scene
					fw.rebuild()
					return

				#if 'ctrl+y', then redo current edl
				elif ctrl and input == 'y':
					#xu.redo(self.myedl)
					#fw.setsworphspeed(0)
					#fw.rebuild()
					
					myedl = self.myedl

					#redo action
					test = xu.redo(myedl)

					#if shift isn't held down, then keep redoing until a mark is found
					if not shift:
						test = xu.redo(myedl)
						while test and test[0] != 'mark':
							test = xu.redo(myedl);

					#update the scene
					fw.rebuild()
					return

				#if 'ctrl+c', then copy select region to clipboard
				elif input == 'c' and ctrl:
					fw.setclipboard(xu.value(strandcursor))
					#fw.setsworphspeed(0)
					fw.rebuild()


				#if 'left' or 'right' cursor, then move text cursor
				elif input == 'left':
					if self.strandcursor and self.strandcursor[4]>0:
						self.strandcursor = self.strandcursor[:4]+(self.strandcursor[4]-1,)
						print self.strandcursor
						#fw.setsworphspeed(0)
						fw.rebuild()

				elif input == 'right':
					if self.strandcursor and self.strandcursor[4]<len(xu.value(self.strandcursor[:4])):
						self.strandcursor = strandcursor[:4]+(self.strandcursor[4]+1,)
						print self.strandcursor
						#fw.setsworphspeed(0)
						fw.rebuild()

				#if 'backspace' or 'delete' and a region is selected, then delete selection
				elif (input == 'backspace' or input == 'delete') and len(self.strandcursor) > 5 and self.strandcursor[5]:
					xu.remove(self.strandcursor[:4],self.strandcursor[4],self.strandcursor[4]+self.strandcursor[5])
					self.strandcursor = self.strandcursor[:5] + (0,)
					fw.setsworphspeed(0)
					fw.rebuild()


				#if 'backspace' or 'delete' then delete content
				elif input == 'backspace':
					if self.strandcursor and self.strandcursor[4]>0:
						xu.remove(self.strandcursor[:4],self.strandcursor[4]-1,self.strandcursor[4])
						self.strandcursor = self.strandcursor[:4]+(self.strandcursor[4]-1,)
						#fw.setsworphspeed(0)
						fw.rebuild()
				elif input == 'delete':
					if self.strandcursor and self.strandcursor[4]<len(xu.value(self.strandcursor[:4])):
						xu.remove(self.strandcursor[:4],self.strandcursor[4],self.strandcursor[4]+1)
						#fw.setsworphspeed(0)
						fw.rebuild()


				#otherwise insert content at strandcursor
				elif letter != '':
					if self.strandcursor:
						xu.createpermascroll(self.myscroll)
						xu.insert(self.strandcursor[:4],self.strandcursor[4],xu.append(self.myscroll,letter))
						self.strandcursor = self.strandcursor[:4]+(self.strandcursor[4]+1,)
						#fw.setsworphspeed(0)
						fw.rebuild()

				#update scene quickly
				#fw.setsworphspeed(0)
				#fw.rebuild()
				
		#if in normal mode
		else:
			
			#if keyboard input
			if devicetype == 'keyboard' and value == 1:
			
				#handle toglling the visibility of different transclusions and flinks
				if input == 'r':
					self.clinkcolours['transclusion'][0] = (1+self.clinkcolours['transclusion'][0])%2
					fw.rebuild()
					return
				elif input == 'o':
					self.clinkcolours['resemblance'][0] = (1+self.clinkcolours['resemblance'][0])%2
					fw.rebuild()
					return
				elif input == 'y':
					self.clinkcolours['sticky note'][0] = (1+self.clinkcolours['sticky note'][0])%2
					fw.rebuild()
					return
				elif input == 'g':
					self.clinkcolours['comment'][0] = (1+self.clinkcolours['comment'][0])%2
					fw.rebuild()
					return
				elif input == 'b':
					self.clinkcolours['connection'][0] = (1+self.clinkcolours['connection'][0])%2
					fw.rebuild()
					return
				elif input == 'k':
					self.clinkcolours['clash'][0] = (1+self.clinkcolours['clash'][0])%2
					fw.rebuild()
					return
				elif input == 'i':
					self.clinkcolours['pointer'][0] = (1+self.clinkcolours['pointer'][0])%2
					fw.rebuild()
					return
				elif input == 'p':
					self.clinkcolours['correspondence'][0] = (1+self.clinkcolours['correspondence'][0])%2
					self.clinkcolours['counterpart'][0] = (1+self.clinkcolours['counterpart'][0])%2
					fw.rebuild()
					return
					pass
				elif input == 'd':
					self.clinkcolours['disagreement'][0] = (1+self.clinkcolours['disagreement'][0])%2
					fw.rebuild()
					return
				elif input == 'a':
					set = self.clinkcolours['transclusion'][0]
					if set == 0:set = 1
					else: set = 0
					for name,val in self.clinkcolours.iteritems():
						self.clinkcolours[name][0] = set
					fw.rebuild()
					return
				elif input == 'e':

					prevstrand = None
					prevchunk = None
					
					prevstrand,prevchunk = self.prevchunk(self.currentstrand,self.currentchunk)
					
					while True:	
						if not prevchunk:
							break
						if self.interesting(prevstrand,prevchunk):
							break
						prevstrand,prevchunk = self.prevchunk(prevstrand,prevchunk)
					
					if prevchunk:
						self.currentstrand = prevstrand
						self.currentchunk = prevchunk
						fw.rebuild()
					
					return
				elif input == 'c':
					
					nextstrand = None
					nextchunk = None
					
					nextstrand,nextchunk = self.nextchunk(self.currentstrand,self.currentchunk)
					while True:
						if not nextchunk:
							break
						if self.interesting(nextstrand,nextchunk):
							break
						nextstrand,nextchunk = self.nextchunk(nextstrand,nextchunk)					
					
					if nextchunk:
						self.currentstrand = nextstrand
						self.currentchunk = nextchunk
						fw.rebuild()
						
					return
				
				elif input == 's':

					prevstrand,prevchunk = self.prevstrand(self.currentstrand,self.currentchunk)					
					if prevstrand:
						self.currentstrand = prevstrand
						self.currentchunk = prevchunk
						fw.rebuild()
					
					return
				
				elif input == 'f':
					
					nextstrand,nextchunk = self.nextstrand(self.currentstrand,self.currentchunk)
					if nextstrand:
						self.currentstrand = nextstrand
						self.currentchunk = nextchunk
						fw.rebuild()
						
					return
				
				elif input == '1':
					self.mode = 1
					fw.rebuild()
					return
				elif input == '2':
					self.mode = 2
					fw.rebuild()
					return
				elif input == '3':
					self.mode = 3
					fw.rebuild()
					return


		#if a mouse button is pressed or released
		if devicetype == 'mouse' and inputtype == 'button' and input == 0 and value == 1:

			#do a hittest for the mouse cursor position
			coord, cell, index = fw.hittest()

			#get the represented strand
			rept = zz.clonehead(zz.next(cell,'d.representstype'))
			if rept:

				#try and unpickle it
				testout = None
				try:
					testout = cPickle.loads(zz.value(rept))
				except:
					pass

				#if it unpickled
				if testout:

					#if left mouse button down, then set as current strand cursor start and end position
					if value == 1 and input == 0:
						self.strandcursor = testout[:4] + (testout[4]+index,0)
						fw.setselect(zz.value(rept),index)
						#fw.setfocus(rept,index)

					#if left mouse button up
					if value == 0 and input == 0:

						#if it's the same strand, then change the end value
						if self.strandcursor and self.strandcursor[:4] == testout[:4]:
							self.strandcursor = self.strandcursor[:5] + (testout[4]+index-self.strandcursor[4],)
							fw.setselectend(zz.value(rept),index)
							if(self.strandcursor[5]<0):
								self.strandcursor = self.strandcursor[:4] + (self.strandcursor[4]+self.strandcursor[5], -self.strandcursor[5])

						#otherwise, set as current strand cursor start and end position
						else:
							self.strandcursor = self.strandcursor[:4] + (testout[4]+index,0)
							fw.setselect(zz.value(rept),index)

					#if middle button down, then selection at this position
					if value == 1 and input == 1 and self.strandcursor:
						xu.insert(testout, testout[4]+index, self.strandcursor)
						fw.setsworphspeed(0)
						fw.rebuild()
						
		#chain up
		Applitude.input(self)


	def MakeSlab(self, mystrand, things, centrechunk, scale):
		
		centretetroid = None
		
		#create slab vunit, white, fixed width, and represents the strand
		myslice = ('','','Test Slice')
		slab = zz.createcell(myslice, 'slab')
		zz.insert(slab, 'd.color', 1, 1, 1)
		zz.insert(slab, 'd.representstype', str(mystrand))
		zz.insert(slab, 'd.size', 30*scale, 0, 1)
		zz.insert(slab, 'd.translate', 10)


		#add a first tetroid
		nexttetroid = zz.insert(slab, 'd.flowposition', 'tetroid')

		#for each chunk in turn
		for strandchunk in xu.strandchunks(mystrand):
			chunk = xu.chunk(strandchunk)

			#create and add tetroid, with text, fontsize, color, and id
			nexttetroid = zz.insert(nexttetroid, 'd.2', 'tetroid')
			zz.insert(nexttetroid, 'd.text', xu.value(strandchunk))
			zz.insert(nexttetroid, 'd.representstype', cPickle.dumps(strandchunk))
			zz.insert(nexttetroid, 'd.color',0,0,0,0)
			zz.insert(nexttetroid, dfontsize,1*scale,1*scale)

			"""
			#get the number of bold and italic clinks
			bold = len(xu.fromclinks(chunk,'bold'))
			italic = len(xu.fromclinks(chunk,'italic'))

			#if bold then set color to red
			if bold: zz.insert(nexttetroid, 'd.color', 1, 0.95, 0.95, 1)

			#if italic then set text color to green
			if italic: zz.insert(nexttetroid, 'd.fontcolor', 0, 1, 0, 1)

			#if selected then set text color to blue
			if chunk in self.selectionchunks: zz.insert(nexttetroid, 'd.fontcolor', 0.9, 0, 0, 1)
			"""
			
			#add chunk to lookup map
			if not chunk in things:
				things[chunk] = []
			things[chunk].append(nexttetroid)

			#if this is the chunk (tetroid) to centre about, then store
			if chunk == centrechunk:
				centretetroid = nexttetroid

		#runtime error if the chunk didn't exist in the strand
		if not centretetroid:
			print 'error!!!'

		return centretetroid


	def build(self):
		
		starttime = fw.time()
		
		#fw.updatescene(zz.createcell(('','','tempslice'),'spheroid'))
		
		
		

		#create list for chunk information
		things = dict()

		#create list of slabs
		slabs = dict()

		#create slice for scene
		myslice = ('','','Test Slice')
		zz.destroyslice(myslice)
		zz.createslice(myslice)
		scene = zz.createcell(myslice)

		#create styles
		slabstyle = zz.createcell(myslice,'slab') 
		#zz.insert(slabstyle, dparentcenter, 1, 0, 0)
		#zz.insert(slabstyle, dcenter, 0, 0, 0)
		#zz.insert(slabstyle, dparentrotate, 0, -1)
		#zz.insert(slabstyle, drotate, 0, -1)

		lefttopstyle = zz.createcell(myslice,'point')
		zz.insert(lefttopstyle, dparentcenter, 1, 0)
		zz.insert(lefttopstyle, dtranslate, 0, 0, 0.2)
		
		leftbottomstyle = zz.createcell(myslice,'point')
		zz.insert(leftbottomstyle, dparentcenter, 1, 1)
		zz.insert(leftbottomstyle, dtranslate, 0, 0, 0.2)

		righttopstyle = zz.createcell(myslice,'point')
		zz.insert(righttopstyle, dparentcenter, 0, 0)
		zz.insert(righttopstyle, dtranslate, 0, 0, 0.2)
		
		rightbottomstyle = zz.createcell(myslice,'point')				
		zz.insert(rightbottomstyle, dparentcenter, 0, 1)
		zz.insert(rightbottomstyle, dtranslate, 0, 0, 0.2)
		
		#get edl
		myedl = ('','','Test EDL')



		if self.mode == 1:
			
			#position the 'focused' slab
			maintetroid = self.MakeSlab(self.currentstrand,things,self.currentchunk,1.8)
			zz.insert(scene,drelativeposition,maintetroid)
			zz.insert(maintetroid,dcenter,0.5,0,0)
			corner = zz.insert(maintetroid,drelativeposition)
			slabs[self.currentstrand] = maintetroid
		
		if self.mode == 2:
			
			#position the 'focused' slab to the left
			maintetroid = self.MakeSlab(self.currentstrand,things,self.currentchunk,0.9)
			zz.insert(scene,drelativeposition,maintetroid)
			zz.insert(maintetroid,dcenter,1,0,0)
			zz.insert(maintetroid,dtranslate,-0.5)
			corner = zz.insert(maintetroid,drelativeposition)
			slabs[self.currentstrand] = maintetroid
			
			#position the 'right' slab to the right
			nextstrand,nextchunk = self.nextstrand(self.currentstrand,self.currentchunk)
			if nextstrand and nextstrand not in slabs:
				
				#create dummy vunit positioned to the right of the centre tetroid 
				test = zz.insert(corner,d2,'dummy1')
				zz.insert(test,dparentcenter,1,0,0)
				zz.insert(test,dtranslate,0.5)
				
				#create slab
				nexttetroid = self.MakeSlab(nextstrand,things,nextchunk,0.9)
				
				#add slab
				zz.insert(test,drelativeposition,nexttetroid)
				slabs[nextstrand] = nexttetroid 
				
		if self.mode == 3:
	
			#position the 'focused' slab
			maintetroid = self.MakeSlab(self.currentstrand,things,self.currentchunk,1)
			zz.insert(scene,drelativeposition,maintetroid)
			zz.insert(maintetroid,dcenter,0.5,0,0)
			corner = zz.insert(maintetroid,drelativeposition)
			slabs[self.currentstrand] = maintetroid 
	
			#if there is a next strand
			nextstrand,nextchunk = self.nextstrand(self.currentstrand,self.currentchunk)
			if nextstrand and nextstrand not in slabs:
				
				#create dummy vunit positioned to the right of the centre tetroid 
				test = zz.insert(corner,d2,'dummy1')
				zz.insert(test,dparentcenter,1,0,0)
				zz.insert(test,dtranslate,1)
				
				#create slab
				nexttetroid = self.MakeSlab(nextstrand,things,nextchunk,0.7)
				#nexttetroid = zz.createcell(myslice,'slab')
				#zz.insert(nexttetroid, 'd.representstype', str(nextstrand))
				
				#add slab
				zz.insert(test,drelativeposition,nexttetroid)
				slabs[nextstrand] = nexttetroid
	
			#if there is a previous strand
			prevstrand,prevchunk = self.prevstrand(self.currentstrand,self.currentchunk)
			if prevstrand and prevstrand not in slabs:
				
				#create dummy vunit positioned to the left of the cntre tetroid
				test = zz.insert(corner,d2,'dummy2')
				zz.insert(test,dparentcenter,0,0,0)
				zz.insert(test,dtranslate,-1)
				
				#create slab
				prevtetroid = self.MakeSlab(prevstrand,things,prevchunk,0.7)
				#prevtetroid = zz.createcell(myslice,'slab')
				#zz.insert(prevtetroid, 'd.representstype', str(prevstrand))
				
				#add slab
				#zz.insert(prevtetroid,dcenter,1,0,0)
				#HACK - because the positioning isn't doing what it should... :(
				#zz.insert(test,dtranslate,-22,0,0)
				zz.insert(prevtetroid,dcenter,1,0,0)
				
				zz.insert(test,drelativeposition,prevtetroid)
				slabs[prevstrand] = prevtetroid
				
				#pass
			
				#self.currentstrand = prevstrand
				#self.currentchunk
				#print 'Move test'
				#fw.rebuild()
						
			
			#look for next and previous transclusions
			#self.currentchunk
			
	
			"""
			#for each strand in the edl
			prev = None
			index = 0
			for strand in xu.strands(myedl):
	
				#make a slab for the strand
				slab = self.MakeSlab(strand, things)
				thisindex = index
				index = index+1
				
				#position it relatively to the previous strand (if any)...
				if prev:
					zz.insert(prev,drelativeposition,slab)
				else:
					zz.insert(scene,d2,slab)
	
				#...so that the strands curve
				zz.insert(slab, dmastershape, zz.createclone(slabstyle))
				prev = slab
			"""
			
			"""
				#position camera if in-front of slab3
				camera = zz.insert(slab,'d.relativeposition','camera')
				zz.insert(camera,'d.parentcenter',0.5,0.5,0)
				zz.insert(camera,'d.translate',0,0,20)
			"""

		#get number of slabs yet to show
		slabsize = len(xu.strands(myedl))-len(slabs)

		#now add all other slabs, in order, in the background
		slabcount = 0
		for strand in xu.strands(myedl):
			slabcount = slabcount + 1
			
			if strand not in slabs:
				#dummy = zz.insert(scene,d2)
				dummy = zz.append(scene,d2)
				
				nexttetroid = self.MakeSlab(strand,things,xu.chunks(strand)[0],1)
				zz.insert(dummy,drelativeposition,nexttetroid)
				#zz.insert(nexttetroid,dcentre,0.5,0,0)
				zz.insert(dummy,dtranslate,(slabcount-0.5-slabsize/2)*40,0,-500)
			
			
			pass

		
		#for each chunk (of all those displayed)
		for chunk, list in things.iteritems():
		
			
		
			if not zz.next(list[0],drelativeposition):
				zz.insert(list[0],drelativeposition)
			left = zz.next(list[0],drelativeposition)
				
			lefttop = zz.insert(left, d2)
			leftbottom = zz.insert(lefttop, d2)

			zz.insert(lefttop, dmastershape, zz.createclone(lefttopstyle))
			zz.insert(leftbottom, dmastershape, zz.createclone(leftbottomstyle))
			
			
			#display clinks
			for clink in xu.fromclinks(chunk):
				pass
			
		
				#if the clink type is disabled, then ignore it
				color = self.clinkcolours[xu.type(clink)]
				if color:
					if color[0]==1:
						print 'cancelling1!!!!'
						continue
				else:
					print 'error!!!'
					
				#if there is a corresponding colour for the clink type
				color = self.clinkcolours[xu.type(clink)]
				if color:
					color = color[1]
					for item in list:
						if self.mode == 1:
							zz.insert(item, dcolor, color[0], color[1], color[2], 0.1)
						else:
							zz.insert(item, dcolor, color[0], color[1], color[2], 0.2)
					
				
				for next in xu.tochunks(clink):
					
					pass
									
	
					if next == chunk: continue
					if next not in things: continue

					nextlist = things[next]


					if not zz.next(nextlist[0],drelativeposition):
						zz.insert(nextlist[0],drelativeposition)
					right = zz.next(nextlist[0],drelativeposition)
				
					righttop = zz.insert(right, d2)
					rightbottom = zz.insert(righttop, d2)
					zz.insert(righttop, dmastershape, zz.createclone(righttopstyle))
					zz.insert(rightbottom, dmastershape, zz.createclone(rightbottomstyle))
					
				
					poly = zz.insert(scene, d2, 'trianglestrip')
								
					zz.insert(poly, dpoints, zz.createclone(lefttop), zz.createclone(leftbottom), zz.createclone(righttop), zz.createclone(rightbottom))
		
					zz.insert(poly, drepresentstype, str(next)+str(clink)+'clink')
					


					#if there is a corresponding colour for the clink type
					color = self.clinkcolours[xu.type(clink)]
					if color:
						color = color[1]
					
					if color:
						zz.insert(poly, dcolor, color[0], color[1], color[2], 0.2)

					#zz.insert(list[0], 'd.color', 0, 0, 1, 0.2)
					zz.insert(list[0], dcolor, color[0], color[1], color[2], 0.2)

					#zz.insert(nextlist[0], 'd.color', 0, 0, 1, 0.2)
					zz.insert(nextlist[0], dcolor, color[0], color[1], color[2], 0.2)
				
					

			#display transclusions
			if self.clinkcolours['transclusion'][0]==0:
				
				if len(xu.strandchunks(chunk)) > 1:
			
					#if there is a corresponding colour for the clink type
					color = (1,0,0,0.2)
					for item in list:	
						if self.mode == 1:						
							zz.insert(item, dcolor, color[0], color[1], color[2], 0.1)
						else:
							zz.insert(item, dcolor, color[0], color[1], color[2], 0.2)

						
				
					
				while len(list) > 1:
	
	
					zz.insert(list[0],dcolor,1,0,0,0.2)
					zz.insert(list[1],dcolor,1,0,0,0.2)
	
					#daisy chain them together
					if not zz.next(list[0],drelativeposition):
						zz.insert(list[0],drelativeposition)
					left = zz.next(list[0],drelativeposition)
	
					lefttop = zz.insert(left, d2)
					leftbottom = zz.insert(lefttop, d2)
					zz.insert(lefttop, dmastershape, zz.createclone(lefttopstyle))
					zz.insert(leftbottom, dmastershape, zz.createclone(leftbottomstyle))
	
					if not zz.next(list[1],drelativeposition):
						zz.insert(list[1],drelativeposition)
					right = zz.next(list[1],drelativeposition)
	
					righttop = zz.insert(right, d2)
					rightbottom = zz.insert(righttop, d2)
					zz.insert(righttop, dmastershape, zz.createclone(righttopstyle))
					zz.insert(rightbottom, dmastershape, zz.createclone(rightbottomstyle))

	
					poly = zz.insert(scene, d2, 'trianglestrip')
					zz.insert(poly, dpoints, lefttop, leftbottom, righttop, rightbottom)
					zz.insert(poly, dcolor, 1, 0, 0, 0.2)
					zz.insert(poly, drepresentstype, str(list[0])+'transclusion')
	
					list = list[1:]
			

		#print myslice, scene, len(scene), scene[0], scene[1], scene[2], scene[3]
		
		
		fw.updatescene(scene)

		#print 'update time',fw.time()-starttime
		
		
#create translit applitude
TranslitApplitude2()
#print 'ok'
