#Created by dan december 2011. www.danomagnum.com #from Tkinter import Tk, Frame, BOTH, RIGHT, LEFT, RAISED, Label, IntVar, BooleanVar, X, RAISED, Menu, Scrollbar,Y, Scrollbar, TclError, N, S from Tkinter import * #from ttk import Button, Style, Scale from ttk import Scale import ladder_tk import time import pickle import copy import tkFileDialog FORMATS = [('Python Ladder Logic','*.pll')] class AutoScrollbar(Scrollbar): # a scrollbar that hides itself if it's not needed. only # works if you use the grid geometry manager. def set(self, lo, hi): if float(lo) <= 0.0 and float(hi) >= 1.0: # grid_remove is currently missing from Tkinter! self.tk.call("grid", "remove", self) else: self.grid() Scrollbar.set(self, lo, hi) def pack(self, **kw): raise TclError, "cannot use pack with this widget" def place(self, **kw): raise TclError, "cannot use place with this widget" class MainWindow(Frame): def __init__(self, parent): Frame.__init__(self, parent, background="white") self.parent = parent self.rungs = [] self.exspeed = 100 self.paused = False self.initUI() self.updatesize = False self.calculating = False def initUI(self): #this sets up the interface, and then goes into the program part #self.parent.title("PyLadderLogic") #self.style = Style() #self.style.theme_use("default") #self.pack(fill=BOTH,expand=1) self.grid(row=0,column=0,sticky='news') ladder_tk.fix_scroll = self.scrollsizeupdate ladder_tk.remove_row = self.removerows #sc = Scrollbar(self) #sc.pack(side=RIGHT,fill=Y) topperfrm = Frame(self) topperfrm.pack(fill=X,expand=1) spdlbl = Label(topperfrm,text="Speed^-1") spdlbl.pack(side=LEFT) scale = Scale(topperfrm, from_=50, to=1000, command=self.onScale,value=100) scale.pack(side=LEFT) spdlbl = Button(topperfrm,text="Play/Pause",command=self.playpause) spdlbl.pack(side=RIGHT) button1 = Button(topperfrm,text="Run one loop",command=self.runone) button1.pack(side=RIGHT) button1 = Button(topperfrm,text="Update",command=self.toggleit) button1.pack(side=RIGHT) topfrm = Frame(self) topfrm.pack(fill=X,expand=1) self.popup = Menu(root,tearoff=0) self.popup.add_command(label='Add Rung',command=self.addrung) self.popup.add_command(label='Save',command=self.save) self.popup.add_command(label='Load',command=self.load) root.config(menu=self.popup) #this section defines the "bits" in the "plc" and a few 10-bit words I0 = ladder_tk.value_word(0,"I0:0") I0.bits_display_new(topfrm) self.I0 = I0.bits() self.I0[0].set(True) self.I0[1].set(True) self.I0[2].set(True) self.I0[6].set(True) ladder_tk.itemlist += self.I0 topfrm2 = Frame(self) topfrm2.pack(fill=X,expand=1) B0 = ladder_tk.value_word(0,"B0:0") B0.bits_display_new(topfrm2) self.B0 = B0.bits() ladder_tk.itemlist += self.B0 topfrm4 = Frame(self) topfrm4.pack(fill=X,expand=1) O0 = ladder_tk.value_word(0,"O0:0") O0.bits_display_new(topfrm4) self.O0 = O0.bits() ladder_tk.itemlist += self.O0 topfrm3 = Frame(self) topfrm3.pack(fill=X,expand=1) W0 = ladder_tk.value_word(0,"W0") W1 = ladder_tk.value_word(10,"W1") W2 = ladder_tk.value_word(1,"W2") W3 = ladder_tk.value_word(0,"W3") W4 = ladder_tk.value_word(0,"W4") W5 = ladder_tk.value_word(0,"W5") W6 = ladder_tk.value_word(0,"W6") self.Words = [W0,W1,W2,W3,W4,W5,W6] for w in self.Words: w.display_new(topfrm3) ladder_tk.itemlist += self.Words self.dataforms = [topfrm,topfrm2,topfrm4,topfrm3] def addrung(self): r = ladder_tk.rung() self.rungs.append(r) r.display_new(self) def toggleit(self): #this function is named this because I just kept reusing it, so no reason. #self.bv.set(random.randint(0,1023)) #print self.bv #self.bv.display_update() #self.blk1.display_update() #for r in self.rungs: #r.display_update() #self.update_idletasks() #canvas.config(scrollregion=canvas.bbox("all")) #print self.A0 self.removedata() def runone(self): #do one run through the ladder self.paused = True for r in self.rungs: r.run() r.display_update() def onScale(self, val): #set the speed speed = int(float(val)) self.exspeed = int(float(val)) def playpause(self): #toggle the play/pause self.paused = not self.paused def scrollsizeupdate(self): #print "test" #canvas.config(scrollregion=canvas.bbox("all")) self.updatesize=True def removerows(self,row): pausestate = self.paused self.paused = True while self.calculating: time.sleep(.1) self.rungs.remove(row) row.__del__() self.paused = pausestate def removedata(self): pausestate = self.paused self.paused = True while self.calculating: time.sleep(.1) self.I0 = None self.B0 = None self.O0 = None ladder_tk.itemlist = [] dfs = self.dataforms[:] for f in dfs: f.destroy() self.dataforms = [] self.paused = pausestate def save(self): filename = tkFileDialog.asksaveasfilename(parent=root,filetypes=FORMATS,title="Save") if not filename: return False pausestate = self.paused self.paused = True while self.calculating: time.sleep(.1) dfs = self.dataforms[:] #print dfs for f in dfs: f.destroy() #filename = "test.pll" f = open(filename,'w') output = self.rungs for o in output: o.pickleprepare() for i in self.I0: i.pickleprepare() for i in self.B0: i.pickleprepare() for i in self.O0: i.pickleprepare() for w in self.Words: w.pickleprepare() pickle.dump([output,self.I0,self.B0,self.O0,self.Words],f) f.close() #for o in output: #self.removerows(o) #self.load(filename=filename) self.dataforms = [] self.reinit() self.paused = pausestate def load(self): filename = tkFileDialog.askopenfilename(parent=root,filetypes=FORMATS,title="Save") if not filename: return False rows = self.rungs[:] for r in rows: self.removerows(r) self.removedata() f = open(filename,'r') [self.rungs,self.I0,self.B0,self.O0,self.Words] = pickle.load(f) f.close() self.reinit() self.updatesize=True def reinit(self): for rung in self.rungs: rung.postpickle() for item in self.I0: item.postpickle() for item in self.B0: item.postpickle() for item in self.O0: item.postpickle() for item in self.Words: item.postpickle() ladder_tk.itemlist = [] topfrm = Frame(self) topfrm.pack(fill=X,expand=1) for i in self.I0: i.display_new(topfrm) ladder_tk.itemlist += self.I0 self.dataforms.append(topfrm) topfrm = Frame(self) topfrm.pack(fill=X,expand=1) for i in self.B0: i.display_new(topfrm) ladder_tk.itemlist += self.B0 self.dataforms.append(topfrm) topfrm = Frame(self) topfrm.pack(fill=X,expand=1) for i in self.O0: i.display_new(topfrm) ladder_tk.itemlist += self.O0 self.dataforms.append(topfrm) topfrm = Frame(self) topfrm.pack(fill=X,expand=1) for i in self.Words: i.display_new(topfrm) ladder_tk.itemlist += self.Words self.dataforms.append(topfrm) for r in self.rungs: r.display_new(self) r.display_update() def calculatron(*args): #this is what automatically executes the logic at whatever interval is set app = args[0] if not app.paused: app.calculating = True for r in app.rungs: r.run() r.display_update() app.calculating = False root.after(app.exspeed,calculatron,app) def scrollbarupdate(*args): app = args[0] if app.updatesize: canvas.config(scrollregion=canvas.bbox("all")) app.updatesize = False root.after(100,scrollbarupdate,app) def OnMouseWheel(event): d = 0 if event.num == 5 or event.delta == -120: d = 1 elif event.num == 4 or event.delta == 120: d = -1 canvas.yview("scroll", d, "units") root = Tk() vscrollbar = AutoScrollbar(root) vscrollbar.grid(row=0,column=1, sticky=N+S) hscrollbar = AutoScrollbar(root, orient=HORIZONTAL) hscrollbar.grid(row=1, column=0, sticky=E+W) canvas = Canvas(root, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set,width=1000,height=300) canvas.grid(row=0, column=0, sticky=N+S+E+W) root.bind('', OnMouseWheel) root.bind('', OnMouseWheel) root.bind('', OnMouseWheel) vscrollbar.config(command=canvas.yview) hscrollbar.config(command=canvas.xview) root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0,weight=1) frame = Frame(canvas) frame.rowconfigure(1, weight=1) frame.columnconfigure(1,weight=1) #rows = 5 #for i in range(1,rows): #for j in range(1,10): #button = Button(frame, padx=7, pady=7, text="[%d,%d]" % (i,j)) #button.grid(row=i, column=j, sticky='news') app = MainWindow(frame) canvas.create_window(0, 0, anchor=NW, window=frame) frame.update_idletasks() canvas.config(scrollregion=canvas.bbox("all")) app.update_idletasks() root.after(100,calculatron,app) root.after(100,scrollbarupdate,app) root.mainloop()