]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/module.cpp
fixing osx_cocoa
[wxWidgets.git] / src / common / module.cpp
index b18af89b14b42598130b0b76fe178dd5a3e885c9..3532ceb1497cb06e571faab4034b2e9e7080a35a 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        module.cpp
+// Name:        src/common/module.cpp
 // Purpose:     Modules initialization/destruction
 // Author:      Wolfram Gloger/adapted by Guilhem Lavaux
 // Modified by:
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "module.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #include "wx/module.h"
-#include "wx/hash.h"
 
-IMPLEMENT_CLASS(wxModule, wxObject)
+#ifndef WX_PRECOMP
+    #include "wx/hash.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+#endif
+
+#include "wx/listimpl.cpp"
 
-wxList wxModule::m_modules;
+#define TRACE_MODULE wxT("module")
+
+WX_DEFINE_LIST(wxModuleList)
+
+wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject)
+
+wxModuleList wxModule::m_modules;
 
 void wxModule::RegisterModule(wxModule* module)
 {
-  m_modules.Append(module);
+    module->m_state = State_Registered;
+    m_modules.Append(module);
+}
+
+void wxModule::UnregisterModule(wxModule* module)
+{
+    m_modules.DeleteObject(module);
+    delete module;
 }
 
 // Collect up all module-derived classes, create an instance of each,
 // and register them.
-bool wxModule::RegisterModules(void)
+void wxModule::RegisterModules()
+{
+    for (wxClassInfo::const_iterator it  = wxClassInfo::begin_classinfo(),
+                                     end = wxClassInfo::end_classinfo();
+         it != end; ++it)
+    {
+        const wxClassInfo* classInfo = *it;
+
+        if ( classInfo->IsKindOf(CLASSINFO(wxModule)) &&
+             (classInfo != (& (wxModule::ms_classInfo))) )
+        {
+            wxLogTrace(TRACE_MODULE, wxT("Registering module %s"),
+                       classInfo->GetClassName());
+            wxModule* module = (wxModule *)classInfo->CreateObject();
+            wxModule::RegisterModule(module);
+        }
+    }
+}
+
+bool wxModule::DoInitializeModule(wxModule *module,
+                                  wxModuleList &initializedModules)
 {
-    wxNode *node;
-    wxClassInfo* classInfo;
+    if ( module->m_state == State_Initializing )
+    {
+        wxLogError(_("Circular dependency involving module \"%s\" detected."),
+                   module->GetClassInfo()->GetClassName());
+        return false;
+    }
+
+    module->m_state = State_Initializing;
+
+    // translate named dependencies to the normal ones first
+    if ( !module->ResolveNamedDependencies() )
+      return false;
+
+    const wxArrayClassInfo& dependencies = module->m_dependencies;
 
-    wxClassInfo::sm_classTable->BeginFind();
-    node = wxClassInfo::sm_classTable->Next();
-    while (node)
+    // satisfy module dependencies by loading them before the current module
+    for ( unsigned int i = 0; i < dependencies.size(); ++i )
     {
-        classInfo = (wxClassInfo *)node->Data();
-        if ((classInfo != (& (wxModule::sm_classwxModule))) &&
-            classInfo->IsKindOf(CLASSINFO(wxModule)))
+        wxClassInfo * cinfo = dependencies[i];
+
+        // Check if the module is already initialized
+        wxModuleList::compatibility_iterator node;
+        for ( node = initializedModules.GetFirst(); node; node = node->GetNext() )
+        {
+            if ( node->GetData()->GetClassInfo() == cinfo )
+                break;
+        }
+
+        if ( node )
+        {
+            // this dependency is already initialized, nothing to do
+            continue;
+        }
+
+        // find the module in the registered modules list
+        for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
         {
-            wxModule* module = (wxModule*) classInfo->CreateObject();
-            RegisterModule(module);
+            wxModule *moduleDep = node->GetData();
+            if ( moduleDep->GetClassInfo() == cinfo )
+            {
+                if ( !DoInitializeModule(moduleDep, initializedModules ) )
+                {
+                    // failed to initialize a dependency, so fail this one too
+                    return false;
+                }
+
+                break;
+            }
+        }
+
+        if ( !node )
+        {
+            wxLogError(_("Dependency \"%s\" of module \"%s\" doesn't exist."),
+                       cinfo->GetClassName(),
+                       module->GetClassInfo()->GetClassName());
+            return false;
         }
-        node = wxClassInfo::sm_classTable->Next();
     }
-    return TRUE;
+
+    if ( !module->Init() )
+    {
+        wxLogError(_("Module \"%s\" initialization failed"),
+                   module->GetClassInfo()->GetClassName());
+        return false;
+    }
+
+    wxLogTrace(TRACE_MODULE, wxT("Module \"%s\" initialized"),
+               module->GetClassInfo()->GetClassName());
+
+    module->m_state = State_Initialized;
+    initializedModules.Append(module);
+
+    return true;
 }
 
-bool wxModule::InitializeModules(void)
+// Initialize user-defined modules
+bool wxModule::InitializeModules()
 {
-  // Initialize user-defined modules
-    for (wxNode *node = m_modules.First(); node; node = node->Next())
+    wxModuleList initializedModules;
+
+    for ( wxModuleList::compatibility_iterator node = m_modules.GetFirst();
+          node;
+          node = node->GetNext() )
     {
-      if (!((wxModule*)(node->Data()))->Init())
-        return FALSE;
+        wxModule *module = node->GetData();
+
+        // the module could have been already initialized as dependency of
+        // another one
+        if ( module->m_state == State_Registered )
+        {
+            if ( !DoInitializeModule( module, initializedModules ) )
+            {
+                // failed to initialize all modules, so clean up the already
+                // initialized ones
+                DoCleanUpModules(initializedModules);
+
+                return false;
+            }
+        }
     }
-    return TRUE;
+
+    // remember the real initialisation order
+    m_modules = initializedModules;
+
+    return true;
 }
 
-void wxModule::CleanUpModules(void)
+// Clean up all currently initialized modules
+void wxModule::DoCleanUpModules(const wxModuleList& modules)
 {
-  // Cleanup user-defined modules
-    for(wxNode* node = m_modules.Last(); node; node = node->Previous())
+    // cleanup user-defined modules in the reverse order compared to their
+    // initialization -- this ensures that dependencies are respected
+    for ( wxModuleList::compatibility_iterator node = modules.GetLast();
+          node;
+          node = node->GetPrevious() )
     {
-      ((wxModule*)(node->Data()))->Exit();
-      delete (wxModule*)(node->Data());
+        wxLogTrace(TRACE_MODULE, wxT("Cleanup module %s"),
+                   node->GetData()->GetClassInfo()->GetClassName());
+
+        wxModule * module = node->GetData();
+
+        wxASSERT_MSG( module->m_state == State_Initialized,
+                        wxT("not initialized module being cleaned up") );
+
+        module->Exit();
+        module->m_state = State_Registered;
     }
-    m_modules.Clear();
+
+    // clear all modules, even the non-initialized ones
+    WX_CLEAR_LIST(wxModuleList, m_modules);
 }
 
+bool wxModule::ResolveNamedDependencies()
+{
+    // first resolve required dependencies
+    for ( size_t i = 0; i < m_namedDependencies.size(); ++i )
+    {
+        wxClassInfo *info = wxClassInfo::FindClass(m_namedDependencies[i]);
+
+        if ( !info )
+        {
+            // required dependency not found
+            return false;
+        }
+
+        // add it even if it is not derived from wxModule because
+        // DoInitializeModule() will make sure a module with the same class
+        // info exists and fail if it doesn't
+        m_dependencies.Add(info);
+    }
+
+    return true;
+}