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