/***************************************************************************
 *   Copyright (C) 2004 by Juergen Thies                                   *
 *   layout@juergenthies.de                                                *
 *                                                                         *
 *   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.             *
 ***************************************************************************/
#ifndef DRAWINGFIELD_H
#define DRAWINGFIELD_H

#include <qwidget.h>
#include <qpixmap.h>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QResizeEvent>
#include <QEvent>
#include <QApplication>
#include "elements/cell.h"
#include "elements/celllist.h"
#include "elements/cellref.h"
#include "layers.h"
#include "setup.h"
#include "widgets/selectwidget.h"
#include <qdatetime.h>
#include <qstringlist.h>
#include <qprinter.h>
#include <qtimer.h>
#include <QPolygon>
#include <QMimeData>
#include <QReadWriteLock>
#include "paintpixmapthread.h"
#ifdef netlistutility
#endif
#ifdef backgroundutility
class backgroundModule;
#endif
/*
@author Juergen Thies
*/
//#define drawingfield drawingField 
//#define aktive_layer activeLayer
//#define aktuell_cell currentCell
//#define first_cell firstCell
//#define deleteAktuellCell deleteActuellCell
class elementList;
class baseMode;
//class paintPixmapThread;
//! head class of the drawing
/*!
Each layout main windows has exactly one object of the class drawingField. This object can be accessed via the @link "Class layout;layout class".
In the drawingField all drawing relevant information are accessible. The basic setup is stored in @link "databaseunits%Class drawingField;databaseunits", @link "userunits%Class drawingField;userunits" and @link "userunits%Class drawingField;databaseunits". The different cell are accessabe via @link "firstCell%Class drawingField;firstCell". @link "currentCell%Class drawingField;currentCell" holds a point to the curretnly displayed cell.

All members of the drawingField class are useable in a simplyfied form without braces, commas and semicolons from the commandline-toolbar. The characters are essential, if used in a macro.
*/
class drawingField : public QWidget
{
Q_OBJECT
private:
    // Prevent instances from being copied.
    drawingField(const drawingField &);
    drawingField &operator=(const drawingField &);

public:
	int paintNode;
	QString paintDevice;
	bool autorepaint;
private:
   paintPixmapThread *pixmap;
   bool mousemove;    //click or press moved
   int mouseStatus;  // modifiers on mouse pressed
   
   QPoint mousePos, mouseDrawingPos;
   bool mouseVisible;
   int mouseButton;
   Qt::KeyboardModifiers mouseModifiers;
   void prepareOutput();
   //paintPixmapThread *paintPixmap;
#ifdef  _MSC_VER
   cellref cellrefPaint;
#else
   cellref::cellref cellrefPaint;
#endif
   int paintMode; // mode during painting
   strans cellrefTrans;
   quint8 paintDetailLevel;
   void calcDetails(){ if (paintDetailLevel==0) paintDetailLevel=99;}
   int defaultMode;
protected:
            bool eventFilter(QObject *obj, QEvent *event);
#ifdef backgroundutility
backgroundModule *bgModule;
#endif
public:
//! list of all cell
/*!
This is a list of all cells in the drawing.
*/
   cellList *firstCell;
//! current cell
/*!
This is a pointer on the cell displayed.
*/
   cell *currentCell;
   cell *cell_ref;
private:
   pointArray pointarray;
   QPoint minPoint;
   QPoint maxPoint;
   QPoint mousepress;
   elementList *elementUsed;
   QList<element*> elementExcluded;
   bool elementUsedLocked;

QTimer dragTimer;
QPoint dragPoint;
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
bool dragDropRunning;
void writeMimeData(QMimeData *);
void readMimeData(const QMimeData *);
bool mouseMoveFunction();
private slots:
void startDrag();

public:
//! active layer
/*!
This is the default layer, on which most of the operation take place.
*/  
   int activeLayer;
//! actuell grid in X
/*!
This member holds the actuell X-grid in drawinguntis
*/
   int gridX;
//! actuell grid in Y
/*!
This member holds the actuell X-grid in drawinguntis
*/
   int gridY;
//! actuell grid-offset in X
/*!
This member holds the actuell grid-offset in X in drawinguntis
*/
   int gridOffsetX;
//! actuell grid-offset in Y
/*!
This member holds the actuell grid-offset in Y in drawinguntis
*/
   int gridOffsetY;
private:
   bool snapGrid;
   bool snapPoint;
   bool snapLine;
   bool snapMiddle;
   bool snapCenter;
   bool snapIntersection;
   bool modifyStatus;
public:
//! automatic grid
/*!
If this member is true, the grid is automaticly change after changing the scale.
*/
   bool gridauto;
   QDate date_modification,date_access;
   QTime time_modification,time_access;
//! userunits
/*!
All values in the main widget are displayed in this unit.
*/
   double userunits;
//! databaseunits
/*!
All coordinates are integer. This value is the factor of these integers to the real value.
*/
   double databaseunits;
//! libname
/*!
Name of this libary as used in GDS-file.
*/
   QString libname;
//! file type
/*!
Gives information on the type of the file, if it was loaded.
*/
   QString fileType;
//! previous cell
/*!
The name of the cell used before the current cell
*/
   QString previousCell;
// macrorecording
   bool record;
   QString macro;
// redo undo
   cell *undo_[20];
   cell *redo_[20];
    drawingField(QWidget *parent = 0, const char *name = 0);
    ~drawingField();

protected:    
  virtual void resizeEvent(QResizeEvent *event);
  virtual void mouseMoveEvent(QMouseEvent *e);
  virtual void mousePressEvent(QMouseEvent *e);
  virtual void mouseReleaseEvent(QMouseEvent *e);
  virtual void leaveEvent(QEvent *e);
  virtual void enterEvent(QEvent *e);
  virtual void wheelEvent(QWheelEvent *e);
  virtual void paintEvent ( QPaintEvent * e );
  void setMouseHelp();
signals:
  void requestFontSetup();
  void undoEnable(bool b);
  void redoEnable(bool b);
  void message(QString s);
  void mousePosChange(QPoint pos);
  void mousePosDifChange(QPoint pos,QPoint dif);
  void cellsChange();
  void gridChange();
  void rightclick();
  void rightclick(QMenu *m);
  void selectChange(elementCount c);
  void selectReset();
  void report(QString s,int rang);
  void painted();
  void tabPressed();
  void currentCellChanged();
  void activeLayerChanged();
  void changed(char c);
  void moveByRequest();
  void drawingTime(int time);
  void detailedLevelChanged(quint8 level);
  void newMode(int mode);
  void removeAllCells();
  void saveOpenAccess(QString filename);
public:
//! modified status
/*!
@return true ,if the design was modifies after the last save
@nomacro
*/ 
   bool modified(){ return modifyStatus;}
//! set modified changed
/*!
marks the design to be modified
@nomacro
*/ 
   void setModifyChanged(){modifyStatus=true;emit changed(2);}
//! set modified added
/*!
marks the design shapes to be added
@nomacro
*/
   void setModifyAdded(){modifyStatus=true;emit changed(1);}
//! set modified no
/*!
marks the design not to be modified
@nomacro
*/
   void setModifySaved(){modifyStatus=false;emit changed(0);}
public slots:
// contentsmenu items
void contextMainMenu();
void contextProperties();
void contextMoveScale();
void contextCopyMove();
void contextGroup();
void contextRotate();
void contextMirror();
void contextDelete();
void contextMoveLayer();
void contextToPolygon();
void contextAddElementUsed();

//
  void setDetailLevelAuto(){
        paintDetailLevel=99;
	emit detailedLevelChanged(99);
	}
  void setDetailLevelAll(){
        paintDetailLevel=1;
	emit detailedLevelChanged(1);
	}
  void setDetailLevel1(){
        paintDetailLevel=2;
	emit detailedLevelChanged(2);
	}
  void setDetailLevel2(){
        paintDetailLevel=3;
	emit detailedLevelChanged(3);
	}
  void setDetailLevel3(){
        paintDetailLevel=4;
	emit detailedLevelChanged(4);
	}
  void showMessage(QString s){emit message(s);};
  void showReport(QString s,int rang){emit report(s,rang);};
  void emitSelectChange(elementCount c){emit selectChange(c);}
//! recount selected elements
/*!
triggers a recount of selected elements
@nomacro
*/
  void recountSelect();
//! paint
/*!
triggers a repaint of the design
@nomacro
*/
  void paint();
  void forcePaint();
  void nop(){}; // only to avoid warnings on SLOT macro
//select
//! fselect
/*!
Activates the fselect mode.
@nomacro
*/
  void setFselectMode(){mode=10;modestep=0;setMouseHelp();}
//! fdeselect
/*!
Activates the fdeselect mode.
@nomacro
*/
  void setFdeselectMode(){mode=15;modestep=0;setMouseHelp();}
  void setFselectModes(){
	if (QApplication::keyboardModifiers ()==Qt::ShiftModifier) setFdeselectMode();
	else setFselectMode();
	}
//! pselect
/*!
Activates the pselect mode.
@nomacro
*/
  void setPselectMode(){mode=20;modestep=0;setMouseHelp();}
//! pdeselect
/*!
Activates the pdeselect mode.
@nomacro
*/
  void setPdeselectMode(){mode=25;modestep=0;setMouseHelp();}
  void setPselectModes(){
	if (QApplication::keyboardModifiers ()==Qt::ShiftModifier) setPdeselectMode();
	else setPselectMode();
	}
//! cselect
/*!
Activates the cselect mode.
@nomacro
*/
  void setCselectMode(){reset();mode=30;modestep=0;setMouseHelp();}
//! cdeselect
/*!
Activates the cdeselect mode.
@nomacro
*/
  void setCdeselectMode(){reset();mode=35;modestep=0;setMouseHelp();}
  void setCselectModes(){
	if (QApplication::keyboardModifiers ()==Qt::ShiftModifier) setCdeselectMode();
	else setCselectMode();
	}
public:
//! form select
/*!
If one coordinate was added before with the point or p command, the nearest element is selected.
If two coordinate were added before with the point or p command, all element in the region p1,p2 are selected.
*/
  void fSelect();
//! form all select
/*!
If two coordinate were added before with the point or p command, all element in the region p1,p2 are selected. All Points of the element must be inside the region.
*/
  void fAllSelect();
//! form deselect
/*!
If one coordinate was added before with the point or p command, the nearest element is deselected.
If two coordinate were added before with the point or p command, all element in the region p1,p2 are deselected.
*/
  void fDeselect();
//! form deselect
/*!

If two coordinate were added before with the point or p command, all element in the region p1,p2 are deselected. All Points of the element must be inside the region.
*/
  void fAllDeselect();
//! form select
/*!
If one coordinate was added before with the point or p command, the nearest point is selected.
If two coordinate were added before with the point or p command, all points in the region p1,p2 are selected.
*/
  void pSelect();
//! form deselect
/*!
If one coordinate was added before with the point or p command, the nearest point is deselected.
If two coordinate were added before with the point or p command, all points in the region p1,p2 are deselected.
*/
  void pDeselect();
//! form select
/*!
If one coordinate was added before with the point or p command, the nearest cellref is selected.
If two coordinate were added before with the point or p command, all cellrefs in the region p1,p2 are selected.
*/
  void cSelect();
//! form deselect
/*!
If one coordinate was added before with the point or p command, the nearest cellref is deselected.
If two coordinate were added before with the point or p command, all cellrefs in the region p1,p2 are deselected.
*/
  void cDeselect();
//! invert select
/*!
The selection in the current cell is inverted.
@see @link "Invert Selection". 
*/
  void invertSelect(){currentCell->invertSelect();}
//! select all
/*!
All elements in the current cell are selected.
@see @link "Select All". 
*/
  void selectAll(){
	currentCell->selectAll();
	}
//! select visible
/*!
All visible elements in the current cell are deselected.
@see @link "Select Visible". 
*/
  void selectVisible(){
	currentCell->selectVisible();
	}
//! deselect all
/*!
All elements in the current cell are deselected.
@see @link "Deselect All". 
*/
  void deselectAll(){
	currentCell->deselectAll();
	}
//! select active layer
/*!
All elements on the active layer are selected.
@see @link "Layer Select". 
*/
  void selectActiveLayer(){
	currentCell->selectLayer(activeLayer);
	}
//! deselect active layer
/*!
All elements on the active layer are deselected.
@see @link "Layer Deselect".
*/
  void deselectActiveLayer(){
	currentCell->deselectLayer(activeLayer);
	}
//! path select
/*!
All visible path elements in the current cell are selected.
@see @link "Path Select".
*/
void pathSelect(){
	currentCell->pathSelectVisible();
	}
//! path deselect
/*!
All path elements in the current cell are deselected.
@see @link "Path Deselect".
*/
void pathDeselect(){
	currentCell->pathDeselect();
	}
//! box select
/*!
All visible boxes in the current cell are selected.
@see @link "Box Select".
*/
void boxSelect() {
	currentCell->boxSelectVisible();
	}
//! box deselect
/*!
All boxes in the current cell are deselected.
@see @link "Box Deselect".
*/
void boxDeselect() {
	currentCell->boxDeselect();
	}
//! polygon select
/*!
All visible polygons in the current cell are selected.
@see @link "Polygon Select".
*/
void polygonSelect() {
	currentCell->polygonSelectVisible();
	}
//! polygon deselect
/*!
All polygons in the current cell are deselected.
@see @link "Polygon Deselect".
*/
void polygonDeselect(){
	currentCell->polygonDeselect();
	}
//! text select
/*!
All visible text elements in the current cell are selected.
@see @link "Text Select".
*/
void textSelect(){
	currentCell->textSelectVisible();
	}
//! text select
/*!
All text elements having the text 'textname' are selected..
*/
void selectText(QString textname){
	currentCell->selectText(textname);
	}
//! select cellref
/*!
All cellref to cells named cellname are selected
*/
void selectCellref(QString cellname){
	currentCell->selectCellref(cellname);
	}
//! tetxt deselect
/*!
All text elements in the current cell are deselected.
@see @link "Text Deselect".
*/
void textDeselect(){
	currentCell->textDeselect();
	}
public slots:
//draw
//! box mode
/*!
Activates the box mode.
@nomacro
*/
  void setBoxMode(){
	mode=100;
	modestep=0;
	setMouseHelp();
	}
//! polygon mode
/*!
Activates the polygon mode.
@nomacro
*/
  void setPolygonMode(){
	mode=110;
	modestep=0;
	setMouseHelp();
	}
//! box cell ref mode
/*!
Activates the cellref mode.
@nomacro
*/
  void setCellrefMode(cell *cell_){
	if (cell_==NULL)  {emit newMode(120);emit newMode(mode);return;}
	cell_ref=cell_;
	mode=120;modestep=0; 
	maxPoint=QPoint(0,0);
	minPoint=QPoint(0,0);
	uint help;
	cell_->paintInfoGet(&minPoint,&maxPoint,&help);
	setMouseHelp();
	cellrefTrans.reset();

	}
//! cell ref arrray mode
/*!
Activates the cell ref array mode.
@nomacro
*/
  void setCellrefArrayMode(cell *cell_,int nx=2, int ny=1){
	if (cell_==NULL)  {emit newMode(130); emit newMode(mode);return;}
	cell_ref=cell_;
	pointarray.resize(3);
	if (nx<1) nx=1;
	if (ny<1) ny=1;
	pointarray.setPoint(2,QPoint(nx,ny));
	mode=130;
	modestep=0;  
	maxPoint=QPoint(0,0);
	minPoint=QPoint(0,0);
	uint help;
	cell_->paintInfoGet(&minPoint,&maxPoint,&help);
	setMouseHelp();
	cellrefTrans.reset();
	}
//! text mode
/*!
Activates the text mode.
@nomacro
*/
  void setTextMode(){
	mode=140;
	modestep=0;
	setMouseHelp();
	}
//! path mode
/*!
Activates the path mode.
@nomacro
*/
  void setPathMode(){
	mode=150;
	modestep=0;
	setMouseHelp();
	}
//! ruler mode
/*!
Activates the ruler mode.
@nomacro
*/
  void setRulerMode(){
	mode=180;
	modestep=0;
	setMouseHelp();
	}
//! length mode
/*!
Activates the length mode.
@nomacro
*/
  void setLengthMode(){
	mode=181;
	modestep=0;
	setMouseHelp();
	}
//! length element mode
/*!
Activates the length element mode.
@nomacro
*/
  void setLengthElementMode(){
	mode=182;
	modestep=0;
	setMouseHelp();
	}
//! element size mode
/*!
Activates the element size mode.
@nomacro
*/
  void setElementSizeMode(){
	mode=183;
	modestep=0;
	reset();
	setMouseHelp();
	}
//! angle mode
/*!
Activates the angle mode.
@nomacro
*/
  void setAngleMode(){
	mode=185;
	modestep=0;
	setMouseHelp();
	}
//! circle fit mode
/*!
Activates the circle fit mode.
@nomacro
*/
  void setCircleFitMode(){
	mode=188;
	modestep=0;
	setMouseHelp();
	}
//! circle box mode
/*!
Activates the circle box mode.
@nomacro
*/
  void setCircleBoxMode(){
	mode=189;
	modestep=0;
	setMouseHelp();
	}
//! spiral mode
/*!
Activates the  spiral mode.
@nomacro
*/
  void setSpiralMode(){
	mode=190;
	modestep=0;
	setMouseHelp();
	}
//! circle mode
/*!
Activates the circle mode.
@nomacro
*/
  void setCircleMode(){
	mode=191;
	modestep=0;
	setMouseHelp();
	}
//! sector mode
/*!
Activates the sector mode.
@nomacro
*/
  void setSectorMode(){
	mode=192;
	modestep=0;
	setMouseHelp();
	}
//! arc mode
/*!
Activates the arc mode.
@nomacro
*/
  void setArcMode(){
	mode=193;
	modestep=0;
	setMouseHelp();
	}
//! polygon arc mode
/*!
Activates the polygon arc mode.
@nomacro
*/
  void setPolygonArcMode(){
	mode=194;
	modestep=0;
	setMouseHelp();
	}
//! bezier 2 mode
/*!
Activates the bezier 2 mode.
@nomacro
*/
  void setBezier2Mode(){
	mode=195;
	modestep=0;
	setMouseHelp();
	}
//! bezier 3 mode
/*!
Activates the bezier 3 mode.
@nomacro
*/
  void setBezier3Mode(){
	mode=196;
	modestep=0;
	setMouseHelp();
	}
//! zoom mode
/*!
Activates the zomm mode.
@nomacro
*/
  void setZoomMode(){
	mode=200;
	modestep=0;
	setMouseHelp();
	}
//! mirror mode
/*!
Activates the morror mode.
@nomacro
*/
  void setMirrorMode(){
	mode=300;
	modestep=0;
	setMouseHelp();
	}
//! move x mode
/*!
Activates the move x mode.
@nomacro
*/
  void setMoveXMode(){
	mode=308;
	modestep=0;
	setMouseHelp();
	}
//! move y mode
/*!
Activates the move y mode.
@nomacro
*/
  void setMoveYMode(){
	mode=309;
	modestep=0;
	setMouseHelp();
	}
//! move mode
/*!
Activates the move mode.
@nomacro
*/
  void setMoveMode(){
	mode=310;
	modestep=0;
	setMouseHelp();
	}
//! move point mode
/*!
Activates the move point mode.
@nomacro
*/
  void setMovePointMode(){
	mode=312;
	modestep=0;
	elementUsed=NULL;
	setMouseHelp();
	}
//! insert point mode
/*!
Activates the box mode.
@nomacro
*/
  void setInsertPointMode(){
	mode=313;
	modestep=0;
	elementUsed=NULL;
	setMouseHelp();
	}
//! cell origin mode
/*!
Activates the cell origin mode.
@nomacro
*/
  void setCellOriginMode(){
	mode=315;
	modestep=0;
	setMouseHelp();
	}
//! rotate mode
/*!
Activates the rotate mode.
@nomacro
*/
  void setRotateMode(){
	mode=320;
	modestep=0;
	setMouseHelp();
	}
//! copy mode
/*!
Activates the copy mode.
@nomacro
*/
  void setCopyMode(){
	mode=330;
	modestep=0;
	setMouseHelp();
	}
//! cut mode
/*!
Activates the cut mode.
@nomacro
*/
  void setCutMode(){
	mode=340;
	modestep=0;
	setMouseHelp();
	}
//! scale mode
/*!
Activates the scale mode.
@nomacro
*/
  void setScaleMode(){
	mode=350;
	modestep=0;
	setMouseHelp();
	}
//! properties mode
/*!
Activates the properties mode.
@nomacro
*/
  void setPropertiesMode(){
	mode=400;
	modestep=0;
	elementUsedLocked=false;
	setMouseHelp();
	}
//! command mode
/*!
Activates the command mode.
@nomacro
*/
  void setCommandMode(){
	mode=1;
	modestep=0;
	setMouseHelp();
	}
  void setDefaultMode(int dm){
	defaultMode=dm;
	mode=defaultMode;
	modestep=0;
	setMouseHelp();
	}
  void setDefaultMode(){
	mode=defaultMode;
	modestep=0;
	setMouseHelp();
	}
//! align center mode
/*!
Activates the align center mode.
@nomacro
*/
  void setAlignCenterMode(){
	mode=500;
	modestep=0;
	setMouseHelp();
	}
//! align center x mode
/*!
Activates the align center x mode.
@nomacro
*/
  void setAlignCenterXMode(){
	mode=501;
	modestep=0;
	setMouseHelp();
	}
//! align center y mode
/*!
Activates the align center y mode.
@nomacro
*/
  void setAlignCenterYMode(){
	mode=502;
	modestep=0;
	setMouseHelp();
	}
//! set center mode
/*!
Activates the set center mode.
@nomacro
*/
  void setCenterMode(){
	mode=503;
	modestep=0;
	setMouseHelp();
	}
//! set center x mode
/*!
Activates the set center x mode.
@nomacro
*/
  void setCenterXMode(){
	mode=504;
	modestep=0;
	setMouseHelp();
	}
//! set center y mode
/*!
Activates the set center y mode.
@nomacro
*/
  void setCenterYMode(){
	mode=505;
	modestep=0;
	setMouseHelp();
	}
//! align left mode
/*!
Activates the aglin left mode.
@nomacro
*/
  void setAlignLeftMode(){
	mode=510;
	modestep=0;
	setMouseHelp();
	}
//! align right mode
/*!
Activates the align right mode.
@nomacro
*/
  void setAlignRightMode(){
	mode=512;
	modestep=0;
	setMouseHelp();
	}
//! align top mode
/*!
Activates the align top mode.
@nomacro
*/
  void setAlignTopMode(){
	mode=514;
	modestep=0;
	setMouseHelp();
	}
//! align bottom mode
/*!
Activates the align bottom mode.
@nomacro
*/
  void setAlignBottomMode(){
	mode=516;
	modestep=0;
	setMouseHelp();
	}
//! align value mode
/*!
Activates the align value mode.
@nomacro
*/
  void setAlignValueMode(){
	mode=520;
	modestep=0;
	setMouseHelp();
	}
//! select cell mode
/*!
Activates the select cell mode.
@nomacro
*/
  void setSelectCellMode(){
	mode=600;
	modestep=0;
	setMouseHelp();
	}
  //void setPlaceCellMode(cell *cell_,QList<pointArray> connections,QString devicename);
  //void setRouteMode(QList<pointArray> connections,QString nodename);
  /*void setRouteMode(){
  QList<pointArray> connections;
  setRouteMode(connections,"node_unnamed");
  }*/
//! set node mode
/*!
Activates the set node mode.
@nomacro
*/
  void setNodeMode(){
    paintNode=-1;
	mode=170;modestep=0; 
	setMouseHelp();
  }
//! show node mode
/*!
Activates the show node mode.
@nomacro
*/
  void showNode(int i){
    paintNode=i;
	mode=170;modestep=1; 
	setMouseHelp();
	paint();
  }
//! show device mode
/*!
Activates the show device mode.
@nomacro
*/
  void showDevice(QString device){
    paintDevice=device;
	mode=170;modestep=2; 
	setMouseHelp();
	paint();
  }
//! show device node mode
/*!
Activates the show device node mode.
@nomacro
*/
  void showDeviceNode(QString device,int i){
    paintDevice=device;
	paintNode=i;
	mode=170;modestep=3; 
	setMouseHelp();
	paint();
  };

  int getGrid(){return (gridX+gridY)/2;};
public:
 //! set grid
/*!
The grid in x and y axis (@link "gridX%Class drawingField;gridX", @link "gridY%Class drawingField;gridY") is set to raster. The gridoffset (@link "gridOffsetX%Class drawingField;gridOffsetX", @link "gridOffsetY%Class drawingField;gridOffsetY") is reseted. 
@param raster grid in @link "databaseunits%Class drawingField;databaseunits"
*/
  void setGrid(int raster){gridX=raster;gridY=raster,gridOffsetX=0;gridOffsetY=0;}
//! set cell
/*!
Set the Cell with the name cell to the currentCell. @link "currentCell%Class drawingField;currentCell" is set to the new set cell.
@param cell cellname of the cell to be displayed. 
*/
  void setCell(const QString &cell);
//! set cell
/*!
Set the Cell to the currentCell. @link "currentCell%Class drawingField;currentCell" is set to the new set cell.
@param cell pointer to the cell to be displayed. 
*/
  void setCell(const cell *Cell);
//! relink cellref
/*!
Selected cellreferences of the current cell are relinked to the cell with the name cell. There are not tests for circular or self references. 
@param cell cellname to be linked
*/
  void relink(const QString &cell);
//! cell up
/*!
A cell which uses the current cell is set as the current cell.
@see @link "Cell Up".
*/
  void cellUp();
public slots:
  void cellUpGui();
  void setSelectCellModeCellUp(){
	if (QApplication::keyboardModifiers ()==Qt::ShiftModifier) cellUpGui();
	else if (QApplication::keyboardModifiers ()==Qt::ControlModifier) setPreviousCellGui();
	else setSelectCellMode();
	}


  void setCellGui(const QString &s); //used in layout::setCell();
  void setPreviousCellGui();
  void forceCellGui(const QString &s);
public:
//! merge select
/*!
Selected elements in the currentCell are merged. The orginal shape is use to build the path to inner polygons. The function works for a small amount of elements. Use the @link "Class booleanHandler;booleanHandler" to merge a large amount of element.
@see @link "Merge".
*/
  void mergeSelect();
//! delete select
/*!
Selected elements/points in the currentCell are deleted.
@see @link "Delete".
*/
  void deleteSelect();
//view
public slots:
//! scale plus
/*!
The scale is increased,
@see @link "Zoom In".
*/
  void scalePlus();
//! scale minus
/*!
The scale is decreased,
@see @link "Zoom Out".
*/
  void scaleMinus();
//! scale full
/*!
The display scale is adjusted to the size of the drawing.
@see @link "Zoom Fit All".
*/
  void scaleFull();
  void scaleFullGui();
  void scaleSelectGui();
  void scalePlusMinus(){
	if (QApplication::keyboardModifiers ()==Qt::ShiftModifier) scalePlus();
	else if(QApplication::keyboardModifiers ()==Qt::ControlModifier) scaleMinus();
	else scaleFull();
 }
//! scale select
/*!
The display scale is adjusted to the size of all selected elements.
@see @link "Zoom Fit Selection".
*/
  void scaleSelect();
//! scale ein
/*!
The current view is scaled to 1 drawingunit to 1 pixel
@see @link "Zoom Eins".
*/
  void scaleEins();
//! scale points
/*!
The current view is scaled so that the rectangular created by both point is visible with the maximal size.
*/
  void scale(QPoint p1, QPoint p2);
//! scroll left
/*!
The current view is scrolled left.
@see @link "Scroll Left".
*/
  void scrollLeft();
//! scroll right
/*!
The current view is scrolled right.
@see @link "Scroll Right".
*/
  void scrollRight();
//! scroll up
/*!
The current view is scrolled up.
@see @link "Scroll Up".
*/
  void scrollUp();
//! scroll down
/*!
The current view is scrolled down.
@see @link "Scroll Down".
*/
  void scrollDown();
public:
//! set view
/*!
The current view is set to the scale and offset p(x,y).
*/
void setView(double scale,int x,int y);
//! get view
/*!
The current view is returned: scale and offset p(x,y).
*/
void getView(double *scale,int *x,int *y);
//! toggle grid
/*!
Show/hide the visibility of the grid.
@see @link "Show Grid".
*/
  void showGridToggle();
//! auto grid
/*!
Activate the autogrid.
@see @link "Grid Automatic".
*/
  void setAutoGrid();

//undo redo
//! undo
/*!
Undo the last modification. Multiply use is not possible.
@see @link "Undo".
*/
  void undo();
//! redo
/*!
Revoke the last undo.
@see @link "Redo".
*/
  void redo();
//! prepare undo.
/*!
Save the cell for the next undo.
*/
  void prepareUndo();
//! reset undo
/*!
Reset the last undo.
*/
  void resetUndo();
  void updateCellref(cell *oldCell, cell* newCell);

//input/output  
//! open file
/*!
A file with the name s is opened.
*/
  void openFile(QString s);
//! open open access
/*!
opens the given openaccess view as layout
@nomacro
*/
  void openView(QString library,QString cellName,QString viewName);
//! save file
/*!
The drawing is saved to s.
*/
  void saveFile(QString s);
//! import file
/*!
The file s is added to the current drawing.
*/
  void importFile(QString s);
//! update file
/*!
Cell with the same cellname with cell in the file s are replaced by the cell of this file.
*/
  void updateFile(QString s);
//! screenshot
/*!
The screen will be saved in the file with the name filename. The type is selected by the extension.
*/ 
    void saveScreenshot(QString filename);
  void print(QPrinter *p);
//tools
  QStringList undependendCells();
//! find cell
/*!
@return pointer to the cell with name s. Null if the name does not exist.
*/
  cell* findCell(QString s);
//! exist cell
/*!
@return true if a cell with the name s exist.
*/
  bool existCellname(QString s);
  bool depend(cell *cell_);
//! add cell
/*!
Add a cell to the drawing. A pointer to the new cellList is returned.
*/
  cellList *addCell();
//! new cell
/*!
A new empty cell will be added, named with an unused cell name and it is set as current cell.
*/ 
    void newCell();
  
//! delete cell
/*!
The current cell is deleted.
*/
  void deleteCurrentCell();
//! delete actuell cell
/*!
The current cell is deleted.
OBSOLETE: Please use deleteCurrentCell() instead.
*/ 
  void deleteActuellCell(){deleteCurrentCell();}
  
//! add point
/*!
Set the Command Mode and add the point p(x,y) in drawing units.
*/
  void point(int x,int y);
//! add point userunits
/*!
Set the Command Mode and add the point p(x,y) in user units.
*/
  void p(double x,double y);
//! add relative point
/*!
Set the Command Mode and add the point p(x,y) in drawing units relative to the last point entered. The first entered point is set absolute.
*/
  void pointRel(int x,int y);
//! add relative point userunits
/*!
Set the Command Mode and add the point p(x,y) in user units relative to the last point entered. The first entered point is set absolute.
*/
  void pRel(double x,double y);
//! add relative point userunits with direction
/*!
Set the Command Mode and add the point p(length,dir) in user units relative to the last point entered. Dir is the angle to the x-axis.
*/
  void pDir(double length,double dir);
//! add point
/*!
Set the Command Mode and add the point p relative to the last point entered. The first entered point is set absolute.
*/
  void pointRel(QPoint p);
//! move last point
/*!
The last entered point is moved by point p(x,y).
*/
  void pointMove(int x,int y);
//! move last point
/*!
The last entered point is moved by point p(x,y) in user units.
*/
  void pMove(double x,double y);
//! move last point
/*!
The last entered point is moved by point p(x,y).
*/
  void pointMove(QPoint p);
//! delete point
/*!
Delete the last entered point.
*/
  void delPoint();
//! clear points
/*!
Delete all entered point.
*/
  void clearPoints();
//! add point
/*!
Set the Command Mode and add the point p.
*/
  void point(QPoint p);
//! add box
/*!
Add a box to the current cell. Two coordinates had to be entered before with the point command.
*/
  void box();
//! add dot
/*!
Add a box to the current cell. Two coordinates had to be entered before with the point command.The first point is the center point, the second point is a corner point.
*/
  void dot();
//! add polygon
/*!
Add a polygon to the current cell. Three coordinates had to be entered before with the point command.
*/
  void polygon();
//! add path
/*!
Add a path to the current cell. Two coordinates had to be entered before with the point command.
*/
  void path();
//! add text
/*!
Add a text to the current cell. One coordinate had to be entered before with the point command.
*/
  void text(QString s);
//! add cellref
/*!
Add a cellref to the current cell. One coordinate had to be entered before with the point command. This point is the reference point of the insert cellref.
*/
  void cellRef(QString s);
//! add text
/*!
Add an array of cellref's to the current cell. Two coordinates have to be entered before calling this function using the point command. The first point is the reference point of the inserted array of cellref. The second point defines the spacing grid. The cellref is arrayed 'x' times in the x-dimension and 'y' time in the y-dimension.
*/
  void cellrefarray(QString s,int x, int y);
//! add spiral
/*!
Add a spiral path to the current cell. Three coordinates had to be entered before with the point command.
*/
  void spiral();
//! add circle
/*!
Add a circular polygon to the current cell. Two coordinates had to be entered before with the point command. The first entered point is the center, the second point mark the radius.
*/
  void circle();
//! add circle in box
/*!
Add a circular polygon to the current cell. Two coordinates had to be entered before with the point command. The two points mark a bounding square in which the circle is added.
*/
  void circleBox();
//! fit to circle
/*!
Add a circular polygon to the current cell. The circle is fitted to the before entered points.
*/
  void circleFit();
//! add ellipse
/*!
Add a ellipse to the current cell. Two coordinates had to be entered before with the point command. The two points mark a bounding square in which the ellipse is added.
*/
  void ellipse();
//! add sector
/*!
Add a sector polygon to the current cell. Three coordinates had to be entered before with the point command.
*/
  void sector();
//! add arc
/*!
Add a arc path to the current cell. Three coordinates had to be entered before with the point command.
*/
  void arc();
//! add polygon arc
/*!
Add a arc polygon to the current cell. Three coordinates had to be entered before with the point command.
*/
  void polygonArc();
//! add bezier 2nd order
/*!
Add a second order bezier path to the current cell. Three coordinates had to be entered before with the point command.
*/
  void bezier2();
//! add bezier 3rd order
/*!
Add a third order bezier path to the current cell. Four coordinates had to be entered before with the point command.
*/
  void bezier3();
//! top cell
/*!
@return cell which is not referred by an other cell.
*/
  cell* findTopCell();
  QList<cell*> findTopCells();
//! compare cell
/*!
Compares the current cell with the cell s. Non identical elements will be selected in both cells. All other elements will be deselected.
*/
void compareCell(QString s);
//! delete except one layer
/*!
All element not on the layer "layer" will be delete in any cell of the current drawing. The function can be useful for preparing data for mask production.
*/
  void deleteExceptOneLayer(int layer);
//! swap layer
/*!
This function swap the layers i and k in the current cell.
*/
  void swapLayer(int i,int k);
//! swap layer select
/*!
This function swap the layers i and k of the selected elements in the current cell.
*/
  void swapLayerSelect(int i,int k);
//! swap layer all cells
/*!
This function swap the layers i and k in all cells of the current drawing.
*/
  void swapLayerAll(int i,int k);
//! map layer
/*!
all elements are maped with layerTranslator t.
*/
 void mapLayer(layerTranslator *t);
//! flatten
/*!
Selected cellrefs and cellrefarrays are flatten.
@see @link "Cell Flat". 
*/
  void flat();
//! flatten multilevel
/*!
Selected cellrefs and cellrefarrays are flatten. If the the cellrefs contain more cellrefs, they are flatten as well.
@see @link "Cell Flat Multilevel". 
*/
  void flatAll();
//! simple group selected elements
/*!
All selected elements are moved to a new cell. A correlating cellref will be added.
@see @link "Group Simple". 
*/ 
  void groupSimple();
//! group selected elements
/*!
All selected elements are moved to a new cell. A correlating cellref will be added. If a identical cell exists, a cellref to this cell is added and the selected elements are deleted.
@see @link "Group". 
*/ 
  void group();
//! group selected elements
/*!
All selected elements are moved to a new cell. A correlating cellref will be added. If a identical cell exists, a cellref to this cell is added and the selected elements are deleted. <br>
Identical structures in the current cell are also replaced by a cellref. The number of replaced structures is returned.
@see @link "Group Structure". 
*/ 
  int groupStructure();
//! group selected elements
/*!
All selected elements are moved to a new cell. A correlating cellref will be added. If a identical cell exists, a cellref to this cell is added and the selected elements are deleted. <br>
Identical structures in complete library are also replaced by a cellref. The number of replaced structures is returned.
@see @link "Group Global". 
*/ 
  int groupGlobal();
//! convert to box
/*!
Selected polygons are converted to a box-element if possible.
@see @link "Convert to Box".
*/
  void toBox();
//! convert to polygon
/*!
Selected path, box and text elements are converted to a polygons if possible.
@see @link "Convert to Polygon".
*/
  void toPolygon();
//! to circle
/*!
Converts selected element polygon and box element to a circle. The circle is fitted in all existing points of the element.
@see @link "Convert to Circle".
*/
  void toCircle();
//! close to polygon
/*!
Closes selected path elements to a polygon.
*/
  void closeToPolygon();
//! converts path to polygon if closed
/*!
Converts selected path elements to a polygon, if the last point is identical with the first point.
*/
  void closedPathToPolygon();
//! move select
/*!
If one coordinate was added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command, selected elements are moved by p1.
If two coordinate were added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command, selected elements are moved by p2-p1.
*/
  void move();
//! move x select
/*!
Selected elements are moved in x axis by p2-p1. Two coordinates had to be added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command.
*/
  void moveX();
//! move y select
/*!
Selected elements are moved in y axis by p2-p1. Two coordinates had to be added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command.
*/
  void moveY();
//! move orgin
/*!
The orgin of the current cell is move to the prior entered point. All references to this cell are adjusted.
*/
  void moveOrigin();
//! cut select
/*!
Selected elements between p1 and p2 are separated. Two coordinates had to be added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command.
*/
  void cut();
//! mirror select
/*!
Selected elements are mirror between p1 and p2. Two coordinates had to be added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command.
*/
  void mirror();
//! rotate select
/*!
Selected elements are rotate by angle at a point prior added with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command.
@param angle rotating angle in deg.
*/
  void rotate(double angle);
//! copy select
/*!
If one coordinate was added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command, selected elements are copyed and moved by p1.
If two coordinate were added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command, selected elements are copyed and moved by p2-p1.
*/
  void copy();
//! copy select array
/*!
If one coordinate was added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command, selected elements are copyed in a array by p1.x() and p1.y().
If two coordinate were added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command, selected elements are copyed and moved by (p2-p1).x() and (p2-p1).y().
*/
  void arrayCopy(int nx, int ny );
//! scale select
/*!
Three coordinates had to be added before with the @link "point%Class drawingField;point()" or @link "p%Class drawingField;p()" command.
*/
  void scale();

//! set width
/*!
The width of selected path and text elements is set to w.
@param w width in @link "databaseunits%Class drawingField;databaseunits".
*/
  void setWidth(int w);
//! set cap
/*!
In selected path elements the caps is set to w. (0 for no cap, 1 for round caps, 2 for square caps)
*/
  void setCap(int w);
//! copy current cell
/*!
The current cell is copied. The copied cell is name oldcellname_copy.
@see @link "Copy Current Cell".
*/
  void copyCurrentCell();
//! extract current cell
/*!
The current is flatten multilevel and all other cell are removed
@see @link "Extract Current Cell".
*/
  void extractCurrentCell();
//! strip unneeded
/*!
All cell not needed in the current cell are deleted
@see @link "Strip Unneeded".
*/
  void stripUnneeded();
  //! strip unneeded
/*!
All cell empty cells are deleted
@see @link "Strip Empty Cells".
*/
  void stripEmptyCells();
  //! strip unneeded
/*!
All cell array references in the design are flatten to cell references.
@see @link "Remove Cell Arrays".
*/
  void removeCellArrays();
  //! remove not ortogonal cellrefs
/*!
@see @link "Remove not Orthogonal References".
*/
  void removeNotOrthogonalCellref();
   //! remove sclaed cellrefs
/*!
@see @link "Remove Scaled References".
*/
  void removeScaledCellref(); 
//! strip identical elements
/*!
If the current cell contains two identical elements at the same position, it is impossible to see it. This function will detect this and remove one of the element.
*/
   void stripIdenticalElements();
//! extract active layer
/*!
All element on another than the active layer will be deleted
@see @link "Extract Active Layer".
*/
  void extractActiveLayer();
//! add Convex Polygon
/*!
A convex polygon around all prio entered point is added to the active
layer.
*/
  void addConvexPolygon();
//! add Bounding Box
/*!
A bounding box of the prior entered points is add to the active layer.
*/
  void addBoundingBox();

//debug
  void setMode(baseMode *);
public slots:
  void nextPoint();

public:
//! use layer
/*!
@return true if layer is used in the current design, otherwise false.
*/
  bool useLayer(int layer);
  void deleteCell(cell *);
  void writeViewMacro(QString filename);
  void startMacroRecording();
  void stopMacroRecording(QString filename);
  void macroAdd(QString s){if (record) macro+=s+"\n";}
  static QString str(int i){QString s; s.setNum(i); return s;}
  static QString str(double d){QString s; s.setNum(d,'f'); return s;}
  static QString str(QPoint p){QString s2,s1; s1.setNum(p.x()); s2.setNum(p.y()); return s1+","+s2;}
private:
  QPoint getDUnits(QPoint pos);
  QPoint snap(QPoint pos);
  QPoint perpendicular(const QPoint posCurrent, const QPoint posBase);
  QPoint angleFine(const QPoint posCurrent, const QPoint posBase);
  QPoint angle45(const QPoint posCurrent, const QPoint posBase);
  QPoint square(const QPoint posCurrent, const QPoint posBase);
  QPoint raster(QPoint pos);
  void deleteAllCell();
  static QRect makeRect(QPoint p1, QPoint p2);
  static QRect makeDot(QPoint p1, QPoint p2);
  static QRect makeRectPaintEvent(QPoint p1, QPoint p2);
  static QRect makeDotPaintEvent(QPoint p1, QPoint p2);
  int mode,modestep;
  baseMode *modeHandler;
  void reset();

// mutex on data
   QReadWriteLock mutex;
   void mutexInit();
   bool mutexPaint;
   bool mutexChange;
   bool mutexAdd;
   uint mutexRead;
   QMutex mutexInternal;
public:
   bool mutexPaintTryLock();
   void mutexPaintUnlock();
//!  mutex add try GUI lock
/*!
Simultan access to the design data may be fatal. Some simultan access makes no probelm. To organisize the access a mutex system is used.
Each program had to say the mutex before the acces to the data in which kind it will used the data. Three type are sepatated. Read, Add and Change.
The mutx will answer if this acces is ok or not. You also can decide to wait until the dataacces is avaiable. After the use of the data the mutex had to be freed.
<br>
@code
if drawing.mutexReadTryLock():<br>
&nbsp;&nbsp;# your code to read the data<br>
&nbsp;&nbsp;drawing.mutexReadUnlock()<br>
@endcode
<br>
The methods with 'Gui' will do the same as without it, but show a message the the data is not avaiable.
@nomacro
*/
   bool mutexAddGuiTryLock();
//!  mutex add unlock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   void mutexAddUnlock();
//!  mutex read try lock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   bool mutexReadTryLock();
//!  mutex read try GUI lock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   bool mutexReadGuiTryLock();
//!  mutex read lock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   void mutexReadLock();
//! mutex read unlock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   void mutexReadUnlock();
//! mutex change lock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   void mutexChangeLock();
//! mutex change try lock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   bool mutexChangeTryLock();
//! mutex change GUI lock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   bool mutexChangeGuiTryLock();
//! mutex change unlock
/*!
@see mutexAddGuiTryLock()
@nomacro
*/
   void mutexChangeUnlock();
   void mutexStatus();
private slots:
   void setBlankCursor(){setCursor(QCursor(Qt::BlankCursor));};
   void setWaitCursor(){ setCursor(QCursor(Qt::WaitCursor));};
signals:
   void requestBlankCursor();
   void requestWaitCursor();
#ifdef netlistutility
#endif
private:
// access to mode+emit cellChanged
   friend class drc;
   
// access to snap vars
   friend class layout;
// access to width/heigt,scale
   friend class widget3d;
// access to mode modestep
   friend class paintPixmapThread;
// modes
   friend class baseMode;
   friend class barcodeMode;
   friend class linkMode;
   friend class routeMode;
   friend class placeMode;
   friend class barcodeModule;
   friend class textproperties;
#ifdef SCHEMATIC
   friend class schematicDisplay;
#endif
#ifdef backgroundutility
   friend class backgroundModule;
#endif
private:
   void drawElement(element *e){
	if (mutexPaint) pixmap->imagePainter->drawElement(e);
	else e->paint(pixmap->imagePainter);
}
};

#endif
