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