def __init__(self, text): self.text = text self.redir = WidgetRedirector(text) self.top = self.bottom = Delegator(text) self.bottom.insert = self.redir.register('insert', self.insert) self.bottom.delete = self.redir.register('delete', self.delete) self.filters = []
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redirector = WidgetRedirector(self) self.insert = self.redirector.register("insert", lambda *args, **kw: "break") self.delete = self.redirector.register("delete", lambda *args, **kw: "break") self.bind("<Control-a>", self._on_ctrl_a)
def __init__(self, *args, **kwargs): tkinter.Text.__init__(self, *args, **kwargs) self.redirector = WidgetRedirector(self) self.insert = \ self.redirector.register("insert", lambda *args, **kw: "break") self.delete = \ self.redirector.register("delete", lambda *args, **kw: "break")
def __init__(self, master=None, **kwargs): ScrolledText.__init__(self, master, **kwargs) self.redirector = WidgetRedirector(self) self.insert = self.redirector.register("insert", lambda *args, **kw: "break") self.delete = self.redirector.register("delete", lambda *args, **kw: "break")
class _ReadOnlyText(tk.Text): """Subclass of tk.Text that is read-only.""" def __init__(self, *args, **kwargs): """Replace insert and delete bindings.""" # subclass to tk.Text import tkinter as tk tk.Text.__init__(self, *args, **kwargs) self.SEL = tk.SEL self.END = tk.END self.INSERT = tk.INSERT from idlelib.redirector import WidgetRedirector self.redirector = WidgetRedirector(self) # freeze user changes self.insert = self.redirector.register('insert', lambda *args, **kw: 'break') self.delete = self.redirector.register('delete', lambda *args, **kw: 'break') # bind ctrl-a as select all self.bind("<Control-Key-a>", self.select_all) def select_all(self, event): """Select all event bound to ctrl-a.""" # select all text self.tag_add(self.SEL, '1.0', self.END) self.mark_set(self.INSERT, '1.0') self.see(self.INSERT) return 'break'
def __init__(self, text): # XXX would be nice to inherit from Delegator self.text = text self.redir = WidgetRedirector(text) self.top = self.bottom = Delegator(text) self.bottom.insert = self.redir.register("insert", self.insert) self.bottom.delete = self.redir.register("delete", self.delete) self.filters = []
class TextReadOnly(Text): def __init__(self, *args, **kwargs): Text.__init__(self, *args, **kwargs) self.redirector = WidgetRedirector(self) self.insert = self.redirector.register("insert", lambda *args, **kw: "break") self.delete = self.redirector.register("delete", lambda *args, **kw: "break")
class Percolator: def __init__(self, text): # XXX would be nice to inherit from Delegator self.text = text self.redir = WidgetRedirector(text) self.top = self.bottom = Delegator(text) self.bottom.insert = self.redir.register("insert", self.insert) self.bottom.delete = self.redir.register("delete", self.delete) self.filters = [] def close(self): while self.top is not self.bottom: self.removefilter(self.top) self.top = None self.bottom.setdelegate(None) self.bottom = None self.redir.close() self.redir = None self.text = None def insert(self, index, chars, tags=None): # Could go away if inheriting from Delegator self.top.insert(index, chars, tags) def delete(self, index1, index2=None): # Could go away if inheriting from Delegator self.top.delete(index1, index2) def insertfilter(self, filter): # Perhaps rename to pushfilter()? assert isinstance(filter, Delegator) assert filter.delegate is None filter.setdelegate(self.top) self.top = filter def removefilter(self, filter): # XXX Perhaps should only support popfilter()? assert isinstance(filter, Delegator) assert filter.delegate is not None f = self.top if f is filter: self.top = filter.delegate filter.setdelegate(None) else: while f.delegate is not filter: assert f is not self.bottom f.resetcache() f = f.delegate f.setdelegate(filter.delegate) filter.setdelegate(None)
def __init__(self, *args, **kwargs): """Replace insert and delete bindings.""" # subclass to tk.Text import tkinter as tk tk.Text.__init__(self, *args, **kwargs) self.SEL = tk.SEL self.END = tk.END self.INSERT = tk.INSERT from idlelib.redirector import WidgetRedirector self.redirector = WidgetRedirector(self) # freeze user changes self.insert = self.redirector.register('insert', lambda *args, **kw: 'break') self.delete = self.redirector.register('delete', lambda *args, **kw: 'break') # bind ctrl-a as select all self.bind("<Control-Key-a>", self.select_all)
class Percolator: def __init__(self, text): self.text = text self.redir = WidgetRedirector(text) self.top = self.bottom = Delegator(text) self.bottom.insert = self.redir.register('insert', self.insert) self.bottom.delete = self.redir.register('delete', self.delete) self.filters = [] def close(self): while self.top is not self.bottom: self.removefilter(self.top) self.top = None self.bottom.setdelegate(None) self.bottom = None self.redir.close() self.redir = None self.text = None def insert(self, index, chars, tags=None): self.top.insert(index, chars, tags) def delete(self, index1, index2=None): self.top.delete(index1, index2) def insertfilter(self, filter): assert isinstance(filter, Delegator) assert filter.delegate is None filter.setdelegate(self.top) self.top = filter def removefilter(self, filter): assert isinstance(filter, Delegator) assert filter.delegate is not None f = self.top if f is filter: self.top = filter.delegate filter.setdelegate(None) else: while f.delegate is not filter: assert f is not self.bottom f.resetcache() f = f.delegate f.setdelegate(filter.delegate) filter.setdelegate(None)
def __init__(self, master, **opt): opt['exportselection'] = 0 # Don't let it write to clipboard opt['takefocus'] = 0 # Ignore when tabbing super().__init__(master, **opt) self.redirector = redir = WidgetRedirector(self) # These two TK commands are used for all text operations, # so cancelling them stops anything from happening. self.insert = redir.register('insert', event_cancel) self.delete = redir.register('delete', event_cancel)
class ReadOnlyText(Text): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redirector = WidgetRedirector(self) self.insert = self.redirector.register("insert", lambda *args, **kw: "break") self.delete = self.redirector.register("delete", lambda *args, **kw: "break") self.bind("<Control-a>", self._on_ctrl_a) def _on_ctrl_a(self, ev): self.tag_add("sel", "1.0", "end") return "break"
def __init__(self, master: Widget, document: FileDocument, **kwargs) \ -> None: """ Creates a live preview widget. :param master: the parent widget :param document: the model for the current KnitScript document """ super().__init__(master, **kwargs) self.pack_propagate(False) self._text = Text(self, font=_get_default_font(), wrap=WORD, padx=5, pady=5, relief=FLAT, bg=("systemSheetBackground" if platform.system() == "Darwin" else "systemMenu"), highlightthickness=0) menu = _create_edit_menu(self._text) self._text.bind(_BUTTONS["context_menu"], partial(_show_context_menu, menu), add=True) redirector = WidgetRedirector(self._text) redirector.register("insert", lambda *args: "break") redirector.register("delete", lambda *args: "break") scrollbar = Scrollbar(self, command=self._text.yview) self._text.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side=RIGHT, fill=Y) self._text.pack(side=LEFT, expand=YES, fill=BOTH) self._document = document self._document.bind("<<Opened>>", self._preview, add=True) self._document.bind("<<Set>>", _debounce(master, 500)(self._preview), add=True) self._preview()
class WidgetRedirectorTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') cls.root = Tk() cls.root.withdraw() cls.text = Text(cls.root) @classmethod def tearDownClass(cls): del cls.text cls.root.update_idletasks() cls.root.destroy() del cls.root def setUp(self): self.redir = WidgetRedirector(self.text) self.func = Func() self.orig_insert = self.redir.register('insert', self.func) self.text.insert('insert', 'asdf') def tearDown(self): self.text.delete('1.0', 'end') self.redir.close() def test_repr(self): self.assertIn('Redirector', repr(self.redir)) self.assertIn('Original', repr(self.orig_insert)) def test_register(self): self.assertEqual(self.text.get('1.0', 'end'), '\n') self.assertEqual(self.func.args, ('insert', 'asdf')) self.assertIn('insert', self.redir._operations) self.assertIn('insert', self.text.__dict__) self.assertEqual(self.text.insert, self.func) def test_original_command(self): self.assertEqual(self.orig_insert.operation, 'insert') self.assertEqual(self.orig_insert.tk_call, self.text.tk.call) self.orig_insert('insert', 'asdf') self.assertEqual(self.text.get('1.0', 'end'), 'asdf\n') def test_unregister(self): self.assertIsNone(self.redir.unregister('invalid operation name')) self.assertEqual(self.redir.unregister('insert'), self.func) self.assertNotIn('insert', self.redir._operations) self.assertNotIn('insert', self.text.__dict__) def test_unregister_no_attribute(self): del self.text.insert self.assertEqual(self.redir.unregister('insert'), self.func) def test_dispatch_intercept(self): self.func.__init__(True) self.assertTrue(self.redir.dispatch('insert', False)) self.assertFalse(self.func.args[0]) def test_dispatch_bypass(self): self.orig_insert('insert', 'asdf') self.assertEqual(self.redir.dispatch('delete', '1.0', 'end'), '') self.assertEqual(self.text.get('1.0', 'end'), '\n') def test_dispatch_error(self): self.func.__init__(TclError()) self.assertEqual(self.redir.dispatch('insert', False), '') self.assertEqual(self.redir.dispatch('invalid'), '') def test_command_dispatch(self): self.root.call(self.text._w, 'insert', 'hello') self.assertEqual(self.func.args, ('hello', )) self.assertEqual(self.text.get('1.0', 'end'), '\n') self.func.__init__(TclError()) self.assertEqual(self.root.call(self.text._w, 'insert', 'boo'), '')
def setUp(self): self.redir = WidgetRedirector(self.text) self.func = Func() self.orig_insert = self.redir.register('insert', self.func) self.text.insert('insert', 'asdf') # leaves self.text empty
def test_close(self): redir = WidgetRedirector(self.text) redir.register('insert', Func) redir.close() self.assertEqual(redir._operations, {}) self.assertFalse(hasattr(self.text, 'widget'))
class WidgetRedirectorTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') cls.root = Tk() cls.root.withdraw() cls.text = Text(cls.root) @classmethod def tearDownClass(cls): del cls.text cls.root.update_idletasks() cls.root.destroy() del cls.root def setUp(self): self.redir = WidgetRedirector(self.text) self.func = Func() self.orig_insert = self.redir.register('insert', self.func) self.text.insert('insert', 'asdf') # leaves self.text empty def tearDown(self): self.text.delete('1.0', 'end') self.redir.close() def test_repr(self): # partly for 100% coverage self.assertIn('Redirector', repr(self.redir)) self.assertIn('Original', repr(self.orig_insert)) def test_register(self): self.assertEqual(self.text.get('1.0', 'end'), '\n') self.assertEqual(self.func.args, ('insert', 'asdf')) self.assertIn('insert', self.redir._operations) self.assertIn('insert', self.text.__dict__) self.assertEqual(self.text.insert, self.func) def test_original_command(self): self.assertEqual(self.orig_insert.operation, 'insert') self.assertEqual(self.orig_insert.tk_call, self.text.tk.call) self.orig_insert('insert', 'asdf') self.assertEqual(self.text.get('1.0', 'end'), 'asdf\n') def test_unregister(self): self.assertIsNone(self.redir.unregister('invalid operation name')) self.assertEqual(self.redir.unregister('insert'), self.func) self.assertNotIn('insert', self.redir._operations) self.assertNotIn('insert', self.text.__dict__) def test_unregister_no_attribute(self): del self.text.insert self.assertEqual(self.redir.unregister('insert'), self.func) def test_dispatch_intercept(self): self.func.__init__(True) self.assertTrue(self.redir.dispatch('insert', False)) self.assertFalse(self.func.args[0]) def test_dispatch_bypass(self): self.orig_insert('insert', 'asdf') # tk.call returns '' where Python would return None self.assertEqual(self.redir.dispatch('delete', '1.0', 'end'), '') self.assertEqual(self.text.get('1.0', 'end'), '\n') def test_dispatch_error(self): self.func.__init__(TclError()) self.assertEqual(self.redir.dispatch('insert', False), '') self.assertEqual(self.redir.dispatch('invalid'), '') def test_command_dispatch(self): # Test that .__init__ causes redirection of tk calls # through redir.dispatch self.root.call(self.text._w, 'insert', 'hello') self.assertEqual(self.func.args, ('hello', )) self.assertEqual(self.text.get('1.0', 'end'), '\n') # Ensure that called through redir .dispatch and not through # self.text.insert by having mock raise TclError. self.func.__init__(TclError()) self.assertEqual(self.root.call(self.text._w, 'insert', 'boo'), '')
def test_init(self): redir = WidgetRedirector(self.text) self.assertEqual(redir.widget, self.text) self.assertEqual(redir.tk, self.text.tk) self.assertRaises(TclError, WidgetRedirector, self.text) redir.close() # restore self.tk, self.text
def __init__(self, master: Widget, document: FileDocument, **kwargs) \ -> None: """ Creates a text editor widget. :param master: the parent widget :param document: the model for the current KnitScript document """ super().__init__(master, **kwargs) self.pack_propagate(False) text = Text(self, undo=True, font=_get_fixed_font(), wrap=WORD, padx=5, pady=5, relief=FLAT, highlightthickness=0) menu = _create_edit_menu(text) text.bind(_BUTTONS["context_menu"], partial(_show_context_menu, menu), add=True) scrollbar = Scrollbar(self, command=text.yview) text.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side=RIGHT, fill=Y) text.pack(side=LEFT, expand=YES, fill=BOTH) self.bind("<FocusIn>", lambda event: text.focus_set()) # TODO: # This is kind of a hack to stop Ctrl-O from inserting a new line. :/ if platform.system() != "Darwin": def on_open(_event: Event) -> str: self.master.open() return "break" text.bind("<Control-o>", on_open) def on_enter(_event: Event) -> str: # Keep the indent on the new line the same as the current line. line = text.get("insert linestart", "insert lineend") indent = " " * sum(1 for _ in takewhile(lambda c: c == " ", line)) if text.tag_ranges(SEL) == (): text.insert(INSERT, "\n" + indent) else: text.replace(SEL_FIRST, SEL_LAST, "\n" + indent) return "break" text.bind("<Return>", on_enter) def on_change(operation: Callable[..., None], *args) -> None: operation(*args) document.text = _strip_trailing_newline(text.get("1.0", END)) document.modified = text.edit_modified() redirector = WidgetRedirector(text) insert = redirector.register("insert", None) delete = redirector.register("delete", None) replace = redirector.register("replace", None) redirector.register("insert", partial(on_change, insert)) redirector.register("delete", partial(on_change, delete)) redirector.register("replace", partial(on_change, replace)) def bind_text_modified() -> None: def on_text_modified(_event: Event) -> None: document.modified = text.edit_modified() text.edit_modified(False) text.bind("<<Modified>>", on_text_modified, add=True) text.insert("1.0", document.text) self.after_idle(bind_text_modified) def on_document_opened(_event: Event) -> None: text.replace("1.0", END, document.text) text.edit_modified(False) def on_document_modified(_event: Event) -> None: if document.modified != text.edit_modified(): text.edit_modified(document.modified) document.bind("<<Opened>>", on_document_opened, add=True) document.bind("<<Modified>>", on_document_modified, add=True)
class WidgetRedirectorTest(unittest.TestCase): @classmethod def setUpClass(cls): requires('gui') cls.tk = Tk() cls.text = Text(cls.tk) @classmethod def tearDownClass(cls): cls.text.destroy() cls.tk.destroy() del cls.text, cls.tk def setUp(self): self.redir = WidgetRedirector(self.text) self.func = Func() self.orig_insert = self.redir.register('insert', self.func) self.text.insert('insert', 'asdf') # leaves self.text empty def tearDown(self): self.text.delete('1.0', 'end') self.redir.close() def test_repr(self): # partly for 100% coverage self.assertIn('Redirector', repr(self.redir)) self.assertIn('Original', repr(self.orig_insert)) def test_register(self): self.assertEqual(self.text.get('1.0', 'end'), '\n') self.assertEqual(self.func.args, ('insert', 'asdf')) self.assertIn('insert', self.redir._operations) self.assertIn('insert', self.text.__dict__) self.assertEqual(self.text.insert, self.func) def test_original_command(self): self.assertEqual(self.orig_insert.operation, 'insert') self.assertEqual(self.orig_insert.tk_call, self.text.tk.call) self.orig_insert('insert', 'asdf') self.assertEqual(self.text.get('1.0', 'end'), 'asdf\n') def test_unregister(self): self.assertIsNone(self.redir.unregister('invalid operation name')) self.assertEqual(self.redir.unregister('insert'), self.func) self.assertNotIn('insert', self.redir._operations) self.assertNotIn('insert', self.text.__dict__) def test_unregister_no_attribute(self): del self.text.insert self.assertEqual(self.redir.unregister('insert'), self.func) def test_dispatch_intercept(self): self.func.__init__(True) self.assertTrue(self.redir.dispatch('insert', False)) self.assertFalse(self.func.args[0]) def test_dispatch_bypass(self): self.orig_insert('insert', 'asdf') # tk.call returns '' where Python would return None self.assertEqual(self.redir.dispatch('delete', '1.0', 'end'), '') self.assertEqual(self.text.get('1.0', 'end'), '\n') def test_dispatch_error(self): self.func.__init__(TclError()) self.assertEqual(self.redir.dispatch('insert', False), '') self.assertEqual(self.redir.dispatch('invalid'), '') def test_command_dispatch(self): # Test that .__init__ causes redirection of tk calls # through redir.dispatch self.tk.call(self.text._w, 'insert', 'hello') self.assertEqual(self.func.args, ('hello',)) self.assertEqual(self.text.get('1.0', 'end'), '\n') # Ensure that called through redir .dispatch and not through # self.text.insert by having mock raise TclError. self.func.__init__(TclError()) self.assertEqual(self.tk.call(self.text._w, 'insert', 'boo'), '')
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redirector = WidgetRedirector(self) self.insert = self.redirector.register("insert", lambda *a, **k: BREAK) self.delete = self.redirector.register("delete", lambda *a, **k: BREAK)