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