diff options
Diffstat (limited to 'src/diagram.cpp')
-rw-r--r-- | src/diagram.cpp | 697 |
1 files changed, 343 insertions, 354 deletions
diff --git a/src/diagram.cpp b/src/diagram.cpp index 18817e9..80c85c6 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -36,86 +33,80 @@ //----------------------------------------------------------------------------- -class DiagramItemList; +class TreeDiagram; +class DiagramItem; +using DiagramItemList = std::vector<DiagramItem*>; /** Class representing a single node in the built-in class diagram */ -class DiagramItem +class DiagramItem { public: - DiagramItem(DiagramItem *p,int number,const ClassDef *cd, + DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, Protection prot,Specifier virt,const char *ts); - ~DiagramItem(); QCString label() const; QCString fileName() const; - DiagramItem *parentItem() { return parent; } - DiagramItemList *getChildren() { return children; } - void move(int dx,int dy) { x+=dx; y+=dy; } - int xPos() const { return x; } - int yPos() const { return y; } - int avgChildPos() const; - int numChildren() const; + DiagramItem *parentItem() { return m_parent; } + DiagramItemList getChildren() { return m_children; } + void move(int dx,int dy) { m_x+=(uint)dx; m_y+=(uint)dy; } + uint xPos() const { return m_x; } + uint yPos() const { return m_y; } + uint avgChildPos() const; + uint numChildren() const; void addChild(DiagramItem *di); - int number() const { return num; } - Protection protection() const { return prot; } - Specifier virtualness() const { return virt; } - void putInList() { inList=TRUE; } - bool isInList() const { return inList; } - const ClassDef *getClassDef() const { return classDef; } + uint number() const { return m_num; } + Protection protection() const { return m_prot; } + Specifier virtualness() const { return m_virt; } + void putInList() { m_inList=TRUE; } + bool isInList() const { return m_inList; } + const ClassDef *getClassDef() const { return m_classDef; } private: - DiagramItemList *children; - DiagramItem *parent; - int x,y; - int num; - Protection prot; - Specifier virt; - QCString templSpec; - bool inList; - const ClassDef *classDef; -}; - -/** Class representing a list of DiagramItem object. */ -class DiagramItemList : public QList<DiagramItem> -{ - public: - DiagramItemList() : QList<DiagramItem>() {} - ~DiagramItemList() {} + DiagramItemList m_children; + DiagramItem *m_parent; + uint m_x = 0; + uint m_y = 0; + uint m_num; + Protection m_prot; + Specifier m_virt; + QCString m_templSpec; + bool m_inList = false; + const ClassDef *m_classDef; }; /** Class representing a row in the built-in class diagram */ -class DiagramRow : public QList<DiagramItem> +class DiagramRow { public: - DiagramRow(TreeDiagram *d,int l) : QList<DiagramItem>() - { - diagram=d; - level=l; - setAutoDelete(TRUE); - } + using Ptr = std::unique_ptr<DiagramItem>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; + using reverse_iterator = typename Vec::reverse_iterator; + DiagramRow(TreeDiagram *d,uint l) : m_diagram(d), m_level(l) {} void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts); - uint number() { return level; } - private: - TreeDiagram *diagram; - uint level; -}; + uint number() { return m_level; } -/** Class representing iterator for the rows in the built-in class diagram. */ -class DiagramRowIterator : public QListIterator<DiagramRow> -{ - public: - DiagramRowIterator(const QList<DiagramRow> &d) - : QListIterator<DiagramRow>(d) {} + DiagramItem *item(int index) { return m_items.at(index).get(); } + uint numItems() const { return static_cast<uint>(m_items.size()); } + iterator begin() { return m_items.begin(); } + iterator end() { return m_items.end(); } + reverse_iterator rbegin() { return m_items.rbegin(); } + reverse_iterator rend() { return m_items.rend(); } + private: + TreeDiagram *m_diagram; + uint m_level; + Vec m_items; }; /** Class representing the tree layout for the built-in class diagram. */ -class TreeDiagram : public QList<DiagramRow> +class TreeDiagram { public: + using Ptr = std::unique_ptr<DiagramRow>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; TreeDiagram(const ClassDef *root,bool doBases); - ~TreeDiagram(); void computeLayout(); uint computeRows(); - //uint computeCols(); void moveChildren(DiagramItem *root,int dx); void computeExtremes(uint *labelWidth,uint *xpos); void drawBoxes(FTextStream &t,Image *image, @@ -128,10 +119,17 @@ class TreeDiagram : public QList<DiagramRow> bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellheight); + DiagramRow *row(int index) { return m_rows.at(index).get(); } + uint numRows() const { return static_cast<uint>(m_rows.size()); } + DiagramRow *addRow(uint l) + { m_rows.push_back(std::make_unique<DiagramRow>(this,l)); return m_rows.back().get(); } + iterator begin() { return m_rows.begin(); } + iterator end() { return m_rows.end(); } private: - bool layoutTree(DiagramItem *root,int row); + bool layoutTree(DiagramItem *root,uint row); TreeDiagram &operator=(const TreeDiagram &); TreeDiagram(const TreeDiagram &); + Vec m_rows; }; @@ -139,26 +137,14 @@ class TreeDiagram : public QList<DiagramRow> //----------------------------------------------------------------------------- const uint maxTreeWidth = 8; -const int gridWidth = 100; -const int gridHeight = 100; +const uint gridWidth = 100; +const uint gridHeight = 100; const uint labelHorSpacing = 10; // horizontal distance between labels const uint labelVertSpacing = 32; // vertical distance between labels const uint labelHorMargin = 6; // horiz. spacing between label and box const uint fontHeight = 12; // height of a character -//static QCString escapeLatex(const char *s) -//{ -// QCString result; -// char c; -// while ((c=*s++)) -// { -// if (c=='_') result+="\\_"; -// else result+=c; -// } -// return result; -//} - static uint protToMask(Protection p) { switch(p) @@ -171,7 +157,7 @@ static uint protToMask(Protection p) return 0; } -static uint protToColor(Protection p) +static uchar protToColor(Protection p) { switch(p) { @@ -207,39 +193,44 @@ static uint virtToMask(Specifier p) } // pre: dil is not empty -static Protection getMinProtectionLevel(DiagramItemList *dil) +static Protection getMinProtectionLevel(const DiagramItemList &dil) { - QListIterator<DiagramItem> it(*dil); - DiagramItem *di=it.current(); - Protection result=di->protection(); - for (++it;(di=it.current());++it) + auto it = dil.begin(); + Protection result = Private; + if (it!=dil.end()) { - Protection p=di->protection(); - if (p!=result) + result=(*it)->protection(); + for (++it;it!=dil.end();++it) { - if (result==Protected && p==Public) result=p; - else if (result==Private) result=p; + Protection p=(*it)->protection(); + if (p!=result) + { + if (result==Protected && p==Public) result=p; + else if (result==Private) result=p; + } } } return result; } static void writeBitmapBox(DiagramItem *di,Image *image, - int x,int y,int w,int h,bool firstRow, + uint x,uint y,uint w,uint h,bool firstRow, bool hasDocs,bool children=FALSE) { - int colFill = hasDocs ? (firstRow ? 0 : 2) : 7; - int colBorder = (firstRow || !hasDocs) ? 1 : 3; - int l = Image::stringLength(di->label()); + uchar colFill = hasDocs ? (firstRow ? 0 : 2) : 7; + uchar colBorder = (firstRow || !hasDocs) ? 1 : 3; + uint l = Image::stringLength(di->label()); uint mask=virtToMask(di->virtualness()); image->fillRect(x+1,y+1,w-2,h-2,colFill,mask); image->drawRect(x,y,w,h,colBorder,mask); image->writeString(x+(w-l)/2, y+(h-fontHeight)/2, di->label(),1); if (children) { - int i; + uint i; for (i=0;i<5;i++) + { image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff); + } } } @@ -253,15 +244,15 @@ static void writeVectorBox(FTextStream &t,DiagramItem *di, } static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, - int x,int y,int w,int h) + uint x,uint y,uint w,uint h) { if (cd->isLinkable()) { QCString ref=cd->getReference(); t << "<area "; - if (!ref.isEmpty()) + if (!ref.isEmpty()) { - t << externalLinkTarget(); + t << externalLinkTarget(true); } t << "href=\""; t << externalRef(relPath,ref,TRUE); @@ -276,50 +267,36 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { t << "title=\"" << convertToHtml(tooltip) << "\" "; } - t << "alt=\"" << convertToXML(cd->displayName()); + t << "alt=\"" << convertToXML(cd->displayName()); t << "\" shape=\"rect\" coords=\"" << x << "," << y << ","; t << (x+w) << "," << (y+h) << "\"/>" << endl; } } //----------------------------------------------------------------------------- -DiagramItem::DiagramItem(DiagramItem *p,int number,const ClassDef *cd, - Protection pr,Specifier vi,const char *ts) -{ - parent=p; - x=y=0; - //name=n; - num=number; - children = new DiagramItemList; - prot=pr; - virt=vi; - inList=FALSE; - classDef=cd; - templSpec=ts; -} - -DiagramItem::~DiagramItem() -{ - delete children; +DiagramItem::DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, + Protection pr,Specifier vi,const char *ts) + : m_parent(p), m_num(number), m_prot(pr), m_virt(vi), m_templSpec(ts), m_classDef(cd) +{ } QCString DiagramItem::label() const { QCString result; - if (!templSpec.isEmpty()) + if (!m_templSpec.isEmpty()) { // we use classDef->name() here and not displayName() in order // to get the name used in the inheritance relation. - QCString n = classDef->name(); + QCString n = m_classDef->name(); if (/*n.right(2)=="-g" ||*/ n.right(2)=="-p") { n = n.left(n.length()-2); } - result=insertTemplateSpecifierInScope(n,templSpec); + result=insertTemplateSpecifierInScope(n,m_templSpec); } else { - result=classDef->displayName(); + result=m_classDef->displayName(); } if (Config_getBool(HIDE_SCOPE_NAMES)) result=stripScope(result); return result; @@ -327,146 +304,129 @@ QCString DiagramItem::label() const QCString DiagramItem::fileName() const { - return classDef->getOutputFileBase(); + return m_classDef->getOutputFileBase(); } -int DiagramItem::avgChildPos() const +uint DiagramItem::avgChildPos() const { DiagramItem *di; - int c=children->count(); + size_t c=m_children.size(); if (c==0) // no children -> don't move return xPos(); - if ((di=children->getFirst())->isInList()) // children should be in a list + if ((di=m_children.front())->isInList()) // children should be in a list return di->xPos(); if (c&1) // odd number of children -> get pos of middle child - return children->at(c/2)->xPos(); + return m_children.at(c/2)->xPos(); else // even number of children -> get middle of most middle children - return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2; + return (m_children.at(c/2-1)->xPos()+m_children.at(c/2)->xPos())/2; } -int DiagramItem::numChildren() const +uint DiagramItem::numChildren() const { - return children->count(); + return static_cast<uint>(m_children.size()); } void DiagramItem::addChild(DiagramItem *di) { - children->append(di); + m_children.push_back(di); } +//--------------------------------------------------------------------------- + void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts) { - //if (cd->visited) return; // the visit check does not work in case of - // multiple inheritance of the same class! - DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(), - cd,prot,virt,ts); - //cd->visited=TRUE; - if (parent) parent->addChild(di); - di->move(count()*gridWidth,level*gridHeight); - append(di); - BaseClassList *bcl=doBases ? cd->baseClasses() : cd->subClasses(); + auto di = std::make_unique<DiagramItem>(parent, m_diagram->row(m_level)->numItems(), + cd,prot,virt,ts); + DiagramItem *di_ptr = di.get(); + if (parent) parent->addChild(di_ptr); + di->move((int)(m_items.size()*gridWidth),(int)(m_level*gridHeight)); + m_items.push_back(std::move(di)); int count=0; - if (bcl) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { /* there are base/sub classes */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) - { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++; - } + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy()) count++; } if (count>0 && (prot!=Private || !doBases)) { DiagramRow *row=0; - if (diagram->count()<=level+1) /* add new row */ + if (m_diagram->numRows()<=m_level+1) /* add new row */ { - row = new DiagramRow(diagram,level+1); - diagram->append(row); + row=m_diagram->addRow(m_level+1); } else /* get next row */ { - row=diagram->at(level+1); + row=m_diagram->row(m_level+1); } - /* insert base classes in the next row */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy()) { - row->insertClass(di,ccd,doBases,bcd->prot, - doBases?bcd->virt:Normal, - doBases?bcd->templSpecifiers.data():""); + row->insertClass(di_ptr,ccd,doBases,bcd.prot, + doBases?bcd.virt:Normal, + doBases?bcd.templSpecifiers.data():""); } } } } -TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) -{ - setAutoDelete(TRUE); - DiagramRow *row=new DiagramRow(this,0); - append(row); - row->insertClass(0,root,doBases,Public,Normal,0); -} +//--------------------------------------------------------------------------- -TreeDiagram::~TreeDiagram() +TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) { + auto row = std::make_unique<DiagramRow>(this,0); + DiagramRow *row_ptr = row.get(); + m_rows.push_back(std::move(row)); + row_ptr->insertClass(0,root,doBases,Public,Normal,0); } - void TreeDiagram::moveChildren(DiagramItem *root,int dx) { - DiagramItemList *dil=root->getChildren(); - QListIterator<DiagramItem> it(*dil); - DiagramItem *di; - for (;(di=it.current());++it) + for (const auto &di : root->getChildren()) { di->move(dx,0); moveChildren(di,dx); } } -bool TreeDiagram::layoutTree(DiagramItem *root,int r) +bool TreeDiagram::layoutTree(DiagramItem *root,uint r) { bool moved=FALSE; //printf("layoutTree(%s,%d)\n",root->label().data(),r); - DiagramItemList *dil=root->getChildren(); - if (dil->count()>0) + if (root->numChildren()>0) { + auto children = root->getChildren(); uint k; - int pPos=root->xPos(); - int cPos=root->avgChildPos(); + uint pPos=root->xPos(); + uint cPos=root->avgChildPos(); if (pPos>cPos) // move children { - DiagramRow *row=at(r+1); + const auto &row=m_rows.at(r+1); //printf("Moving children %d-%d in row %d\n", // dil->getFirst()->number(),row->count()-1,r+1); - for (k=dil->getFirst()->number();k<row->count();k++) - row->at(k)->move(pPos-cPos,0); + for (k=children.front()->number();k<row->numItems();k++) + row->item(k)->move((int)(pPos-cPos),0); moved=TRUE; } else if (pPos<cPos) // move parent { - DiagramRow *row=at(r); + const auto &row=m_rows.at(r); //printf("Moving parents %d-%d in row %d\n", // root->number(),row->count()-1,r); - for (k=root->number();k<row->count();k++) - row->at(k)->move(cPos-pPos,0); + for (k=root->number();k<row->numItems();k++) + row->item(k)->move((int)(cPos-pPos),0); moved=TRUE; } // recurse to children - QListIterator<DiagramItem> it(*dil); - DiagramItem *di; - for (;(di=it.current()) && !moved && !di->isInList();++it) + auto it = children.begin(); + for (;it!=children.end() && !moved && !(*it)->isInList();++it) { - moved = layoutTree(di,r+1); + moved = layoutTree(*it,r+1); } } return moved; @@ -474,18 +434,16 @@ bool TreeDiagram::layoutTree(DiagramItem *root,int r) void TreeDiagram::computeLayout() { - QListIterator<DiagramRow> it(*this); - DiagramRow *row; - for (;(row=it.current()) && row->count()<maxTreeWidth;++it) {} - if (row) + auto it = m_rows.begin(); + while (it!=m_rows.end() && (*it)->numItems()<maxTreeWidth) ++it; + if (it!=m_rows.end()) { + const auto &row = *it; //printf("computeLayout() list row at %d\n",row->number()); - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; DiagramItem *opi=0; int delta=0; bool first=TRUE; - for (;(di=rit.current());++rit) + for (const auto &di : *row) { DiagramItem *pi=di->parentItem(); if (pi==opi && !first) { delta-=gridWidth; } @@ -498,21 +456,24 @@ void TreeDiagram::computeLayout() } // re-organize the diagram items - DiagramItem *root=getFirst()->getFirst(); + DiagramItem *root=m_rows.front()->item(0); while (layoutTree(root,0)) { } // move first items of the lists - if (row) + if (it!=m_rows.end()) { - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; - while ((di=rit.current())) + const auto &row = *it; + auto rit = row->begin(); + while (rit!=row->end()) { - DiagramItem *pi=di->parentItem(); - if (pi->getChildren()->count()>1) + DiagramItem *pi=(*rit)->parentItem(); + if (pi->numChildren()>1) { - di->move(gridWidth,0); - while (di && di->parentItem()==pi) { ++rit; di=rit.current(); } + (*rit)->move(gridWidth,0); + while (rit!=row->end() && (*rit)->parentItem()==pi) + { + ++rit; + } } else { @@ -525,24 +486,24 @@ void TreeDiagram::computeLayout() uint TreeDiagram::computeRows() { //printf("TreeDiagram::computeRows()=%d\n",count()); - int count=0; - QListIterator<DiagramRow> it(*this); - DiagramRow *row; - for (;(row=it.current()) && !row->getFirst()->isInList();++it) + uint count=0; + auto it = m_rows.begin(); + while (it!=m_rows.end() && !(*it)->item(0)->isInList()) { - count++; + ++it; + ++count; } + //printf("count=%d row=%p\n",count,row); - if (row) + if (it!=m_rows.end()) { - int maxListLen=0; - int curListLen=0; + const auto &row = *it; + uint maxListLen=0; + uint curListLen=0; DiagramItem *opi=0; - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; - for (;(di=rit.current());++rit) + for (const auto &di : *row) // for each item in a row { - if (di->parentItem()!=opi) curListLen=1; else curListLen++; + if (di->parentItem()!=opi) curListLen=1; else curListLen++; if (curListLen>maxListLen) maxListLen=curListLen; opi=di->parentItem(); } @@ -555,48 +516,80 @@ uint TreeDiagram::computeRows() void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos) { uint ml=0,mx=0; - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; - bool done=FALSE; - for (;(dr=it.current()) && !done;++it) + for (const auto &dr : m_rows) // for each row { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + bool done=FALSE; + for (const auto &di : *dr) // for each item in a row { if (di->isInList()) done=TRUE; if (maxXPos) mx=QMAX(mx,(uint)di->xPos()); if (maxLabelLen) ml=QMAX(ml,Image::stringLength(di->label())); } + if (done) break; } if (maxLabelLen) *maxLabelLen=ml; if (maxXPos) *maxXPos=mx; } -void TreeDiagram::drawBoxes(FTextStream &t,Image *image, +//! helper class representing an iterator that can iterate forwards or backwards +template<class C,class I> +class DualDirIterator +{ + public: + DualDirIterator(C &container,bool fwd) + : m_container(container), m_forward(fwd) + { + if (fwd) m_it = container.begin(); + else m_rit = container.rbegin(); + } + void operator++() + { + if (m_forward) ++m_it++; else ++m_rit; + } + I &operator*() + { + return m_forward ? *m_it : *m_rit; + } + + bool atEnd() + { + if (m_forward) + return m_it==m_container.end(); + else + return m_rit==m_container.rend(); + } + + private: + C &m_container; + bool m_forward; + typename C::iterator m_it; + typename C::reverse_iterator m_rit; +}; + +void TreeDiagram::drawBoxes(FTextStream &t,Image *image, bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellHeight, QCString relPath, bool generateMap) { - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; - if (!doBase) ++it; - bool done=FALSE; + auto it = m_rows.begin(); + if (it!=m_rows.end() && !doBase) ++it; bool firstRow = doBase; - for (;(dr=it.current()) && !done;++it) + bool done=FALSE; + for (;it!=m_rows.end() && !done;++it) // for each row { - int x=0,y=0; + const auto &dr = *it; + uint x=0,y=0; float xf=0.0f,yf=0.0f; - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di = rit.current(); - if (di->isInList()) // put boxes in a list + DiagramItem *firstDi = dr->item(0); + if (firstDi->isInList()) // put boxes in a list { DiagramItem *opi=0; - if (doBase) rit.toLast(); else rit.toFirst(); - while ((di=rit.current())) + DualDirIterator<DiagramRow,const std::unique_ptr<DiagramItem>&> dit(*dr,!doBase); + while (!dit.atEnd()) { + DiagramItem *di = (*dit).get(); if (di->parentItem()==opi) { if (bitmap) @@ -617,7 +610,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth; if (doBase) { - y = image->getHeight()- + y = image->height()- superRows*cellHeight- (superRows-1)*labelVertSpacing- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; @@ -642,34 +635,34 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, } } opi=di->parentItem(); - + if (bitmap) { bool hasDocs=di->getClassDef()->isLinkable(); writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow, - hasDocs,di->getChildren()->count()>0); - if (!firstRow && generateMap) + hasDocs,di->numChildren()>0); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else { - writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0); + writeVectorBox(t,di,xf,yf,di->numChildren()>0); } - - if (doBase) --rit; else ++rit; + + ++dit; } done=TRUE; } else // draw a tree of boxes { - for (rit.toFirst();(di=rit.current());++rit) + for (const auto &di : *dr) { if (bitmap) { x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth; if (doBase) { - y = image->getHeight()- + y = image->height()- superRows*cellHeight- (superRows-1)*labelVertSpacing- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; @@ -680,8 +673,8 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; } bool hasDocs=di->getClassDef()->isLinkable(); - writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); - if (!firstRow && generateMap) + writeBitmapBox(di.get(),image,x,y,cellWidth,cellHeight,firstRow,hasDocs); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else @@ -695,7 +688,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, { yf = superRows-1-di->yPos()/(float)gridHeight; } - writeVectorBox(t,di,xf,yf); + writeVectorBox(t,di.get(),xf,yf); } } } @@ -708,22 +701,23 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, uint baseRows,uint superRows, uint cellWidth,uint cellHeight) { - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; bool done=FALSE; - for (;(dr=it.current()) && !done;++it) // for each row + auto it = m_rows.begin(); + for (;it!=m_rows.end() && !done;++it) // for each row { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di = rit.current(); - if (di->isInList()) // row consists of list connectors + const auto &dr = *it; + DiagramItem *rootDi = dr->item(0); + if (rootDi->isInList()) // row consists of list connectors { - int x=0,y=0,ys=0; + uint x=0,y=0,ys=0; float xf=0.0f,yf=0.0f,ysf=0.0f; - for (;(di=rit.current());++rit) + auto rit = dr->begin(); + while (rit!=dr->end()) { + DiagramItem *di=(*rit).get(); DiagramItem *pi=di->parentItem(); - DiagramItemList *dil=pi->getChildren(); - DiagramItem *last=dil->getLast(); + DiagramItemList dil=pi->getChildren(); + DiagramItem *last=dil.back(); if (di==last) // single child { if (bitmap) // draw pixels @@ -731,7 +725,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { - y = image->getHeight()- + y = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; image->drawVertArrow(x,y,y+labelVertSpacing/2, @@ -753,13 +747,13 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << (di->xPos()/(float)gridWidth) << " " + t << "1 " << (di->xPos()/(float)gridWidth) << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << (di->xPos()/(float)gridWidth) << " " - << ((float)superRows-0.25-di->yPos()/(float)gridHeight) + t << "0 " << (di->xPos()/(float)gridWidth) << " " + << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } } @@ -772,7 +766,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, (cellWidth+labelHorSpacing)/gridWidth+cellWidth/2; if (doBase) // base classes { - ys = image->getHeight()- + ys = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; y = ys - cellHeight/2; @@ -831,7 +825,8 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, yf -= 1.0f; } } - ++rit; di=rit.current(); + ++rit; + if (rit!=dr->end()) di = (*rit).get(); else di=0; } // add last horizontal line and a vertical connection line if (bitmap) @@ -873,19 +868,20 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } else { - t << xf << " " << (ysf + 0.25) << " " << yf << " vedge\n"; + t << xf << " " << (ysf + 0.25f) << " " << yf << " vedge\n"; } } } + if (rit!=dr->end()) ++rit; } done=TRUE; // the tree is drawn now } else // normal tree connector { - for (;(di=rit.current());++rit) + for (const auto &di : *dr) { - int x=0,y=0; - DiagramItemList *dil = di->getChildren(); + uint x=0,y=0; + DiagramItemList dil = di->getChildren(); DiagramItem *parent = di->parentItem(); if (parent) // item has a parent -> connect to it { @@ -894,7 +890,7 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { - y = image->getHeight()- + y = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; /* write input line */ @@ -918,28 +914,28 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << di->xPos()/(float)gridWidth << " " - << ((float)superRows-0.25-di->yPos()/(float)gridHeight) + t << "0 " << di->xPos()/(float)gridWidth << " " + << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } } } - if (dil->count()>0) + if (!dil.empty()) { Protection p=getMinProtectionLevel(dil); uint mask=protToMask(p); - uint col=protToColor(p); + uchar col=protToColor(p); if (bitmap) { x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; if (doBase) // base classes { - y = image->getHeight()- + y = image->height()- (superRows-1)*(cellHeight+labelVertSpacing)- cellHeight-labelVertSpacing/2- di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; @@ -958,34 +954,34 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " out\n"; } else { - t << "1 " << di->xPos()/(float)gridWidth << " " - << ((float)superRows-1.75-di->yPos()/(float)gridHeight) + t << "1 " << di->xPos()/(float)gridWidth << " " + << ((float)superRows-1.75f-di->yPos()/(float)gridHeight) << " out\n"; } } /* write input line */ - DiagramItem *first = dil->getFirst(); - DiagramItem *last = dil->getLast(); + DiagramItem *first = dil.front(); + DiagramItem *last = dil.back(); if (first!=last && !first->isInList()) /* connect with all base classes */ { if (bitmap) { - int xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + uint xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + + cellWidth/2; + uint xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; - int xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth - + cellWidth/2; if (doBase) // base classes { - image->drawHorzLine(y,xs,xe,col,mask); + image->drawHorzLine(y,xs,xe,col,mask); } else // super classes { - image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); + image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); } } else @@ -993,14 +989,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " - << (first->yPos()/(float)gridHeight+superRows-1) + << (first->yPos()/(float)gridHeight+superRows-1) << " conn\n"; } else { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " << ((float)superRows-first->yPos()/(float)gridHeight) << " conn\n"; @@ -1013,74 +1009,69 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } } +//----------------------------------------------------------------- -void clearVisitFlags() +struct ClassDiagram::Private { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) - { - cd->setVisited(FALSE); - } -} + Private(const ClassDef *root) : base(root,true), super(root,false) {} + TreeDiagram base; + TreeDiagram super; +}; + +//----------------------------------------------------------------- + -ClassDiagram::ClassDiagram(const ClassDef *root) +ClassDiagram::ClassDiagram(const ClassDef *root) : p(std::make_unique<Private>(root)) { - clearVisitFlags(); - base = new TreeDiagram(root,TRUE); - base->computeLayout(); - clearVisitFlags(); - super = new TreeDiagram(root,FALSE); - super->computeLayout(); - DiagramItem *baseItem = base->getFirst()->getFirst(); - DiagramItem *superItem = super->getFirst()->getFirst(); - int xbase = baseItem->xPos(); - int xsuper = superItem->xPos(); + p->base.computeLayout(); + p->super.computeLayout(); + DiagramItem *baseItem = p->base.row(0)->item(0); + DiagramItem *superItem = p->super.row(0)->item(0); + uint xbase = baseItem->xPos(); + uint xsuper = superItem->xPos(); if (xbase>xsuper) { - superItem->move(xbase-xsuper,0); - super->moveChildren(superItem,xbase-xsuper); + superItem->move((int)(xbase-xsuper),0); + p->super.moveChildren(superItem,(int)(xbase-xsuper)); } else if (xbase<xsuper) { - baseItem->move(xsuper-xbase,0); - base->moveChildren(baseItem,xsuper-xbase); + baseItem->move((int)(xsuper-xbase),0); + p->base.moveChildren(baseItem,(int)(xsuper-xbase)); } } ClassDiagram::~ClassDiagram() { - delete base; - delete super; } void ClassDiagram::writeFigure(FTextStream &output,const char *path, const char *fileName) const { - uint baseRows=base->computeRows(); - uint superRows=super->computeRows(); + uint baseRows=p->base.computeRows(); + uint superRows=p->super.computeRows(); uint baseMaxX, baseMaxLabelWidth, superMaxX, superMaxLabelWidth; - base->computeExtremes(&baseMaxLabelWidth,&baseMaxX); - super->computeExtremes(&superMaxLabelWidth,&superMaxX); + p->base.computeExtremes(&baseMaxLabelWidth,&baseMaxX); + p->super.computeExtremes(&superMaxLabelWidth,&superMaxX); - uint rows=baseRows+superRows-1; + uint rows=QMAX(1,baseRows+superRows-1); uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth; - + // Estimate the image aspect width and height in pixels. uint estHeight = rows*40; uint estWidth = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth)); //printf("Estimated size %d x %d\n",estWidth,estHeight); - + const float pageWidth = 14.0f; // estimated page width in cm. // Somewhat lower to deal with estimation - // errors. - + // errors. + // compute the image height in centimeters based on the estimates float realHeight = QMIN(rows,12); // real height in cm float realWidth = realHeight * estWidth/(float)estHeight; if (realWidth>pageWidth) // assume that the page width is about 15 cm { - realHeight*=pageWidth/realWidth; + realHeight*=pageWidth/realWidth; realWidth=pageWidth; } @@ -1088,11 +1079,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, output << "\\begin{figure}[H]\n" "\\begin{center}\n" "\\leavevmode\n"; - output << "\\includegraphics[height=" << realHeight << "cm]{" + output << "\\includegraphics[height=" << realHeight << "cm]{" << fileName << "}" << endl; output << "\\end{center}\n" "\\end{figure}\n"; - + //printf("writeFigure rows=%d cols=%d\n",rows,cols); QCString epsBaseName=(QCString)path+"/"+fileName; @@ -1104,11 +1095,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, term("Could not open file %s for writing\n",f1.name().data()); } FTextStream t(&f1); - + //printf("writeEPS() rows=%d cols=%d\n",rows,cols); - + // generate EPS header and postscript variables and procedures - + t << "%!PS-Adobe-2.0 EPSF-2.0\n"; t << "%%Title: ClassName\n"; t << "%%Creator: Doxygen\n"; @@ -1116,7 +1107,7 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, t << "%%For: \n"; t << "%Magnification: 1.00\n"; t << "%%Orientation: Portrait\n"; - t << "%%BoundingBox: 0 0 500 " << estHeight*500.0/(float)estWidth << "\n"; + t << "%%BoundingBox: 0 0 500 " << estHeight*500.0f/(float)estWidth << "\n"; t << "%%Pages: 0\n"; t << "%%BeginSetup\n"; t << "%%EndSetup\n"; @@ -1286,31 +1277,29 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, t << "1 boundaspect scale\n"; - bool done=FALSE; - QListIterator<DiagramRow> bit(*base); - DiagramRow *dr; - for (;(dr=bit.current()) && !done;++bit) + for (const auto &dr : p->base) { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + bool done=FALSE; + for (const auto &di : *dr) { done=di->isInList(); t << "(" << convertToPSString(di->label()) << ") cw\n"; } + if (done) break; } - QListIterator<DiagramRow> sit(*super); - ++sit; - done=FALSE; - for (;(dr=sit.current()) && !done;++sit) + + auto it = p->super.begin(); + if (it!=p->super.end()) ++it; + for (;it!=p->super.end();++it) { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + const auto &dr = *it; + bool done=FALSE; + for (const auto &di : *dr) { done=di->isInList(); t << "(" << convertToPSString(di->label()) << ") cw\n"; } + if (done) break; } t << "/boxwidth boxwidth marginwidth 2 mul add def\n" @@ -1321,14 +1310,14 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n" << " max def\n" << "boundx scalefactor div boundy scalefactor div scale\n"; - + t << "\n% ----- classes -----\n\n"; - base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); - super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); - + p->base.drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); + p->super.drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); + t << "\n% ----- relations -----\n\n"; - base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); - super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); + p->base.drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); + p->super.drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); f1.close(); if (Config_getBool(USE_PDFLATEX)) @@ -1350,17 +1339,17 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, void ClassDiagram::writeImage(FTextStream &t,const char *path, - const char *relPath,const char *fileName, + const char *relPath,const char *fileName, bool generateMap) const { - uint baseRows=base->computeRows(); - uint superRows=super->computeRows(); + uint baseRows=p->base.computeRows(); + uint superRows=p->super.computeRows(); uint rows=baseRows+superRows-1; uint lb,ls,xb,xs; - base->computeExtremes(&lb,&xb); - super->computeExtremes(&ls,&xs); - + p->base.computeExtremes(&lb,&xb); + p->super.computeExtremes(&ls,&xs); + uint cellWidth = QMAX(lb,ls)+labelHorMargin*2; uint maxXPos = QMAX(xb,xs); uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3 @@ -1371,10 +1360,10 @@ void ClassDiagram::writeImage(FTextStream &t,const char *path, Image image(imageWidth,imageHeight); - base->drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); - super->drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); - base->drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight); - super->drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight); + p->base.drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); + p->super.drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); + p->base.drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight); + p->super.drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight); #define IMAGE_EXT ".png" image.save((QCString)path+"/"+fileName+IMAGE_EXT); |