1from idlelib.delegator import Delegator 2from idlelib.redirector import WidgetRedirector 3 4 5class Percolator: 6 7 def __init__(self, text): 8 # XXX would be nice to inherit from Delegator 9 self.text = text 10 self.redir = WidgetRedirector(text) 11 self.top = self.bottom = Delegator(text) 12 self.bottom.insert = self.redir.register("insert", self.insert) 13 self.bottom.delete = self.redir.register("delete", self.delete) 14 self.filters = [] 15 16 def close(self): 17 while self.top is not self.bottom: 18 self.removefilter(self.top) 19 self.top = None 20 self.bottom.setdelegate(None) 21 self.bottom = None 22 self.redir.close() 23 self.redir = None 24 self.text = None 25 26 def insert(self, index, chars, tags=None): 27 # Could go away if inheriting from Delegator 28 self.top.insert(index, chars, tags) 29 30 def delete(self, index1, index2=None): 31 # Could go away if inheriting from Delegator 32 self.top.delete(index1, index2) 33 34 def insertfilter(self, filter): 35 # Perhaps rename to pushfilter()? 36 assert isinstance(filter, Delegator) 37 assert filter.delegate is None 38 filter.setdelegate(self.top) 39 self.top = filter 40 41 def removefilter(self, filter): 42 # XXX Perhaps should only support popfilter()? 43 assert isinstance(filter, Delegator) 44 assert filter.delegate is not None 45 f = self.top 46 if f is filter: 47 self.top = filter.delegate 48 filter.setdelegate(None) 49 else: 50 while f.delegate is not filter: 51 assert f is not self.bottom 52 f.resetcache() 53 f = f.delegate 54 f.setdelegate(filter.delegate) 55 filter.setdelegate(None) 56 57 58def _percolator(parent): # htest # 59 import tkinter as tk 60 61 class Tracer(Delegator): 62 def __init__(self, name): 63 self.name = name 64 Delegator.__init__(self, None) 65 66 def insert(self, *args): 67 print(self.name, ": insert", args) 68 self.delegate.insert(*args) 69 70 def delete(self, *args): 71 print(self.name, ": delete", args) 72 self.delegate.delete(*args) 73 74 box = tk.Toplevel(parent) 75 box.title("Test Percolator") 76 x, y = map(int, parent.geometry().split('+')[1:]) 77 box.geometry("+%d+%d" % (x, y + 175)) 78 text = tk.Text(box) 79 p = Percolator(text) 80 pin = p.insertfilter 81 pout = p.removefilter 82 t1 = Tracer("t1") 83 t2 = Tracer("t2") 84 85 def toggle1(): 86 (pin if var1.get() else pout)(t1) 87 def toggle2(): 88 (pin if var2.get() else pout)(t2) 89 90 text.pack() 91 var1 = tk.IntVar(parent) 92 cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1) 93 cb1.pack() 94 var2 = tk.IntVar(parent) 95 cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2) 96 cb2.pack() 97 98if __name__ == "__main__": 99 import unittest 100 unittest.main('idlelib.idle_test.test_percolator', verbosity=2, 101 exit=False) 102 103 from idlelib.idle_test.htest import run 104 run(_percolator) 105