import Tkinter import time import patterns class Widget(patterns.Subject): def __init__(self, factory): patterns.Subject.__init__(self) self.factory = factory class Window(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_title(self, text): raise NotImplementedError class Frame(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_label(self, text): raise NotImplementedError def set_contents(self, widgets): raise NotImplementedError class Button(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_label(self, text): raise NotImplementedError class Label(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_label(self, text): raise NotImplementedError class Edit(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_text(self, text): raise NotImplementedError class BigEdit(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_text(self, text): raise NotImplementedError class NewLine(Widget): def __init__(self, factory): Widget.__init__(self, factory) class Space(Widget): def __init__(self, factory): Widget.__init__(self, factory) def set_ems(self, ems): raise NotImplementedError class WidgetFactory(object): def __init__(self): pass def window(self): return TkWindow() def frame(self): raise NotImplementedError def button(self): raise NotImplementedError def label(self): raise NotImplementedError def edit(self): raise NotImplementedError def bigedit(self): raise NotImplementedError def newline(self): raise NotImplementedError def space(self): raise NotImplementedError class TkWidgetFactory(WidgetFactory): def __init__(self): pass def window(self): return TkWindow(self) def frame(self): return TkFrame(self) def button(self): return TkButton(self) def label(self): return TkLabel(self) def edit(self): return TkEdit(self) def bigedit(self): return TkBigEdit(self) def newline(self): return NewLine(self) def space(self): return TkSpace(self) class TkWidget(object): def set_master(self, master): raise NotImplementedError class TkFrameMixin(TkWidget): def __init__(self): # FIXME: Expect the class this is mixed in with to have self.factory self.master = None self.tkframe = None self.label = None self.content_widgets = [] def set_label(self, text): # FIXME: update() doesn't work quite as hoped for self.label = text self.update() def set_contents(self, widgets): self.content_widgets = widgets self.update() def set_master(self, master): if not self.master: self.master = master self.tkframe = Tkinter.Frame(master) self.update() elif master != self.master: raise Exception def update(self): # Why there are two frames (tkframe and tksubframe): # - tkframes get stacked left to right # - tksubframes implement the newline() widget by getting # stacked top to bottom. The number of tksubframes is # equal to the number of newlines + 1. # FIXME: Why isn't something this freakish done with cleanroom # techniques? # FIXME: "and self.content_widgets" is a hack if self.tkframe and self.content_widgets: label_widgets = [] if self.label: label = self.factory.label() label.set_label(self.label) label_widgets.append(label) label_widgets.append(self.factory.newline()) tksubframe = Tkinter.Frame(self.tkframe) for w in label_widgets + self.content_widgets: if w.__class__ is NewLine: tksubframe.pack(fill=Tkinter.X) tksubframe = Tkinter.Frame(self.tkframe) else: w.set_master(tksubframe) tksubframe.pack(fill=Tkinter.X) self.tkframe.pack(side=Tkinter.LEFT) self.tkframe.update() class TkFrame(Frame,TkFrameMixin): def __init__(self, factory): Frame.__init__(self, factory) TkFrameMixin.__init__(self) def set_master(self, master): if not self.master: self.master = master self.tkframe = Tkinter.Frame(master, borderwidth=6, relief=Tkinter.RIDGE) self.update() elif master != self.master: raise Exception def set_label(self, text): TkFrameMixin.set_label(self, text) def set_contents(self, widgets): self.content_widgets = [] if self.master: self.tkframe.destroy() master = self.master self.master = None self.set_master(master) TkFrameMixin.set_contents(self, widgets) class TkWindow(Window,TkFrameMixin): def __init__(self, factory): Window.__init__(self, factory) TkFrameMixin.__init__(self) TkFrameMixin.set_master(self, None) def set_title(self, text): TkFrameMixin.set_label(text) class TkButton(Button,TkWidget): def __init__(self, factory): Button.__init__(self, factory) self.master = None self.tkbutton = None self.tkstringvar = None self.label = None def set_master(self, master): if not self.master: self.master = master self.tkstringvar = Tkinter.StringVar() self.tkbutton = Tkinter.Button(master, textvariable = self.tkstringvar, command = self.tkcallback) self.update() elif master != self.master: raise Exception def set_label(self, text): self.label = text self.update() def update(self): if self.tkbutton: self.tkstringvar.set(self.label) self.tkbutton.pack(side=Tkinter.LEFT) def tkcallback(self): self.Notify() #print self class TkLabel(Label,TkWidget): def __init__(self, factory): Label.__init__(self, factory) self.master = None self.tklabel = None self.tkstringvar = None self.label = None def set_master(self, master): if not self.master: self.master = master self.tkstringvar = Tkinter.StringVar() self.tklabel = Tkinter.Label(master, textvariable = self.tkstringvar) self.update() elif master != self.master: raise Exception def set_label(self, text): self.label = text self.update() def update(self): if self.tklabel: self.tkstringvar.set(self.label) self.tklabel.pack(side=Tkinter.LEFT) def tkcallback(self): print self class TkEdit(Edit,TkWidget): def __init__(self, factory): Edit.__init__(self, factory) self.master = None self.tkentry = None self.tkstringvar = None self.text = None def set_master(self, master): if not self.master: self.master = master self.tkstringvar = Tkinter.StringVar() self.tkstringvar.trace_variable('w', self.tkcallback) self.tkentry = Tkinter.Entry(master, textvariable = self.tkstringvar) self.update() elif master != self.master: raise Exception def set_text(self, text): self.text = text def update(self): if self.tkentry: if self.text != self.tkstringvar.get(): self.tkstringvar.set(self.text) self.tkentry.pack(side=Tkinter.LEFT) def tkcallback(self, *args): self.text = self.tkstringvar.get() self.Notify() #print self, self.text class TkBigEdit(BigEdit,TkWidget): def __init__(self, factory): BigEdit.__init__(self, factory) def set_text(self, text): raise NotImplementedError class TkSpace(Space,TkWidget): def __init__(self, factory): Space.__init__(self, factory) self.label_widget = factory.label() def set_ems(self, ems): self.label_widget.set_label(' ' * int(ems*3)) def set_master(self, master): return self.label_widget.set_master(master) def update(self): return self.label_widget.update() def tkcallback(self): print self def test_tk(): factory = TkWidgetFactory() window = factory.window() label = factory.label() edit1 = factory.edit() button1 = factory.button() button2 = factory.button() button3 = factory.button() button4 = factory.button() newline = factory.newline() frame1 = factory.frame() button1.set_label('hurray') label.set_label('my foo label') button2.set_label('yay') button3.set_label('go') frame1.set_contents([ button4, edit1, ]) window.set_contents([ button1, label, button2, newline, frame1, newline, button3, ]) time.sleep(1) button1.set_label('hurray 1') window.tkframe.update() # FIXME time.sleep(1) button1.set_label('hurray 12') window.tkframe.update() # FIXME time.sleep(1) button1.set_label('hurray 123') window.tkframe.update() # FIXME window.tkframe.mainloop() # FIXME if __name__ == '__main__': test_tk()