]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/filebrowsebutton.py
Correct way to find the region
[wxWidgets.git] / wxPython / wx / lib / filebrowsebutton.py
CommitLineData
d14a1e28
RD
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#----------------------------------------------------------------------
b881fc78
RD
14# 12/02/2003 - Jeff Grimmett (grimmtooth@softhome.net)
15#
16# o 2.5 Compatability changes
17#
18
19import os
20import types
d14a1e28 21
b881fc78 22import wx
d14a1e28
RD
23
24#----------------------------------------------------------------------
25
b881fc78 26class FileBrowseButton(wx.Panel):
fdc775af
RD
27 """
28 A control to allow the user to type in a filename or browse with
29 the standard file dialog to select file
d14a1e28
RD
30 """
31 def __init__ (self, parent, id= -1,
fdc775af
RD
32 pos = wx.DefaultPosition,
33 size = wx.DefaultSize,
34 style = wx.TAB_TRAVERSAL,
35 labelText= "File Entry:",
36 buttonText= "Browse",
37 toolTip= "Type filename or click browse to choose file",
38 # following are the values for a file dialog box
39 dialogTitle = "Choose a file",
40 startDirectory = ".",
41 initialValue = "",
42 fileMask = "*.*",
43 fileMode = wx.OPEN,
44 # callback for when value changes (optional)
45 changeCallback= lambda x:x
d14a1e28 46 ):
fdc775af
RD
47 """
48 :param labelText: Text for label to left of text field
49 :param buttonText: Text for button which launches the file dialog
50 :param toolTip: Help text
51 :param dialogTitle: Title used in file dialog
52 :param startDirectory: Default directory for file dialog startup
53 :param fileMask: File mask (glob pattern, such as *.*) to use in file dialog
54 :param fileMode: wx.OPEN or wx.SAVE, indicates type of file dialog to use
acb04297 55 :param changeCallback: Optional callback called for all changes in value of the control
fdc775af
RD
56 """
57
d14a1e28
RD
58 # store variables
59 self.labelText = labelText
60 self.buttonText = buttonText
61 self.toolTip = toolTip
62 self.dialogTitle = dialogTitle
63 self.startDirectory = startDirectory
64 self.initialValue = initialValue
65 self.fileMask = fileMask
66 self.fileMode = fileMode
67 self.changeCallback = changeCallback
68 self.callCallback = True
69
70
71 # get background to match it
72 try:
73 self._bc = parent.GetBackgroundColour()
74 except:
75 pass
76
77 # create the dialog
78 self.createDialog(parent, id, pos, size, style )
79 # Setting a value causes the changeCallback to be called.
80 # In this case that would be before the return of the
81 # constructor. Not good. So a default value on
82 # SetValue is used to disable the callback
83 self.SetValue( initialValue, 0)
84
85
86 def createDialog( self, parent, id, pos, size, style ):
87 """Setup the graphic representation of the dialog"""
b881fc78 88 wx.Panel.__init__ (self, parent, id, pos, size, style)
acb04297
RD
89 self.SetMinSize(size) # play nice with sizers
90
d14a1e28
RD
91 # try to set the background colour
92 try:
acb7a89a
KO
93 #Question: is this still needed on other platforms?
94 #It should have transparent background on Mac
95 if wx.Platform != "__WXMAC__":
96 self.SetBackgroundColour(self._bc)
d14a1e28
RD
97 except:
98 pass
acb04297 99
b881fc78 100 box = wx.BoxSizer(wx.HORIZONTAL)
d14a1e28
RD
101
102 self.label = self.createLabel( )
b881fc78 103 box.Add( self.label, 0, wx.CENTER )
d14a1e28
RD
104
105 self.textControl = self.createTextControl()
b881fc78 106 box.Add( self.textControl, 1, wx.LEFT|wx.CENTER, 5)
d14a1e28
RD
107
108 self.browseButton = self.createBrowseButton()
b881fc78 109 box.Add( self.browseButton, 0, wx.LEFT|wx.CENTER, 5)
d14a1e28
RD
110
111 # add a border around the whole thing and resize the panel to fit
b881fc78
RD
112 outsidebox = wx.BoxSizer(wx.VERTICAL)
113 outsidebox.Add(box, 1, wx.EXPAND|wx.ALL, 3)
d14a1e28
RD
114 outsidebox.Fit(self)
115
116 self.SetAutoLayout(True)
117 self.SetSizer( outsidebox )
118 self.Layout()
119 if type( size ) == types.TupleType:
b881fc78
RD
120 size = apply( wx.Size, size)
121 self.SetDimensions(-1, -1, size.width, size.height, wx.SIZE_USE_EXISTING)
d14a1e28
RD
122
123# if size.width != -1 or size.height != -1:
124# self.SetSize(size)
125
126 def SetBackgroundColour(self,color):
b881fc78 127 wx.Panel.SetBackgroundColour(self,color)
d14a1e28
RD
128 self.label.SetBackgroundColour(color)
129
130 def createLabel( self ):
131 """Create the label/caption"""
b881fc78 132 label = wx.StaticText(self, -1, self.labelText, style =wx.ALIGN_RIGHT )
d14a1e28
RD
133 font = label.GetFont()
134 w, h, d, e = self.GetFullTextExtent(self.labelText, font)
b881fc78 135 label.SetSize((w+5, h))
d14a1e28
RD
136 return label
137
138 def createTextControl( self):
139 """Create the text control"""
b881fc78 140 textControl = wx.TextCtrl(self, -1)
d14a1e28
RD
141 textControl.SetToolTipString( self.toolTip )
142 if self.changeCallback:
b881fc78
RD
143 textControl.Bind(wx.EVT_TEXT, self.OnChanged)
144 textControl.Bind(wx.EVT_COMBOBOX, self.OnChanged)
d14a1e28
RD
145 return textControl
146
147 def OnChanged(self, evt):
148 if self.callCallback and self.changeCallback:
149 self.changeCallback(evt)
150
151 def createBrowseButton( self):
152 """Create the browse-button control"""
b881fc78 153 button =wx.Button(self, -1, self.buttonText)
d14a1e28 154 button.SetToolTipString( self.toolTip )
b881fc78 155 button.Bind(wx.EVT_BUTTON, self.OnBrowse)
d14a1e28
RD
156 return button
157
158
159 def OnBrowse (self, event = None):
160 """ Going to browse for file... """
161 current = self.GetValue()
162 directory = os.path.split(current)
163 if os.path.isdir( current):
164 directory = current
165 current = ''
166 elif directory and os.path.isdir( directory[0] ):
167 current = directory[1]
168 directory = directory [0]
169 else:
170 directory = self.startDirectory
b881fc78
RD
171 dlg = wx.FileDialog(self, self.dialogTitle, directory, current,
172 self.fileMask, self.fileMode)
d14a1e28 173
b881fc78 174 if dlg.ShowModal() == wx.ID_OK:
d14a1e28
RD
175 self.SetValue(dlg.GetPath())
176 dlg.Destroy()
177
178
179 def GetValue (self):
fdc775af
RD
180 """
181 retrieve current value of text control
182 """
d14a1e28
RD
183 return self.textControl.GetValue()
184
185 def SetValue (self, value, callBack=1):
fdc775af 186 """set current value of text control"""
d14a1e28
RD
187 save = self.callCallback
188 self.callCallback = callBack
189 self.textControl.SetValue(value)
190 self.callCallback = save
191
192
193 def Enable (self, value):
194 """ Convenient enabling/disabling of entire control """
195 self.label.Enable (value)
196 self.textControl.Enable (value)
197 return self.browseButton.Enable (value)
198
199 def GetLabel( self ):
200 """ Retrieve the label's current text """
201 return self.label.GetLabel()
202
203 def SetLabel( self, value ):
204 """ Set the label's current text """
205 rvalue = self.label.SetLabel( value )
206 self.Refresh( True )
207 return rvalue
208
209
210
211
212class FileBrowseButtonWithHistory( FileBrowseButton ):
fdc775af
RD
213 """
214 with following additions:
d14a1e28
RD
215 __init__(..., history=None)
216
217 history -- optional list of paths for initial history drop-down
218 (must be passed by name, not a positional argument)
219 If history is callable it will must return a list used
220 for the history drop-down
fdc775af 221
d14a1e28 222 changeCallback -- as for FileBrowseButton, but with a work-around
b881fc78 223 for win32 systems which don't appear to create wx.EVT_COMBOBOX
d14a1e28
RD
224 events properly. There is a (slight) chance that this work-around
225 will cause some systems to create two events for each Combobox
226 selection. If you discover this condition, please report it!
fdc775af 227
d14a1e28 228 As for a FileBrowseButton.__init__ otherwise.
fdc775af 229
d14a1e28
RD
230 GetHistoryControl()
231 Return reference to the control which implements interfaces
232 required for manipulating the history list. See GetHistoryControl
233 documentation for description of what that interface is.
fdc775af 234
d14a1e28
RD
235 GetHistory()
236 Return current history list
fdc775af 237
d14a1e28
RD
238 SetHistory( value=(), selectionIndex = None )
239 Set current history list, if selectionIndex is not None, select that index
fdc775af 240
d14a1e28
RD
241 """
242 def __init__( self, *arguments, **namedarguments):
243 self.history = namedarguments.get( "history" )
244 if self.history:
245 del namedarguments["history"]
246
247 self.historyCallBack=None
248 if callable(self.history):
249 self.historyCallBack=self.history
250 self.history=None
251 apply( FileBrowseButton.__init__, ( self,)+arguments, namedarguments)
252
253
254 def createTextControl( self):
255 """Create the text control"""
b881fc78 256 textControl = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN )
d14a1e28 257 textControl.SetToolTipString( self.toolTip )
b881fc78 258 textControl.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
d14a1e28 259 if self.changeCallback:
b881fc78
RD
260 textControl.Bind(wx.EVT_TEXT, self.changeCallback)
261 textControl.Bind(wx.EVT_COMBOBOX, self.changeCallback)
d14a1e28
RD
262 if self.history:
263 history=self.history
264 self.history=None
265 self.SetHistory( history, control=textControl)
266 return textControl
267
268
269 def GetHistoryControl( self ):
fdc775af
RD
270 """
271 Return a pointer to the control which provides (at least)
272 the following methods for manipulating the history list:
273
d14a1e28
RD
274 Append( item ) -- add item
275 Clear() -- clear all items
276 Delete( index ) -- 0-based index to delete from list
277 SetSelection( index ) -- 0-based index to select in list
fdc775af 278
d14a1e28
RD
279 Semantics of the methods follow those for the wxComboBox control
280 """
281 return self.textControl
282
283
284 def SetHistory( self, value=(), selectionIndex = None, control=None ):
285 """Set the current history list"""
286 if control is None:
287 control = self.GetHistoryControl()
288 if self.history == value:
289 return
290 self.history = value
291 # Clear history values not the selected one.
292 tempValue=control.GetValue()
293 # clear previous values
294 control.Clear()
295 control.SetValue(tempValue)
296 # walk through, appending new values
297 for path in value:
298 control.Append( path )
299 if selectionIndex is not None:
300 control.SetSelection( selectionIndex )
301
302
303 def GetHistory( self ):
304 """Return the current history list"""
305 if self.historyCallBack != None:
306 return self.historyCallBack()
307 else:
308 return list( self.history )
309
310
311 def OnSetFocus(self, event):
312 """When the history scroll is selected, update the history"""
313 if self.historyCallBack != None:
314 self.SetHistory( self.historyCallBack(), control=self.textControl)
315 event.Skip()
316
317
b881fc78 318 if wx.Platform == "__WXMSW__":
d14a1e28
RD
319 def SetValue (self, value, callBack=1):
320 """ Convenient setting of text control value, works
b881fc78 321 around limitation of wx.ComboBox """
d14a1e28
RD
322 save = self.callCallback
323 self.callCallback = callBack
324 self.textControl.SetValue(value)
325 self.callCallback = save
326
327 # Hack to call an event handler
328 class LocalEvent:
329 def __init__(self, string):
330 self._string=string
331 def GetString(self):
332 return self._string
333 if callBack==1:
334 # The callback wasn't being called when SetValue was used ??
335 # So added this explicit call to it
336 self.changeCallback(LocalEvent(value))
337
338
339class DirBrowseButton(FileBrowseButton):
340 def __init__(self, parent, id = -1,
b881fc78
RD
341 pos = wx.DefaultPosition, size = wx.DefaultSize,
342 style = wx.TAB_TRAVERSAL,
d14a1e28
RD
343 labelText = 'Select a directory:',
344 buttonText = 'Browse',
345 toolTip = 'Type directory name or browse to select',
346 dialogTitle = '',
347 startDirectory = '.',
348 changeCallback = None,
280432a9
RD
349 dialogClass = wx.DirDialog,
350 newDirectory = False):
d14a1e28
RD
351 FileBrowseButton.__init__(self, parent, id, pos, size, style,
352 labelText, buttonText, toolTip,
353 dialogTitle, startDirectory,
354 changeCallback = changeCallback)
6046f864 355 self.dialogClass = dialogClass
280432a9 356 self.newDirectory = newDirectory
d14a1e28 357 #
6046f864 358
d14a1e28 359 def OnBrowse(self, ev = None):
280432a9
RD
360 style=0
361
362 if self.newDirectory:
363 style|=wx.DD_NEW_DIR_BUTTON
364
6046f864
RD
365 dialog = self.dialogClass(self,
366 message = self.dialogTitle,
280432a9
RD
367 defaultPath = self.startDirectory,
368 style = style)
369
b881fc78 370 if dialog.ShowModal() == wx.ID_OK:
d14a1e28 371 self.SetValue(dialog.GetPath())
6046f864 372 dialog.Destroy()
d14a1e28 373 #
d14a1e28
RD
374
375
376#----------------------------------------------------------------------
377
378
379if __name__ == "__main__":
380 #from skeletonbuilder import rulesfile
381 class SimpleCallback:
382 def __init__( self, tag ):
383 self.tag = tag
384 def __call__( self, event ):
385 print self.tag, event.GetString()
b881fc78 386 class DemoFrame( wx.Frame ):
d14a1e28 387 def __init__(self, parent):
b881fc78
RD
388 wx.Frame.__init__(self, parent, -1, "File entry with browse", size=(500,260))
389 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
390 panel = wx.Panel (self,-1)
391 innerbox = wx.BoxSizer(wx.VERTICAL)
d14a1e28
RD
392 control = FileBrowseButton(
393 panel,
394 initialValue = "z:\\temp",
395 )
b881fc78 396 innerbox.Add( control, 0, wx.EXPAND )
d14a1e28
RD
397 middlecontrol = FileBrowseButtonWithHistory(
398 panel,
399 labelText = "With History",
400 initialValue = "d:\\temp",
401 history = ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"],
402 changeCallback= SimpleCallback( "With History" ),
403 )
b881fc78 404 innerbox.Add( middlecontrol, 0, wx.EXPAND )
d14a1e28
RD
405 middlecontrol = FileBrowseButtonWithHistory(
406 panel,
407 labelText = "History callback",
408 initialValue = "d:\\temp",
409 history = self.historyCallBack,
410 changeCallback= SimpleCallback( "History callback" ),
411 )
b881fc78 412 innerbox.Add( middlecontrol, 0, wx.EXPAND )
d14a1e28
RD
413 self.bottomcontrol = control = FileBrowseButton(
414 panel,
415 labelText = "With Callback",
b881fc78 416 style = wx.SUNKEN_BORDER|wx.CLIP_CHILDREN ,
d14a1e28
RD
417 changeCallback= SimpleCallback( "With Callback" ),
418 )
b881fc78 419 innerbox.Add( control, 0, wx.EXPAND)
d14a1e28
RD
420 self.bottommostcontrol = control = DirBrowseButton(
421 panel,
422 labelText = "Simple dir browse button",
b881fc78
RD
423 style = wx.SUNKEN_BORDER|wx.CLIP_CHILDREN)
424 innerbox.Add( control, 0, wx.EXPAND)
425 ID = wx.NewId()
426 innerbox.Add( wx.Button( panel, ID,"Change Label", ), 1, wx.EXPAND)
427 self.Bind(wx.EVT_BUTTON, self.OnChangeLabel , id=ID)
428 ID = wx.NewId()
429 innerbox.Add( wx.Button( panel, ID,"Change Value", ), 1, wx.EXPAND)
430 self.Bind(wx.EVT_BUTTON, self.OnChangeValue, id=ID )
d14a1e28
RD
431 panel.SetAutoLayout(True)
432 panel.SetSizer( innerbox )
433 self.history={"c:\\temp":1, "c:\\tmp":1, "r:\\temp":1,"z:\\temp":1}
434
435 def historyCallBack(self):
436 keys=self.history.keys()
437 keys.sort()
438 return keys
439
440 def OnFileNameChangedHistory (self, event):
441 self.history[event.GetString ()]=1
442
443 def OnCloseMe(self, event):
444 self.Close(True)
445 def OnChangeLabel( self, event ):
446 self.bottomcontrol.SetLabel( "Label Updated" )
447 def OnChangeValue( self, event ):
448 self.bottomcontrol.SetValue( "r:\\somewhere\\over\\the\\rainbow.htm" )
449
450 def OnCloseWindow(self, event):
451 self.Destroy()
452
b881fc78 453 class DemoApp(wx.App):
d14a1e28 454 def OnInit(self):
b881fc78
RD
455 wx.InitAllImageHandlers()
456 frame = DemoFrame(None)
d14a1e28
RD
457 frame.Show(True)
458 self.SetTopWindow(frame)
459 return True
460
461 def test( ):
462 app = DemoApp(0)
463 app.MainLoop()
464 print 'Creating dialog'
465 test( )
466
1fded56b 467
1fded56b 468