jpayne@68: from idlelib.delegator import Delegator jpayne@68: from idlelib.redirector import WidgetRedirector jpayne@68: jpayne@68: jpayne@68: class Percolator: jpayne@68: jpayne@68: def __init__(self, text): jpayne@68: # XXX would be nice to inherit from Delegator jpayne@68: self.text = text jpayne@68: self.redir = WidgetRedirector(text) jpayne@68: self.top = self.bottom = Delegator(text) jpayne@68: self.bottom.insert = self.redir.register("insert", self.insert) jpayne@68: self.bottom.delete = self.redir.register("delete", self.delete) jpayne@68: self.filters = [] jpayne@68: jpayne@68: def close(self): jpayne@68: while self.top is not self.bottom: jpayne@68: self.removefilter(self.top) jpayne@68: self.top = None jpayne@68: self.bottom.setdelegate(None) jpayne@68: self.bottom = None jpayne@68: self.redir.close() jpayne@68: self.redir = None jpayne@68: self.text = None jpayne@68: jpayne@68: def insert(self, index, chars, tags=None): jpayne@68: # Could go away if inheriting from Delegator jpayne@68: self.top.insert(index, chars, tags) jpayne@68: jpayne@68: def delete(self, index1, index2=None): jpayne@68: # Could go away if inheriting from Delegator jpayne@68: self.top.delete(index1, index2) jpayne@68: jpayne@68: def insertfilter(self, filter): jpayne@68: # Perhaps rename to pushfilter()? jpayne@68: assert isinstance(filter, Delegator) jpayne@68: assert filter.delegate is None jpayne@68: filter.setdelegate(self.top) jpayne@68: self.top = filter jpayne@68: jpayne@68: def removefilter(self, filter): jpayne@68: # XXX Perhaps should only support popfilter()? jpayne@68: assert isinstance(filter, Delegator) jpayne@68: assert filter.delegate is not None jpayne@68: f = self.top jpayne@68: if f is filter: jpayne@68: self.top = filter.delegate jpayne@68: filter.setdelegate(None) jpayne@68: else: jpayne@68: while f.delegate is not filter: jpayne@68: assert f is not self.bottom jpayne@68: f.resetcache() jpayne@68: f = f.delegate jpayne@68: f.setdelegate(filter.delegate) jpayne@68: filter.setdelegate(None) jpayne@68: jpayne@68: jpayne@68: def _percolator(parent): # htest # jpayne@68: import tkinter as tk jpayne@68: jpayne@68: class Tracer(Delegator): jpayne@68: def __init__(self, name): jpayne@68: self.name = name jpayne@68: Delegator.__init__(self, None) jpayne@68: jpayne@68: def insert(self, *args): jpayne@68: print(self.name, ": insert", args) jpayne@68: self.delegate.insert(*args) jpayne@68: jpayne@68: def delete(self, *args): jpayne@68: print(self.name, ": delete", args) jpayne@68: self.delegate.delete(*args) jpayne@68: jpayne@68: box = tk.Toplevel(parent) jpayne@68: box.title("Test Percolator") jpayne@68: x, y = map(int, parent.geometry().split('+')[1:]) jpayne@68: box.geometry("+%d+%d" % (x, y + 175)) jpayne@68: text = tk.Text(box) jpayne@68: p = Percolator(text) jpayne@68: pin = p.insertfilter jpayne@68: pout = p.removefilter jpayne@68: t1 = Tracer("t1") jpayne@68: t2 = Tracer("t2") jpayne@68: jpayne@68: def toggle1(): jpayne@68: (pin if var1.get() else pout)(t1) jpayne@68: def toggle2(): jpayne@68: (pin if var2.get() else pout)(t2) jpayne@68: jpayne@68: text.pack() jpayne@68: var1 = tk.IntVar(parent) jpayne@68: cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1) jpayne@68: cb1.pack() jpayne@68: var2 = tk.IntVar(parent) jpayne@68: cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2) jpayne@68: cb2.pack() jpayne@68: jpayne@68: if __name__ == "__main__": jpayne@68: from unittest import main jpayne@68: main('idlelib.idle_test.test_percolator', verbosity=2, exit=False) jpayne@68: jpayne@68: from idlelib.idle_test.htest import run jpayne@68: run(_percolator)