ยปCore Development>Code coverage>Tools/pynche/PyncheWidget.py

Python code coverage for Tools/pynche/PyncheWidget.py

#countcontent
1n/a"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
2n/a
3n/aThis window provides the basic decorations, primarily including the menubar.
4n/aIt is used to bring up other windows.
5n/a"""
6n/a
7n/aimport sys
8n/aimport os
9n/afrom tkinter import *
10n/afrom tkinter import messagebox, filedialog
11n/aimport ColorDB
12n/a
13n/a# Milliseconds between interrupt checks
14n/aKEEPALIVE_TIMER = 500
15n/a
16n/a
17n/a
18n/aclass PyncheWidget:
19n/a def __init__(self, version, switchboard, master=None, extrapath=[]):
20n/a self.__sb = switchboard
21n/a self.__version = version
22n/a self.__textwin = None
23n/a self.__listwin = None
24n/a self.__detailswin = None
25n/a self.__helpwin = None
26n/a self.__dialogstate = {}
27n/a modal = self.__modal = not not master
28n/a # If a master was given, we are running as a modal dialog servant to
29n/a # some other application. We rearrange our UI in this case (there's
30n/a # no File menu and we get `Okay' and `Cancel' buttons), and we do a
31n/a # grab_set() to make ourselves modal
32n/a if modal:
33n/a self.__tkroot = tkroot = Toplevel(master, class_='Pynche')
34n/a tkroot.grab_set()
35n/a tkroot.withdraw()
36n/a else:
37n/a # Is there already a default root for Tk, say because we're
38n/a # running under Guido's IDE? :-) Two conditions say no, either the
39n/a # import fails or _default_root is None.
40n/a tkroot = None
41n/a try:
42n/a from Tkinter import _default_root
43n/a tkroot = self.__tkroot = _default_root
44n/a except ImportError:
45n/a pass
46n/a if not tkroot:
47n/a tkroot = self.__tkroot = Tk(className='Pynche')
48n/a # but this isn't our top level widget, so make it invisible
49n/a tkroot.withdraw()
50n/a # create the menubar
51n/a menubar = self.__menubar = Menu(tkroot)
52n/a #
53n/a # File menu
54n/a #
55n/a filemenu = self.__filemenu = Menu(menubar, tearoff=0)
56n/a filemenu.add_command(label='Load palette...',
57n/a command=self.__load,
58n/a underline=0)
59n/a if not modal:
60n/a filemenu.add_command(label='Quit',
61n/a command=self.__quit,
62n/a accelerator='Alt-Q',
63n/a underline=0)
64n/a #
65n/a # View menu
66n/a #
67n/a views = make_view_popups(self.__sb, self.__tkroot, extrapath)
68n/a viewmenu = Menu(menubar, tearoff=0)
69n/a for v in views:
70n/a viewmenu.add_command(label=v.menutext(),
71n/a command=v.popup,
72n/a underline=v.underline())
73n/a #
74n/a # Help menu
75n/a #
76n/a helpmenu = Menu(menubar, name='help', tearoff=0)
77n/a helpmenu.add_command(label='About Pynche...',
78n/a command=self.__popup_about,
79n/a underline=0)
80n/a helpmenu.add_command(label='Help...',
81n/a command=self.__popup_usage,
82n/a underline=0)
83n/a #
84n/a # Tie them all together
85n/a #
86n/a menubar.add_cascade(label='File',
87n/a menu=filemenu,
88n/a underline=0)
89n/a menubar.add_cascade(label='View',
90n/a menu=viewmenu,
91n/a underline=0)
92n/a menubar.add_cascade(label='Help',
93n/a menu=helpmenu,
94n/a underline=0)
95n/a
96n/a # now create the top level window
97n/a root = self.__root = Toplevel(tkroot, class_='Pynche', menu=menubar)
98n/a root.protocol('WM_DELETE_WINDOW',
99n/a modal and self.__bell or self.__quit)
100n/a root.title('Pynche %s' % version)
101n/a root.iconname('Pynche')
102n/a # Only bind accelerators for the File->Quit menu item if running as a
103n/a # standalone app
104n/a if not modal:
105n/a root.bind('<Alt-q>', self.__quit)
106n/a root.bind('<Alt-Q>', self.__quit)
107n/a else:
108n/a # We're a modal dialog so we have a new row of buttons
109n/a bframe = Frame(root, borderwidth=1, relief=RAISED)
110n/a bframe.grid(row=4, column=0, columnspan=2,
111n/a sticky='EW',
112n/a ipady=5)
113n/a okay = Button(bframe,
114n/a text='Okay',
115n/a command=self.__okay)
116n/a okay.pack(side=LEFT, expand=1)
117n/a cancel = Button(bframe,
118n/a text='Cancel',
119n/a command=self.__cancel)
120n/a cancel.pack(side=LEFT, expand=1)
121n/a
122n/a def __quit(self, event=None):
123n/a self.__tkroot.quit()
124n/a
125n/a def __bell(self, event=None):
126n/a self.__tkroot.bell()
127n/a
128n/a def __okay(self, event=None):
129n/a self.__sb.withdraw_views()
130n/a self.__tkroot.grab_release()
131n/a self.__quit()
132n/a
133n/a def __cancel(self, event=None):
134n/a self.__sb.canceled()
135n/a self.__okay()
136n/a
137n/a def __keepalive(self):
138n/a # Exercise the Python interpreter regularly so keyboard interrupts get
139n/a # through.
140n/a self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
141n/a
142n/a def start(self):
143n/a if not self.__modal:
144n/a self.__keepalive()
145n/a self.__tkroot.mainloop()
146n/a
147n/a def window(self):
148n/a return self.__root
149n/a
150n/a def __popup_about(self, event=None):
151n/a from Main import __version__
152n/a messagebox.showinfo('About Pynche ' + __version__,
153n/a '''\
154n/aPynche %s
155n/aThe PYthonically Natural
156n/aColor and Hue Editor
157n/a
158n/aFor information
159n/acontact: Barry A. Warsaw
160n/aemail: bwarsaw@python.org''' % __version__)
161n/a
162n/a def __popup_usage(self, event=None):
163n/a if not self.__helpwin:
164n/a self.__helpwin = Helpwin(self.__root, self.__quit)
165n/a self.__helpwin.deiconify()
166n/a
167n/a def __load(self, event=None):
168n/a while 1:
169n/a idir, ifile = os.path.split(self.__sb.colordb().filename())
170n/a file = filedialog.askopenfilename(
171n/a filetypes=[('Text files', '*.txt'),
172n/a ('All files', '*'),
173n/a ],
174n/a initialdir=idir,
175n/a initialfile=ifile)
176n/a if not file:
177n/a # cancel button
178n/a return
179n/a try:
180n/a colordb = ColorDB.get_colordb(file)
181n/a except IOError:
182n/a messagebox.showerror('Read error', '''\
183n/aCould not open file for reading:
184n/a%s''' % file)
185n/a continue
186n/a if colordb is None:
187n/a messagebox.showerror('Unrecognized color file type', '''\
188n/aUnrecognized color file type in file:
189n/a%s''' % file)
190n/a continue
191n/a break
192n/a self.__sb.set_colordb(colordb)
193n/a
194n/a def withdraw(self):
195n/a self.__root.withdraw()
196n/a
197n/a def deiconify(self):
198n/a self.__root.deiconify()
199n/a
200n/a
201n/a
202n/aclass Helpwin:
203n/a def __init__(self, master, quitfunc):
204n/a from Main import docstring
205n/a self.__root = root = Toplevel(master, class_='Pynche')
206n/a root.protocol('WM_DELETE_WINDOW', self.__withdraw)
207n/a root.title('Pynche Help Window')
208n/a root.iconname('Pynche Help Window')
209n/a root.bind('<Alt-q>', quitfunc)
210n/a root.bind('<Alt-Q>', quitfunc)
211n/a root.bind('<Alt-w>', self.__withdraw)
212n/a root.bind('<Alt-W>', self.__withdraw)
213n/a
214n/a # more elaborate help is available in the README file
215n/a readmefile = os.path.join(sys.path[0], 'README')
216n/a try:
217n/a fp = None
218n/a try:
219n/a fp = open(readmefile)
220n/a contents = fp.read()
221n/a # wax the last page, it contains Emacs cruft
222n/a i = contents.rfind('\f')
223n/a if i > 0:
224n/a contents = contents[:i].rstrip()
225n/a finally:
226n/a if fp:
227n/a fp.close()
228n/a except IOError:
229n/a sys.stderr.write("Couldn't open Pynche's README, "
230n/a 'using docstring instead.\n')
231n/a contents = docstring()
232n/a
233n/a self.__text = text = Text(root, relief=SUNKEN,
234n/a width=80, height=24)
235n/a self.__text.focus_set()
236n/a text.insert(0.0, contents)
237n/a scrollbar = Scrollbar(root)
238n/a scrollbar.pack(fill=Y, side=RIGHT)
239n/a text.pack(fill=BOTH, expand=YES)
240n/a text.configure(yscrollcommand=(scrollbar, 'set'))
241n/a scrollbar.configure(command=(text, 'yview'))
242n/a
243n/a def __withdraw(self, event=None):
244n/a self.__root.withdraw()
245n/a
246n/a def deiconify(self):
247n/a self.__root.deiconify()
248n/a
249n/a
250n/a
251n/aimport functools
252n/a@functools.total_ordering
253n/aclass PopupViewer:
254n/a def __init__(self, module, name, switchboard, root):
255n/a self.__m = module
256n/a self.__name = name
257n/a self.__sb = switchboard
258n/a self.__root = root
259n/a self.__menutext = module.ADDTOVIEW
260n/a # find the underline character
261n/a underline = module.ADDTOVIEW.find('%')
262n/a if underline == -1:
263n/a underline = 0
264n/a else:
265n/a self.__menutext = module.ADDTOVIEW.replace('%', '', 1)
266n/a self.__underline = underline
267n/a self.__window = None
268n/a
269n/a def menutext(self):
270n/a return self.__menutext
271n/a
272n/a def underline(self):
273n/a return self.__underline
274n/a
275n/a def popup(self, event=None):
276n/a if not self.__window:
277n/a # class and module must have the same name
278n/a class_ = getattr(self.__m, self.__name)
279n/a self.__window = class_(self.__sb, self.__root)
280n/a self.__sb.add_view(self.__window)
281n/a self.__window.deiconify()
282n/a
283n/a def __eq__(self, other):
284n/a return self.__menutext == other.__menutext
285n/a
286n/a def __lt__(self, other):
287n/a return self.__menutext < other.__menutext
288n/a
289n/a
290n/adef make_view_popups(switchboard, root, extrapath):
291n/a viewers = []
292n/a # where we are in the file system
293n/a dirs = [os.path.dirname(__file__)] + extrapath
294n/a for dir in dirs:
295n/a if dir == '':
296n/a dir = '.'
297n/a for file in os.listdir(dir):
298n/a if file[-9:] == 'Viewer.py':
299n/a name = file[:-3]
300n/a try:
301n/a module = __import__(name)
302n/a except ImportError:
303n/a # Pynche is running from inside a package, so get the
304n/a # module using the explicit path.
305n/a pkg = __import__('pynche.'+name)
306n/a module = getattr(pkg, name)
307n/a if hasattr(module, 'ADDTOVIEW') and module.ADDTOVIEW:
308n/a # this is an external viewer
309n/a v = PopupViewer(module, name, switchboard, root)
310n/a viewers.append(v)
311n/a # sort alphabetically
312n/a viewers.sort()
313n/a return viewers