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$