/***************************************************************************
 *   Copyright (C) 2011 by Jeremy Burton   *
 *   jburton@39net-w04   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <math.h>
#include <QPainter>
#include <QPrinter>
#include <QMouseEvent>

#include "dom.h"
#include "textitem.h"
#include "textitem2.h"
#include "polygonitem.h"
#include "ellipseitem.h"
#include "boxitem.h"
#include "shapeitem.h"
#include "canvas.h"

CCanvas::CCanvas(QWidget *parent) : QWidget(parent)
{
  textitem *item;

  mousemode = MouseIdle;
  zoom = 1.5;
  auto_zoom_req = auto_zoom_block = false;
  preview = false;

  textitem2 *item2 = new textitem2;
  item2->str = "ABCDEFGHIJ";
  items.append(item2);

   polygonitem *polygon = new polygonitem;
   items << polygon;
// 
//   polygon = new polygonitem;
//   polygon->points=3;
//   items << polygon;
// 
//   polygon = new polygonitem;
//   polygon->points=8;
//   polygon->radius1=50;
//   items << polygon;
// 
//   item = new textitem;
//   item->str = "ABCDEFGHIJ";
//   items.append(item);

  item = new textitem1;
  item->forward = false;
  item->anchorangle = 180.0;
  item->radius1 = 50.0;
  item->str = "www.jedi98.co.uk";
  items.append(item);

  ellipseitem *circle = new ellipseitem;
  circle->radius1=circle->radius2=75.0;
  circle->circular=true;
  items << circle;

  boxitem *box = new boxitem;
  items << box;

  curitem = 0;
  grid_type = 1;

  modified = false;
}

CCanvas::~CCanvas()
{
}

void CCanvas::clear()
{
  items.clear();
  update();
}

void CCanvas::resizeEvent(QResizeEvent */*event*/)
{
  auto_zoom_req = true;
}

void CCanvas::paintEvent(QPaintEvent */*event*/)
{
  if (items.count() == 0)
    return;

  if (auto_zoom_req)
  {
    auto_zoom();
    auto_zoom_req = false;
  }
//printf("paintEvent: %p\n",this);

  int
    i,j,
    w = width()/2,
    h = height()/2,
    o = sqrt(w*w+h*h);
  double
    n = 10.0*zoom,
    a;
  QPoint ctr(0,0);

  centre.setX(w);
  centre.setY(h);

  QPainter painter(this);

  QPen pen1(Qt::SolidLine);

    painter.resetTransform();
    painter.translate(centre);
  painter.eraseRect(painter.window());
painter.setRenderHint(QPainter::Antialiasing, true);

  //TODO: config
  //10mm Grid...
  pen1.setColor(Qt::lightGray);
  painter.setPen(pen1);
  switch (grid_type)
  {
    case 1:
	//Y
	painter.drawLine(-w,0,w,0);
	for (i=1,j=n; j<h; i++,j=i*n)
	{
	  painter.drawLine(-w,j,w,j);
	  painter.drawLine(-w,-j,w,-j);
	}
	//X
	painter.drawLine(0,-h,0,h);
	for (i=1,j=n; j<w; i++,j=i*n)
	{
	  painter.drawLine(j,-h,j,h);
	  painter.drawLine(-j,-h,-j,h);
	}
	//Centre cross
	pen1.setColor(Qt::darkGray);
	painter.setPen(pen1);
	painter.drawLine(-10,-10,10,10);
	painter.drawLine(-10,10,10,-10);
	break;

    case 2:
	//C
	for (i=1,j=n; j<o; i++,j=i*n)
	  painter.drawEllipse(ctr,j,j);
	//R
	for (i=0; i<360; i+=15)
	{
	  a = (double)i/180.0*pi;
	  painter.drawLine(0,0,o*sin(a),o*cos(a));
	}
	break;
  }
  //painter.setPen(Qt::blue);
  //painter.setFont(QFont("Arial", 30));
  //painter.drawText(rect(), Qt::AlignCenter, "Qt");

//  painter.translate(painter.device()->width()/2.0,painter.device()->height()/2.0);
  for (int i=items.count()-1;i>=0;i--)
  {
    painter.save();
    items[i]->paint(painter, curitem==i || preview, zoom);
    painter.restore();
  }

  if (curitem>=0 && !preview)
  {
    painter.save();
    items[curitem]->paint_handles(painter, zoom);
    painter.restore();
  }
}

  // charwidth/2 + atan(startang)*radius
/*
% Wrap text around outside of circle, CW direction
% real:x real:y real:startangle real:radius real:spacing string:text
/CTextCW
{
  /_s exch def
  /_i exch def
  /_r exch def
  /_a exch def

  /_c 1 string def

  gsave 
  translate 
  newpath

  DBG_CONSTR {.25 setlinewidth 0 0 _r circle stroke} if
  _s {
    _c 0 3 -1 roll put
    /_a _a _c stringwidth pop 2 div _r atan _i mul add def
  } forall	% go back 1/2 the angle of the whole string to centre it
  _s {
    _c 0 2 index put
    /_xi _c stringwidth pop 2 div def  % = half X inc
    /_ai _xi _r atan _i mul def  % = half angular inc
    /_a _a _ai sub def
    DBG_CONSTR {0 0 moveto} if
    _a cos _r mul _a sin _r mul
    DBG_CONSTR {lineto} {moveto} ifelse
    gsave _a 90 sub rotate
    _xi neg 0 rmoveto
    _c show grestore
    /_a _a _ai sub def
    pop
  } forall

/CTextCCW
{
  /_s exch def
  /_i exch def
  /_r exch def
  /_a exch def

  /_c 1 string def

  gsave 
  translate 
  newpath

  DBG_CONSTR {.25 setlinewidth 0 0 _r circle stroke} if
  _s {
    _c 0 3 -1 roll put
    /_a _a _c stringwidth pop 2 div _r atan _i mul sub def
  } forall	% go back 1/2 the angle of the whole string to centre it
  _s {
    _c 0 2 index put
    /_xi _c stringwidth pop 2 div def  % = half X inc
    /_ai _xi _r atan _i mul def  % = half angular inc
    /_a _a _ai add def
    DBG_CONSTR {0 0 moveto} if
    _a cos _r mul _a sin _r mul
    DBG_CONSTR {lineto} {moveto} ifelse
    gsave _a 270 sub rotate
    _xi neg 0 rmoveto
    _c show grestore
    /_a _a _ai add def
    pop
  } forall
  stroke

  grestore
}
*/

#define Normalise(v,l1,l2) {while ((v)<(l1)) (v)+=abs((l1)-(l2)); while ((v)>=(l2)) (v)-=abs((l1)-(l2));}
#define Constrain(v,l1,l2) {if ((v)<(l1)) (v)=(l1); else if ((v)>(l2)) (v)=(l2);}

void CCanvas::mouseMoveEvent(QMouseEvent *event)
{
  if (mousemode == MouseIdle)
    return;

//  baseitem
//    *item = (baseitem *)items[curitem];
  QPoint
    //ctr(width()/2+item->centre.x()*zoom,height()/2-item->centre.y()*zoom),
    mousepos = event->pos()-centre;
  double
    ox = mousepos.x()-mouseorig.x(),
    oy = mouseorig.y()-mousepos.y();

//printf("mouseMoveEvent: mode=%d, mousepos=(%d,%d)\n\tmouseorig=(%d,%d)\n",mousemode,mousepos.x(),mousepos.y(),mouseorig.x(),mouseorig.y());
  switch (mousemode)
  {
    case MouseIdle: break;
    case ItemAngle:	//Rotation angle
    {
      baseitem
	*item = (baseitem *)items[curitem];

      item->angle = RadToDeg(atan2(ox,oy));
      Normalise(item->angle,0.0,360.0);
 //printf("\tangle=%f\n",item->angle);

      emit itemChange(curitem);
      update();
      break;
    }

    case TextAnchorAngle:	//Textitem: Anchor Angle
    {
      textitem
	*item = (textitem *)items[curitem];

      item->anchorangle = RadToDeg(atan2(ox/item->radius1,oy/item->radius2))-item->angle;
      Normalise(item->anchorangle,0.0,360.0);

      emit itemChange(curitem);
      update();
      break;
    }

    case ResizeRadius1:		//Polaritem: radius1
    {
//printf("mouseMoveEvent: mousepos=(%d,%d)\n",mousepos.x(),mousepos.y());
//printf("mouseMoveEvent: offset=(%.0f,%.0f)\n",ox,oy);
      polaritem
	*item = (polaritem *)items[curitem];

      double
	r = sqrt(ox*ox+oy*oy)/zoom;

      Constrain(r,0.5,200.0);
      item->radius1 = r;
      emit itemChange(curitem);
      update();
      break;
    }

    case ResizeRadius2:		//Polaritem: radius2
    {
      polaritem
	*item = (polaritem *)items[curitem];

      double
	r = sqrt(ox*ox+oy*oy)/zoom;

      Constrain(r,0.5,200.0);
      item->radius2 = r;
//printf("\tradius2=%f\n",r);
      emit itemChange(curitem);
      update();
      break;
    }

    case FontHeight:	//Textitem: font height
    {
      textitem
	*item = (textitem *)items[curitem];

      double
	h = sqrt(ox*ox+oy*oy)/zoom - item->radius1;

      Constrain(h,1.0,100.0);
      item->fontheight = h;
      emit itemChange(curitem);
      update();
      break;
    }

    case ResizeBox:	//boxitem: Width & height
    {
      boxitem
	*item = (boxitem *)items[curitem];
      CPoint
	pos((int)ox,(int)oy);
pos.rotate(item->angle);
      double
	w = abs((double)pos.x()*2.0/zoom),
	h = abs((double)pos.y()*2.0/zoom);

      Constrain(w,1.0,400.0);
      Constrain(h,1.0,400.0);
      item->width = w;
      if (!item->square) item->height = h;
      emit itemChange(curitem);
      update();
      break;
    }

    case ResizeRadius3:	//Radius2 on a radial
    {
      radialitem
	*item = (radialitem *)items[curitem];
      double
	r = sqrt(ox*ox+oy*oy)/zoom;

      Constrain(r,0.5,100.0);
      item->radius3 = r;
      emit itemChange(curitem);
      update();
      break;
    }

    case ItemMove:	//Move centre
    {
//printf("mouseMoveEvent: mousepos=(%d,%d)\n",mousepos.x(),mousepos.y());
      baseitem
	*item = (baseitem *)items[curitem];
      double
	x = mousepos.x()/zoom,
	y = -mousepos.y()/zoom;
	//x = (event->x()-ctr.x())/zoom,
	//y = (ctr.y()-event->y())/zoom;

      Constrain(x,-100.0,100.0);
      Constrain(y,-100.0,100.0);
      item->centre.setX(x);
      item->centre.setY(y);
      emit itemChange(curitem);
      update();
      break;
    }

    case OffsetMove:	//Move offset
    {
//printf("mouseMoveEvent: mousepos=(%d,%d)\n",mousepos.x(),mousepos.y());
      shapeitem
	*item = (shapeitem *)items[curitem];
      CPointF
	pos(ox/zoom,oy/zoom); pos.rotate(item->angle);
      double
	x = pos.x(),
	y = pos.y();

      Constrain(x,-100.0,100.0);
      Constrain(y,-100.0,100.0);
      item->offset.setX(x);
      item->offset.setY(y);
      emit itemChange(curitem);
      update();
      break;
    }
  }
}

#define IsNear(e,p,s) (abs((e)->x()-(p).x())<(s) && abs((e)->y()-(p).y())<(s))
#define IsNear2(c,p,s) (abs((c).x()-(p).x())<(s) && abs((c).y()-(p).y())<(s))

void CCanvas::mousePressEvent(QMouseEvent *event)
{
  if (curitem<0 || preview)
    return;

  baseitem
    *item = (baseitem *)items[curitem];

  mouseorig.setX(item->centre.x()*zoom);
  mouseorig.setY(-item->centre.y()*zoom);

  QPoint
    click = event->pos()-centre;

//printf("mousePressEvent: (%d,%d)\n\tmove_handle=(%d,%d)\n",click.x(),click.y(),item->move_handle.x(),item->move_handle.y());
  if (IsNear2(click,item->move_handle,7) && !item->centrelock)		//Baseitem Move handle
  {
    mousemode = ItemMove;
    return;
  }

  switch (items[curitem]->getType())
  {
    case baseitem::textitem1_type:
    {
      textitem
	*item = (textitem *)items[curitem];

//TODO: clean this up
//printf("\tanchorangle_handle=(%d,%d)\n",item->anchorangle_handle.x(),item->anchorangle_handle.y());
//printf("\tradius1_handle=(%d,%d)\n",item->radius1_handle.x(),item->radius1_handle.y());
//printf("\tfontheight_handle=(%d,%d)\n",item->fontheight_handle.x(),item->fontheight_handle.y());
      if (IsNear2(click,item->anchorangle_handle,ANCHORANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = TextAnchorAngle;
//printf("mousemode=%d\n",mousemode);
      }
      else
      if (IsNear2(click,item->radius1_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius1;
//printf("mousemode=%d\n",mousemode);
      }
      else
      if (IsNear2(click,item->fontheight_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = FontHeight;
//printf("mousemode=%d\n",mousemode);
      }
      break;
    }

    ////////////////////////////////////////////////////////

    case baseitem::textitem2_type:
    {
      textitem2
	*item = (textitem2 *)items[curitem];
//printf("\tangle_handle=(%d,%d)\n",item->angle_handle.x(),item->angle_handle.y());
//printf("\tanchorangle_handle=(%d,%d)\n",item->anchorangle_handle.x(),item->anchorangle_handle.y());
//printf("\tradius1_handle=(%d,%d)\n",item->radius1_handle.x(),item->radius1_handle.y());
      if (IsNear2(click,item->angle_handle,ANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = ItemAngle;
      }
      else
      if (IsNear2(click,item->anchorangle_handle,ANCHORANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = TextAnchorAngle;
      }
      else
      if (IsNear2(click,item->radius1_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius1;
      }
      else
      if (IsNear2(click,item->radius2_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius2;
      }
      else
      if (IsNear2(click,item->fontheight_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = FontHeight;
      }
      break;
    }

    ////////////////////////////////////////////////////////

    case baseitem::polygonitem_type:
    {
      polygonitem
	*item = (polygonitem *)items[curitem];

      if (IsNear2(click,item->angle_handle,ANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = ItemAngle;
      }
      else
      if (IsNear2(click,item->radius1_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius1;
      }
      break;
    }

    ////////////////////////////////////////////////////////

    case baseitem::boxitem_type:
    {
      boxitem *item = (boxitem *)items[curitem];

//printf("\tangle_handle=(%d,%d)\n",item->angle_handle.x(),item->angle_handle.y());
//printf("\tsize_handle=(%d,%d)\n",item->size_handle.x(),item->size_handle.y());
      if (IsNear2(click,item->angle_handle,ANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = ItemAngle;
      }
      else
      if (IsNear2(click,item->size_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeBox;
//printf("mousemode=%d\n",mousemode);
      }
      break;
    }

    ////////////////////////////////////////////////////////

    case baseitem::shapeitem_type:
    {
      shapeitem *item = (shapeitem *)items[curitem];

//printf("\tangle_handle=(%d,%d)\n",item->angle_handle.x(),item->angle_handle.y());
//printf("\tsize_handle=(%d,%d)\n",item->size_handle.x(),item->size_handle.y());
      if (IsNear2(click,item->offset_handle,MOVE_HANDLE_SIZE) && !item->centrelock)
      {
	mousemode = OffsetMove;
      }
      else
      if (IsNear2(click,item->angle_handle,ANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = ItemAngle;
      }
      break;
    }

    ////////////////////////////////////////////////////////

    case baseitem::ellipseitem_type:
    {
      ellipseitem *item = (ellipseitem *)items[curitem];
//printf("\tangle_handle=(%d,%d)\n",item->angle_handle.x(),item->angle_handle.y());
//printf("\tradius2_handle=(%d,%d)\n",item->radius2_handle.x(),item->radius2_handle.y());
      if (IsNear2(click,item->angle_handle,ANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = ItemAngle;
      }
      else
      if (IsNear2(click,item->radius1_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius1;
      }
      else
      if (IsNear2(click,item->radius2_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius2;
      }
      break;
    }

    ////////////////////////////////////////////////////////

    case baseitem::radialitem_type:
    {
      radialitem
	*item = (radialitem *)items[curitem];
//printf("\tangle_handle=(%d,%d)\n",item->angle_handle.x(),item->angle_handle.y());
//printf("\tradius1_handle=(%d,%d)\n",item->radius1_handle.x(),item->radius1_handle.y());
//printf("\tradius2_handle=(%d,%d)\n",item->radius2_handle.x(),item->radius2_handle.y());
      if (IsNear2(click,item->angle_handle,ANGLE_HANDLE_SIZE) && !item->anglelock)
      {
	mousemode = ItemAngle;
      }
      else
      if (IsNear2(click,item->radius1_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius1;
      }
      else
      if (IsNear2(click,item->radius3_handle,SIZE_HANDLE_SIZE) && !item->sizelock)
      {
	auto_zoom_block = true;
	mousemode = ResizeRadius3;
      }
      break;
    }
  }
}

void CCanvas::mouseReleaseEvent ( QMouseEvent * /*event*/ )
{
  mousemode = MouseIdle;
  auto_zoom_block = false;
  auto_zoom();
}

#define realtodev(n,r) ((n)/25.4*(r))

void CCanvas::output(QString &fileName)
{
  //int item_count=2;
  qreal max_size=0,margin=10;

  max_size = extent()*2.0;

  QPrinter printer(QPrinter::HighResolution);
  printer.setOutputFileName(fileName /*"/tmp/circtext.pdf"*/);
  printer.setOutputFormat(QPrinter::PdfFormat);
  printer.setPaperSize(QSizeF(max_size+margin*2,max_size+margin*2), QPrinter::Millimeter);
  QPainter painter(&printer);
printf("max size=%fmm\n",max_size);
printf("paper size=%fmm\n",max_size+margin*2);
printf("DPI=%d,%d\n",painter.device()->logicalDpiX(),painter.device()->logicalDpiY());
  //painter.eraseRect(painter.window());
  painter.translate(painter.device()->width()/2,painter.device()->height()/2);
painter.setRenderHint(QPainter::Antialiasing, true);

  for (int i=items.count()-1;i>=0;i--)
  {
    //items[i]->ctr.setX(0);
    //items[i]->ctr.setY(0);
    painter.save();
    items[i]->output(painter);
    painter.restore();
  }
}

void CCanvas::setZoom(double v)
{
  zoom=v/2.0;
  emit canvasChange();
  update();
}

double CCanvas::getZoom()
{
  return zoom*2.0;
}

void CCanvas::setGridType(int v)
{
  grid_type = v;
}

double CCanvas::extent()
{
  double e,emax = 0.0;
  for (int i=0; i<items.count(); i++)
  {
    baseitem *item = items[i];
//printf("extent: type=%d, describe=%s\n",item->getType(),item->describe().toAscii().data());
    if ((e=std::max(abs(item->centre.x()),abs(item->centre.y()))+item->extent()+1.0) > emax)
      emax = e;
  }

/*  for (int i=0; i<items.count(); i++)
  {
    switch (items[i]->getType())
    {

      case baseitem::textitem2_type:
      case baseitem::textitem1_type:
      {
	textitem *item = (textitem *)items[i];
	if ((e=std::max(abs(item->centre.x()),abs(item->centre.y()))+item->radius1+item->fontheight) > emax)
	  emax = e;
	break;
      }

      case baseitem::boxitem_type:
      {
	boxitem *item = (boxitem *)items[i];
	QPoint2 p(item->width+item->strokewidth,item->width+item->strokewidth);
	p.rotate(item->angle);
	if ((e=abs(item->centre.x())+abs(p.x()/2.0)) > emax)
	  emax = e;
	if ((e=abs(item->centre.y())+abs(p.y()/2.0)) > emax)
	  emax = e;
	break;
      }

      case baseitem::radialitem_type:
      case baseitem::ellipseitem_type:
      {
	polaritem *item = (polaritem *)items[i];
	if ((e=std::max(abs(item->centre.x()),abs(item->centre.y()))+std::max(item->radius1,item->radius2)+item->strokewidth/2.0) > emax)
	  emax = e;
	break;
      }
      case baseitem::polygonitem_type:
      {
	polygonitem *item = (polygonitem *)items[i];
	if ((e=std::max(abs(item->centre.x()),abs(item->centre.y()))+item->radius1+item->strokewidth/2.0) > emax)
	  emax = e;
	break;
      }

      case baseitem::shapeitem_type:
      {
	shapeitem *item = (shapeitem *)items[i];
	if ((e=std::max(abs(item->centre.x()),abs(item->centre.y()))+item->extent()+item->strokewidth/2.0) > emax)
	  emax = e;
	break;
      }

    }
  }
*/
  return emax;
}

void CCanvas::auto_zoom()
{
  if (auto_zoom_block)
    return;

  double e = extent();
  int n = std::min(width(),height());
  double z = (double)(n-56)/2.0/e;
//printf("auto_zoom: r=%f, n=%d, z=%f\n",n,r,z);
  setZoom(z*2.0);
}

void CCanvas::toDom(QDomDocument &doc,QDomElement &parent)
{
  QDomElement ca = doc.createElement( "canvas" );
  int i;

  //ca.setAttribute(QString("zoom"),zoom);

  //version.toDom(doc,ca);

  toDom_Text(doc,ca,"zoom",zoom);

  for (i=0;i<items.size();i++)
    items[i]->toDom(doc,ca);

  parent.appendChild(ca);
}

void CCanvas::fromDom(QDomDocument &doc,QDomElement &element)
{
  items.clear();

  //forward = element.attribute("forward", "1").toInt() != 0;

  QDomNode n = element.firstChild();
  while(!n.isNull()) 
  {
    QDomElement e = n.toElement(); // try to convert the node to an element.
    if(!e.isNull())
    {
      if (e.tagName() == "zoom")
        zoom = e.text().toDouble();
      else if (e.tagName() == "textitem1")
      {
	textitem1 *item = new textitem1();
	item->fromDom(doc,e);
	items << item;
      }
      else if (e.tagName() == "textitem2")
      {
	textitem2 *item = new textitem2();
	item->fromDom(doc,e);
	items << item;
      }
      else if (e.tagName() == "boxitem")
      {
	boxitem *item = new boxitem();
	item->fromDom(doc,e);
	items << item;
      }
/*      else if (e.tagName() == "circleitem")
      {
	circleitem *item = new circleitem();
	item->fromDom(doc,e);
	items << item;
      }*/
      else if (e.tagName() == "ellipseitem" || e.tagName() == "circleitem")
      {
	ellipseitem *item = new ellipseitem();
	item->fromDom(doc,e);
	items << item;
      }
      else if (e.tagName() == "polygonitem")
      {
	polygonitem *item = new polygonitem();
	item->fromDom(doc,e);
	items << item;
      }
      else if (e.tagName() == "radialitem")
      {
	radialitem *item = new radialitem();
	item->fromDom(doc,e);
	items << item;
      }
      else if (e.tagName() == "shapeitem")
      {
	shapeitem *item = new shapeitem();
	item->fromDom(doc,e);
	items << item;
      }
    }
    n = n.nextSibling();
  }
}
