]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/lib/filebrowsebutton.py
newevent module now returns a PyEventBinder instead of a function
[wxWidgets.git] / wxPython / wx / lib / filebrowsebutton.py
index fd03baab5296ccdb2b57cd6c2907c33e6fddf005..e9481d5daa53ffe5cc3959c22ffb2bf0b3abbb24 100644 (file)
@@ -1,8 +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."""
 
-from wx import _rename
-from wxPython.lib import filebrowsebutton
-_rename(globals(), filebrowsebutton.__dict__, modulename='lib.filebrowsebutton')
-del filebrowsebutton
-del _rename