Commit fe818bf8 authored by Dimitri van Heesch's avatar Dimitri van Heesch

Added graphical hierarchy support to template engine

parent 3ebc4315
...@@ -666,6 +666,18 @@ class TranslateContext::Private : public PropertyMapper ...@@ -666,6 +666,18 @@ class TranslateContext::Private : public PropertyMapper
static bool extractAll = Config_getBool("EXTRACT_ALL"); static bool extractAll = Config_getBool("EXTRACT_ALL");
return theTranslator->trNamespaceMemberDescription(extractAll); return theTranslator->trNamespaceMemberDescription(extractAll);
} }
TemplateVariant classHierarchyDescription() const
{
return theTranslator->trClassHierarchyDescription();
}
TemplateVariant gotoGraphicalHierarchy() const
{
return theTranslator->trGotoGraphicalHierarchy();
}
TemplateVariant gotoTextualHierarchy() const
{
return theTranslator->trGotoTextualHierarchy();
}
TemplateVariant classMembersDescription() const TemplateVariant classMembersDescription() const
{ {
static bool extractAll = Config_getBool("EXTRACT_ALL"); static bool extractAll = Config_getBool("EXTRACT_ALL");
...@@ -1012,6 +1024,12 @@ class TranslateContext::Private : public PropertyMapper ...@@ -1012,6 +1024,12 @@ class TranslateContext::Private : public PropertyMapper
addProperty("macros", this,&Private::macros); addProperty("macros", this,&Private::macros);
//%% string namespaceMembersDescription //%% string namespaceMembersDescription
addProperty("namespaceMembersDescription",this,&Private::namespaceMembersDescription); addProperty("namespaceMembersDescription",this,&Private::namespaceMembersDescription);
//%% string classHierarchyDescription
addProperty("classHierarchyDescription",this,&Private::classHierarchyDescription);
//%% string gotoGraphicalHierarchy
addProperty("gotoGraphicalHierarchy",this,&Private::gotoGraphicalHierarchy);
//%% string gotoTextualHierarchy
addProperty("gotoTextualHierarchy",this,&Private::gotoTextualHierarchy);
m_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); m_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
...@@ -4822,194 +4840,74 @@ TemplateVariant ClassIndexContext::get(const char *n) const ...@@ -4822,194 +4840,74 @@ TemplateVariant ClassIndexContext::get(const char *n) const
//------------------------------------------------------------------------ //------------------------------------------------------------------------
//%% struct ClassInheritanceNode: node in inheritance tree static int computeMaxDepth(const TemplateListIntf *list)
//%% {
class ClassInheritanceNodeContext::Private : public PropertyMapper
{ {
public: int maxDepth=0;
Private(ClassDef *cd) : m_classDef(cd) if (list)
{
TemplateListIntf::ConstIterator *it = list->createIterator();
TemplateVariant v;
for (it->toFirst();it->current(v);it->toNext())
{ {
//%% bool is_leaf_node: true if this node does not have any children const TemplateStructIntf *s = v.toStruct();
addProperty("is_leaf_node",this,&Private::isLeafNode); TemplateVariant child = s->get("children");
//%% ClassInheritance children: list of nested classes/namespaces int d = computeMaxDepth(child.toList())+1;
addProperty("children",this,&Private::children); if (d>maxDepth) maxDepth=d;
//%% Class class: class info
addProperty("class",this,&Private::getClass);
} }
void addChildren(const BaseClassList *bcl,bool hideSuper) delete it;
{ }
if (bcl==0) return; return maxDepth;
BaseClassListIterator bcli(*bcl); }
BaseClassDef *bcd;
for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli)
{
ClassDef *cd=bcd->classDef;
if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
{
continue;
}
bool b;
if (cd->getLanguage()==SrcLangExt_VHDL)
{
b=hasVisibleRoot(cd->subClasses());
}
else
{
b=hasVisibleRoot(cd->baseClasses());
}
if (cd->isVisibleInHierarchy() && b) // hasVisibleRoot(cd->baseClasses())) static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxLevel)
{ {
bool hasChildren = !cd->visited && !hideSuper && classHasVisibleChildren(cd); int num=0;
ClassInheritanceNodeContext *tnc = new ClassInheritanceNodeContext(cd); if (level<maxLevel)
m_children.append(tnc); {
if (hasChildren) num++;
{ TemplateVariant child = s->get("children");
//printf("Class %s at %p visited=%d\n",cd->name().data(),cd,cd->visited); if (child.toList())
bool wasVisited=cd->visited;
cd->visited=TRUE;
if (cd->getLanguage()==SrcLangExt_VHDL)
{
tnc->addChildren(cd->baseClasses(),wasVisited);
}
else
{
tnc->addChildren(cd->subClasses(),wasVisited);
}
}
}
}
}
TemplateVariant isLeafNode() const
{
return m_children.isEmpty();
}
TemplateVariant children() const
{
return TemplateVariant(&m_children);
}
TemplateVariant getClass() const
{ {
if (!m_cache.classContext) TemplateListIntf::ConstIterator *it = child.toList()->createIterator();
TemplateVariant v;
for (it->toFirst();it->current(v);it->toNext())
{ {
m_cache.classContext.reset(ClassContext::alloc(m_classDef)); num+=computeNumNodesAtLevel(v.toStruct(),level+1,maxLevel);
} }
return m_cache.classContext.get(); delete it;
} }
private: }
ClassDef *m_classDef; return num;
GenericNodeListContext m_children;
struct Cachable
{
SharedPtr<ClassContext> classContext;
};
mutable Cachable m_cache;
};
//%% }
ClassInheritanceNodeContext::ClassInheritanceNodeContext(ClassDef *cd) : RefCountedContext("ClassInheritanceNodeContext")
{
p = new Private(cd);
}
ClassInheritanceNodeContext::~ClassInheritanceNodeContext()
{
delete p;
}
TemplateVariant ClassInheritanceNodeContext::get(const char *n) const
{
return p->get(n);
}
void ClassInheritanceNodeContext::addChildren(const BaseClassList *bcl,bool hideSuper)
{
p->addChildren(bcl,hideSuper);
} }
//------------------------------------------------------------------------ static int computePreferredDepth(const TemplateListIntf *list,int maxDepth)
//%% list ClassInheritance[ClassInheritanceNode]: list of classes
class ClassInheritanceContext::Private : public GenericNodeListContext
{ {
public: int preferredNumEntries = Config_getInt("HTML_INDEX_NUM_ENTRIES");
void addClasses(const ClassSDict &classSDict) int preferredDepth=1;
if (preferredNumEntries>0)
{
int depth = maxDepth;
for (int i=1;i<=depth;i++)
{ {
ClassSDict::Iterator cli(classSDict); int num=0;
ClassDef *cd; TemplateListIntf::ConstIterator *it = list->createIterator();
for (cli.toFirst();(cd=cli.current());++cli) TemplateVariant v;
for (it->toFirst();it->current(v);it->toNext())
{ {
bool b; num+=computeNumNodesAtLevel(v.toStruct(),0,i);
if (cd->getLanguage()==SrcLangExt_VHDL) }
{ delete it;
if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) if (num<=preferredNumEntries)
{ {
continue; preferredDepth=i;
} }
b=!hasVisibleRoot(cd->subClasses()); else
} {
else break;
{
b=!hasVisibleRoot(cd->baseClasses());
}
if (b)
{
if (cd->isVisibleInHierarchy()) // should it be visible
{
// new root level class
ClassInheritanceNodeContext *tnc = ClassInheritanceNodeContext::alloc(cd);
append(tnc);
bool hasChildren = !cd->visited && classHasVisibleChildren(cd);
if (cd->getLanguage()==SrcLangExt_VHDL && hasChildren)
{
tnc->addChildren(cd->baseClasses(),cd->visited);
cd->visited=TRUE;
}
else if (hasChildren)
{
tnc->addChildren(cd->subClasses(),cd->visited);
cd->visited=TRUE;
}
}
}
} }
} }
};
ClassInheritanceContext::ClassInheritanceContext() : RefCountedContext("ClassInheritanceContext")
{
p = new Private;
initClassHierarchy(Doxygen::classSDict);
initClassHierarchy(Doxygen::hiddenClasses);
p->addClasses(*Doxygen::classSDict);
p->addClasses(*Doxygen::hiddenClasses);
}
ClassInheritanceContext::~ClassInheritanceContext()
{
delete p;
}
// TemplateListIntf
int ClassInheritanceContext::count() const
{
return (int)p->count();
}
TemplateVariant ClassInheritanceContext::at(int index) const
{
TemplateVariant result;
if (index>=0 && index<count())
{
result = p->at(index);
} }
return result; return preferredDepth;
}
TemplateListIntf::ConstIterator *ClassInheritanceContext::createIterator() const
{
return p->createIterator();
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
...@@ -5019,13 +4917,27 @@ TemplateListIntf::ConstIterator *ClassInheritanceContext::createIterator() const ...@@ -5019,13 +4917,27 @@ TemplateListIntf::ConstIterator *ClassInheritanceContext::createIterator() const
class ClassHierarchyContext::Private : public PropertyMapper class ClassHierarchyContext::Private : public PropertyMapper
{ {
public: public:
Private()
{
m_classTree.reset(NestingContext::alloc(0,0));
initClassHierarchy(Doxygen::classSDict);
initClassHierarchy(Doxygen::hiddenClasses);
m_classTree->addClassHierarchy(*Doxygen::classSDict,TRUE);
m_classTree->addClassHierarchy(*Doxygen::hiddenClasses,TRUE);
//%% ClassInheritance tree
addProperty("tree", this,&Private::tree);
addProperty("fileName", this,&Private::fileName);
addProperty("relPath", this,&Private::relPath);
addProperty("highlight", this,&Private::highlight);
addProperty("subhighlight", this,&Private::subhighlight);
addProperty("title", this,&Private::title);
addProperty("preferredDepth", this,&Private::preferredDepth);
addProperty("maxDepth", this,&Private::maxDepth);
addProperty("diagrams", this,&Private::diagrams);
}
TemplateVariant tree() const TemplateVariant tree() const
{ {
if (!m_cache.classTree) return m_classTree.get();
{
m_cache.classTree.reset(ClassInheritanceContext::alloc());
}
return m_cache.classTree.get();
} }
TemplateVariant fileName() const TemplateVariant fileName() const
{ {
...@@ -5043,6 +4955,34 @@ class ClassHierarchyContext::Private : public PropertyMapper ...@@ -5043,6 +4955,34 @@ class ClassHierarchyContext::Private : public PropertyMapper
{ {
return "classhierarchy"; return "classhierarchy";
} }
DotGfxHierarchyTable *getHierarchy() const
{
if (!m_cache.hierarchy)
{
m_cache.hierarchy.reset(new DotGfxHierarchyTable());
}
return m_cache.hierarchy.get();
}
TemplateVariant diagrams() const
{
if (!m_cache.diagrams)
{
TemplateList *diagrams = TemplateList::alloc();
DotGfxHierarchyTable *hierarchy = getHierarchy();
if (hierarchy->subGraphs())
{
int id=0;
QListIterator<DotNode> li(*hierarchy->subGraphs());
DotNode *n;
for (li.toFirst();(n=li.current());++li)
{
diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++));
}
}
m_cache.diagrams.reset(diagrams);
}
return m_cache.diagrams.get();
}
TemplateVariant title() const TemplateVariant title() const
{ {
static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
...@@ -5055,20 +4995,36 @@ class ClassHierarchyContext::Private : public PropertyMapper ...@@ -5055,20 +4995,36 @@ class ClassHierarchyContext::Private : public PropertyMapper
return theTranslator->trClassHierarchy(); return theTranslator->trClassHierarchy();
} }
} }
Private() TemplateVariant maxDepth() const
{ {
//%% ClassInheritance tree if (!m_cache.maxDepthComputed)
addProperty("tree",this,&Private::tree); {
addProperty("fileName",this,&Private::fileName); m_cache.maxDepth = computeMaxDepth(m_classTree.get());
addProperty("relPath",this,&Private::relPath); m_cache.maxDepthComputed=TRUE;
addProperty("highlight",this,&Private::highlight); }
addProperty("subhighlight",this,&Private::subhighlight); return m_cache.maxDepth;
addProperty("title",this,&Private::title); }
TemplateVariant preferredDepth() const
{
if (!m_cache.preferredDepthComputed)
{
m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt());
m_cache.preferredDepthComputed=TRUE;
}
return m_cache.preferredDepth;
} }
private: private:
SharedPtr<NestingContext> m_classTree;
struct Cachable struct Cachable
{ {
SharedPtr<ClassInheritanceContext> classTree; Cachable() : maxDepth(0), maxDepthComputed(FALSE),
preferredDepth(0), preferredDepthComputed(FALSE), hierarchy(0) {}
int maxDepth;
bool maxDepthComputed;
int preferredDepth;
bool preferredDepthComputed;
SharedPtr<TemplateList> diagrams;
ScopedPtr<DotGfxHierarchyTable> hierarchy;
}; };
mutable Cachable m_cache; mutable Cachable m_cache;
}; };
...@@ -5097,7 +5053,7 @@ class NestingNodeContext::Private : public PropertyMapper ...@@ -5097,7 +5053,7 @@ class NestingNodeContext::Private : public PropertyMapper
{ {
public: public:
Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode, Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode,
Definition *d,int index,int level,bool addCls) Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper)
: m_parent(parent), m_def(d), m_level(level), m_index(index) : m_parent(parent), m_def(d), m_level(level), m_index(index)
{ {
m_children.reset(NestingContext::alloc(thisNode,level+1)); m_children.reset(NestingContext::alloc(thisNode,level+1));
...@@ -5131,7 +5087,7 @@ class NestingNodeContext::Private : public PropertyMapper ...@@ -5131,7 +5087,7 @@ class NestingNodeContext::Private : public PropertyMapper
addProperty("fileName",this,&Private::fileName); addProperty("fileName",this,&Private::fileName);
addNamespaces(addCls); addNamespaces(addCls);
addClasses(); addClasses(inherit,hideSuper);
addDirFiles(); addDirFiles();
addPages(); addPages();
addModules(); addModules();
...@@ -5283,12 +5239,34 @@ class NestingNodeContext::Private : public PropertyMapper ...@@ -5283,12 +5239,34 @@ class NestingNodeContext::Private : public PropertyMapper
return m_def->getOutputFileBase(); return m_def->getOutputFileBase();
} }
void addClasses() //------------------------------------------------------------------
void addClasses(bool inherit, bool hideSuper)
{ {
ClassDef *cd = m_def->definitionType()==Definition::TypeClass ? (ClassDef*)m_def : 0; ClassDef *cd = m_def->definitionType()==Definition::TypeClass ? (ClassDef*)m_def : 0;
if (cd && cd->getClassSDict()) if (inherit)
{ {
m_children->addClasses(*cd->getClassSDict(),FALSE); bool hasChildren = !cd->visited && !hideSuper && classHasVisibleChildren(cd);
if (hasChildren)
{
bool wasVisited=cd->visited;
cd->visited=TRUE;
if (cd->getLanguage()==SrcLangExt_VHDL)
{
m_children->addDerivedClasses(cd->baseClasses(),wasVisited);
}
else
{
m_children->addDerivedClasses(cd->subClasses(),wasVisited);
}
}
}
else
{
if (cd && cd->getClassSDict())
{
m_children->addClasses(*cd->getClassSDict(),FALSE);
}
} }
} }
void addNamespaces(bool addClasses) void addNamespaces(bool addClasses)
...@@ -5352,9 +5330,10 @@ class NestingNodeContext::Private : public PropertyMapper ...@@ -5352,9 +5330,10 @@ class NestingNodeContext::Private : public PropertyMapper
//%% } //%% }
NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent, NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent,
Definition *d,int index,int level,bool addClass) : RefCountedContext("NestingNodeContext") Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper)
: RefCountedContext("NestingNodeContext")
{ {
p = new Private(parent,this,d,index,level,addClass); p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper);
} }
NestingNodeContext::~NestingNodeContext() NestingNodeContext::~NestingNodeContext()
...@@ -5394,7 +5373,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5394,7 +5373,7 @@ class NestingContext::Private : public GenericNodeListContext
bool isLinkable = nd->isLinkableInProject(); bool isLinkable = nd->isLinkableInProject();
if (isLinkable || hasChildren) if (isLinkable || hasChildren)
{ {
NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses); NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses,FALSE,FALSE);
append(nnc); append(nnc);
m_index++; m_index++;
} }
...@@ -5423,7 +5402,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5423,7 +5402,7 @@ class NestingContext::Private : public GenericNodeListContext
{ {
if (classVisibleInIndex(cd) && cd->templateMaster()==0) if (classVisibleInIndex(cd) && cd->templateMaster()==0)
{ {
NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE); NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,FALSE,FALSE);
append(nnc); append(nnc);
m_index++; m_index++;
} }
...@@ -5438,7 +5417,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5438,7 +5417,7 @@ class NestingContext::Private : public GenericNodeListContext
{ {
if (dd->getOuterScope()==Doxygen::globalScope) if (dd->getOuterScope()==Doxygen::globalScope)
{ {
append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
...@@ -5449,7 +5428,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5449,7 +5428,7 @@ class NestingContext::Private : public GenericNodeListContext
DirDef *dd; DirDef *dd;
for (li.toFirst();(dd=li.current());++li) for (li.toFirst();(dd=li.current());++li)
{ {
append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
...@@ -5465,7 +5444,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5465,7 +5444,7 @@ class NestingContext::Private : public GenericNodeListContext
{ {
if (fd->getDirDef()==0) // top level file if (fd->getDirDef()==0) // top level file
{ {
append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
...@@ -5477,7 +5456,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5477,7 +5456,7 @@ class NestingContext::Private : public GenericNodeListContext
FileDef *fd; FileDef *fd;
for (li.toFirst();(fd=li.current());++li) for (li.toFirst();(fd=li.current());++li)
{ {
append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
...@@ -5491,7 +5470,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5491,7 +5470,7 @@ class NestingContext::Private : public GenericNodeListContext
pd->getOuterScope()==0 || pd->getOuterScope()==0 ||
pd->getOuterScope()->definitionType()!=Definition::TypePage) pd->getOuterScope()->definitionType()!=Definition::TypePage)
{ {
append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
...@@ -5507,7 +5486,7 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5507,7 +5486,7 @@ class NestingContext::Private : public GenericNodeListContext
(!gd->isReference() || externalGroups) (!gd->isReference() || externalGroups)
) )
{ {
append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
...@@ -5520,11 +5499,74 @@ class NestingContext::Private : public GenericNodeListContext ...@@ -5520,11 +5499,74 @@ class NestingContext::Private : public GenericNodeListContext
{ {
if (gd->isVisible()) if (gd->isVisible())
{ {
append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE)); append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE));
m_index++; m_index++;
} }
} }
} }
void addDerivedClasses(const BaseClassList *bcl,bool hideSuper)
{
if (bcl==0) return;
BaseClassListIterator bcli(*bcl);
BaseClassDef *bcd;
for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli)
{
ClassDef *cd=bcd->classDef;
if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
{
continue;
}
bool b;
if (cd->getLanguage()==SrcLangExt_VHDL)
{
b=hasVisibleRoot(cd->subClasses());
}
else
{
b=hasVisibleRoot(cd->baseClasses());
}
if (cd->isVisibleInHierarchy() && b)
{
NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,hideSuper);
append(tnc);
m_index++;
}
}
}
void addClassHierarchy(const ClassSDict &classSDict,bool)
{
ClassSDict::Iterator cli(classSDict);
ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
bool b;
if (cd->getLanguage()==SrcLangExt_VHDL)
{
if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
{
continue;
}
b=!hasVisibleRoot(cd->subClasses());
}
else
{
b=!hasVisibleRoot(cd->baseClasses());
}
if (b)
{
if (cd->isVisibleInHierarchy()) // should it be visible
{
// new root level class
NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,cd->visited);
append(nnc);
m_index++;
}
}
}
}
private: private:
const NestingNodeContext *m_parent; const NestingNodeContext *m_parent;
int m_level; int m_level;
...@@ -5602,78 +5644,17 @@ void NestingContext::addModules(const GroupList &modules) ...@@ -5602,78 +5644,17 @@ void NestingContext::addModules(const GroupList &modules)
p->addModules(modules); p->addModules(modules);
} }
//------------------------------------------------------------------------ void NestingContext::addClassHierarchy(const ClassSDict &classSDict,bool rootOnly)
static int computeMaxDepth(const TemplateListIntf *list)
{ {
int maxDepth=0; p->addClassHierarchy(classSDict,rootOnly);
if (list)
{
TemplateListIntf::ConstIterator *it = list->createIterator();
TemplateVariant v;
for (it->toFirst();it->current(v);it->toNext())
{
const TemplateStructIntf *s = v.toStruct();
TemplateVariant child = s->get("children");
int d = computeMaxDepth(child.toList())+1;
if (d>maxDepth) maxDepth=d;
}
delete it;
}
return maxDepth;
} }
static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxLevel) void NestingContext::addDerivedClasses(const BaseClassList *bcl,bool hideSuper)
{ {
int num=0; p->addDerivedClasses(bcl,hideSuper);
if (level<maxLevel)
{
num++;
TemplateVariant child = s->get("children");
if (child.toList())
{
TemplateListIntf::ConstIterator *it = child.toList()->createIterator();
TemplateVariant v;
for (it->toFirst();it->current(v);it->toNext())
{
num+=computeNumNodesAtLevel(v.toStruct(),level+1,maxLevel);
}
delete it;
}
}
return num;
}
static int computePreferredDepth(const TemplateListIntf *list,int maxDepth)
{
int preferredNumEntries = Config_getInt("HTML_INDEX_NUM_ENTRIES");
int preferredDepth=1;
if (preferredNumEntries>0)
{
int depth = maxDepth;
for (int i=1;i<=depth;i++)
{
int num=0;
TemplateListIntf::ConstIterator *it = list->createIterator();
TemplateVariant v;
for (it->toFirst();it->current(v);it->toNext())
{
num+=computeNumNodesAtLevel(v.toStruct(),0,i);
}
delete it;
if (num<=preferredNumEntries)
{
preferredDepth=i;
}
else
{
break;
}
}
}
return preferredDepth;
} }
//------------------------------------------------------------------------
//%% struct ClassTree: Class nesting relations //%% struct ClassTree: Class nesting relations
//%% { //%% {
...@@ -7049,6 +7030,56 @@ TemplateVariant NamespaceMembersIndexContext::get(const char *name) const ...@@ -7049,6 +7030,56 @@ TemplateVariant NamespaceMembersIndexContext::get(const char *name) const
return p->get(name); return p->get(name);
} }
//------------------------------------------------------------------------
//%% struct InheritanceGraph: a connected graph reprenting part of the overall interitance tree
//%% {
class InheritanceGraphContext::Private : public PropertyMapper
{
public:
Private(DotGfxHierarchyTable *hierarchy,DotNode *n,int id) : m_hierarchy(hierarchy), m_node(n), m_id(id)
{
addProperty("graph",this,&Private::graph);
}
TemplateVariant graph() const
{
QGString result;
static bool haveDot = Config_getBool("HAVE_DOT");
static bool graphicalHierarchy = Config_getBool("GRAPHICAL_HIERARCHY");
if (haveDot && graphicalHierarchy)
{
FTextStream t(&result);
m_hierarchy->createGraph(m_node,t,
/*GOF_BITMAP,
EOF_Html,*/
g_globals.outputDir,
g_globals.outputDir+portable_pathSeparator()+"inherits"+Doxygen::htmlFileExtension,
m_id);
}
return TemplateVariant(result.data(),TRUE);
}
private:
DotGfxHierarchyTable *m_hierarchy;
DotNode *m_node;
int m_id;
};
InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id)
: RefCountedContext("InheritanceGraphContext")
{
p = new Private(hierarchy,n,id);
}
InheritanceGraphContext::~InheritanceGraphContext()
{
delete p;
}
TemplateVariant InheritanceGraphContext::get(const char *name) const
{
return p->get(name);
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
...@@ -8086,7 +8117,7 @@ class HtmlSpaceless : public TemplateSpacelessIntf ...@@ -8086,7 +8117,7 @@ class HtmlSpaceless : public TemplateSpacelessIntf
{ {
m_insideString='\0'; m_insideString='\0';
} }
else // start of string else if (m_insideString=='\0') // start of string
{ {
m_insideString=c; m_insideString=c;
} }
...@@ -8111,8 +8142,8 @@ class HtmlSpaceless : public TemplateSpacelessIntf ...@@ -8111,8 +8142,8 @@ class HtmlSpaceless : public TemplateSpacelessIntf
} }
} }
result+='\0'; result+='\0';
//printf("HtmlSpaceless::remove({%s})={%s} m_insideTag=%d m_insideString=%d removeSpaces=%d\n",s.data(),result.data(), //printf("HtmlSpaceless::remove({%s})={%s} m_insideTag=%d m_insideString=%c (%d) removeSpaces=%d\n",s.data(),result.data(),
// m_insideTag,m_insideString,m_removeSpaces); // m_insideTag,m_insideString,m_insideString,m_removeSpaces);
return result.data(); return result.data();
} }
private: private:
......
...@@ -51,6 +51,8 @@ struct MemberInfo; ...@@ -51,6 +51,8 @@ struct MemberInfo;
class MemberGroup; class MemberGroup;
class MemberGroupSDict; class MemberGroupSDict;
class MemberGroupList; class MemberGroupList;
class DotNode;
class DotGfxHierarchyTable;
//---------------------------------------------------- //----------------------------------------------------
...@@ -419,6 +421,26 @@ class ClassIndexContext : public RefCountedContext, public TemplateStructIntf ...@@ -419,6 +421,26 @@ class ClassIndexContext : public RefCountedContext, public TemplateStructIntf
//---------------------------------------------------- //----------------------------------------------------
class InheritanceGraphContext : public RefCountedContext, public TemplateStructIntf
{
public:
static InheritanceGraphContext *alloc(DotGfxHierarchyTable *hierarchy,DotNode *n,int id)
{ return new InheritanceGraphContext(hierarchy,n,id); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
virtual int addRef() { return RefCountedContext::addRef(); }
virtual int release() { return RefCountedContext::release(); }
private:
InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id);
~InheritanceGraphContext();
class Private;
Private *p;
};
//----------------------------------------------------
class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf
{ {
public: public:
...@@ -485,8 +507,8 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf ...@@ -485,8 +507,8 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
{ {
public: public:
static NestingNodeContext *alloc(const NestingNodeContext *parent,Definition *def, static NestingNodeContext *alloc(const NestingNodeContext *parent,Definition *def,
int index,int level,bool addClasses) int index,int level,bool addClasses,bool inherit,bool hideSuper)
{ return new NestingNodeContext(parent,def,index,level,addClasses); } { return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper); }
QCString id() const; QCString id() const;
...@@ -497,7 +519,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf ...@@ -497,7 +519,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
private: private:
NestingNodeContext(const NestingNodeContext *parent, NestingNodeContext(const NestingNodeContext *parent,
Definition *,int index,int level,bool addClasses); Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper);
~NestingNodeContext(); ~NestingNodeContext();
class Private; class Private;
Private *p; Private *p;
...@@ -527,6 +549,8 @@ class NestingContext : public RefCountedContext, public TemplateListIntf ...@@ -527,6 +549,8 @@ class NestingContext : public RefCountedContext, public TemplateListIntf
void addPages(const PageSDict &pages,bool rootOnly); void addPages(const PageSDict &pages,bool rootOnly);
void addModules(const GroupSDict &modules); void addModules(const GroupSDict &modules);
void addModules(const GroupList &modules); void addModules(const GroupList &modules);
void addClassHierarchy(const ClassSDict &clDict,bool rootOnly);
void addDerivedClasses(const BaseClassList *bcl,bool hideSuper);
private: private:
NestingContext(const NestingNodeContext *parent,int level); NestingContext(const NestingNodeContext *parent,int level);
......
...@@ -772,18 +772,18 @@ static bool checkDeliverables(const QCString &file1, ...@@ -772,18 +772,18 @@ static bool checkDeliverables(const QCString &file1,
//-------------------------------------------------------------------- //--------------------------------------------------------------------
/** Class representing a list of DotNode objects. */ inline int DotNode::findParent( DotNode *n )
class DotNodeList : public QList<DotNode>
{ {
public: if ( !m_parents ) return -1;
DotNodeList() : QList<DotNode>() {} return m_parents->find(n);
~DotNodeList() {} }
private:
int compareValues(const DotNode *n1,const DotNode *n2) const //--------------------------------------------------------------------
{
return qstricmp(n1->m_label,n2->m_label); int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const
} {
}; return qstricmp(n1->m_label,n2->m_label);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -1908,7 +1908,7 @@ void DotNode::write(FTextStream &t, ...@@ -1908,7 +1908,7 @@ void DotNode::write(FTextStream &t,
bool reNumber bool reNumber
) )
{ {
//printf("DotNode::write(%d) name=%s this=%p written=%d\n",distance,m_label.data(),this,m_written); //printf("DotNode::write(%d) name=%s this=%p written=%d visible=%d\n",m_distance,m_label.data(),this,m_written,m_visible);
if (m_written) return; // node already written to the output if (m_written) return; // node already written to the output
if (!m_visible) return; // node is not visible if (!m_visible) return; // node is not visible
writeBox(t,gt,format,m_truncated==Truncated,reNumber); writeBox(t,gt,format,m_truncated==Truncated,reNumber);
...@@ -2261,12 +2261,106 @@ const DotNode *DotNode::findDocNode() const ...@@ -2261,12 +2261,106 @@ const DotNode *DotNode::findDocNode() const
int DotGfxHierarchyTable::m_curNodeNumber; int DotGfxHierarchyTable::m_curNodeNumber;
void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out,
const char *path,const char *fileName,int id) const
{
QDir d(path);
QCString baseName;
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
baseName.sprintf("inherit_graph_%d",id);
QCString imgName = baseName+"."+ imgExt;
QCString mapName = baseName+".map";
QCString absImgName = QCString(d.absPath().data())+"/"+imgName;
QCString absMapName = QCString(d.absPath().data())+"/"+mapName;
QCString absBaseName = QCString(d.absPath().data())+"/"+baseName;
QListIterator<DotNode> dnli2(*m_rootNodes);
DotNode *node;
// compute md5 checksum of the graph were are about to generate
QGString theGraph;
FTextStream md5stream(&theGraph);
writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy());
md5stream << " rankdir=\"LR\";" << endl;
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
{
if (node->m_subgraphId==n->m_subgraphId)
{
node->clearWriteFlag();
}
}
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
{
if (node->m_subgraphId==n->m_subgraphId)
{
node->write(md5stream,DotNode::Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE,TRUE);
}
}
writeGraphFooter(md5stream);
resetReNumbering();
uchar md5_sig[16];
QCString sigStr(33);
MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
MD5SigToString(md5_sig,sigStr.data(),33);
bool regenerate=FALSE;
if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
!checkDeliverables(absImgName,absMapName))
{
regenerate=TRUE;
// image was new or has changed
QCString dotName=absBaseName+".dot";
QFile f(dotName);
if (!f.open(IO_WriteOnly)) return;
FTextStream t(&f);
t << theGraph;
f.close();
resetReNumbering();
DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName);
dotRun->addJob(imgExt,absImgName);
dotRun->addJob(MAP_CMD,absMapName);
DotManager::instance()->addRun(dotRun);
}
else
{
removeDotGraph(absBaseName+".dot");
}
Doxygen::indexList->addImageFile(imgName);
// write image and map in a table row
QCString mapLabel = escapeCharsInString(n->m_label,FALSE);
if (imgExt=="svg") // vector graphics
{
if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName))
{
if (regenerate)
{
DotManager::instance()->addSVGConversion(absImgName,QCString(),
FALSE,QCString(),FALSE,0);
}
int mapId = DotManager::instance()->addSVGObject(fileName,baseName,
absImgName,QCString());
out << "<!-- SVG " << mapId << " -->" << endl;
}
}
else // normal bitmap
{
out << "<img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#"
<< mapLabel << "\"/>" << endl;
if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel))
{
int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(),
FALSE,QCString(),mapLabel);
out << "<!-- MAP " << mapId << " -->" << endl;
}
}
}
void DotGfxHierarchyTable::writeGraph(FTextStream &out, void DotGfxHierarchyTable::writeGraph(FTextStream &out,
const char *path,const char *fileName) const const char *path,const char *fileName) const
{ {
//printf("DotGfxHierarchyTable::writeGraph(%s)\n",name); //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name);
//printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count()); //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count());
if (m_rootSubgraphs->count()==0) return; if (m_rootSubgraphs->count()==0) return;
QDir d(path); QDir d(path);
...@@ -2284,97 +2378,8 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, ...@@ -2284,97 +2378,8 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out,
int count=0; int count=0;
for (dnli.toFirst();(n=dnli.current());++dnli) for (dnli.toFirst();(n=dnli.current());++dnli)
{ {
QCString baseName;
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
baseName.sprintf("inherit_graph_%d",count++);
//baseName = convertNameToFile(baseName);
QCString imgName = baseName+"."+ imgExt;
QCString mapName = baseName+".map";
QCString absImgName = QCString(d.absPath().data())+"/"+imgName;
QCString absMapName = QCString(d.absPath().data())+"/"+mapName;
QCString absBaseName = QCString(d.absPath().data())+"/"+baseName;
QListIterator<DotNode> dnli2(*m_rootNodes);
DotNode *node;
// compute md5 checksum of the graph were are about to generate
QGString theGraph;
FTextStream md5stream(&theGraph);
writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy());
md5stream << " rankdir=\"LR\";" << endl;
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
{
if (node->m_subgraphId==n->m_subgraphId)
{
node->clearWriteFlag();
}
}
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
{
if (node->m_subgraphId==n->m_subgraphId)
{
node->write(md5stream,DotNode::Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE,TRUE);
}
}
writeGraphFooter(md5stream);
resetReNumbering();
uchar md5_sig[16];
QCString sigStr(33);
MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
MD5SigToString(md5_sig,sigStr.data(),33);
bool regenerate=FALSE;
if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
!checkDeliverables(absImgName,absMapName))
{
regenerate=TRUE;
// image was new or has changed
QCString dotName=absBaseName+".dot";
QFile f(dotName);
if (!f.open(IO_WriteOnly)) return;
FTextStream t(&f);
t << theGraph;
f.close();
resetReNumbering();
DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName);
dotRun->addJob(imgExt,absImgName);
dotRun->addJob(MAP_CMD,absMapName);
DotManager::instance()->addRun(dotRun);
}
else
{
removeDotGraph(absBaseName+".dot");
}
Doxygen::indexList->addImageFile(imgName);
// write image and map in a table row
QCString mapLabel = escapeCharsInString(n->m_label,FALSE);
out << "<tr><td>"; out << "<tr><td>";
if (imgExt=="svg") // vector graphics createGraph(n,out,path,fileName,count++);
{
if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName))
{
if (regenerate)
{
DotManager::instance()->addSVGConversion(absImgName,QCString(),
FALSE,QCString(),FALSE,0);
}
int mapId = DotManager::instance()->addSVGObject(fileName,baseName,
absImgName,QCString());
out << "<!-- SVG " << mapId << " -->" << endl;
}
}
else // normal bitmap
{
out << "<img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#"
<< mapLabel << "\"/>" << endl;
if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel))
{
int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(),
FALSE,QCString(),mapLabel);
out << "<!-- MAP " << mapId << " -->" << endl;
}
}
out << "</td></tr>" << endl; out << "</td></tr>" << endl;
} }
out << "</table>" << endl; out << "</table>" << endl;
......
...@@ -122,6 +122,7 @@ class DotNode ...@@ -122,6 +122,7 @@ class DotNode
friend class DotNodeList; friend class DotNodeList;
friend class DotCallGraph; friend class DotCallGraph;
friend class DotGroupCollaboration; friend class DotGroupCollaboration;
friend class DotInheritanceGraph;
friend QCString computeMd5Signature( friend QCString computeMd5Signature(
DotNode *root, GraphType gt, DotNode *root, GraphType gt,
...@@ -133,12 +134,15 @@ class DotNode ...@@ -133,12 +134,15 @@ class DotNode
); );
}; };
inline int DotNode::findParent( DotNode *n ) /** Class representing a list of DotNode objects. */
class DotNodeList : public QList<DotNode>
{ {
if( !m_parents ) public:
return -1; DotNodeList() : QList<DotNode>() {}
return m_parents->find(n); ~DotNodeList() {}
} private:
int compareValues(const DotNode *n1,const DotNode *n2) const;
};
/** Represents a graphical class hierarchy */ /** Represents a graphical class hierarchy */
class DotGfxHierarchyTable class DotGfxHierarchyTable
...@@ -147,6 +151,8 @@ class DotGfxHierarchyTable ...@@ -147,6 +151,8 @@ class DotGfxHierarchyTable
DotGfxHierarchyTable(); DotGfxHierarchyTable();
~DotGfxHierarchyTable(); ~DotGfxHierarchyTable();
void writeGraph(FTextStream &t,const char *path, const char *fileName) const; void writeGraph(FTextStream &t,const char *path, const char *fileName) const;
void createGraph(DotNode *rootNode,FTextStream &t,const char *path,const char *fileName,int id) const;
const DotNodeList *subGraphs() const { return m_rootSubgraphs; }
private: private:
void addHierarchy(DotNode *n,ClassDef *cd,bool hide); void addHierarchy(DotNode *n,ClassDef *cd,bool hide);
......
...@@ -1976,10 +1976,21 @@ class ExpressionParser ...@@ -1976,10 +1976,21 @@ class ExpressionParser
ExprAst *parseLiteral() ExprAst *parseLiteral()
{ {
TRACE(("{parseLiteral(%s)\n",m_curToken.id.data())); TRACE(("{parseLiteral(%s)\n",m_curToken.id.data()));
ExprAst *lit = new ExprAstLiteral(m_curToken.id); ExprAst *expr = new ExprAstLiteral(m_curToken.id);
getNextToken(); getNextToken();
if (expr)
{
while (m_curToken.type==ExprToken::Operator &&
m_curToken.op==Operator::Filter)
{
getNextToken();
ExprAstFilter *filter = parseFilter();
if (!filter) break;
expr = new ExprAstFilterAppl(expr,filter);
}
}
TRACE(("}parseLiteral()\n")); TRACE(("}parseLiteral()\n"));
return lit; return expr;
} }
ExprAst *parseIdentifierOptionalArgs() ExprAst *parseIdentifierOptionalArgs()
...@@ -3550,6 +3561,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> ...@@ -3550,6 +3561,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
{ {
outputFile.prepend(ci->outputDirectory()+"/"); outputFile.prepend(ci->outputDirectory()+"/");
} }
//printf("NoteCreate(%s)\n",outputFile.data());
QFile f(outputFile); QFile f(outputFile);
if (f.open(IO_WriteOnly)) if (f.open(IO_WriteOnly))
{ {
...@@ -3622,9 +3634,11 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> ...@@ -3622,9 +3634,11 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
{ {
//printf("TemplateNodeTree::renderChildren(%d)\n",ctx->list->count()); //printf("TemplateNodeTree::renderChildren(%d)\n",ctx->list->count());
// render all children of node to a string and return it // render all children of node to a string and return it
TemplateContext *c = ctx->templateCtx;
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
if (ci==0) return QCString(); // should not happen
QGString result; QGString result;
FTextStream ss(&result); FTextStream ss(&result);
TemplateContext *c = ctx->templateCtx;
c->push(); c->push();
TemplateVariant node; TemplateVariant node;
TemplateListIntf::ConstIterator *it = ctx->list->createIterator(); TemplateListIntf::ConstIterator *it = ctx->list->createIterator();
...@@ -3642,14 +3656,21 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> ...@@ -3642,14 +3656,21 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
if (list && list->count()>0) // non-empty list if (list && list->count()>0) // non-empty list
{ {
TreeContext childCtx(this,list,ctx->templateCtx); TreeContext childCtx(this,list,ctx->templateCtx);
// TemplateVariant children(&childCtx,renderChildrenStub);
TemplateVariant children(TemplateVariant::Delegate::fromFunction(&childCtx,renderChildrenStub)); TemplateVariant children(TemplateVariant::Delegate::fromFunction(&childCtx,renderChildrenStub));
children.setRaw(TRUE); children.setRaw(TRUE);
c->set("children",children); c->set("children",children);
m_treeNodes.render(ss,c); m_treeNodes.render(ss,c);
hasChildren=TRUE; hasChildren=TRUE;
} }
else if (list==0)
{
ci->warn(m_templateName,m_line,"recursetree: children attribute has type '%s' instead of list\n",v.typeAsString().data());
}
} }
//else
//{
// ci->warn(m_templateName,m_line,"recursetree: children attribute is not valid");
//}
} }
if (!hasChildren) if (!hasChildren)
{ {
......
...@@ -227,7 +227,7 @@ span.lineno a:hover { ...@@ -227,7 +227,7 @@ span.lineno a:hover {
background-color: #C8C8C8; background-color: #C8C8C8;
} }
div.ah { div.ah, span.ah {
background-color: black; background-color: black;
font-weight: bold; font-weight: bold;
color: #ffffff; color: #ffffff;
...@@ -245,6 +245,15 @@ div.ah { ...@@ -245,6 +245,15 @@ div.ah {
background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
} }
div.classindex ul {
list-style: none;
padding-left: 0;
}
div.classindex span.ai {
display: inline-block;
}
div.groupHeader { div.groupHeader {
margin-left: 16px; margin-left: 16px;
margin-top: 12px; margin-top: 12px;
......
...@@ -4,18 +4,46 @@ ...@@ -4,18 +4,46 @@
<div class="textblock"> <div class="textblock">
{% indexentry nav name=tr.classIndex file=page.fileName anchor='' %} {% indexentry nav name=tr.classIndex file=page.fileName anchor='' %}
</div> </div>
<div class="classindex" style="column-count:{{ config.COLS_IN_ALPHA_INDEX }};-moz-column-count:{{ config.COLS_IN_ALPHA_INDEX }};-webkit-column-count:{{ config.COLS_IN_ALPHA_INDEX}}">
<ul>
{% with index=classIndex.list|alphaIndex:'name' %} {% with index=classIndex.list|alphaIndex:'name' %}
{# quick index at top #}
<div class="qindex">
{% for section in index %} {% for section in index %}
<div class="ah">&#160;&#160;{{ section.letter }}&#160;&#160;</div> <a class="qindex" href="#letter_{{ section.label }}">{{ section.letter }}</a>
{% if not forloop.last %}
&#160;|&#160;
{% endif %}
{% endfor %}
</div>
{# multi column index #}
<div class="classindex" style="column-count:{{ config.COLS_IN_ALPHA_INDEX }};-moz-column-count:{{ config.COLS_IN_ALPHA_INDEX }};-webkit-column-count:{{ config.COLS_IN_ALPHA_INDEX}}">
{% for section in index %}
<ul>
{% for cls in section.items %} {% for cls in section.items %}
<li>{{ cls.name }}</li> <li>
<span class="ai">
{% if forloop.first %}
<a name="#letter_{{ section.label }}"></a>
<span class="ah">&#160;&#160;{{ section.letter }}&#160;&#160;</span><br/>
{% endif %}
{% with obj=cls text=cls.name %}
{% include 'htmlobjlink.tpl' %}
{% endwith %}
</span>
</li>
{% endfor %} {% endfor %}
</ul>
{% endfor %}
</div><!-- classindex -->
{# quick index at bottom #}
<div class="qindex">
{% for section in index %}
<a class="qindex" href="#letter_{{ section.label }}">{{ section.letter }}</a>
{% if not forloop.last %}
&#160;|&#160;
{% endif %}
{% endfor %} {% endfor %}
</div>
{% endwith %} {% endwith %}
</ul>
</div><!-- classindex -->
</div><!-- contents --> </div><!-- contents -->
{% endblock %} {% endblock %}
{% extend 'htmlbase.tpl' %}
{% block content %}
<div class="contents">
<div class="textblock">
<p><a href="hierarchy{{ config.HTML_FILE_EXTENSION }}">{{ tr.gotoTextualHierarchy }}</a></p>
</div>
<table border="0" cellspacing="10" cellpadding="0">
{% for d in classHierarchy.diagrams %}
<tr><td>{{ d.graph }}</td></tr>
{% endfor %}
</table>
</div>
{% endblock %}
{% extend 'htmlbase.tpl' %}
{% block content %}
<div class="contents">
<div class="textblock">
<p>{{ tr.classHierarchyDescription }}</p>
{% if config.HAVE_DOT and config.GRAPHICAL_HIERARCHY %}
<p><a href="inherits{{ config.HTML_FILE_EXTENSION }}">{{ tr.gotoGraphicalHierarchy }}</a></p>
{% endif %}
</div>
{% indexentry nav name=tr.classHierarchy file=page.fileName anchor='' %}
{% opensubindex nav %}
{% with tree=classHierarchy %}
{% include 'htmldirtree.tpl' %}
{% endwith %}
{% closesubindex nav %}
</div>
{% endblock %}
...@@ -179,7 +179,12 @@ ...@@ -179,7 +179,12 @@
{# TODO: write the class inheritance hierarchy #} {# TODO: write the class inheritance hierarchy #}
{% if classHierarchy.tree %} {% if classHierarchy.tree %}
{% with page=classHierarchy %} {% with page=classHierarchy %}
{# {% create classHierarchy.fileName|append:config.HTML_FILE_EXTENSION from 'hierarchy.tpl' %} #} {% create classHierarchy.fileName|append:config.HTML_FILE_EXTENSION from 'htmlhierarchy.tpl' %}
{% endwith %}
{% with page=classHierarchy %}
{% if config.HAVE_DOT and config.GRAPHICAL_HIERARCHY %}
{% create 'inherits'|append:config.HTML_FILE_EXTENSION from 'htmlgraphhierarchy.tpl' %}
{% endif %}
{% endwith %} {% endwith %}
{% endif %} {% endif %}
......
...@@ -34,7 +34,9 @@ ...@@ -34,7 +34,9 @@
{% if classHierarchy.tree %} {% if classHierarchy.tree %}
<li><a href="{{ page.relPath }}hierarchy{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classHierarchy }} </span></a></li> <li><a href="{{ page.relPath }}hierarchy{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classHierarchy }} </span></a></li>
{% endif %} {% endif %}
{% if classMembersIndex.all %}
<li><a href="{{ page.relPath }}functions{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classMembers }} </span></a></li> <li><a href="{{ page.relPath }}functions{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classMembers }} </span></a></li>
{% endif %}
</ul> </ul>
</li> </li>
{% endif %} {% endif %}
......
...@@ -83,7 +83,9 @@ ...@@ -83,7 +83,9 @@
{% if classHierarchy.tree %} {% if classHierarchy.tree %}
<li{% if page.subhighlight=='classhierarchy' %} class="current"{% endif %}><a href="{{ page.relPath }}hierarchy{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classHierarchy|nowrap }}</span></a></li> <li{% if page.subhighlight=='classhierarchy' %} class="current"{% endif %}><a href="{{ page.relPath }}hierarchy{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classHierarchy|nowrap }}</span></a></li>
{% endif %} {% endif %}
{% if classMembersIndex.all %}
<li{% if page.subhighlight=='classmembers' %} class="current"{% endif %}><a href="{{ page.relPath }}functions{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classMembers|nowrap }}</span></a></li> <li{% if page.subhighlight=='classmembers' %} class="current"{% endif %}><a href="{{ page.relPath }}functions{{ config.HTML_FILE_EXTENSION }}"><span>{{ tr.classMembers|nowrap }}</span></a></li>
{% endif %}
{% endif %} {% endif %}
{# file subtabs #} {# file subtabs #}
{% if page.highlight=='files' %} {% if page.highlight=='files' %}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment