]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/filebrowsebutton.py
731a48dd3447a5f4310737b75885661799ac7650
[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
68 # get background to match it
69 try:
70 self._bc = parent.GetBackgroundColour()
71 except:
72 pass
73
74 # create the dialog
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)
81
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
86 try:
87 self.SetBackgroundColour(self._bc)
88 except:
89 pass
90 box = wxBoxSizer(wxHORIZONTAL)
91
92 self.label = self.createLabel( )
93 box.Add( self.label, 0, wxCENTER )
94
95 self.textControl = self.createTextControl()
96 box.Add( self.textControl, 1, wxLEFT|wxCENTER, 5)
97
98 self.browseButton = self.createBrowseButton()
99 box.Add( self.browseButton, 0, wxCENTER)
100
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)
104 outsidebox.Fit(self)
105
106 self.SetAutoLayout(true)
107 self.SetSizer( outsidebox )
108 self.Layout()
109 if size.width != -1 or size.height != -1:
110 self.SetSize(size)
111
112 def SetBackgroundColour(self,color):
113 wxPanel.SetBackgroundColour(self,color)
114 self.label.SetBackgroundColour(color)
115
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))
122 return label
123
124 def createTextControl( self):
125 """Create the text control"""
126 ID = wxNewId()
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)
132 return textControl
133
134 def createBrowseButton( self):
135 """Create the browse-button control"""
136 ID = wxNewId()
137 button =wxButton(self, ID, self.buttonText)
138 button.SetToolTipString( self.toolTip )
139 EVT_BUTTON(button, ID, self.OnBrowse)
140 return button
141
142
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):
148 directory = current
149 current = ''
150 elif directory and os.path.isdir( directory[0] ):
151 current = directory[1]
152 directory = directory [0]
153 else:
154 directory = self.startDirectory
155 dlg = wxFileDialog(self, self.dialogTitle, directory, current, self.fileMask, self.fileMode)
156
157 if dlg.ShowModal() == wxID_OK:
158 self.SetValue (dlg.GetPath())
159 dlg.Destroy()
160
161
162
163 def GetValue (self):
164 """ Convenient access to text control value """
165 return self.textControl.GetValue ()
166
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)
171
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)
177
178 def GetLabel( self ):
179 """ Retrieve the label's current text """
180 return self.label.GetLabel()
181
182 def SetLabel( self, value ):
183 """ Set the label's current text """
184 rvalue = self.label.SetLabel( value )
185 self.Refresh( true )
186 return rvalue
187
188
189
190 class FileBrowseButtonWithHistory( FileBrowseButton ):
191 """ with following additions:
192 __init__(..., history=None)
193
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.
204 GetHistoryControl()
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.
208 GetHistory()
209 Return current history list
210 SetHistory( value=(), selectionIndex = None )
211 Set current history list, if selectionIndex is not None, select that index
212 """
213 def __init__( self, *arguments, **namedarguments):
214 self.history = namedarguments.get( "history" )
215 if self.history:
216 del namedarguments["history"]
217
218 self.historyCallBack=None
219 if callable(self.history):
220 self.historyCallBack=self.history
221 self.history=None
222 apply( FileBrowseButton.__init__, ( self,)+arguments, namedarguments)
223
224 def createTextControl( self):
225 """Create the text control"""
226 ID = wxNewId()
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)
233 if self.history:
234 history=self.history
235 self.history=None
236 self.SetHistory( history, control=textControl)
237 return textControl
238
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
247 """
248 return self.textControl
249
250 def SetHistory( self, value=(), selectionIndex = None, control=None ):
251 """Set the current history list"""
252 if control is None:
253 control = self.GetHistoryControl()
254 if self.history == value:
255 return
256 self.history = value
257 # Clear history values not the selected one.
258 tempValue=control.GetValue()
259 # clear previous values
260 control.Clear()
261 control.SetValue(tempValue)
262 # walk through, appending new values
263 for path in value:
264 control.Append( path )
265 if selectionIndex is not None:
266 control.SetSelection( selectionIndex )
267
268 def GetHistory( self ):
269 """Return the current history list"""
270 if self.historyCallBack != None:
271 return self.historyCallBack()
272 else:
273 return list( self.history )
274
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)
279 event.Skip()
280
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
288 class LocalEvent:
289 def __init__(self, string):
290 self._string=string
291 def GetString(self):
292 return self._string
293 if callBack==1:
294 # The callback wasn't being called when SetValue was used ??
295 # So added this explicit call to it
296 self.changeCallback(LocalEvent(value))
297
298
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',
306 dialogTitle = '',
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)
314 #
315 self._dirDialog = dialogClass(self,
316 message = dialogTitle,
317 defaultPath = startDirectory)
318 #
319 def OnBrowse(self, ev = None):
320 dialog = self._dirDialog
321 if dialog.ShowModal() == wxID_OK:
322 self.SetValue(dialog.GetPath())
323 #
324 def __del__(self):
325 if self.__dict__.has_key('_dirDialog'):
326 self._dirDialog.Destroy()
327
328
329 #----------------------------------------------------------------------
330
331
332 if __name__ == "__main__":
333 #from skeletonbuilder import rulesfile
334 class SimpleCallback:
335 def __init__( self, tag ):
336 self.tag = 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(
346 panel,
347 initialValue = "z:\\temp",
348 )
349 innerbox.Add( control, 0, wxEXPAND )
350 middlecontrol = FileBrowseButtonWithHistory(
351 panel,
352 labelText = "With History",
353 initialValue = "d:\\temp",
354 history = ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"],
355 changeCallback= SimpleCallback( "With History" ),
356 )
357 innerbox.Add( middlecontrol, 0, wxEXPAND )
358 middlecontrol = FileBrowseButtonWithHistory(
359 panel,
360 labelText = "History callback",
361 initialValue = "d:\\temp",
362 history = self.historyCallBack,
363 changeCallback= SimpleCallback( "History callback" ),
364 )
365 innerbox.Add( middlecontrol, 0, wxEXPAND )
366 self.bottomcontrol = control = FileBrowseButton(
367 panel,
368 labelText = "With Callback",
369 style = wxSUNKEN_BORDER|wxCLIP_CHILDREN ,
370 changeCallback= SimpleCallback( "With Callback" ),
371 )
372 innerbox.Add( control, 0, wxEXPAND)
373 self.bottommostcontrol = control = DirBrowseButton(
374 panel,
375 labelText = "Simple dir browse button",
376 style = wxSUNKEN_BORDER|wxCLIP_CHILDREN)
377 innerbox.Add( control, 0, wxEXPAND)
378 ID = wxNewId()
379 innerbox.Add( wxButton( panel, ID,"Change Label", ), 1, wxEXPAND)
380 EVT_BUTTON( self, ID, self.OnChangeLabel )
381 ID = wxNewId()
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}
387
388 def historyCallBack(self):
389 keys=self.history.keys()
390 keys.sort()
391 return keys
392
393 def OnFileNameChangedHistory (self, event):
394 self.history[event.GetString ()]=1
395
396 def OnCloseMe(self, event):
397 self.Close(true)
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" )
402
403 def OnCloseWindow(self, event):
404 self.Destroy()
405
406 class DemoApp(wxApp):
407 def OnInit(self):
408 wxImage_AddHandler(wxJPEGHandler())
409 wxImage_AddHandler(wxPNGHandler())
410 wxImage_AddHandler(wxGIFHandler())
411 frame = DemoFrame(NULL)
412 #frame = RulesPanel(NULL )
413 frame.Show(true)
414 self.SetTopWindow(frame)
415 return true
416
417 def test( ):
418 app = DemoApp(0)
419 app.MainLoop()
420 print 'Creating dialog'
421 test( )
422
423
424