# 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)]