]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/filebrowsebutton.py
added a test to check how exception handling works with Win32 SEH; corrected copyright
[wxWidgets.git] / wxPython / wx / lib / filebrowsebutton.py
CommitLineData
d14a1e28
RD
1#----------------------------------------------------------------------
2# Name: wxPython.lib.filebrowsebutton
3# Purpose: Composite controls that provide a Browse button next to
4# either a wxTextCtrl or a wxComboBox. The Browse button
5# launches a wxFileDialog and loads the result into the
6# other control.
7#
8# Author: Mike Fletcher
9#
10# RCS-ID: $Id$
11# Copyright: (c) 2000 by Total Control Software
12# Licence: wxWindows license
13#----------------------------------------------------------------------
b881fc78
RD
14# 12/02/2003 - Jeff Grimmett (grimmtooth@softhome.net)
15#
16# o 2.5 Compatability changes
17#
18
19import os
20import types
d14a1e28 21
b881fc78 22import wx
d14a1e28
RD
23
24#----------------------------------------------------------------------
25
b881fc78 26class FileBrowseButton(wx.Panel):
fdc775af
RD
27 """
28 A control to allow the user to type in a filename or browse with
29 the standard file dialog to select file
d14a1e28
RD
30 """
31 def __init__ (self, parent, id= -1,
fdc775af
RD
32 pos = wx.DefaultPosition,
33 size = wx.DefaultSize,
34 style = wx.TAB_TRAVERSAL,
35 labelText= "File Entry:",
36 buttonText= "Browse",
37 toolTip= "Type filename or click browse to choose file",
38 # following are the values for a file dialog box
39 dialogTitle = "Choose a file",
40 startDirectory = ".",
41 initialValue = "",
42 fileMask = "*.*",
43 fileMode = wx.OPEN,
44 # callback for when value changes (optional)
45 changeCallback= lambda x:x
d14a1e28 46 ):
fdc775af
RD
47 """
48 :param labelText: Text for label to left of text field
49 :param buttonText: Text for button which launches the file dialog
50 :param toolTip: Help text
51 :param dialogTitle: Title used in file dialog
52 :param startDirectory: Default directory for file dialog startup
53 :param fileMask: File mask (glob pattern, such as *.*) to use in file dialog
54 :param fileMode: wx.OPEN or wx.SAVE, indicates type of file dialog to use
55 :param changeCallback: callback receives all changes in value of control
56 """
57
d14a1e28
RD
58 # store variables
59 self.labelText = labelText
60 self.buttonText = buttonText
61 self.toolTip = toolTip
62 self.dialogTitle = dialogTitle
63 self.startDirectory = startDirectory
64 self.initialValue = initialValue
65 self.fileMask = fileMask
66 self.fileMode = fileMode
67 self.changeCallback = changeCallback
68 self.callCallback = True
69
70
71 # get background to match it
72 try:
73 self._bc = parent.GetBackgroundColour()
74 except:
75 pass
76
77 # create the dialog
78 self.createDialog(parent, id, pos, size, style )
79 # Setting a value causes the changeCallback to be called.
80 # In this case that would be before the return of the
81 # constructor. Not good. So a default value on
82 # SetValue is used to disable the callback
83 self.SetValue( initialValue, 0)
84
85
86 def createDialog( self, parent, id, pos, size, style ):
87 """Setup the graphic representation of the dialog"""
b881fc78 88 wx.Panel.__init__ (self, parent, id, pos, size, style)
d14a1e28
RD
89 # try to set the background colour
90 try:
91 self.SetBackgroundColour(self._bc)
92 except:
93 pass
b881fc78 94 box = wx.BoxSizer(wx.HORIZONTAL)
d14a1e28
RD
95
96 self.label = self.createLabel( )
b881fc78 97 box.Add( self.label, 0, wx.CENTER )
d14a1e28
RD
98
99 self.textControl = self.createTextControl()
b881fc78 100 box.Add( self.textControl, 1, wx.LEFT|wx.CENTER, 5)
d14a1e28
RD
101
102 self.browseButton = self.createBrowseButton()
b881fc78 103 box.Add( self.browseButton, 0, wx.LEFT|wx.CENTER, 5)
d14a1e28
RD
104
105 # add a border around the whole thing and resize the panel to fit
b881fc78
RD
106 outsidebox = wx.BoxSizer(wx.VERTICAL)
107 outsidebox.Add(box, 1, wx.EXPAND|wx.ALL, 3)
d14a1e28
RD
108 outsidebox.Fit(self)
109
110 self.SetAutoLayout(True)
111 self.SetSizer( outsidebox )
112 self.Layout()
113 if type( size ) == types.TupleType:
b881fc78
RD
114 size = apply( wx.Size, size)
115 self.SetDimensions(-1, -1, size.width, size.height, wx.SIZE_USE_EXISTING)
d14a1e28
RD
116
117# if size.width != -1 or size.height != -1:
118# self.SetSize(size)
119
120 def SetBackgroundColour(self,color):
b881fc78 121 wx.Panel.SetBackgroundColour(self,color)
d14a1e28
RD
122 self.label.SetBackgroundColour(color)
123
124 def createLabel( self ):
125 """Create the label/caption"""
b881fc78 126 label = wx.StaticText(self, -1, self.labelText, style =wx.ALIGN_RIGHT )
d14a1e28
RD
127 font = label.GetFont()
128 w, h, d, e = self.GetFullTextExtent(self.labelText, font)
b881fc78 129 label.SetSize((w+5, h))
d14a1e28
RD
130 return label
131
132 def createTextControl( self):
133 """Create the text control"""
b881fc78 134 textControl = wx.TextCtrl(self, -1)
d14a1e28
RD
135 textControl.SetToolTipString( self.toolTip )
136 if self.changeCallback:
b881fc78
RD
137 textControl.Bind(wx.EVT_TEXT, self.OnChanged)
138 textControl.Bind(wx.EVT_COMBOBOX, self.OnChanged)
d14a1e28
RD
139 return textControl
140
141 def OnChanged(self, evt):
142 if self.callCallback and self.changeCallback:
143 self.changeCallback(evt)
144
145 def createBrowseButton( self):
146 """Create the browse-button control"""
b881fc78 147 button =wx.Button(self, -1, self.buttonText)
d14a1e28 148 button.SetToolTipString( self.toolTip )
b881fc78 149 button.Bind(wx.EVT_BUTTON, self.OnBrowse)
d14a1e28
RD
150 return button
151
152
153 def OnBrowse (self, event = None):
154 """ Going to browse for file... """
155 current = self.GetValue()
156 directory = os.path.split(current)
157 if os.path.isdir( current):
158 directory = current
159 current = ''
160 elif directory and os.path.isdir( directory[0] ):
161 current = directory[1]
162 directory = directory [0]
163 else:
164 directory = self.startDirectory
b881fc78
RD
165 dlg = wx.FileDialog(self, self.dialogTitle, directory, current,
166 self.fileMask, self.fileMode)
d14a1e28 167
b881fc78 168 if dlg.ShowModal() == wx.ID_OK:
d14a1e28
RD
169 self.SetValue(dlg.GetPath())
170 dlg.Destroy()
171
172
173 def GetValue (self):
fdc775af
RD
174 """
175 retrieve current value of text control
176 """
d14a1e28
RD
177 return self.textControl.GetValue()
178
179 def SetValue (self, value, callBack=1):
fdc775af 180 """set current value of text control"""
d14a1e28
RD
181 save = self.callCallback
182 self.callCallback = callBack
183 self.textControl.SetValue(value)
184 self.callCallback = save
185
186
187 def Enable (self, value):
188 """ Convenient enabling/disabling of entire control """
189 self.label.Enable (value)
190 self.textControl.Enable (value)
191 return self.browseButton.Enable (value)
192
193 def GetLabel( self ):
194 """ Retrieve the label's current text """
195 return self.label.GetLabel()
196
197 def SetLabel( self, value ):
198 """ Set the label's current text """
199 rvalue = self.label.SetLabel( value )
200 self.Refresh( True )
201 return rvalue
202
203
204
205
206class FileBrowseButtonWithHistory( FileBrowseButton ):
fdc775af
RD
207 """
208 with following additions:
d14a1e28
RD
209 __init__(..., history=None)
210
211 history -- optional list of paths for initial history drop-down
212 (must be passed by name, not a positional argument)
213 If history is callable it will must return a list used
214 for the history drop-down
fdc775af 215
d14a1e28 216 changeCallback -- as for FileBrowseButton, but with a work-around
b881fc78 217 for win32 systems which don't appear to create wx.EVT_COMBOBOX
d14a1e28
RD
218 events properly. There is a (slight) chance that this work-around
219 will cause some systems to create two events for each Combobox
220 selection. If you discover this condition, please report it!
fdc775af 221
d14a1e28 222 As for a FileBrowseButton.__init__ otherwise.
fdc775af 223
d14a1e28
RD
224 GetHistoryControl()
225 Return reference to the control which implements interfaces
226 required for manipulating the history list. See GetHistoryControl
227 documentation for description of what that interface is.
fdc775af 228
d14a1e28
RD
229 GetHistory()
230 Return current history list
fdc775af 231
d14a1e28
RD
232 SetHistory( value=(), selectionIndex = None )
233 Set current history list, if selectionIndex is not None, select that index
fdc775af 234
d14a1e28
RD
235 """
236 def __init__( self, *arguments, **namedarguments):
237 self.history = namedarguments.get( "history" )
238 if self.history:
239 del namedarguments["history"]
240
241 self.historyCallBack=None
242 if callable(self.history):
243 self.historyCallBack=self.history
244 self.history=None
245 apply( FileBrowseButton.__init__, ( self,)+arguments, namedarguments)
246
247
248 def createTextControl( self):
249 """Create the text control"""
b881fc78 250 textControl = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN )
d14a1e28 251 textControl.SetToolTipString( self.toolTip )
b881fc78 252 textControl.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
d14a1e28 253 if self.changeCallback:
b881fc78
RD
254 textControl.Bind(wx.EVT_TEXT, self.changeCallback)
255 textControl.Bind(wx.EVT_COMBOBOX, self.changeCallback)
d14a1e28
RD
256 if self.history:
257 history=self.history
258 self.history=None
259 self.SetHistory( history, control=textControl)
260 return textControl
261
262
263 def GetHistoryControl( self ):
fdc775af
RD
264 """
265 Return a pointer to the control which provides (at least)
266 the following methods for manipulating the history list:
267
d14a1e28
RD
268 Append( item ) -- add item
269 Clear() -- clear all items
270 Delete( index ) -- 0-based index to delete from list
271 SetSelection( index ) -- 0-based index to select in list
fdc775af 272
d14a1e28
RD
273 Semantics of the methods follow those for the wxComboBox control
274 """
275 return self.textControl
276
277
278 def SetHistory( self, value=(), selectionIndex = None, control=None ):
279 """Set the current history list"""
280 if control is None:
281 control = self.GetHistoryControl()
282 if self.history == value:
283 return
284 self.history = value
285 # Clear history values not the selected one.
286 tempValue=control.GetValue()
287 # clear previous values
288 control.Clear()
289 control.SetValue(tempValue)
290 # walk through, appending new values
291 for path in value:
292 control.Append( path )
293 if selectionIndex is not None:
294 control.SetSelection( selectionIndex )
295
296
297 def GetHistory( self ):
298 """Return the current history list"""
299 if self.historyCallBack != None:
300 return self.historyCallBack()
301 else:
302 return list( self.history )
303
304
305 def OnSetFocus(self, event):
306 """When the history scroll is selected, update the history"""
307 if self.historyCallBack != None:
308 self.SetHistory( self.historyCallBack(), control=self.textControl)
309 event.Skip()
310
311
b881fc78 312 if wx.Platform == "__WXMSW__":
d14a1e28
RD
313 def SetValue (self, value, callBack=1):
314 """ Convenient setting of text control value, works
b881fc78 315 around limitation of wx.ComboBox """
d14a1e28
RD
316 save = self.callCallback
317 self.callCallback = callBack
318 self.textControl.SetValue(value)
319 self.callCallback = save
320
321 # Hack to call an event handler
322 class LocalEvent:
323 def __init__(self, string):
324 self._string=string
325 def GetString(self):
326 return self._string
327 if callBack==1:
328 # The callback wasn't being called when SetValue was used ??
329 # So added this explicit call to it
330 self.changeCallback(LocalEvent(value))
331
332
333class DirBrowseButton(FileBrowseButton):
334 def __init__(self, parent, id = -1,
b881fc78
RD
335 pos = wx.DefaultPosition, size = wx.DefaultSize,
336 style = wx.TAB_TRAVERSAL,
d14a1e28
RD
337 labelText = 'Select a directory:',
338 buttonText = 'Browse',
339 toolTip = 'Type directory name or browse to select',
340 dialogTitle = '',
341 startDirectory = '.',
342 changeCallback = None,
b881fc78 343 dialogClass = wx.DirDialog):
d14a1e28
RD
344 FileBrowseButton.__init__(self, parent, id, pos, size, style,
345 labelText, buttonText, toolTip,
346 dialogTitle, startDirectory,
347 changeCallback = changeCallback)
6046f864 348 self.dialogClass = dialogClass
d14a1e28 349 #
6046f864 350
d14a1e28 351 def OnBrowse(self, ev = None):
6046f864
RD
352 dialog = self.dialogClass(self,
353 message = self.dialogTitle,
354 defaultPath = self.startDirectory)
b881fc78 355 if dialog.ShowModal() == wx.ID_OK:
d14a1e28 356 self.SetValue(dialog.GetPath())
6046f864 357 dialog.Destroy()
d14a1e28 358 #
d14a1e28
RD
359
360
361#----------------------------------------------------------------------
362
363
364if __name__ == "__main__":
365 #from skeletonbuilder import rulesfile
366 class SimpleCallback:
367 def __init__( self, tag ):
368 self.tag = tag
369 def __call__( self, event ):
370 print self.tag, event.GetString()
b881fc78 371 class DemoFrame( wx.Frame ):
d14a1e28 372 def __init__(self, parent):
b881fc78
RD
373 wx.Frame.__init__(self, parent, -1, "File entry with browse", size=(500,260))
374 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
375 panel = wx.Panel (self,-1)
376 innerbox = wx.BoxSizer(wx.VERTICAL)
d14a1e28
RD
377 control = FileBrowseButton(
378 panel,
379 initialValue = "z:\\temp",
380 )
b881fc78 381 innerbox.Add( control, 0, wx.EXPAND )
d14a1e28
RD
382 middlecontrol = FileBrowseButtonWithHistory(
383 panel,
384 labelText = "With History",
385 initialValue = "d:\\temp",
386 history = ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"],
387 changeCallback= SimpleCallback( "With History" ),
388 )
b881fc78 389 innerbox.Add( middlecontrol, 0, wx.EXPAND )
d14a1e28
RD
390 middlecontrol = FileBrowseButtonWithHistory(
391 panel,
392 labelText = "History callback",
393 initialValue = "d:\\temp",
394 history = self.historyCallBack,
395 changeCallback= SimpleCallback( "History callback" ),
396 )
b881fc78 397 innerbox.Add( middlecontrol, 0, wx.EXPAND )
d14a1e28
RD
398 self.bottomcontrol = control = FileBrowseButton(
399 panel,
400 labelText = "With Callback",
b881fc78 401 style = wx.SUNKEN_BORDER|wx.CLIP_CHILDREN ,
d14a1e28
RD
402 changeCallback= SimpleCallback( "With Callback" ),
403 )
b881fc78 404 innerbox.Add( control, 0, wx.EXPAND)
d14a1e28
RD
405 self.bottommostcontrol = control = DirBrowseButton(
406 panel,
407 labelText = "Simple dir browse button",
b881fc78
RD
408 style = wx.SUNKEN_BORDER|wx.CLIP_CHILDREN)
409 innerbox.Add( control, 0, wx.EXPAND)
410 ID = wx.NewId()
411 innerbox.Add( wx.Button( panel, ID,"Change Label", ), 1, wx.EXPAND)
412 self.Bind(wx.EVT_BUTTON, self.OnChangeLabel , id=ID)
413 ID = wx.NewId()
414 innerbox.Add( wx.Button( panel, ID,"Change Value", ), 1, wx.EXPAND)
415 self.Bind(wx.EVT_BUTTON, self.OnChangeValue, id=ID )
d14a1e28
RD
416 panel.SetAutoLayout(True)
417 panel.SetSizer( innerbox )
418 self.history={"c:\\temp":1, "c:\\tmp":1, "r:\\temp":1,"z:\\temp":1}
419
420 def historyCallBack(self):
421 keys=self.history.keys()
422 keys.sort()
423 return keys
424
425 def OnFileNameChangedHistory (self, event):
426 self.history[event.GetString ()]=1
427
428 def OnCloseMe(self, event):
429 self.Close(True)
430 def OnChangeLabel( self, event ):
431 self.bottomcontrol.SetLabel( "Label Updated" )
432 def OnChangeValue( self, event ):
433 self.bottomcontrol.SetValue( "r:\\somewhere\\over\\the\\rainbow.htm" )
434
435 def OnCloseWindow(self, event):
436 self.Destroy()
437
b881fc78 438 class DemoApp(wx.App):
d14a1e28 439 def OnInit(self):
b881fc78
RD
440 wx.InitAllImageHandlers()
441 frame = DemoFrame(None)
d14a1e28
RD
442 frame.Show(True)
443 self.SetTopWindow(frame)
444 return True
445
446 def test( ):
447 app = DemoApp(0)
448 app.MainLoop()
449 print 'Creating dialog'
450 test( )
451
1fded56b 452
1fded56b 453