# TkTeXCad
# (C) Copyright 2001 Hilmar Straube; dieses Programm untersteht der GPL.
# Keinerlei Garantie auf was auch immer, was mit diesem Programm zu tun hat.

from Tkinter import *
import math

from internat import * # Sprache und Konfiguration auch hier benutzen
from config import *
from globalpars import *

fakt = FAKT

CLIPBOARDNAME = None # gesichert als Name des Clipboard

def notifyfaktchange(newfakt):
    global fakt
    fakt = newfakt

class diameter: # Sucht einen passenden Durchmesser zu gegebenem
	def getd(self, d, as):
		index = 0
		if as:
			pd = POSSIBLEDIAMETERSAS
		else:
			pd = POSSIBLEDIAMETERS
		while pd[index] < d:
			index += 1
			if index >= len(pd) - 1:
				return pd[index]
			
		if index == 0: # index - 1 gibt Ärger!
			return pd[0]
		if abs(pd[index] - d) < abs(pd[index - 1] - d):
			return pd[index]
		else:
			return pd[index - 1]

diameterer = diameter()

class angle: # Klasse zum Bestimmen eines besten LaTeX-Paares zu einem gegebenen Winkel
	def __init__(self, set):
		self.erg = []
		for dxdy in set:
			if dxdy != (0, 1):
				m = dxdy[1]/float(dxdy[0])
				alpha = math.atan(m)
				self.erg.append([alpha, dxdy])
			else:
				self.erg.append([math.pi/2, dxdy])
	def getdxdy(self, alpha): # Winkel im Bereich [0; pi/2]
		dev = -1
		index = -1
		z = 0
		for el in self.erg:
			aktudev = abs(el[0] - alpha)
			if aktudev < dev or index == -1:
				index = z
				dev = aktudev
			z += 1
		return self.erg[index]

angler = angle(POSSIBLEDXDY) # Für allg. Benutzung
vecangler = angle(VECDXDY) # Für Pfeile

class picelEx(Exception):
	pass

class picel:
	# Basisklasse für alle Bildelemente; jedes muss sich aus Parametern erzeugen lassen,
	# Sich selbst zeichnen, für sich in uids alle dabei benutzten ids sichern und diese an den Aufrufer zurückliefern.
	# Grund: picel1 ist in putter1 ist in picture1 ist in putter2 ist in picture2 ist in Oberfläche
	# Oberflächer liefert id, und picture kann sagen, dass diese in putter2, in ... -> Rückschluss
	def __init__(self):
		self.uids = []
	def undrawhook(self):
		pass
	def draw(self): # WIRD NICHT AUFGERUFEN! Nur zur Hilfestellung.
		self.uids = []
		return self.uids

class pcs: # Klasse zur Verwaltung aller Teilbildklassen und ihrer Namen
	def __init__(self):
		self.pictures = []
		self.names = []
	def append(self, item):
		self.pictures.append(item)
		self.names.append(item.name)
	def __delitem__(self, nr):
		del self.pictures[nr]
		del self.names[nr]
	def newname(self, name):
		return not(name in self.names)
	def changename(self, oldname, newname):
		try:
			index = self.names.index(oldname)
			self.names[index] = newname
			self.pictures[index].name = newname
			return 1
		except ValueError:
			return 0

def plboundingbox(putterlist):
	"Bestimmt Extremausmaße der enthaltenen Elemente und setzt dann die eigenen entsprechend"
	x1 = x2 = y1 = y2 = None # Umschließendes Rechteck feststellen
	for el in putterlist:
		dx1, dy1, dx2, dy2 = el.dxdy()
		if x1 > dx1 or x1 == None:
			x1 = dx1
		if x2 < dx2 or x2 == None:
			x2 = dx2
		if y1 > dy1 or y1 == None:
			y1 = dy1
		if y2 < dy2 or y2 == None:
			y2 = dy2

	return (x1, y1, x2, y2)

class pictureEx(picelEx):
	pass

class pictureclass:
	def dumptex(self):
		sf = '% ' + PROGNAME + GENMARK[LANG]
		sf += '\\begin{picture}' + `(self.xsize, self.ysize)` + '\n'
		for el in self.putters:
			sf += el.dumptex() + '\n'
		sf += '\\end{picture}'
		return sf
	def __init__(self, xsize, ysize, name):
		if xsize < 0 or ysize < 0:
			raise pictureEx
		self.xsize = xsize
		self.ysize = ysize
		self.name = name
		self.putters = []
	def untk(self): # Alle Elemente, die mit tk beginnen, können nicht gepickelt werden, werden also vorher gelöscht.
		# Diese Prozedur muss für jede zu pickelnde Klasse aufgerufen werden
		for putter in self.putters:
			keys = putter.__dict__.keys()
			for key in keys:
				if key[:2] == 'tk':
					del putter.__dict__[key]
			keys = putter.pe.__dict__.keys()
			for key in keys:
				if key[:2] == 'tk':
					del putter.pe.__dict__[key]
	def getallblocks(self, ofpc, root = None):
		# Die Methode liefert alle Klassen, deren Instanzen in dem Baum von self ofpc enthalten.

		if root == None: # Baumausgang sichern
			root = self
			
		blocked = []
		for putter in self.putters: # Alle Putter der Klasse durchlaufen
			if putter.pe.__class__ == picture:
				# Dieser putter ist ein Bild.
				if putter.pe.pc == ofpc: # Ist Putter picture und Instanz der gefragten Klasse
					bc = putter.pe.bc
					if bc not in blocked: # ... hänge alle noch nicht blockierten Klassen an
						blocked.append(bc)
						erg = root.getallblocks(bc) # Geh den Baum nochmal durch: Alle Klassen, die enthaltende enthalten sind ebenfalls zu blockieren.
						for el in erg: # Dopplungen vermeiden
							if el not in blocked:
								blocked.append(el)
				else:
					# Der Baum spaltet sich auf; das picel im putter ist ein anderes Bild
					erg = putter.pe.pc.getallblocks(ofpc, root) # Hereingehen.
					for el in erg:
						if el not in blocked:
							blocked.append(el)
		return blocked # Rückgabe
	def adjustdxdy(self): # Minimale Abmessungen bestimmen und benutzen; nicht wenn kein Putter da ist.
		if self.putters != []:
			x1, y1, x2, y2 = plboundingbox(self.putters)
			for z in range(len(self.putters)):
				self.putters[z].x -= x1
				self.putters[z].y -= y1
			self.xsize = x2 - x1
			self.ysize = y2 - y1			      

class picture(picel):
	clickdepth = 1
	def dumptex(self):
		return '\\setlength{\\unitlength}{' + `self.scale`+ '\\unitlength}\\input{' + self.pc.name + '}'
	def __init__(self, pc, scale, blockedclasses):
		#  letzter Parameter: Liste der Klassen, in deren Instanzen das neue Bild enthalten ist
		self.pc = pc
		self.putters = self.pc.putters
		self.bc = blockedclasses
		self.scale = scale
	def dxdy(self, x, y):
		return x, y, x + self.pc.xsize, x + self.pc.ysize
	def copy(self):
		return picture(self.pc, self.scale, self.bc)
	def changecb(self, event = None):
		try:
			self.scale = self.tkscale.get() / 100.0
			self.tkcallredraw()
		except ValueError:
			self.tkscale.set(self.scale)
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = PICTURELABELCLASS[LANG] + self.pc.name).grid(row = 0, columnspan = 2)
		Label(frame, text = PICTURELABELSCALE[LANG]).grid(row = 1, column = 0)
		self.tkscale = DoubleVar()
		self.tkscale.set(self.scale * 100)
		e = Entry(frame, textvariable = self.tkscale)
		e.grid(row = 1, column = 1, sticky = E + W)
		e.bind("<Return>", self.changecb)
	def doscale(self, scale):
		self.scale *= scale
	def draw(self, x, y, maxy, canvas, scale = 1): 
		self.uids = []
		for putter in self.putters:
			self.uids += putter.draw(x / self.scale / scale, y / self.scale / scale, maxy / self.scale / scale, canvas, self.scale * scale)
			# Im neuen System ist für den Aufgerufenen x,y und maxy entsprechend größer
		return self.uids
	def getputter(self, uid):
		"Nur für oberstes picture; funktioniert nat. auch mit multiputters; 0 für Misserfolg"
		for putter in self.putters:
			if uid in putter.uids:
				return putter
		return 0
	def undraw(self, canvas):
		"NUR FÜR OBERSTES (angezeigtes) PICTURE, ruft alle putter.undraws auf"
		self.uids = []
		for putter in self.putters:
			putter.undraw(canvas)
	
class circleEx(picelEx):
	pass

class circle(picel):
	clickdepth = 2
	def dumptex(self):
		if self.bold:
			sf = '\\thicklines'
		else:
			sf = '\\thinlines'
		sf += '\\circle'
		if self.filled:
			sf += '*'
		sf += '{' + `self.d` + '}'
		return sf
	def __init__(self, d, filled, bold = 0):
		picel.__init__(self)
		if filled:
			if d not in POSSIBLEDIAMETERSAS:
				raise circleEx
		else:
			if d not in POSSIBLEDIAMETERS:
				raise circleEx
		
		self.d = float(d) # LaTeX erwartet Durchmesser!
		self.filled = filled
		self.bold = bold
		self.changed = 0
	def dxdy(self, x, y):
		d = self.d
		return x - d/2, y - d/2, x + d/2, y + d/2
	def savestate(self):
		self.state = self.d, self.filled, self.bold
	def cancel(self):
		self.d, self.filled, self.bold = self.state
	def minfo(self, ox, oy, x, y): # Rechnet mit zweiten Punkt von Benutzeroberfläche die neue Neigung aus
		dx = x - ox # Relative Position
		dy = y - oy
		e = 2 * (dx**2 + dy**2)**0.5 # Entfernung bestimmen
		self.d = float(diameterer.getd(e, self.filled)) # damit d/2 nicht Durchmesser 1 und 2 ... gleich macht!
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\circle; \circle*").grid()
		
		self.tkbold = IntVar()
		Checkbutton(frame, text = PICELLABELBOLD[LANG], variable = self.tkbold, command = self.changecb).grid()
		self.tkbold.set(self.bold)

		self.tkfilled = IntVar()
		Checkbutton(frame, text = CIRCLELABELFILLED[LANG], variable = self.tkfilled, command = self.changecb).grid()
		self.tkfilled.set(self.filled)
	def copy(self):
		return circle(self.d, self.filled, self.bold)
	def doscale(self, scale):
		d = self.d * scale
		self.d = diameterer.getd(d, self.filled)
	def draw(self, x, y, maxy, canvas, scale = 1):
		if self.changed:
			self.bold = self.tkbold.get()
			self.filled = self.tkfilled.get()
			self.d = float(diameterer.getd(self.d, self.filled)) # mgl. Durchmesser von gefülltem und ungefülltem Kreis sind verschieden
			self.changed = 0
		self.uids = []

		d = self.d * scale
		d = diameterer.getd(d, self.filled)
		r = d/2.0
		boundbox = (fakt * (x - r),
			    fakt * (maxy - y - r),
			    fakt * (x + r),
			    fakt * (maxy - y + r))
		if self.bold:
			wi = THICKWIDTH * fakt
		else:
			wi = THINWIDTH * fakt
		self.uids = [canvas.create_oval(boundbox, width = wi)]
		if self.filled:
			canvas.itemconfigure(self.uids[0], fill = "BLACK")
		return self.uids

class lineEx(picelEx):
	pass

class line(picel):
	clickdepth = 2
	def dumptex(self):
		if self.bold:
			sf = '\\thicklines'
		else:
			sf = '\\thinlines'
		if self.vec:
			sf += '\\vector'
		else:
			sf += '\\line'
		sf += `(self.dx, self.dy)` # :-)
		sf += '{' + `self.len`+ '}'
		return sf
	def __init__(self, dx, dy, len, vec, bold = 0):
		picel.__init__(self)
		if not (abs(dx), abs(dy)) in POSSIBLEDXDY:
			raise lineEx
		self.dx = dx
		self.dy = dy
		self.len = len
		self.vec = vec
		self.bold = bold
		self.changed = 0 # für die Konfiguration via change
	def dxdy(self, x, y):
		absdxdy = abs(self.dx), abs(self.dy)
		if absdxdy == (0, 1): # Längen im ersten Quadranten bestimmen
			dx = 0
			dy = self.len
		else:
			dx = self.len
			m = absdxdy[1]/float(absdxdy[0])
			dy = m * dx
		if self.dx < 0:
			dx = -dx
		if self.dy < 0:
			dy = -dy

		x2 = x + dx # zweite Punkte bilden
		y2 = y + dy

		return min(x, x2), min(y, y2), max(x, x2), max(y, y2) # richtig geordnete Rückgabe
	def savestate(self):
		self.state = self.dx, self.dy, self.len, self.vec, self.bold
	def cancel(self):
		self.dx, self.dy, self.len, self.vec, self.bold = self.state
	def minfo(self, ox, oy, x, y): # Rechnet mit zweiten Punkt von Benutzeroberfläche die neue Neigung aus
		dx = x - ox # Relative Position
		dy = y - oy
		if dx == 0:
			alpha = math.pi/2
		else:
			m = dy/float(dx)
			alpha = abs(math.atan(m)) # Winkel des zweiten Punktes zum ersten in den Bereich [0; pi/2] pressen.
		if self.vec:
			self.dx, self.dy = vecangler.getdxdy(alpha)[1] # nächsten LaTeX-Neigungswinkel errechnen
		else:
			self.dx, self.dy = angler.getdxdy(alpha)[1] # nächsten LaTeX-Neigungswinkel errechnen

		if dx < 0:
			self.dx = -self.dx
		if dy < 0:
			self.dy = -self.dy
		if self.dx == 0:
			self.len = abs(dy)
		else:
			self.len = abs(dx)
        def vecchangecb(self):
		if self.dx == 0:
			self.changecb()
			return                    
		angle = math.atan(abs(self.dy / float(self.dx)))
		ndx, ndy = vecangler.getdxdy(angle)[1]
		if self.dx < 0:
			ndx = -ndx
		if self.dy < 0:
			ndy = -ndx
		self.dx, self.dy = ndx, ndy
		self.changecb()
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\line; \vector").grid(columnspan = 2)
		
		self.tkbold = IntVar()
		Checkbutton(frame, text = PICELLABELBOLD[LANG], variable = self.tkbold, command = self.changecb).grid(row = 1, columnspan = 2)
		self.tkbold.set(self.bold)

		self.tkvec = IntVar()
		Radiobutton(frame, text = LINELABELLINE[LANG], variable = self.tkvec, value = 0, command = self.changecb).grid(row = 2, column = 0)
		Radiobutton(frame, text = LINELABELVEC[LANG], variable = self.tkvec, value = 1, command = self.vecchangecb).grid(row = 2, column = 1)
		self.tkvec.set(self.vec)

	def copy(self):
		return line(self.dx, self.dy, self.len, self.vec, self.bold)
	def doscale(self, scale):
		self.len *= scale
	def draw(self, x, y, maxy, canvas, scale = 1):
		len = self.len * scale
		if self.changed:
			self.vec = self.tkvec.get()
			self.bold = self.tkbold.get()
			self.changed = 0
		self.uids = []
		# Koordinaten des zweiten Punktes bestimmen
		if (abs(self.dx), abs(self.dy)) == (0, 1): # Vertikale Linie
			x2 = x
			ylen = self.dy/(abs(self.dy)) * len # Vorzeichenbehaftet!
			y2 = y + ylen
		else: # Alle anderen Liniensorten
			# aus x-Projektion der Länge und Neigung den y-Anteil ausrechnen
			m = self.dy/float(self.dx)
			xlen = self.dx/abs(self.dx) * len # LaTeX-Länge + Vorzeichen -> DeltaX
			ylen = m * xlen
			x2 = x + xlen
			y2 = y + ylen
		arrowshape = (ARROWSHAPE[0] * scale * fakt, ARROWSHAPE[1] * scale * fakt, ARROWSHAPE[2] * scale * fakt)
		if self.vec: # Pfeil?
			ar = LAST
		else:
			ar = NONE
		if self.bold:
			wi = THICKWIDTH * fakt
		else:
			wi = THINWIDTH * fakt
			
		self.uids = [canvas.create_line(fakt * x, fakt * (maxy - y), fakt * x2, fakt * (maxy - y2), width = wi, arrow = ar, arrowshape = arrowshape)]
		return self.uids

class ovalEx(picelEx):
	pass

class oval(picel):
	clickdepth = 2
	BUTTEXTS = (OVALALL[LANG],
		    OVALT[LANG],
		    OVALL[LANG],
		    OVALR[LANG],
		    OVALB[LANG],
		    OVALTR[LANG],
		    OVALTL[LANG],
		    OVALBL[LANG],
		    OVALBR[LANG])
	def dumptex(self):
		if self.bold:
			sf = '\\thicklines'
		else:
			sf = '\\thinlines'
			
		selstr = ('',
			  '[t]',
			  '[l]',
			  '[r]',
			  '[b]',
			  '[tr]',
			  '[tl]',
			  '[bl]',
			  '[br]')[self.at]
			  
		sf += '\\oval' + `(self.dx, self.dy)` + selstr

		return sf
	def atlrbTrTlBlBr2selector(self, atlrbTrTlBlBr):
		if atlrbTrTlBlBr == 0: # A
			return 1, 1, 1, 1
		elif atlrbTrTlBlBr == 1: # T
			return 1, 1, 0, 0
		elif atlrbTrTlBlBr == 2: # L
			return 0, 1, 1, 0
		elif atlrbTrTlBlBr == 3: # R
			return 1, 0, 0, 1
		elif atlrbTrTlBlBr == 4: # B
			return 0, 0, 1, 1
		elif atlrbTrTlBlBr == 5: # TR
			return 1, 0, 0, 0
		elif atlrbTrTlBlBr == 6: # TL
			return 0, 1, 0, 0
		elif atlrbTrTlBlBr == 7: # BL
			return 0, 0, 1, 0
		elif atlrbTrTlBlBr == 8: # BR
			return 0, 0, 0, 1		
	def __init__(self, dx, dy, atlrbTrTlBlBr = 0, bold = 0):
		# atlrb - alles = 0, top = 1, left = 2 ...
		if atlrbTrTlBlBr not in range(9):
			raise ovalEx
		picel.__init__(self)
		self.dx = dx
		self.dy = dy
		self.selector = self.atlrbTrTlBlBr2selector(atlrbTrTlBlBr)
		self.at = atlrbTrTlBlBr
		self.bold = bold
		self.changed = 0
	def dxdy(self, x, y):
		dxh = self.dx / 2.0
		dyh = self.dy / 2.0
		if self.at in [4, 8, 5]: #[R, BR, TR]:
			x1 = x
		else:
			x1 = x - dxh
		if self.at in [1, 6, 5]: #[T, TL, TR]:
			y1 = y 
		else:
			y1 = y - dyh

		if self.at in [3, 6, 7]: #[L, TL, BL]:
			x2 = x
		else:
			x2 = x + dxh

		if self.at in [2, 7, 8]: #[B, BL, BR]:
			y2 = y
		else:
			y2 = y + dyh
		return x1, y1, x2, y2
	def savestate(self):
		self.state = self.dx, self.dy, self.selector, self.at, self.bold
	def cancel(self):
		self.dx, self.dy, self.selector, self.at, self.bold = self.state
	def minfo(self, ox, oy, x, y):
		self.dx = abs(ox - x) * 2
		self.dy = abs(oy - y) * 2
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\oval").pack()
		
		self.tkbold = IntVar()
		Checkbutton(frame, text = PICELLABELBOLD[LANG], variable = self.tkbold, command = self.changecb).pack()
		self.tkbold.set(self.bold)

		self.tksel = IntVar()
		for z in range(9):
			Radiobutton(frame, text = self.BUTTEXTS[z], variable = self.tksel, value = z, command = self.changecb).pack(anchor = W)
		self.tksel.set(self.at)
	def copy(self):
		return oval(self.dx, self.dy, self.at, self.bold)
	def doscale(self, scale):
		self.dx *= scale
		self.dy *= scale
	def draw(self, x, y, maxy, canvas, scale = 1):
		dx = self.dx * scale
		dy = self.dy * scale
		if self.changed:
			self.bold = self.tkbold.get()
			self.at = self.tksel.get()
			self.selector = self.atlrbTrTlBlBr2selector(self.at)
			self.changed = 0
		self.uids = []
		# Kürzere Seite bestimmen
		if dx < dy:
			lmin = dx
		else:
			lmin = dy
		d = 0 # Daraus kann LaTeX machen was es will. Wohl nicht viel.
		# Radius bestimmen
		for i in range(len(POSSIBLEDIAMETERS) - 1, -1, -1):
			if POSSIBLEDIAMETERS[i] <= lmin:
				d = POSSIBLEDIAMETERS[i]
				break
		d = float(d)
		# Eckpunkte bestimmen
		mx = x
		my = y
		x -= dx/2
		y -= dy/2
		x2 = x + dx
		y2 = y + dy

		# Kreisbögen zeichnen
		if self.bold:
			wi = THICKWIDTH * fakt
		else:
			wi = THINWIDTH * fakt
		
		# rechts oben
		if self.selector[0]:
			self.uids.append(
				canvas.create_line(
				fakt * mx, fakt * (maxy - y2), fakt * (x2 - d/2), fakt * (maxy - y2), width = wi))
			self.uids.append(
				canvas.create_line(
				fakt * x2, fakt * (maxy - my), fakt * x2, fakt * (maxy - (y2 - d/2)), width = wi))
			bbox = fakt * (x2 - d), fakt * (maxy - (y2 - d)), fakt * x2, fakt * (maxy - y2)
			self.uids.append(
				canvas.create_arc(bbox, start = 0, extent = 90, style = ARC, width = wi))
		# Links oben
		if self.selector[1]:
			self.uids.append(
				canvas.create_line(
				fakt * (x + d/2), fakt * (maxy - y2), fakt * mx, fakt * (maxy - y2), width = wi))
			self.uids.append(
				canvas.create_line(
				fakt * x, fakt * (maxy - my), fakt * x, fakt * (maxy - (y2 - d/2)), width = wi))
			bbox = fakt * x, fakt * (maxy - (y2 - d)), fakt * (x + d), fakt * (maxy - y2)
			self.uids.append(
				canvas.create_arc(bbox, start = 90, extent = 90, style = ARC, width = wi))
		# Links unten
		if self.selector[2]:
			self.uids.append(
				canvas.create_line(
				fakt * x, fakt * (maxy - (y + d/2)), fakt * x, fakt * (maxy - my), width = wi))
			self.uids.append(
				canvas.create_line(
				fakt * (x + d/2), fakt * (maxy - y), fakt * mx, fakt * (maxy - y), width = wi))
			bbox = fakt * x, fakt * (maxy - y), fakt * (x + d), fakt * (maxy - (y + d))
			self.uids.append(
				canvas.create_arc(bbox, start = 180, extent = 90, style = ARC, width = wi))
		# Rechts unten
		if self.selector[3]:
			self.uids.append(
				canvas.create_line(
				fakt * mx, fakt * (maxy - y), fakt * (x2 - d/2), fakt * (maxy - y), width = wi))
			self.uids.append(
				canvas.create_line(
				fakt * x2, fakt * (maxy - (y + d/2)), fakt * x2, fakt * (maxy - my), width = wi))
			bbox = fakt * (x2 - d), fakt * (maxy - y), fakt * x2, fakt * (maxy - (y + d))
			self.uids.append(
				canvas.create_arc(bbox, start = 270, extent = 90, style = ARC, width = wi))
		return self.uids

class bezierEx(picelEx):
	pass

class bezier(picel):
	clickdepth = 3
	def dumptex(self):
		if self.bold:
			sf = '\\thicklines'
		else:
			sf = '\\thinlines'
		sf += '\\qbezier' + `(self.xa, self.ya)` + `(self.xb, self.yb)` + `(self.xc, self.yc)`
		return sf
	def __init__(self, xa, ya, xb, yb, xc, yc, bold = 0):
		picel.__init__(self)
		self.xa = xa
		self.ya = ya
		self.xb = xb
		self.yb = yb
		self.xc = xc
		self.yc = yc
		self.bold = bold
		self.changed = 0
	def dxdy(self, x, y):
		x1 = min(self.xa, self.xb, self.xc)
		x2 = max(self.xa, self.xb, self.xc)
		y1 = min(self.ya, self.yb, self.yc)
		y2 = max(self.ya, self.yb, self.yc)
		return x1 + x, y1 + y, x2 + x, y2 + y
	def copy(self):
		return bezier(self.xa, self.ya, self.xb, self.yb, self.xc, self.yc, self.bold)
	def savestate(self):
		self.state = self.xa, self.ya, self.xb, self.yb, self.xc, self.yc
	def cancel(self):
		self.xa, self.ya, self.xb, self.yb, self.xc, self.yc = self.state
	def minfo(self, ox, oy, x, y):
		dx = x - ox
		dy = y - oy
		self.xc = dx
		self.yc = dy
	def minfo2(self, ox, oy, x, y):
		dx = x - ox
		dy = y - oy
		self.xb = dx
		self.yb = dy
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\qbezier").grid()
		
		self.tkbold = IntVar()
		Checkbutton(frame, text = PICELLABELBOLD[LANG], variable = self.tkbold, command = self.changecb).grid()
		self.tkbold.set(self.bold)
	def doscale(self, scale):
		self.xa *= scale
		self.ya *= scale
		self.xb *= scale
		self.yb *= scale
		self.xc *= scale
		self.yc *= scale		
	def draw(self, x, y, maxy, canvas, scale = 1):
		xa = self.xa * scale
		ya = self.ya * scale
		xb = self.xb * scale
		yb = self.yb * scale
		xc = self.xc * scale
		yc = self.yc * scale
		if self.changed:
			self.bold = self.tkbold.get()
			self.changed = 0
		self.uids = []
		if self.bold:
			wi = THICKWIDTH * fakt
		else:
			wi = THINWIDTH * fakt
		uid = canvas.create_line(fakt * (x + xa),
					 fakt * (maxy - (y + ya)),
					 fakt * (x + xb),
					 fakt * (maxy - (y + yb)),
					 fakt * (x + xc),
					 fakt * (maxy - (y + yc)),
					 smooth = 1,
					 width = wi
					 )
		self.uids = [uid]
		return self.uids

class simpletext(picel):
	# Einfacher Textstring
	clickdepth = 1
	def dumptex(self):
		return self.text
	def __init__(self, text):
		picel.__init__(self)
		self.text = text
	def dxdy(self, x, y): # Keine Ahnung, wie groß der Text wird, ich müsste ja LaTeX neu schreiben!
		return x, y, x, y
	def copy(self):
		return simpletext(self.text)
	def changecb(self, a1, a2, a3):
		self.text = self.tktext.get() # Muss eine Zeichenkette sein
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "<einfacher Text>").grid()
		
		self.tktext = StringVar()
		Entry(frame, textvariable = self.tktext).grid()
		self.tktext.set(self.text)
		self.tktext.trace("w", self.changecb)
	def doscale(self, scale):
		pass
	def draw(self, x, y, maxy, canvas, scale = 1):
		self.uids = []
		uid = canvas.create_text(fakt * x, fakt * (maxy - y), anchor = S + W, text = '*TEXT*')
		
		self.uids = [uid]
		return self.uids

class textboxEx(picelEx):
	pass

class textbox(picel):
	# VORSICHT: textbox erlaubt negative dx, dy!
	clickdepth = 2
	def dumptex(self, x, y, dx, dy, n): # und daher wird dieser hier nur mit allen Informationen von multiputer aufgefordert, dessen Job zu übernehmen.
		sdx = self.dx
		sdy = self.dy
		if sdx < 0:
			sdx = -sdx
			x -= sdx
		if sdy < 0:
			sdy = -sdy
			y -= sdy

		if n != 1:
			sf = '\\multiput' + `(x, y)` + `(dx, dy)` + '{' + `n` + '}{'
		else:
			sf = '\\put' + `(x, y)` + '{'

		if self.bold:
			sf += '\\thicklines'
		else:
			sf += '\\thinlines'
		# Auswahl des Kommandos
		if self.dash < 0:
			sf += '\\makebox'
		elif self.dash == 0:
			sf += '\\framebox'
		elif self.dash > 0:
			sf += '\\dashbox{' + `self.dash` + '}'

		sf += `(sdx, sdy)`

		# Poitionierungsangabe
		if self.lmr != 1 or self.bmt != 1:
			sf += '['
			sf += ['l', '', 'r'][self.lmr]
			sf += ['b', '', 't'][self.bmt]
			sf += ']'
		sf += '{' + self.text

		sf += '}}' # von der box und vom putter

		return sf
	def __init__(self, dx, dy, lmr, bmt, dash, text, bold = 0):
		"lmr -> 0: l, 1: m, 2: r ...; dash = 0 -> \framebox, sonst Strichlänge; negativ -> kein Rahmen"
		self.lmr = lmr
		self.bmt = bmt
		if not (lmr in range(3) and bmt in range(3)):
			raise textboxEx
		picel.__init__(self)
		self.text = text
		self.dx = dx
		self.dy = dy
		self.dash = dash
		self.bold = bold
		self.changed = 0
	def copy(self):
		return textbox(self.dx, self.dy, self.lmr, self.bmt, self.dash, self.text, self.bold)
	def dxdy(self, x, y):
		if self.dx < 0:
			x1 = x + self.dx
			x2 = x
		else:
			x1 = x
			x2 = x + self.dx
		if self.dy < 0:
			y1 = y + self.dy
			y2 = y
		else:
			y1 = y
			y2 = y + self.dy
		return x1, y1, x2, y2
	def savestate(self):
		self.state = self.lmr, self.bmt, self.text, self.dx, self.dy, self.dash, self.bold
	def cancel(self):
		self.lmr, self.bmt, self.text, self.dx, self.dy, self.dash, self.bold = self.state
	def minfo(self, ox, oy, x, y):
		self.dx = x - ox
		self.dy = y - oy
	def changecb2(self, a1, a2, a3):
		self.text = self.tktext.get()
		self.changed = 1
		self.tkcallredraw()
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def changecbworkaround(self, event):
		self.changecb()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\dashbox; \framebox; \makebox").pack()

		# Fett
		self.tkbold = IntVar()
		Checkbutton(frame, text = PICELLABELBOLD[LANG], variable = self.tkbold, command = self.changecb).pack()
		self.tkbold.set(self.bold)

		# Text
		self.tktext = StringVar()
		textframe = Frame(frame, borderwidth = 1, relief = RAISED)
		textframe.pack(fill = BOTH, expand = 1)
		Label(textframe, text = PICELLABELTEXT[LANG]).pack(side = LEFT)
		Entry(textframe, textvariable = self.tktext).pack(side = RIGHT, fill = X, expand = 1)
		self.tktext.set(self.text)
		self.tktext.trace("w", self.changecb2)

		# Rahmenart

		self.tkstyle = IntVar()
		borderframe = Frame(frame, borderwidth = 1, relief = RAISED)
		borderframe.pack(fill = BOTH, expand = 1)
		Label(borderframe, text = TEXTBOXLABELBORDER[LANG]).grid(row = 0, column = 0, columnspan = 3)
		Radiobutton(borderframe, text = TEXTBOXLABELNOBORDER[LANG], variable = self.tkstyle, value = -1, command = self.changecb).grid(row = 1, column = 0)
		Radiobutton(borderframe, text = TEXTBOXLABELFULLBORDER[LANG], variable = self.tkstyle, value = 0, command = self.changecb).grid(row = 1, column = 1)
		Radiobutton(borderframe, text = TEXTBOXLABELDASHEDBORDER[LANG], variable = self.tkstyle, value = 1, command = self.changecb).grid(row = 1, column = 2)
		if self.dash < 0:
			self.tkstyle.set(-1)
		elif self.dash == 0:
			self.tkstyle.set(0)
		else:
			self.tkstyle.set(1)

		self.tkdashlen = DoubleVar()
		borderframe2 = Frame(borderframe)
		borderframe2.grid(sticky = N+E+S+W, columnspan = 3)
		Label(borderframe2, text = TEXTBOXLABELDASHLEN[LANG]).pack(side = LEFT)
		EDashLen = Entry(borderframe2, textvariable = self.tkdashlen)
		EDashLen.pack(side = RIGHT, fill = X, expand = 1)
		EDashLen.bind('<Return>', self.changecbworkaround)
		if self.tkstyle.get() == 1: # Inhalt des Strichlängenfeldes bestimmen
			self.tkdashlen.set(self.dash)
		else:
			self.tkdashlen.set(DEFAULTDASHLEN)
		
		# Position
		self.tkpos = IntVar()
		posframe = Frame(frame, borderwidth = 1, relief = RAISED)
		posframe.pack(fill = BOTH, expand = 1)
		Label(posframe, text = TEXTBOXLABELPOS[LANG]).grid(row = 0, columnspan = 3)
		Radiobutton(posframe, variable = self.tkpos, value = 00, command = self.changecb).grid(row = 3, column = 0)
		Radiobutton(posframe, variable = self.tkpos, value = 01, command = self.changecb).grid(row = 3, column = 1)
		Radiobutton(posframe, variable = self.tkpos, value = 02, command = self.changecb).grid(row = 3, column = 2)

		Radiobutton(posframe, variable = self.tkpos, value = 10, command = self.changecb).grid(row = 2, column = 0)
		Radiobutton(posframe, variable = self.tkpos, value = 11, command = self.changecb).grid(row = 2, column = 1)
		Radiobutton(posframe, variable = self.tkpos, value = 12, command = self.changecb).grid(row = 2, column = 2)

		Radiobutton(posframe, variable = self.tkpos, value = 20, command = self.changecb).grid(row = 1, column = 0)
		Radiobutton(posframe, variable = self.tkpos, value = 21, command = self.changecb).grid(row = 1, column = 1)
		Radiobutton(posframe, variable = self.tkpos, value = 22, command = self.changecb).grid(row = 1, column = 2)
		self.tkpos.set(self.bmt * 10 + self.lmr)
		# bmt, lmr -> init
		# Beide zusammen werden als value des Knopfes gesichert, indem der vertikale Anteil mit 10
		# multipliziert eingeht.
	def dashline(self, x1, x2, y, dash, h, wi, canvas): # Hilfsfunktion
		uids = []
		if x2 < x1: # ggf. Parameter vertauschen
			dummy = x2
			x2 = x1
			x1 = dummy

		anz = (x2 - x1) / float(dash) # Anzahl der kompletten Striche
		rest = (anz - int(anz)) * dash # Länge des Reststückes
		z = -1
		for z in range(anz):
			if z % 2 == 0: # Nur die Hälfte der Striche anzeigen
				if h:
					newuid = canvas.create_line(x1 + z * dash, y, x1 + (z + 1) * dash, y, width = wi)
				else:
					newuid = canvas.create_line(y, x1 + z * dash, y, x1 + (z + 1) * dash, width = wi)
				uids.append(newuid)
		z += 1
		if z % 2 == 0:
			if h:
				newuid = canvas.create_line(x1 + z * dash, y, x2, y, width = wi)
			else:
				newuid = canvas.create_line(y, x1 + z * dash, y, x2, width = wi)
			uids.append(newuid)
		return uids
	def drawdash(self, x, y, maxy, canvas, scale = 1):
		"Hilfsfunktion für .draw: alle \dahslines"
		dx = self.dx * scale
		dy = self.dy * scale
		dash = self.dash * scale
		self.uids = []
		if self.bold:
			wi = THICKWIDTH * fakt
		else:
			wi = THINWIDTH * fakt
		# Horizontale Linien (h = 1)
		self.uids += \
			self.dashline(fakt * x, fakt * (x + dx), fakt * (maxy - y), fakt * dash, 1, wi, canvas)
		self.uids += \
			self.dashline(fakt * x, fakt * (x + dx), fakt * (maxy - (y + dy)), fakt * dash, 1, wi, canvas)
		# Vertikale Linien (h = 0)
		self.uids += \
			self.dashline(fakt * (maxy - y), fakt * (maxy - (y + dy)), fakt * x, fakt * dash, 0, wi, canvas)
		self.uids += \
			self.dashline(fakt * (maxy - y), fakt * (maxy - (y + dy)), fakt * (x + dx), fakt * dash, 0, wi, canvas)
	def drawfull(self, x, y, maxy, canvas, scale = 1):
		"Hilfsfunktion für .draw: alle \makebox sowie \framebox"
		dx = self.dx * scale
		dy = self.dy * scale
		self.uids = []
		if self.bold:
			wi = THICKWIDTH * fakt
		else:
			wi = THINWIDTH * fakt
		# Horizontale Linien
		if self.dash < 0:
			col = MAKEBOXCOL
		else:
			col = "black"
		self.uids.append(
			canvas.create_line(fakt * x, fakt * (maxy - y), fakt * (x + dx), fakt * (maxy - y), width = wi, fill = col))
		self.uids.append(
			canvas.create_line(fakt * x, fakt * (maxy - (y + dy)), fakt * (x + dx), fakt * (maxy - (y + dy)), width = wi, fill = col))
		# Vertikale Linien
		self.uids.append(
			canvas.create_line(fakt * x, fakt * (maxy - y), fakt * x, fakt * (maxy - (y + dy)), width = wi, fill = col))
		self.uids.append(
			canvas.create_line(fakt * (x + dx), fakt * (maxy - y), fakt * (x + dx), fakt * (maxy - (y + dy)), width = wi, fill = col))
	def doscale(self, scale):
		self.dx *= scale
		self.dy *= scale
		if self.dash > 0:
			self.dash *= scale
	def draw(self, x, y, maxy, canvas, scale = 1):
		if self.changed:
			self.bold = self.tkbold.get()
			val = self.tkpos.get()
			self.bmt = val / 10
			self.lmr = val % 10
			# Siehe Kommentar in change
			dashstyle = self.tkstyle.get()
			if dashstyle == -1: # Ohne Rahmen
				self.dash = -1
			elif dashstyle == 0: # Durchgezogen
				self.dash = 0
			else:
				try:
					if self.tkdashlen.get() <= 0:
						raise ValueError
					self.dash = self.tkdashlen.get() # gestrichelt
				except:
					self.tkdashlen.set(self.dash)
			self.changed = 0
		# Rand zeichnen
		if self.dash <= 0:
			self.drawfull(x, y, maxy, canvas, scale)
		else:
			self.drawdash(x, y, maxy, canvas, scale)
		dx = self.dx * scale
		dy = self.dy * scale
		# Text zeichnen
		an = ''
		xpos = x + dx/2
		ypos = y + dy/2
		if self.text != '':
			if self.bmt == 0:
				an += S
				if dy < 0:
					ypos = y + dy
				else:
					ypos = y
			elif self.bmt == 2:
				an += N
				if dy < 0:
					ypos = y
				else:
					ypos = y + dy
			if self.lmr == 0:
				an += W
				if dx < 0:
					xpos = x + dx
				else:
					xpos = x
			elif self.lmr == 2:
				an += E
				if dx < 0:
					xpos = x
				else:
					xpos = x + dx
			if an == '':
				an = CENTER
			self.uids.append(
				canvas.create_text(fakt * xpos, fakt * (maxy - ypos), text = "*TEXT*", anchor = an))
		return self.uids

class shortstackEx(picelEx):
	pass

class shortstack(picel):
	clickdepth = 1
	def dumptex(self):
		sf = '\\shortstack'
		sf += ['[l]{', '{', '[r]{'][self.lrc]
		sf += self.text + '}'
		return sf	
	def __init__(self, lrc, text):
		if lrc not in range(3):
			raise shortstackEx
		picel.__init__(self)
		self.text = text
		self.lrc = lrc
		self.changed = 0
	def dxdy(self, x, y):
		return x, y, x, y # Keine Ahnung betreffend die Größe von self.text
	def copy(self):
		return shortstack(self.lrc, self.text)
	def changecb2(self, a1, a2, a3):
		self.text = self.tktext.get()
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\\shortstack").grid(columnspan = 2)
		self.tktext = StringVar()
		Label(frame, text = PICELLABELTEXT[LANG]).grid(row = 1, column = 0)
		Entry(frame, textvariable = self.tktext).grid(row = 1, column = 1)
		self.tktext.set(self.text)
		self.tktext.trace("w", self.changecb2)

		self.tklrc = IntVar()
		Radiobutton(frame, text = SHORTSTACKLABELLEFT[LANG], variable = self.tklrc, value = 0, command = self.changecb).grid(sticky = W)
		Radiobutton(frame, text = SHORTSTACKLABELCENTERED[LANG], variable = self.tklrc, value = 1, command = self.changecb).grid(sticky = W)
		Radiobutton(frame, text = SHORTSTACKLABELRIGHT[LANG], variable = self.tklrc, value = 2, command = self.changecb).grid(sticky = W)
		self.tklrc.set(self.lrc)
	def doscale(self, scale):
		pass
	def draw(self, x, y, maxy, canvas, scale = 1):
		if self.changed:
			self.lrc = self.tklrc.get()
			self.changed = 0
		self.uids = []
		if self.lrc == 0:
			disptext = SHORTSTACKSHOWLEFT[LANG]
		elif self.lrc == 1:
			disptext = SHORTSTACKSHOWCENTERED[LANG]
		elif self.lrc == 2:
			disptext = SHORTSTACKSHOWRIGHT[LANG]
		self.uids.append(
			canvas.create_text(fakt * x, fakt * (maxy - y), text = disptext, anchor = S + W))
		return self.uids

class sizechanger: # Ändert dazu noch den Namen
	def __init__(self, root, sizex, sizey, name, names, changedcb):
		# Alte Werte; names: Liste der benutzten Namen; changedcb(x, y, name)
		self.sizex = sizex
		self.sizey = sizey
		self.name = name
		self.names = names
		self.changedcb = changedcb

		# Fenster erstellen
		self.tl = Toplevel(root)
		self.tl.title = 'Abmessungen'
		
		self.tkx = DoubleVar()
		self.tky = DoubleVar()
		self.tkname = StringVar()
		self.tkx.set(sizex)
		self.tky.set(sizey)
		self.tkname.set(name)
		Label(self.tl, text = SIZECHANGEX[LANG]).grid(row = 0, column = 0)
		Label(self.tl, text = SIZECHANGEY[LANG]).grid(row = 1, column = 0)
		Label(self.tl, text = SIZECHANGENAME[LANG]).grid(row = 2, column = 0)
		Entry(self.tl, textvariable = self.tkx).grid(row = 0, column = 1, sticky = E + W)
		Entry(self.tl, textvariable = self.tky).grid(row = 1, column = 1, sticky = E + W)
		Entry(self.tl, textvariable = self.tkname).grid(row = 2, column = 1, sticky = E + W)		
		Button(self.tl, command = self.apply, text = SIZECHANGEOK[LANG], state = ACTIVE).grid(row = 3, column = 0, columnspan = 2)
		self.tl.bind("<Return>", self.apply)
	def apply(self, event = None):
		xgot, ygot, namegot = self.tkx.get(), self.tky.get(), self.tkname.get()
		if xgot < 0:
			xgot = self.sizex
		if ygot < 0:
			ygot = self.sizey
		if namegot in self.names:
			namegot = self.name
		self.changedcb(xgot, ygot, namegot)
		self.tl.destroy()

class bb(picel):
	"Dicker Strich in Funktion eines ausgefüllten Rechtecks; Skalierungsfehler: Breite wird nie angepasst; richtige Darstellung (hoffentlich)"
	clickdepth = 2
	def dumptex(self, x, y, dx, dy, n): # Braucht auch die Informationen vom Putter, denn putter kommt links in der Mitte.
		py = y + self.dy / 2.0
		if self.dx < 0:
			px = self.dx + x
		else:
			px = x
		len = abs(self.dx)

		thickness = abs(self.dy)
		
		if n != 1:
			sf = '\\multiput' + `(px, py)` + `(dx, dy)` + '{' + `n` + '}{'
		else:
			sf = '\\put' + `(px, py)` + '{'

		sf += '\\linethickness{' + `thickness`+ '\unitlength}'
		sf += '\\line(1, 0){' + `len` + '} }'

		return sf
	def __init__(self, dx, dy):
		picel.__init__(self)
		self.dx = dx
		self.dy = dy
	def dxdy(self, x, y):
		if self.dx < 0:
			x1 = x + self.dx
			x2 = x
		else:
			x1 = x
			x2 = x + self.dx
		if self.dy < 0:
			y1 = y + self.dy
			y2 = y
		else:
			y1 = y
			y2 = y + self.dy
		return x1, y1, x2, y2
	def savestate(self):
		self.state = self.dx, self.dy
	def cancel(self):
		self.dx, self.dy = self.state
	def minfo(self, ox, oy, x, y): 
		self.dx = x - ox # Relative Position
		self.dy = y - oy
	def change(self, frame, tkcallredraw):
		Label(frame, text = "\\textwidth\\line").pack()		
	def copy(self):
		return bb(self.dx, self.dy)
	def doscale(self, scale): 
		self.dx *= scale
		self.dy *= scale
	def draw(self, x, y, maxy, canvas, scale = 1):
		boundbox = (fakt * (x),
			    fakt * (maxy - y),
			    fakt * (x + self.dx * scale),
			    fakt * (maxy - (y + self.dy * scale)))		
		return [canvas.create_rectangle(boundbox, fill = "BLACK")]

class objignorestatus:
	def status(sf):
		pass

class tkfiledummy: # simuliert die gebrauchte Funktionalität
	def __init__(self):
		self.size = (10, 10)
	def resize(self, newsizetup):
		self.size = newsizetup
	
class eps(picel):
	clickdepth = 2
	def dumptex(self):
		sf = "\includegraphics[width = " + `self.dx` + '\unitlength, height = ' + `self.dy` + "\unitlength]{" + self.filename + "}"
		return sf
	def loadfile(self, filename, statusobj):
		print "loadfile called"
		self.filename = filename
		try:
			self.tkfile = Image.open(filename)
		except:
			statusobj.status(EPSCANNOTOPEN[LANG])
			self.tkfile = tkfiledummy()
			return 0
		if self.tkfile.format != 'EPS':
			statusobj.status(EPSNOEPS[LANG])
			self.tkfile = tkfiledummy()
			return 0
		return 1
	def __init__(self, dx = 0, dy = 0, keepaspect = 1):
		picel.__init__(self)
		self.tkfile = tkfiledummy() # NOCH NICHT BENUTZEN!!! Loadfile aufrufen!
		self.dx = dx
		self.dy = dy
		self.keepaspect = keepaspect
		self.tkimagelist = [] # Photoimages brauchen zusätzliche Referenz. Bei putter.undraw() wird imagelist geleert.
		self.changed = 0
	def dxdy(self, x, y):
		return x, y, x + self.dx, y + self.dy
	def savestate(self):
		self.state = self.tkfile, self.dx, self.dy
	def cancel(self):
		self.tkfile, self.dx, self.dy = self.state
	def minfo(self, ox, oy, x, y):
		aspect = self.tkfile.size[0] / float(self.tkfile.size[1])
		dx = x - ox # Relative Position
		dy = y - oy
		if dx < 0:
			dx = 0
		if dy < 0:
			dy = 0
		if self.keepaspect: # Verhältnis Länge/Höhe beibehalten
			dx = aspect * dy
		self.dx, self.dy = dx, dy
	def changecb(self):
		self.changed = 1
		self.tkcallredraw()
	def change(self, frame, tkcallredraw):
		self.tkcallredraw = tkcallredraw
		Label(frame, text = "\epsfig").pack()
		Label(frame, text = EPSINSERTNOTE[LANG]).pack()
		self.tkkeepaspect = IntVar()
		self.tkkeepaspect.set(self.keepaspect)
		Checkbutton(frame, text = EPSASPECT[LANG], variable = self.tkkeepaspect, command = self.changecb).pack()
	def copy(self):
		neweps = eps(self.dx, self.dy, self.keepaspect)
		neweps.loadfile(self.filename, objignorestatus())
		return neweps
	def doscale(self, scale): 
		self.dx *= scale
		self.dy *= scale
	def undrawhook(self):
		self.tkimagelist = []
	def draw(self, x, y, maxy, canvas, scale = 1):
		if self.changed:
			self.keepaspect = self.tkkeepaspect.get()
			if self.keepaspect: # verzerrtes Bild richten, wenn Benutzer ausgeschalteten aspect wieder eingeschaltet hat.
				self.minfo(0, 0, self.dx, self.dy)
		width = self.dx * fakt * scale
		height = self.dy * fakt * scale
		if self.tkfile.__class__ != tkfiledummy:
			im = ImageTk.PhotoImage(image = self.tkfile.resize((width, height)) )
			self.tkimagelist.append(im)
			uid = canvas.create_image(fakt * x + width / 2, fakt * maxy - (fakt * y + height / 2), image = im)
			return [uid]
		else:
			boundbox = (fakt * (x),
				    fakt * (maxy - y),
				    fakt * (x + self.dx * scale),
				    fakt * (maxy - (y + self.dy * scale)))
			return [canvas.create_rectangle(boundbox),
				canvas.create_line(boundbox)]
