]> git.saurik.com Git - wxWidgets.git/commitdiff
allow customizing wxStandardPaths logic for the program directory determination
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 11 Jun 2009 16:46:19 +0000 (16:46 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 11 Jun 2009 16:46:19 +0000 (16:46 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61003 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/msw/stdpaths.h
interface/wx/stdpaths.h
src/msw/stdpaths.cpp

index 5cbf0265b12858a882607ebe357e05c67ddca0eb..305e4254adac1b2d09cc66c7d9921a82364b66cd 100644 (file)
@@ -356,6 +356,7 @@ MSW:
 - Update CRT environment block in wxSetEnv() too.
 - Fix wxMDIChildFrame::SetSize() (Lars Rosenboom).
 - Fix wxTreeCtrl::UnselectItem() in single selection controls.
+- Allow customizing wxStandardPaths logic for program directory determination.
 
 i18n:
 
index cb141af92c7572f270f66a726eb949c63439ca90..e6668daa147958d93acccd117f1fd162c9828603 100644 (file)
 class WXDLLIMPEXP_BASE wxStandardPaths : public wxStandardPathsBase
 {
 public:
-    wxStandardPaths()
-    {
-        UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
-    }
-
-    ~wxStandardPaths() { }
+    // ctor calls IgnoreAppBuildSubDirs() and also sets up the object to use
+    // both vendor and application name by default
+    wxStandardPaths();
 
     // implement base class pure virtuals
     virtual wxString GetExecutablePath() const;
@@ -36,12 +33,44 @@ public:
     virtual wxString GetPluginsDir() const;
     virtual wxString GetDocumentsDir() const;
 
+
+    // MSW-specific methods
+
+    // This class supposes that data, plugins &c files are located under the
+    // program directory which is the directory containing the application
+    // binary itself. But sometimes this binary may be in a subdirectory of the
+    // main program directory, e.g. this happens in at least the following
+    // common cases:
+    //  1. The program is in "bin" subdirectory of the installation directory.
+    //  2. The program is in "debug" subdirectory of the directory containing
+    //     sources and data files during development
+    //
+    // By calling this function you instruct the class to remove the last
+    // component of the path if it matches its argument. Notice that it may be
+    // called more than once, e.g. you can call both IgnoreAppSubDir("bin") and
+    // IgnoreAppSubDir("debug") to take care of both production and development
+    // cases above but that each call will only remove the last path component.
+    // Finally note that the argument can contain wild cards so you can also
+    // call IgnoreAppSubDir("vc*msw*") to ignore all build directories at once
+    // when using wxWidgets-inspired output directories names.
+    void IgnoreAppSubDir(const wxString& subdirPattern);
+
+    // This function is used to ignore all common build directories and is
+    // called from the ctor -- use DontIgnoreAppSubDir() to undo this.
+    void IgnoreAppBuildSubDirs();
+
+    // Undo the effects of all preceding IgnoreAppSubDir() calls.
+    void DontIgnoreAppSubDir();
+
 protected:
     // get the path corresponding to the given standard CSIDL_XXX constant
     static wxString DoGetDirectory(int csidl);
 
     // return the directory of the application itself
-    static wxString GetAppDir();
+    wxString GetAppDir() const;
+
+    // directory returned by GetAppDir()
+    mutable wxString m_appDir;
 };
 
 // ----------------------------------------------------------------------------
index d082af4b97976c92eb2366a851f4ec95df2c91bb..fa4d965c4f4ba463c0c6dc6bfa44fcae4b5ea955 100644 (file)
 class wxStandardPaths
 {
 public:
+    /**
+        MSW-specific function undoing the effect of IgnoreAppSubDir() calls.
+
+        After a call to this function the program directory will be exactly the
+        directory containing the main application binary, i.e. it undoes the
+        effect of any previous IgnoreAppSubDir() calls including the ones done
+        indirectly by IgnoreAppBuildSubDirs() called from the class
+        constructor.
+
+        @since 2.9.1
+     */
+    void DontIgnoreAppSubDir();
+
     /**
         Returns reference to the unique global standard paths object.
     */
@@ -215,6 +228,53 @@ public:
     */
     virtual wxString GetUserLocalDataDir() const;
 
+    /**
+        MSW-specific function to customize application directory detection.
+
+        This class supposes that data, plugins &c files are located under the
+        program directory which is the directory containing the application
+        binary itself. But sometimes this binary may be in a subdirectory of
+        the main program directory, e.g. this happens in at least the following
+        common cases:
+         - The program is in "bin" subdirectory of the installation directory.
+         - The program is in "debug" subdirectory of the directory containing
+           sources and data files during development
+
+        By calling this function you instruct the class to remove the last
+        component of the path if it matches its argument. Notice that it may be
+        called more than once, e.g. you can call both IgnoreAppSubDir("bin") and
+        IgnoreAppSubDir("debug") to take care of both production and development
+        cases above but that each call will only remove the last path component.
+        Finally note that the argument can contain wild cards so you can also
+        call IgnoreAppSubDir("vc*msw*") to ignore all build directories at once
+        when using wxWidgets-inspired output directories names.
+
+        @since 2.9.1
+
+        @see IgnoreAppBuildSubDirs()
+
+        @param subdirPattern
+            The subdirectory containing the application binary which should be
+            ignored when determining the top application directory. The pattern
+            is case-insensitive and may contain wild card characters @c '?' and
+            @c '*'.
+     */
+    void IgnoreAppSubDir(const wxString& subdirPattern);
+
+    /**
+        MSW-specific function to ignore all common build directories.
+
+        This function calls IgnoreAppSubDir() with all common values for build
+        directory, e.g. @c "debug" and @c "release".
+
+        It is called by the class constructor and so the build directories are
+        always ignored by default. You may use DontIgnoreAppSubDir() to avoid
+        ignoring them if this is inappropriate for your application.
+
+        @since 2.9.1
+     */
+    void IgnoreAppBuildSubDirs();
+
     /**
         Lets wxStandardPaths know about the real program installation prefix on a Unix
         system. By default, the value returned by GetInstallPrefix() is used.
index e8340f1a26a99de771d53ff906bf25f479a8129e..4f2cfd65c531a9d2961f75a2ee056faaf2954e96 100644 (file)
@@ -79,10 +79,14 @@ typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
 #ifndef SHGFP_TYPE_DEFAULT
     #define SHGFP_TYPE_DEFAULT 1
 #endif
+
 // ----------------------------------------------------------------------------
 // module globals
 // ----------------------------------------------------------------------------
 
+namespace
+{
+
 struct ShellFunctions
 {
     ShellFunctions()
@@ -101,13 +105,13 @@ struct ShellFunctions
 // in spite of using a static variable, this is MT-safe as in the worst case it
 // results in initializing the function pointer several times -- but this is
 // harmless
-static ShellFunctions gs_shellFuncs;
+ShellFunctions gs_shellFuncs;
 
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------
 
-static void ResolveShellFunctions()
+void ResolveShellFunctions()
 {
 #if wxUSE_DYNLIB_CLASS
 
@@ -161,6 +165,8 @@ static void ResolveShellFunctions()
 #endif
 }
 
+} // anonymous namespace
+
 // ============================================================================
 // wxStandardPaths implementation
 // ============================================================================
@@ -245,24 +251,14 @@ wxString wxStandardPaths::DoGetDirectory(int csidl)
     return dir;
 }
 
-/* static */
-wxString wxStandardPaths::GetAppDir()
+wxString wxStandardPaths::GetAppDir() const
 {
-    wxFileName fn(wxGetFullModuleName());
-
-    // allow running the apps directly from build directory in MSVC debug builds
-#ifdef _DEBUG
-    wxString lastdir;
-    if ( fn.GetDirCount() )
+    if ( m_appDir.empty() )
     {
-        lastdir = fn.GetDirs().Last();
-        lastdir.MakeLower();
-        if ( lastdir.Matches(_T("debug*")) || lastdir.Matches(_T("vc*msw*")) )
-            fn.RemoveLastDir();
+        m_appDir = wxFileName(wxGetFullModuleName()).GetPath();
     }
-#endif // _DEBUG
 
-    return fn.GetPath();
+    return m_appDir;
 }
 
 wxString wxStandardPaths::GetDocumentsDir() const
@@ -270,10 +266,74 @@ wxString wxStandardPaths::GetDocumentsDir() const
     return DoGetDirectory(CSIDL_PERSONAL);
 }
 
+// ----------------------------------------------------------------------------
+// MSW-specific functions
+// ----------------------------------------------------------------------------
+
+void wxStandardPaths::IgnoreAppSubDir(const wxString& subdirPattern)
+{
+    wxFileName fn = wxFileName::DirName(GetAppDir());
+
+    if ( !fn.GetDirCount() )
+    {
+        // no last directory to ignore anyhow
+        return;
+    }
+
+    const wxString lastdir = fn.GetDirs().Last().Lower();
+    if ( lastdir.Matches(subdirPattern.Lower()) )
+    {
+        fn.RemoveLastDir();
+
+        // store the cached value so that subsequent calls to GetAppDir() will
+        // reuse it instead of using just the program binary directory
+        m_appDir = fn.GetPath();
+    }
+}
+
+void wxStandardPaths::IgnoreAppBuildSubDirs()
+{
+    IgnoreAppSubDir("debug");
+    IgnoreAppSubDir("release");
+
+    wxString compilerPrefix;
+#ifdef __VISUALC__
+    compilerPrefix = "vc";
+#elif defined(__GNUG__)
+    compilerPrefix = "gcc";
+#elif defined(__BORLANDC__)
+    compilerPrefix = "bcc";
+#elif defined(__DIGITALMARS__)
+    compilerPrefix = "dmc";
+#elif defined(__WATCOMC__)
+    compilerPrefix = "wat";
+#else
+    return;
+#endif
+
+    IgnoreAppSubDir(compilerPrefix + "_msw*");
+}
+
+void wxStandardPaths::DontIgnoreAppSubDir()
+{
+    // this will force the next call to GetAppDir() to use the program binary
+    // path as the application directory
+    m_appDir.clear();
+}
+
 // ----------------------------------------------------------------------------
 // public functions
 // ----------------------------------------------------------------------------
 
+wxStandardPaths::wxStandardPaths()
+{
+    // under MSW it's common to use both the applicatio nand vendor
+    UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
+
+    // make it possible to run uninstalled application from the build directory
+    IgnoreAppBuildSubDirs();
+}
+
 wxString wxStandardPaths::GetExecutablePath() const
 {
     return wxGetFullModuleName();