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