ยปCore Development>Code coverage>Lib/idlelib/WidgetRedirector.py

Python code coverage for Lib/idlelib/WidgetRedirector.py

#countcontent
1n/afrom tkinter import *
2n/a
3n/aclass WidgetRedirector:
4n/a
5n/a """Support for redirecting arbitrary widget subcommands.
6n/a
7n/a Some Tk operations don't normally pass through Tkinter. For example, if a
8n/a character is inserted into a Text widget by pressing a key, a default Tk
9n/a binding to the widget's 'insert' operation is activated, and the Tk library
10n/a processes the insert without calling back into Tkinter.
11n/a
12n/a Although a binding to <Key> could be made via Tkinter, what we really want
13n/a to do is to hook the Tk 'insert' operation itself.
14n/a
15n/a When a widget is instantiated, a Tcl command is created whose name is the
16n/a same as the pathname widget._w. This command is used to invoke the various
17n/a widget operations, e.g. insert (for a Text widget). We are going to hook
18n/a this command and provide a facility ('register') to intercept the widget
19n/a operation.
20n/a
21n/a In IDLE, the function being registered provides access to the top of a
22n/a Percolator chain. At the bottom of the chain is a call to the original
23n/a Tk widget operation.
24n/a
25n/a """
26n/a def __init__(self, widget):
27n/a self._operations = {}
28n/a self.widget = widget # widget instance
29n/a self.tk = tk = widget.tk # widget's root
30n/a w = widget._w # widget's (full) Tk pathname
31n/a self.orig = w + "_orig"
32n/a # Rename the Tcl command within Tcl:
33n/a tk.call("rename", w, self.orig)
34n/a # Create a new Tcl command whose name is the widget's pathname, and
35n/a # whose action is to dispatch on the operation passed to the widget:
36n/a tk.createcommand(w, self.dispatch)
37n/a
38n/a def __repr__(self):
39n/a return "WidgetRedirector(%s<%s>)" % (self.widget.__class__.__name__,
40n/a self.widget._w)
41n/a
42n/a def close(self):
43n/a for operation in list(self._operations):
44n/a self.unregister(operation)
45n/a widget = self.widget; del self.widget
46n/a orig = self.orig; del self.orig
47n/a tk = widget.tk
48n/a w = widget._w
49n/a tk.deletecommand(w)
50n/a # restore the original widget Tcl command:
51n/a tk.call("rename", orig, w)
52n/a
53n/a def register(self, operation, function):
54n/a self._operations[operation] = function
55n/a setattr(self.widget, operation, function)
56n/a return OriginalCommand(self, operation)
57n/a
58n/a def unregister(self, operation):
59n/a if operation in self._operations:
60n/a function = self._operations[operation]
61n/a del self._operations[operation]
62n/a if hasattr(self.widget, operation):
63n/a delattr(self.widget, operation)
64n/a return function
65n/a else:
66n/a return None
67n/a
68n/a def dispatch(self, operation, *args):
69n/a '''Callback from Tcl which runs when the widget is referenced.
70n/a
71n/a If an operation has been registered in self._operations, apply the
72n/a associated function to the args passed into Tcl. Otherwise, pass the
73n/a operation through to Tk via the original Tcl function.
74n/a
75n/a Note that if a registered function is called, the operation is not
76n/a passed through to Tk. Apply the function returned by self.register()
77n/a to *args to accomplish that. For an example, see ColorDelegator.py.
78n/a
79n/a '''
80n/a m = self._operations.get(operation)
81n/a try:
82n/a if m:
83n/a return m(*args)
84n/a else:
85n/a return self.tk.call((self.orig, operation) + args)
86n/a except TclError:
87n/a return ""
88n/a
89n/a
90n/aclass OriginalCommand:
91n/a
92n/a def __init__(self, redir, operation):
93n/a self.redir = redir
94n/a self.operation = operation
95n/a self.tk = redir.tk
96n/a self.orig = redir.orig
97n/a self.tk_call = self.tk.call
98n/a self.orig_and_operation = (self.orig, self.operation)
99n/a
100n/a def __repr__(self):
101n/a return "OriginalCommand(%r, %r)" % (self.redir, self.operation)
102n/a
103n/a def __call__(self, *args):
104n/a return self.tk_call(self.orig_and_operation + args)
105n/a
106n/a
107n/adef main():
108n/a root = Tk()
109n/a root.wm_protocol("WM_DELETE_WINDOW", root.quit)
110n/a text = Text()
111n/a text.pack()
112n/a text.focus_set()
113n/a redir = WidgetRedirector(text)
114n/a global previous_tcl_fcn
115n/a def my_insert(*args):
116n/a print("insert", args)
117n/a previous_tcl_fcn(*args)
118n/a previous_tcl_fcn = redir.register("insert", my_insert)
119n/a root.mainloop()
120n/a redir.unregister("insert") # runs after first 'close window'
121n/a redir.close()
122n/a root.mainloop()
123n/a root.destroy()
124n/a
125n/aif __name__ == "__main__":
126n/a main()