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
8 # Author: Mike Fletcher
11 # Copyright: (c) 2000 by Total Control Software
12 # Licence: wxWindows license
13 #----------------------------------------------------------------------
15 from wxPython
.wx
import *
18 #----------------------------------------------------------------------
20 class FileBrowseButton(wxPanel
):
21 """ A control to allow the user to type in a filename
22 or browse with the standard file dialog to select file
25 parent, id, pos, size -- passed directly to wxPanel initialisation
26 style = wxTAB_TRAVERSAL -- passed directly to wxPanel initialisation
27 labelText -- Text for label to left of text field
28 buttonText -- Text for button which launches the file dialog
30 dialogTitle -- Title used in file dialog
31 startDirectory -- Default directory for file dialog startup
32 fileMask -- File mask (glob pattern, such as *.*) to use in file dialog
33 fileMode -- wxOPEN or wxSAVE, indicates type of file dialog to use
34 changeCallback -- callback receives all changes in value of control
36 GetValue() -- retrieve current value of text control
37 SetValue(string) -- set current value of text control
38 label -- pointer to internal label widget
39 textControl -- pointer to internal text control
40 browseButton -- pointer to button
42 def __init__ (self
, parent
, id= -1,
43 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
44 style
= wxTAB_TRAVERSAL
,
45 labelText
= "File Entry:",
47 toolTip
= "Type filename or click browse to choose file",
48 # following are the values for a file dialog box
49 dialogTitle
= "Choose a file",
54 # callback for when value changes (optional)
55 changeCallback
= lambda x
:x
58 self
.labelText
= labelText
59 self
.buttonText
= buttonText
60 self
.toolTip
= toolTip
61 self
.dialogTitle
= dialogTitle
62 self
.startDirectory
= startDirectory
63 self
.initialValue
= initialValue
64 self
.fileMask
= fileMask
65 self
.fileMode
= fileMode
66 self
.changeCallback
= changeCallback
68 # get background to match it
70 self
._bc
= parent
.GetBackgroundColour()
75 self
.createDialog(parent
, id, pos
, size
, style
)
76 # Setting a value causes the changeCallback to be called.
77 # In this case that would be before the return of the
78 # constructor. Not good. So a default value on
79 # SetValue is used to disable the callback
80 self
.SetValue( initialValue
, 0)
82 def createDialog( self
, parent
, id, pos
, size
, style
):
83 """Setup the graphic representation of the dialog"""
84 wxPanel
.__init
__ (self
, parent
, id, pos
, size
, style
)
85 # try to set the background colour
87 self
.SetBackgroundColour(self
._bc
)
90 box
= wxBoxSizer(wxHORIZONTAL
)
92 self
.label
= self
.createLabel( )
93 box
.Add( self
.label
, 0, wxCENTER
)
95 self
.textControl
= self
.createTextControl()
96 box
.Add( self
.textControl
, 1, wxLEFT|wxCENTER
, 5)
98 self
.browseButton
= self
.createBrowseButton()
99 box
.Add( self
.browseButton
, 0, wxCENTER
)
101 # add a border around the whole thing and resize the panel to fit
102 outsidebox
= wxBoxSizer(wxVERTICAL
)
103 outsidebox
.Add(box
, 1, wxEXPAND|wxALL
, 3)
106 self
.SetAutoLayout(true
)
107 self
.SetSizer( outsidebox
)
109 if size
.width
!= -1 or size
.height
!= -1:
112 def SetBackgroundColour(self
,color
):
113 wxPanel
.SetBackgroundColour(self
,color
)
114 self
.label
.SetBackgroundColour(color
)
116 def createLabel( self
):
117 """Create the label/caption"""
118 label
= wxStaticText(self
, -1, self
.labelText
, style
=wxALIGN_RIGHT
)
119 font
= label
.GetFont()
120 w
, h
, d
, e
= self
.GetFullTextExtent(self
.labelText
, font
)
121 label
.SetSize(wxSize(w
+5, h
))
124 def createTextControl( self
):
125 """Create the text control"""
127 textControl
= wxTextCtrl(self
, ID
)
128 textControl
.SetToolTipString( self
.toolTip
)
129 if self
.changeCallback
:
130 EVT_TEXT(textControl
, ID
, self
.changeCallback
)
131 EVT_COMBOBOX(textControl
, ID
, self
.changeCallback
)
134 def createBrowseButton( self
):
135 """Create the browse-button control"""
137 button
=wxButton(self
, ID
, self
.buttonText
)
138 button
.SetToolTipString( self
.toolTip
)
139 EVT_BUTTON(button
, ID
, self
.OnBrowse
)
143 def OnBrowse (self
, event
= None):
144 """ Going to browse for file... """
145 current
= self
.GetValue()
146 directory
= os
.path
.split(current
)
147 if os
.path
.isdir( current
):
150 elif directory
and os
.path
.isdir( directory
[0] ):
151 current
= directory
[1]
152 directory
= directory
[0]
154 directory
= self
.startDirectory
155 dlg
= wxFileDialog(self
, self
.dialogTitle
, directory
, current
, self
.fileMask
, self
.fileMode
)
157 if dlg
.ShowModal() == wxID_OK
:
158 self
.SetValue (dlg
.GetPath())
164 """ Convenient access to text control value """
165 return self
.textControl
.GetValue ()
167 def SetValue (self
, value
, callBack
=1):
168 """ Convenient setting of text control value """
169 # Removed the return from here because SetValue doesn't return anything.
170 self
.textControl
.SetValue (value
)
172 def Enable (self
, value
):
173 """ Convenient enabling/disabling of entire control """
174 self
.label
.Enable (value
)
175 self
.textControl
.Enable (value
)
176 return self
.browseButton
.Enable (value
)
178 def GetLabel( self
):
179 """ Retrieve the label's current text """
180 return self
.label
.GetLabel()
182 def SetLabel( self
, value
):
183 """ Set the label's current text """
184 rvalue
= self
.label
.SetLabel( value
)
190 class FileBrowseButtonWithHistory( FileBrowseButton
):
191 """ with following additions:
192 __init__(..., history=None)
194 history -- optional list of paths for initial history drop-down
195 (must be passed by name, not a positional argument)
196 If history is callable it will must return a list used
197 for the history drop-down
198 changeCallback -- as for FileBrowseButton, but with a work-around
199 for win32 systems which don't appear to create EVT_COMBOBOX
200 events properly. There is a (slight) chance that this work-around
201 will cause some systems to create two events for each Combobox
202 selection. If you discover this condition, please report it!
203 As for a FileBrowseButton.__init__ otherwise.
205 Return reference to the control which implements interfaces
206 required for manipulating the history list. See GetHistoryControl
207 documentation for description of what that interface is.
209 Return current history list
210 SetHistory( value=(), selectionIndex = None )
211 Set current history list, if selectionIndex is not None, select that index
213 def __init__( self
, *arguments
, **namedarguments
):
214 self
.history
= namedarguments
.get( "history" )
216 del namedarguments
["history"]
218 self
.historyCallBack
=None
219 if callable(self
.history
):
220 self
.historyCallBack
=self
.history
222 apply( FileBrowseButton
.__init
__, ( self
,)+arguments
, namedarguments
)
224 def createTextControl( self
):
225 """Create the text control"""
227 textControl
= wxComboBox(self
, ID
, style
= wxCB_DROPDOWN
)
228 textControl
.SetToolTipString( self
.toolTip
)
229 EVT_SET_FOCUS(textControl
, self
.OnSetFocus
)
230 if self
.changeCallback
:
231 EVT_TEXT(textControl
, ID
, self
.changeCallback
)
232 EVT_COMBOBOX(textControl
, ID
, self
.changeCallback
)
236 self
.SetHistory( history
, control
=textControl
)
239 def GetHistoryControl( self
):
240 """Return a pointer to the control which provides (at least)
241 the following methods for manipulating the history list.:
242 Append( item ) -- add item
243 Clear() -- clear all items
244 Delete( index ) -- 0-based index to delete from list
245 SetSelection( index ) -- 0-based index to select in list
246 Semantics of the methods follow those for the wxComboBox control
248 return self
.textControl
250 def SetHistory( self
, value
=(), selectionIndex
= None, control
=None ):
251 """Set the current history list"""
253 control
= self
.GetHistoryControl()
254 if self
.history
== value
:
257 # Clear history values not the selected one.
258 tempValue
=control
.GetValue()
259 # clear previous values
261 control
.SetValue(tempValue
)
262 # walk through, appending new values
264 control
.Append( path
)
265 if selectionIndex
is not None:
266 control
.SetSelection( selectionIndex
)
268 def GetHistory( self
):
269 """Return the current history list"""
270 if self
.historyCallBack
!= None:
271 return self
.historyCallBack()
273 return list( self
.history
)
275 def OnSetFocus(self
, event
):
276 """When the history scroll is selected, update the history"""
277 if self
.historyCallBack
!= None:
278 self
.SetHistory( self
.historyCallBack(), control
=self
.textControl
)
281 if wxPlatform
== "__WXMSW__":
282 def SetValue (self
, value
, callBack
=1):
283 """ Convenient setting of text control value, works
284 around limitation of wxComboBox """
285 # Removed the return from here because SetValue doesn't return anything.
286 self
.textControl
.SetValue (value
)
287 # Hack to call an event handler
289 def __init__(self
, string
):
294 # The callback wasn't being called when SetValue was used ??
295 # So added this explicit call to it
296 self
.changeCallback(LocalEvent(value
))
299 class DirBrowseButton(FileBrowseButton
):
300 def __init__(self
, parent
, id = -1,
301 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
302 style
= wxTAB_TRAVERSAL
,
303 labelText
= 'Select a directory:',
304 buttonText
= 'Browse',
305 toolTip
= 'Type directory name or browse to select',
307 startDirectory
= '.',
308 changeCallback
= None,
309 dialogClass
= wxDirDialog
):
310 FileBrowseButton
.__init
__(self
, parent
, id, pos
, size
, style
,
311 labelText
, buttonText
, toolTip
,
312 dialogTitle
, startDirectory
,
313 changeCallback
= changeCallback
)
315 self
._dirDialog
= dialogClass(self
,
316 message
= dialogTitle
,
317 defaultPath
= startDirectory
)
319 def OnBrowse(self
, ev
= None):
320 dialog
= self
._dirDialog
321 if dialog
.ShowModal() == wxID_OK
:
322 self
.SetValue(dialog
.GetPath())
325 if self
.__dict
__.has_key('_dirDialog'):
326 self
._dirDialog
.Destroy()
329 #----------------------------------------------------------------------
332 if __name__
== "__main__":
333 #from skeletonbuilder import rulesfile
334 class SimpleCallback
:
335 def __init__( self
, tag
):
337 def __call__( self
, event
):
338 print self
.tag
, event
.GetString()
339 class DemoFrame( wxFrame
):
340 def __init__(self
, parent
):
341 wxFrame
.__init
__(self
, parent
, 2400, "File entry with browse", size
=(500,260) )
342 EVT_CLOSE(self
, self
.OnCloseWindow
)
343 panel
= wxPanel (self
,-1)
344 innerbox
= wxBoxSizer(wxVERTICAL
)
345 control
= FileBrowseButton(
347 initialValue
= "z:\\temp",
349 innerbox
.Add( control
, 0, wxEXPAND
)
350 middlecontrol
= FileBrowseButtonWithHistory(
352 labelText
= "With History",
353 initialValue
= "d:\\temp",
354 history
= ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"],
355 changeCallback
= SimpleCallback( "With History" ),
357 innerbox
.Add( middlecontrol
, 0, wxEXPAND
)
358 middlecontrol
= FileBrowseButtonWithHistory(
360 labelText
= "History callback",
361 initialValue
= "d:\\temp",
362 history
= self
.historyCallBack
,
363 changeCallback
= SimpleCallback( "History callback" ),
365 innerbox
.Add( middlecontrol
, 0, wxEXPAND
)
366 self
.bottomcontrol
= control
= FileBrowseButton(
368 labelText
= "With Callback",
369 style
= wxSUNKEN_BORDER|wxCLIP_CHILDREN
,
370 changeCallback
= SimpleCallback( "With Callback" ),
372 innerbox
.Add( control
, 0, wxEXPAND
)
373 self
.bottommostcontrol
= control
= DirBrowseButton(
375 labelText
= "Simple dir browse button",
376 style
= wxSUNKEN_BORDER|wxCLIP_CHILDREN
)
377 innerbox
.Add( control
, 0, wxEXPAND
)
379 innerbox
.Add( wxButton( panel
, ID
,"Change Label", ), 1, wxEXPAND
)
380 EVT_BUTTON( self
, ID
, self
.OnChangeLabel
)
382 innerbox
.Add( wxButton( panel
, ID
,"Change Value", ), 1, wxEXPAND
)
383 EVT_BUTTON( self
, ID
, self
.OnChangeValue
)
384 panel
.SetAutoLayout(true
)
385 panel
.SetSizer( innerbox
)
386 self
.history
={"c:\\temp":1, "c:\\tmp":1, "r:\\temp":1,"z:\\temp":1}
388 def historyCallBack(self
):
389 keys
=self
.history
.keys()
393 def OnFileNameChangedHistory (self
, event
):
394 self
.history
[event
.GetString ()]=1
396 def OnCloseMe(self
, event
):
398 def OnChangeLabel( self
, event
):
399 self
.bottomcontrol
.SetLabel( "Label Updated" )
400 def OnChangeValue( self
, event
):
401 self
.bottomcontrol
.SetValue( "r:\\somewhere\\over\\the\\rainbow.htm" )
403 def OnCloseWindow(self
, event
):
406 class DemoApp(wxApp
):
408 wxImage_AddHandler(wxJPEGHandler())
409 wxImage_AddHandler(wxPNGHandler())
410 wxImage_AddHandler(wxGIFHandler())
411 frame
= DemoFrame(NULL
)
412 #frame = RulesPanel(NULL )
414 self
.SetTopWindow(frame
)
420 print 'Creating dialog'