ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/Utils/src/TClassDocOutput.cxx
Revision: 1.1
Committed: Tue Aug 11 23:09:28 2009 UTC (15 years, 8 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_025c_branch2, Mit_025c_branch1, Mit_030, Mit_029c, Mit_029b, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_025c_branch0, Mit_028, Mit_027a, Mit_027, Mit_026, Mit_025e, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1, Mit_018, Mit_017, Mit_017pre3, Mit_017pre2, Mit_017pre1, Mit_016, Mit_015b, Mit_015a, Mit_015, Mit_014e, Mit_014d, Mit_014c, Mit_014b, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, Mit_012i, Mit_012h, Mit_012g, Mit_012f, Mit_012e, Mit_012d, Mit_012c, Mit_012b, Mit_012a, Mit_012, Mit_011a, Mit_011, Mit_010a, HEAD
Branch point for: Mit_025c_branch
Log Message:
Added THtml from ROOT

File Contents

# Content
1 // @(#)root/html:$Id: TClassDocOutput.cxx 26715 2008-12-07 17:32:59Z axel $
2 // Author: Axel Naumann 2007-01-09
3
4 /*************************************************************************
5 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12 #include "MitAna/Utils/interface/TClassDocOutput.h"
13
14 #include "TBaseClass.h"
15 #include "TDataMember.h"
16 #include "TMethodArg.h"
17 #include "TDataType.h"
18 #include "MitAna/Utils/interface/TDocInfo.h"
19 #include "MitAna/Utils/interface/TDocParser.h"
20 #include "TEnv.h"
21 #include "TError.h"
22 #include "THtml.h"
23 #include "TMethod.h"
24 #include "TROOT.h"
25 #include "TSystem.h"
26 #include "TVirtualPad.h"
27 #include "TVirtualMutex.h"
28 #include "Riostream.h"
29 #include <sstream>
30
31 //______________________________________________________________________________
32 //
33 // Write the documentation for a class or namespace. The documentation is
34 // parsed by TDocParser and then passed to TClassDocOutput to generate
35 // the class doc header, the class description, members overview, and method
36 // documentation. All generic output functionality is in TDocOutput; it is
37 // re-used in this derived class.
38 //
39 // You usually do not use this class yourself; it is invoked indirectly by
40 // THtml. Customization of the output should happen via the interfaces defined
41 // by THtml.
42 //______________________________________________________________________________
43
44
45 ClassImp(TClassDocOutput)
46
47 //______________________________________________________________________________
48 TClassDocOutput::TClassDocOutput(THtml& html, TClass* cl, TList* typedefs):
49 TDocOutput(html), fHierarchyLines(0), fCurrentClass(cl),
50 fCurrentClassesTypedefs(typedefs), fParser(0)
51 {
52 // Create an object given the invoking THtml object, and the TClass
53 // object that we will generate output for.
54
55 fParser = new TDocParser(*this, fCurrentClass);
56 }
57
58 //______________________________________________________________________________
59 TClassDocOutput::~TClassDocOutput()
60 {
61 // Destructor, deletes fParser
62 delete fParser;
63 }
64
65 //______________________________________________________________________________
66 void TClassDocOutput::Class2Html(Bool_t force)
67 {
68 // Create HTML files for a single class.
69 //
70
71 gROOT->GetListOfGlobals(kTRUE);
72
73 // create a filename
74 TString filename(fCurrentClass->GetName());
75 NameSpace2FileName(filename);
76
77 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
78
79 filename += ".html";
80
81 if (!force && !IsModified(fCurrentClass, kSource)
82 && !IsModified(fCurrentClass, kDoc)) {
83 Printf(fHtml->GetCounterFormat(), "-no change-", fHtml->GetCounter(), filename.Data());
84 return;
85 }
86
87 // open class file
88 std::ofstream classFile(filename);
89
90 if (!classFile.good()) {
91 Error("Make", "Can't open file '%s' !", filename.Data());
92 return;
93 }
94
95 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
96
97 // write a HTML header for the classFile file
98 WriteHtmlHeader(classFile, fCurrentClass->GetName(), "", fCurrentClass);
99 WriteClassDocHeader(classFile);
100
101 // copy .h file to the Html output directory
102 TString declf;
103 if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declf))
104 CopyHtmlFile(declf);
105
106 // process a '.cxx' file
107 fParser->Parse(classFile);
108
109 // write classFile footer
110 WriteHtmlFooter(classFile, "",
111 fParser->GetSourceInfo(TDocParser::kInfoLastUpdate),
112 fParser->GetSourceInfo(TDocParser::kInfoAuthor),
113 fParser->GetSourceInfo(TDocParser::kInfoCopyright));
114 }
115
116 //______________________________________________________________________________
117 void TClassDocOutput::ListFunctions(std::ostream& classFile)
118 {
119 // Write the list of functions
120
121 // loop to get a pointers to method names
122
123 TString currClassNameMangled(fCurrentClass->GetName());
124 NameSpace2FileName(currClassNameMangled);
125
126 classFile << endl << "<div id=\"functions\">" << endl;
127 classFile << "<h2><a id=\"" << currClassNameMangled
128 << ":Function_Members\"></a>Function Members (Methods)</h2>" << endl;
129
130 const char* tab4nbsp="&nbsp;&nbsp;&nbsp;&nbsp;";
131 TString declFile;
132 fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFile);
133 if (fCurrentClass->Property() & kIsAbstract)
134 classFile << "&nbsp;<br /><b>"
135 << tab4nbsp << "This is an abstract class, constructors will not be documented.<br />" << endl
136 << tab4nbsp << "Look at the <a href=\""
137 << gSystem->BaseName(declFile)
138 << "\">header</a> to check for available constructors.</b><br />" << endl;
139
140 Int_t minAccess = 0;
141 if (fHtml->IsNamespace(fCurrentClass))
142 minAccess = TDocParser::kPublic;
143 for (Int_t access = TDocParser::kPublic; access >= minAccess; --access) {
144
145 const TList* methods = fParser->GetMethods((TDocParser::EAccess)access);
146 if (methods->GetEntries() == 0)
147 continue;
148
149 classFile << "<div class=\"access\" ";
150 const char* accessID [] = {"priv", "prot", "publ"};
151 const char* accesstxt[] = {"private", "protected", "public"};
152
153 classFile << "id=\"func" << accessID[access] << "\"><b>"
154 << accesstxt[access] << ":</b>" << endl
155 << "<table class=\"func\" id=\"tabfunc" << accessID[access] << "\" cellspacing=\"0\">" << endl;
156
157 TIter iMethWrap(methods);
158 TDocParser::TMethodWrapper *methWrap = 0;
159 while ((methWrap = (TDocParser::TMethodWrapper*) iMethWrap())) {
160 const TMethod* method = methWrap->GetMethod();
161
162 // it's a c'tor - Cint stores the class name as return type
163 Bool_t isctor = (!strcmp(method->GetName(), method->GetReturnTypeName()));
164 // it's a d'tor - Cint stores "void" as return type
165 Bool_t isdtor = (!isctor && method->GetName()[0] == '~');
166
167 classFile << "<tr class=\"func";
168 if (method->GetClass() != fCurrentClass)
169 classFile << "inh";
170 classFile << "\"><td class=\"funcret\">";
171 if (kIsVirtual & method->Property()) {
172 if (!isdtor)
173 classFile << "virtual ";
174 else
175 classFile << " virtual";
176 }
177
178 if (kIsStatic & method->Property())
179 classFile << "static ";
180
181 if (!isctor && !isdtor)
182 fParser->DecorateKeywords(classFile, method->GetReturnTypeName());
183
184 TString mangled(method->GetClass()->GetName());
185 NameSpace2FileName(mangled);
186 classFile << "</td><td class=\"funcname\"><a class=\"funcname\" href=\"";
187 if (method->GetClass() != fCurrentClass) {
188 TString htmlFile;
189 fHtml->GetHtmlFileName(method->GetClass(), htmlFile);
190 classFile << htmlFile;
191 }
192 classFile << "#" << mangled;
193 classFile << ":";
194 mangled = method->GetName();
195 NameSpace2FileName(mangled);
196 classFile << mangled << "\">";
197 if (method->GetClass() != fCurrentClass) {
198 classFile << "<span class=\"baseclass\">";
199 ReplaceSpecialChars(classFile, method->GetClass()->GetName());
200 classFile << "::</span>";
201 }
202 ReplaceSpecialChars(classFile, method->GetName());
203 classFile << "</a>";
204
205 fParser->DecorateKeywords(classFile, const_cast<TMethod*>(method)->GetSignature());
206 bool propSignal = false;
207 bool propMenu = false;
208 bool propToggle = false;
209 bool propGetter = false;
210 if (method->GetTitle()) {
211 propSignal = (strstr(method->GetTitle(), "*SIGNAL*"));
212 propMenu = (strstr(method->GetTitle(), "*MENU*"));
213 propToggle = (strstr(method->GetTitle(), "*TOGGLE*"));
214 propGetter = (strstr(method->GetTitle(), "*GETTER"));
215 if (propSignal || propMenu || propToggle || propGetter) {
216 classFile << "<span class=\"funcprop\">";
217 if (propSignal) classFile << "<abbr title=\"emits a signal\">SIGNAL</abbr> ";
218 if (propMenu) classFile << "<abbr title=\"has a popup menu entry\">MENU</abbr> ";
219 if (propToggle) classFile << "<abbr title=\"toggles a state\">TOGGLE</abbr> ";
220 if (propGetter) {
221 TString getter(method->GetTitle());
222 Ssiz_t posGetter = getter.Index("*GETTER=");
223 getter.Remove(0, posGetter + 8);
224 classFile << "<abbr title=\"use " + getter + "() as getter\">GETTER</abbr> ";
225 }
226 classFile << "</span>";
227 }
228 }
229 classFile << "</td></tr>" << endl;
230 }
231 classFile << endl << "</table></div>" << endl;
232 }
233
234 classFile << "</div>" << endl; // class="functions"
235 }
236
237 //______________________________________________________________________________
238 void TClassDocOutput::ListDataMembers(std::ostream& classFile)
239 {
240 // Write the list of data members and enums
241
242 // make a loop on data members
243 Bool_t haveDataMembers = (fParser->GetDataMembers(TDocParser::kPrivate)->GetEntries() ||
244 fParser->GetDataMembers(TDocParser::kProtected)->GetEntries() ||
245 fParser->GetDataMembers(TDocParser::kPublic)->GetEntries() ||
246 fParser->GetEnums(TDocParser::kPublic)->GetEntries() ||
247 fParser->GetEnums(TDocParser::kProtected)->GetEntries() ||
248 fParser->GetEnums(TDocParser::kPrivate)->GetEntries());
249
250 if (!haveDataMembers) return;
251
252 TString currClassNameMangled(fCurrentClass->GetName());
253 NameSpace2FileName(currClassNameMangled);
254
255 classFile << endl << "<div id=\"datamembers\">" << endl;
256 classFile << "<h2><a name=\"" << currClassNameMangled
257 << ":Data_Members\"></a>Data Members</h2>" << endl;
258
259 for (Int_t access = 5; access >= 0 && !fHtml->IsNamespace(fCurrentClass); --access) {
260 const TList* datamembers = 0;
261 if (access > 2) datamembers = fParser->GetEnums((TDocParser::EAccess) (access - 3));
262 else datamembers = fParser->GetDataMembers((TDocParser::EAccess) access);
263 if (datamembers->GetEntries() == 0)
264 continue;
265
266 classFile << "<div class=\"access\" ";
267 const char* what = "data";
268 if (access > 2) what = "enum";
269 const char* accessID [] = {"priv", "prot", "publ"};
270 const char* accesstxt[] = {"private", "protected", "public"};
271
272 classFile << "id=\"" << what << accessID[access%3] << "\"><b>"
273 << accesstxt[access%3] << ":</b>" << endl
274 << "<table class=\"data\" id=\"tab" << what << accessID[access%3] << "\" cellspacing=\"0\">" << endl;
275
276 TIter iDM(datamembers);
277 TDataMember *member = 0;
278 TString prevEnumName;
279 Bool_t prevIsInh = kTRUE;
280
281 while ((member = (TDataMember*) iDM())) {
282 Bool_t haveNewEnum = access > 2 && prevEnumName != member->GetTypeName();
283 if (haveNewEnum) {
284 if (prevEnumName.Length()) {
285 classFile << "<tr class=\"data";
286 if (prevIsInh)
287 classFile << "inh";
288 classFile << "\"><td class=\"datatype\">};</td><td></td><td></td></tr>" << endl;
289 }
290 prevEnumName = member->GetTypeName();
291 }
292
293 classFile << "<tr class=\"data";
294 prevIsInh = (member->GetClass() != fCurrentClass);
295 if (prevIsInh)
296 classFile << "inh";
297 classFile << "\"><td class=\"datatype\">";
298 if (haveNewEnum) {
299 TString enumName(member->GetTypeName());
300 TString myScope(fCurrentClass->GetName());
301 myScope += "::";
302 enumName.ReplaceAll(myScope, "");
303 if (enumName.EndsWith("::"))
304 enumName += "<i>[unnamed]</i>";
305 Ssiz_t startClassName = 0;
306 if (!enumName.BeginsWith("enum "))
307 classFile << "enum ";
308 else
309 startClassName = 5;
310
311 Ssiz_t endClassName = enumName.Last(':'); // need template handling here!
312 if (endClassName != kNPOS && endClassName > 0 && enumName[endClassName - 1] == ':') {
313 // TClass* cl = fHtml->GetClass(TString(enumName(startClassName, endClassName - startClassName - 1)));
314 TSubString substr(enumName(startClassName, endClassName - startClassName + 1));
315 // if (cl)
316 // ReferenceEntity(substr, cl);
317 enumName.Insert(substr.Start() + substr.Length(), "</span>");
318 enumName.Insert(substr.Start(), "<span class=\"baseclass\">");
319 }
320 classFile << enumName << " { ";
321 } else
322 if (access < 3) {
323 if (member->Property() & G__BIT_ISSTATIC)
324 classFile << "static ";
325 fParser->DecorateKeywords(classFile, member->GetFullTypeName());
326 }
327
328 TString mangled(member->GetClass()->GetName());
329 NameSpace2FileName(mangled);
330 classFile << "</td><td class=\"dataname\"><a ";
331 if (member->GetClass() != fCurrentClass) {
332 classFile << "href=\"";
333 TString htmlFile;
334 fHtml->GetHtmlFileName(member->GetClass(), htmlFile);
335 classFile << htmlFile << "#";
336 } else
337 classFile << "name=\"";
338 classFile << mangled;
339 classFile << ":";
340 mangled = member->GetName();
341 NameSpace2FileName(mangled);
342 classFile << mangled << "\">";
343 if (member->GetClass() == fCurrentClass)
344 classFile << "</a>";
345 if (access < 3 && member->GetClass() != fCurrentClass) {
346 classFile << "<span class=\"baseclass\">";
347 ReplaceSpecialChars(classFile, member->GetClass()->GetName());
348 classFile << "::</span>";
349 }
350 ReplaceSpecialChars(classFile, member->GetName());
351
352 // Add the dimensions to "array" members
353 for (Int_t indx = 0; indx < member->GetArrayDim(); ++indx)
354 if (member->GetMaxIndex(indx) <= 0)
355 break;
356 else
357 classFile << "[" << member->GetMaxIndex(indx) << "]";
358
359 if (member->GetClass() != fCurrentClass)
360 classFile << "</a>";
361 classFile << "</td>";
362 if (member->GetTitle() && member->GetTitle()[0]) {
363 classFile << "<td class=\"datadesc\">";
364 ReplaceSpecialChars(classFile, member->GetTitle());
365 } else classFile << "<td>";
366 classFile << "</td></tr>" << endl;
367 } // for members
368
369 if (prevEnumName.Length()) {
370 classFile << "<tr class=\"data";
371 if (prevIsInh)
372 classFile << "inh";
373 classFile << "\"><td class=\"datatype\">};</td><td></td><td></td></tr>" << endl;
374 }
375 classFile << endl << "</table></div>" << endl;
376 } // for access
377
378 classFile << "</div>" << endl; // datamembers
379 }
380
381 //______________________________________________________________________________
382 Bool_t TClassDocOutput::ClassDotCharts(std::ostream& out)
383 {
384 // This function builds the class charts for one class in GraphViz/Dot format,
385 // i.e. the inheritance diagram, the include dependencies, and the library
386 // dependency.
387 //
388 // Input: out - output file stream
389
390 if (!fHtml->HaveDot())
391 return kFALSE;
392
393 TString title(fCurrentClass->GetName());
394 NameSpace2FileName(title);
395
396 TString dir("inh");
397 gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
398 gSystem->MakeDirectory(dir);
399
400 dir = "inhmem";
401 gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
402 gSystem->MakeDirectory(dir);
403
404 dir = "incl";
405 gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
406 gSystem->MakeDirectory(dir);
407
408 dir = "lib";
409 gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
410 gSystem->MakeDirectory(dir);
411
412 TString filenameInh(title);
413 gSystem->PrependPathName("inh", filenameInh);
414 gSystem->PrependPathName(fHtml->GetOutputDir(), filenameInh);
415 filenameInh += "_Inh";
416 if (!CreateDotClassChartInh(filenameInh + ".dot") ||
417 !RunDot(filenameInh, &out))
418 return kFALSE;
419
420 TString filenameInhMem(title);
421 gSystem->PrependPathName("inhmem", filenameInhMem);
422 gSystem->PrependPathName(fHtml->GetOutputDir(), filenameInhMem);
423 filenameInhMem += "_InhMem";
424 if (CreateDotClassChartInhMem(filenameInhMem + ".dot"))
425 RunDot(filenameInhMem, &out);
426
427 TString filenameIncl(title);
428 gSystem->PrependPathName("incl", filenameIncl);
429 gSystem->PrependPathName(fHtml->GetOutputDir(), filenameIncl);
430 filenameIncl += "_Incl";
431 if (CreateDotClassChartIncl(filenameIncl + ".dot"))
432 RunDot(filenameIncl, &out);
433
434 TString filenameLib(title);
435 gSystem->PrependPathName("lib", filenameLib);
436 gSystem->PrependPathName(fHtml->GetOutputDir(), filenameLib);
437 filenameLib += "_Lib";
438 if (CreateDotClassChartLib(filenameLib + ".dot"))
439 RunDot(filenameLib, &out);
440
441 out << "<div class=\"tabs\">" << endl
442 << "<a id=\"img" << title << "_Inh\" class=\"tabsel\" href=\"inh/" << title << "_Inh.gif\" onclick=\"javascript:return SetImg('Charts','inh/" << title << "_Inh.gif');\">Inheritance</a>" << endl
443 << "<a id=\"img" << title << "_InhMem\" class=\"tab\" href=\"inhmem/" << title << "_InhMem.gif\" onclick=\"javascript:return SetImg('Charts','inhmem/" << title << "_InhMem.gif');\">Inherited Members</a>" << endl
444 << "<a id=\"img" << title << "_Incl\" class=\"tab\" href=\"incl/" << title << "_Incl.gif\" onclick=\"javascript:return SetImg('Charts','incl/" << title << "_Incl.gif');\">Includes</a>" << endl
445 << "<a id=\"img" << title << "_Lib\" class=\"tab\" href=\"lib/" << title << "_Lib.gif\" onclick=\"javascript:return SetImg('Charts','lib/" << title << "_Lib.gif');\">Libraries</a><br/>" << endl
446 << "</div><div class=\"classcharts\"><div class=\"classchartswidth\"></div>" << endl
447 << "<img id=\"Charts\" alt=\"Class Charts\" class=\"classcharts\" usemap=\"#Map" << title << "_Inh\" src=\"inh/" << title << "_Inh.gif\"/></div>" << endl;
448
449 return kTRUE;
450 }
451
452 //______________________________________________________________________________
453 void TClassDocOutput::ClassHtmlTree(std::ostream& out, TClass * classPtr,
454 ETraverse dir, int depth)
455 {
456 // This function builds the class tree for one class in HTML
457 // (inherited and succeeding classes, called recursively)
458 //
459 //
460 // Input: out - output file stream
461 // classPtr - pointer to the class
462 // dir - direction to traverse tree: up, down or both
463 //
464
465 if (dir == kBoth) {
466 out << "<!--INHERITANCE TREE-->" << endl;
467
468 // draw class tree into nested tables recursively
469 out << "<table><tr><td width=\"10%\"></td><td width=\"70%\">"
470 << "<a href=\"ClassHierarchy.html\">Inheritance Chart</a>:</td></tr>";
471 out << "<tr class=\"inhtree\"><td width=\"10%\"></td><td width=\"70%\">";
472
473 out << "<table class=\"inhtree\"><tr><td>" << endl;
474 out << "<table width=\"100%\" border=\"0\" ";
475 out << "cellpadding =\"0\" cellspacing=\"2\"><tr>" << endl;
476 } else {
477 out << "<table><tr>";
478 }
479
480 ////////////////////////////////////////////////////////
481 // Loop up to mother classes
482 if (dir == kUp || dir == kBoth) {
483
484 // make a loop on base classes
485 TBaseClass *inheritFrom;
486 TIter nextBase(classPtr->GetListOfBases());
487
488 UInt_t bgcolor=255-depth*8;
489 Bool_t first = kTRUE;
490 while ((inheritFrom = (TBaseClass *) nextBase())) {
491
492 if (first) {
493 out << "<td><table><tr>" << endl;
494 first = kFALSE;
495 } else
496 out << "</tr><tr>" << endl;
497 out << "<td bgcolor=\""
498 << Form("#%02x%02x%02x", bgcolor, bgcolor, bgcolor)
499 << "\" align=\"right\">" << endl;
500 // get a class
501 TClass *classInh = fHtml->GetClass((const char *) inheritFrom->GetName());
502 if (classInh)
503 ClassHtmlTree(out, classInh, kUp, depth+1);
504 else
505 out << "<tt>"
506 << (const char *) inheritFrom->GetName()
507 << "</tt>";
508 out << "</td>"<< endl;
509 }
510 if (!first) {
511 out << "</tr></table></td>" << endl; // put it in additional row in table
512 out << "<td>&larr;</td>";
513 }
514 }
515
516 out << "<td>" << endl; // put it in additional row in table
517 ////////////////////////////////////////////////////////
518 // Output Class Name
519
520 const char *className = classPtr->GetName();
521 TString htmlFile;
522 fHtml->GetHtmlFileName(classPtr, htmlFile);
523 TString anchor(className);
524 NameSpace2FileName(anchor);
525
526 if (dir == kUp) {
527 if (htmlFile) {
528 out << "<center><tt><a name=\"" << anchor;
529 out << "\" href=\"" << htmlFile << "\">";
530 ReplaceSpecialChars(out, className);
531 out << "</a></tt></center>" << endl;
532 } else
533 ReplaceSpecialChars(out, className);
534 }
535
536 if (dir == kBoth) {
537 if (htmlFile.Length()) {
538 out << "<center><big><b><tt><a name=\"" << anchor;
539 out << "\" href=\"" << htmlFile << "\">";
540 ReplaceSpecialChars(out, className);
541 out << "</a></tt></b></big></center>" << endl;
542 } else
543 ReplaceSpecialChars(out, className);
544 }
545
546 out << "</td>" << endl; // put it in additional row in table
547
548 ////////////////////////////////////////////////////////
549 // Loop down to child classes
550
551 if (dir == kDown || dir == kBoth) {
552
553 // 1. make a list of class names
554 // 2. use DescendHierarchy
555
556 out << "<td><table><tr>" << endl;
557 fHierarchyLines = 0;
558 DescendHierarchy(out,classPtr,10);
559
560 out << "</tr></table>";
561 if (dir==kBoth && fHierarchyLines>=10)
562 out << "</td><td align=\"left\">&nbsp;<a href=\"ClassHierarchy.html\">[more...]</a>";
563 out<<"</td>" << endl;
564
565 // free allocated memory
566 }
567
568 out << "</tr></table>" << endl;
569 if (dir == kBoth)
570 out << "</td></tr></table></td></tr></table>"<<endl;
571 }
572
573
574 //______________________________________________________________________________
575 void TClassDocOutput::ClassTree(TVirtualPad * psCanvas, Bool_t force)
576 {
577 // It makes a graphical class tree
578 //
579 //
580 // Input: psCanvas - pointer to the current canvas
581 // classPtr - pointer to the class
582 //
583
584 if (!psCanvas || !fCurrentClass)
585 return;
586
587 TString filename(fCurrentClass->GetName());
588 NameSpace2FileName(filename);
589
590 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
591
592
593 filename += "_Tree.pdf";
594
595 if (IsModified(fCurrentClass, kTree) || force) {
596 // TCanvas already prints pdf being saved
597 // Printf(fHtml->GetCounterFormat(), "", "", filename);
598 fCurrentClass->Draw("same");
599 Int_t saveErrorIgnoreLevel = gErrorIgnoreLevel;
600 gErrorIgnoreLevel = kWarning;
601 psCanvas->SaveAs(filename);
602 gErrorIgnoreLevel = saveErrorIgnoreLevel;
603 } else
604 Printf(fHtml->GetCounterFormat(), "-no change-", "", filename.Data());
605 }
606
607 //______________________________________________________________________________
608 Bool_t TClassDocOutput::CreateDotClassChartInh(const char* filename)
609 {
610 // Build the class tree for one class in GraphViz/Dot format
611 //
612 //
613 // Input: filename - output dot file incl. path
614
615 std::ofstream outdot(filename);
616 outdot << "strict digraph G {" << endl
617 << "rankdir=RL;" << endl
618 << "ranksep=2;" << endl
619 << "nodesep=0;" << endl
620 << "size=\"8,10\";" << endl
621 << "ratio=auto;" << endl
622 << "margin=0;" << endl
623 << "node [shape=plaintext,fontsize=40,width=4,height=0.75];" << endl
624 << "\"" << fCurrentClass->GetName() << "\" [shape=ellipse];" << endl;
625
626 std::stringstream ssDep;
627 std::list<TClass*> writeBasesFor;
628 writeBasesFor.push_back(fCurrentClass);
629 Bool_t haveBases = fCurrentClass->GetListOfBases() &&
630 fCurrentClass->GetListOfBases()->GetSize();
631 if (haveBases) {
632 outdot << "{" << endl;
633 while (!writeBasesFor.empty()) {
634 TClass* cl = writeBasesFor.front();
635 writeBasesFor.pop_front();
636 if (cl != fCurrentClass) {
637 outdot << " \"" << cl->GetName() << "\"";
638 const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
639 if (htmlFileName)
640 outdot << " [URL=\"" << htmlFileName << "\"]";
641 outdot << ";" << endl;
642 }
643 if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
644 ssDep << " \"" << cl->GetName() << "\" -> {";
645 TIter iBase(cl->GetListOfBases());
646 TBaseClass* base = 0;
647 while ((base = (TBaseClass*)iBase())) {
648 ssDep << " \"" << base->GetName() << "\";";
649 writeBasesFor.push_back(base->GetClassPointer());
650 }
651 ssDep << "}" << endl;
652 }
653 }
654 outdot << "}" << endl; // cluster
655 }
656
657 std::map<TClass*, Int_t> derivesFromMe;
658 std::map<TClass*, unsigned int> entriesPerDerived;
659 std::set<TClass*> wroteNode;
660 wroteNode.insert(fCurrentClass);
661 static const unsigned int maxClassesPerDerived = 20;
662 fHtml->GetDerivedClasses(fCurrentClass, derivesFromMe);
663 outdot << "{" << endl;
664 for (Int_t level = 1; kTRUE; ++level) {
665 Bool_t levelExists = kFALSE;
666 for (std::map<TClass*, Int_t>::iterator iDerived = derivesFromMe.begin();
667 iDerived != derivesFromMe.end(); ++iDerived) {
668 if (iDerived->second != level) continue;
669 levelExists = kTRUE;
670 TIter iBaseOfDerived(iDerived->first->GetListOfBases());
671 TBaseClass* baseDerived = 0;
672 Bool_t writeNode = kFALSE;
673 TClass* writeAndMoreFor = 0;
674 while ((baseDerived = (TBaseClass*) iBaseOfDerived())) {
675 TClass* clBaseDerived = baseDerived->GetClassPointer();
676 if (clBaseDerived->InheritsFrom(fCurrentClass)
677 && wroteNode.find(clBaseDerived) != wroteNode.end()) {
678 unsigned int& count = entriesPerDerived[clBaseDerived];
679 if (count < maxClassesPerDerived) {
680 writeNode = kTRUE;
681 ssDep << "\"" << iDerived->first->GetName() << "\" -> \""
682 << clBaseDerived->GetName() << "\";" << endl;
683 ++count;
684 } else if (count == maxClassesPerDerived) {
685 writeAndMoreFor = clBaseDerived;
686 ssDep << "\"...andmore" << clBaseDerived->GetName() << "\"-> \""
687 << clBaseDerived->GetName() << "\";" << endl;
688 ++count;
689 }
690 }
691 }
692
693 if (writeNode) {
694 wroteNode.insert(iDerived->first);
695 outdot << " \"" << iDerived->first->GetName() << "\"";
696 const char* htmlFileName = fHtml->GetHtmlFileName(iDerived->first->GetName());
697 if (htmlFileName)
698 outdot << " [URL=\"" << htmlFileName << "\"]";
699 outdot << ";" << endl;
700 } else if (writeAndMoreFor) {
701 outdot << " \"...andmore" << writeAndMoreFor->GetName()
702 << "\" [label=\"...and more\",fontname=\"Times-Italic\",fillcolor=lightgrey,style=filled];" << endl;
703 }
704 }
705 if (!levelExists) break;
706 }
707 outdot << "}" << endl; // cluster
708
709 outdot << ssDep.str();
710
711 outdot << "}" << endl; // digraph
712
713 return kTRUE;
714 }
715
716 //______________________________________________________________________________
717 Bool_t TClassDocOutput::CreateDotClassChartInhMem(const char* filename) {
718 // Build the class tree of inherited members for one class in GraphViz/Dot format
719 //
720 // Input: filename - output dot file incl. path
721
722 std::ofstream outdot(filename);
723 outdot << "strict digraph G {" << endl
724 << "ratio=auto;" << endl
725 << "rankdir=RL;" << endl
726 << "compound=true;" << endl
727 << "constraint=false;" << endl
728 << "ranksep=0.1;" << endl
729 << "nodesep=0;" << endl
730 << "margin=0;" << endl;
731 outdot << " node [style=filled,width=0.7,height=0.15,fixedsize=true,shape=plaintext,fontsize=10];" << endl;
732
733 std::stringstream ssDep;
734 const int numColumns = 3;
735
736 std::list<TClass*> writeBasesFor;
737 writeBasesFor.push_back(fCurrentClass);
738 while (!writeBasesFor.empty()) {
739 TClass* cl = writeBasesFor.front();
740 writeBasesFor.pop_front();
741
742 const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
743
744 outdot << "subgraph \"cluster" << cl->GetName() << "\" {" << endl
745 << " color=lightgray;" << endl
746 << " label=\"" << cl->GetName() << "\";" << endl;
747 if (cl != fCurrentClass && htmlFileName)
748 outdot << " URL=\"" << htmlFileName << "\"" << endl;
749
750 //Bool_t haveMembers = (cl->GetListOfDataMembers() && cl->GetListOfDataMembers()->GetSize());
751 Bool_t haveFuncs = cl->GetListOfMethods() && cl->GetListOfMethods()->GetSize();
752
753 // DATA MEMBERS
754 {
755 // make sure each member name is listed only once
756 // that's useless for data members, but symmetric to what we have for methods
757 std::map<std::string, TDataMember*> dmMap;
758
759 {
760 TIter iDM(cl->GetListOfDataMembers());
761 TDataMember* dm = 0;
762 while ((dm = (TDataMember*) iDM()))
763 dmMap[dm->GetName()] = dm;
764 }
765
766 outdot << "subgraph \"clusterData0" << cl->GetName() << "\" {" << endl
767 << " color=white;" << endl
768 << " label=\"\";" << endl
769 << " \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
770 TString prevColumnNode;
771 Int_t pos = dmMap.size();
772 Int_t column = 0;
773 Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
774 for (std::map<std::string, TDataMember*>::iterator iDM = dmMap.begin();
775 iDM != dmMap.end(); ++iDM, --pos) {
776 TDataMember* dm = iDM->second;
777 TString nodeName(cl->GetName());
778 nodeName += "::";
779 nodeName += dm->GetName();
780 if (iDM == dmMap.begin())
781 prevColumnNode = nodeName;
782
783 outdot << "\"" << nodeName << "\" [label=\""
784 << dm->GetName() << "\"";
785 if (dm->Property() & kIsPrivate)
786 outdot << ",color=\"#FFCCCC\"";
787 else if (dm->Property() & kIsProtected)
788 outdot << ",color=\"#FFFF77\"";
789 else
790 outdot << ",color=\"#CCFFCC\"";
791 outdot << "];" << endl;
792 if (pos % newColumnEvery == 1) {
793 ++column;
794 outdot << "};" << endl // end dataR
795 << "subgraph \"clusterData" << column << cl->GetName() << "\" {" << endl
796 << " color=white;" << endl
797 << " label=\"\";" << endl
798 << " \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
799 } else if (iDM != dmMap.begin() && pos % newColumnEvery == 0) {
800 ssDep << "\"" << prevColumnNode
801 << "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
802 prevColumnNode = nodeName;
803 }
804 }
805
806 while (column < numColumns - 1) {
807 ++column;
808 outdot << " \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
809 }
810
811 outdot << "};" << endl; // subgraph dataL/R
812 } // DATA MEMBERS
813
814 // FUNCTION MEMBERS
815 if (haveFuncs) {
816 // make sure each member name is listed only once
817 std::map<std::string, TMethod*> methMap;
818
819 {
820 TIter iMeth(cl->GetListOfMethods());
821 TMethod* meth = 0;
822 while ((meth = (TMethod*) iMeth()))
823 methMap[meth->GetName()] = meth;
824 }
825
826 outdot << "subgraph \"clusterFunc0" << cl->GetName() << "\" {" << endl
827 << " color=white;" << endl
828 << " label=\"\";" << endl
829 << " \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
830
831 TString prevColumnNodeFunc;
832 Int_t pos = methMap.size();
833 Int_t column = 0;
834 Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
835 for (std::map<std::string, TMethod*>::iterator iMeth = methMap.begin();
836 iMeth != methMap.end(); ++iMeth, --pos) {
837 TMethod* meth = iMeth->second;
838 TString nodeName(cl->GetName());
839 nodeName += "::";
840 nodeName += meth->GetName();
841 if (iMeth == methMap.begin())
842 prevColumnNodeFunc = nodeName;
843
844 outdot << "\"" << nodeName << "\" [label=\"" << meth->GetName() << "\"";
845 if (cl != fCurrentClass &&
846 fCurrentClass->GetMethodAny(meth->GetName()))
847 outdot << ",color=\"#777777\"";
848 else if (meth->Property() & kIsPrivate)
849 outdot << ",color=\"#FFCCCC\"";
850 else if (meth->Property() & kIsProtected)
851 outdot << ",color=\"#FFFF77\"";
852 else
853 outdot << ",color=\"#CCFFCC\"";
854 outdot << "];" << endl;
855 if (pos % newColumnEvery == 1) {
856 ++column;
857 outdot << "};" << endl // end funcR
858 << "subgraph \"clusterFunc" << column << cl->GetName() << "\" {" << endl
859 << " color=white;" << endl
860 << " label=\"\";" << endl;
861 } else if (iMeth != methMap.begin() && pos % newColumnEvery == 0) {
862 ssDep << "\"" << prevColumnNodeFunc
863 << "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
864 prevColumnNodeFunc = nodeName;
865 }
866 }
867 outdot << "};" << endl; // subgraph funcL/R
868 }
869
870 outdot << "}" << endl; // cluster class
871
872 for (Int_t pos = 0; pos < numColumns - 1; ++pos)
873 ssDep << "\"clusterNode" << pos << cl->GetName() << "\" -> \"clusterNode" << pos + 1 << cl->GetName() << "\" [style=invis];" << endl;
874
875 if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
876 TIter iBase(cl->GetListOfBases());
877 TBaseClass* base = 0;
878 while ((base = (TBaseClass*)iBase())) {
879 ssDep << " \"clusterNode" << numColumns - 1 << cl->GetName() << "\" -> "
880 << " \"clusterNode0" << base->GetName() << "\" [ltail=\"cluster" << cl->GetName()
881 << "\",lhead=\"cluster" << base->GetName() << "\"";
882 if (base != cl->GetListOfBases()->First())
883 ssDep << ",weight=0";
884 ssDep << "];" << endl;
885 writeBasesFor.push_back(base->GetClassPointer());
886 }
887 }
888 }
889
890 outdot << ssDep.str();
891
892 outdot << "}" << endl; // digraph
893
894 return kTRUE;
895 }
896
897 //______________________________________________________________________________
898 Bool_t TClassDocOutput::CreateDotClassChartIncl(const char* filename) {
899 // Build the include dependency graph for one class in
900 // GraphViz/Dot format
901 //
902 // Input: filename - output dot file incl. path
903
904 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
905
906 std::map<std::string, std::string> filesToParse;
907 std::list<std::string> listFilesToParse;
908 TString declFileName;
909 TString implFileName;
910 fHtml->GetImplFileName(fCurrentClass, kFALSE, implFileName);
911 if (fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFileName)) {
912 TString real;
913 if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, real)) {
914 filesToParse[declFileName.Data()] = real.Data();
915 listFilesToParse.push_back(declFileName.Data());
916 }
917 }
918 /* do it only for the header
919 if (implFileName && strlen(implFileName)) {
920 char* real = gSystem->Which(fHtml->GetInputPath(), implFileName, kReadPermission);
921 if (real) {
922 filesToParse[implFileName] = real;
923 listFilesToParse.push_back(implFileName);
924 delete real;
925 }
926 }
927 */
928
929 std::ofstream outdot(filename);
930 outdot << "strict digraph G {" << endl
931 << "ratio=compress;" << endl
932 << "rankdir=TB;" << endl
933 << "concentrate=true;" << endl
934 << "ranksep=0;" << endl
935 << "nodesep=0;" << endl
936 << "size=\"8,10\";" << endl
937 << "node [fontsize=20,shape=plaintext];" << endl;
938
939 for (std::list<std::string>::iterator iFile = listFilesToParse.begin();
940 iFile != listFilesToParse.end(); ++iFile) {
941 ifstream in(filesToParse[*iFile].c_str());
942 std::string line;
943 while (in && !in.eof()) {
944 std::getline(in, line);
945 size_t pos = 0;
946 while (line[pos] == ' ' || line[pos] == '\t') ++pos;
947 if (line[pos] != '#') continue;
948 ++pos;
949 while (line[pos] == ' ' || line[pos] == '\t') ++pos;
950 if (line.compare(pos, 8, "include ") != 0) continue;
951 pos += 8;
952 while (line[pos] == ' ' || line[pos] == '\t') ++pos;
953 if (line[pos] != '"' && line[pos] != '<')
954 continue;
955 char delim = line[pos];
956 if (delim == '<') delim = '>';
957 ++pos;
958 line.erase(0, pos);
959 pos = 0;
960 pos = line.find(delim);
961 if (pos == std::string::npos) continue;
962 line.erase(pos);
963 if (filesToParse.find(line) == filesToParse.end()) {
964 TString sysfilename;
965 if (!GetHtml()->GetPathDefinition().GetFileNameFromInclude(line.c_str(), sysfilename))
966 continue;
967 listFilesToParse.push_back(line);
968 filesToParse[line] = sysfilename;
969 if (*iFile == implFileName.Data() || *iFile == declFileName.Data())
970 outdot << "\"" << *iFile << "\" [style=filled,fillcolor=lightgray];" << endl;
971 }
972 outdot << "\"" << *iFile << "\" -> \"" << line << "\";" << endl;
973 }
974 }
975
976 outdot << "}" << endl; // digraph
977
978 return kTRUE;
979 }
980
981 //______________________________________________________________________________
982 Bool_t TClassDocOutput::CreateDotClassChartLib(const char* filename) {
983 // Build the library dependency graph for one class in
984 // GraphViz/Dot format
985 //
986 // Input: filename - output dot file incl. path
987
988 std::ofstream outdot(filename);
989 outdot << "strict digraph G {" << endl
990 << "ratio=auto;" << endl
991 << "rankdir=RL;" << endl
992 << "compound=true;" << endl
993 << "constraint=false;" << endl
994 << "ranksep=0.7;" << endl
995 << "nodesep=0.3;" << endl
996 << "size=\"8,8\";" << endl
997 << "ratio=compress;" << endl;
998
999 TString libs(fCurrentClass->GetSharedLibs());
1000 outdot << "\"All Libraries\" [URL=\"LibraryDependencies.html\",shape=box,rank=max,fillcolor=lightgray,style=filled];" << endl;
1001
1002 if (libs.Length()) {
1003 TString firstLib(libs);
1004 Ssiz_t end = firstLib.Index(' ');
1005 if (end != kNPOS) {
1006 firstLib.Remove(end, firstLib.Length());
1007 libs.Remove(0, end + 1);
1008 } else libs = "";
1009
1010 {
1011 Ssiz_t posExt = firstLib.First(".");
1012 if (posExt != kNPOS)
1013 firstLib.Remove(posExt, firstLib.Length());
1014 }
1015
1016 outdot << "\"All Libraries\" -> \"" << firstLib << "\" [style=invis];" << endl;
1017 outdot << "\"" << firstLib << "\" -> {" << endl;
1018
1019 if (firstLib != "libCore")
1020 libs += " libCore";
1021 if (firstLib != "libCint")
1022 libs += " libCint";
1023 TString thisLib;
1024 for (Ssiz_t pos = 0; pos < libs.Length(); ++pos)
1025 if (libs[pos] != ' ')
1026 thisLib += libs[pos];
1027 else if (thisLib.Length()) {
1028 Ssiz_t posExt = thisLib.First(".");
1029 if (posExt != kNPOS)
1030 thisLib.Remove(posExt, thisLib.Length());
1031 outdot << " \"" << thisLib << "\";";
1032 thisLib = "";
1033 }
1034 // remaining lib
1035 if (thisLib.Length()) {
1036 Ssiz_t posExt = thisLib.First(".");
1037 if (posExt != kNPOS)
1038 thisLib.Remove(posExt, thisLib.Length());
1039 outdot << " \"" << thisLib << "\";";
1040 thisLib = "";
1041 }
1042 outdot << "}" << endl; // dependencies
1043 } else
1044 outdot << "\"No rlibmap information avaliable.\"" << endl;
1045
1046 outdot << "}" << endl; // digraph
1047
1048 return kTRUE;
1049 }
1050
1051 //______________________________________________________________________________
1052 void TClassDocOutput::CreateClassHierarchy(std::ostream& out, const char* docFileName)
1053 {
1054 // Create the hierarchical class list part for the current class's
1055 // base classes. docFileName contains doc for fCurrentClass.
1056 //
1057
1058 // Find basic base classes
1059 TList *bases = fCurrentClass->GetListOfBases();
1060 if (!bases || bases->IsEmpty())
1061 return;
1062
1063 out << "<hr />" << endl;
1064
1065 out << "<table><tr><td><ul><li><tt>";
1066 if (docFileName) {
1067 out << "<a name=\"" << fCurrentClass->GetName() << "\" href=\""
1068 << docFileName << "\">";
1069 ReplaceSpecialChars(out, fCurrentClass->GetName());
1070 out << "</a>";
1071 } else {
1072 ReplaceSpecialChars(out, fCurrentClass->GetName());
1073 }
1074
1075 // find derived classes
1076 out << "</tt></li></ul></td>";
1077 fHierarchyLines = 0;
1078 DescendHierarchy(out, fCurrentClass);
1079
1080 out << "</tr></table>" << endl;
1081 }
1082
1083 //______________________________________________________________________________
1084 Bool_t TClassDocOutput::CreateHierarchyDot()
1085 {
1086 // Create a hierarchical class list
1087 // The algorithm descends from the base classes and branches into
1088 // all derived classes. Mixing classes are displayed several times.
1089 //
1090 //
1091
1092 const char* title = "ClassHierarchy";
1093 TString filename(title);
1094 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
1095
1096 // open out file
1097 std::ofstream dotout(filename + ".dot");
1098
1099 if (!dotout.good()) {
1100 Error("CreateHierarchy", "Can't open file '%s.dot' !",
1101 filename.Data());
1102 return kFALSE;
1103 }
1104
1105 dotout << "digraph G {" << endl
1106 << "ratio=auto;" << endl
1107 << "rankdir=RL;" << endl;
1108
1109 // loop on all classes
1110 TClassDocInfo* cdi = 0;
1111 TIter iClass(fHtml->GetListOfClasses());
1112 while ((cdi = (TClassDocInfo*)iClass())) {
1113
1114 TDictionary *dict = cdi->GetClass();
1115 TClass *cl = dynamic_cast<TClass*>(dict);
1116 if (cl == 0) {
1117 if (!dict)
1118 Warning("THtml::CreateHierarchy", "skipping class %s\n", cdi->GetName());
1119 continue;
1120 }
1121
1122 // Find immediate base classes
1123 TList *bases = cl->GetListOfBases();
1124 if (bases && !bases->IsEmpty()) {
1125 dotout << "\"" << cdi->GetName() << "\" -> { ";
1126 TIter iBase(bases);
1127 TBaseClass* base = 0;
1128 while ((base = (TBaseClass*) iBase())) {
1129 // write out current class
1130 if (base != bases->First())
1131 dotout << "; ";
1132 dotout << "\"" << base->GetName() << "\"";
1133 }
1134 dotout << "};" << endl;
1135 } else
1136 // write out current class - no bases
1137 dotout << "\"" << cdi->GetName() << "\";" << endl;
1138
1139 }
1140
1141 dotout << "}";
1142 dotout.close();
1143
1144 std::ofstream out(filename + ".html");
1145 if (!out.good()) {
1146 Error("CreateHierarchy", "Can't open file '%s.html' !",
1147 filename.Data());
1148 return kFALSE;
1149 }
1150
1151 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), (filename + ".html").Data());
1152 // write out header
1153 WriteHtmlHeader(out, "Class Hierarchy");
1154 out << "<h1>Class Hierarchy</h1>" << endl;
1155
1156 WriteSearch(out);
1157
1158 RunDot(filename, &out);
1159
1160 out << "<img usemap=\"#Map" << title << "\" src=\"" << title << ".gif\"/>" << endl;
1161 // write out footer
1162 WriteHtmlFooter(out);
1163 return kTRUE;
1164 }
1165
1166 //______________________________________________________________________________
1167 void TClassDocOutput::CreateSourceOutputStream(std::ostream& out, const char* extension,
1168 TString& sourceHtmlFileName)
1169 {
1170 // Open a Class.cxx.html file, where Class is defined by classPtr, and .cxx.html by extension
1171 // It's created in fHtml->GetOutputDir()/src. If successful, the HTML header is written to out.
1172
1173 TString sourceHtmlDir("src");
1174 gSystem->PrependPathName(fHtml->GetOutputDir(), sourceHtmlDir);
1175 // create directory if necessary
1176 {
1177 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1178
1179 if (gSystem->AccessPathName(sourceHtmlDir))
1180 gSystem->MakeDirectory(sourceHtmlDir);
1181 }
1182 sourceHtmlFileName = fCurrentClass->GetName();
1183 NameSpace2FileName(sourceHtmlFileName);
1184 gSystem->PrependPathName(sourceHtmlDir, sourceHtmlFileName);
1185 sourceHtmlFileName += extension;
1186 dynamic_cast<std::ofstream&>(out).open(sourceHtmlFileName);
1187 if (!out) {
1188 Warning("LocateMethodsInSource", "Can't open beautified source file '%s' for writing!",
1189 sourceHtmlFileName.Data());
1190 sourceHtmlFileName.Remove(0);
1191 return;
1192 }
1193
1194 // write a HTML header
1195 TString title(fCurrentClass->GetName());
1196 title += " - source file";
1197 WriteHtmlHeader(out, title, "../", fCurrentClass);
1198 out << "<pre class=\"code\">" << std::endl;
1199 }
1200
1201 //______________________________________________________________________________
1202 void TClassDocOutput::DescendHierarchy(std::ostream& out, TClass* basePtr, Int_t maxLines, Int_t depth)
1203 {
1204 // Descend hierarchy recursively
1205 // loop over all classes and look for classes with base class basePtr
1206
1207 if (maxLines)
1208 if (fHierarchyLines >= maxLines) {
1209 out << "<td></td>" << endl;
1210 return;
1211 }
1212
1213 UInt_t numClasses = 0;
1214
1215 TClassDocInfo* cdi = 0;
1216 TIter iClass(fHtml->GetListOfClasses());
1217 while ((cdi = (TClassDocInfo*)iClass()) && (!maxLines || fHierarchyLines<maxLines)) {
1218
1219 TClass *classPtr = dynamic_cast<TClass*>(cdi->GetClass());
1220 if (!classPtr) continue;
1221
1222 // find base classes with same name as basePtr
1223 TList* bases=classPtr->GetListOfBases();
1224 if (!bases) continue;
1225
1226 TBaseClass *inheritFrom=(TBaseClass*)bases->FindObject(basePtr->GetName());
1227 if (!inheritFrom) continue;
1228
1229 if (!numClasses)
1230 out << "<td>&larr;</td><td><table><tr>" << endl;
1231 else
1232 out << "</tr><tr>"<<endl;
1233 fHierarchyLines++;
1234 numClasses++;
1235 UInt_t bgcolor=255-depth*8;
1236 out << "<td bgcolor=\""
1237 << Form("#%02x%02x%02x", bgcolor, bgcolor, bgcolor)
1238 << "\">";
1239 out << "<table><tr><td>" << endl;
1240
1241 TString htmlFile(cdi->GetHtmlFileName());
1242 if (htmlFile.Length()) {
1243 out << "<center><tt><a name=\"" << cdi->GetName() << "\" href=\""
1244 << htmlFile << "\">";
1245 ReplaceSpecialChars(out, cdi->GetName());
1246 out << "</a></tt></center>";
1247 } else {
1248 ReplaceSpecialChars(out, cdi->GetName());
1249 }
1250 // write title
1251 // commented out for now because it reduces overview
1252 /*
1253 len = strlen(classNames[i]);
1254 for (Int_t w = 0; w < (maxLen - len + 2); w++)
1255 out << ".";
1256 out << " ";
1257
1258 out << "<a name=\"Title:";
1259 out << classPtr->GetName();
1260 out << "\">";
1261 ReplaceSpecialChars(out, classPtr->GetTitle());
1262 out << "</a></tt>" << endl;
1263 */
1264
1265 out << "</td>" << endl;
1266 DescendHierarchy(out,classPtr,maxLines, depth+1);
1267 out << "</tr></table></td>" << endl;
1268
1269 } // loop over all classes
1270 if (numClasses)
1271 out << "</tr></table></td>" << endl;
1272 else
1273 out << "<td></td>" << endl;
1274 }
1275
1276 //______________________________________________________________________________
1277 void TClassDocOutput::MakeTree(Bool_t force /*= kFALSE*/)
1278 {
1279 // Create an output file with a graphical representation of the class
1280 // inheritance. If force, replace existing output file.
1281 // This routine does nothing if fHtml->HaveDot() is true - use
1282 // ClassDotCharts() instead!
1283
1284 // class tree only if no dot, otherwise it's part of charts
1285 if (!fCurrentClass || fHtml->HaveDot())
1286 return;
1287
1288 TString htmlFile;
1289 fHtml->GetHtmlFileName(fCurrentClass, htmlFile);
1290 if (htmlFile.Length()
1291 && (htmlFile.BeginsWith("http://")
1292 || htmlFile.BeginsWith("https://")
1293 || gSystem->IsAbsoluteFileName(htmlFile))
1294 ) {
1295 htmlFile.Remove(0);
1296 }
1297
1298 if (!htmlFile.Length()) {
1299 TString what(fCurrentClass->GetName());
1300 what += " (source not found)";
1301 Printf(fHtml->GetCounterFormat(), "-skipped-", "", what.Data());
1302 return;
1303 }
1304
1305 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1306
1307 // Create a canvas without linking against GUI libs
1308 Bool_t wasBatch = gROOT->IsBatch();
1309 if (!wasBatch)
1310 gROOT->SetBatch();
1311 TVirtualPad *psCanvas = (TVirtualPad*)gROOT->ProcessLineFast("new TCanvas(\"R__THtml\",\"psCanvas\",0,0,1000,1200);");
1312 if (!wasBatch)
1313 gROOT->SetBatch(kFALSE);
1314
1315 if (!psCanvas) {
1316 Error("MakeTree", "Cannot create a TCanvas!");
1317 return;
1318 }
1319
1320 // make a class tree
1321 ClassTree(psCanvas, force);
1322
1323 psCanvas->Close();
1324 delete psCanvas;
1325 }
1326
1327 //______________________________________________________________________________
1328 void TClassDocOutput::WriteClassDescription(std::ostream& out, const TString& description)
1329 {
1330 // Called by TDocParser::LocateMethods(), this hook writes out the class description
1331 // found by TDocParser. It's even called if none is found, i.e. if the first method
1332 // has occurred before a class description is found, so missing class descriptions
1333 // can be handled.
1334 // For HTML, its creates the description block, the list of functions and data
1335 // members, and the inheritance tree or, if Graphviz's dot is found, the class charts.
1336
1337 // Class Description Title
1338 out << "<div class=\"dropshadow\"><div class=\"withshadow\">";
1339 TString anchor(fCurrentClass->GetName());
1340 NameSpace2FileName(anchor);
1341 out << "<h1><a name=\"" << anchor;
1342 out << ":description\"></a>";
1343
1344 if (fHtml->IsNamespace(fCurrentClass))
1345 out << "namespace ";
1346 else
1347 out << "class ";
1348 ReplaceSpecialChars(out, fCurrentClass->GetName());
1349
1350
1351 // make a loop on base classes
1352 Bool_t first = kTRUE;
1353 TBaseClass *inheritFrom;
1354 TIter nextBase(fCurrentClass->GetListOfBases());
1355
1356 while ((inheritFrom = (TBaseClass *) nextBase())) {
1357 if (first) {
1358 out << ": ";
1359 first = kFALSE;
1360 } else
1361 out << ", ";
1362 Long_t property = inheritFrom->Property();
1363 if (property & kIsPrivate)
1364 out << "private ";
1365 else if (property & kIsProtected)
1366 out << "protected ";
1367 else
1368 out << "public ";
1369
1370 // get a class
1371 TClass *classInh = fHtml->GetClass(inheritFrom->GetName());
1372
1373 TString htmlFile;
1374 fHtml->GetHtmlFileName(classInh, htmlFile);
1375
1376 if (htmlFile.Length()) {
1377 // make a link to the base class
1378 out << "<a href=\"" << htmlFile << "\">";
1379 ReplaceSpecialChars(out, inheritFrom->GetName());
1380 out << "</a>";
1381 } else
1382 ReplaceSpecialChars(out, inheritFrom->GetName());
1383 }
1384 out << "</h1>" << endl;
1385
1386 out << "<div class=\"classdescr\">" << endl;
1387
1388 if (description.Length())
1389 out << "<pre>" << description << "</pre>";
1390
1391 // typedefs pointing to this class:
1392 if (fCurrentClassesTypedefs && !fCurrentClassesTypedefs->IsEmpty()) {
1393 out << "<h4>This class is also known as (typedefs to this class)</h4>";
1394 TIter iTD(fCurrentClassesTypedefs);
1395 bool firsttd = true;
1396 TDataType* dt = 0;
1397 while ((dt = (TDataType*) iTD())) {
1398 if (!firsttd)
1399 out << ", ";
1400 else firsttd = false;
1401 fParser->DecorateKeywords(out, dt->GetName());
1402 }
1403 }
1404
1405 out << "</div>" << std::endl
1406 << "</div></div>" << std::endl;
1407
1408 ListFunctions(out);
1409 ListDataMembers(out);
1410
1411 // create dot class charts or an html inheritance tree
1412 out << "<h2><a id=\"" << anchor
1413 << ":Class_Charts\"></a>Class Charts</h2>" << endl;
1414 if (!fHtml->IsNamespace(fCurrentClass))
1415 if (!ClassDotCharts(out))
1416 ClassHtmlTree(out, fCurrentClass);
1417
1418 // header for the following function docs:
1419 out << "<h2>Function documentation</h2>" << endl;
1420 }
1421
1422
1423 //______________________________________________________________________________
1424 void TClassDocOutput::WriteClassDocHeader(std::ostream& classFile)
1425 {
1426 // Write out the introduction of a class description (shortcuts and links)
1427
1428 classFile << "<a name=\"TopOfPage\"></a>" << endl;
1429
1430
1431 // show box with lib, include
1432 // needs to go first to allow title on the left
1433 TString sTitle(fCurrentClass->GetName());
1434 ReplaceSpecialChars(sTitle);
1435 if (fHtml->IsNamespace(fCurrentClass))
1436 sTitle.Prepend("namespace ");
1437 else
1438 sTitle.Prepend("class ");
1439
1440 TString sInclude;
1441 TString sLib;
1442 const char* lib=fCurrentClass->GetSharedLibs();
1443 GetHtml()->GetPathDefinition().GetIncludeAs(fCurrentClass, sInclude);
1444 if (lib) {
1445 char* libDup=StrDup(lib);
1446 char* libDupSpace=strchr(libDup,' ');
1447 if (libDupSpace) *libDupSpace=0;
1448 char* libDupEnd=libDup+strlen(libDup);
1449 while (libDupEnd!=libDup)
1450 if (*(--libDupEnd)=='.') {
1451 *libDupEnd=0;
1452 break;
1453 }
1454 sLib = libDup;
1455 delete[] libDup;
1456 }
1457 classFile << "<script type=\"text/javascript\">WriteFollowPageBox('"
1458 << sTitle << "','" << sLib << "','" << sInclude << "');</script>" << endl;
1459
1460 TString modulename;
1461 fHtml->GetModuleNameForClass(modulename, fCurrentClass);
1462 TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
1463 WriteTopLinks(classFile, module, fCurrentClass->GetName());
1464
1465 classFile << "<div class=\"descrhead\">" << endl
1466 << "<span class=\"descrtitle\">Source:</span>" << endl;
1467
1468 // make a link to the '.cxx' file
1469 TString classFileName(fCurrentClass->GetName());
1470 NameSpace2FileName(classFileName);
1471
1472 TString headerFileName;
1473 fHtml->GetDeclFileName(fCurrentClass, kFALSE, headerFileName);
1474 TString sourceFileName;
1475 fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
1476 if (headerFileName.Length())
1477 classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
1478 << ".h.html\">header file</a>" << endl;
1479
1480 if (sourceFileName.Length())
1481 classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
1482 << ".cxx.html\">source file</a>" << endl;
1483
1484 if (!fHtml->IsNamespace(fCurrentClass) && !fHtml->HaveDot()) {
1485 // make a link to the inheritance tree (postscript)
1486 classFile << "<a class=\"descrheadentry\" href=\"" << classFileName << "_Tree.pdf\"";
1487 classFile << ">inheritance tree (.pdf)</a> ";
1488 }
1489
1490 const TString& viewCVSLink = GetHtml()->GetViewCVS();
1491 Bool_t mustReplace = viewCVSLink.Contains("%f");
1492 if (viewCVSLink.Length()) {
1493 if (headerFileName.Length()) {
1494 TString link(viewCVSLink);
1495 TString sHeader(headerFileName);
1496 if (GetHtml()->GetProductName() && !strcmp(GetHtml()->GetProductName(), "ROOT")
1497 && sHeader.BeginsWith("include")) {
1498 sHeader.Remove(0,7);
1499 if (sourceFileName && strstr(sourceFileName, "src")) {
1500 TString src(sourceFileName);
1501 src.Remove(src.Index("src"), src.Length());
1502 src += "inc";
1503 sHeader.Prepend(src);
1504 } else {
1505 TString src(fCurrentClass->GetSharedLibs());
1506 Ssiz_t posEndLib = src.Index(' ');
1507 if (posEndLib != kNPOS)
1508 src.Remove(posEndLib, src.Length());
1509 if (src.BeginsWith("lib"))
1510 src.Remove(0, 3);
1511 posEndLib = src.Index('.');
1512 if (posEndLib != kNPOS)
1513 src.Remove(posEndLib, src.Length());
1514 src.ToLower();
1515 src += "/inc";
1516 sHeader.Prepend(src);
1517 }
1518 if (sHeader.BeginsWith("tmva/inc/TMVA"))
1519 sHeader.Remove(8, 5);
1520 }
1521 if (mustReplace) link.ReplaceAll("%f", sHeader);
1522 else link += sHeader;
1523 classFile << "<a class=\"descrheadentry\" href=\"" << link << "\">viewVC header</a> ";
1524 }
1525 if (sourceFileName.Length()) {
1526 TString link(viewCVSLink);
1527 if (mustReplace) link.ReplaceAll("%f", sourceFileName);
1528 else link += sourceFileName;
1529 classFile << "<a class=\"descrheadentry\" href=\"" << link << "\">viewVC source</a> ";
1530 }
1531 }
1532
1533 TString currClassNameMangled(fCurrentClass->GetName());
1534 NameSpace2FileName(currClassNameMangled);
1535
1536 TString wikiLink = GetHtml()->GetWikiURL();
1537 if (wikiLink.Length()) {
1538 if (wikiLink.Contains("%c")) wikiLink.ReplaceAll("%c", currClassNameMangled);
1539 else wikiLink += currClassNameMangled;
1540 classFile << "<a class=\"descrheadentry\" href=\"" << wikiLink << "\">wiki</a> ";
1541 }
1542
1543 classFile << endl << "</div>" << endl;
1544
1545 classFile << "<div class=\"descrhead\">" << endl
1546 << "<span class=\"descrtitle\">Sections:</span>" << endl
1547 << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled;
1548 if (fHtml->IsNamespace(fCurrentClass))
1549 classFile << ":description\">namespace description</a> ";
1550 else
1551 classFile << ":description\">class description</a> ";
1552 classFile << endl
1553 << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Function_Members\">function members</a>" << endl
1554 << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Data_Members\">data members</a>" << endl
1555 << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Class_Charts\">class charts</a>" << endl
1556 << "</div>" << endl
1557 << "</div>" << endl;
1558 }
1559
1560
1561 //______________________________________________________________________________
1562 void TClassDocOutput::WriteMethod(std::ostream& out, TString& ret,
1563 TString& name, TString& params,
1564 const char* filename, TString& anchor,
1565 TString& comment, TString& codeOneLiner,
1566 TMethod* guessedMethod)
1567 {
1568 // Write method name with return type ret and parameters param to out.
1569 // Build a link using file and anchor. Cooment it with comment, and
1570 // show the code codeOneLiner (set if the func consists of only one line
1571 // of code, immediately surrounded by "{","}"). Also updates fMethodNames's
1572 // count of method names.
1573
1574 fParser->DecorateKeywords(ret);
1575 out << "<div class=\"funcdoc\"><span class=\"funcname\">"
1576 << ret << " <a class=\"funcname\" name=\"";
1577 TString mangled(fCurrentClass->GetName());
1578 NameSpace2FileName(mangled);
1579 out << mangled << ":";
1580 mangled = name;
1581 NameSpace2FileName(mangled);
1582 out << mangled << "\" href=\"src/" << filename;
1583 if (anchor.Length())
1584 out << "#" << anchor;
1585 out << "\">";
1586 ReplaceSpecialChars(out, name);
1587 out << "</a>";
1588 if (guessedMethod) {
1589 out << "(";
1590 TMethodArg* arg;
1591 TIter iParam(guessedMethod->GetListOfMethodArgs());
1592 Bool_t first = kTRUE;
1593 while ((arg = (TMethodArg*) iParam())) {
1594 if (!first) out << ", ";
1595 else first = kFALSE;
1596 TString paramGuessed(arg->GetFullTypeName());
1597 paramGuessed += " ";
1598 paramGuessed += arg->GetName();
1599 if (arg->GetDefault() && strlen(arg->GetDefault())) {
1600 paramGuessed += " = ";
1601 paramGuessed += arg->GetDefault();
1602 }
1603 fParser->DecorateKeywords(paramGuessed);
1604 out << paramGuessed;
1605 }
1606 out << ")";
1607 if (guessedMethod->Property() & kIsMethConst)
1608 out << " const";
1609 } else {
1610 fParser->DecorateKeywords(params);
1611 out << params;
1612 }
1613 out << "</span><br />" << std::endl;
1614
1615 if (comment.Length())
1616 out << "<div class=\"funccomm\"><pre>" << comment << "</pre></div>" << std::endl;
1617
1618 if (codeOneLiner.Length()) {
1619 out << std::endl << "<div class=\"code\"><code class=\"inlinecode\">"
1620 << codeOneLiner << "</code></div>" << std::endl
1621 << "<div style=\"clear:both;\"></div>" << std::endl;
1622 codeOneLiner.Remove(0);
1623 }
1624 out << "</div>" << std::endl;
1625 }
1626
1627
1628