blob: 5e691ece29a8ee73d11ab56d564b3def60e6952f [file] [log] [blame]
Barry Warsawfefbf791998-01-31 23:39:01 +00001"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
Barry Warsaweb61fbd1998-10-02 16:06:27 +00002
3This window provides the basic decorations, primarily including the menubar.
4It is used to bring up other windows.
Barry Warsawfefbf791998-01-31 23:39:01 +00005"""
6
Barry Warsawce0bbd21998-12-03 19:50:24 +00007import sys
8import os
9import string
Barry Warsawfefbf791998-01-31 23:39:01 +000010from Tkinter import *
Barry Warsawa9b45581998-09-29 20:03:53 +000011import tkMessageBox
Barry Warsawa69c1ba1998-09-28 23:38:44 +000012
13# Milliseconds between interrupt checks
14KEEPALIVE_TIMER = 500
Barry Warsawfefbf791998-01-31 23:39:01 +000015
Barry Warsaw552ac171998-02-17 22:25:23 +000016
17
Barry Warsawa69c1ba1998-09-28 23:38:44 +000018class PyncheWidget:
Barry Warsawca07ba01998-10-22 03:25:59 +000019 def __init__(self, version, switchboard, master=None):
Barry Warsaw86daeb71998-10-01 16:46:16 +000020 self.__sb = switchboard
21 self.__version = version
22 self.__textwin = None
Barry Warsawbd36d6e1998-10-02 16:05:48 +000023 self.__listwin = None
Barry Warsaw9044b8e1998-10-05 21:14:46 +000024 self.__detailswin = None
Barry Warsawce0bbd21998-12-03 19:50:24 +000025 self.__helpwin = None
Barry Warsawca07ba01998-10-22 03:25:59 +000026 modal = self.__modal = not not master
27 # If a master was given, we are running as a modal dialog servant to
28 # some other application. We rearrange our UI in this case (there's
29 # no File menu and we get `Okay' and `Cancel' buttons), and we do a
30 # grab_set() to make ourselves modal
31 if modal:
32 self.__tkroot = tkroot = Toplevel(master, class_='Pynche')
33 tkroot.grab_set()
34 tkroot.withdraw()
35 else:
36 # Is there already a default root for Tk, say because we're
37 # running under Guido's IDE? :-) Two conditions say no, either the
38 # import fails or _default_root is None.
39 tkroot = None
40 try:
41 from Tkinter import _default_root
42 tkroot = self.__tkroot = _default_root
43 except ImportError:
44 pass
45 if not tkroot:
46 tkroot = self.__tkroot = Tk(className='Pynche')
47 # but this isn't our top level widget, so make it invisible
48 tkroot.withdraw()
Barry Warsawa69c1ba1998-09-28 23:38:44 +000049 # create the menubar
Barry Warsaw38365031998-10-06 19:39:34 +000050 menubar = self.__menubar = Menu(tkroot)
Barry Warsawa69c1ba1998-09-28 23:38:44 +000051 #
52 # File menu
53 #
Barry Warsawca07ba01998-10-22 03:25:59 +000054 if not modal:
55 filemenu = self.__filemenu = Menu(menubar, tearoff=0)
56 filemenu.add_command(label='Quit',
57 command=self.__quit,
58 accelerator='Alt-Q',
59 underline=0)
Barry Warsawa69c1ba1998-09-28 23:38:44 +000060 #
Barry Warsaw86daeb71998-10-01 16:46:16 +000061 # View menu
62 #
Barry Warsaw38365031998-10-06 19:39:34 +000063 viewmenu = Menu(menubar, tearoff=0)
Barry Warsaw86daeb71998-10-01 16:46:16 +000064 viewmenu.add_command(label='Text Window...',
65 command=self.__popup_text,
66 underline=0)
Barry Warsawbd36d6e1998-10-02 16:05:48 +000067 viewmenu.add_command(label='Color List Window...',
68 command=self.__popup_listwin,
69 underline=0)
Barry Warsaw9044b8e1998-10-05 21:14:46 +000070 viewmenu.add_command(label='Details Window...',
71 command=self.__popup_details,
Barry Warsaw38365031998-10-06 19:39:34 +000072 underline=0)
73 #
Barry Warsawa69c1ba1998-09-28 23:38:44 +000074 # Help menu
75 #
Barry Warsaw38365031998-10-06 19:39:34 +000076 helpmenu = Menu(menubar, name='help', tearoff=0)
Barry Warsaw8a09e1c1998-10-20 20:45:46 +000077 helpmenu.add_command(label='About Pynche...',
Barry Warsawa69c1ba1998-09-28 23:38:44 +000078 command=self.__popup_about,
79 underline=0)
Barry Warsawce0bbd21998-12-03 19:50:24 +000080 helpmenu.add_command(label='Help...',
81 command=self.__popup_usage,
82 underline=0)
Barry Warsaw38365031998-10-06 19:39:34 +000083 #
84 # Tie them all together
85 #
Barry Warsawca07ba01998-10-22 03:25:59 +000086 if not modal:
87 menubar.add_cascade(label='File',
88 menu=filemenu,
89 underline=0)
Barry Warsaw38365031998-10-06 19:39:34 +000090 menubar.add_cascade(label='View',
91 menu=viewmenu,
92 underline=0)
93 menubar.add_cascade(label='Help',
94 menu=helpmenu,
95 underline=0)
96
97 # now create the top level window
98 root = self.__root = Toplevel(tkroot, class_='Pynche', menu=menubar)
Barry Warsawca07ba01998-10-22 03:25:59 +000099 root.protocol('WM_DELETE_WINDOW',
Barry Warsawd9e52141998-10-22 18:46:28 +0000100 modal and self.__bell or self.__quit)
Barry Warsaw38365031998-10-06 19:39:34 +0000101 root.title('Pynche %s' % version)
102 root.iconname('Pynche')
Barry Warsawca07ba01998-10-22 03:25:59 +0000103 # Only bind accelerators for the File->Quit menu item if running as a
104 # standalone app
105 if not modal:
106 root.bind('<Alt-q>', self.__quit)
107 root.bind('<Alt-Q>', self.__quit)
108 else:
109 # We're a modal dialog so we have a new row of buttons
110 bframe = Frame(root, borderwidth=1, relief=RAISED)
111 bframe.grid(row=4, column=0, columnspan=2,
112 sticky='EW',
113 ipady=5)
114 okay = Button(bframe,
115 text='Okay',
116 command=self.__okay)
117 okay.pack(side=LEFT, expand=1)
118 cancel = Button(bframe,
119 text='Cancel',
120 command=self.__cancel)
121 cancel.pack(side=LEFT, expand=1)
Barry Warsawe7f4a471998-10-06 19:50:33 +0000122
123 def __quit(self, event=None):
Barry Warsawca07ba01998-10-22 03:25:59 +0000124 self.__tkroot.quit()
125
Barry Warsawd9e52141998-10-22 18:46:28 +0000126 def __bell(self, event=None):
127 self.__tkroot.bell()
Barry Warsawca07ba01998-10-22 03:25:59 +0000128
129 def __okay(self, event=None):
130 self.__sb.withdraw_views()
131 self.__tkroot.grab_release()
132 self.__quit()
133
134 def __cancel(self, event=None):
135 self.__sb.canceled()
136 self.__okay()
Barry Warsaw552ac171998-02-17 22:25:23 +0000137
Barry Warsawa69c1ba1998-09-28 23:38:44 +0000138 def __keepalive(self):
139 # Exercise the Python interpreter regularly so keyboard interrupts get
140 # through.
Barry Warsaw38365031998-10-06 19:39:34 +0000141 self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
Barry Warsaw552ac171998-02-17 22:25:23 +0000142
Barry Warsawa69c1ba1998-09-28 23:38:44 +0000143 def start(self):
Barry Warsawca07ba01998-10-22 03:25:59 +0000144 if not self.__modal:
145 self.__keepalive()
Barry Warsaw38365031998-10-06 19:39:34 +0000146 self.__tkroot.mainloop()
Barry Warsawa69c1ba1998-09-28 23:38:44 +0000147
Barry Warsawca07ba01998-10-22 03:25:59 +0000148 def window(self):
Barry Warsawa69c1ba1998-09-28 23:38:44 +0000149 return self.__root
Barry Warsawf67575d1998-03-10 00:17:01 +0000150
Barry Warsawa69c1ba1998-09-28 23:38:44 +0000151 def __popup_about(self, event=None):
Barry Warsaw0926dea1998-10-07 03:36:58 +0000152 from Main import __version__
Barry Warsawad3a67c1998-10-06 18:52:59 +0000153 tkMessageBox.showinfo('About Pynche ' + __version__,
Barry Warsawa9b45581998-09-29 20:03:53 +0000154 '''\
Barry Warsawad3a67c1998-10-06 18:52:59 +0000155Pynche %s
156The PYthonically Natural
157Color and Hue Editor
Barry Warsawa69c1ba1998-09-28 23:38:44 +0000158
Barry Warsaw64039911998-12-15 01:02:51 +0000159For information
160contact: Barry A. Warsaw
161email: bwarsaw@python.org''' % __version__)
Barry Warsaw86daeb71998-10-01 16:46:16 +0000162
Barry Warsawce0bbd21998-12-03 19:50:24 +0000163 def __popup_usage(self, event=None):
164 if not self.__helpwin:
165 self.__helpwin = Helpwin(self.__root, self.__quit)
166 self.__helpwin.deiconify()
167
Barry Warsaw86daeb71998-10-01 16:46:16 +0000168 def __popup_text(self, event=None):
169 if not self.__textwin:
170 from TextViewer import TextViewer
171 self.__textwin = TextViewer(self.__sb, self.__root)
172 self.__sb.add_view(self.__textwin)
173 self.__textwin.deiconify()
Barry Warsawbd36d6e1998-10-02 16:05:48 +0000174
175 def __popup_listwin(self, event=None):
176 if not self.__listwin:
177 from ListViewer import ListViewer
178 self.__listwin = ListViewer(self.__sb, self.__root)
179 self.__sb.add_view(self.__listwin)
180 self.__listwin.deiconify()
Barry Warsaw9044b8e1998-10-05 21:14:46 +0000181
182 def __popup_details(self, event=None):
183 if not self.__detailswin:
184 from DetailsViewer import DetailsViewer
185 self.__detailswin = DetailsViewer(self.__sb, self.__root)
186 self.__sb.add_view(self.__detailswin)
187 self.__detailswin.deiconify()
Barry Warsawca07ba01998-10-22 03:25:59 +0000188
189 def withdraw(self):
190 self.__root.withdraw()
Barry Warsawd9e52141998-10-22 18:46:28 +0000191
192 def deiconify(self):
193 self.__root.deiconify()
Barry Warsawce0bbd21998-12-03 19:50:24 +0000194
195
196
197class Helpwin:
198 def __init__(self, master, quitfunc):
199 from Main import __version__, docstring
200 self.__root = root = Toplevel(master, class_='Pynche')
201 root.protocol('WM_DELETE_WINDOW', self.__withdraw)
202 root.title('Pynche Help Window')
203 root.iconname('Pynche Help Window')
204 root.bind('<Alt-q>', quitfunc)
205 root.bind('<Alt-Q>', quitfunc)
206 root.bind('<Alt-w>', self.__withdraw)
207 root.bind('<Alt-W>', self.__withdraw)
208
209 # more elaborate help is available in the README file
210 readmefile = os.path.join(sys.path[0], 'README')
211 try:
212 fp = None
213 try:
214 fp = open(readmefile)
215 contents = fp.read()
216 # wax the last page, it contains Emacs cruft
217 i = string.rfind(contents, '\f')
218 if i > 0:
219 contents = string.rstrip(contents[:i])
220 finally:
221 if fp:
222 fp.close()
223 except IOError:
224 sys.stderr.write("Couldn't open Pynche's README, "
225 'using docstring instead.\n')
226 contents = docstring()
227
228 self.__text = text = Text(root, relief=SUNKEN,
229 width=80, height=24)
Barry Warsawecb1a651999-03-26 16:11:40 +0000230 self.__text.focus_set()
Barry Warsawce0bbd21998-12-03 19:50:24 +0000231 text.insert(0.0, contents)
232 scrollbar = Scrollbar(root)
233 scrollbar.pack(fill=Y, side=RIGHT)
234 text.pack(fill=BOTH, expand=YES)
235 text.configure(yscrollcommand=(scrollbar, 'set'))
236 scrollbar.configure(command=(text, 'yview'))
237
238 def __withdraw(self, event=None):
239 self.__root.withdraw()
240
241 def deiconify(self):
242 self.__root.deiconify()