]>
Commit | Line | Data |
---|---|---|
1e4a197e RD |
1 | #---------------------------------------------------------------------- |
2 | # Name: wxPython.lib.dialogs | |
3 | # Purpose: wxScrolledMessageDialog, wxMultipleChoiceDialog and | |
4 | # function wrappers for the common dialogs by Kevin Altis. | |
5 | # | |
6 | # Author: Various | |
7 | # | |
8 | # Created: 3-January-2002 | |
9 | # RCS-ID: $Id$ | |
10 | # Copyright: (c) 2002 by Total Control Software | |
11 | # Licence: wxWindows license | |
12 | #---------------------------------------------------------------------- | |
cf694132 | 13 | |
1e4a197e RD |
14 | from wxPython import wx |
15 | from layoutf import Layoutf | |
cf694132 | 16 | |
1e4a197e | 17 | #---------------------------------------------------------------------- |
cf694132 | 18 | |
1e4a197e RD |
19 | class wxScrolledMessageDialog(wx.wxDialog): |
20 | def __init__(self, parent, msg, caption, pos = wx.wxDefaultPosition, size = (500,300)): | |
21 | wx.wxDialog.__init__(self, parent, -1, caption, pos, size) | |
80f7e650 RD |
22 | x, y = pos |
23 | if x == -1 and y == -1: | |
1e4a197e RD |
24 | self.CenterOnScreen(wx.wxBOTH) |
25 | text = wx.wxTextCtrl(self, -1, msg, wx.wxDefaultPosition, | |
26 | wx.wxDefaultSize, | |
27 | wx.wxTE_MULTILINE | wx.wxTE_READONLY) | |
28 | ok = wx.wxButton(self, wx.wxID_OK, "OK") | |
cf694132 RD |
29 | text.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok))) |
30 | ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self,))) | |
1e4a197e | 31 | self.SetAutoLayout(1) |
8bf5d46e | 32 | self.Layout() |
cf694132 RD |
33 | |
34 | ||
1e4a197e | 35 | class wxMultipleChoiceDialog(wx.wxDialog): |
1fded56b RD |
36 | def __init__(self, parent, msg, title, lst, pos = wx.wxDefaultPosition, |
37 | size = (200,200), style = wx.wxDEFAULT_DIALOG_STYLE): | |
38 | wx.wxDialog.__init__(self, parent, -1, title, pos, size, style) | |
80f7e650 RD |
39 | x, y = pos |
40 | if x == -1 and y == -1: | |
1e4a197e RD |
41 | self.CenterOnScreen(wx.wxBOTH) |
42 | dc = wx.wxClientDC(self) | |
cf694132 | 43 | height = 0 |
1e4a197e | 44 | for line in msg.splitlines(): |
1fded56b | 45 | height = height + dc.GetTextExtent(line)[1] + 2 |
1e4a197e RD |
46 | stat = wx.wxStaticText(self, -1, msg) |
47 | self.lbox = wx.wxListBox(self, 100, wx.wxDefaultPosition, | |
48 | wx.wxDefaultSize, lst, wx.wxLB_MULTIPLE) | |
49 | ok = wx.wxButton(self, wx.wxID_OK, "OK") | |
50 | cancel = wx.wxButton(self, wx.wxID_CANCEL, "Cancel") | |
cf694132 RD |
51 | stat.SetConstraints(Layoutf('t=t10#1;l=l5#1;r=r5#1;h!%d' % (height,), |
52 | (self,))) | |
53 | self.lbox.SetConstraints(Layoutf('t=b10#2;l=l5#1;r=r5#1;b=t5#3', | |
54 | (self, stat, ok))) | |
55 | ok.SetConstraints(Layoutf('b=b5#1;x%w25#1;w!80;h!25', (self,))) | |
56 | cancel.SetConstraints(Layoutf('b=b5#1;x%w75#1;w!80;h!25', (self,))) | |
1e4a197e | 57 | self.SetAutoLayout(1) |
cf694132 | 58 | self.lst = lst |
8bf5d46e | 59 | self.Layout() |
cf694132 RD |
60 | |
61 | def GetValue(self): | |
62 | return self.lbox.GetSelections() | |
63 | ||
64 | def GetValueString(self): | |
65 | sel = self.lbox.GetSelections() | |
66 | val = [] | |
67 | for i in sel: | |
68 | val.append(self.lst[i]) | |
69 | return tuple(val) | |
70 | ||
edc2a036 | 71 | |
1e4a197e RD |
72 | |
73 | #---------------------------------------------------------------------- | |
74 | """ | |
75 | function wrappers for wxPython system dialogs | |
76 | Author: Kevin Altis | |
77 | Date: 2003-1-2 | |
78 | Rev: 3 | |
79 | ||
80 | This is the third refactor of the PythonCard dialog.py module | |
81 | for inclusion in the main wxPython distribution. There are a number of | |
82 | design decisions and subsequent code refactoring to be done, so I'm | |
83 | releasing this just to get some feedback. | |
84 | ||
85 | rev 3: | |
86 | - result dictionary replaced by DialogResults class instance | |
87 | - should message arg be replaced with msg? most wxWindows dialogs | |
88 | seem to use the abbreviation? | |
89 | ||
90 | rev 2: | |
91 | - All dialog classes have been replaced by function wrappers | |
92 | - Changed arg lists to more closely match wxWindows docs and wxPython.lib.dialogs | |
93 | - changed 'returned' value to the actual button id the user clicked on | |
94 | - added a returnedString value for the string version of the return value | |
95 | - reworked colorDialog and fontDialog so you can pass in just a color or font | |
96 | for the most common usage case | |
97 | - probably need to use colour instead of color to match the English English | |
98 | spelling in wxWindows (sigh) | |
99 | - I still think we could lose the parent arg and just always use None | |
100 | """ | |
101 | ||
102 | class DialogResults: | |
103 | def __init__(self, returned): | |
104 | self.returned = returned | |
105 | self.accepted = returned in (wx.wxID_OK, wx.wxID_YES) | |
106 | self.returnedString = returnedString(returned) | |
107 | ||
108 | def __repr__(self): | |
109 | return str(self.__dict__) | |
110 | ||
111 | def returnedString(ret): | |
112 | if ret == wx.wxID_OK: | |
113 | return "Ok" | |
114 | elif ret == wx.wxID_CANCEL: | |
115 | return "Cancel" | |
116 | elif ret == wx.wxID_YES: | |
117 | return "Yes" | |
118 | elif ret == wx.wxID_NO: | |
119 | return "No" | |
120 | ||
121 | ||
122 | # findDialog was created before wxPython got a Find/Replace dialog | |
123 | # but it may be instructive as to how a function wrapper can | |
124 | # be added for your own custom dialogs | |
125 | # this dialog is always modal, while wxFindReplaceDialog is | |
126 | # modeless and so doesn't lend itself to a function wrapper | |
127 | def findDialog(parent=None, searchText='', wholeWordsOnly=0, caseSensitive=0): | |
128 | dlg = wx.wxDialog(parent, -1, "Find", wx.wxDefaultPosition, wx.wxSize(370, 120)) | |
129 | ||
130 | wx.wxStaticText(dlg, -1, 'Find what:', wx.wxPoint(7, 10)) | |
131 | wSearchText = wx.wxTextCtrl(dlg, -1, searchText, | |
132 | wx.wxPoint(70, 7), wx.wxSize(195, -1)) | |
133 | wSearchText.SetValue(searchText) | |
134 | wx.wxButton(dlg, wx.wxID_OK, "Find Next", wx.wxPoint(280, 5), wx.wxDefaultSize).SetDefault() | |
135 | wx.wxButton(dlg, wx.wxID_CANCEL, "Cancel", wx.wxPoint(280, 35), wx.wxDefaultSize) | |
136 | wWholeWord = wx.wxCheckBox(dlg, -1, 'Match whole word only', | |
137 | wx.wxPoint(7, 35), wx.wxDefaultSize, wx.wxNO_BORDER) | |
138 | if wholeWordsOnly: | |
139 | wWholeWord.SetValue(1) | |
140 | wCase = wx.wxCheckBox(dlg, -1, 'Match case', | |
141 | wx.wxPoint(7, 55), wx.wxDefaultSize, wx.wxNO_BORDER) | |
142 | if caseSensitive: | |
143 | wCase.SetValue(1) | |
144 | wSearchText.SetSelection(0, len(wSearchText.GetValue())) | |
145 | wSearchText.SetFocus() | |
146 | ||
147 | result = DialogResults(dlg.ShowModal()) | |
148 | result.text = wSearchText.GetValue() | |
149 | result.wholeword = wWholeWord.GetValue() | |
150 | result.casesensitive = wCase.GetValue() | |
151 | dlg.Destroy() | |
152 | return result | |
153 | ||
154 | ||
155 | def colorDialog(parent=None, colorData=None, color=None): | |
156 | if colorData: | |
157 | dialog = wx.wxColourDialog(parent, colorData) | |
158 | else: | |
159 | dialog = wx.wxColourDialog(parent) | |
160 | dialog.GetColourData().SetChooseFull(1) | |
161 | if color is not None: | |
162 | dialog.GetColourData().SetColour(color) | |
163 | result = DialogResults(dialog.ShowModal()) | |
164 | result.colorData = dialog.GetColourData() | |
165 | result.color = result.colorData.GetColour().Get() | |
166 | dialog.Destroy() | |
167 | return result | |
168 | ||
169 | # it is easier to just duplicate the code than | |
170 | # try and replace color with colour in the result | |
171 | def colourDialog(parent=None, colourData=None, colour=None): | |
172 | if colourData: | |
173 | dialog = wx.wxColourDialog(parent, colourData) | |
174 | else: | |
175 | dialog = wx.wxColourDialog(parent) | |
176 | dialog.GetColourData().SetChooseFull(1) | |
177 | if colour is not None: | |
178 | dialog.GetColourData().SetColour(color) | |
179 | result = DialogResults(dialog.ShowModal()) | |
180 | result.colourData = dialog.GetColourData() | |
181 | result.colour = result.colourData.GetColour().Get() | |
182 | dialog.Destroy() | |
183 | return result | |
184 | ||
185 | ||
186 | def fontDialog(parent=None, fontData=None, font=None): | |
187 | if fontData is None: | |
188 | fontData = wx.wxFontData() | |
189 | if font is not None: | |
190 | aFontData.SetInitialFont(font) | |
191 | dialog = wx.wxFontDialog(parent, fontData) | |
192 | result = DialogResults(dialog.ShowModal()) | |
193 | if result.accepted: | |
194 | fontData = dialog.GetFontData() | |
195 | result.fontData = fontData | |
196 | result.color = fontData.GetColour().Get() | |
197 | result.colour = result.color | |
198 | result.font = fontData.GetChosenFont() | |
199 | else: | |
200 | result.color = None | |
201 | result.colour = None | |
202 | result.font = None | |
203 | dialog.Destroy() | |
204 | return result | |
205 | ||
206 | ||
207 | def textEntryDialog(parent=None, message='', title='', defaultText='', style=wx.wxOK | wx.wxCANCEL): | |
208 | dialog = wx.wxTextEntryDialog(parent, message, title, defaultText, style) | |
209 | result = DialogResults(dialog.ShowModal()) | |
210 | result.text = dialog.GetValue() | |
211 | dialog.Destroy() | |
212 | return result | |
213 | ||
214 | ||
215 | def messageDialog(parent=None, message='', title='Message box', | |
216 | aStyle = wx.wxOK | wx.wxCANCEL | wx.wxCENTRE, | |
217 | pos=wx.wxDefaultPosition): | |
218 | dialog = wx.wxMessageDialog(parent, message, title, aStyle, pos) | |
219 | result = DialogResults(dialog.ShowModal()) | |
220 | dialog.Destroy() | |
221 | return result | |
222 | ||
223 | ||
224 | # KEA alerts are common, so I'm providing a class rather than | |
225 | # requiring the user code to set up the right icons and buttons | |
226 | # the with messageDialog function | |
227 | def alertDialog(parent=None, message='', title='Alert', pos=wx.wxDefaultPosition): | |
228 | return messageDialog(parent, message, title, wx.wxICON_EXCLAMATION | wx.wxOK, pos) | |
229 | ||
230 | ||
231 | def scrolledMessageDialog(parent=None, message='', title='', pos=wx.wxDefaultPosition, size=(500,300)): | |
232 | dialog = wxScrolledMessageDialog(parent, message, title, pos, size) | |
233 | result = DialogResults(dialog.ShowModal()) | |
234 | dialog.Destroy() | |
235 | return result | |
236 | ||
237 | ||
238 | def fileDialog(parent=None, title='Open', directory='', filename='', wildcard='*.*', | |
239 | style=wx.wxOPEN | wx.wxMULTIPLE): | |
240 | dialog = wx.wxFileDialog(parent, title, directory, filename, wildcard, style) | |
241 | result = DialogResults(dialog.ShowModal()) | |
242 | if result.accepted: | |
243 | result.paths = dialog.GetPaths() | |
244 | else: | |
245 | result.paths = None | |
246 | dialog.Destroy() | |
247 | return result | |
248 | ||
249 | ||
250 | # openFileDialog and saveFileDialog are convenience functions | |
251 | # they represent the most common usages of the fileDialog | |
252 | # with the most common style options | |
253 | def openFileDialog(parent=None, title='Open', directory='', filename='', | |
254 | wildcard='All Files (*.*)|*.*', | |
255 | style=wx.wxOPEN | wx.wxMULTIPLE): | |
256 | return fileDialog(parent, title, directory, filename, wildcard, style) | |
257 | ||
258 | ||
259 | def saveFileDialog(parent=None, title='Save', directory='', filename='', | |
260 | wildcard='All Files (*.*)|*.*', | |
261 | style=wx.wxSAVE | wx.wxHIDE_READONLY | wx.wxOVERWRITE_PROMPT): | |
262 | return fileDialog(parent, title, directory, filename, wildcard, style) | |
263 | ||
264 | ||
265 | def dirDialog(parent=None, message='Choose a directory', path='', style=0, | |
266 | pos=wx.wxDefaultPosition, size=wx.wxDefaultSize): | |
267 | dialog = wx.wxDirDialog(parent, message, path, style, pos, size) | |
268 | result = DialogResults(dialog.ShowModal()) | |
269 | if result.accepted: | |
270 | result.path = dialog.GetPath() | |
271 | else: | |
272 | result.path = None | |
273 | dialog.Destroy() | |
274 | return result | |
275 | ||
276 | directoryDialog = dirDialog | |
277 | ||
278 | ||
279 | def singleChoiceDialog(parent=None, message='', title='', lst=[], | |
280 | style=wx.wxOK | wx.wxCANCEL | wx.wxCENTRE): | |
281 | dialog = wx.wxSingleChoiceDialog(parent, | |
282 | message, | |
283 | title, | |
284 | lst, | |
285 | style) | |
286 | result = DialogResults(dialog.ShowModal()) | |
287 | result.selection = dialog.GetStringSelection() | |
288 | dialog.Destroy() | |
289 | return result | |
290 | ||
291 | ||
292 | def multipleChoiceDialog(parent=None, message='', title='', lst=[], pos=wx.wxDefaultPosition, size=(200,200)): | |
293 | dialog = wxMultipleChoiceDialog(parent, message, title, lst, pos, size) | |
294 | result = DialogResults(dialog.ShowModal()) | |
295 | result.selection = dialog.GetValueString() | |
296 | dialog.Destroy() | |
297 | return result | |
298 | ||
299 | ||
cf694132 | 300 | if __name__ == '__main__': |
1e4a197e RD |
301 | class MyApp(wx.wxApp): |
302 | ||
cf694132 | 303 | def OnInit(self): |
1e4a197e RD |
304 | frame = wx.wxFrame(wx.NULL, -1, "Dialogs", size=(400, 200)) |
305 | panel = wx.wxPanel(frame, -1) | |
306 | self.panel = panel | |
cf694132 | 307 | |
1e4a197e | 308 | frame.Show(1) |
cf694132 | 309 | |
1e4a197e RD |
310 | dialogNames = [ |
311 | 'alertDialog', | |
312 | 'colorDialog', | |
313 | 'directoryDialog', | |
314 | 'fileDialog', | |
315 | 'findDialog', | |
316 | 'fontDialog', | |
317 | 'messageDialog', | |
318 | 'multipleChoiceDialog', | |
319 | 'openFileDialog', | |
320 | 'saveFileDialog', | |
321 | 'scrolledMessageDialog', | |
322 | 'singleChoiceDialog', | |
323 | 'textEntryDialog', | |
324 | ] | |
325 | self.nameList = wx.wxListBox(panel, -1, (0, 0), (130, 180), dialogNames, style=wx.wxLB_SINGLE) | |
326 | wx.EVT_LISTBOX(panel, self.nameList.GetId(), self.OnNameListSelected) | |
cf694132 | 327 | |
1e4a197e RD |
328 | tstyle = wx.wxTE_RICH2 | wx.wxTE_PROCESS_TAB | wx.wxTE_MULTILINE |
329 | self.text1 = wx.wxTextCtrl(panel, -1, pos=(150, 0), size=(200, 180), style=tstyle) | |
cf694132 | 330 | |
1e4a197e | 331 | self.SetTopWindow(frame) |
cf694132 | 332 | |
1e4a197e | 333 | return 1 |
cf694132 | 334 | |
1e4a197e RD |
335 | def OnNameListSelected(self, evt): |
336 | import pprint | |
337 | sel = evt.GetString() | |
338 | result = None | |
339 | if sel == 'alertDialog': | |
340 | result = alertDialog(message='Danger Will Robinson') | |
341 | elif sel == 'colorDialog': | |
342 | result = colorDialog() | |
343 | elif sel == 'directoryDialog': | |
344 | result = directoryDialog() | |
345 | elif sel == 'fileDialog': | |
346 | wildcard = "JPG files (*.jpg;*.jpeg)|*.jpeg;*.JPG;*.JPEG;*.jpg|GIF files (*.gif)|*.GIF;*.gif|All Files (*.*)|*.*" | |
347 | result = fileDialog(None, 'Open', '', '', wildcard) | |
348 | elif sel == 'findDialog': | |
349 | result = findDialog() | |
350 | elif sel == 'fontDialog': | |
351 | result = fontDialog() | |
352 | elif sel == 'messageDialog': | |
353 | result = messageDialog(None, 'Hello from Python and wxPython!', | |
354 | 'A Message Box', wx.wxOK | wx.wxICON_INFORMATION) | |
355 | #wx.wxYES_NO | wx.wxNO_DEFAULT | wx.wxCANCEL | wx.wxICON_INFORMATION) | |
356 | #result = messageDialog(None, 'message', 'title') | |
357 | elif sel == 'multipleChoiceDialog': | |
358 | result = multipleChoiceDialog(None, "message", "title", ['one', 'two', 'three']) | |
359 | elif sel == 'openFileDialog': | |
360 | result = openFileDialog() | |
361 | elif sel == 'saveFileDialog': | |
362 | result = saveFileDialog() | |
363 | elif sel == 'scrolledMessageDialog': | |
364 | msg = "Can't find the file dialog.py" | |
365 | try: | |
366 | # read this source file and then display it | |
367 | import sys | |
368 | filename = sys.argv[-1] | |
369 | fp = open(filename) | |
370 | message = fp.read() | |
371 | fp.close() | |
372 | except: | |
373 | pass | |
374 | result = scrolledMessageDialog(None, message, filename) | |
375 | elif sel == 'singleChoiceDialog': | |
376 | result = singleChoiceDialog(None, "message", "title", ['one', 'two', 'three']) | |
377 | elif sel == 'textEntryDialog': | |
378 | result = textEntryDialog(None, "message", "title", "text") | |
cf694132 | 379 | |
1e4a197e RD |
380 | if result: |
381 | #self.text1.SetValue(pprint.pformat(result.__dict__)) | |
382 | self.text1.SetValue(str(result)) | |
cf694132 | 383 | |
1e4a197e RD |
384 | app = MyApp(0) |
385 | app.MainLoop() |