PageRenderTime 34ms CodeModel.GetById 9ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/lib-tk/tkSimpleDialog.py

http://unladen-swallow.googlecode.com/
Python | 319 lines | 148 code | 72 blank | 99 comment | 23 complexity | 4d8bfd459327aa5565d6a2af2a179bcd MD5 | raw file
  1#
  2# An Introduction to Tkinter
  3# tkSimpleDialog.py
  4#
  5# Copyright (c) 1997 by Fredrik Lundh
  6#
  7# fredrik@pythonware.com
  8# http://www.pythonware.com
  9#
 10
 11# --------------------------------------------------------------------
 12# dialog base class
 13
 14'''Dialog boxes
 15
 16This module handles dialog boxes. It contains the following
 17public symbols:
 18
 19Dialog -- a base class for dialogs
 20
 21askinteger -- get an integer from the user
 22
 23askfloat -- get a float from the user
 24
 25askstring -- get a string from the user
 26'''
 27
 28from Tkinter import *
 29
 30class Dialog(Toplevel):
 31
 32    '''Class to open dialogs.
 33
 34    This class is intended as a base class for custom dialogs
 35    '''
 36
 37    def __init__(self, parent, title = None):
 38
 39        '''Initialize a dialog.
 40
 41        Arguments:
 42
 43            parent -- a parent window (the application window)
 44
 45            title -- the dialog title
 46        '''
 47        Toplevel.__init__(self, parent)
 48
 49        # If the master is not viewable, don't
 50        # make the child transient, or else it
 51        # would be opened withdrawn
 52        if parent.winfo_viewable():
 53            self.transient(parent)
 54
 55        if title:
 56            self.title(title)
 57
 58        self.parent = parent
 59
 60        self.result = None
 61
 62        body = Frame(self)
 63        self.initial_focus = self.body(body)
 64        body.pack(padx=5, pady=5)
 65
 66        self.buttonbox()
 67
 68        self.wait_visibility() # window needs to be visible for the grab
 69        self.grab_set()
 70
 71        if not self.initial_focus:
 72            self.initial_focus = self
 73
 74        self.protocol("WM_DELETE_WINDOW", self.cancel)
 75
 76        if self.parent is not None:
 77            self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
 78                                      parent.winfo_rooty()+50))
 79
 80        self.initial_focus.focus_set()
 81
 82        self.wait_window(self)
 83
 84    def destroy(self):
 85        '''Destroy the window'''
 86        self.initial_focus = None
 87        Toplevel.destroy(self)
 88
 89    #
 90    # construction hooks
 91
 92    def body(self, master):
 93        '''create dialog body.
 94
 95        return widget that should have initial focus.
 96        This method should be overridden, and is called
 97        by the __init__ method.
 98        '''
 99        pass
100
101    def buttonbox(self):
102        '''add standard button box.
103
104        override if you do not want the standard buttons
105        '''
106
107        box = Frame(self)
108
109        w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
110        w.pack(side=LEFT, padx=5, pady=5)
111        w = Button(box, text="Cancel", width=10, command=self.cancel)
112        w.pack(side=LEFT, padx=5, pady=5)
113
114        self.bind("<Return>", self.ok)
115        self.bind("<Escape>", self.cancel)
116
117        box.pack()
118
119    #
120    # standard button semantics
121
122    def ok(self, event=None):
123
124        if not self.validate():
125            self.initial_focus.focus_set() # put focus back
126            return
127
128        self.withdraw()
129        self.update_idletasks()
130
131        try:
132            self.apply()
133        finally:
134            self.cancel()
135
136    def cancel(self, event=None):
137
138        # put focus back to the parent window
139        if self.parent is not None:
140            self.parent.focus_set()
141        self.destroy()
142
143    #
144    # command hooks
145
146    def validate(self):
147        '''validate the data
148
149        This method is called automatically to validate the data before the
150        dialog is destroyed. By default, it always validates OK.
151        '''
152
153        return 1 # override
154
155    def apply(self):
156        '''process the data
157
158        This method is called automatically to process the data, *after*
159        the dialog is destroyed. By default, it does nothing.
160        '''
161
162        pass # override
163
164
165# --------------------------------------------------------------------
166# convenience dialogues
167
168class _QueryDialog(Dialog):
169
170    def __init__(self, title, prompt,
171                 initialvalue=None,
172                 minvalue = None, maxvalue = None,
173                 parent = None):
174
175        if not parent:
176            import Tkinter
177            parent = Tkinter._default_root
178
179        self.prompt   = prompt
180        self.minvalue = minvalue
181        self.maxvalue = maxvalue
182
183        self.initialvalue = initialvalue
184
185        Dialog.__init__(self, parent, title)
186
187    def destroy(self):
188        self.entry = None
189        Dialog.destroy(self)
190
191    def body(self, master):
192
193        w = Label(master, text=self.prompt, justify=LEFT)
194        w.grid(row=0, padx=5, sticky=W)
195
196        self.entry = Entry(master, name="entry")
197        self.entry.grid(row=1, padx=5, sticky=W+E)
198
199        if self.initialvalue:
200            self.entry.insert(0, self.initialvalue)
201            self.entry.select_range(0, END)
202
203        return self.entry
204
205    def validate(self):
206
207        import tkMessageBox
208
209        try:
210            result = self.getresult()
211        except ValueError:
212            tkMessageBox.showwarning(
213                "Illegal value",
214                self.errormessage + "\nPlease try again",
215                parent = self
216            )
217            return 0
218
219        if self.minvalue is not None and result < self.minvalue:
220            tkMessageBox.showwarning(
221                "Too small",
222                "The allowed minimum value is %s. "
223                "Please try again." % self.minvalue,
224                parent = self
225            )
226            return 0
227
228        if self.maxvalue is not None and result > self.maxvalue:
229            tkMessageBox.showwarning(
230                "Too large",
231                "The allowed maximum value is %s. "
232                "Please try again." % self.maxvalue,
233                parent = self
234            )
235            return 0
236
237        self.result = result
238
239        return 1
240
241
242class _QueryInteger(_QueryDialog):
243    errormessage = "Not an integer."
244    def getresult(self):
245        return int(self.entry.get())
246
247def askinteger(title, prompt, **kw):
248    '''get an integer from the user
249
250    Arguments:
251
252        title -- the dialog title
253        prompt -- the label text
254        **kw -- see SimpleDialog class
255
256    Return value is an integer
257    '''
258    d = _QueryInteger(title, prompt, **kw)
259    return d.result
260
261class _QueryFloat(_QueryDialog):
262    errormessage = "Not a floating point value."
263    def getresult(self):
264        return float(self.entry.get())
265
266def askfloat(title, prompt, **kw):
267    '''get a float from the user
268
269    Arguments:
270
271        title -- the dialog title
272        prompt -- the label text
273        **kw -- see SimpleDialog class
274
275    Return value is a float
276    '''
277    d = _QueryFloat(title, prompt, **kw)
278    return d.result
279
280class _QueryString(_QueryDialog):
281    def __init__(self, *args, **kw):
282        if kw.has_key("show"):
283            self.__show = kw["show"]
284            del kw["show"]
285        else:
286            self.__show = None
287        _QueryDialog.__init__(self, *args, **kw)
288
289    def body(self, master):
290        entry = _QueryDialog.body(self, master)
291        if self.__show is not None:
292            entry.configure(show=self.__show)
293        return entry
294
295    def getresult(self):
296        return self.entry.get()
297
298def askstring(title, prompt, **kw):
299    '''get a string from the user
300
301    Arguments:
302
303        title -- the dialog title
304        prompt -- the label text
305        **kw -- see SimpleDialog class
306
307    Return value is a string
308    '''
309    d = _QueryString(title, prompt, **kw)
310    return d.result
311
312if __name__ == "__main__":
313
314    root = Tk()
315    root.update()
316
317    print askinteger("Spam", "Egg count", initialvalue=12*12)
318    print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
319    print askstring("Spam", "Egg label")