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