C++ Context Class factory
When implementing a C++ context class factory, the factory must return a context class instance for each valid resource reference number (see examples below). When using ODE, the context class factory is generated by the ClassEditor. Otherwise it has to be implemented explicitly.
One might mix C++ context classes with OSI context classes, but not with C# context classes, i.e. one has to decide whether the interface is implemented in C++/OSI or C#/OSI. One might also mix C++ and OSI context functions in one context class. In this case, the context class should be defined as C++ context class.
// Simple user-defined ContextClass factory
void *__cdecl CreateContext (int32 resid )
{
void *ctx_void = 0;
switch ( resid ) {
case 602630 : ctx_void = new cStdWizard(); break;
case 603810 : ctx_void = new cStdOutputArea(); break;
case 603811 : ctx_void = new cStdProjectTree(); break;
// ...
// more ltable entries
// ...
default :
}
}
// ContextClass factory generated by ClassEditor
void *__cdecl CreateContext (int32 resid )
{
using namespace odabagui;
typedef int32 (* context_create_pointer)(BaseContext **);
typedef std::map<int32,context_create_pointer> FunctionTable;
static FunctionTable function_table;
static bool initialized = false;
BaseContext *ctx_void = NULL;
if ( !initialized ) {
function_table.insert(FunctionTable::value_type(602630,cStdWizard::Create));
function_table.insert(FunctionTable::value_type(603810,cStdOutputArea::Create));
function_table.insert(FunctionTable::value_type(603811,cStdProjectTree::Create));
// ...
// more ltable entries
// ...
initialized = true;
}
Application::resetApplicationError();
FunctionTable::iterator it = function_table.find(resid);
if ( it != function_table.end() )
(*it->second)(&ctx_void);
Application::resetApplicationError();
return(ctx_void);
}
In order to define proper context class factories, the development database should be checked for resource references associated with a context class. This could be done writing a simple OSI function. A better way is, however, generating context classes
directly from database definitions by defining a template that collects the resource references (SDB_ResourceRef), which are associated with a context class. Since relevant information is stored in the resource reference object, the template just needs to select resource references having a context class associated, in order to create a proper CreateContext() function. This is more or less, what the ClassEditor is doing just using another template and a bit more sophisticated class selection in order to support several context classes in different projects.
$template CreateCCFactory()$
void *__cdecl CreateContext (int32 resid )
{
void *ctx_void = 0;
switch ( resid ) {
$SDB_ResourceRef()->CreateCCLine()$
default : ;
}
}
$end$
$template SDB_ResourceRef::CreateCCLine()$
$while next$\
$if context_class.count > 0$\
case $__AUTOIDENT$ : ctx_void = new $context_class.get(0).sys_ident$(); break;
$end$\
$end$\
$end$