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