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