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