📄 diagram.cpp
字号:
/****************************************************************************** * * $Id: diagram.cpp,v 1.30 2001/03/19 19:27:40 root Exp $ * * * Copyright (C) 1997-2001 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 * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */#include "qtbc.h"#include <stdio.h>#include <stdlib.h>#include <qlist.h>#include <qarray.h>#include <qtextstream.h>#include <qfile.h>#include "diagram.h"#include "image.h"#include "classdef.h"#include "config.h"#include "message.h"#include "util.h"#include "latexgen.h"#include "htmlgen.h"#include "doxygen.h"//-----------------------------------------------------------------------------const uint maxTreeWidth = 8;const int gridWidth = 100;const int gridHeight = 100;const uint labelHorSpacing = 10; // horizontal distance between labelsconst uint labelVertSpacing = 32; // vertical distance between labelsconst uint labelHorMargin = 6; // horiz. spacing between label and boxconst 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) { case Public: return 0xffffffff; case Protected: return 0xcccccccc; case Private: return 0xaaaaaaaa; } return 0;}static uint protToColor(Protection p){ switch(p) { case Public: return 6; case Protected: return 5; case Private: return 4; } return 0;}static QCString protToString(Protection p){ switch(p) { case Public: return "solid"; case Protected: return "dashed"; case Private: return "dotted"; } return 0;}static uint virtToMask(Specifier p){ switch(p) { case Normal: return 0xffffffff; case Virtual: return 0xf0f0f0f0; default: return 0; } return 0;}// pre: dil is not emptystatic Protection getMinProtectionLevel(DiagramItemList *dil){ DiagramItem *di=dil->first(); Protection result=di->protection(); di=dil->next(); while (di) { Protection p=di->protection(); if (p!=result) { if (result==Protected && p==Public) result=p; else if (result==Private) result=p; } di=dil->next(); } return result;}static void writeBitmapBox(DiagramItem *di,Image *image, int x,int y,int w,int 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()); 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; for (i=0;i<5;i++) image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff); }}static void writeVectorBox(QTextStream &t,DiagramItem *di, float x,float y,bool children=FALSE){ if (di->virtualness()==Virtual) t << "dashed\n"; t << " (" << di->label() << ") " << x << " " << y << " box\n"; if (children) t << x << " " << y << " mark\n"; if (di->virtualness()==Virtual) t << "solid\n";}static void writeMapArea(QTextStream &t,ClassDef *cd,int x,int y,int w,int h){ if (cd->isLinkable()) { QCString *dest; QCString ref=cd->getReference(); t << "<area "; if (!ref.isEmpty()) { t << "doxygen=\"" << ref << ":"; if ((dest=Doxygen::tagDestinationDict[ref])) t << *dest << "/"; t << "\" "; } t << "href=\""; if (!ref.isEmpty()) { if ((dest=Doxygen::tagDestinationDict[ref])) t << *dest << "/"; } t << cd->getOutputFileBase() << ".html\" "; t << "alt=\"" << cd->name(); t << "\" shape=\"rect\" coords=\"" << x << "," << y << ","; t << (x+w) << "," << (y+h) << "\">" << endl; }}//-----------------------------------------------------------------------------DiagramItem::DiagramItem(DiagramItem *p,int number,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;}QCString DiagramItem::label() const{ QCString result; if (!templSpec.isEmpty()) { result=insertTemplateSpecifierInScope(classDef->name(),templSpec); } else { result=classDef->name(); } if (Config_getBool("HIDE_SCOPE_NAMES")) result=stripScope(result); return result;}QCString DiagramItem::fileName() const{ return classDef->getOutputFileBase();}int DiagramItem::avgChildPos() const{ DiagramItem *di; int c=children->count(); if (c==0) // no children -> don't move return xPos(); if ((di=children->getFirst())->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(); else // even number of children -> get middle of most middle children return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2;}int DiagramItem::numChildren() const{ return children->count();}void DiagramItem::addChild(DiagramItem *di){ children->append(di);}void DiagramRow::insertClass(DiagramItem *parent,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(); /* there are base/sub classes */ int count=0; BaseClassDef *bcd=bcl->first(); while (bcd) { ClassDef *ccd=bcd->classDef; if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++; bcd=bcl->next(); } if (count>0 && (prot!=Private || !doBases)) { DiagramRow *row=0; if (diagram->count()<=level+1) /* add new row */ { row = new DiagramRow(diagram,level+1); diagram->append(row); } else /* get next row */ { row=diagram->at(level+1); } /* insert base classes in the next row */ BaseClassDef *bcd=bcl->first(); while (bcd) { ClassDef *ccd=bcd->classDef; if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) { row->insertClass(di,ccd,doBases,bcd->prot, doBases?bcd->virt:Normal, doBases?bcd->templSpecifiers.data():""); } bcd=bcl->next(); } }}TreeDiagram::TreeDiagram(ClassDef *root,bool doBases){ setAutoDelete(TRUE); DiagramRow *row=new DiagramRow(this,0); append(row); row->insertClass(0,root,doBases,Public,Normal,0);}TreeDiagram::~TreeDiagram(){}void TreeDiagram::moveChildren(DiagramItem *root,int dx){ DiagramItemList *dil=root->getChildren(); DiagramItem *di=dil->first(); while (di) { di->move(dx,0); moveChildren(di,dx); di=dil->next(); }}bool TreeDiagram::layoutTree(DiagramItem *root,int r){ bool moved=FALSE; //printf("layoutTree(%s,%d)\n",root->label().data(),r); DiagramItemList *dil=root->getChildren(); if (dil->count()>0) { uint k; int pPos=root->xPos(); int cPos=root->avgChildPos(); if (pPos>cPos) // move children { DiagramRow *row=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); moved=TRUE; } else if (pPos<cPos) // move parent { DiagramRow *row=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); moved=TRUE; } // recurse to children DiagramItem *di=dil->first(); while (di && !moved && !di->isInList()) { moved = moved || layoutTree(di,r+1); di=dil->next(); } } return moved;}void TreeDiagram::computeLayout(){ DiagramRow *row=first(); while (row && row->count()<maxTreeWidth) row=next(); if (row) { //printf("computeLayout() list row at %d\n",row->number()); DiagramItem *di=row->first(); DiagramItem *opi=0; int delta=0; bool first=TRUE; while (di) { DiagramItem *pi=di->parentItem(); if (pi==opi && !first) { delta-=gridWidth; } first = pi!=opi; opi=pi; di->move(delta,0); // collapse all items in the same // list (except the first) di->putInList(); di=row->next(); } } // re-organize the diagram items DiagramItem *root=getFirst()->getFirst(); while (layoutTree(root,0)); // move first items of the lists if (row) { DiagramItem *di=row->first(); while (di) { DiagramItem *pi=di->parentItem(); if (pi->getChildren()->count()>1) { di->move(gridWidth,0); while (di && di->parentItem()==pi) di=row->next(); } else { di=row->next(); } } }}uint TreeDiagram::computeRows(){ //printf("TreeDiagram::computeRows()=%d\n",count()); int count=0; DiagramRow *row=first(); while (row && !row->getFirst()->isInList()) { count++; row=next(); } //printf("count=%d row=%p\n",count,row); if (row) { int maxListLen=0; int curListLen=0; DiagramItem *di=row->first(),*opi=0; while (di) { if (di->parentItem()!=opi) curListLen=1; else curListLen++; if (curListLen>maxListLen) maxListLen=curListLen; opi=di->parentItem(); di=row->next(); } //printf("maxListLen=%d\n",maxListLen); count+=maxListLen; } return count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -