#Created by dan december 2011. www.danomagnum.com #from ttk import Label, Button#, Checkbutton, Style from Tkinter import StringVar, LEFT, RIGHT, BOTH, Frame, X, RAISED, IntVar, Menu, Checkbutton, Y, BooleanVar, Label, Button import tkMessageBox import tkSimpleDialog import block_functions import ladder TRUECOLOR = "green" FALSECOLOR = "red" FAULTCOLOR = "yellow" LATCHCOLOR = "blue" DEFAULTCOLOR = "black" fix_scroll = lambda x:x remove_row = lambda x:x functionlist = block_functions.BLOCK_FUNCTION_LIST itemlist = [] #need to fill this in to add stuff I guess class IO(ladder.IO): def __init__(self,value,name,typedesc,input=False,description=""): super(IO,self).__init__(value,name,typedesc,input,description) self.displayvariable = StringVar() if self.typedesc == 'bool': self.displayvalue = BooleanVar() elif self.typedesc == 'int': self.displayvalue = IntVar() else: self.displayvalue = StringVar() self.display = [] def prompt_for_value(self): if self.typedesc == 'int': result = tkSimpleDialog.askinteger(self.name,self.name,initialvalue=self.value,minvalue=0,maxvalue=1023) if result is not None: self.set(result) self.display_update() def delifparent(self,parent): displays = self.display[:] for d in displays: if d.master == parent: #I am a child of you, so I wll delete myself self.display.remove(d) d.destroy() if not self.display: del(self) def latchon(self): super(IO,self).latchon() self.display_update() def latchoff(self): super(IO,self).latchoff() self.display_update() def unlatch(self): super(IO,self).unlatch() self.display_update() def clicked(self): #super(IO,self).clicked() self.toggle_and_display() def toggle_and_display(self): self.toggle() self.display_update() def display_new(self,parent): self.display_update() b = Checkbutton(parent,textvariable=self.displayvariable,command=self.clicked,variable=self.displayvalue,indicatoron=0) b.pack(side=LEFT) self.display.append(b) self.popup = Menu(parent,tearoff=0) self.popup.add_command(label="force on",command=self.latchon) self.popup.add_command(label="force off",command=self.latchoff) self.popup.add_command(label="remove force",command=self.unlatch) self.popup.add_separator() self.popup.add_command(label="properties",command=self.properties_display) self.popup.add_command(label="Set",command=self.prompt_for_value) self.popup.add_command(label="description",command=self.setdesc) b.bind("",self.popup_menu) return b def popup_menu(self,event): try: self.popup.tk_popup(event.x_root,event.y_root,0) finally: self.popup.grab_release() def properties_display(self): ds = self.properties() tkMessageBox.showinfo(self.name,ds) def display_update(self): if self.display: for d in self.display: if self.latched: d.configure(foreground=LATCHCOLOR) else: d.configure(foreground=DEFAULTCOLOR) ds = self.name + "\n" + str(self.value) if self.description: ds += "\n" + self.description if self.displayvariable: self.displayvariable.set(ds) dv = None if self.typedesc == 'bool': dv = bool(self.value) elif self.typedesc == 'int': dv = int(self.value) else: dv = str(self.value) self.displayvalue.set(dv) def setdesc(self): result = tkSimpleDialog.askstring(self.name,self.name,initialvalue=self.description) if result is not None: self.description = result self.display_update() class block(ladder.block): def __init__(self,function = block_functions.DEFAULT,parent=None,output=False,rung=None): super(block,self).__init__(function,parent,output,rung) self.display = None self.frm2 = None self.popupparent = None if parent: self.display_new(parent) if output: self.display_update_output() else: self.display_update() def run(self,on=True): try: super(block,self).run(on) except: self.display_update() raise def delifparent(self,parent): if self.frm.master == parent: #I am a child of you, so I wll delete myself if self.frm2: self.frm2.destroy() for a in self.arguments: a.delifparent(self.frm) def removeblock(self,child): if child in self.arguments: self.arguments.remove(child) def display_new(self,parent): frm = Frame(parent,border=2,relief=RAISED,pady=5) frm2 = Frame(frm,border=1,relief=RAISED,) frm2.pack(fill=X) l = Label(frm2,text=self.function.__name__()) l.pack() for bit in self.arguments: bit.display_new(frm) frm.pack(side=LEFT) self.display = frm self.popupparent = parent self.popup = Menu(self.popupparent,tearoff=0,postcommand=self.updatemenu) addmenu = Menu(self.popup,tearoff=0) for item in itemlist: addmenu.add_command(label=item.name,command=self.additem(item)) self.popup.add_cascade(label="add argument",menu=addmenu) self.popup.add_command(label="properties",command=self.properties_display) self.popup.add_separator() self.popup.add_command(label="remove block",command=self.delblock) self.popup.add_separator() self.updatemenu() self.frm = frm frm.bind("",self.popup_menu) fix_scroll() def testing(self): print self.arguments print self.status() print self.function.on def properties_display(self): ds = self.properties() tkMessageBox.showinfo(self.name,ds) def updatemenu(self): self.popup.delete(5) self.popup.delete(4) self.popup.delete(3) self.popup.delete(2) self.popup.delete(1) self.popup.delete(1) self.popup.delete(1) addmenu = Menu(self.popup,tearoff=0) for item in itemlist: addmenu.add_command(label=item.name,command=self.additem(item)) for fnct in functionlist: addmenu.add_command(label=fnct.__name__,command=self.addsubblock(fnct)) self.popup.add_cascade(label="add argument",menu=addmenu) self.popup.add_command(label="properties",command=self.properties) self.popup.add_command(label="test",command=self.testing) self.popup.add_separator() self.popup.add_command(label="remove block",command=self.delblock) self.popup.add_separator() self.removeargsmenu = Menu(self.popup,tearoff=0) for item in self.arguments: self.removeargsmenu.add_command(label=item.name,command=self.removearg(item)) self.popup.add_cascade(label="remove argument",menu=self.removeargsmenu,) def addsubblock(self,fnct): return lambda:self.arguments.append(block(fnct,parent=self.frm,rung=self)) def removearg(self,item): return lambda:self.removearg2(item) def removearg2(self,item): item.delifparent(self.frm) self.arguments.remove(item) def additem(self,item): return lambda:self.additem2(item) def additem2(self,item): self.arguments.append(item) item.display_new(self.frm) fix_scroll() def delblock(self): if self.frm2: self.frm2.destroy() self.frm.destroy() def popup_menu(self,event): try: self.popup.tk_popup(event.x_root,event.y_root,0) finally: self.popup.grab_release() def display_update(self): if self.display: if self.faulted: self.display.configure(bg=FAULTCOLOR) elif self.status(): self.display.configure(bg=TRUECOLOR) else: self.display.configure(bg=FALSECOLOR) for bit in self.arguments: bit.display_update() def display_update_output(self): for bit in self.arguments: bit.display_update() class rung(ladder.rung): def __init__(self): super(rung,self).__init__() self.frminput = None self.frmoutput = None def __del__(self): for i in self.inputs: i.delifparent(self.frminput) for o in self.outputs: o.delifparent(self.frmoutput) self.frminput.destroy() self.frmoutput.destroy() self.frm.destroy() def run(self): super(rung,self).run() conds = map(lambda x:x.status(),self.inputs) if all(conds) or not self.inputs: if self.frminput: self.frminput.configure(bg=TRUECOLOR) else: if self.frminput: self.frminput.configure(bg=FALSECOLOR) def removeblock(self,child): if child in self.inputs: self.inputs.remove(child) elif child in self.outputs: self.outputs.remove(child) def display_new(self,parent): frm = Frame(parent,border=2,relief=RAISED) frmminheight = Frame(frm,height=20,width=1) frmminheight.pack(side=LEFT) self.frminput = Frame(frm,border=1,relief=RAISED) self.frmoutput = Frame(frm,border=1,relief=RAISED) self.frminput.pack(side=LEFT,fill=Y) self.frmoutput.pack(side=RIGHT,fill=Y) for inputblock in self.inputs: inputblock.display_new(self.frminput) for outputblock in self.outputs: outputblock.display_new(self.frmoutput) frm.pack(fill=X,expand=1) self.display = frm self.popup = Menu(parent,tearoff=0) self.inputmenu = Menu(self.popup,tearoff=0) self.outputmenu = Menu(self.popup,tearoff=0) for fnct in functionlist: self.inputmenu.add_command(label=fnct.__name__,command=self.addinput(fnct)) self.outputmenu.add_command(label=fnct.__name__,command=self.addoutput(fnct)) self.popup.add_cascade(label="add input",menu=self.inputmenu) self.popup.add_cascade(label="add output",menu=self.outputmenu) self.popup.add_separator() self.popup.add_command(label="remove rung",command=self.removerowclick) self.popup.add_command(label="new rung") self.popup.add_command(label="test",command=self.test) frm.bind("",self.popup_menu) self.frminput.bind("",self.popup_menu_input) fix_scroll() self.frm = frm def test(self): for i in self. inputs: i.test(self.frminput) def removerowclick(self): remove_row(self) def addinput(self,fnct): return lambda:self.inputs.append(block(fnct,parent=self.frminput,rung=self)) def addoutput(self,fnct): return lambda:self.outputs.append(block(fnct,parent=self.frmoutput,output=True)) def popup_menu(self,event): try: self.popup.tk_popup(event.x_root,event.y_root,0) finally: self.popup.grab_release() def popup_menu_input(self,event): try: self.inputmenu.tk_popup(event.x_root,event.y_root,0) finally: self.popup.grab_release() def display_update(self): for inputblock in self.inputs: inputblock.display_update() for outputblock in self.outputs: outputblock.display_update_output() def closeblock(bit): b = block() b.arguments.append(bit) return b if __name__ == '__main__': I1 = create_binary_array(10,'I1:0/') b1 = block() b1.function = func_and b1.arguments.append(I1[0]) b1.arguments.append(I1[1]) I1[0].set(True) I1[1].set(True) a = value_word(0) out1 = block() out1.function = func_add out1.arguments.append(a) out1.arguments.append(1) out1.run() r = rung() r.inputs += [b1] r.outputs += [out1] r.run() I1[0].set(False) r.run()