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