| ";
out << "" << endl;
out << "" << endl;
} else {
out << "";
}
////////////////////////////////////////////////////////
// Loop up to mother classes
if (dir == kUp || dir == kBoth) {
// make a loop on base classes
TBaseClass *inheritFrom;
TIter nextBase(classPtr->GetListOfBases());
UInt_t bgcolor=255-depth*8;
Bool_t first = kTRUE;
while ((inheritFrom = (TBaseClass *) nextBase())) {
if (first) {
out << "" << endl;
first = kFALSE;
} else
out << " " << endl;
out << "" << endl;
// get a class
TClass *classInh = fHtml->GetClass((const char *) inheritFrom->GetName());
if (classInh)
ClassHtmlTree(out, classInh, kUp, depth+1);
else
out << ""
<< (const char *) inheritFrom->GetName()
<< "";
out << " | "<< endl;
}
if (!first) {
out << "
| " << endl; // put it in additional row in table
out << "← | ";
}
}
out << "" << endl; // put it in additional row in table
////////////////////////////////////////////////////////
// Output Class Name
const char *className = classPtr->GetName();
TString htmlFile;
fHtml->GetHtmlFileName(classPtr, htmlFile);
TString anchor(className);
NameSpace2FileName(anchor);
if (dir == kUp) {
if (htmlFile) {
out << "";
ReplaceSpecialChars(out, className);
out << "" << endl;
} else
ReplaceSpecialChars(out, className);
}
if (dir == kBoth) {
if (htmlFile.Length()) {
out << "";
ReplaceSpecialChars(out, className);
out << "" << endl;
} else
ReplaceSpecialChars(out, className);
}
out << " | " << endl; // put it in additional row in table
////////////////////////////////////////////////////////
// Loop down to child classes
if (dir == kDown || dir == kBoth) {
// 1. make a list of class names
// 2. use DescendHierarchy
out << "" << endl;
fHierarchyLines = 0;
DescendHierarchy(out,classPtr,10);
out << " ";
if (dir==kBoth && fHierarchyLines>=10)
out << " | [more...]";
out<<" | " << endl;
// free allocated memory
}
out << " " << endl;
if (dir == kBoth)
out << "
| "<GetName());
NameSpace2FileName(filename);
gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
filename += "_Tree.pdf";
if (IsModified(fCurrentClass, kTree) || force) {
// TCanvas already prints pdf being saved
// Printf(fHtml->GetCounterFormat(), "", "", filename);
fCurrentClass->Draw("same");
Int_t saveErrorIgnoreLevel = gErrorIgnoreLevel;
gErrorIgnoreLevel = kWarning;
psCanvas->SaveAs(filename);
gErrorIgnoreLevel = saveErrorIgnoreLevel;
} else
Printf(fHtml->GetCounterFormat(), "-no change-", "", filename.Data());
}
//______________________________________________________________________________
Bool_t TClassDocOutput::CreateDotClassChartInh(const char* filename)
{
// Build the class tree for one class in GraphViz/Dot format
//
//
// Input: filename - output dot file incl. path
std::ofstream outdot(filename);
outdot << "strict digraph G {" << endl
<< "rankdir=RL;" << endl
<< "ranksep=2;" << endl
<< "nodesep=0;" << endl
<< "size=\"8,10\";" << endl
<< "ratio=auto;" << endl
<< "margin=0;" << endl
<< "node [shape=plaintext,fontsize=40,width=4,height=0.75];" << endl
<< "\"" << fCurrentClass->GetName() << "\" [shape=ellipse];" << endl;
std::stringstream ssDep;
std::list writeBasesFor;
writeBasesFor.push_back(fCurrentClass);
Bool_t haveBases = fCurrentClass->GetListOfBases() &&
fCurrentClass->GetListOfBases()->GetSize();
if (haveBases) {
outdot << "{" << endl;
while (!writeBasesFor.empty()) {
TClass* cl = writeBasesFor.front();
writeBasesFor.pop_front();
if (cl != fCurrentClass) {
outdot << " \"" << cl->GetName() << "\"";
const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
if (htmlFileName)
outdot << " [URL=\"" << htmlFileName << "\"]";
outdot << ";" << endl;
}
if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
ssDep << " \"" << cl->GetName() << "\" -> {";
TIter iBase(cl->GetListOfBases());
TBaseClass* base = 0;
while ((base = (TBaseClass*)iBase())) {
ssDep << " \"" << base->GetName() << "\";";
writeBasesFor.push_back(base->GetClassPointer());
}
ssDep << "}" << endl;
}
}
outdot << "}" << endl; // cluster
}
std::map derivesFromMe;
std::map entriesPerDerived;
std::set wroteNode;
wroteNode.insert(fCurrentClass);
static const unsigned int maxClassesPerDerived = 20;
fHtml->GetDerivedClasses(fCurrentClass, derivesFromMe);
outdot << "{" << endl;
for (Int_t level = 1; kTRUE; ++level) {
Bool_t levelExists = kFALSE;
for (std::map::iterator iDerived = derivesFromMe.begin();
iDerived != derivesFromMe.end(); ++iDerived) {
if (iDerived->second != level) continue;
levelExists = kTRUE;
TIter iBaseOfDerived(iDerived->first->GetListOfBases());
TBaseClass* baseDerived = 0;
Bool_t writeNode = kFALSE;
TClass* writeAndMoreFor = 0;
while ((baseDerived = (TBaseClass*) iBaseOfDerived())) {
TClass* clBaseDerived = baseDerived->GetClassPointer();
if (clBaseDerived->InheritsFrom(fCurrentClass)
&& wroteNode.find(clBaseDerived) != wroteNode.end()) {
unsigned int& count = entriesPerDerived[clBaseDerived];
if (count < maxClassesPerDerived) {
writeNode = kTRUE;
ssDep << "\"" << iDerived->first->GetName() << "\" -> \""
<< clBaseDerived->GetName() << "\";" << endl;
++count;
} else if (count == maxClassesPerDerived) {
writeAndMoreFor = clBaseDerived;
ssDep << "\"...andmore" << clBaseDerived->GetName() << "\"-> \""
<< clBaseDerived->GetName() << "\";" << endl;
++count;
}
}
}
if (writeNode) {
wroteNode.insert(iDerived->first);
outdot << " \"" << iDerived->first->GetName() << "\"";
const char* htmlFileName = fHtml->GetHtmlFileName(iDerived->first->GetName());
if (htmlFileName)
outdot << " [URL=\"" << htmlFileName << "\"]";
outdot << ";" << endl;
} else if (writeAndMoreFor) {
outdot << " \"...andmore" << writeAndMoreFor->GetName()
<< "\" [label=\"...and more\",fontname=\"Times-Italic\",fillcolor=lightgrey,style=filled];" << endl;
}
}
if (!levelExists) break;
}
outdot << "}" << endl; // cluster
outdot << ssDep.str();
outdot << "}" << endl; // digraph
return kTRUE;
}
//______________________________________________________________________________
Bool_t TClassDocOutput::CreateDotClassChartInhMem(const char* filename) {
// Build the class tree of inherited members for one class in GraphViz/Dot format
//
// Input: filename - output dot file incl. path
std::ofstream outdot(filename);
outdot << "strict digraph G {" << endl
<< "ratio=auto;" << endl
<< "rankdir=RL;" << endl
<< "compound=true;" << endl
<< "constraint=false;" << endl
<< "ranksep=0.1;" << endl
<< "nodesep=0;" << endl
<< "margin=0;" << endl;
outdot << " node [style=filled,width=0.7,height=0.15,fixedsize=true,shape=plaintext,fontsize=10];" << endl;
std::stringstream ssDep;
const int numColumns = 3;
std::list writeBasesFor;
writeBasesFor.push_back(fCurrentClass);
while (!writeBasesFor.empty()) {
TClass* cl = writeBasesFor.front();
writeBasesFor.pop_front();
const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
outdot << "subgraph \"cluster" << cl->GetName() << "\" {" << endl
<< " color=lightgray;" << endl
<< " label=\"" << cl->GetName() << "\";" << endl;
if (cl != fCurrentClass && htmlFileName)
outdot << " URL=\"" << htmlFileName << "\"" << endl;
//Bool_t haveMembers = (cl->GetListOfDataMembers() && cl->GetListOfDataMembers()->GetSize());
Bool_t haveFuncs = cl->GetListOfMethods() && cl->GetListOfMethods()->GetSize();
// DATA MEMBERS
{
// make sure each member name is listed only once
// that's useless for data members, but symmetric to what we have for methods
std::map dmMap;
{
TIter iDM(cl->GetListOfDataMembers());
TDataMember* dm = 0;
while ((dm = (TDataMember*) iDM()))
dmMap[dm->GetName()] = dm;
}
outdot << "subgraph \"clusterData0" << cl->GetName() << "\" {" << endl
<< " color=white;" << endl
<< " label=\"\";" << endl
<< " \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
TString prevColumnNode;
Int_t pos = dmMap.size();
Int_t column = 0;
Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
for (std::map::iterator iDM = dmMap.begin();
iDM != dmMap.end(); ++iDM, --pos) {
TDataMember* dm = iDM->second;
TString nodeName(cl->GetName());
nodeName += "::";
nodeName += dm->GetName();
if (iDM == dmMap.begin())
prevColumnNode = nodeName;
outdot << "\"" << nodeName << "\" [label=\""
<< dm->GetName() << "\"";
if (dm->Property() & kIsPrivate)
outdot << ",color=\"#FFCCCC\"";
else if (dm->Property() & kIsProtected)
outdot << ",color=\"#FFFF77\"";
else
outdot << ",color=\"#CCFFCC\"";
outdot << "];" << endl;
if (pos % newColumnEvery == 1) {
++column;
outdot << "};" << endl // end dataR
<< "subgraph \"clusterData" << column << cl->GetName() << "\" {" << endl
<< " color=white;" << endl
<< " label=\"\";" << endl
<< " \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
} else if (iDM != dmMap.begin() && pos % newColumnEvery == 0) {
ssDep << "\"" << prevColumnNode
<< "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
prevColumnNode = nodeName;
}
}
while (column < numColumns - 1) {
++column;
outdot << " \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
}
outdot << "};" << endl; // subgraph dataL/R
} // DATA MEMBERS
// FUNCTION MEMBERS
if (haveFuncs) {
// make sure each member name is listed only once
std::map methMap;
{
TIter iMeth(cl->GetListOfMethods());
TMethod* meth = 0;
while ((meth = (TMethod*) iMeth()))
methMap[meth->GetName()] = meth;
}
outdot << "subgraph \"clusterFunc0" << cl->GetName() << "\" {" << endl
<< " color=white;" << endl
<< " label=\"\";" << endl
<< " \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
TString prevColumnNodeFunc;
Int_t pos = methMap.size();
Int_t column = 0;
Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
for (std::map::iterator iMeth = methMap.begin();
iMeth != methMap.end(); ++iMeth, --pos) {
TMethod* meth = iMeth->second;
TString nodeName(cl->GetName());
nodeName += "::";
nodeName += meth->GetName();
if (iMeth == methMap.begin())
prevColumnNodeFunc = nodeName;
outdot << "\"" << nodeName << "\" [label=\"" << meth->GetName() << "\"";
if (cl != fCurrentClass &&
fCurrentClass->GetMethodAny(meth->GetName()))
outdot << ",color=\"#777777\"";
else if (meth->Property() & kIsPrivate)
outdot << ",color=\"#FFCCCC\"";
else if (meth->Property() & kIsProtected)
outdot << ",color=\"#FFFF77\"";
else
outdot << ",color=\"#CCFFCC\"";
outdot << "];" << endl;
if (pos % newColumnEvery == 1) {
++column;
outdot << "};" << endl // end funcR
<< "subgraph \"clusterFunc" << column << cl->GetName() << "\" {" << endl
<< " color=white;" << endl
<< " label=\"\";" << endl;
} else if (iMeth != methMap.begin() && pos % newColumnEvery == 0) {
ssDep << "\"" << prevColumnNodeFunc
<< "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
prevColumnNodeFunc = nodeName;
}
}
outdot << "};" << endl; // subgraph funcL/R
}
outdot << "}" << endl; // cluster class
for (Int_t pos = 0; pos < numColumns - 1; ++pos)
ssDep << "\"clusterNode" << pos << cl->GetName() << "\" -> \"clusterNode" << pos + 1 << cl->GetName() << "\" [style=invis];" << endl;
if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
TIter iBase(cl->GetListOfBases());
TBaseClass* base = 0;
while ((base = (TBaseClass*)iBase())) {
ssDep << " \"clusterNode" << numColumns - 1 << cl->GetName() << "\" -> "
<< " \"clusterNode0" << base->GetName() << "\" [ltail=\"cluster" << cl->GetName()
<< "\",lhead=\"cluster" << base->GetName() << "\"";
if (base != cl->GetListOfBases()->First())
ssDep << ",weight=0";
ssDep << "];" << endl;
writeBasesFor.push_back(base->GetClassPointer());
}
}
}
outdot << ssDep.str();
outdot << "}" << endl; // digraph
return kTRUE;
}
//______________________________________________________________________________
Bool_t TClassDocOutput::CreateDotClassChartIncl(const char* filename) {
// Build the include dependency graph for one class in
// GraphViz/Dot format
//
// Input: filename - output dot file incl. path
R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
std::map filesToParse;
std::list listFilesToParse;
TString declFileName;
TString implFileName;
fHtml->GetImplFileName(fCurrentClass, kFALSE, implFileName);
if (fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFileName)) {
TString real;
if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, real)) {
filesToParse[declFileName.Data()] = real.Data();
listFilesToParse.push_back(declFileName.Data());
}
}
/* do it only for the header
if (implFileName && strlen(implFileName)) {
char* real = gSystem->Which(fHtml->GetInputPath(), implFileName, kReadPermission);
if (real) {
filesToParse[implFileName] = real;
listFilesToParse.push_back(implFileName);
delete real;
}
}
*/
std::ofstream outdot(filename);
outdot << "strict digraph G {" << endl
<< "ratio=compress;" << endl
<< "rankdir=TB;" << endl
<< "concentrate=true;" << endl
<< "ranksep=0;" << endl
<< "nodesep=0;" << endl
<< "size=\"8,10\";" << endl
<< "node [fontsize=20,shape=plaintext];" << endl;
for (std::list::iterator iFile = listFilesToParse.begin();
iFile != listFilesToParse.end(); ++iFile) {
ifstream in(filesToParse[*iFile].c_str());
std::string line;
while (in && !in.eof()) {
std::getline(in, line);
size_t pos = 0;
while (line[pos] == ' ' || line[pos] == '\t') ++pos;
if (line[pos] != '#') continue;
++pos;
while (line[pos] == ' ' || line[pos] == '\t') ++pos;
if (line.compare(pos, 8, "include ") != 0) continue;
pos += 8;
while (line[pos] == ' ' || line[pos] == '\t') ++pos;
if (line[pos] != '"' && line[pos] != '<')
continue;
char delim = line[pos];
if (delim == '<') delim = '>';
++pos;
line.erase(0, pos);
pos = 0;
pos = line.find(delim);
if (pos == std::string::npos) continue;
line.erase(pos);
if (filesToParse.find(line) == filesToParse.end()) {
TString sysfilename;
if (!GetHtml()->GetPathDefinition().GetFileNameFromInclude(line.c_str(), sysfilename))
continue;
listFilesToParse.push_back(line);
filesToParse[line] = sysfilename;
if (*iFile == implFileName.Data() || *iFile == declFileName.Data())
outdot << "\"" << *iFile << "\" [style=filled,fillcolor=lightgray];" << endl;
}
outdot << "\"" << *iFile << "\" -> \"" << line << "\";" << endl;
}
}
outdot << "}" << endl; // digraph
return kTRUE;
}
//______________________________________________________________________________
Bool_t TClassDocOutput::CreateDotClassChartLib(const char* filename) {
// Build the library dependency graph for one class in
// GraphViz/Dot format
//
// Input: filename - output dot file incl. path
std::ofstream outdot(filename);
outdot << "strict digraph G {" << endl
<< "ratio=auto;" << endl
<< "rankdir=RL;" << endl
<< "compound=true;" << endl
<< "constraint=false;" << endl
<< "ranksep=0.7;" << endl
<< "nodesep=0.3;" << endl
<< "size=\"8,8\";" << endl
<< "ratio=compress;" << endl;
TString libs(fCurrentClass->GetSharedLibs());
outdot << "\"All Libraries\" [URL=\"LibraryDependencies.html\",shape=box,rank=max,fillcolor=lightgray,style=filled];" << endl;
if (libs.Length()) {
TString firstLib(libs);
Ssiz_t end = firstLib.Index(' ');
if (end != kNPOS) {
firstLib.Remove(end, firstLib.Length());
libs.Remove(0, end + 1);
} else libs = "";
{
Ssiz_t posExt = firstLib.First(".");
if (posExt != kNPOS)
firstLib.Remove(posExt, firstLib.Length());
}
outdot << "\"All Libraries\" -> \"" << firstLib << "\" [style=invis];" << endl;
outdot << "\"" << firstLib << "\" -> {" << endl;
if (firstLib != "libCore")
libs += " libCore";
if (firstLib != "libCint")
libs += " libCint";
TString thisLib;
for (Ssiz_t pos = 0; pos < libs.Length(); ++pos)
if (libs[pos] != ' ')
thisLib += libs[pos];
else if (thisLib.Length()) {
Ssiz_t posExt = thisLib.First(".");
if (posExt != kNPOS)
thisLib.Remove(posExt, thisLib.Length());
outdot << " \"" << thisLib << "\";";
thisLib = "";
}
// remaining lib
if (thisLib.Length()) {
Ssiz_t posExt = thisLib.First(".");
if (posExt != kNPOS)
thisLib.Remove(posExt, thisLib.Length());
outdot << " \"" << thisLib << "\";";
thisLib = "";
}
outdot << "}" << endl; // dependencies
} else
outdot << "\"No rlibmap information available.\"" << endl;
outdot << "}" << endl; // digraph
return kTRUE;
}
//______________________________________________________________________________
void TClassDocOutput::CreateClassHierarchy(std::ostream& out, const char* docFileName)
{
// Create the hierarchical class list part for the current class's
// base classes. docFileName contains doc for fCurrentClass.
//
// Find basic base classes
TList *bases = fCurrentClass->GetListOfBases();
if (!bases || bases->IsEmpty())
return;
out << " " << endl;
out << " | ";
fHierarchyLines = 0;
DescendHierarchy(out, fCurrentClass);
out << " " << endl;
}
//______________________________________________________________________________
Bool_t TClassDocOutput::CreateHierarchyDot()
{
// Create a hierarchical class list
// The algorithm descends from the base classes and branches into
// all derived classes. Mixing classes are displayed several times.
//
//
const char* title = "ClassHierarchy";
TString filename(title);
gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
// open out file
std::ofstream dotout(filename + ".dot");
if (!dotout.good()) {
Error("CreateHierarchy", "Can't open file '%s.dot' !",
filename.Data());
return kFALSE;
}
dotout << "digraph G {" << endl
<< "ratio=auto;" << endl
<< "rankdir=RL;" << endl;
// loop on all classes
TClassDocInfo* cdi = 0;
TIter iClass(fHtml->GetListOfClasses());
while ((cdi = (TClassDocInfo*)iClass())) {
TDictionary *dict = cdi->GetClass();
TClass *cl = dynamic_cast(dict);
if (cl == 0) {
if (!dict)
Warning("THtml::CreateHierarchy", "skipping class %s\n", cdi->GetName());
continue;
}
// Find immediate base classes
TList *bases = cl->GetListOfBases();
if (bases && !bases->IsEmpty()) {
dotout << "\"" << cdi->GetName() << "\" -> { ";
TIter iBase(bases);
TBaseClass* base = 0;
while ((base = (TBaseClass*) iBase())) {
// write out current class
if (base != bases->First())
dotout << "; ";
dotout << "\"" << base->GetName() << "\"";
}
dotout << "};" << endl;
} else
// write out current class - no bases
dotout << "\"" << cdi->GetName() << "\";" << endl;
}
dotout << "}";
dotout.close();
std::ofstream out(filename + ".html");
if (!out.good()) {
Error("CreateHierarchy", "Can't open file '%s.html' !",
filename.Data());
return kFALSE;
}
Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), (filename + ".html").Data());
// write out header
WriteHtmlHeader(out, "Class Hierarchy");
out << "Class Hierarchy" << endl;
WriteSearch(out);
RunDot(filename, &out);
out << "" << endl;
// write out footer
WriteHtmlFooter(out);
return kTRUE;
}
//______________________________________________________________________________
void TClassDocOutput::CreateSourceOutputStream(std::ostream& out, const char* extension,
TString& sourceHtmlFileName)
{
// Open a Class.cxx.html file, where Class is defined by classPtr, and .cxx.html by extension
// It's created in fHtml->GetOutputDir()/src. If successful, the HTML header is written to out.
TString sourceHtmlDir("src");
gSystem->PrependPathName(fHtml->GetOutputDir(), sourceHtmlDir);
// create directory if necessary
{
R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
if (gSystem->AccessPathName(sourceHtmlDir))
gSystem->MakeDirectory(sourceHtmlDir);
}
sourceHtmlFileName = fCurrentClass->GetName();
NameSpace2FileName(sourceHtmlFileName);
gSystem->PrependPathName(sourceHtmlDir, sourceHtmlFileName);
sourceHtmlFileName += extension;
dynamic_cast(out).open(sourceHtmlFileName);
if (!out) {
Warning("LocateMethodsInSource", "Can't open beautified source file '%s' for writing!",
sourceHtmlFileName.Data());
sourceHtmlFileName.Remove(0);
return;
}
// write a HTML header
TString title(fCurrentClass->GetName());
title += " - source file";
WriteHtmlHeader(out, title, "../", fCurrentClass);
out << "" << std::endl;
}
//______________________________________________________________________________
void TClassDocOutput::DescendHierarchy(std::ostream& out, TClass* basePtr, Int_t maxLines, Int_t depth)
{
// Descend hierarchy recursively
// loop over all classes and look for classes with base class basePtr
if (maxLines)
if (fHierarchyLines >= maxLines) {
out << " | " << endl;
return;
}
UInt_t numClasses = 0;
TClassDocInfo* cdi = 0;
TIter iClass(fHtml->GetListOfClasses());
while ((cdi = (TClassDocInfo*)iClass()) && (!maxLines || fHierarchyLines(cdi->GetClass());
if (!classPtr) continue;
// find base classes with same name as basePtr
TList* bases=classPtr->GetListOfBases();
if (!bases) continue;
TBaseClass *inheritFrom=(TBaseClass*)bases->FindObject(basePtr->GetName());
if (!inheritFrom) continue;
if (!numClasses)
out << "← | " << endl;
else
out << " "<";
out << "" << endl;
} // loop over all classes
if (numClasses)
out << "
| " << endl;
else
out << " | " << endl;
}
//______________________________________________________________________________
void TClassDocOutput::MakeTree(Bool_t force /*= kFALSE*/)
{
// Create an output file with a graphical representation of the class
// inheritance. If force, replace existing output file.
// This routine does nothing if fHtml->HaveDot() is true - use
// ClassDotCharts() instead!
// class tree only if no dot, otherwise it's part of charts
if (!fCurrentClass || fHtml->HaveDot())
return;
TString htmlFile;
fHtml->GetHtmlFileName(fCurrentClass, htmlFile);
if (htmlFile.Length()
&& (htmlFile.BeginsWith("http://")
|| htmlFile.BeginsWith("https://")
|| gSystem->IsAbsoluteFileName(htmlFile))
) {
htmlFile.Remove(0);
}
if (!htmlFile.Length()) {
TString what(fCurrentClass->GetName());
what += " (source not found)";
Printf(fHtml->GetCounterFormat(), "-skipped-", "", what.Data());
return;
}
R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
// Create a canvas without linking against GUI libs
Bool_t wasBatch = gROOT->IsBatch();
if (!wasBatch)
gROOT->SetBatch();
TVirtualPad *psCanvas = (TVirtualPad*)gROOT->ProcessLineFast("new TCanvas(\"R__THtml\",\"psCanvas\",0,0,1000,1200);");
if (!wasBatch)
gROOT->SetBatch(kFALSE);
if (!psCanvas) {
Error("MakeTree", "Cannot create a TCanvas!");
return;
}
// make a class tree
ClassTree(psCanvas, force);
psCanvas->Close();
delete psCanvas;
}
//______________________________________________________________________________
void TClassDocOutput::WriteClassDescription(std::ostream& out, const TString& description)
{
// Called by TDocParser::LocateMethods(), this hook writes out the class description
// found by TDocParser. It's even called if none is found, i.e. if the first method
// has occurred before a class description is found, so missing class descriptions
// can be handled.
// For HTML, its creates the description block, the list of functions and data
// members, and the inheritance tree or, if Graphviz's dot is found, the class charts.
// Class Description Title
out << "";
TString anchor(fCurrentClass->GetName());
NameSpace2FileName(anchor);
out << " ";
if (fHtml->IsNamespace(fCurrentClass))
out << "namespace ";
else
out << "class ";
ReplaceSpecialChars(out, fCurrentClass->GetName());
// make a loop on base classes
Bool_t first = kTRUE;
TBaseClass *inheritFrom;
TIter nextBase(fCurrentClass->GetListOfBases());
while ((inheritFrom = (TBaseClass *) nextBase())) {
if (first) {
out << ": ";
first = kFALSE;
} else
out << ", ";
Long_t property = inheritFrom->Property();
if (property & kIsPrivate)
out << "private ";
else if (property & kIsProtected)
out << "protected ";
else
out << "public ";
// get a class
TClass *classInh = fHtml->GetClass(inheritFrom->GetName());
TString htmlFile;
fHtml->GetHtmlFileName(classInh, htmlFile);
if (htmlFile.Length()) {
// make a link to the base class
out << "";
ReplaceSpecialChars(out, inheritFrom->GetName());
out << "";
} else
ReplaceSpecialChars(out, inheritFrom->GetName());
}
out << "" << endl;
out << " " << endl;
if (description.Length())
out << " " << description << " ";
// typedefs pointing to this class:
if (fCurrentClassesTypedefs && !fCurrentClassesTypedefs->IsEmpty()) {
out << " This class is also known as (typedefs to this class)";
TIter iTD(fCurrentClassesTypedefs);
bool firsttd = true;
TDataType* dt = 0;
while ((dt = (TDataType*) iTD())) {
if (!firsttd)
out << ", ";
else firsttd = false;
fParser->DecorateKeywords(out, dt->GetName());
}
}
out << " " << std::endl
<< " " << std::endl;
ListFunctions(out);
ListDataMembers(out);
// create dot class charts or an html inheritance tree
out << "Class Charts" << endl;
if (!fHtml->IsNamespace(fCurrentClass))
if (!ClassDotCharts(out))
ClassHtmlTree(out, fCurrentClass);
// header for the following function docs:
out << "Function documentation" << endl;
}
//______________________________________________________________________________
void TClassDocOutput::WriteClassDocHeader(std::ostream& classFile)
{
// Write out the introduction of a class description (shortcuts and links)
classFile << "" << endl;
// show box with lib, include
// needs to go first to allow title on the left
TString sTitle(fCurrentClass->GetName());
ReplaceSpecialChars(sTitle);
if (fHtml->IsNamespace(fCurrentClass))
sTitle.Prepend("namespace ");
else
sTitle.Prepend("class ");
TString sInclude;
TString sLib;
const char* lib=fCurrentClass->GetSharedLibs();
GetHtml()->GetPathDefinition().GetIncludeAs(fCurrentClass, sInclude);
if (lib) {
char* libDup=StrDup(lib);
char* libDupSpace=strchr(libDup,' ');
if (libDupSpace) *libDupSpace=0;
char* libDupEnd=libDup+strlen(libDup);
while (libDupEnd!=libDup)
if (*(--libDupEnd)=='.') {
*libDupEnd=0;
break;
}
sLib = libDup;
delete[] libDup;
}
classFile << "" << endl;
TString modulename;
fHtml->GetModuleNameForClass(modulename, fCurrentClass);
TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
WriteTopLinks(classFile, module, fCurrentClass->GetName(), kFALSE);
classFile << "" << endl // descrhead line 3
<< " Source:" << endl;
// make a link to the '.cxx' file
TString classFileName(fCurrentClass->GetName());
NameSpace2FileName(classFileName);
TString headerFileName;
fHtml->GetDeclFileName(fCurrentClass, kFALSE, headerFileName);
TString sourceFileName;
fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
if (headerFileName.Length())
classFile << " header file" << endl;
else
classFile << " " << endl;
if (sourceFileName.Length())
classFile << " source file" << endl;
else
classFile << " " << endl;
if (!fHtml->IsNamespace(fCurrentClass) && !fHtml->HaveDot()) {
// make a link to the inheritance tree (postscript)
classFile << " inheritance tree (.pdf) ";
}
const TString& viewCVSLink = GetHtml()->GetViewCVS();
Bool_t mustReplace = viewCVSLink.Contains("%f");
if (viewCVSLink.Length()) {
if (headerFileName.Length()) {
TString link(viewCVSLink);
TString sHeader(headerFileName);
if (GetHtml()->GetProductName() && !strcmp(GetHtml()->GetProductName(), "ROOT")) {
Ssiz_t posInclude = sHeader.Index("/include/");
if (posInclude != kNPOS) {
// Cut off ".../include", i.e. keep leading '/'
sHeader.Remove(0, posInclude + 8);
} else {
// no /include/; maybe /inc?
posInclude = sHeader.Index("/inc/");
if (posInclude != kNPOS) {
sHeader = "/";
sHeader += sInclude;
}
}
if (sourceFileName && strstr(sourceFileName, "src")) {
TString src(sourceFileName);
src.Remove(src.Index("src"), src.Length());
src += "inc";
sHeader.Prepend(src);
} else {
TString src(fCurrentClass->GetSharedLibs());
Ssiz_t posEndLib = src.Index(' ');
if (posEndLib != kNPOS)
src.Remove(posEndLib, src.Length());
if (src.BeginsWith("lib"))
src.Remove(0, 3);
posEndLib = src.Index('.');
if (posEndLib != kNPOS)
src.Remove(posEndLib, src.Length());
src.ToLower();
src += "/inc";
sHeader.Prepend(src);
}
if (sHeader.BeginsWith("tmva/inc/TMVA"))
sHeader.Remove(8, 5);
}
if (mustReplace) link.ReplaceAll("%f", sHeader);
else link += sHeader;
classFile << " viewVC header ";
} else
classFile << " ";
if (sourceFileName.Length()) {
TString link(viewCVSLink);
if (mustReplace) link.ReplaceAll("%f", sourceFileName);
else link += sourceFileName;
classFile << " viewVC source ";
} else
classFile << " ";
}
TString currClassNameMangled(fCurrentClass->GetName());
NameSpace2FileName(currClassNameMangled);
TString wikiLink = GetHtml()->GetWikiURL();
if (wikiLink.Length()) {
if (wikiLink.Contains("%c")) wikiLink.ReplaceAll("%c", currClassNameMangled);
else wikiLink += currClassNameMangled;
classFile << " wiki ";
}
classFile << endl << " " << endl; // descrhead line 3
classFile << "" << endl // descrhead line 4
<< " " << endl; // toplinks, from TDocOutput::WriteTopLinks
WriteLocation(classFile, module, fCurrentClass->GetName());
}
//______________________________________________________________________________
void TClassDocOutput::WriteMethod(std::ostream& out, TString& ret,
TString& name, TString& params,
const char* filename, TString& anchor,
TString& comment, TString& codeOneLiner,
TDocMethodWrapper* guessedMethod)
{
// Write method name with return type ret and parameters param to out.
// Build a link using file and anchor. Cooment it with comment, and
// show the code codeOneLiner (set if the func consists of only one line
// of code, immediately surrounded by "{","}"). Also updates fMethodNames's
// count of method names.
fParser->DecorateKeywords(ret);
out << "" << std::endl;
}
|