# 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 tkSimpleDialog
import tkFileDialog
import tkMessageBox
from internat import *
from config import *
from globalpars import *
from picels import *
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]
self.selected = [] # Nix angew�hlt
self.parts = pcs() # Noch keine Teilbilder
self.tkclass = IntVar() # F�r die Auswahl der blockerten
self.tkclass.set(-1)
self.tkchangeclass = IntVar() # ... und unblockierten Teilbilder in picmenu
self.tkchangeclass.set(0)
self.root.title(PROGNAME)
helperwin = Toplevel(self.root)
helperwin.transient(self.root)
helperwin.protocol('WM_DELETE_WINDOW', self.donothing)
self.helperwin = helperwin
helperwin.title(CHANGEWINTITLE[LANG])
self.changeframe = Frame(helperwin) # Frame f�r weitere Operationen
self.changeframe.pack(fill = BOTH, expand = 1) # Ist hier nur, damit es zerst�rt werden kann. Das eigentlich wichtige wird in .editwin getan.
Label(self.changeframe, text = STATUSNOSELECTION[LANG]).pack()
self.picmenu = Menu(postcommand = self.updatepicmenu, tearoff = 0) # Abrei�en gibt bei diesem Men� heftig �rger
self.viewpicture(picc)
# Funktionsweise des Callbackwaldes:
# die new...-Funktionen erstellen das gefragte Objekt und stellen Fest, ob
# ein, zwei oder drei Punkte gefordert sind (mousinputdepth).
# Daraufhin rufen sie eine Funktion auf, die einen (ebenfalls leeren) putter darum erstellt.
# Der erste Klick f�llt in clickcb diese Putterstruktur.
# Sind mehr Punkte n�tig, werden die Mausbewegungen in motion abgefangen und das picel �ber
# seines putters minfo-Routine �ber die Position der Maus informiert.
# Nach dieser Information wird die Anzeige aufgefrischt.
# Bei Tiefe 3 wird dann noch clickcb2 ausgef�hrt, der motion so �ndert, dass minfo2 aufgerufen wird.
# Sind alle Informationen aufgerufen, folgt done und ein self.update().
menu = Menu(self.root)
self.root["menu"] = menu
menu.add_cascade(label = MENUCLASSES[LANG], menu = self.picmenu)
menu.add_cascade(label = MENUFILE[LANG], menu = filemenu)
menu.add_cascade(label = MENUNEW[LANG], menu = newmenu)
menu.add_cascade(label = MENUDISPLAY[LANG], menu = faktmenu)
menu.add_cascade(label = MENUELEM[LANG], menu = selmenu)
menu.add_cascade(label = MENUCLIP[LANG], menu = clipmenu)
# Ist gerade kein Men� vorhanden, soll ein linker Mausklick das Bearbeitungsfenster �ffnen
self.canvas.bind("<Button-1>", self.editwin)
self.frameuid = None
self.griduids = []
def filemenu_load(self, event = None):
self.changeframe.destroy()
ft = [(FTLABEL[LANG], "*.pic")]
filename = tkFileDialog.askopenfilename(title = LOADTITLE[LANG], filetypes = ft)
if filename == '':
return
try:
f = open(filename)
self.parts = pickle.load(f)
for picclass in self.parts.pictures: # F�r alle Putter, die gerade geladen werden diese Information bereit stellen.
for putter in picclass.putters:
putter.notifyunpickle(self)
f.close()
self.viewpicture(self.parts.pictures[0])
self.changeframe.destroy()
self.update()
except:
tkMessageBox.showerror(title = PROGNAME, message = LOADERROR[LANG] + `sys.exc_info()[0]`)
traceback.print_tb(sys.exc_info()[2])
def filemenu_save(self, event = None):
ft = [(FTLABEL[LANG], "*.pic")]
filename = tkFileDialog.asksaveasfilename(title = SAVETITLE[LANG], filetypes = ft, defaultextension = '.pic')
if filename == '':
return
try:
f = open(filename, "w")
for pc in self.parts.pictures: # Unpickelbare tk-Variablen vernichten
pc.untk()
pickle.dump(self.parts, f)
for picclass in self.parts.pictures: # F�r alle Putter, die gerade geladen werden: diese Information bereit stellen.
for putter in picclass.putters:
putter.notifypickle(self)
f.close()
except:
tkMessageBox.showerror(title = PROGNAME, message = SAVEERROR[LANG] + `sys.exc_info()[0]`)
traceback.print_tb(sys.exc_info()[2])
def filemenu_import(self, event = None): # fast wie load
self.changeframe.destroy()
ft = [(FTLABEL[LANG], "*.pic")]
filename = tkFileDialog.askopenfilename(title = INSERTTITLE[LANG], filetypes = ft)
if filename == '':
return
try:
f = open(filename)
newparts = pickle.load(f)
f.close()
for newname in newparts.names:
if newname in self.parts.names:
self.status(STATUSNAMECOL[LANG])
return
# Keine �berschneidungen
for picclass in newparts.pictures: # F�r alle Putter, die gerade geladen werden: diese Information bereit stellen.
for putter in picclass.putters:
putter.notifypickle(self)
self.parts.pictures += newparts.pictures
self.parts.names += newparts.names
except:
tkMessageBox.showerror(title = PROGNAME, message = LOADERROR[LANG] + `sys.exc_info()[0]`)
traceback.print_tb(sys.exc_info()[2])
def filemenu_export(self, event = None):
z = 0
for z in range(len(self.parts.names)):
f = open(self.parts.names[z] + SUFFIX, 'w')
f.write(self.parts.pictures[z].dumptex())
def filemenu_quit(self, event = None):
self.root.destroy()
def faktmenu_change(self, event = None):
global fakt
fakt = self.tkfakt.get()
notifyfaktchange(fakt)
self.update()
def faktmenu_gridf(self, event = None):
global FGRID
FGRID = self.tkfGrid.get()
self.update()
def faktmenu_gridfkey(self, event = None):
self.tkfGrid.set(not self.tkfGrid.get())
self.faktmenu_gridf()
def faktmenu_grid(self, event = None):
global GRID
g = tkSimpleDialog.askfloat(PROGNAME, LABELNEWGRID[LANG], minvalue = 0.0000001)
if g != None:
GRID = g
self.update()
def picmenu_addmenus(self, menu, block): # H�ngt an menu Radiobuttons an, m�glicherweise enthaltende blockiert, oder auch nicht.
if block:
blocks = self.parts.pictures[0].getallblocks(self.pic.pc) + [self.pic.pc]
for z in range(len(self.parts.pictures)):
sf = self.parts.names[z]
if block:
if self.parts.pictures[z] in blocks:
menu.add_radiobutton(label = sf, state = DISABLED, variable = self.tkclass, value = z)
else:
menu.add_radiobutton(label = sf, state = NORMAL, variable = self.tkclass, value = z)
else:
menu.add_radiobutton(label = sf, variable = self.tkchangeclass, value = z, command = self.picmenu_changepc)
def updatepicmenu(self):
self.picmenu.delete(0, 99999) # Das ist unsch�n!
self.picmenu.add_cascade(label = MENUCHANGECLASS[LANG], menu = changemenu)
def picmenu_getclass(self, nr = 0): # Liest tkclass aus und gibt Fehlermeldung und None bzw. Klasse
blocks = rootpc.getallblocks(self.pic.pc) + [self.pic.pc]
classnr = self.tkclass.get()
if classnr == -1:
self.status(STATUSNOCLASSEL[LANG])
return None
elif self.parts.pictures[classnr] in blocks:
self.status(STATUSBLOCKED[LANG])
return None
else:
if nr: # Nutzer der Klasse w�hlt, ob er Nummer oder Instanz braucht
return classnr
else:
return self.parts.pictures[classnr]
def picmenu_newpicture(self, event = None):
picclass = self.picmenu_getclass()
if picclass == None:
return
self.pendingpicel = picture(picclass, 1.0, self.pic.pc)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def picmenu_delpc(self, event = None):
nr = self.picmenu_getclass(nr = 1)
if nr == None:
return
picclass = self.parts.pictures[nr]
if picclass == None:
return
blocks = self.parts.pictures[0].getallblocks(self.parts.pictures[nr]) # Klassen bestimmen, in deren Instanzen die Klasse enthalten ist.
if blocks != [] or nr == 0: # L�schbar ist er nur, wenn nirgendwo Instanzen lungern und es nicht das Hauptbild ist.
self.status(STATUSDELCLASSREJECT[LANG])
return
del self.parts[nr]
def picmenu_changepc(self, event = None):
pc = self.parts.pictures[self.tkchangeclass.get()]
self.viewpicture(pc)
self.changeframe.destroy()
self.update()
def picmenu_changesize(self, event = None): # Fenster zur Gr��en�nderung
sc = sizechanger(self.root, self.pic.pc.xsize, self.pic.pc.ysize, self.pic.pc.name, self.parts.names, self.picmenu_sccb)
def picmenu_sccb(self, xs, ys, name):
self.pic.pc.xsize = xs
self.pic.pc.ysize = ys
self.parts.changename(self.pic.pc.name, name) # in parts und pc �ndern
self.canvas.delete(self.frameuid)
self.frameuid = self.canvas.create_rectangle(0, fakt * self.pic.pc.ysize, fakt * self.pic.pc.xsize, 0, fill = None, outline = PICFRAMECOL)
self.update()
def picmenu_adjustdxdy(self, event = None):
self.pic.pc.adjustdxdy()
self.update()
# ENDE picmenu
def clip_copy(self, event = None):
#def createpicwork(self, newpicclass, action):
# action: 0: Instanz einf�gen; action 1: Einzelelemente lassen; action 2: Einzelemente nur verschwinden lassen
self.clipboard = pictureclass(0, 0, CLIPBOARDNAME)
self.createpicwork(self.clipboard, 1)
self.update()
def clip_cut(self, event = None):
self.clipboard = pictureclass(0, 0, CLIPBOARDNAME)
self.createpicwork(self.clipboard, 2)
self.update()
def clip_paste(self, event = None):
self.pendingpicel = picture(self.clipboard, 1.0, self.pic.pc)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel() # done k�mmert sich um die Aufl�sung in Einzelelemente
# ENDE clip
def viewpicture(self, picc):
self.tkclass.set(-1) # Danach ist die angeklickte Klasse mgl. blockiert
try:
self.pic.undraw(self.canvas)
except AttributeError:
pass # Falls pic noch nicht existiert
self.pic = picture(picc, 1.0, None)
def donothing(self): # Um das Nebenfenster zu erhalten
pass
def drawgrid(self):
self.griduids = []
xanz = int(self.pic.pc.xsize / GRID)
yanz = int(self.pic.pc.ysize / GRID)
if xanz != 0:
xstep = self.pic.pc.xsize / float(xanz)
if yanz != 0:
ystep = self.pic.pc.ysize / float(yanz)
for z in range(xanz):
self.griduids.append(self.canvas.create_line(fakt * (z * xstep),
fakt * (self.pic.pc.ysize - 0),
fakt * (z * xstep),
0, # fakt * (ysize - ysize)
fill = GRIDCOL))
for z in range(yanz):
self.griduids.append(self.canvas.create_line(0,
fakt * (self.pic.pc.ysize - z * ystep),
fakt * self.pic.pc.xsize,
fakt * (self.pic.pc.ysize - z * ystep),
fill = GRIDCOL))
for uid in self.griduids:
self.canvas.lower(uid)
def undrawgrid(self):
for uid in self.griduids:
self.canvas.delete(uid)
def update(self):
# Rahmen und Netz und Bild entfernen (falls vorhanden)
if self.frameuid != None:
self.canvas.delete(self.frameuid)
self.undrawgrid()
self.pic.undraw(self.canvas)
if FGRID:
self.drawgrid()
self.frameuid = self.canvas.create_rectangle(0, fakt * self.pic.pc.ysize, fakt * self.pic.pc.xsize, 0, fill = None, outline = PICFRAMECOL) # Rahmen
self.pic.draw(0, 0, self.pic.pc.ysize, self.canvas) # Bild
self.canvas['scrollregion'] = self.canvas.bbox(ALL) # Scrollleisten einstellen
self.selected = [] # mgl. Auswahl angezeigt l�schen, Anzeige ist schon weg (Bilder aufl�sen k�nnte �rger geben beim weiter halten)
def status(self, text):
self.statuslabel['text'] = text
def editwin(self, event): # Dem Mausklick n�chste Uid suchen, putter holen und aufrufen
x = event.widget.canvasx(event.x)
y = event.widget.canvasy(event.y)
if FGRID: # Das Netz st�rt bei find-closest
self.undrawgrid()
uid = event.widget.find_closest(x, y)[0]
if FGRID:
self.drawgrid()
putter = self.pic.getputter(uid)
# Putter == 0: Rahmen wurde angeklickt:
if putter == 0:
return
self.editwin2(putter)
def editwin2(self, putter): # wird von putter und done (Objekt erzeugt) aufgerufen
self.changeframe.destroy()
self.changeframe = Frame(self.helperwin)
self.changeframe.pack(fill = BOTH, expand = 1)
putter.change(self.changeframe, self)
def bindings(self, done, cancel):
self.canvas.bind("<Motion>", self.motion)
self.canvas.bind("<Button-1>", done)
self.canvas.bind("<Button-3>", cancel)
self.movecb_uids = []
def unbind(self):
self.canvas.bind("<Button-1>", self.editwin) # Zur�ckbinden
self.canvas.unbind("<Motion>")
self.canvas.unbind("<Button-3>")
def motion(self, event):
self.pendingputter.undraw(self.canvas)
x = round(self.canvas.canvasx(event.x) / float(fakt * GRID)) * GRID
y = self.pic.pc.ysize - round(self.canvas.canvasy(event.y) / float(fakt * GRID)) * GRID
if self.motionmode == 0:
self.pendingputter.x = x
self.pendingputter.y = y
elif self.motionmode == 1:
self.pendingputter.minfo(x, y) # Information �bertragen
elif self.motionmode == 2:
self.pendingputter.minfo2(x, y) # Falls drei Mausklicks n�tig sein sollten ...
self.pendingputter.draw(0, 0, self.pic.pc.ysize, self.canvas) # neu zeichnen
def cancel(self, event):
self.unbind()
self.status(STATUSCANCEL[LANG])
self.pendingputter.undraw(self.canvas)
del self.pendingpicel
del self.pendingputter
def done(self, event):
if self.mouseinputdepth == 1:
self.pendingputter.x = round(self.canvas.canvasx(event.x) / float(fakt * GRID)) * GRID
self.pendingputter.y = self.pic.pc.ysize - round(self.canvas.canvasy(event.y) / float(fakt * GRID)) * GRID
self.unbind()
self.status(STATUSDONE[LANG])
self.pic.putters.append(self.pendingputter) # Erstelltes Objekt einf�gen sowie hiesige Referenz entfernen
if not(self.pendingputter.pe.__class__ == picture and self.pendingputter.pe.pc.name == CLIPBOARDNAME):
self.editwin2(self.pendingputter) # Aufl�ser!
self.update() # UIDs auffrischen
def clickcb(self, event):
# Putter mit richtigen Anfangskoordinaten versorgen
self.pendingputter.x = round(self.canvas.canvasx(event.x) / float(fakt * GRID)) * GRID
self.pendingputter.y = self.pic.pc.ysize - round(self.canvas.canvasy(event.y) / float(fakt * GRID)) * GRID
self.status(STATUSPOINT2[LANG])
if self.mouseinputdepth == 2:
self.bindings(self.done, self.cancel) # done, cancel und motion aktivieren
elif self.mouseinputdepth == 3:
self.bindings(self.clickcb2, self.cancel)
elif self.mouseinputdepth == 200:
self.bindings(self.getuids2, self.cancel)
self.motionmode = 1
def clickcb2(self, event):
self.status(STATUSPOINT3[LANG])
if self.mouseinputdepth == 3:
self.bindings(self.done, self.cancel)
self.motionmode = 2
def newpicel(self, event = None):
self.pendingputter = multiputter(0, 0, 0, 0, 1, self.pendingpicel)
self.status(STATUSPOINT1[LANG])
self.motionmode = 0
if self.mouseinputdepth > 1:
self.bindings(self.clickcb, self.cancel)
else:
self.bindings(self.done, self.cancel)
def newline(self, event = None):
self.pendingpicel = line(1, 1, 1, 0)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newvec(self, event = None):
self.pendingpicel = line(1, 1, 1, 1)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newcircleas(self, event = None):
self.pendingpicel = circle(1, 1)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newcircle(self, event = None):
self.pendingpicel = circle(1, 0)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newoval(self, event = None):
self.pendingpicel = oval(3, 2)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newbezier(self, event = None):
self.pendingpicel = bezier(0, 0, 1, 1, 2, 1)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newbb(self, event = None):
self.pendingpicel = bb(2, 2)
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def neweps(self, event = None):
self.pendingpicel = eps()
ft = [(FTLABEL[LANG], "*.eps")]
filename = tkFileDialog.askopenfilename(title = EPSLOADTITLE[LANG], filetypes = ft)
if FPIL:
if not self.pendingpicel.loadfile(filename, self):
del self.pendingpicel
return
else:
self.pendingpicel.filename = filename
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newsimpletext(self, event = None):
self.pendingpicel = simpletext(INITIALSIMPLETEXT[LANG])
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newshortstack(self, event = None):
self.pendingpicel = shortstack(1, INITIALSHORTSTACK[LANG])
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def newtextbox(self, event = None):
self.pendingpicel = textbox(0, 0, 1, 1, DEFAULTDASHLEN, '')
self.mouseinputdepth = self.pendingpicel.clickdepth
self.newpicel()
def getuids(self, event = None):
self.pendingpicel = textbox(0, 0, 1, 1, 0, INITIALTEXTBOX[LANG])
self.mouseinputdepth = 200
self.newpicel()
# Unsch�n (200): Teilt den Nachfolgenden Prozeduren mit, dass hier eigentlich nur die Anzeigeroutinen der Textbox benutzt werden, aber nur deren Koordinaten interessieren. Damit werden dann in einer ver�nderten Version von done die richtigen Koordinaten gesichert.
def getuids2(self, event): # Genau hierhin. self.pendingpicel d�rfte nun die gew�nschten Daten enthalten
self.update() # Eine einfache undraw-Routine scheitert daran, dass fill unterschiedliche Werte anfangs hat.
# Koordinaten ausrechnen
self.pendingputter.undraw(self.canvas) # Die uids l�schen, die zum gezogenen Rahmen geh�ren, sp�ter wird er auch gel�scht.
x = fakt * self.pendingputter.x
y = fakt * (self.pic.pc.ysize - self.pendingputter.y)
x2 = fakt * self.pendingpicel.dx + x
y2 = fakt * (self.pic.pc.ysize - (self.pendingputter.y + self.pendingpicel.dy))
uids = self.canvas.find_overlapping(x, y, x2, y2)
uids = list(uids) # find liefert tupel
putters = []
for uid in uids:
for putter in self.pic.putters:
if uid in putter.uids and putter not in putters:
putters.append(putter)
self.selected = putters
self.unbind()
self.select()
def select(self): # Auswahl anzeigen
for putter in self.selected:
putter.mark(self.canvas)
def clearselect(self, event = None): # Auswahl l�schen
self.selected = []
self.status(STATUSDESELECT[LANG])
self.update()
def delselected(self, event = None, update = 1): # AusGEW�HLTE l�schen
for putter in self.selected:
putter.undraw(self.canvas)
index = self.pic.putters.index(putter)
del self.pic.putters[index]
if update:
self.status(STATUSELSDELETED[LANG])
self.update()
def createpic(self):
if self.selected != []:
# Namen abfragen und �berpr�fen
name = tkSimpleDialog.askstring(PROGNAME, LABELNEWCLASSNAME[LANG])
if name == None or not(self.parts.newname(name)) or name == "":
self.status(STATUSINVALIDNAME[LANG])
return
pc = pictureclass(0, 0, name)
self.createpicwork(pc, 0)
self.update()
self.parts.append(pc)
self.status(STATUSNEWCLASS[LANG])
else:
self.status(STATUSNOSELECTION[LANG])
def createpicwork(self, newpicclass, action):
# action: 0: Instanz einf�gen; action 1: Einzelelemente lassen; action 2: Einzelemente nur verschwinden lassen
if self.selected != []:
x1, y1, x2, y2 = plboundingbox(self.selected)
dx = x2 - x1
dy = y2 - y1
newpicclass.xsize, newpicclass.ysize = dx, dy
# Alle putter bewegen
for putter in self.selected:
putter.x -= x1
putter.y -= y1
# Neue Bildklasse damit f�llen
if action != 1:
newpicclass.putters = self.selected
else: # F�r Kopieren brauchen wir eine hier und eine Unabh�ngige in der Zwischenablage
for el in self.selected:
elcopy = el.copy()
el.x += x1
el.y += y1
newpicclass.putters.append(elcopy)
self.pic.undraw(self.canvas) # alle Canvasitems entfernen (Referenz k�nnte verschwinden)
if action != 1:
self.delselected(update = 0) # ... jetzt
if action == 0:
self.pic.putters.append( # Anstelle dessen kommte nur ein putter f�r das neu erstellte Objekt der neuen Klasse
multiputter(x1, y1, 0, 0, 1, picture(newpicclass, 1.0, self.pic.pc))
)
self.changeframe.destroy()
class multiputter: # Steht f�r einen multiput-Befehl
def dumptex(self):
if self.pe.__class__ in [textbox, bb]: # Dieser macht das selbst, da LaTeX nicht mit negativen H�hen und Breiten rechnet.
return self.pe.dumptex(self.x, self.y, self.dx, self.dy, self.n)
else:
if self.n != 1:
sf = '\\multiput' + `(self.x, self.y)` + `(self.dx, self.dy)` + '{' + `self.n` + '}{'
else:
sf = '\\put' + `(self.x, self.y)` + '{'
sf += self.pe.dumptex() + '}'
return sf
def __init__(self, x, y, dx, dy, n, pe):
"dx, dy - jew. Verschiebung beim n-ten Anzeigen"
self.x = x
self.y = y
self.pe = pe
self.dx = dx
self.dy = dy
self.n = n
self.multiput = 1
self.uids = []
def mark(self, canvas):
for uid in self.uids:
type = canvas.type(uid)
if type in ['arc', 'oval']:
canvas.itemconfigure(uid, outline = SELECTCOL)
elif type == 'image':
pass
else:
canvas.itemconfigure(uid, fill = SELECTCOL)
def draw(self, x, y, maxy, canvas, scale = 1): # Element mehrfach zeichnen
# Ist firstcall gesetzt, werden x- und y-Position nicht skaliert, aber scale �bergeben.
# F�r den ersten Aufruf aus einem picture
self.uids = []
for z in range(self.n):
self.uids += self.pe.draw(
scale * (self.x + z * self.dx + x),
scale * (self.y + z * self.dy + y),
scale * maxy, canvas, scale)
return self.uids
def undraw(self, canvas):
self.pe.undrawhook()
for uid in self.uids:
canvas.delete(uid)
self.uids = []
def minfo(self, x, y): # Leitet nur weiter
self.pe.minfo(self.x, self.y, x, y)
def minfo2(self, x, y):
self.pe.minfo2(self.x, self.y, x, y)
def dxdy(self): # Liefert Abmessungen des multiput in LaTeX-Koordinaten
x1, y1, x2, y2 = self.pe.dxdy(self.x, self.y)
if self.dx > 0:
x2 += (self.n - 1) * self.dx
else:
x1 += (self.n - 1) * self.dx
if self.dy > 0:
y2 += (self.n - 1) * self.dy
else:
y1 += (self.n - 1) * self.dy
return x1, y1, x2, y2
# moveput, click2 und click3 nutzen vom mainwindow die Routinen in motionmode 0 bis 2
def click2(self):
self.pe.savestate()
p = self.tkparent
p.motionmode = 1
p.pendingputter = self
p.bindings(self.done, self.c23cancel)
def click3(self):
self.pe.savestate()
p = self.tkparent
p.motionmode = 2
p.pendingputter = self
p.bindings(self.done, self.c23cancel)
def c23cancel(self, event):
self.pe.cancel()
self.cancel()
def moveput(self):
p = self.tkparent
p.motionmode = 0
self.cancelx = self.x
self.cancely = self.y
p.bindings(self.done, self.mpcancel)
p.pendingputter = self
def mpcancel(self, event):
self.x = self.cancelx
self.y = self.cancely
self.cancel()
def cancel(self):
self.tkparent.status(STATUSCANCEL[LANG])
del self.tkparent.pendingputter
self.tkparent.unbind()
self.tkparent.update()
def done(self, event):
self.tkparent.status(STATUSDONE[LANG])
del self.tkparent.pendingputter
self.tkparent.unbind()
def capply(self, event): # Eingegebene Felder lesen und fehlerpr�fen
try:
self.dx = self.tkdx.get()
except ValueError:
self.tkdx.set(self.dx)
try:
self.dy = self.tkdy.get()
except ValueError:
self.tkdy.set(self.dy)
try:
if self.tkn.get() < 1:
raise ValueError
self.n = self.tkn.get()
if self.n == 1:
self.tkBMultiAuf['state'] = DISABLED
else:
self.tkBMultiAuf['state'] = NORMAL
except ValueError:
self.tkn.set(self.n)
self.tkcallredraw()
def change(self, frame, parent):
# Multifelder anzeigen
self.tkframe = frame # Speichern f�r die Aufl�sebefehle
self.tkparent = parent
self.tkcallredraw = parent.update
Label(frame, text = '\[multi]put').grid(row = 0, column = 0, columnspan = 2)
Label(frame, text = MULTIDX[LANG]).grid(row = 1, column = 0)
Label(frame, text = MULTIDY[LANG]).grid(row = 2, column = 0)
Label(frame, text = MULTIN[LANG]).grid(row = 3, column = 0)
# Punktfelder nach picel anzeigen
Button(frame, text = MULTISETROOT[LANG], command = self.moveput).grid(row = 4, columnspan = 2, sticky = E + W)
if self.pe.clickdepth > 1:
Button(frame, text = MULTISETP2[LANG], command = self.click2).grid(row = 5, columnspan = 2, sticky = E + W)
if self.pe.clickdepth > 2:
Button(frame, text = MULTISETP3[LANG], command = self.click3).grid(row = 6, columnspan = 2, sticky = E + W)
self.tkBMultiAuf = Button(frame, text = MULTIUNMULTI[LANG], state = [NORMAL, DISABLED][self.n == 1], command = self.cbMultiAuf)
self.tkBMultiAuf.grid(row = 7, column = 0, sticky = E + W)
if self.pe.__class__ == picture:
Button(frame, text = MULTIUNPIC[LANG], command = self.cbPicAuf).grid(row = 7, column = 1, sticky = E + W)
# picel auffordern, sein Konfigurationsfenster anzuzeigen
peframe = Frame(frame, width = 100, height = 100, borderwidth = 2, relief = RIDGE)
peframe.grid(sticky = N + S + W + E, columnspan = 2)
self.pe.change(peframe, self.tkcallredraw)
def copy(self):
return multiputter(self.x, self.y, self.dx, self.dy, self.n, self.pe.copy())
def cbMultiAuf(self): # Multiputter in viele putter aufl�sen
# Referenz zum enthaltenden Bild holen
putters = self.tkparent.pic.pc.putters # pic ist eigentlich nicht n�tig
# Neue Putter f�r n - 1 erstellen und sich selbst zur�ckstufen
for z in range(1, self.n):
pecopy = self.pe.copy()
newputter = multiputter(self.x + z * self.dx, self.y + z * self.dy, 0, 0, 1, pecopy)
putters.append(newputter)
self.dx = 0
self.dy = 0
self.n = 1
# �nderungen anzeigen
self.tkparent.update()
self.tkframe.destroy()
def cbPicAuf(self):
self.undraw(self.tkparent.canvas)
# Referenz zum enthaltenden Bild holen
putters = self.tkparent.pic.pc.putters # pic ist eigentlich nicht n�tig
# Alle Bildelemente aus Klasse duplizieren und direkt in die enthaltende Klasse einf�gen
for z in range(self.n):
for putter in self.pe.pc.putters:
pecopy = putter.pe.copy()
pecopy.doscale(self.pe.scale)
newputter = multiputter(self.pe.scale * (putter.x + self.dx * z) + self.x,
self.pe.scale * (putter.y + self.dy * z) + self.y,
self.pe.scale * putter.dx,
self.pe.scale * putter.dy,
putter.n, pecopy)
putters.append(newputter)
del putters[putters.index(self)] # Die Instanz entfernt den letzten Bezug auf sich selbst.
# �nderungen anzeigen
self.tkparent.update()
if self.__dict__.has_key("tkframe"):
self.tkframe.destroy()
def notifydone(self, parent):
self.tkparent = parent
if self.pe.__class__ == picture and self.pe.pc.name == CLIPBOARDNAME:
self.cbPicAuf()
def notifyunpickle(self, parent): # Dies wird f�r jedes frisch entpickelte Element aufgerufen.
if self.pe.__class__ == eps:
self.pe.loadfile(self.pe.filename, parent)
def notifypickle(self, parent): # Dies wird f�r jedes frisch gepickelte Element aufgerufen.
if self.pe.__class__ == eps:
self.pe.loadfile(self.pe.filename, parent)
parent.update()
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