Doxygen
Loading...
Searching...
No Matches
diagram.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <algorithm>
19
20#include "diagram.h"
21#include "image.h"
22#include "classdef.h"
23#include "config.h"
24#include "message.h"
25#include "util.h"
26#include "doxygen.h"
27#include "portable.h"
28#include "indexlist.h"
29#include "classlist.h"
30#include "textstream.h"
31#include "growbuf.h"
32#include "dir.h"
33
34//-----------------------------------------------------------------------------
35
36class TreeDiagram;
37class DiagramItem;
38using DiagramItemList = std::vector<DiagramItem*>;
39
40/** Class representing a single node in the built-in class diagram */
42{
43 public:
44 DiagramItem(DiagramItem *p,uint32_t number,const ClassDef *cd,
45 Protection prot,Specifier virt,const QCString &ts);
46 QCString label() const;
47 QCString fileName() const;
50 void move(int dx,int dy) { m_x=static_cast<uint32_t>(m_x+dx); m_y=static_cast<uint32_t>(m_y+dy); }
51 uint32_t xPos() const { return m_x; }
52 uint32_t yPos() const { return m_y; }
53 float xfPos() const { return static_cast<float>(m_x); }
54 float yfPos() const { return static_cast<float>(m_y); }
55 uint32_t avgChildPos() const;
56 uint32_t numChildren() const;
57 void addChild(DiagramItem *di);
58 uint32_t number() const { return m_num; }
59 Protection protection() const { return m_prot; }
60 Specifier virtualness() const { return m_virt; }
62 bool isInList() const { return m_inList; }
63 const ClassDef *getClassDef() const { return m_classDef; }
64 private:
67 uint32_t m_x = 0;
68 uint32_t m_y = 0;
69 uint32_t m_num;
72 QCString m_templSpec;
73 bool m_inList = false;
74 const ClassDef *m_classDef;
75};
76
77/** Class representing a row in the built-in class diagram */
79{
80 public:
81 using Ptr = std::unique_ptr<DiagramItem>;
82 using Vec = std::vector<Ptr>;
83 using iterator = typename Vec::iterator;
84 using reverse_iterator = typename Vec::reverse_iterator;
85 DiagramRow(TreeDiagram *d,uint32_t l) : m_diagram(d), m_level(l) {}
86 void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases,
87 Protection prot,Specifier virt,const QCString &ts);
88 uint32_t number() { return m_level; }
89
90 DiagramItem *item(int index) { return m_items.at(index).get(); }
91 uint32_t numItems() const { return static_cast<uint32_t>(m_items.size()); }
92 iterator begin() { return m_items.begin(); }
93 iterator end() { return m_items.end(); }
94 reverse_iterator rbegin() { return m_items.rbegin(); }
95 reverse_iterator rend() { return m_items.rend(); }
96 private:
97 TreeDiagram *m_diagram;
98 uint32_t m_level;
100};
101
102/** Class representing the tree layout for the built-in class diagram. */
104{
105 public:
106 using Ptr = std::unique_ptr<DiagramRow>;
107 using Vec = std::vector<Ptr>;
108 using iterator = typename Vec::iterator;
109 TreeDiagram(const ClassDef *root,bool doBases);
110 void computeLayout();
111 uint32_t computeRows();
112 void moveChildren(DiagramItem *root,int dx);
113 void computeExtremes(uint32_t *labelWidth,uint32_t *xpos);
114 void drawBoxes(TextStream &t,Image *image,
115 bool doBase,bool bitmap,
116 uint32_t baseRows,uint32_t superRows,
117 uint32_t cellWidth,uint32_t cellHeight,
118 QCString relPath="",
119 bool generateMap=TRUE);
120 void drawConnectors(TextStream &t,Image *image,
121 bool doBase,bool bitmap,
122 uint32_t baseRows,uint32_t superRows,
123 uint32_t cellWidth,uint32_t cellheight);
124 DiagramRow *row(int index) { return m_rows.at(index).get(); }
125 uint32_t numRows() const { return static_cast<uint32_t>(m_rows.size()); }
126 DiagramRow *addRow(uint32_t l)
127 { m_rows.push_back(std::make_unique<DiagramRow>(this,l)); return m_rows.back().get(); }
128 iterator begin() { return m_rows.begin(); }
129 iterator end() { return m_rows.end(); }
130 private:
131 bool layoutTree(DiagramItem *root,uint32_t row);
133};
134
135
136
137//-----------------------------------------------------------------------------
138
139const uint32_t maxTreeWidth = 8;
140const uint32_t gridWidth = 100;
141const uint32_t gridHeight = 100;
142
143const uint32_t labelHorSpacing = 10; // horizontal distance between labels
144const uint32_t labelVertSpacing = 32; // vertical distance between labels
145const uint32_t labelHorMargin = 6; // horiz. spacing between label and box
146const uint32_t fontHeight = 12; // height of a character
147
148static uint32_t protToMask(Protection p)
149{
150 switch(p)
151 {
152 case Protection::Public: return 0xffffffff;
153 case Protection::Package: // package is not possible!
154 case Protection::Protected: return 0xcccccccc;
155 case Protection::Private: return 0xaaaaaaaa;
156 }
157 return 0;
158}
159
160static uint8_t protToColor(Protection p)
161{
162 switch(p)
163 {
164 case Protection::Public: return 6;
165 case Protection::Package: // package is not possible!
166 case Protection::Protected: return 5;
167 case Protection::Private: return 4;
168 }
169 return 0;
170}
171
173{
174 switch(p)
175 {
176 case Protection::Public: return "solid";
177 case Protection::Package: // package is not possible!
178 case Protection::Protected: return "dashed";
179 case Protection::Private: return "dotted";
180 }
181 return QCString();
182}
183
184static uint32_t virtToMask(Specifier p)
185{
186 switch(p)
187 {
188 case Specifier::Normal: return 0xffffffff;
189 case Specifier::Virtual: return 0xf0f0f0f0;
190 default: break;
191 }
192 return 0;
193}
194
196{
197 if (s.isEmpty()) return s;
198 GrowBuf growBuf;
199 const char *p=s.data();
200 char c=0;
201 while ((c=*p++))
202 {
203 switch (c)
204 {
205 case '(': growBuf.addStr("\\("); break;
206 case ')': growBuf.addStr("\\)"); break;
207 default: growBuf.addChar(c); break;
208 }
209 }
210 growBuf.addChar(0);
211 return growBuf.get();
212}
213
214// pre: dil is not empty
216{
217 auto it = dil.begin();
219 if (it!=dil.end())
220 {
221 result=(*it)->protection();
222 for (++it;it!=dil.end();++it)
223 {
224 Protection p=(*it)->protection();
225 if (p!=result)
226 {
227 if (result==Protection::Protected && p==Protection::Public) result=p;
228 else if (result==Protection::Private) result=p;
229 }
230 }
231 }
232 return result;
233}
234
235static void writeBitmapBox(DiagramItem *di,Image *image,
236 uint32_t x,uint32_t y,uint32_t w,uint32_t h,bool firstRow,
237 bool hasDocs,bool children=FALSE)
238{
239 uint8_t colFill = hasDocs ? (firstRow ? 8 : 2) : 7;
240 uint8_t colBorder = (firstRow || !hasDocs) ? 1 : 3;
241 uint32_t l = Image::stringLength(di->label());
242 uint32_t mask=virtToMask(di->virtualness());
243 image->fillRect(x+1,y+1,w-2,h-2,colFill,mask);
244 image->drawRect(x,y,w,h,colBorder,mask);
245 image->writeString(x+(w-l)/2, y+(h-fontHeight)/2, di->label(),1);
246 if (children)
247 {
248 for (uint32_t i=0;i<5;i++)
249 {
250 image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff);
251 }
252 }
253}
254
256 float x,float y,bool children=FALSE)
257{
258 if (di->virtualness()==Specifier::Virtual) t << "dashed\n";
259 t << " (" << convertToPSString(di->label()) << ") " << x << " " << y << " box\n";
260 if (children) t << x << " " << y << " mark\n";
261 if (di->virtualness()==Specifier::Virtual) t << "solid\n";
262}
263
264static void writeMapArea(TextStream &t,const ClassDef *cd,QCString relPath,
265 uint32_t x,uint32_t y,uint32_t w,uint32_t h)
266{
267 if (cd->isLinkable())
268 {
269 QCString ref=cd->getReference();
270 t << "<area ";
271 if (!ref.isEmpty())
272 {
273 t << externalLinkTarget(true);
274 }
275 t << "href=\"";
276 t << externalRef(relPath,ref,TRUE);
277 QCString fn = cd->getOutputFileBase();
279 t << fn;
280 if (!cd->anchor().isEmpty())
281 {
282 t << "#" << cd->anchor();
283 }
284 t << "\" ";
285 QCString tooltip = cd->briefDescriptionAsTooltip();
286 if (!tooltip.isEmpty())
287 {
288 t << "title=\"" << convertToHtml(tooltip) << "\" ";
289 }
290 t << "alt=\"" << convertToXML(cd->displayName());
291 t << "\" shape=\"rect\" coords=\"" << x << "," << y << ",";
292 t << (x+w) << "," << (y+h) << "\"/>\n";
293 }
294}
295//-----------------------------------------------------------------------------
296
298 Protection pr,Specifier vi,const QCString &ts)
299 : m_parent(p), m_num(number), m_prot(pr), m_virt(vi), m_templSpec(ts), m_classDef(cd)
300{
301}
302
304{
305 QCString result;
306 if (!m_templSpec.isEmpty())
307 {
308 // we use classDef->name() here and not displayName() in order
309 // to get the name used in the inheritance relation.
310 QCString n = m_classDef->name();
311 if (n.endsWith("-p"))
312 {
313 n = n.left(n.length()-2);
314 }
316 }
317 else
318 {
319 result=m_classDef->displayName();
320 }
321 if (Config_getBool(HIDE_SCOPE_NAMES)) result=stripScope(result);
322 return result;
323}
324
326{
327 return m_classDef->getOutputFileBase();
328}
329
331{
332 DiagramItem *di = nullptr;
333 size_t c=m_children.size();
334 if (c==0) // no children -> don't move
335 return xPos();
336 if ((di=m_children.front())->isInList()) // children should be in a list
337 return di->xPos();
338 if (c&1) // odd number of children -> get pos of middle child
339 return m_children.at(c/2)->xPos();
340 else // even number of children -> get middle of most middle children
341 return (m_children.at(c/2-1)->xPos()+m_children.at(c/2)->xPos())/2;
342}
343
345{
346 return static_cast<uint32_t>(m_children.size());
347}
348
350{
351 m_children.push_back(di);
352}
353
354//---------------------------------------------------------------------------
355
357 Protection prot,Specifier virt,const QCString &ts)
358{
359 auto di = std::make_unique<DiagramItem>(parent, m_diagram->row(m_level)->numItems(),
360 cd,prot,virt,ts);
361 DiagramItem *di_ptr = di.get();
362 if (parent) parent->addChild(di_ptr);
363 di->move(static_cast<int>(m_items.size()*gridWidth),static_cast<int>(m_level*gridHeight));
364 m_items.push_back(std::move(di));
365 int count=0;
366 for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses())
367 {
368 /* there are base/sub classes */
369 ClassDef *ccd=bcd.classDef;
370 if (ccd && ccd->isVisibleInHierarchy()) count++;
371 }
372 if (count>0 && (prot!=Protection::Private || !doBases))
373 {
374 DiagramRow *row=nullptr;
375 if (m_diagram->numRows()<=m_level+1) /* add new row */
376 {
377 row=m_diagram->addRow(m_level+1);
378 }
379 else /* get next row */
380 {
381 row=m_diagram->row(m_level+1);
382 }
383 for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses())
384 {
385 ClassDef *ccd=bcd.classDef;
386 if (ccd && ccd->isVisibleInHierarchy())
387 {
388 row->insertClass(di_ptr,ccd,doBases,bcd.prot,
389 doBases ? bcd.virt : Specifier::Normal,
390 doBases ? bcd.templSpecifiers : QCString());
391 }
392 }
393 }
394}
395
396//---------------------------------------------------------------------------
397
398TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases)
399{
400 auto row = std::make_unique<DiagramRow>(this,0);
401 DiagramRow *row_ptr = row.get();
402 m_rows.push_back(std::move(row));
403 row_ptr->insertClass(nullptr,root,doBases,Protection::Public,Specifier::Normal,QCString());
404}
405
407{
408 for (const auto &di : root->getChildren())
409 {
410 di->move(dx,0);
411 moveChildren(di,dx);
412 }
413}
414
416{
417 bool moved=FALSE;
418 //printf("layoutTree(%s,%d)\n",qPrint(root->label()),r);
419
420 if (root->numChildren()>0)
421 {
422 auto children = root->getChildren();
423 uint32_t pPos=root->xPos();
424 uint32_t cPos=root->avgChildPos();
425 if (pPos>cPos) // move children
426 {
427 const auto &row=m_rows.at(r+1);
428 //printf("Moving children %d-%d in row %d\n",
429 // dil->getFirst()->number(),row->count()-1,r+1);
430 for (uint32_t k=children.front()->number();k<row->numItems();k++)
431 {
432 row->item(k)->move(static_cast<int>(pPos-cPos),0);
433 }
434 moved=TRUE;
435 }
436 else if (pPos<cPos) // move parent
437 {
438 const auto &row=m_rows.at(r);
439 //printf("Moving parents %d-%d in row %d\n",
440 // root->number(),row->count()-1,r);
441 for (uint32_t k=root->number();k<row->numItems();k++)
442 {
443 row->item(k)->move(static_cast<int>(cPos-pPos),0);
444 }
445 moved=TRUE;
446 }
447
448 // recurse to children
449 auto it = children.begin();
450 for (;it!=children.end() && !moved && !(*it)->isInList();++it)
451 {
452 moved = layoutTree(*it,r+1);
453 }
454 }
455 return moved;
456}
457
459{
460 auto it = m_rows.begin();
461 while (it!=m_rows.end() && (*it)->numItems()<maxTreeWidth) ++it;
462 if (it!=m_rows.end())
463 {
464 const auto &row = *it;
465 //printf("computeLayout() list row at %d\n",row->number());
466 DiagramItem *opi=nullptr;
467 int delta=0;
468 bool first=TRUE;
469 for (const auto &di : *row)
470 {
471 DiagramItem *pi=di->parentItem();
472 if (pi==opi && !first) { delta-=gridWidth; }
473 first = pi!=opi;
474 opi=pi;
475 di->move(delta,0); // collapse all items in the same
476 // list (except the first)
477 di->putInList();
478 }
479 }
480
481 // re-organize the diagram items
482 DiagramItem *root=m_rows.front()->item(0);
483 while (layoutTree(root,0)) { }
484
485 // move first items of the lists
486 if (it!=m_rows.end())
487 {
488 const auto &row = *it;
489 auto rit = row->begin();
490 while (rit!=row->end())
491 {
492 DiagramItem *pi=(*rit)->parentItem();
493 if (pi->numChildren()>1)
494 {
495 (*rit)->move(gridWidth,0);
496 while (rit!=row->end() && (*rit)->parentItem()==pi)
497 {
498 ++rit;
499 }
500 }
501 else
502 {
503 ++rit;
504 }
505 }
506 }
507}
508
510{
511 //printf("TreeDiagram::computeRows()=%d\n",count());
512 uint32_t count=0;
513 auto it = m_rows.begin();
514 while (it!=m_rows.end() && !(*it)->item(0)->isInList())
515 {
516 ++it;
517 ++count;
518 }
519
520 //printf("count=%d row=%p\n",count,row);
521 if (it!=m_rows.end())
522 {
523 const auto &row = *it;
524 uint32_t maxListLen=0;
525 uint32_t curListLen=0;
526 DiagramItem *opi=nullptr;
527 for (const auto &di : *row) // for each item in a row
528 {
529 if (di->parentItem()!=opi) curListLen=1; else curListLen++;
530 if (curListLen>maxListLen) maxListLen=curListLen;
531 opi=di->parentItem();
532 }
533 //printf("maxListLen=%d\n",maxListLen);
534 count+=maxListLen;
535 }
536 return count;
537}
538
539void TreeDiagram::computeExtremes(uint32_t *maxLabelLen,uint32_t *maxXPos)
540{
541 uint32_t ml=0,mx=0;
542 for (const auto &dr : m_rows) // for each row
543 {
544 bool done=FALSE;
545 for (const auto &di : *dr) // for each item in a row
546 {
547 if (di->isInList()) done=TRUE;
548 if (maxXPos) mx=std::max(mx,di->xPos());
549 if (maxLabelLen) ml=std::max(ml,Image::stringLength(di->label()));
550 }
551 if (done) break;
552 }
553 if (maxLabelLen) *maxLabelLen=ml;
554 if (maxXPos) *maxXPos=mx;
555}
556
557//! helper class representing an iterator that can iterate forwards or backwards
558template<class C,class I>
560{
561 public:
562 DualDirIterator(C &container,bool fwd)
563 : m_container(container), m_forward(fwd)
564 {
565 if (fwd) m_it = container.begin();
566 else m_rit = container.rbegin();
567 }
569 {
570 if (m_forward) ++m_it++; else ++m_rit;
571 }
573 {
574 return m_forward ? *m_it : *m_rit;
575 }
576
577 bool atEnd()
578 {
579 if (m_forward)
580 return m_it==m_container.end();
581 else
582 return m_rit==m_container.rend();
583 }
584
585 private:
588 typename C::iterator m_it;
589 typename C::reverse_iterator m_rit;
590};
591
593 bool doBase,bool bitmap,
594 uint32_t baseRows,uint32_t superRows,
595 uint32_t cellWidth,uint32_t cellHeight,
596 QCString relPath,
597 bool generateMap)
598{
599 auto it = m_rows.begin();
600 if (it!=m_rows.end() && !doBase) ++it;
601 bool firstRow = doBase;
602 bool done=FALSE;
603 float superRowsF = static_cast<float>(superRows);
604 for (;it!=m_rows.end() && !done;++it) // for each row
605 {
606 const auto &dr = *it;
607 uint32_t x=0,y=0;
608 float xf=0.0f,yf=0.0f;
609 DiagramItem *firstDi = dr->item(0);
610 if (firstDi->isInList()) // put boxes in a list
611 {
612 DiagramItem *opi=nullptr;
613 DualDirIterator<DiagramRow,const std::unique_ptr<DiagramItem>&> dit(*dr,!doBase);
614 while (!dit.atEnd())
615 {
616 DiagramItem *di = (*dit).get();
617 if (di->parentItem()==opi)
618 {
619 if (bitmap)
620 {
621 if (doBase) y -= cellHeight+labelVertSpacing;
622 else y += cellHeight+labelVertSpacing;
623 }
624 else
625 {
626 if (doBase) yf += 1.0f;
627 else yf -= 1.0f;
628 }
629 }
630 else
631 {
632 if (bitmap)
633 {
634 x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
635 if (doBase)
636 {
637 y = image->height()-
638 superRows*cellHeight-
639 (superRows-1)*labelVertSpacing-
640 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
641 }
642 else
643 {
644 y = (baseRows-1)*(cellHeight+labelVertSpacing)+
645 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
646 }
647 }
648 else
649 {
650 xf = di->xfPos()/gridWidth;
651 if (doBase)
652 {
653 yf = di->yfPos()/gridHeight+superRowsF-1.0f;
654 }
655 else
656 {
657 yf = superRowsF-1.0f-di->yfPos()/gridHeight;
658 }
659 }
660 }
661 opi=di->parentItem();
662
663 if (bitmap)
664 {
665 bool hasDocs=di->getClassDef()->isLinkable();
666 writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,
667 hasDocs,di->numChildren()>0);
668 if (!firstRow && generateMap)
669 writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight);
670 }
671 else
672 {
673 writeVectorBox(t,di,xf,yf,di->numChildren()>0);
674 }
675
676 ++dit;
677 }
678 done=TRUE;
679 }
680 else // draw a tree of boxes
681 {
682 for (const auto &di : *dr)
683 {
684 if (bitmap)
685 {
686 x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
687 if (doBase)
688 {
689 y = image->height()-
690 superRows*cellHeight-
691 (superRows-1)*labelVertSpacing-
692 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
693 }
694 else
695 {
696 y = (baseRows-1)*(cellHeight+labelVertSpacing)+
697 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
698 }
699 bool hasDocs=di->getClassDef()->isLinkable();
700 writeBitmapBox(di.get(),image,x,y,cellWidth,cellHeight,firstRow,hasDocs);
701 if (!firstRow && generateMap)
702 writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight);
703 }
704 else
705 {
706 xf=di->xfPos()/gridWidth;
707 if (doBase)
708 {
709 yf = di->yfPos()/gridHeight+superRowsF-1.0f;
710 }
711 else
712 {
713 yf = superRowsF-1.0f-di->yfPos()/gridHeight;
714 }
715 writeVectorBox(t,di.get(),xf,yf);
716 }
717 }
718 }
719 firstRow=FALSE;
720 }
721}
722
724 bool doBase,bool bitmap,
725 uint32_t baseRows,uint32_t superRows,
726 uint32_t cellWidth,uint32_t cellHeight)
727{
728 bool done=FALSE;
729 auto it = m_rows.begin();
730 float superRowsF = static_cast<float>(superRows);
731 for (;it!=m_rows.end() && !done;++it) // for each row
732 {
733 const auto &dr = *it;
734 DiagramItem *rootDi = dr->item(0);
735 if (rootDi->isInList()) // row consists of list connectors
736 {
737 uint32_t x=0,y=0,ys=0;
738 float xf=0.0f,yf=0.0f,ysf=0.0f;
739 auto rit = dr->begin();
740 while (rit!=dr->end())
741 {
742 DiagramItem *di=(*rit).get();
743 DiagramItem *pi=di->parentItem();
745 DiagramItem *last=dil.back();
746 if (di==last) // single child
747 {
748 if (bitmap) // draw pixels
749 {
750 x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
751 if (doBase) // base classes
752 {
753 y = image->height()-
754 (superRows-1)*(cellHeight+labelVertSpacing)-
755 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
756 image->drawVertArrow(x,y,y+labelVertSpacing/2,
757 protToColor(di->protection()),
758 protToMask(di->protection()));
759 }
760 else // super classes
761 {
762 y = (baseRows-1)*(cellHeight+labelVertSpacing)-
764 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
765 image->drawVertLine(x,y,y+labelVertSpacing/2,
766 protToColor(di->protection()),
767 protToMask(di->protection()));
768 }
769 }
770 else // draw vectors
771 {
772 t << protToString(di->protection()) << "\n";
773 if (doBase)
774 {
775 t << "1 " << (di->xfPos()/gridWidth) << " "
776 << (di->yfPos()/gridHeight+superRowsF-1.0f) << " in\n";
777 }
778 else
779 {
780 t << "0 " << (di->xfPos()/gridWidth) << " "
781 << (superRowsF-0.25f-di->yfPos()/gridHeight)
782 << " in\n";
783 }
784 }
785 }
786 else // multiple children, put them in a vertical list
787 {
788 if (bitmap)
789 {
790 x = di->parentItem()->xPos()*
791 (cellWidth+labelHorSpacing)/gridWidth+cellWidth/2;
792 if (doBase) // base classes
793 {
794 ys = image->height()-
795 (superRows-1)*(cellHeight+labelVertSpacing)-
796 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
797 y = ys - cellHeight/2;
798 }
799 else // super classes
800 {
801 ys = (baseRows-1)*(cellHeight+labelVertSpacing)+
802 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
803 y = ys + cellHeight/2;
804 }
805 }
806 else
807 {
808 xf = di->parentItem()->xfPos()/gridWidth;
809 if (doBase)
810 {
811 ysf = di->yfPos()/gridHeight+superRowsF-1.0f;
812 yf = ysf + 0.5f;
813 }
814 else
815 {
816 ysf = superRowsF-0.25f-di->yfPos()/gridHeight;
817 yf = ysf - 0.25f;
818 }
819 }
820 while (di!=last) // more children to add
821 {
822 if (bitmap)
823 {
824 if (doBase) // base classes
825 {
826 image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
827 protToColor(di->protection()),
828 protToMask(di->protection()));
829 y -= cellHeight+labelVertSpacing;
830 }
831 else // super classes
832 {
833 image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
834 protToColor(di->protection()),
835 protToMask(di->protection()));
836 y += cellHeight+labelVertSpacing;
837 }
838 }
839 else
840 {
841 t << protToString(di->protection()) << "\n";
842 if (doBase)
843 {
844 t << "1 " << xf << " " << yf << " hedge\n";
845 yf += 1.0f;
846 }
847 else
848 {
849 t << "0 " << xf << " " << yf << " hedge\n";
850 yf -= 1.0f;
851 }
852 }
853 ++rit;
854 if (rit!=dr->end()) di = (*rit).get(); else di=nullptr;
855 }
856 // add last horizontal line and a vertical connection line
857 if (bitmap)
858 {
859 if (doBase) // base classes
860 {
861 image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
862 protToColor(di->protection()),
863 protToMask(di->protection()));
864 image->drawVertLine(x,y,ys+labelVertSpacing/2,
867 }
868 else // super classes
869 {
870 image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
871 protToColor(di->protection()),
872 protToMask(di->protection()));
873 image->drawVertLine(x,ys-labelVertSpacing/2,y,
876 }
877 }
878 else
879 {
880 t << protToString(di->protection()) << "\n";
881 if (doBase)
882 {
883 t << "1 " << xf << " " << yf << " hedge\n";
884 }
885 else
886 {
887 t << "0 " << xf << " " << yf << " hedge\n";
888 }
889 t << protToString(getMinProtectionLevel(dil)) << "\n";
890 if (doBase)
891 {
892 t << xf << " " << ysf << " " << yf << " vedge\n";
893 }
894 else
895 {
896 t << xf << " " << (ysf + 0.25f) << " " << yf << " vedge\n";
897 }
898 }
899 }
900 if (rit!=dr->end()) ++rit;
901 }
902 done=TRUE; // the tree is drawn now
903 }
904 else // normal tree connector
905 {
906 for (const auto &di : *dr)
907 {
908 uint32_t x=0,y=0;
909 DiagramItemList dil = di->getChildren();
910 DiagramItem *parent = di->parentItem();
911 if (parent) // item has a parent -> connect to it
912 {
913 if (bitmap) // draw pixels
914 {
915 x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
916 if (doBase) // base classes
917 {
918 y = image->height()-
919 (superRows-1)*(cellHeight+labelVertSpacing)-
920 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
921 /* write input line */
922 image->drawVertArrow(x,y,y+labelVertSpacing/2,
923 protToColor(di->protection()),
924 protToMask(di->protection()));
925 }
926 else // super classes
927 {
928 y = (baseRows-1)*(cellHeight+labelVertSpacing)-
930 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
931 /* write output line */
932 image->drawVertLine(x,y,y+labelVertSpacing/2,
933 protToColor(di->protection()),
934 protToMask(di->protection()));
935 }
936 }
937 else // draw pixels
938 {
939 t << protToString(di->protection()) << "\n";
940 if (doBase)
941 {
942 t << "1 " << di->xfPos()/gridWidth << " "
943 << (di->yfPos()/gridHeight+superRowsF-1.0f) << " in\n";
944 }
945 else
946 {
947 t << "0 " << di->xfPos()/gridWidth << " "
948 << (superRowsF-0.25f-di->yfPos()/gridHeight)
949 << " in\n";
950 }
951 }
952 }
953 if (!dil.empty())
954 {
956 uint32_t mask=protToMask(p);
957 uint8_t col=protToColor(p);
958 if (bitmap)
959 {
960 x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
961 if (doBase) // base classes
962 {
963 y = image->height()-
964 (superRows-1)*(cellHeight+labelVertSpacing)-
965 cellHeight-labelVertSpacing/2-
966 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
967 image->drawVertLine(x,y,y+labelVertSpacing/2-1,col,mask);
968 }
969 else // super classes
970 {
971 y = (baseRows-1)*(cellHeight+labelVertSpacing)+
972 cellHeight+
973 di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
974 image->drawVertArrow(x,y,y+labelVertSpacing/2-1,col,mask);
975 }
976 }
977 else
978 {
979 t << protToString(p) << "\n";
980 if (doBase)
981 {
982 t << "0 " << di->xfPos()/gridWidth << " "
983 << (di->yfPos()/gridHeight+superRowsF-1.0f) << " out\n";
984 }
985 else
986 {
987 t << "1 " << di->xfPos()/gridWidth << " "
988 << (superRowsF-1.75f-di->yfPos()/gridHeight)
989 << " out\n";
990 }
991 }
992 /* write input line */
993 DiagramItem *first = dil.front();
994 DiagramItem *last = dil.back();
995 if (first!=last && !first->isInList()) /* connect with all base classes */
996 {
997 if (bitmap)
998 {
999 uint32_t xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth
1000 + cellWidth/2;
1001 uint32_t xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth
1002 + cellWidth/2;
1003 if (doBase) // base classes
1004 {
1005 image->drawHorzLine(y,xs,xe,col,mask);
1006 }
1007 else // super classes
1008 {
1009 image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask);
1010 }
1011 }
1012 else
1013 {
1014 t << protToString(p) << "\n";
1015 if (doBase)
1016 {
1017 t << first->xfPos()/gridWidth << " "
1018 << last->xfPos()/gridWidth << " "
1019 << (first->yfPos()/gridHeight+superRowsF-1.0f)
1020 << " conn\n";
1021 }
1022 else
1023 {
1024 t << first->xfPos()/gridWidth << " "
1025 << last->xfPos()/gridWidth << " "
1026 << (superRowsF-first->yfPos()/gridHeight)
1027 << " conn\n";
1028 }
1029 }
1030 }
1031 }
1032 }
1033 }
1034 }
1035}
1036
1037//-----------------------------------------------------------------
1038
1040{
1041 Private(const ClassDef *root) : base(root,true), super(root,false) {}
1042 TreeDiagram base;
1043 TreeDiagram super;
1044};
1045
1046//-----------------------------------------------------------------
1047
1048
1049ClassDiagram::ClassDiagram(const ClassDef *root) : p(std::make_unique<Private>(root))
1050{
1051 p->base.computeLayout();
1052 p->super.computeLayout();
1053 DiagramItem *baseItem = p->base.row(0)->item(0);
1054 DiagramItem *superItem = p->super.row(0)->item(0);
1055 uint32_t xbase = baseItem->xPos();
1056 uint32_t xsuper = superItem->xPos();
1057 if (xbase>xsuper)
1058 {
1059 int dist=static_cast<int>(xbase-xsuper);
1060 superItem->move(dist,0);
1061 p->super.moveChildren(superItem,dist);
1062 }
1063 else if (xbase<xsuper)
1064 {
1065 int dist=static_cast<int>(xsuper-xbase);
1066 baseItem->move(dist,0);
1067 p->base.moveChildren(baseItem,dist);
1068 }
1069}
1070
1071ClassDiagram::~ClassDiagram() = default;
1072
1074 const QCString &fileName) const
1075{
1076 uint32_t baseRows=p->base.computeRows();
1077 uint32_t superRows=p->super.computeRows();
1078 uint32_t baseMaxX = 0, baseMaxLabelWidth = 0, superMaxX = 0, superMaxLabelWidth = 0;
1079 p->base.computeExtremes(&baseMaxLabelWidth,&baseMaxX);
1080 p->super.computeExtremes(&superMaxLabelWidth,&superMaxX);
1081
1082 uint32_t rows=std::max(1u,baseRows+superRows-1);
1083 uint32_t cols=(std::max(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth;
1084
1085 // Estimate the image aspect width and height in pixels.
1086 float estHeight = static_cast<float>(rows)*40.0f;
1087 float estWidth = static_cast<float>(cols)*(20+static_cast<float>(std::max(baseMaxLabelWidth,superMaxLabelWidth)));
1088 //printf("Estimated size %d x %d\n",estWidth,estHeight);
1089
1090 const float pageWidth = 14.0f; // estimated page width in cm.
1091 // Somewhat lower to deal with estimation
1092 // errors.
1093
1094 // compute the image height in centimeters based on the estimates
1095 float realHeight = static_cast<float>(std::min(rows,12u)); // real height in cm
1096 float realWidth = realHeight * estWidth/estHeight;
1097 if (realWidth>pageWidth) // assume that the page width is about 15 cm
1098 {
1099 realHeight*=pageWidth/realWidth;
1100 }
1101
1102 //output << "}\n";
1103 output << "\\begin{figure}[H]\n"
1104 "\\begin{center}\n"
1105 "\\leavevmode\n";
1106 output << "\\includegraphics[height=" << realHeight << "cm]{"
1107 << fileName << "}\n";
1108 output << "\\end{center}\n"
1109 "\\end{figure}\n";
1110
1111 //printf("writeFigure rows=%d cols=%d\n",rows,cols);
1112
1113 QCString epsBaseName=QCString(path)+"/"+fileName;
1114 QCString epsName=epsBaseName+".eps";
1115 std::ofstream f = Portable::openOutputStream(epsName);
1116 if (!f.is_open())
1117 {
1118 term("Could not open file %s for writing\n",qPrint(epsName));
1119 }
1120 else
1121 {
1122 TextStream t(&f);
1123
1124 //printf("writeEPS() rows=%d cols=%d\n",rows,cols);
1125
1126 // generate EPS header and postscript variables and procedures
1127
1128 t << "%!PS-Adobe-2.0 EPSF-2.0\n";
1129 t << "%%Title: ClassName\n";
1130 t << "%%Creator: Doxygen\n";
1131 t << "%%CreationDate: Time\n";
1132 t << "%%For: \n";
1133 t << "%Magnification: 1.00\n";
1134 t << "%%Orientation: Portrait\n";
1135 t << "%%BoundingBox: 0 0 500 " << estHeight*500.0f/estWidth << "\n";
1136 t << "%%Pages: 0\n";
1137 t << "%%BeginSetup\n";
1138 t << "%%EndSetup\n";
1139 t << "%%EndComments\n";
1140 t << "\n";
1141 t << "% ----- variables -----\n";
1142 t << "\n";
1143 t << "/boxwidth 0 def\n";
1144 t << "/boxheight 40 def\n";
1145 t << "/fontheight 24 def\n";
1146 t << "/marginwidth 10 def\n";
1147 t << "/distx 20 def\n";
1148 t << "/disty 40 def\n";
1149 t << "/boundaspect " << estWidth/estHeight << " def % aspect ratio of the BoundingBox (width/height)\n";
1150 t << "/boundx 500 def\n";
1151 t << "/boundy boundx boundaspect div def\n";
1152 t << "/xspacing 0 def\n";
1153 t << "/yspacing 0 def\n";
1154 t << "/rows " << rows << " def\n";
1155 t << "/cols " << cols << " def\n";
1156 t << "/scalefactor 0 def\n";
1157 t << "/boxfont /Times-Roman findfont fontheight scalefont def\n";
1158 t << "\n";
1159 t << "% ----- procedures -----\n";
1160 t << "\n";
1161 t << "/dotted { [1 4] 0 setdash } def\n";
1162 t << "/dashed { [5] 0 setdash } def\n";
1163 t << "/solid { [] 0 setdash } def\n";
1164 t << "\n";
1165 t << "/max % result = MAX(arg1,arg2)\n";
1166 t << "{\n";
1167 t << " /a exch def\n";
1168 t << " /b exch def\n";
1169 t << " a b gt {a} {b} ifelse\n";
1170 t << "} def\n";
1171 t << "\n";
1172 t << "/xoffset % result = MAX(0,(scalefactor-(boxwidth*cols+distx*(cols-1)))/2)\n";
1173 t << "{\n";
1174 t << " 0 scalefactor boxwidth cols mul distx cols 1 sub mul add sub 2 div max\n";
1175 t << "} def\n";
1176 t << "\n";
1177 t << "/cw % boxwidth = MAX(boxwidth, stringwidth(arg1))\n";
1178 t << "{\n";
1179 t << " /str exch def\n";
1180 t << " /boxwidth boxwidth str stringwidth pop max def\n";
1181 t << "} def\n";
1182 t << "\n";
1183 t << "/box % draws a box with text 'arg1' at grid pos (arg2,arg3)\n";
1184 t << "{ gsave\n";
1185 t << " 2 setlinewidth\n";
1186 t << " newpath\n";
1187 t << " exch xspacing mul xoffset add\n";
1188 t << " exch yspacing mul\n";
1189 t << " moveto\n";
1190 t << " boxwidth 0 rlineto \n";
1191 t << " 0 boxheight rlineto \n";
1192 t << " boxwidth neg 0 rlineto \n";
1193 t << " 0 boxheight neg rlineto \n";
1194 t << " closepath\n";
1195 t << " dup stringwidth pop neg boxwidth add 2 div\n";
1196 t << " boxheight fontheight 2 div sub 2 div\n";
1197 t << " rmoveto show stroke\n";
1198 t << " grestore\n";
1199 t << "} def \n";
1200 t << "\n";
1201 t << "/mark\n";
1202 t << "{ newpath\n";
1203 t << " exch xspacing mul xoffset add boxwidth add\n";
1204 t << " exch yspacing mul\n";
1205 t << " moveto\n";
1206 t << " 0 boxheight 4 div rlineto\n";
1207 t << " boxheight neg 4 div boxheight neg 4 div rlineto\n";
1208 t << " closepath\n";
1209 t << " eofill\n";
1210 t << " stroke\n";
1211 t << "} def\n";
1212 t << "\n";
1213 t << "/arrow\n";
1214 t << "{ newpath\n";
1215 t << " moveto\n";
1216 t << " 3 -8 rlineto\n";
1217 t << " -6 0 rlineto\n";
1218 t << " 3 8 rlineto\n";
1219 t << " closepath\n";
1220 t << " eofill\n";
1221 t << " stroke\n";
1222 t << "} def\n";
1223 t << "\n";
1224 t << "/out % draws an output connector for the block at (arg1,arg2)\n";
1225 t << "{\n";
1226 t << " newpath\n";
1227 t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
1228 t << " exch yspacing mul boxheight add\n";
1229 t << " /y exch def\n";
1230 t << " /x exch def\n";
1231 t << " x y moveto\n";
1232 t << " 0 disty 2 div rlineto \n";
1233 t << " stroke\n";
1234 t << " 1 eq { x y disty 2 div add arrow } if\n";
1235 t << "} def\n";
1236 t << "\n";
1237 t << "/in % draws an input connector for the block at (arg1,arg2)\n";
1238 t << "{\n";
1239 t << " newpath\n";
1240 t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
1241 t << " exch yspacing mul disty 2 div sub\n";
1242 t << " /y exch def\n";
1243 t << " /x exch def\n";
1244 t << " x y moveto\n";
1245 t << " 0 disty 2 div rlineto\n";
1246 t << " stroke\n";
1247 t << " 1 eq { x y disty 2 div add arrow } if\n";
1248 t << "} def\n";
1249 t << "\n";
1250 t << "/hedge\n";
1251 t << "{\n";
1252 t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
1253 t << " exch yspacing mul boxheight 2 div sub\n";
1254 t << " /y exch def\n";
1255 t << " /x exch def\n";
1256 t << " newpath\n";
1257 t << " x y moveto\n";
1258 t << " boxwidth 2 div distx add 0 rlineto\n";
1259 t << " stroke\n";
1260 t << " 1 eq\n";
1261 t << " { newpath x boxwidth 2 div distx add add y moveto\n";
1262 t << " -8 3 rlineto\n";
1263 t << " 0 -6 rlineto\n";
1264 t << " 8 3 rlineto\n";
1265 t << " closepath\n";
1266 t << " eofill\n";
1267 t << " stroke\n";
1268 t << " } if\n";
1269 t << "} def\n";
1270 t << "\n";
1271 t << "/vedge\n";
1272 t << "{\n";
1273 t << " /ye exch def\n";
1274 t << " /ys exch def\n";
1275 t << " /xs exch def\n";
1276 t << " newpath\n";
1277 t << " xs xspacing mul xoffset add boxwidth 2 div add dup\n";
1278 t << " ys yspacing mul boxheight 2 div sub\n";
1279 t << " moveto\n";
1280 t << " ye yspacing mul boxheight 2 div sub\n";
1281 t << " lineto\n";
1282 t << " stroke\n";
1283 t << "} def\n";
1284 t << "\n";
1285 t << "/conn % connections the blocks from col 'arg1' to 'arg2' of row 'arg3'\n";
1286 t << "{\n";
1287 t << " /ys exch def\n";
1288 t << " /xe exch def\n";
1289 t << " /xs exch def\n";
1290 t << " newpath\n";
1291 t << " xs xspacing mul xoffset add boxwidth 2 div add\n";
1292 t << " ys yspacing mul disty 2 div sub\n";
1293 t << " moveto\n";
1294 t << " xspacing xe xs sub mul 0\n";
1295 t << " rlineto\n";
1296 t << " stroke\n";
1297 t << "} def\n";
1298 t << "\n";
1299 t << "% ----- main ------\n";
1300 t << "\n";
1301 t << "boxfont setfont\n";
1302 t << "1 boundaspect scale\n";
1303
1304
1305 for (const auto &dr : p->base)
1306 {
1307 bool done=FALSE;
1308 for (const auto &di : *dr)
1309 {
1310 done=di->isInList();
1311 t << "(" << convertToPSString(di->label()) << ") cw\n";
1312 }
1313 if (done) break;
1314 }
1315
1316 auto it = p->super.begin();
1317 if (it!=p->super.end()) ++it;
1318 for (;it!=p->super.end();++it)
1319 {
1320 const auto &dr = *it;
1321 bool done=FALSE;
1322 for (const auto &di : *dr)
1323 {
1324 done=di->isInList();
1325 t << "(" << convertToPSString(di->label()) << ") cw\n";
1326 }
1327 if (done) break;
1328 }
1329
1330 t << "/boxwidth boxwidth marginwidth 2 mul add def\n"
1331 << "/xspacing boxwidth distx add def\n"
1332 << "/yspacing boxheight disty add def\n"
1333 << "/scalefactor \n"
1334 << " boxwidth cols mul distx cols 1 sub mul add\n"
1335 << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n"
1336 << " max def\n"
1337 << "boundx scalefactor div boundy scalefactor div scale\n";
1338
1339 t << "\n% ----- classes -----\n\n";
1340 p->base.drawBoxes(t,nullptr,TRUE,FALSE,baseRows,superRows,0,0);
1341 p->super.drawBoxes(t,nullptr,FALSE,FALSE,baseRows,superRows,0,0);
1342
1343 t << "\n% ----- relations -----\n\n";
1344 p->base.drawConnectors(t,nullptr,TRUE,FALSE,baseRows,superRows,0,0);
1345 p->super.drawConnectors(t,nullptr,FALSE,FALSE,baseRows,superRows,0,0);
1346
1347 }
1348 f.close();
1349
1350 if (Config_getBool(USE_PDFLATEX))
1351 {
1352 QCString epstopdfArgs(4096, QCString::ExplicitSize);
1353 epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
1354 qPrint(epsBaseName),qPrint(epsBaseName));
1355 //printf("Converting eps using '%s'\n",qPrint(epstopdfArgs));
1356 if (Portable::system("epstopdf",epstopdfArgs)!=0)
1357 {
1358 err("Problems running epstopdf. Check your TeX installation!\n");
1359 return;
1360 }
1361 else
1362 {
1363 Dir().remove(epsBaseName.str()+".eps");
1364 }
1365 }
1366}
1367
1368
1370 const QCString &relPath,const QCString &fileName,
1371 bool generateMap) const
1372{
1373 uint32_t baseRows=p->base.computeRows();
1374 uint32_t superRows=p->super.computeRows();
1375 uint32_t rows=baseRows+superRows-1;
1376
1377 uint32_t lb=0,ls=0,xb=0,xs=0;
1378 p->base.computeExtremes(&lb,&xb);
1379 p->super.computeExtremes(&ls,&xs);
1380
1381 uint32_t cellWidth = std::max(lb,ls)+labelHorMargin*2;
1382 uint32_t maxXPos = std::max(xb,xs);
1383 uint32_t labelVertMargin = 6; //std::max(6,(cellWidth-fontHeight)/6); // aspect at least 1:3
1384 uint32_t cellHeight = labelVertMargin*2+fontHeight;
1385 uint32_t imageWidth = (maxXPos+gridWidth)*cellWidth/gridWidth+
1386 (maxXPos*labelHorSpacing)/gridWidth;
1387 uint32_t imageHeight = rows*cellHeight+(rows-1)*labelVertSpacing;
1388
1389 Image image(imageWidth,imageHeight);
1390
1391 p->base.drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap);
1392 p->super.drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap);
1393 p->base.drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight);
1394 p->super.drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight);
1395
1396#define IMAGE_EXT ".png"
1397 image.save(QCString(path)+"/"+fileName+IMAGE_EXT);
1398 Doxygen::indexList->addImageFile(QCString(fileName)+IMAGE_EXT);
1399}
1400
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual bool isVisibleInHierarchy() const =0
the class is visible in a class diagram, or class hierarchy
virtual const BaseClassList & baseClasses() const =0
Returns the list of base classes from which this class directly inherits.
virtual const BaseClassList & subClasses() const =0
Returns the list of sub classes that directly derive from this class.
void writeImage(TextStream &t, const QCString &path, const QCString &relPath, const QCString &file, bool generateMap=true) const
Definition diagram.cpp:1369
ClassDiagram(const ClassDef *root)
Definition diagram.cpp:1049
void writeFigure(TextStream &t, const QCString &path, const QCString &file) const
Definition diagram.cpp:1073
std::unique_ptr< Private > p
Definition diagram.h:42
virtual bool isLinkable() const =0
virtual QCString anchor() const =0
virtual QCString briefDescriptionAsTooltip() const =0
virtual QCString getReference() const =0
virtual QCString displayName(bool includeScope=TRUE) const =0
virtual QCString getOutputFileBase() const =0
Class representing a single node in the built-in class diagram.
Definition diagram.cpp:42
uint32_t m_x
Definition diagram.cpp:67
Specifier virtualness() const
Definition diagram.cpp:60
DiagramItem(DiagramItem *p, uint32_t number, const ClassDef *cd, Protection prot, Specifier virt, const QCString &ts)
Definition diagram.cpp:297
void addChild(DiagramItem *di)
Definition diagram.cpp:349
QCString fileName() const
Definition diagram.cpp:325
DiagramItemList getChildren()
Definition diagram.cpp:49
Specifier m_virt
Definition diagram.cpp:71
uint32_t m_num
Definition diagram.cpp:69
uint32_t number() const
Definition diagram.cpp:58
const ClassDef * m_classDef
Definition diagram.cpp:74
uint32_t avgChildPos() const
Definition diagram.cpp:330
DiagramItem * parentItem()
Definition diagram.cpp:48
const ClassDef * getClassDef() const
Definition diagram.cpp:63
uint32_t m_y
Definition diagram.cpp:68
uint32_t numChildren() const
Definition diagram.cpp:344
DiagramItem * m_parent
Definition diagram.cpp:66
Protection protection() const
Definition diagram.cpp:59
QCString label() const
Definition diagram.cpp:303
float xfPos() const
Definition diagram.cpp:53
bool isInList() const
Definition diagram.cpp:62
void move(int dx, int dy)
Definition diagram.cpp:50
void putInList()
Definition diagram.cpp:61
QCString m_templSpec
Definition diagram.cpp:72
bool m_inList
Definition diagram.cpp:73
Protection m_prot
Definition diagram.cpp:70
uint32_t xPos() const
Definition diagram.cpp:51
DiagramItemList m_children
Definition diagram.cpp:65
float yfPos() const
Definition diagram.cpp:54
uint32_t yPos() const
Definition diagram.cpp:52
TreeDiagram * m_diagram
Definition diagram.cpp:97
uint32_t numItems() const
Definition diagram.cpp:91
std::vector< Ptr > Vec
Definition diagram.cpp:82
std::unique_ptr< DiagramItem > Ptr
Definition diagram.cpp:81
DiagramItem * item(int index)
Definition diagram.cpp:90
typename Vec::reverse_iterator reverse_iterator
Definition diagram.cpp:84
Vec m_items
Definition diagram.cpp:99
uint32_t number()
Definition diagram.cpp:88
DiagramRow(TreeDiagram *d, uint32_t l)
Definition diagram.cpp:85
typename Vec::iterator iterator
Definition diagram.cpp:83
iterator begin()
Definition diagram.cpp:92
iterator end()
Definition diagram.cpp:93
void insertClass(DiagramItem *parent, const ClassDef *cd, bool doBases, Protection prot, Specifier virt, const QCString &ts)
Definition diagram.cpp:356
reverse_iterator rend()
Definition diagram.cpp:95
reverse_iterator rbegin()
Definition diagram.cpp:94
uint32_t m_level
Definition diagram.cpp:98
static IndexList * indexList
Definition doxygen.h:134
void operator++()
Definition diagram.cpp:568
C::reverse_iterator m_rit
Definition diagram.cpp:589
DualDirIterator(C &container, bool fwd)
Definition diagram.cpp:562
C::iterator m_it
Definition diagram.cpp:588
Class representing a string buffer optimized for growing.
Definition growbuf.h:28
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
Class representing a bitmap image generated by doxygen.
Definition image.h:27
void drawVertLine(uint32_t x, uint32_t ys, uint32_t ye, uint8_t colIndex, uint32_t mask)
Definition image.cpp:309
void drawHorzLine(uint32_t y, uint32_t xs, uint32_t xe, uint8_t colIndex, uint32_t mask)
Definition image.cpp:289
void drawVertArrow(uint32_t x, uint32_t ys, uint32_t ye, uint8_t colIndex, uint32_t mask)
Definition image.cpp:318
void fillRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint8_t colIndex, uint32_t mask)
Definition image.cpp:336
uint32_t height() const
Definition image.cpp:209
void drawHorzArrow(uint32_t y, uint32_t xs, uint32_t xe, uint8_t colIndex, uint32_t mask)
Definition image.cpp:299
void drawRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint8_t colIndex, uint32_t mask)
Definition image.cpp:328
void writeString(uint32_t x, uint32_t y, const QCString &s, uint8_t fg)
Definition image.cpp:263
friend uint32_t stringLength(const QCString &s)
Definition image.cpp:277
void addImageFile(const QCString &name)
Definition indexlist.h:126
This is an alternative implementation of QCString.
Definition qcstring.h:101
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool endsWith(const char *s) const
Definition qcstring.h:504
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
const std::string & str() const
Definition qcstring.h:526
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
@ ExplicitSize
Definition qcstring.h:133
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
QCString left(size_t len) const
Definition qcstring.h:214
Text streaming class that buffers data.
Definition textstream.h:36
Class representing the tree layout for the built-in class diagram.
Definition diagram.cpp:104
void drawConnectors(TextStream &t, Image *image, bool doBase, bool bitmap, uint32_t baseRows, uint32_t superRows, uint32_t cellWidth, uint32_t cellheight)
Definition diagram.cpp:723
std::unique_ptr< DiagramRow > Ptr
Definition diagram.cpp:106
iterator end()
Definition diagram.cpp:129
bool layoutTree(DiagramItem *root, uint32_t row)
Definition diagram.cpp:415
DiagramRow * row(int index)
Definition diagram.cpp:124
void drawBoxes(TextStream &t, Image *image, bool doBase, bool bitmap, uint32_t baseRows, uint32_t superRows, uint32_t cellWidth, uint32_t cellHeight, QCString relPath="", bool generateMap=TRUE)
Definition diagram.cpp:592
void moveChildren(DiagramItem *root, int dx)
Definition diagram.cpp:406
typename Vec::iterator iterator
Definition diagram.cpp:108
void computeLayout()
Definition diagram.cpp:458
uint32_t computeRows()
Definition diagram.cpp:509
TreeDiagram(const ClassDef *root, bool doBases)
Definition diagram.cpp:398
DiagramRow * addRow(uint32_t l)
Definition diagram.cpp:126
void computeExtremes(uint32_t *labelWidth, uint32_t *xpos)
Definition diagram.cpp:539
std::vector< Ptr > Vec
Definition diagram.cpp:107
uint32_t numRows() const
Definition diagram.cpp:125
iterator begin()
Definition diagram.cpp:128
#define Config_getBool(name)
Definition config.h:33
const uint32_t maxTreeWidth
Definition diagram.cpp:139
const uint32_t labelHorMargin
Definition diagram.cpp:145
const uint32_t gridWidth
Definition diagram.cpp:140
static void writeMapArea(TextStream &t, const ClassDef *cd, QCString relPath, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
Definition diagram.cpp:264
const uint32_t labelHorSpacing
Definition diagram.cpp:143
static void writeBitmapBox(DiagramItem *di, Image *image, uint32_t x, uint32_t y, uint32_t w, uint32_t h, bool firstRow, bool hasDocs, bool children=FALSE)
Definition diagram.cpp:235
std::vector< DiagramItem * > DiagramItemList
Definition diagram.cpp:38
const uint32_t gridHeight
Definition diagram.cpp:141
const uint32_t fontHeight
Definition diagram.cpp:146
static Protection getMinProtectionLevel(const DiagramItemList &dil)
Definition diagram.cpp:215
static QCString convertToPSString(const QCString &s)
Definition diagram.cpp:195
static void writeVectorBox(TextStream &t, DiagramItem *di, float x, float y, bool children=FALSE)
Definition diagram.cpp:255
static uint32_t virtToMask(Specifier p)
Definition diagram.cpp:184
static uint8_t protToColor(Protection p)
Definition diagram.cpp:160
static QCString protToString(Protection p)
Definition diagram.cpp:172
#define IMAGE_EXT
static uint32_t protToMask(Protection p)
Definition diagram.cpp:148
const uint32_t labelVertSpacing
Definition diagram.cpp:144
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1310
#define err(fmt,...)
Definition message.h:84
#define term(fmt,...)
Definition message.h:94
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:665
int system(const QCString &command, const QCString &args, bool commandHasConsole=true)
Definition portable.cpp:106
Portable versions of functions that are platform dependent.
const char * qPrint(const char *s)
Definition qcstring.h:661
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
Private(const ClassDef *root)
Definition diagram.cpp:1041
Protection
Protection level of members.
Definition types.h:26
@ Package
Definition types.h:26
@ Public
Definition types.h:26
@ Private
Definition types.h:26
@ Protected
Definition types.h:26
Specifier
Virtualness of a member.
Definition types.h:29
@ Virtual
Definition types.h:29
@ Normal
Definition types.h:29
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:6065
QCString insertTemplateSpecifierInScope(const QCString &scope, const QCString &templ)
Definition util.cpp:4100
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:4317
QCString stripScope(const QCString &name)
Definition util.cpp:4133
QCString convertToXML(const QCString &s, bool keepEntities)
Definition util.cpp:4266
QCString externalLinkTarget(const bool parent)
Definition util.cpp:6021
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5243
A bunch of utility functions.