]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/filebrowsebutton.py
5bf576cd917ee1438bbc2564e126ba8aea43c738
[wxWidgets.git] / wxPython / wxPython / lib / filebrowsebutton.py
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 #----------------------------------------------------------------------
14
15 from wxPython.wx import *
16 import os, types
17
18 #----------------------------------------------------------------------
19
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
23
24 __init__ (
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
29 toolTip -- Help text
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
35 )
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
41 """
42 def __init__ (self, parent, id= -1,
43 pos = wxDefaultPosition, size = wxDefaultSize,
44 style = wxTAB_TRAVERSAL,
45 labelText= "File Entry:",
46 buttonText= "Browse",
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",
50 startDirectory = ".",
51 initialValue = "",
52 fileMask = "*.*",
53 fileMode = wxOPEN,
54 # callback for when value changes (optional)
55 changeCallback= lambda x:x
56 ):
57 # store variables
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
67 self.callCallback = true
68
69
70 # get background to match it
71 try:
72 self._bc = parent.GetBackgroundColour()
73 except:
74 pass
75
76 # create the dialog
77 self.createDialog(parent, id, pos, size, style )
78 # Setting a value causes the changeCallback to be called.
79 # In this case that would be before the return of the
80 # constructor. Not good. So a default value on
81 # SetValue is used to disable the callback
82 self.SetValue( initialValue, 0)
83
84
85 def createDialog( self, parent, id, pos, size, style ):
86 """Setup the graphic representation of the dialog"""
87 wxPanel.__init__ (self, parent, id, pos, size, style)
88 # try to set the background colour
89 try:
90 self.SetBackgroundColour(self._bc)
91 except:
92 pass
93 box = wxBoxSizer(wxHORIZONTAL)
94
95 self.label = self.createLabel( )
96 box.Add( self.label, 0, wxCENTER )
97
98 self.textControl = self.createTextControl()
99 box.Add( self.textControl, 1, wxLEFT|wxCENTER, 5)
100
101 self.browseButton = self.createBrowseButton()
102 box.Add( self.browseButton, 0, wxCENTER)
103
104 # add a border around the whole thing and resize the panel to fit
105 outsidebox = wxBoxSizer(wxVERTICAL)
106 outsidebox.Add(box, 1, wxEXPAND|wxALL, 3)
107 outsidebox.Fit(self)
108
109 self.SetAutoLayout(true)
110 self.SetSizer( outsidebox )
111 self.Layout()
112 if type( size ) == types.TupleType:
113 size = apply( wxSize, size)
114 if size.width != -1 or size.height != -1:
115 self.SetSize(size)
116
117 def SetBackgroundColour(self,color):
118 wxPanel.SetBackgroundColour(self,color)
119 self.label.SetBackgroundColour(color)
120
121 def createLabel( self ):
122 """Create the label/caption"""
123 label = wxStaticText(self, -1, self.labelText, style =wxALIGN_RIGHT )
124 font = label.GetFont()
125 w, h, d, e = self.GetFullTextExtent(self.labelText, font)
126 label.SetSize(wxSize(w+5, h))
127 return label
128
129 def createTextControl( self):
130 """Create the text control"""
131 ID = wxNewId()
132 textControl = wxTextCtrl(self, ID)
133 textControl.SetToolTipString( self.toolTip )
134 if self.changeCallback:
135 EVT_TEXT(textControl, ID, self.OnChanged)
136 EVT_COMBOBOX(textControl, ID, self.OnChanged)
137 return textControl
138
139 def OnChanged(self, evt):
140 if self.callCallback and self.changeCallback:
141 self.changeCallback(evt)
142
143 def createBrowseButton( self):
144 """Create the browse-button control"""
145 ID = wxNewId()
146 button =wxButton(self, ID, self.buttonText)
147 button.SetToolTipString( self.toolTip )
148 EVT_BUTTON(button, ID, self.OnBrowse)
149 return button
150
151
152 def OnBrowse (self, event = None):
153 """ Going to browse for file... """
154 current = self.GetValue()
155 directory = os.path.split(current)
156 if os.path.isdir( current):
157 directory = current
158 current = ''
159 elif directory and os.path.isdir( directory[0] ):
160 current = directory[1]
161 directory = directory [0]
162 else:
163 directory = self.startDirectory
164 dlg = wxFileDialog(self, self.dialogTitle, directory, current, self.fileMask, self.fileMode)
165
166 if dlg.ShowModal() == wxID_OK:
167 self.SetValue(dlg.GetPath())
168 dlg.Destroy()
169
170
171 def GetValue (self):
172 """ Convenient access to text control value """
173 return self.textControl.GetValue()
174
175 def SetValue (self, value, callBack=1):
176 """ Convenient setting of text control value """
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
202 class FileBrowseButtonWithHistory( FileBrowseButton ):
203 """ with following additions:
204 __init__(..., history=None)
205
206 history -- optional list of paths for initial history drop-down
207 (must be passed by name, not a positional argument)
208 If history is callable it will must return a list used
209 for the history drop-down
210 changeCallback -- as for FileBrowseButton, but with a work-around
211 for win32 systems which don't appear to create EVT_COMBOBOX
212 events properly. There is a (slight) chance that this work-around
213 will cause some systems to create two events for each Combobox
214 selection. If you discover this condition, please report it!
215 As for a FileBrowseButton.__init__ otherwise.
216 GetHistoryControl()
217 Return reference to the control which implements interfaces
218 required for manipulating the history list. See GetHistoryControl
219 documentation for description of what that interface is.
220 GetHistory()
221 Return current history list
222 SetHistory( value=(), selectionIndex = None )
223 Set current history list, if selectionIndex is not None, select that index
224 """
225 def __init__( self, *arguments, **namedarguments):
226 self.history = namedarguments.get( "history" )
227 if self.history:
228 del namedarguments["history"]
229
230 self.historyCallBack=None
231 if callable(self.history):
232 self.historyCallBack=self.history
233 self.history=None
234 apply( FileBrowseButton.__init__, ( self,)+arguments, namedarguments)
235
236
237 def createTextControl( self):
238 """Create the text control"""
239 ID = wxNewId()
240 textControl = wxComboBox(self, ID, style = wxCB_DROPDOWN )
241 textControl.SetToolTipString( self.toolTip )
242 EVT_SET_FOCUS(textControl, self.OnSetFocus)
243 if self.changeCallback:
244 EVT_TEXT(textControl, ID, self.changeCallback)
245 EVT_COMBOBOX(textControl, ID, self.changeCallback)
246 if self.history:
247 history=self.history
248 self.history=None
249 self.SetHistory( history, control=textControl)
250 return textControl
251
252
253 def GetHistoryControl( self ):
254 """Return a pointer to the control which provides (at least)
255 the following methods for manipulating the history list.:
256 Append( item ) -- add item
257 Clear() -- clear all items
258 Delete( index ) -- 0-based index to delete from list
259 SetSelection( index ) -- 0-based index to select in list
260 Semantics of the methods follow those for the wxComboBox control
261 """
262 return self.textControl
263
264
265 def SetHistory( self, value=(), selectionIndex = None, control=None ):
266 """Set the current history list"""
267 if control is None:
268 control = self.GetHistoryControl()
269 if self.history == value:
270 return
271 self.history = value
272 # Clear history values not the selected one.
273 tempValue=control.GetValue()
274 # clear previous values
275 control.Clear()
276 control.SetValue(tempValue)
277 # walk through, appending new values
278 for path in value:
279 control.Append( path )
280 if selectionIndex is not None:
281 control.SetSelection( selectionIndex )
282
283
284 def GetHistory( self ):
285 """Return the current history list"""
286 if self.historyCallBack != None:
287 return self.historyCallBack()
288 else:
289 return list( self.history )
290
291
292 def OnSetFocus(self, event):
293 """When the history scroll is selected, update the history"""
294 if self.historyCallBack != None:
295 self.SetHistory( self.historyCallBack(), control=self.textControl)
296 event.Skip()
297
298
299 if wxPlatform == "__WXMSW__":
300 def SetValue (self, value, callBack=1):
301 """ Convenient setting of text control value, works
302 around limitation of wxComboBox """
303 save = self.callCallback
304 self.callCallback = callBack
305 self.textControl.SetValue(value)
306 self.callCallback = save
307
308 # Hack to call an event handler
309 class LocalEvent:
310 def __init__(self, string):
311 self._string=string
312 def GetString(self):
313 return self._string
314 if callBack==1:
315 # The callback wasn't being called when SetValue was used ??
316 # So added this explicit call to it
317 self.changeCallback(LocalEvent(value))
318
319
320 class DirBrowseButton(FileBrowseButton):
321 def __init__(self, parent, id = -1,
322 pos = wxDefaultPosition, size = wxDefaultSize,
323 style = wxTAB_TRAVERSAL,
324 labelText = 'Select a directory:',
325 buttonText = 'Browse',
326 toolTip = 'Type directory name or browse to select',
327 dialogTitle = '',
328 startDirectory = '.',
329 changeCallback = None,
330 dialogClass = wxDirDialog):
331 FileBrowseButton.__init__(self, parent, id, pos, size, style,
332 labelText, buttonText, toolTip,
333 dialogTitle, startDirectory,
334 changeCallback = changeCallback)
335 #
336 self._dirDialog = dialogClass(self,
337 message = dialogTitle,
338 defaultPath = startDirectory)
339 #
340 def OnBrowse(self, ev = None):
341 dialog = self._dirDialog
342 if dialog.ShowModal() == wxID_OK:
343 self.SetValue(dialog.GetPath())
344 #
345 def __del__(self):
346 if self.__dict__.has_key('_dirDialog'):
347 self._dirDialog.Destroy()
348
349
350 #----------------------------------------------------------------------
351
352
353 if __name__ == "__main__":
354 #from skeletonbuilder import rulesfile
355 class SimpleCallback:
356 def __init__( self, tag ):
357 self.tag = tag
358 def __call__( self, event ):
359 print self.tag, event.GetString()
360 class DemoFrame( wxFrame ):
361 def __init__(self, parent):
362 wxFrame.__init__(self, parent, 2400, "File entry with browse", size=(500,260) )
363 EVT_CLOSE(self, self.OnCloseWindow)
364 panel = wxPanel (self,-1)
365 innerbox = wxBoxSizer(wxVERTICAL)
366 control = FileBrowseButton(
367 panel,
368 initialValue = "z:\\temp",
369 )
370 innerbox.Add( control, 0, wxEXPAND )
371 middlecontrol = FileBrowseButtonWithHistory(
372 panel,
373 labelText = "With History",
374 initialValue = "d:\\temp",
375 history = ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"],
376 changeCallback= SimpleCallback( "With History" ),
377 )
378 innerbox.Add( middlecontrol, 0, wxEXPAND )
379 middlecontrol = FileBrowseButtonWithHistory(
380 panel,
381 labelText = "History callback",
382 initialValue = "d:\\temp",
383 history = self.historyCallBack,
384 changeCallback= SimpleCallback( "History callback" ),
385 )
386 innerbox.Add( middlecontrol, 0, wxEXPAND )
387 self.bottomcontrol = control = FileBrowseButton(
388 panel,
389 labelText = "With Callback",
390 style = wxSUNKEN_BORDER|wxCLIP_CHILDREN ,
391 changeCallback= SimpleCallback( "With Callback" ),
392 )
393 innerbox.Add( control, 0, wxEXPAND)
394 self.bottommostcontrol = control = DirBrowseButton(
395 panel,
396 labelText = "Simple dir browse button",
397 style = wxSUNKEN_BORDER|wxCLIP_CHILDREN)
398 innerbox.Add( control, 0, wxEXPAND)
399 ID = wxNewId()
400 innerbox.Add( wxButton( panel, ID,"Change Label", ), 1, wxEXPAND)
401 EVT_BUTTON( self, ID, self.OnChangeLabel )
402 ID = wxNewId()
403 innerbox.Add( wxButton( panel, ID,"Change Value", ), 1, wxEXPAND)
404 EVT_BUTTON( self, ID, self.OnChangeValue )
405 panel.SetAutoLayout(true)
406 panel.SetSizer( innerbox )
407 self.history={"c:\\temp":1, "c:\\tmp":1, "r:\\temp":1,"z:\\temp":1}
408
409 def historyCallBack(self):
410 keys=self.history.keys()
411 keys.sort()
412 return keys
413
414 def OnFileNameChangedHistory (self, event):
415 self.history[event.GetString ()]=1
416
417 def OnCloseMe(self, event):
418 self.Close(true)
419 def OnChangeLabel( self, event ):
420 self.bottomcontrol.SetLabel( "Label Updated" )
421 def OnChangeValue( self, event ):
422 self.bottomcontrol.SetValue( "r:\\somewhere\\over\\the\\rainbow.htm" )
423
424 def OnCloseWindow(self, event):
425 self.Destroy()
426
427 class DemoApp(wxApp):
428 def OnInit(self):
429 wxImage_AddHandler(wxJPEGHandler())
430 wxImage_AddHandler(wxPNGHandler())
431 wxImage_AddHandler(wxGIFHandler())
432 frame = DemoFrame(NULL)
433 #frame = RulesPanel(NULL )
434 frame.Show(true)
435 self.SetTopWindow(frame)
436 return true
437
438 def test( ):
439 app = DemoApp(0)
440 app.MainLoop()
441 print 'Creating dialog'
442 test( )
443
444
445