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