X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1fded56b375bf7a4687af1cdb182899614c1b2a8..28e5e577e4d26332a7ebdf7d1dc7492807fa1601:/wxPython/wx/lib/filebrowsebutton.py diff --git a/wxPython/wx/lib/filebrowsebutton.py b/wxPython/wx/lib/filebrowsebutton.py index b8f48bd212..e9481d5daa 100644 --- a/wxPython/wx/lib/filebrowsebutton.py +++ b/wxPython/wx/lib/filebrowsebutton.py @@ -1,11 +1,447 @@ +#---------------------------------------------------------------------- +# Name: wxPython.lib.filebrowsebutton +# Purpose: Composite controls that provide a Browse button next to +# either a wxTextCtrl or a wxComboBox. The Browse button +# launches a wxFileDialog and loads the result into the +# other control. +# +# Author: Mike Fletcher +# +# RCS-ID: $Id$ +# Copyright: (c) 2000 by Total Control Software +# Licence: wxWindows license +#---------------------------------------------------------------------- + +from wxPython.wx import * +import os, types + +#---------------------------------------------------------------------- + +class FileBrowseButton(wxPanel): + """ A control to allow the user to type in a filename + or browse with the standard file dialog to select file + + __init__ ( + parent, id, pos, size -- passed directly to wxPanel initialisation + style = wxTAB_TRAVERSAL -- passed directly to wxPanel initialisation + labelText -- Text for label to left of text field + buttonText -- Text for button which launches the file dialog + toolTip -- Help text + dialogTitle -- Title used in file dialog + startDirectory -- Default directory for file dialog startup + fileMask -- File mask (glob pattern, such as *.*) to use in file dialog + fileMode -- wxOPEN or wxSAVE, indicates type of file dialog to use + changeCallback -- callback receives all > > changes in value of control + ) + GetValue() -- retrieve current value of text control + SetValue(string) -- set current value of text control + label -- pointer to internal label widget + textControl -- pointer to internal text control + browseButton -- pointer to button + """ + def __init__ (self, parent, id= -1, + pos = wxDefaultPosition, size = wxDefaultSize, + style = wxTAB_TRAVERSAL, + labelText= "File Entry:", + buttonText= "Browse", + toolTip= "Type filename or click browse to choose file", + # following are the values for a file dialog box + dialogTitle = "Choose a file", + startDirectory = ".", + initialValue = "", + fileMask = "*.*", + fileMode = wxOPEN, + # callback for when value changes (optional) + changeCallback= lambda x:x + ): + # store variables + self.labelText = labelText + self.buttonText = buttonText + self.toolTip = toolTip + self.dialogTitle = dialogTitle + self.startDirectory = startDirectory + self.initialValue = initialValue + self.fileMask = fileMask + self.fileMode = fileMode + self.changeCallback = changeCallback + self.callCallback = True + + + # get background to match it + try: + self._bc = parent.GetBackgroundColour() + except: + pass + + # create the dialog + self.createDialog(parent, id, pos, size, style ) + # Setting a value causes the changeCallback to be called. + # In this case that would be before the return of the + # constructor. Not good. So a default value on + # SetValue is used to disable the callback + self.SetValue( initialValue, 0) + + + def createDialog( self, parent, id, pos, size, style ): + """Setup the graphic representation of the dialog""" + wxPanel.__init__ (self, parent, id, pos, size, style) + # try to set the background colour + try: + self.SetBackgroundColour(self._bc) + except: + pass + box = wxBoxSizer(wxHORIZONTAL) + + self.label = self.createLabel( ) + box.Add( self.label, 0, wxCENTER ) + + self.textControl = self.createTextControl() + box.Add( self.textControl, 1, wxLEFT|wxCENTER, 5) + + self.browseButton = self.createBrowseButton() + box.Add( self.browseButton, 0, wxLEFT|wxCENTER, 5) + + # add a border around the whole thing and resize the panel to fit + outsidebox = wxBoxSizer(wxVERTICAL) + outsidebox.Add(box, 1, wxEXPAND|wxALL, 3) + outsidebox.Fit(self) + + self.SetAutoLayout(True) + self.SetSizer( outsidebox ) + self.Layout() + if type( size ) == types.TupleType: + size = apply( wxSize, size) + self.SetDimensions(-1, -1, size.width, size.height, wxSIZE_USE_EXISTING) + +# if size.width != -1 or size.height != -1: +# self.SetSize(size) + + def SetBackgroundColour(self,color): + wxPanel.SetBackgroundColour(self,color) + self.label.SetBackgroundColour(color) + + def createLabel( self ): + """Create the label/caption""" + label = wxStaticText(self, -1, self.labelText, style =wxALIGN_RIGHT ) + font = label.GetFont() + w, h, d, e = self.GetFullTextExtent(self.labelText, font) + label.SetSize(wxSize(w+5, h)) + return label + + def createTextControl( self): + """Create the text control""" + ID = wxNewId() + textControl = wxTextCtrl(self, ID) + textControl.SetToolTipString( self.toolTip ) + if self.changeCallback: + EVT_TEXT(textControl, ID, self.OnChanged) + EVT_COMBOBOX(textControl, ID, self.OnChanged) + return textControl + + def OnChanged(self, evt): + if self.callCallback and self.changeCallback: + self.changeCallback(evt) + + def createBrowseButton( self): + """Create the browse-button control""" + ID = wxNewId() + button =wxButton(self, ID, self.buttonText) + button.SetToolTipString( self.toolTip ) + EVT_BUTTON(button, ID, self.OnBrowse) + return button + + + def OnBrowse (self, event = None): + """ Going to browse for file... """ + current = self.GetValue() + directory = os.path.split(current) + if os.path.isdir( current): + directory = current + current = '' + elif directory and os.path.isdir( directory[0] ): + current = directory[1] + directory = directory [0] + else: + directory = self.startDirectory + dlg = wxFileDialog(self, self.dialogTitle, directory, current, self.fileMask, self.fileMode) + + if dlg.ShowModal() == wxID_OK: + self.SetValue(dlg.GetPath()) + dlg.Destroy() + + + def GetValue (self): + """ Convenient access to text control value """ + return self.textControl.GetValue() + + def SetValue (self, value, callBack=1): + """ Convenient setting of text control value """ + save = self.callCallback + self.callCallback = callBack + self.textControl.SetValue(value) + self.callCallback = save + + + def Enable (self, value): + """ Convenient enabling/disabling of entire control """ + self.label.Enable (value) + self.textControl.Enable (value) + return self.browseButton.Enable (value) + + def GetLabel( self ): + """ Retrieve the label's current text """ + return self.label.GetLabel() + + def SetLabel( self, value ): + """ Set the label's current text """ + rvalue = self.label.SetLabel( value ) + self.Refresh( True ) + return rvalue + + + + +class FileBrowseButtonWithHistory( FileBrowseButton ): + """ with following additions: + __init__(..., history=None) + + history -- optional list of paths for initial history drop-down + (must be passed by name, not a positional argument) + If history is callable it will must return a list used + for the history drop-down + changeCallback -- as for FileBrowseButton, but with a work-around + for win32 systems which don't appear to create EVT_COMBOBOX + events properly. There is a (slight) chance that this work-around + will cause some systems to create two events for each Combobox + selection. If you discover this condition, please report it! + As for a FileBrowseButton.__init__ otherwise. + GetHistoryControl() + Return reference to the control which implements interfaces + required for manipulating the history list. See GetHistoryControl + documentation for description of what that interface is. + GetHistory() + Return current history list + SetHistory( value=(), selectionIndex = None ) + Set current history list, if selectionIndex is not None, select that index + """ + def __init__( self, *arguments, **namedarguments): + self.history = namedarguments.get( "history" ) + if self.history: + del namedarguments["history"] + + self.historyCallBack=None + if callable(self.history): + self.historyCallBack=self.history + self.history=None + apply( FileBrowseButton.__init__, ( self,)+arguments, namedarguments) + + + def createTextControl( self): + """Create the text control""" + ID = wxNewId() + textControl = wxComboBox(self, ID, style = wxCB_DROPDOWN ) + textControl.SetToolTipString( self.toolTip ) + EVT_SET_FOCUS(textControl, self.OnSetFocus) + if self.changeCallback: + EVT_TEXT(textControl, ID, self.changeCallback) + EVT_COMBOBOX(textControl, ID, self.changeCallback) + if self.history: + history=self.history + self.history=None + self.SetHistory( history, control=textControl) + return textControl + + + def GetHistoryControl( self ): + """Return a pointer to the control which provides (at least) + the following methods for manipulating the history list.: + Append( item ) -- add item + Clear() -- clear all items + Delete( index ) -- 0-based index to delete from list + SetSelection( index ) -- 0-based index to select in list + Semantics of the methods follow those for the wxComboBox control + """ + return self.textControl + + + def SetHistory( self, value=(), selectionIndex = None, control=None ): + """Set the current history list""" + if control is None: + control = self.GetHistoryControl() + if self.history == value: + return + self.history = value + # Clear history values not the selected one. + tempValue=control.GetValue() + # clear previous values + control.Clear() + control.SetValue(tempValue) + # walk through, appending new values + for path in value: + control.Append( path ) + if selectionIndex is not None: + control.SetSelection( selectionIndex ) + + + def GetHistory( self ): + """Return the current history list""" + if self.historyCallBack != None: + return self.historyCallBack() + else: + return list( self.history ) + + + def OnSetFocus(self, event): + """When the history scroll is selected, update the history""" + if self.historyCallBack != None: + self.SetHistory( self.historyCallBack(), control=self.textControl) + event.Skip() + + + if wxPlatform == "__WXMSW__": + def SetValue (self, value, callBack=1): + """ Convenient setting of text control value, works + around limitation of wxComboBox """ + save = self.callCallback + self.callCallback = callBack + self.textControl.SetValue(value) + self.callCallback = save + + # Hack to call an event handler + class LocalEvent: + def __init__(self, string): + self._string=string + def GetString(self): + return self._string + if callBack==1: + # The callback wasn't being called when SetValue was used ?? + # So added this explicit call to it + self.changeCallback(LocalEvent(value)) + + +class DirBrowseButton(FileBrowseButton): + def __init__(self, parent, id = -1, + pos = wxDefaultPosition, size = wxDefaultSize, + style = wxTAB_TRAVERSAL, + labelText = 'Select a directory:', + buttonText = 'Browse', + toolTip = 'Type directory name or browse to select', + dialogTitle = '', + startDirectory = '.', + changeCallback = None, + dialogClass = wxDirDialog): + FileBrowseButton.__init__(self, parent, id, pos, size, style, + labelText, buttonText, toolTip, + dialogTitle, startDirectory, + changeCallback = changeCallback) + # + self._dirDialog = dialogClass(self, + message = dialogTitle, + defaultPath = startDirectory) + # + def OnBrowse(self, ev = None): + dialog = self._dirDialog + if dialog.ShowModal() == wxID_OK: + self.SetValue(dialog.GetPath()) + # + def __del__(self): + if self.__dict__.has_key('_dirDialog'): + self._dirDialog.Destroy() + + +#---------------------------------------------------------------------- + + +if __name__ == "__main__": + #from skeletonbuilder import rulesfile + class SimpleCallback: + def __init__( self, tag ): + self.tag = tag + def __call__( self, event ): + print self.tag, event.GetString() + class DemoFrame( wxFrame ): + def __init__(self, parent): + wxFrame.__init__(self, parent, 2400, "File entry with browse", size=(500,260) ) + EVT_CLOSE(self, self.OnCloseWindow) + panel = wxPanel (self,-1) + innerbox = wxBoxSizer(wxVERTICAL) + control = FileBrowseButton( + panel, + initialValue = "z:\\temp", + ) + innerbox.Add( control, 0, wxEXPAND ) + middlecontrol = FileBrowseButtonWithHistory( + panel, + labelText = "With History", + initialValue = "d:\\temp", + history = ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"], + changeCallback= SimpleCallback( "With History" ), + ) + innerbox.Add( middlecontrol, 0, wxEXPAND ) + middlecontrol = FileBrowseButtonWithHistory( + panel, + labelText = "History callback", + initialValue = "d:\\temp", + history = self.historyCallBack, + changeCallback= SimpleCallback( "History callback" ), + ) + innerbox.Add( middlecontrol, 0, wxEXPAND ) + self.bottomcontrol = control = FileBrowseButton( + panel, + labelText = "With Callback", + style = wxSUNKEN_BORDER|wxCLIP_CHILDREN , + changeCallback= SimpleCallback( "With Callback" ), + ) + innerbox.Add( control, 0, wxEXPAND) + self.bottommostcontrol = control = DirBrowseButton( + panel, + labelText = "Simple dir browse button", + style = wxSUNKEN_BORDER|wxCLIP_CHILDREN) + innerbox.Add( control, 0, wxEXPAND) + ID = wxNewId() + innerbox.Add( wxButton( panel, ID,"Change Label", ), 1, wxEXPAND) + EVT_BUTTON( self, ID, self.OnChangeLabel ) + ID = wxNewId() + innerbox.Add( wxButton( panel, ID,"Change Value", ), 1, wxEXPAND) + EVT_BUTTON( self, ID, self.OnChangeValue ) + panel.SetAutoLayout(True) + panel.SetSizer( innerbox ) + self.history={"c:\\temp":1, "c:\\tmp":1, "r:\\temp":1,"z:\\temp":1} + + def historyCallBack(self): + keys=self.history.keys() + keys.sort() + return keys + + def OnFileNameChangedHistory (self, event): + self.history[event.GetString ()]=1 + + def OnCloseMe(self, event): + self.Close(True) + def OnChangeLabel( self, event ): + self.bottomcontrol.SetLabel( "Label Updated" ) + def OnChangeValue( self, event ): + self.bottomcontrol.SetValue( "r:\\somewhere\\over\\the\\rainbow.htm" ) + + def OnCloseWindow(self, event): + self.Destroy() + + class DemoApp(wxApp): + def OnInit(self): + wxImage_AddHandler(wxJPEGHandler()) + wxImage_AddHandler(wxPNGHandler()) + wxImage_AddHandler(wxGIFHandler()) + frame = DemoFrame(NULL) + #frame = RulesPanel(NULL ) + frame.Show(True) + self.SetTopWindow(frame) + return True + + def test( ): + app = DemoApp(0) + app.MainLoop() + print 'Creating dialog' + test( ) -"""Renamer stub: provides a way to drop the wx prefix from wxPython objects.""" -__cvsid__ = "$Id$" -__revision__ = "$Revision$"[11:-2] -from wx import _rename -from wxPython.lib import filebrowsebutton -_rename(globals(), filebrowsebutton.__dict__, modulename='lib.filebrowsebutton') -del filebrowsebutton -del _rename