Blame src/diagram.cpp

Packit 1c1d7e
/******************************************************************************
Packit 1c1d7e
 *
Packit 1c1d7e
 * 
Packit 1c1d7e
 *
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 1997-2015 by Dimitri van Heesch.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Permission to use, copy, modify, and distribute this software and its
Packit 1c1d7e
 * documentation under the terms of the GNU General Public License is hereby 
Packit 1c1d7e
 * granted. No representations are made about the suitability of this software 
Packit 1c1d7e
 * for any purpose. It is provided "as is" without express or implied warranty.
Packit 1c1d7e
 * See the GNU General Public License for more details.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Documents produced by Doxygen are derivative works derived from the
Packit 1c1d7e
 * input used in their production; they are not affected by this license.
Packit 1c1d7e
 *
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
#include <stdio.h>
Packit 1c1d7e
#include <stdlib.h>
Packit 1c1d7e
#include <qlist.h>
Packit 1c1d7e
#include <qarray.h>
Packit 1c1d7e
#include "ftextstream.h"
Packit 1c1d7e
#include <qfile.h>
Packit 1c1d7e
Packit 1c1d7e
#include "diagram.h"
Packit 1c1d7e
#include "image.h"
Packit 1c1d7e
#include "classdef.h"
Packit 1c1d7e
#include "config.h"
Packit 1c1d7e
#include "message.h"
Packit 1c1d7e
#include "util.h"
Packit 1c1d7e
#include "doxygen.h"
Packit 1c1d7e
#include "portable.h"
Packit 1c1d7e
#include "index.h"
Packit 1c1d7e
#include "classlist.h"
Packit 1c1d7e
Packit 1c1d7e
//-----------------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
class DiagramItemList;
Packit 1c1d7e
Packit 1c1d7e
/** Class representing a single node in the built-in class diagram */
Packit 1c1d7e
class DiagramItem 
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    DiagramItem(DiagramItem *p,int number,ClassDef *cd,
Packit 1c1d7e
                Protection prot,Specifier virt,const char *ts);
Packit 1c1d7e
   ~DiagramItem();
Packit 1c1d7e
    QCString label() const;
Packit 1c1d7e
    QCString fileName() const;
Packit 1c1d7e
    DiagramItem *parentItem() { return parent; } 
Packit 1c1d7e
    DiagramItemList *getChildren() { return children; }
Packit 1c1d7e
    void move(int dx,int dy) { x+=dx; y+=dy; }
Packit 1c1d7e
    int xPos() const { return x; }
Packit 1c1d7e
    int yPos() const { return y; }
Packit 1c1d7e
    int avgChildPos() const;
Packit 1c1d7e
    int numChildren() const;
Packit 1c1d7e
    void addChild(DiagramItem *di);
Packit 1c1d7e
    int number() const { return num; }
Packit 1c1d7e
    Protection protection() const { return prot; }
Packit 1c1d7e
    Specifier virtualness() const { return virt; }
Packit 1c1d7e
    void putInList() { inList=TRUE; }
Packit 1c1d7e
    bool isInList() const { return inList; } 
Packit 1c1d7e
    ClassDef *getClassDef() const { return classDef; }
Packit 1c1d7e
  private:
Packit 1c1d7e
    DiagramItemList *children;
Packit 1c1d7e
    DiagramItem *parent;
Packit 1c1d7e
    int x,y;
Packit 1c1d7e
    int num;
Packit 1c1d7e
    Protection prot;
Packit 1c1d7e
    Specifier virt;
Packit 1c1d7e
    QCString templSpec;
Packit 1c1d7e
    bool inList;
Packit 1c1d7e
    ClassDef *classDef;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/** Class representing a list of DiagramItem object. */
Packit 1c1d7e
class DiagramItemList : public QList<DiagramItem>
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    DiagramItemList() : QList<DiagramItem>() {}
Packit 1c1d7e
   ~DiagramItemList() {}
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/** Class representing a row in the built-in class diagram */
Packit 1c1d7e
class DiagramRow : public QList<DiagramItem> 
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    DiagramRow(TreeDiagram *d,int l) : QList<DiagramItem>() 
Packit 1c1d7e
    { 
Packit 1c1d7e
      diagram=d; 
Packit 1c1d7e
      level=l;
Packit 1c1d7e
      setAutoDelete(TRUE); 
Packit 1c1d7e
    }
Packit 1c1d7e
    void insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
Packit 1c1d7e
                     Protection prot,Specifier virt,const char *ts);
Packit 1c1d7e
    uint number() { return level; }
Packit 1c1d7e
  private:
Packit 1c1d7e
    TreeDiagram *diagram;
Packit 1c1d7e
    uint level;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/** Class representing iterator for the rows in the built-in class diagram. */
Packit 1c1d7e
class DiagramRowIterator : public QListIterator<DiagramRow>
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    DiagramRowIterator(const QList<DiagramRow> &d) 
Packit 1c1d7e
      : QListIterator<DiagramRow>(d) {}
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/** Class represeting the tree layout for the built-in class diagram. */
Packit 1c1d7e
class TreeDiagram : public QList<DiagramRow>
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    TreeDiagram(ClassDef *root,bool doBases);
Packit 1c1d7e
   ~TreeDiagram();
Packit 1c1d7e
    void computeLayout();
Packit 1c1d7e
    uint computeRows();
Packit 1c1d7e
    //uint computeCols();
Packit 1c1d7e
    void moveChildren(DiagramItem *root,int dx);
Packit 1c1d7e
    void computeExtremes(uint *labelWidth,uint *xpos);
Packit 1c1d7e
    void drawBoxes(FTextStream &t,Image *image,
Packit 1c1d7e
                   bool doBase,bool bitmap,
Packit 1c1d7e
                   uint baseRows,uint superRows,
Packit 1c1d7e
                   uint cellWidth,uint cellHeight,
Packit 1c1d7e
                   QCString relPath="",
Packit 1c1d7e
                   bool generateMap=TRUE);
Packit 1c1d7e
    void drawConnectors(FTextStream &t,Image *image,
Packit 1c1d7e
                   bool doBase,bool bitmap,
Packit 1c1d7e
                   uint baseRows,uint superRows,
Packit 1c1d7e
                   uint cellWidth,uint cellheight);
Packit 1c1d7e
  private:
Packit 1c1d7e
    bool layoutTree(DiagramItem *root,int row);
Packit 1c1d7e
    TreeDiagram &operator=(const TreeDiagram &);
Packit 1c1d7e
    TreeDiagram(const TreeDiagram &);
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
//-----------------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
const uint maxTreeWidth = 8;
Packit 1c1d7e
const int gridWidth  = 100;
Packit 1c1d7e
const int gridHeight = 100;
Packit 1c1d7e
Packit 1c1d7e
const uint labelHorSpacing  = 10;  // horizontal distance between labels
Packit 1c1d7e
const uint labelVertSpacing = 32;  // vertical distance between labels
Packit 1c1d7e
const uint labelHorMargin   = 6;   // horiz. spacing between label and box
Packit 1c1d7e
const uint fontHeight       = 12;  // height of a character
Packit 1c1d7e
Packit 1c1d7e
//static QCString escapeLatex(const char *s)
Packit 1c1d7e
//{
Packit 1c1d7e
//  QCString result;
Packit 1c1d7e
//  char c;
Packit 1c1d7e
//  while ((c=*s++))
Packit 1c1d7e
//  {
Packit 1c1d7e
//    if (c=='_') result+="\\_";
Packit 1c1d7e
//           else result+=c;
Packit 1c1d7e
//  }
Packit 1c1d7e
//  return result;
Packit 1c1d7e
//}
Packit 1c1d7e
Packit 1c1d7e
static uint protToMask(Protection p)
Packit 1c1d7e
{
Packit 1c1d7e
  switch(p)
Packit 1c1d7e
  {
Packit 1c1d7e
    case Public:    return 0xffffffff;
Packit 1c1d7e
    case Package: // package is not possible!
Packit 1c1d7e
    case Protected: return 0xcccccccc;
Packit 1c1d7e
    case Private:   return 0xaaaaaaaa;
Packit 1c1d7e
  }
Packit 1c1d7e
  return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static uint protToColor(Protection p)
Packit 1c1d7e
{
Packit 1c1d7e
  switch(p)
Packit 1c1d7e
  {
Packit 1c1d7e
    case Public:    return 6;
Packit 1c1d7e
    case Package: // package is not possible!
Packit 1c1d7e
    case Protected: return 5;
Packit 1c1d7e
    case Private:   return 4;
Packit 1c1d7e
  }
Packit 1c1d7e
  return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static QCString protToString(Protection p)
Packit 1c1d7e
{
Packit 1c1d7e
  switch(p)
Packit 1c1d7e
  {
Packit 1c1d7e
    case Public:    return "solid";
Packit 1c1d7e
    case Package: // package is not possible!
Packit 1c1d7e
    case Protected: return "dashed";
Packit 1c1d7e
    case Private:   return "dotted";
Packit 1c1d7e
  }
Packit 1c1d7e
  return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static uint virtToMask(Specifier p)
Packit 1c1d7e
{
Packit 1c1d7e
  switch(p)
Packit 1c1d7e
  {
Packit 1c1d7e
    case Normal:    return 0xffffffff;
Packit 1c1d7e
    case Virtual:   return 0xf0f0f0f0;
Packit 1c1d7e
    default:        return 0;
Packit 1c1d7e
  }
Packit 1c1d7e
  return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
// pre: dil is not empty
Packit 1c1d7e
static Protection getMinProtectionLevel(DiagramItemList *dil)
Packit 1c1d7e
{
Packit 1c1d7e
  QListIterator<DiagramItem> it(*dil);
Packit 1c1d7e
  DiagramItem *di=it.current();
Packit 1c1d7e
  Protection result=di->protection();
Packit 1c1d7e
  for (++it;(di=it.current());++it)
Packit 1c1d7e
  {
Packit 1c1d7e
    Protection p=di->protection();
Packit 1c1d7e
    if (p!=result)
Packit 1c1d7e
    {
Packit 1c1d7e
      if (result==Protected && p==Public) result=p;
Packit 1c1d7e
      else if (result==Private) result=p;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  return result;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void writeBitmapBox(DiagramItem *di,Image *image,
Packit 1c1d7e
                           int x,int y,int w,int h,bool firstRow,
Packit 1c1d7e
                           bool hasDocs,bool children=FALSE)
Packit 1c1d7e
{
Packit 1c1d7e
  int colFill = hasDocs ? (firstRow ? 0 : 2) : 7;
Packit 1c1d7e
  int colBorder = (firstRow || !hasDocs) ? 1 : 3;
Packit 1c1d7e
  int l = Image::stringLength(di->label());
Packit 1c1d7e
  uint mask=virtToMask(di->virtualness());
Packit 1c1d7e
  image->fillRect(x+1,y+1,w-2,h-2,colFill,mask);
Packit 1c1d7e
  image->drawRect(x,y,w,h,colBorder,mask);
Packit 1c1d7e
  image->writeString(x+(w-l)/2, y+(h-fontHeight)/2, di->label(),1);
Packit 1c1d7e
  if (children)
Packit 1c1d7e
  {
Packit 1c1d7e
    int i;
Packit 1c1d7e
    for (i=0;i<5;i++)
Packit 1c1d7e
      image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void writeVectorBox(FTextStream &t,DiagramItem *di,
Packit 1c1d7e
                           float x,float y,bool children=FALSE)
Packit 1c1d7e
{
Packit 1c1d7e
  if (di->virtualness()==Virtual) t << "dashed\n";
Packit 1c1d7e
  t << " (" << di->label() << ") " << x << " " << y << " box\n";
Packit 1c1d7e
  if (children) t << x << " " << y << " mark\n";
Packit 1c1d7e
  if (di->virtualness()==Virtual) t << "solid\n";
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void writeMapArea(FTextStream &t,ClassDef *cd,QCString relPath,
Packit 1c1d7e
                         int x,int y,int w,int h)
Packit 1c1d7e
{
Packit 1c1d7e
  if (cd->isLinkable())
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString ref=cd->getReference();
Packit 1c1d7e
    t << "
Packit 1c1d7e
    if (!ref.isEmpty()) 
Packit 1c1d7e
    {
Packit 1c1d7e
      t << externalLinkTarget() << externalRef(relPath,ref,FALSE);
Packit 1c1d7e
    }
Packit 1c1d7e
    t << "href=\"";
Packit 1c1d7e
    t << externalRef(relPath,ref,TRUE);
Packit 1c1d7e
    t << cd->getOutputFileBase() << Doxygen::htmlFileExtension;
Packit 1c1d7e
    if (!cd->anchor().isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      t << "#" << cd->anchor();
Packit 1c1d7e
    }
Packit 1c1d7e
    t << "\" ";
Packit 1c1d7e
    QCString tooltip = cd->briefDescriptionAsTooltip();
Packit 1c1d7e
    if (!tooltip.isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      t << "title=\"" << convertToHtml(tooltip) << "\" ";
Packit 1c1d7e
    }
Packit 1c1d7e
    t << "alt=\"" << convertToXML(cd->displayName()); 
Packit 1c1d7e
    t << "\" shape=\"rect\" coords=\"" << x << "," << y << ",";
Packit 1c1d7e
    t << (x+w) << "," << (y+h) << "\"/>" << endl;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
//-----------------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
DiagramItem::DiagramItem(DiagramItem *p,int number,ClassDef *cd,
Packit 1c1d7e
                         Protection pr,Specifier vi,const char *ts) 
Packit 1c1d7e
{ 
Packit 1c1d7e
  parent=p; 
Packit 1c1d7e
  x=y=0; 
Packit 1c1d7e
  //name=n;
Packit 1c1d7e
  num=number;
Packit 1c1d7e
  children = new DiagramItemList;
Packit 1c1d7e
  prot=pr;
Packit 1c1d7e
  virt=vi;
Packit 1c1d7e
  inList=FALSE;
Packit 1c1d7e
  classDef=cd;
Packit 1c1d7e
  templSpec=ts;
Packit 1c1d7e
}
Packit 1c1d7e
 
Packit 1c1d7e
DiagramItem::~DiagramItem() 
Packit 1c1d7e
{ 
Packit 1c1d7e
  delete children;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
QCString DiagramItem::label() const
Packit 1c1d7e
{
Packit 1c1d7e
  QCString result;
Packit 1c1d7e
  if (!templSpec.isEmpty())
Packit 1c1d7e
  {
Packit 1c1d7e
    // we use classDef->name() here and not diplayName() in order
Packit 1c1d7e
    // to get the name used in the inheritance relation.
Packit 1c1d7e
    QCString n = classDef->name();
Packit 1c1d7e
    if (/*n.right(2)=="-g" ||*/ n.right(2)=="-p")
Packit 1c1d7e
    {
Packit 1c1d7e
      n = n.left(n.length()-2);
Packit 1c1d7e
    }
Packit 1c1d7e
    result=insertTemplateSpecifierInScope(n,templSpec);
Packit 1c1d7e
  }
Packit 1c1d7e
  else
Packit 1c1d7e
  {
Packit 1c1d7e
    result=classDef->displayName();
Packit 1c1d7e
  }
Packit 1c1d7e
  if (Config_getBool(HIDE_SCOPE_NAMES)) result=stripScope(result);
Packit 1c1d7e
  return result;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
QCString DiagramItem::fileName() const
Packit 1c1d7e
{
Packit 1c1d7e
  return classDef->getOutputFileBase();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
int DiagramItem::avgChildPos() const
Packit 1c1d7e
{
Packit 1c1d7e
  DiagramItem *di;
Packit 1c1d7e
  int c=children->count();
Packit 1c1d7e
  if (c==0) // no children -> don't move
Packit 1c1d7e
    return xPos();
Packit 1c1d7e
  if ((di=children->getFirst())->isInList()) // children should be in a list
Packit 1c1d7e
    return di->xPos();
Packit 1c1d7e
  if (c&1) // odd number of children -> get pos of middle child
Packit 1c1d7e
    return children->at(c/2)->xPos();
Packit 1c1d7e
  else // even number of children -> get middle of most middle children
Packit 1c1d7e
    return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
int DiagramItem::numChildren() const
Packit 1c1d7e
{
Packit 1c1d7e
  return children->count();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void DiagramItem::addChild(DiagramItem *di)
Packit 1c1d7e
{
Packit 1c1d7e
  children->append(di);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
Packit 1c1d7e
                             Protection prot,Specifier virt,const char *ts)
Packit 1c1d7e
{
Packit 1c1d7e
  //if (cd->visited) return; // the visit check does not work in case of
Packit 1c1d7e
                             // multiple inheritance of the same class!
Packit 1c1d7e
  DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(), 
Packit 1c1d7e
                                  cd,prot,virt,ts);
Packit 1c1d7e
  //cd->visited=TRUE;
Packit 1c1d7e
  if (parent) parent->addChild(di);
Packit 1c1d7e
  di->move(count()*gridWidth,level*gridHeight);
Packit 1c1d7e
  append(di);
Packit 1c1d7e
  BaseClassList *bcl=doBases ? cd->baseClasses() : cd->subClasses();
Packit 1c1d7e
  int count=0;
Packit 1c1d7e
  if (bcl)
Packit 1c1d7e
  {
Packit 1c1d7e
    /* there are base/sub classes */
Packit 1c1d7e
    BaseClassListIterator it(*bcl);
Packit 1c1d7e
    BaseClassDef *bcd;
Packit 1c1d7e
    for (;(bcd=it.current());++it)
Packit 1c1d7e
    {
Packit 1c1d7e
      ClassDef *ccd=bcd->classDef;
Packit 1c1d7e
      if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  if (count>0 && (prot!=Private || !doBases))
Packit 1c1d7e
  {
Packit 1c1d7e
    DiagramRow *row=0;
Packit 1c1d7e
    if (diagram->count()<=level+1) /* add new row */
Packit 1c1d7e
    {
Packit 1c1d7e
      row = new DiagramRow(diagram,level+1);
Packit 1c1d7e
      diagram->append(row);
Packit 1c1d7e
    }
Packit 1c1d7e
    else /* get next row */
Packit 1c1d7e
    {
Packit 1c1d7e
      row=diagram->at(level+1);
Packit 1c1d7e
    }
Packit 1c1d7e
    /* insert base classes in the next row */
Packit 1c1d7e
    BaseClassListIterator it(*bcl);
Packit 1c1d7e
    BaseClassDef *bcd;
Packit 1c1d7e
    for (;(bcd=it.current());++it)
Packit 1c1d7e
    {
Packit 1c1d7e
      ClassDef *ccd=bcd->classDef;
Packit 1c1d7e
      if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/)
Packit 1c1d7e
      {
Packit 1c1d7e
        row->insertClass(di,ccd,doBases,bcd->prot,
Packit 1c1d7e
            doBases?bcd->virt:Normal,
Packit 1c1d7e
            doBases?bcd->templSpecifiers.data():"");
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
TreeDiagram::TreeDiagram(ClassDef *root,bool doBases)
Packit 1c1d7e
{
Packit 1c1d7e
  setAutoDelete(TRUE); 
Packit 1c1d7e
  DiagramRow *row=new DiagramRow(this,0);
Packit 1c1d7e
  append(row);
Packit 1c1d7e
  row->insertClass(0,root,doBases,Public,Normal,0);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
TreeDiagram::~TreeDiagram()
Packit 1c1d7e
{
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void TreeDiagram::moveChildren(DiagramItem *root,int dx)
Packit 1c1d7e
{
Packit 1c1d7e
  DiagramItemList *dil=root->getChildren();
Packit 1c1d7e
  QListIterator<DiagramItem> it(*dil);
Packit 1c1d7e
  DiagramItem *di;
Packit 1c1d7e
  for (;(di=it.current());++it)
Packit 1c1d7e
  {
Packit 1c1d7e
    di->move(dx,0);
Packit 1c1d7e
    moveChildren(di,dx);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
bool TreeDiagram::layoutTree(DiagramItem *root,int r)
Packit 1c1d7e
{
Packit 1c1d7e
  bool moved=FALSE;
Packit 1c1d7e
  //printf("layoutTree(%s,%d)\n",root->label().data(),r);
Packit 1c1d7e
Packit 1c1d7e
  DiagramItemList *dil=root->getChildren(); 
Packit 1c1d7e
  if (dil->count()>0)
Packit 1c1d7e
  {
Packit 1c1d7e
    uint k;
Packit 1c1d7e
    int pPos=root->xPos();
Packit 1c1d7e
    int cPos=root->avgChildPos();
Packit 1c1d7e
    if (pPos>cPos) // move children
Packit 1c1d7e
    {
Packit 1c1d7e
      DiagramRow *row=at(r+1);
Packit 1c1d7e
      //printf("Moving children %d-%d in row %d\n",
Packit 1c1d7e
      //    dil->getFirst()->number(),row->count()-1,r+1);
Packit 1c1d7e
      for (k=dil->getFirst()->number();k<row->count();k++)
Packit 1c1d7e
        row->at(k)->move(pPos-cPos,0);
Packit 1c1d7e
      moved=TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
    else if (pPos
Packit 1c1d7e
    {
Packit 1c1d7e
      DiagramRow *row=at(r);
Packit 1c1d7e
      //printf("Moving parents %d-%d in row %d\n",
Packit 1c1d7e
      //    root->number(),row->count()-1,r);
Packit 1c1d7e
      for (k=root->number();k<row->count();k++)
Packit 1c1d7e
        row->at(k)->move(cPos-pPos,0);
Packit 1c1d7e
      moved=TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    // recurse to children
Packit 1c1d7e
    QListIterator<DiagramItem> it(*dil);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    for (;(di=it.current()) && !moved && !di->isInList();++it)
Packit 1c1d7e
    {
Packit 1c1d7e
      moved = layoutTree(di,r+1);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  return moved;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void TreeDiagram::computeLayout()
Packit 1c1d7e
{
Packit 1c1d7e
  QListIterator<DiagramRow> it(*this);
Packit 1c1d7e
  DiagramRow *row;
Packit 1c1d7e
  for (;(row=it.current()) && row->count()
Packit 1c1d7e
  if (row)
Packit 1c1d7e
  {
Packit 1c1d7e
    //printf("computeLayout() list row at %d\n",row->number());
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*row);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    DiagramItem *opi=0;
Packit 1c1d7e
    int delta=0;
Packit 1c1d7e
    bool first=TRUE;
Packit 1c1d7e
    for (;(di=rit.current());++rit)
Packit 1c1d7e
    {
Packit 1c1d7e
      DiagramItem *pi=di->parentItem();
Packit 1c1d7e
      if (pi==opi && !first) { delta-=gridWidth; }
Packit 1c1d7e
      first = pi!=opi;
Packit 1c1d7e
      opi=pi;
Packit 1c1d7e
      di->move(delta,0); // collapse all items in the same
Packit 1c1d7e
                         // list (except the first)
Packit 1c1d7e
      di->putInList();
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // re-organize the diagram items
Packit 1c1d7e
  DiagramItem *root=getFirst()->getFirst();
Packit 1c1d7e
  while (layoutTree(root,0)) { }
Packit 1c1d7e
Packit 1c1d7e
  // move first items of the lists
Packit 1c1d7e
  if (row)
Packit 1c1d7e
  {
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*row);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    while ((di=rit.current()))
Packit 1c1d7e
    {
Packit 1c1d7e
      DiagramItem *pi=di->parentItem();
Packit 1c1d7e
      if (pi->getChildren()->count()>1)
Packit 1c1d7e
      {
Packit 1c1d7e
        di->move(gridWidth,0);
Packit 1c1d7e
        while (di && di->parentItem()==pi) { ++rit; di=rit.current(); }
Packit 1c1d7e
      }
Packit 1c1d7e
      else
Packit 1c1d7e
      {
Packit 1c1d7e
        ++rit;
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
uint TreeDiagram::computeRows()
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("TreeDiagram::computeRows()=%d\n",count());
Packit 1c1d7e
  int count=0;
Packit 1c1d7e
  QListIterator<DiagramRow> it(*this);
Packit 1c1d7e
  DiagramRow *row;
Packit 1c1d7e
  for (;(row=it.current()) && !row->getFirst()->isInList();++it)
Packit 1c1d7e
  {
Packit 1c1d7e
    count++;
Packit 1c1d7e
  }
Packit 1c1d7e
  //printf("count=%d row=%p\n",count,row);
Packit 1c1d7e
  if (row)
Packit 1c1d7e
  {
Packit 1c1d7e
    int maxListLen=0;
Packit 1c1d7e
    int curListLen=0;
Packit 1c1d7e
    DiagramItem *opi=0;
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*row);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    for (;(di=rit.current());++rit)
Packit 1c1d7e
    {
Packit 1c1d7e
      if (di->parentItem()!=opi) curListLen=1; else curListLen++; 
Packit 1c1d7e
      if (curListLen>maxListLen) maxListLen=curListLen;
Packit 1c1d7e
      opi=di->parentItem();
Packit 1c1d7e
    }
Packit 1c1d7e
    //printf("maxListLen=%d\n",maxListLen);
Packit 1c1d7e
    count+=maxListLen;
Packit 1c1d7e
  }
Packit 1c1d7e
  return count;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos)
Packit 1c1d7e
{
Packit 1c1d7e
  uint ml=0,mx=0;
Packit 1c1d7e
  QListIterator<DiagramRow> it(*this);
Packit 1c1d7e
  DiagramRow *dr;
Packit 1c1d7e
  bool done=FALSE;
Packit 1c1d7e
  for (;(dr=it.current()) && !done;++it)
Packit 1c1d7e
  {
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*dr);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    for (;(di=rit.current());++rit)
Packit 1c1d7e
    {
Packit 1c1d7e
      if (di->isInList()) done=TRUE;
Packit 1c1d7e
      if (maxXPos) mx=QMAX(mx,(uint)di->xPos());
Packit 1c1d7e
      if (maxLabelLen) ml=QMAX(ml,Image::stringLength(di->label()));
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  if (maxLabelLen) *maxLabelLen=ml;
Packit 1c1d7e
  if (maxXPos)     *maxXPos=mx;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void TreeDiagram::drawBoxes(FTextStream &t,Image *image, 
Packit 1c1d7e
                            bool doBase,bool bitmap,
Packit 1c1d7e
                            uint baseRows,uint superRows,
Packit 1c1d7e
                            uint cellWidth,uint cellHeight,
Packit 1c1d7e
                            QCString relPath,
Packit 1c1d7e
                            bool generateMap)
Packit 1c1d7e
{
Packit 1c1d7e
  QListIterator<DiagramRow> it(*this);
Packit 1c1d7e
  DiagramRow *dr;
Packit 1c1d7e
  if (!doBase) ++it;
Packit 1c1d7e
  bool done=FALSE;
Packit 1c1d7e
  bool firstRow = doBase;
Packit 1c1d7e
  for (;(dr=it.current()) && !done;++it)
Packit 1c1d7e
  {
Packit 1c1d7e
    int x=0,y=0;
Packit 1c1d7e
    float xf=0.0f,yf=0.0f;
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*dr);
Packit 1c1d7e
    DiagramItem *di = rit.current();
Packit 1c1d7e
    if (di->isInList()) // put boxes in a list
Packit 1c1d7e
    {
Packit 1c1d7e
      DiagramItem *opi=0;
Packit 1c1d7e
      if (doBase) rit.toLast(); else rit.toFirst();
Packit 1c1d7e
      while ((di=rit.current()))
Packit 1c1d7e
      {
Packit 1c1d7e
        if (di->parentItem()==opi)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (bitmap)
Packit 1c1d7e
          {
Packit 1c1d7e
            if (doBase) y -= cellHeight+labelVertSpacing;
Packit 1c1d7e
            else        y += cellHeight+labelVertSpacing;
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            if (doBase) yf += 1.0f;
Packit 1c1d7e
            else        yf -= 1.0f;
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        else
Packit 1c1d7e
        {
Packit 1c1d7e
          if (bitmap)
Packit 1c1d7e
          {
Packit 1c1d7e
            x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              y = image->getHeight()-
Packit 1c1d7e
                superRows*cellHeight-
Packit 1c1d7e
                (superRows-1)*labelVertSpacing-
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              y = (baseRows-1)*(cellHeight+labelVertSpacing)+
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            xf = di->xPos()/(float)gridWidth;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              yf = di->yPos()/(float)gridHeight+superRows-1;
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              yf = superRows-1-di->yPos()/(float)gridHeight;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        opi=di->parentItem();
Packit 1c1d7e
        
Packit 1c1d7e
        if (bitmap)
Packit 1c1d7e
        {
Packit 1c1d7e
          bool hasDocs=di->getClassDef()->isLinkable();
Packit 1c1d7e
          writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,
Packit 1c1d7e
              hasDocs,di->getChildren()->count()>0); 
Packit 1c1d7e
          if (!firstRow && generateMap) 
Packit 1c1d7e
            writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight);
Packit 1c1d7e
        }
Packit 1c1d7e
        else
Packit 1c1d7e
        {
Packit 1c1d7e
          writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0);
Packit 1c1d7e
        }
Packit 1c1d7e
        
Packit 1c1d7e
        if (doBase) --rit; else ++rit;
Packit 1c1d7e
      }
Packit 1c1d7e
      done=TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
    else // draw a tree of boxes
Packit 1c1d7e
    {
Packit 1c1d7e
      for (rit.toFirst();(di=rit.current());++rit)
Packit 1c1d7e
      {
Packit 1c1d7e
        if (bitmap)
Packit 1c1d7e
        {
Packit 1c1d7e
          x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
Packit 1c1d7e
          if (doBase)
Packit 1c1d7e
          {
Packit 1c1d7e
            y = image->getHeight()-
Packit 1c1d7e
              superRows*cellHeight-
Packit 1c1d7e
              (superRows-1)*labelVertSpacing-
Packit 1c1d7e
              di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            y = (baseRows-1)*(cellHeight+labelVertSpacing)+
Packit 1c1d7e
              di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
          }
Packit 1c1d7e
          bool hasDocs=di->getClassDef()->isLinkable();
Packit 1c1d7e
          writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); 
Packit 1c1d7e
          if (!firstRow && generateMap) 
Packit 1c1d7e
            writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight);
Packit 1c1d7e
        }
Packit 1c1d7e
        else
Packit 1c1d7e
        {
Packit 1c1d7e
          xf=di->xPos()/(float)gridWidth;
Packit 1c1d7e
          if (doBase)
Packit 1c1d7e
          {
Packit 1c1d7e
            yf = di->yPos()/(float)gridHeight+superRows-1;
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            yf = superRows-1-di->yPos()/(float)gridHeight;
Packit 1c1d7e
          }
Packit 1c1d7e
          writeVectorBox(t,di,xf,yf);
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    firstRow=FALSE;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void TreeDiagram::drawConnectors(FTextStream &t,Image *image,
Packit 1c1d7e
                                 bool doBase,bool bitmap,
Packit 1c1d7e
                                 uint baseRows,uint superRows,
Packit 1c1d7e
                                 uint cellWidth,uint cellHeight)
Packit 1c1d7e
{
Packit 1c1d7e
  QListIterator<DiagramRow> it(*this);
Packit 1c1d7e
  DiagramRow *dr;
Packit 1c1d7e
  bool done=FALSE;
Packit 1c1d7e
  for (;(dr=it.current()) && !done;++it) // for each row
Packit 1c1d7e
  {
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*dr);
Packit 1c1d7e
    DiagramItem *di = rit.current();
Packit 1c1d7e
    if (di->isInList()) // row consists of list connectors
Packit 1c1d7e
    {
Packit 1c1d7e
      int x=0,y=0,ys=0;
Packit 1c1d7e
      float xf=0.0f,yf=0.0f,ysf=0.0f;
Packit 1c1d7e
      for (;(di=rit.current());++rit)
Packit 1c1d7e
      {
Packit 1c1d7e
        DiagramItem *pi=di->parentItem();
Packit 1c1d7e
        DiagramItemList *dil=pi->getChildren();
Packit 1c1d7e
        DiagramItem *last=dil->getLast();
Packit 1c1d7e
        if (di==last) // single child
Packit 1c1d7e
        {
Packit 1c1d7e
          if (bitmap) // draw pixels
Packit 1c1d7e
          {
Packit 1c1d7e
            x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
Packit 1c1d7e
            if (doBase) // base classes
Packit 1c1d7e
            {
Packit 1c1d7e
              y = image->getHeight()-
Packit 1c1d7e
                (superRows-1)*(cellHeight+labelVertSpacing)-
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              image->drawVertArrow(x,y,y+labelVertSpacing/2,
Packit 1c1d7e
                                   protToColor(di->protection()),
Packit 1c1d7e
                                   protToMask(di->protection()));
Packit 1c1d7e
            }
Packit 1c1d7e
            else // super classes
Packit 1c1d7e
            {
Packit 1c1d7e
              y = (baseRows-1)*(cellHeight+labelVertSpacing)-
Packit 1c1d7e
                labelVertSpacing/2+
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              image->drawVertLine(x,y,y+labelVertSpacing/2,
Packit 1c1d7e
                                  protToColor(di->protection()),
Packit 1c1d7e
                                  protToMask(di->protection()));
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // draw vectors
Packit 1c1d7e
          {
Packit 1c1d7e
            t << protToString(di->protection()) << endl;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "1 " << (di->xPos()/(float)gridWidth) << " " 
Packit 1c1d7e
                << (di->yPos()/(float)gridHeight+superRows-1) << " in\n";
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "0 " << (di->xPos()/(float)gridWidth) << " " 
Packit 1c1d7e
                << ((float)superRows-0.25-di->yPos()/(float)gridHeight)
Packit 1c1d7e
                << " in\n";
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        else // multiple children, put them in a vertical list
Packit 1c1d7e
        {
Packit 1c1d7e
          if (bitmap)
Packit 1c1d7e
          {
Packit 1c1d7e
            x = di->parentItem()->xPos()*
Packit 1c1d7e
              (cellWidth+labelHorSpacing)/gridWidth+cellWidth/2;
Packit 1c1d7e
            if (doBase) // base classes
Packit 1c1d7e
            {
Packit 1c1d7e
              ys = image->getHeight()-
Packit 1c1d7e
                (superRows-1)*(cellHeight+labelVertSpacing)-
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              y = ys - cellHeight/2;
Packit 1c1d7e
            }
Packit 1c1d7e
            else // super classes
Packit 1c1d7e
            {
Packit 1c1d7e
              ys = (baseRows-1)*(cellHeight+labelVertSpacing)+
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              y = ys + cellHeight/2;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            xf = di->parentItem()->xPos()/(float)gridWidth;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              ysf = di->yPos()/(float)gridHeight+superRows-1;
Packit 1c1d7e
              yf = ysf + 0.5f;
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              ysf = (float)superRows-0.25f-di->yPos()/(float)gridHeight;
Packit 1c1d7e
              yf = ysf - 0.25f;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          while (di!=last) // more children to add
Packit 1c1d7e
          {
Packit 1c1d7e
            if (bitmap)
Packit 1c1d7e
            {
Packit 1c1d7e
              if (doBase) // base classes
Packit 1c1d7e
              {
Packit 1c1d7e
                image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
Packit 1c1d7e
                    protToColor(di->protection()),
Packit 1c1d7e
                    protToMask(di->protection()));
Packit 1c1d7e
                y -= cellHeight+labelVertSpacing;
Packit 1c1d7e
              }
Packit 1c1d7e
              else // super classes
Packit 1c1d7e
              {
Packit 1c1d7e
                image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
Packit 1c1d7e
                    protToColor(di->protection()),
Packit 1c1d7e
                    protToMask(di->protection()));
Packit 1c1d7e
                y += cellHeight+labelVertSpacing;
Packit 1c1d7e
              }
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << protToString(di->protection()) << endl;
Packit 1c1d7e
              if (doBase)
Packit 1c1d7e
              {
Packit 1c1d7e
                t << "1 " << xf << " " << yf << " hedge\n";
Packit 1c1d7e
                yf += 1.0f;
Packit 1c1d7e
              }
Packit 1c1d7e
              else
Packit 1c1d7e
              {
Packit 1c1d7e
                t << "0 " << xf << " " << yf << " hedge\n";
Packit 1c1d7e
                yf -= 1.0f;
Packit 1c1d7e
              }
Packit 1c1d7e
            }
Packit 1c1d7e
            ++rit; di=rit.current();
Packit 1c1d7e
          }
Packit 1c1d7e
          // add last horizonal line and a vertical connection line
Packit 1c1d7e
          if (bitmap)
Packit 1c1d7e
          {
Packit 1c1d7e
            if (doBase) // base classes
Packit 1c1d7e
            {
Packit 1c1d7e
              image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
Packit 1c1d7e
                  protToColor(di->protection()),
Packit 1c1d7e
                  protToMask(di->protection()));
Packit 1c1d7e
              image->drawVertLine(x,y,ys+labelVertSpacing/2,
Packit 1c1d7e
                  protToColor(getMinProtectionLevel(dil)),
Packit 1c1d7e
                  protToMask(getMinProtectionLevel(dil)));
Packit 1c1d7e
            }
Packit 1c1d7e
            else // super classes
Packit 1c1d7e
            {
Packit 1c1d7e
              image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
Packit 1c1d7e
                  protToColor(di->protection()),
Packit 1c1d7e
                  protToMask(di->protection()));
Packit 1c1d7e
              image->drawVertLine(x,ys-labelVertSpacing/2,y,
Packit 1c1d7e
                  protToColor(getMinProtectionLevel(dil)),
Packit 1c1d7e
                  protToMask(getMinProtectionLevel(dil)));
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            t << protToString(di->protection()) << endl;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "1 " << xf << " " << yf << " hedge\n";
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "0 " << xf << " " << yf << " hedge\n";
Packit 1c1d7e
            }
Packit 1c1d7e
            t << protToString(getMinProtectionLevel(dil)) << endl;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              t << xf << " " << ysf << " " << yf << " vedge\n";
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << xf << " " << (ysf + 0.25) << " " << yf << " vedge\n";
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
      done=TRUE; // the tree is drawn now
Packit 1c1d7e
    }
Packit 1c1d7e
    else // normal tree connector
Packit 1c1d7e
    {
Packit 1c1d7e
      for (;(di=rit.current());++rit)
Packit 1c1d7e
      {
Packit 1c1d7e
        int x=0,y=0;
Packit 1c1d7e
        DiagramItemList *dil = di->getChildren();
Packit 1c1d7e
        DiagramItem *parent  = di->parentItem();
Packit 1c1d7e
        if (parent) // item has a parent -> connect to it
Packit 1c1d7e
        {
Packit 1c1d7e
          if (bitmap) // draw pixels
Packit 1c1d7e
          {
Packit 1c1d7e
            x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
Packit 1c1d7e
            if (doBase) // base classes
Packit 1c1d7e
            {
Packit 1c1d7e
              y = image->getHeight()-
Packit 1c1d7e
                (superRows-1)*(cellHeight+labelVertSpacing)-
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              /* write input line */
Packit 1c1d7e
              image->drawVertArrow(x,y,y+labelVertSpacing/2,
Packit 1c1d7e
                  protToColor(di->protection()),
Packit 1c1d7e
                  protToMask(di->protection()));
Packit 1c1d7e
            }
Packit 1c1d7e
            else // super classes
Packit 1c1d7e
            {
Packit 1c1d7e
              y = (baseRows-1)*(cellHeight+labelVertSpacing)-
Packit 1c1d7e
                labelVertSpacing/2+
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              /* write output line */
Packit 1c1d7e
              image->drawVertLine(x,y,y+labelVertSpacing/2,
Packit 1c1d7e
                  protToColor(di->protection()),
Packit 1c1d7e
                  protToMask(di->protection()));
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // draw pixels
Packit 1c1d7e
          {
Packit 1c1d7e
            t << protToString(di->protection()) << endl;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "1 " << di->xPos()/(float)gridWidth << " " 
Packit 1c1d7e
                << (di->yPos()/(float)gridHeight+superRows-1) << " in\n";
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "0 " << di->xPos()/(float)gridWidth << " " 
Packit 1c1d7e
                << ((float)superRows-0.25-di->yPos()/(float)gridHeight)
Packit 1c1d7e
                << " in\n";
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        if (dil->count()>0)
Packit 1c1d7e
        {
Packit 1c1d7e
          Protection p=getMinProtectionLevel(dil);
Packit 1c1d7e
          uint mask=protToMask(p);
Packit 1c1d7e
          uint col=protToColor(p);
Packit 1c1d7e
          if (bitmap)
Packit 1c1d7e
          {
Packit 1c1d7e
            x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
Packit 1c1d7e
            if (doBase) // base classes
Packit 1c1d7e
            {
Packit 1c1d7e
              y = image->getHeight()-
Packit 1c1d7e
                (superRows-1)*(cellHeight+labelVertSpacing)-
Packit 1c1d7e
                cellHeight-labelVertSpacing/2-
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              image->drawVertLine(x,y,y+labelVertSpacing/2-1,col,mask);
Packit 1c1d7e
            }
Packit 1c1d7e
            else // super classes
Packit 1c1d7e
            {
Packit 1c1d7e
              y = (baseRows-1)*(cellHeight+labelVertSpacing)+
Packit 1c1d7e
                cellHeight+
Packit 1c1d7e
                di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
Packit 1c1d7e
              image->drawVertArrow(x,y,y+labelVertSpacing/2-1,col,mask);
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            t << protToString(p) << endl;
Packit 1c1d7e
            if (doBase)
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "0 " << di->xPos()/(float)gridWidth  << " " 
Packit 1c1d7e
                << (di->yPos()/(float)gridHeight+superRows-1) << " out\n";
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << "1 " << di->xPos()/(float)gridWidth  << " " 
Packit 1c1d7e
                << ((float)superRows-1.75-di->yPos()/(float)gridHeight)
Packit 1c1d7e
                << " out\n";
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          /* write input line */
Packit 1c1d7e
          DiagramItem *first = dil->getFirst();
Packit 1c1d7e
          DiagramItem *last  = dil->getLast();
Packit 1c1d7e
          if (first!=last && !first->isInList()) /* connect with all base classes */
Packit 1c1d7e
          {
Packit 1c1d7e
            if (bitmap)
Packit 1c1d7e
            {
Packit 1c1d7e
              int xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth
Packit 1c1d7e
                + cellWidth/2;
Packit 1c1d7e
              int xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth
Packit 1c1d7e
                + cellWidth/2; 
Packit 1c1d7e
              if (doBase) // base classes
Packit 1c1d7e
              {
Packit 1c1d7e
                image->drawHorzLine(y,xs,xe,col,mask); 
Packit 1c1d7e
              }
Packit 1c1d7e
              else // super classes
Packit 1c1d7e
              {
Packit 1c1d7e
                image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); 
Packit 1c1d7e
              }
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              t << protToString(p) << endl;
Packit 1c1d7e
              if (doBase)
Packit 1c1d7e
              {
Packit 1c1d7e
                t << first->xPos()/(float)gridWidth << " " 
Packit 1c1d7e
                  << last->xPos()/(float)gridWidth << " "
Packit 1c1d7e
                  << (first->yPos()/(float)gridHeight+superRows-1) 
Packit 1c1d7e
                  << " conn\n";
Packit 1c1d7e
              }
Packit 1c1d7e
              else
Packit 1c1d7e
              {
Packit 1c1d7e
                t << first->xPos()/(float)gridWidth << " " 
Packit 1c1d7e
                  << last->xPos()/(float)gridWidth << " "
Packit 1c1d7e
                  << ((float)superRows-first->yPos()/(float)gridHeight)
Packit 1c1d7e
                  << " conn\n";
Packit 1c1d7e
              }
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void clearVisitFlags()
Packit 1c1d7e
{
Packit 1c1d7e
  ClassSDict::Iterator cli(*Doxygen::classSDict);
Packit 1c1d7e
  ClassDef *cd;
Packit 1c1d7e
  for (;(cd=cli.current());++cli)
Packit 1c1d7e
  {
Packit 1c1d7e
    cd->visited=FALSE;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
ClassDiagram::ClassDiagram(ClassDef *root)
Packit 1c1d7e
{
Packit 1c1d7e
  clearVisitFlags();
Packit 1c1d7e
  base  = new TreeDiagram(root,TRUE);
Packit 1c1d7e
  base->computeLayout();
Packit 1c1d7e
  clearVisitFlags();
Packit 1c1d7e
  super = new TreeDiagram(root,FALSE);
Packit 1c1d7e
  super->computeLayout();
Packit 1c1d7e
  DiagramItem *baseItem  = base->getFirst()->getFirst();
Packit 1c1d7e
  DiagramItem *superItem = super->getFirst()->getFirst();
Packit 1c1d7e
  int xbase  = baseItem->xPos();
Packit 1c1d7e
  int xsuper = superItem->xPos();
Packit 1c1d7e
  if (xbase>xsuper)
Packit 1c1d7e
  {
Packit 1c1d7e
    superItem->move(xbase-xsuper,0);
Packit 1c1d7e
    super->moveChildren(superItem,xbase-xsuper);
Packit 1c1d7e
  }
Packit 1c1d7e
  else if (xbase
Packit 1c1d7e
  {
Packit 1c1d7e
    baseItem->move(xsuper-xbase,0);
Packit 1c1d7e
    base->moveChildren(baseItem,xsuper-xbase);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
ClassDiagram::~ClassDiagram()
Packit 1c1d7e
{
Packit 1c1d7e
  delete base;
Packit 1c1d7e
  delete super;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void ClassDiagram::writeFigure(FTextStream &output,const char *path,
Packit 1c1d7e
                               const char *fileName) const
Packit 1c1d7e
{
Packit 1c1d7e
  uint baseRows=base->computeRows();
Packit 1c1d7e
  uint superRows=super->computeRows();
Packit 1c1d7e
  uint baseMaxX, baseMaxLabelWidth, superMaxX, superMaxLabelWidth;
Packit 1c1d7e
  base->computeExtremes(&baseMaxLabelWidth,&baseMaxX);
Packit 1c1d7e
  super->computeExtremes(&superMaxLabelWidth,&superMaxX);
Packit 1c1d7e
Packit 1c1d7e
  uint rows=baseRows+superRows-1;
Packit 1c1d7e
  uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth;
Packit 1c1d7e
  
Packit 1c1d7e
  // Estimate the image aspect width and height in pixels.
Packit 1c1d7e
  uint estHeight = rows*40;
Packit 1c1d7e
  uint estWidth  = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth));
Packit 1c1d7e
  //printf("Estimated size %d x %d\n",estWidth,estHeight);
Packit 1c1d7e
  
Packit 1c1d7e
  const float pageWidth = 14.0f; // estimated page width in cm.
Packit 1c1d7e
                                 // Somewhat lower to deal with estimation
Packit 1c1d7e
                                 // errors. 
Packit 1c1d7e
  
Packit 1c1d7e
  // compute the image height in centimeters based on the estimates
Packit 1c1d7e
  float realHeight = QMIN(rows,12); // real height in cm
Packit 1c1d7e
  float realWidth  = realHeight * estWidth/(float)estHeight;
Packit 1c1d7e
  if (realWidth>pageWidth) // assume that the page width is about 15 cm
Packit 1c1d7e
  {
Packit 1c1d7e
    realHeight*=pageWidth/realWidth; 
Packit 1c1d7e
    realWidth=pageWidth;
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  //output << "}\n";
Packit 1c1d7e
  output << "\\begin{figure}[H]\n"
Packit 1c1d7e
            "\\begin{center}\n"
Packit 1c1d7e
            "\\leavevmode\n";
Packit 1c1d7e
  output << "\\includegraphics[height=" << realHeight << "cm]{" 
Packit 1c1d7e
                                        << fileName << "}" << endl;
Packit 1c1d7e
  output << "\\end{center}\n"
Packit 1c1d7e
            "\\end{figure}\n";
Packit 1c1d7e
  
Packit 1c1d7e
  //printf("writeFigure rows=%d cols=%d\n",rows,cols);
Packit 1c1d7e
Packit 1c1d7e
  QCString epsBaseName=(QCString)path+"/"+fileName;
Packit 1c1d7e
  QCString epsName=epsBaseName+".eps";
Packit 1c1d7e
  QFile f1;
Packit 1c1d7e
  f1.setName(epsName.data());
Packit 1c1d7e
  if (!f1.open(IO_WriteOnly))
Packit 1c1d7e
  {
Packit 1c1d7e
    err("Could not open file %s for writing\n",f1.name().data());
Packit 1c1d7e
    exit(1);
Packit 1c1d7e
  }
Packit 1c1d7e
  FTextStream t(&f1;;
Packit 1c1d7e
  
Packit 1c1d7e
  //printf("writeEPS() rows=%d cols=%d\n",rows,cols);
Packit 1c1d7e
  
Packit 1c1d7e
  // generate EPS header and postscript variables and procedures
Packit 1c1d7e
  
Packit 1c1d7e
  t << "%!PS-Adobe-2.0 EPSF-2.0\n";
Packit 1c1d7e
  t << "%%Title: ClassName\n";
Packit 1c1d7e
  t << "%%Creator: Doxygen\n";
Packit 1c1d7e
  t << "%%CreationDate: Time\n";
Packit 1c1d7e
  t << "%%For: \n";
Packit 1c1d7e
  t << "%Magnification: 1.00\n";
Packit 1c1d7e
  t << "%%Orientation: Portrait\n";
Packit 1c1d7e
  t << "%%BoundingBox: 0 0 500 " << estHeight*500.0/(float)estWidth << "\n";
Packit 1c1d7e
  t << "%%Pages: 0\n";
Packit 1c1d7e
  t << "%%BeginSetup\n";
Packit 1c1d7e
  t << "%%EndSetup\n";
Packit 1c1d7e
  t << "%%EndComments\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "% ----- variables -----\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/boxwidth 0 def\n";
Packit 1c1d7e
  t << "/boxheight 40 def\n";
Packit 1c1d7e
  t << "/fontheight 24 def\n";
Packit 1c1d7e
  t << "/marginwidth 10 def\n";
Packit 1c1d7e
  t << "/distx 20 def\n";
Packit 1c1d7e
  t << "/disty 40 def\n";
Packit 1c1d7e
  t << "/boundaspect " << estWidth/(float)estHeight << " def  % aspect ratio of the BoundingBox (width/height)\n";
Packit 1c1d7e
  t << "/boundx 500 def\n";
Packit 1c1d7e
  t << "/boundy boundx boundaspect div def\n";
Packit 1c1d7e
  t << "/xspacing 0 def\n";
Packit 1c1d7e
  t << "/yspacing 0 def\n";
Packit 1c1d7e
  t << "/rows " << rows << " def\n";
Packit 1c1d7e
  t << "/cols " << cols << " def\n";
Packit 1c1d7e
  t << "/scalefactor 0 def\n";
Packit 1c1d7e
  t << "/boxfont /Times-Roman findfont fontheight scalefont def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "% ----- procedures -----\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/dotted { [1 4] 0 setdash } def\n";
Packit 1c1d7e
  t << "/dashed { [5] 0 setdash } def\n";
Packit 1c1d7e
  t << "/solid  { [] 0 setdash } def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/max % result = MAX(arg1,arg2)\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  /a exch def\n";
Packit 1c1d7e
  t << "  /b exch def\n";
Packit 1c1d7e
  t << "  a b gt {a} {b} ifelse\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/xoffset % result = MAX(0,(scalefactor-(boxwidth*cols+distx*(cols-1)))/2)\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  0 scalefactor boxwidth cols mul distx cols 1 sub mul add sub 2 div max\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/cw % boxwidth = MAX(boxwidth, stringwidth(arg1))\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  /str exch def\n";
Packit 1c1d7e
  t << "  /boxwidth boxwidth str stringwidth pop max def\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/box % draws a box with text `arg1' at grid pos (arg2,arg3)\n";
Packit 1c1d7e
  t << "{ gsave\n";
Packit 1c1d7e
  t << "  2 setlinewidth\n";
Packit 1c1d7e
  t << "  newpath\n";
Packit 1c1d7e
  t << "  exch xspacing mul xoffset add\n";
Packit 1c1d7e
  t << "  exch yspacing mul\n";
Packit 1c1d7e
  t << "  moveto\n";
Packit 1c1d7e
  t << "  boxwidth 0 rlineto \n";
Packit 1c1d7e
  t << "  0 boxheight rlineto \n";
Packit 1c1d7e
  t << "  boxwidth neg 0 rlineto \n";
Packit 1c1d7e
  t << "  0 boxheight neg rlineto \n";
Packit 1c1d7e
  t << "  closepath\n";
Packit 1c1d7e
  t << "  dup stringwidth pop neg boxwidth add 2 div\n";
Packit 1c1d7e
  t << "  boxheight fontheight 2 div sub 2 div\n";
Packit 1c1d7e
  t << "  rmoveto show stroke\n";
Packit 1c1d7e
  t << "  grestore\n";
Packit 1c1d7e
  t << "} def  \n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/mark\n";
Packit 1c1d7e
  t << "{ newpath\n";
Packit 1c1d7e
  t << "  exch xspacing mul xoffset add boxwidth add\n";
Packit 1c1d7e
  t << "  exch yspacing mul\n";
Packit 1c1d7e
  t << "  moveto\n";
Packit 1c1d7e
  t << "  0 boxheight 4 div rlineto\n";
Packit 1c1d7e
  t << "  boxheight neg 4 div boxheight neg 4 div rlineto\n";
Packit 1c1d7e
  t << "  closepath\n";
Packit 1c1d7e
  t << "  eofill\n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/arrow\n";
Packit 1c1d7e
  t << "{ newpath\n";
Packit 1c1d7e
  t << "  moveto\n";
Packit 1c1d7e
  t << "  3 -8 rlineto\n";
Packit 1c1d7e
  t << "  -6 0 rlineto\n";
Packit 1c1d7e
  t << "  3 8 rlineto\n";
Packit 1c1d7e
  t << "  closepath\n";
Packit 1c1d7e
  t << "  eofill\n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/out % draws an output connector for the block at (arg1,arg2)\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  newpath\n";
Packit 1c1d7e
  t << "  exch xspacing mul xoffset add boxwidth 2 div add\n";
Packit 1c1d7e
  t << "  exch yspacing mul boxheight add\n";
Packit 1c1d7e
  t << "  /y exch def\n";
Packit 1c1d7e
  t << "  /x exch def\n";
Packit 1c1d7e
  t << "  x y moveto\n";
Packit 1c1d7e
  t << "  0 disty 2 div rlineto \n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "  1 eq { x y disty 2 div add arrow } if\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/in % draws an input connector for the block at (arg1,arg2)\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  newpath\n";
Packit 1c1d7e
  t << "  exch xspacing mul xoffset add boxwidth 2 div add\n";
Packit 1c1d7e
  t << "  exch yspacing mul disty 2 div sub\n";
Packit 1c1d7e
  t << "  /y exch def\n";
Packit 1c1d7e
  t << "  /x exch def\n";
Packit 1c1d7e
  t << "  x y moveto\n";
Packit 1c1d7e
  t << "  0 disty 2 div rlineto\n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "  1 eq { x y disty 2 div add arrow } if\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/hedge\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  exch xspacing mul xoffset add boxwidth 2 div add\n";
Packit 1c1d7e
  t << "  exch yspacing mul boxheight 2 div sub\n";
Packit 1c1d7e
  t << "  /y exch def\n";
Packit 1c1d7e
  t << "  /x exch def\n";
Packit 1c1d7e
  t << "  newpath\n";
Packit 1c1d7e
  t << "  x y moveto\n";
Packit 1c1d7e
  t << "  boxwidth 2 div distx add 0 rlineto\n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "  1 eq\n";
Packit 1c1d7e
  t << "  { newpath x boxwidth 2 div distx add add y moveto\n";
Packit 1c1d7e
  t << "    -8 3 rlineto\n";
Packit 1c1d7e
  t << "    0 -6 rlineto\n";
Packit 1c1d7e
  t << "    8 3 rlineto\n";
Packit 1c1d7e
  t << "    closepath\n";
Packit 1c1d7e
  t << "    eofill\n";
Packit 1c1d7e
  t << "    stroke\n";
Packit 1c1d7e
  t << "  } if\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/vedge\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  /ye exch def\n";
Packit 1c1d7e
  t << "  /ys exch def\n";
Packit 1c1d7e
  t << "  /xs exch def\n";
Packit 1c1d7e
  t << "  newpath\n";
Packit 1c1d7e
  t << "  xs xspacing mul xoffset add boxwidth 2 div add dup\n";
Packit 1c1d7e
  t << "  ys yspacing mul boxheight 2 div sub\n";
Packit 1c1d7e
  t << "  moveto\n";
Packit 1c1d7e
  t << "  ye yspacing mul boxheight 2 div sub\n";
Packit 1c1d7e
  t << "  lineto\n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "/conn % connections the blocks from col `arg1' to `arg2' of row `arg3'\n";
Packit 1c1d7e
  t << "{\n";
Packit 1c1d7e
  t << "  /ys exch def\n";
Packit 1c1d7e
  t << "  /xe exch def\n";
Packit 1c1d7e
  t << "  /xs exch def\n";
Packit 1c1d7e
  t << "  newpath\n";
Packit 1c1d7e
  t << "  xs xspacing mul xoffset add boxwidth 2 div add\n";
Packit 1c1d7e
  t << "  ys yspacing mul disty 2 div sub\n";
Packit 1c1d7e
  t << "  moveto\n";
Packit 1c1d7e
  t << "  xspacing xe xs sub mul 0\n";
Packit 1c1d7e
  t << "  rlineto\n";
Packit 1c1d7e
  t << "  stroke\n";
Packit 1c1d7e
  t << "} def\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "% ----- main ------\n";
Packit 1c1d7e
  t << "\n";
Packit 1c1d7e
  t << "boxfont setfont\n";
Packit 1c1d7e
  t << "1 boundaspect scale\n";
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
  bool done=FALSE;
Packit 1c1d7e
  QListIterator<DiagramRow> bit(*base);
Packit 1c1d7e
  DiagramRow *dr;
Packit 1c1d7e
  for (;(dr=bit.current()) && !done;++bit)
Packit 1c1d7e
  {
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*dr);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    for (;(di=rit.current());++rit)
Packit 1c1d7e
    {
Packit 1c1d7e
      done=di->isInList();
Packit 1c1d7e
      t << "(" << di->label() << ") cw\n";
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  QListIterator<DiagramRow> sit(*super);
Packit 1c1d7e
  ++sit;
Packit 1c1d7e
  done=FALSE;
Packit 1c1d7e
  for (;(dr=sit.current()) && !done;++sit)
Packit 1c1d7e
  {
Packit 1c1d7e
    QListIterator<DiagramItem> rit(*dr);
Packit 1c1d7e
    DiagramItem *di;
Packit 1c1d7e
    for (;(di=rit.current());++rit)
Packit 1c1d7e
    {
Packit 1c1d7e
      done=di->isInList();
Packit 1c1d7e
      t << "(" << di->label() << ") cw\n";
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  t << "/boxwidth boxwidth marginwidth 2 mul add def\n"
Packit 1c1d7e
    << "/xspacing boxwidth distx add def\n"
Packit 1c1d7e
    << "/yspacing boxheight disty add def\n"
Packit 1c1d7e
    << "/scalefactor \n"
Packit 1c1d7e
    << "  boxwidth cols mul distx cols 1 sub mul add\n"
Packit 1c1d7e
    << "  boxheight rows mul disty rows 1 sub mul add boundaspect mul \n"
Packit 1c1d7e
    << "  max def\n"
Packit 1c1d7e
    << "boundx scalefactor div boundy scalefactor div scale\n";
Packit 1c1d7e
  
Packit 1c1d7e
  t << "\n% ----- classes -----\n\n";
Packit 1c1d7e
  base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0);
Packit 1c1d7e
  super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0);
Packit 1c1d7e
  
Packit 1c1d7e
  t << "\n% ----- relations -----\n\n";
Packit 1c1d7e
  base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0);
Packit 1c1d7e
  super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0);
Packit 1c1d7e
Packit 1c1d7e
  f1.close();
Packit 1c1d7e
  if (Config_getBool(USE_PDFLATEX))
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString epstopdfArgs(4096);
Packit 1c1d7e
    epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
Packit 1c1d7e
                   epsBaseName.data(),epsBaseName.data());
Packit 1c1d7e
    //printf("Converting eps using `%s'\n",epstopdfArgs.data());
Packit 1c1d7e
    portable_sysTimerStart();
Packit 1c1d7e
    if (portable_system("epstopdf",epstopdfArgs)!=0)
Packit 1c1d7e
    {
Packit 1c1d7e
       err("Problems running epstopdf. Check your TeX installation!\n");
Packit 1c1d7e
       portable_sysTimerStop();
Packit 1c1d7e
       return;
Packit 1c1d7e
    }
Packit 1c1d7e
    portable_sysTimerStop();
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void ClassDiagram::writeImage(FTextStream &t,const char *path,
Packit 1c1d7e
                              const char *relPath,const char *fileName, 
Packit 1c1d7e
                              bool generateMap) const
Packit 1c1d7e
{
Packit 1c1d7e
  uint baseRows=base->computeRows();
Packit 1c1d7e
  uint superRows=super->computeRows();
Packit 1c1d7e
  uint rows=baseRows+superRows-1;
Packit 1c1d7e
Packit 1c1d7e
  uint lb,ls,xb,xs;
Packit 1c1d7e
  base->computeExtremes(&lb,&xb;;
Packit 1c1d7e
  super->computeExtremes(&ls,&xs);
Packit 1c1d7e
 
Packit 1c1d7e
  uint cellWidth  = QMAX(lb,ls)+labelHorMargin*2;
Packit 1c1d7e
  uint maxXPos    = QMAX(xb,xs);
Packit 1c1d7e
  uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3
Packit 1c1d7e
  uint cellHeight = labelVertMargin*2+fontHeight;
Packit 1c1d7e
  uint imageWidth = (maxXPos+gridWidth)*cellWidth/gridWidth+
Packit 1c1d7e
                    (maxXPos*labelHorSpacing)/gridWidth;
Packit 1c1d7e
  uint imageHeight = rows*cellHeight+(rows-1)*labelVertSpacing;
Packit 1c1d7e
Packit 1c1d7e
  Image image(imageWidth,imageHeight);
Packit 1c1d7e
Packit 1c1d7e
  base->drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap);
Packit 1c1d7e
  super->drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap);
Packit 1c1d7e
  base->drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight);
Packit 1c1d7e
  super->drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight);
Packit 1c1d7e
Packit 1c1d7e
#define IMAGE_EXT ".png"
Packit 1c1d7e
  image.save((QCString)path+"/"+fileName+IMAGE_EXT);
Packit 1c1d7e
  Doxygen::indexList->addImageFile(QCString(fileName)+IMAGE_EXT);
Packit 1c1d7e
  
Packit 1c1d7e
  if (generateMap) t << "</map>" << endl;
Packit 1c1d7e
}
Packit 1c1d7e