You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdewebdev/kimagemapeditor/kimearea.cpp

1750 lines
34 KiB

/***************************************************************************
kimearea.cpp - description
-------------------
begin : Thu Jun 14 2001
copyright : (C) 2001 by Jan Schaefer
email : janschaefer@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <tqbitmap.h>
#include <tqpointarray.h>
#include <tqpainter.h>
#include <tqpixmap.h>
#include <tqimage.h>
#include <tqpen.h>
#include <tqbrush.h>
#include <tqpalette.h>
#include <tqcolor.h>
#include <tqlistview.h>
#include <kdebug.h>
#include "kimearea.h"
#include "kimecommon.h"
#define SELSIZE 7
bool Area::highlightArea;
bool Area::showAlt;
Area::Area()
{
_coords=new TQPointArray();
_selectionPoints= new SelectionPointList();
_selectionPoints->setAutoDelete(true);
_finished=false;
_isSelected=false;
_name=i18n("noname");
_listViewItem=0L;
currentHighlighted=-1;
_type=Area::None;
_highlightedPixmap=0L;
}
Area* Area::clone() const
{
Area* areaClone = new Area();
areaClone->setArea( *this );
return areaClone;
}
TQPointArray* Area::coords() const {
return _coords;
}
TQString Area::getHTMLAttributes() const
{
TQString retStr="";
for (AttributeIterator it = firstAttribute();it!=lastAttribute();++it)
{
retStr+=it.key()+"=\""+it.data()+"\" ";
}
return retStr;
}
Area::~Area() {
delete _coords;
delete _selectionPoints;
delete _highlightedPixmap;
}
bool Area::contains(const TQPoint &) const {
return false;
}
TQString Area::getHTMLCode() const {
return "";
}
TQString Area::attribute(const TQString & name) const
{
return _attributes[name.lower()];
}
void Area::setAttribute(const TQString & name, const TQString & value)
{
_attributes.replace(name.lower(),value);
if (value.isEmpty())
_attributes.remove(name.lower());
}
AttributeIterator Area::firstAttribute() const
{
return _attributes.begin();
}
AttributeIterator Area::lastAttribute() const
{
return _attributes.end();
}
bool Area::setCoords(const TQString &) {
return true;
}
void Area::moveSelectionPoint(TQRect*, const TQPoint &)
{}
// Default implementation; is specified by subclasses
TQString Area::coordsToString() const
{
return "";
}
Area::ShapeType Area::type() const {
return _type;
}
void Area::setArea(const Area & copy)
{
delete _coords;
delete _selectionPoints;
_coords=new TQPointArray(copy.coords()->copy());
_selectionPoints= new SelectionPointList();
currentHighlighted=-1;
// Need a deep copy of the list
for (TQRect *r=copy.selectionPoints()->first();r!=0L;r=copy.selectionPoints()->next())
_selectionPoints->append(new TQRect( r->topLeft(),r->bottomRight() ) );
_finished=copy.finished();
_isSelected=copy.isSelected();
_rect = copy.rect();
for (AttributeIterator it = copy.firstAttribute();it!=copy.lastAttribute();++it)
{
setAttribute(it.key(),it.data());
}
setMoving(copy.isMoving());
// _listViewItem=0L;
}
void Area::setListViewItem(TQListViewItem* item) {
_listViewItem=item;
}
void Area::deleteListViewItem()
{
delete _listViewItem;
_listViewItem = 0L;
}
void Area::setRect(const TQRect & r)
{
_rect=r;
updateSelectionPoints();
}
TQRect Area::rect() const {
return _rect;
}
void Area::setMoving(bool b) {
_isMoving=b;
}
void Area::moveBy(int dx, int dy) {
_rect.moveBy(dx,dy);
for (uint i=0;i<_coords->size();i++) {
int newX=_coords->point(i).x()+dx;
int newY=_coords->point(i).y()+dy;
_coords->setPoint(i,newX,newY);
}
for (TQRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
r->moveBy(dx,dy);
}
}
void Area::moveTo(int x, int y) {
int dx=x-rect().left();
int dy=y-rect().top();
moveBy(dx,dy);
}
uint Area::countSelectionPoints() const
{
return (uint) selectionPoints()->count();
}
int Area::addCoord(const TQPoint & p)
{
_coords->resize(_coords->size()+1);
_coords->setPoint(_coords->size()-1,p);
TQRect *r= new TQRect(0,0,SELSIZE,SELSIZE);
r->moveCenter(p);
_selectionPoints->append(r);
setRect(_coords->boundingRect());
return _coords->size()-1;
}
void Area::insertCoord(int pos, const TQPoint & p)
{
/*
kdDebug() << p.x() << "," << p.y() << endl;
if ( _coords->size()>0 )
{
for (int i=0; i<_coords->size(); i++)
{
if (p==_coords->point(i))
{
kdDebug() << "same Point already exists" << endl;
return;
}
}
}
*/
_coords->resize(_coords->size()+1);
for (int i=_coords->size()-1;i>pos;i--) {
_coords->setPoint(i,_coords->point(i-1));
}
_coords->setPoint(pos, p);
TQRect *r= new TQRect(0,0,SELSIZE,SELSIZE);
r->moveCenter(p);
_selectionPoints->insert(pos,r);
setRect(_coords->boundingRect());
}
void Area::removeCoord(int pos) {
int count=_coords->size();
if (count<4)
{
kdDebug() << "Danger : trying to remove coordinate from Area with less then 4 coordinates !" << endl;
return;
}
for (int i=pos;i<(count-1);i++)
_coords->setPoint(i, _coords->point(i+1));
_coords->resize(count-1);
_selectionPoints->remove(pos);
setRect(_coords->boundingRect());
}
bool Area::removeSelectionPoint(TQRect * r)
{
if (_selectionPoints->contains(r))
{
removeCoord(_selectionPoints->find(r));
return true;
}
return false;
}
void Area::moveCoord(int pos, const TQPoint & p) {
_coords->setPoint(pos,p);
_selectionPoints->at(pos)->moveCenter(p);
setRect(_coords->boundingRect());
}
void Area::setSelected(bool b)
{
_isSelected=b;
if (_listViewItem) {
_listViewItem->setSelected(b);
}
}
void Area::highlightSelectionPoint(int number){
currentHighlighted=number;
}
TQRect Area::selectionRect() const {
TQRect r = rect();
r.moveBy(-SELSIZE*2,-SELSIZE*2);
r.setSize(r.size()+TQSize(SELSIZE*4,SELSIZE*4));
return r;
}
void Area::drawHighlighting(TQPainter & p)
{
if (Area::highlightArea && !isMoving() && _highlightedPixmap)
{
p.setRasterOp(TQt::CopyROP);
TQPoint point = TQPoint(rect().x(),rect().y());
if (point.x()<0)
point.setX(0);
if (point.y()<0)
point.setY(0);
p.drawPixmap( point, *_highlightedPixmap);
}
}
void Area::drawAlt(TQPainter & p)
{
double x,y;
double scalex = p.worldMatrix().m11();
// double scaley = p.worldMatrix().m12();
TQWMatrix oldMatrix = p.worldMatrix();
p.setWorldMatrix(TQWMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() ));
x = (rect().x()+rect().width()/2)*scalex;
y = (rect().y()+rect().height()/2)*scalex;
TQFontMetrics metrics = p.fontMetrics();
int w = metrics.width(attribute("alt"));
x -= w/2;
y += metrics.height()/4;
if (highlightArea)
{
p.setRasterOp(TQt::CopyROP);
p.setPen(TQt::black);
}
else
{
p.setRasterOp(TQt::XorROP);
p.setPen(TQPen(TQColor("white"),1));
}
p.drawText(myround(x),myround(y),attribute("alt"));
p.setWorldMatrix(oldMatrix);
}
void Area::draw(TQPainter & p)
{
// Only draw the selection points at base class
// the rest is done in the derived classes
if (_isSelected)
{
int i=0;
double scalex = p.worldMatrix().m11();
// double scaley = p.worldMatrix().m12();
TQWMatrix oldMatrix = p.worldMatrix();
p.setWorldMatrix(TQWMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() ));
for (TQRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
// Draw a green circle around the selected point ( only when editing a polygon )
if (i==currentHighlighted) {
TQRect r2(0,0,15,15);
r2.moveCenter(r->center()*scalex);
p.setRasterOp(TQt::CopyROP);
p.setPen(TQPen(TQColor("lightgreen"),2));
p.drawEllipse(r2);
p.setRasterOp(TQt::XorROP);
p.setPen(TQPen(TQColor("white"),1));
}
// Draw the selection point
p.setRasterOp(TQt::XorROP);
TQRect r3(*r);
int d = 1;
if (scalex > 2) d=0;
r3.moveCenter( TQPoint((int)(r3.center().x()*scalex),(int)(r3.center().y()*scalex)) );
p.fillRect(r3,TQBrush("white"));
/*
TQRect r3(*r);
r3.moveTopLeft( TQPoint(r3.left()*scalex+2*(scalex-1), r3.top()*scalex+2*(scalex-1)) );
r3.setSize(r3.size()+TQSize(2,2));
//+ r3.moveBy(-1,-1);
p.setRasterOp(TQt::CopyROP);
p.setPen(TQPen(TQColor("lightgreen"),1));
p.setBrush(TQColor("lightgreen"));
p.drawPie(r3,0,5760);
p.setPen(TQPen(TQColor("black"),1));
r3.setSize(r3.size()+TQSize(2,2));
r3.moveBy(-1,-1);
p.drawEllipse(r3);
*/
i++;
}
p.setWorldMatrix(oldMatrix);
}
if (showAlt)
{
drawAlt(p);
}
p.setRasterOp(TQt::XorROP);
}
TQRect* Area::onSelectionPoint(const TQPoint & p, double zoom) const
{
for (TQRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next())
{
TQRect r2(r->topLeft(),r->bottomRight());
r2.moveCenter(r2.center()*zoom);
if (r2.contains(p))
{
return r;
}
}
return 0L;
}
/**
* returns only the part of the image which is
* covered by the area
*/
TQPixmap Area::cutOut(const TQImage & image)
{
if ( 0>=rect().width() ||
0>=rect().height() ||
!rect().intersects(image.rect()) )
{
TQPixmap dummyPix(10,10);
dummyPix.fill();
delete _highlightedPixmap;
_highlightedPixmap = 0L;
return dummyPix;
}
// Get the mask from the subclasses
TQBitmap mask=getMask();
// The rectangle which is part of the image
TQRect partOfImage=rect();
TQRect partOfMask(0,0,mask.width(),mask.height());
// If the area is outside of the image make the
// preview smaller
if ( (rect().x()+rect().width()) > image.width() ) {
partOfImage.setWidth( image.width()-rect().x() );
partOfMask.setWidth( image.width()-rect().x() );
}
if ( (rect().x() < 0) ) {
partOfImage.setX(0);
partOfMask.setX(myabs(rect().x()));
}
if ( (rect().y()+rect().height()) > image.height() ) {
partOfImage.setHeight( image.height()-rect().y() );
partOfMask.setHeight ( image.height()-rect().y() );
}
if ( (rect().y() < 0) ) {
partOfImage.setY(0);
partOfMask.setY(myabs(rect().y()));
}
TQImage tempImage=mask.convertToImage().copy(partOfMask);
mask.convertFromImage(tempImage);
// partOfImage = partOfImage.normalize();
TQImage cut=image.copy(partOfImage);
TQPixmap pix;
// partOfMask = partOfMask.normalize();
if (!partOfMask.isValid())
kdDebug() << "PartofMask not valid : " << partOfMask.x() << "," << partOfMask.y() << ","
<< partOfMask.width() << "," << partOfMask.height() << "," << endl;
/*
TQBitmap mask2(partOfMask.width(), partOfMask.height());
TQPainter p4(&mask2);
p4.drawPixmap( TQPoint(0,0) ,mask,partOfMask);
p4.flush();
p4.end();
*/
pix.convertFromImage(cut);
setHighlightedPixmap(cut, mask);
TQPixmap retPix(pix.width(),pix.height());
TQPainter p3(&retPix);
// if transparent image fill the background
// with gimp-like rectangles
if (pix.mask()) {
TQPixmap backPix(32,32);
// Gimp like transparent rectangle
TQPainter p2(&backPix);
p2.fillRect(0,0,32,32,TQColor(156,149,156));
p2.fillRect(0,16,16,16,TQColor(98,105,98));
p2.fillRect(16,0,16,16,TQColor(98,105,98));
p2.flush();
p3.setPen(TQPen());
p3.fillRect(0,0,pix.width(),pix.height(),TQBrush(TQColor("black"),backPix));
}
p3.drawPixmap(TQPoint(0,0),pix);
p3.flush();
p3.end();
retPix.setMask(mask);
return retPix;
}
TQBitmap Area::getMask() const
{
TQBitmap b;
return b;
}
void Area::setHighlightedPixmap( TQImage & im, TQBitmap & mask )
{
if (!Area::highlightArea)
return;
delete _highlightedPixmap;
TQImage image = im.convertDepth( 32 );
TQSize size = image.size();
TQColor pixel;
double r,g,b;
// highlight every pixel
for (int y=0; y < size.height(); y++)
{
for (int x=0; x < size.width(); x++)
{
r = tqRed(image.pixel(x,y));
g = tqGreen(image.pixel(x,y));
b = tqBlue(image.pixel(x,y));
r = (r *123 / 255)+132;
g = (g *123 / 255)+132;
b = (b *123 / 255)+132;
pixel.setRgb( (int) r, (int) g, (int) b);
image.setPixel(x,y, pixel.rgb());
}
}
_highlightedPixmap = new TQPixmap();
_highlightedPixmap->convertFromImage( image );
_highlightedPixmap->setMask( mask );
if (_highlightedPixmap->isNull())
kdDebug() << "HighlightedPixmap is null" << endl;
}
/********************************************************************
* RECTANGLE
*******************************************************************/
RectArea::RectArea()
: Area()
{
TQRect *p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
_type=Area::Rectangle;
}
RectArea::~RectArea() {
}
Area* RectArea::clone() const
{
Area* areaClone = new RectArea();
areaClone->setArea( *this );
return areaClone;
}
void RectArea::draw(TQPainter & p)
{
drawHighlighting(p);
// p.setRasterOp(TQt::CopyROP);
// p.setRasterOp(TQt:: OrROP);
// TQBrush b(TQBrush::SolidPattern);
// TQBrush b(TQBrush::Dense4Pattern);
// TQBrush b(TQBrush::BDiagPattern);
// b.setColor(TQColor(32,32,32));
// p.fillRect(rect(), b);
p.setRasterOp(TQt::XorROP);
p.setPen(TQPen(TQColor("white"),1));
TQRect r(rect());
r.setWidth(r.width()+1);
r.setHeight(r.height()+1);
p.drawRect(r);
Area::draw(p);
}
TQBitmap RectArea::getMask() const
{
TQBitmap mask(rect().width(),rect().height());
mask.fill(TQt::color0);
TQPainter p(&mask);
p.setBackgroundColor(TQt::color0);
p.setPen(TQt::color1);
p.setBrush(TQt::color1);
mask.fill(TQt::color1);
p.end();
return mask;
}
TQString RectArea::coordsToString() const
{
TQString retStr=TQString("%1,%2,%3,%4")
.arg(rect().left())
.arg(rect().top())
.arg(rect().right())
.arg(rect().bottom());
return retStr;
}
bool RectArea::contains(const TQPoint & p) const{
return rect().contains(p);
}
void RectArea::moveSelectionPoint(TQRect* selectionPoint, const TQPoint & p)
{
selectionPoint->moveCenter(p);
int i=0;
for (TQRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
if (r==selectionPoint)
break;
i++;
}
TQRect r2(_rect);
switch (i) {
case 0 : _rect.setLeft(p.x());
_rect.setTop(p.y());
break;
case 1 : _rect.setRight(p.x());
_rect.setTop(p.y());
break;
case 2 : _rect.setLeft(p.x());
_rect.setBottom(p.y());
break;
case 3 : _rect.setRight(p.x());
_rect.setBottom(p.y());
break;
}
if ( ! _rect.isValid())
_rect=r2;
updateSelectionPoints();
}
void RectArea::updateSelectionPoints()
{
_selectionPoints->first()->moveCenter(_rect.topLeft());
_selectionPoints->next()->moveCenter(_rect.topRight()+TQPoint(1,0));
_selectionPoints->next()->moveCenter(_rect.bottomLeft()+TQPoint(0,1));
_selectionPoints->next()->moveCenter(_rect.bottomRight()+TQPoint(1,1));
}
bool RectArea::setCoords(const TQString & s)
{
_finished=true;
TQStringList list=TQStringList::split(",",s);
TQRect r;
bool ok=true;
TQStringList::Iterator it = list.begin();
r.setLeft((*it).toInt(&ok,10));it++;
r.setTop((*it).toInt(&ok,10));it++;
r.setRight((*it).toInt(&ok,10));it++;
r.setBottom((*it).toInt(&ok,10));
if (ok) {
setRect(r);
return true;
} else
return false;
}
TQString RectArea::getHTMLCode() const {
TQString retStr;
retStr+="<area ";
retStr+="shape=\"rect\" ";
retStr+=getHTMLAttributes();
retStr+="coords=\""+coordsToString()+"\" ";
retStr+="/>";
return retStr;
}
/********************************************************************
* CIRCLE
*******************************************************************/
CircleArea::CircleArea()
: Area()
{
_type=Area::Circle;
TQRect *p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
p = new TQRect(0,0,SELSIZE,SELSIZE);
_selectionPoints->append(p);
}
CircleArea::~CircleArea() {
}
Area* CircleArea::clone() const
{
Area* areaClone = new CircleArea();
areaClone->setArea( *this );
return areaClone;
}
void CircleArea::draw(TQPainter & p)
{
drawHighlighting(p);
/*
p.setRasterOp(TQt::CopyROP);
TQBrush bold = p.brush();
TQBrush b(TQBrush::Dense5Pattern);
b.setColor(TQColor("green"));
p.setBrush(b);
TQRect r = _rect;
r.moveBy(1,1);
r.setSize( r.size()-TQSize(2,2) );
p.drawChord(r,0,5760);
p.setBrush(bold);
*/
p.setRasterOp(TQt::XorROP);
p.setPen(TQPen(TQColor("white"),1));
TQRect r(_rect);
r.setWidth(r.width()+1);
r.setHeight(r.height()+1);
p.drawEllipse(r);
Area::draw(p);
}
TQBitmap CircleArea::getMask() const
{
TQBitmap mask(_rect.width(),_rect.height());
mask.fill(TQt::color0);
TQPainter p(&mask);
p.setBackgroundColor(TQt::color0);
p.setPen(TQt::color1);
p.setBrush(TQt::color1);
p.drawPie(TQRect(0,0,_rect.width(),_rect.height()),0,5760);
p.flush();
p.end();
return mask;
}
TQString CircleArea::coordsToString() const
{
TQString retStr=TQString("%1,%2,%3")
.arg(_rect.center().x())
.arg(_rect.center().y())
.arg(_rect.width()/2);
return retStr;
}
bool CircleArea::contains(const TQPoint & p) const
{
TQRegion r(_rect,TQRegion::Ellipse);
return r.contains(p);
}
void CircleArea::moveSelectionPoint(TQRect* selectionPoint, const TQPoint & p)
{
selectionPoint->moveCenter(p);
int i=0;
for (TQRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
if (r==selectionPoint)
break;
i++;
}
// The code below really sucks, but I have no better idea.
// it only makes sure that the circle is perfektly round
TQPoint newPoint;
int diff=myabs(p.x()-_rect.center().x());
if (myabs(p.y()-_rect.center().y())>diff)
diff=myabs(p.y()-_rect.center().y());
newPoint.setX( p.x()-_rect.center().x()<0
? _rect.center().x()-diff
: _rect.center().x()+diff);
newPoint.setY( p.y()-_rect.center().y()<0
? _rect.center().y()-diff
: _rect.center().y()+diff);
switch (i) {
case 0 : if (newPoint.x() < _rect.center().x() &&
newPoint.y() < _rect.center().y())
{
_rect.setLeft(newPoint.x());
_rect.setTop(newPoint.y());
}
break;
case 1 : if (newPoint.x() > _rect.center().x() &&
newPoint.y() < _rect.center().y())
{
_rect.setRight(newPoint.x());
_rect.setTop(newPoint.y());
}
break;
case 2 : if (newPoint.x() < _rect.center().x() &&
newPoint.y() > _rect.center().y())
{
_rect.setLeft(newPoint.x());
_rect.setBottom(newPoint.y());
}
break;
case 3 : if (newPoint.x() > _rect.center().x() &&
newPoint.y() > _rect.center().y())
{
_rect.setRight(newPoint.x());
_rect.setBottom(newPoint.y());
}
break;
}
updateSelectionPoints();
}
void CircleArea::setRect(const TQRect & r)
{
TQRect r2 = r;
if ( r2.height() != r2.width() )
r2.setHeight( r2.width() );
Area::setRect(r2);
}
void CircleArea::updateSelectionPoints()
{
_selectionPoints->first()->moveCenter(_rect.topLeft());
_selectionPoints->next()->moveCenter(_rect.topRight());
_selectionPoints->next()->moveCenter(_rect.bottomLeft());
_selectionPoints->next()->moveCenter(_rect.bottomRight());
}
bool CircleArea::setCoords(const TQString & s)
{
_finished=true;
TQStringList list=TQStringList::split(",",s);
bool ok=true;
TQStringList::Iterator it = list.begin();
int x=(*it).toInt(&ok,10);it++;
int y=(*it).toInt(&ok,10);it++;
int rad=(*it).toInt(&ok,10);
if (!ok) return false;
TQRect r;
r.setWidth(rad*2);
r.setHeight(rad*2);
r.moveCenter(TQPoint(x,y));
setRect(r);
return true;
}
TQString CircleArea::getHTMLCode() const {
TQString retStr;
retStr+="<area ";
retStr+="shape=\"circle\" ";
retStr+=getHTMLAttributes();
retStr+="coords=\""+coordsToString()+"\" ";
retStr+="/>";
return retStr;
}
/********************************************************************
* POLYGON
*******************************************************************/
PolyArea::PolyArea()
: Area()
{
_type=Area::Polygon;
}
PolyArea::~PolyArea() {
}
Area* PolyArea::clone() const
{
Area* areaClone = new PolyArea();
areaClone->setArea( *this );
return areaClone;
}
void PolyArea::draw(TQPainter & p)
{
drawHighlighting(p);
p.setRasterOp(TQt::XorROP);
p.setPen(TQPen(TQColor("white"),1));
if (_coords->count()==0) return;
if (_finished)
p.drawPolygon ( *_coords,false,0,_coords->count());
else
p.drawPolyline ( *_coords,0,_coords->count());
/*
p.moveTo(_coords->point(0));
for (int i=1;i<_coords->count();i++)
p.lineTo(_coords->point(i));
if (_finished)
p.lineTo(_coords->point(0));
*/
Area::draw(p);
}
TQBitmap PolyArea::getMask() const
{
TQBitmap mask(_rect.width(),_rect.height());
mask.fill(TQt::color0);
TQPainter p(&mask);
p.setBackgroundColor(TQt::color0);
p.setPen(TQt::color1);
p.setBrush(TQt::color1);
p.setClipping(true);
TQRegion r(*_coords);
r.translate(-_rect.left(),-_rect.top());
p.setClipRegion(r);
p.fillRect(TQRect(0,0,_rect.width(),_rect.height()),TQt::color1);
p.flush();
p.end();
return mask;
}
TQString PolyArea::coordsToString() const
{
TQString retStr;
for (uint i=0;i<_coords->count();i++) {
retStr.append(TQString("%1,%2,")
.arg(_coords->point(i).x())
.arg(_coords->point(i).y()));
}
retStr.remove(retStr.length()-1,1);
return retStr;
}
int PolyArea::distance(const TQPoint &p1, const TQPoint &p2)
{
TQPoint temp = p1-p2;
return temp.manhattanLength();
}
bool PolyArea::isBetween(const TQPoint &p, const TQPoint &p1, const TQPoint &p2)
{
int dist = distance(p,p1)+distance(p,p2)-distance(p1,p2);
if (myabs(dist)<1)
return true;
else
return false;
}
void PolyArea::simplifyCoords()
{
if (_coords->size()<4)
return;
TQPoint p = _coords->point(0) - _coords->point(1);
uint i = 1;
while( (i<_coords->size()) && (_coords->size() > 3) )
{
p = _coords->point(i-1) - _coords->point(i);
if (p.manhattanLength() < 3)
removeCoord(i);
else
i++;
}
p = _coords->point(0) - _coords->point(1);
double angle2;
double angle1;
if (p.y()==0)
angle1 = 1000000000;
else
angle1 = (double) p.x() / (double) p.y();
i=2;
while( (i<_coords->size()) && (_coords->size() > 3) )
{
p = _coords->point(i-1) - _coords->point(i);
if (p.y()==0)
angle2 = 1000000000;
else
angle2 = (double) p.x() / (double) p.y();
if ( angle2==angle1 )
{
kdDebug() << "removing " << i-1 << endl;
removeCoord(i-1);
}
else
{
i++;
kdDebug() << "skipping " << i-1 << " cause " << angle1 << "!= " << angle2 << endl;
angle1 = angle2;
}
}
}
int PolyArea::addCoord(const TQPoint & p)
{
if (_coords->size()<3)
{
return Area::addCoord(p);
}
if (_coords->point(_coords->size()-1) == p)
{
kdDebug() << "equal Point added" << endl;
return -1;
}
int n=_coords->size();
// TQPoint temp = p-_coords->point(0);
int nearest = 0;
int olddist = distance(p,_coords->point(0));
int mindiff = 999999999;
// find the two points, which are the nearest one to the new point
for (int i=1; i <= n; i++)
{
int dist = distance(p,_coords->point(i%n));
int dist2 = distance(_coords->point(i-1),_coords->point(i%n));
int diff = myabs(dist+olddist-dist2);
if ( diff<mindiff )
{
mindiff = diff;
nearest = i%n;
}
olddist=dist;
}
insertCoord(nearest, p);
return nearest;
}
bool PolyArea::contains(const TQPoint & p) const
{
// A line can't contain a point
if (_coords->count() >2 ) {
TQRegion r(*_coords);
return r.contains(p);
}
else
return false;
}
void PolyArea::moveSelectionPoint(TQRect* selectionPoint, const TQPoint & p)
{
selectionPoint->moveCenter(p);
int i=0;
for (TQRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) {
if (r==selectionPoint)
break;
i++;
}
_coords->setPoint(i,p);
_rect=_coords->boundingRect();
}
void PolyArea::updateSelectionPoints()
{
TQRect *r;
r=_selectionPoints->first();
for (uint i=0;i<_coords->size();i++)
{
r->moveCenter(_coords->point(i));
r=_selectionPoints->next();
}
}
bool PolyArea::setCoords(const TQString & s)
{
_finished=true;
TQStringList list=TQStringList::split(",",s);
_coords=new TQPointArray();
_selectionPoints= new SelectionPointList();
for (TQStringList::Iterator it = list.begin(); it !=list.end(); ++it)
{
bool ok=true;
int newXCoord=(*it).toInt(&ok,10);
if (!ok) return false;
it++;
if (it==list.end()) break;
int newYCoord=(*it).toInt(&ok,10);
if (!ok) return false;
insertCoord(_coords->size(), TQPoint(newXCoord,newYCoord));
}
return true;
}
TQString PolyArea::getHTMLCode() const {
TQString retStr;
retStr+="<area ";
retStr+="shape=\"poly\" ";
retStr+=getHTMLAttributes();
retStr+="coords=\""+coordsToString()+"\" ";
retStr+="/>";
return retStr;
}
void PolyArea::setFinished(bool b)
{
// The last Point is the same as the first
// so delete it
_coords->resize(_coords->size()-1);
_selectionPoints->removeLast();
_finished=b;
}
TQRect PolyArea::selectionRect() const
{
TQRect r = _rect;
r.moveBy(-10,-10);
r.setSize(r.size()+TQSize(21,21));
return r;
}
/********************************************************************
* DEFAULT
*******************************************************************/
DefaultArea::DefaultArea()
: Area()
{
_type=Area::Default;
}
DefaultArea::~DefaultArea() {
}
Area* DefaultArea::clone() const
{
Area* areaClone = new DefaultArea();
areaClone->setArea( *this );
return areaClone;
}
void DefaultArea::draw(TQPainter &)
{}
TQString DefaultArea::getHTMLCode() const {
TQString retStr;
retStr+="<area ";
retStr+="shape=\"default\" ";
retStr+=getHTMLAttributes();
retStr+="/>";
return retStr;
}
/********************************************************************
* AreaSelection
*******************************************************************/
AreaSelection::AreaSelection()
: Area()
{
_areas = new AreaList();
_name = "Selection";
invalidate();
}
AreaSelection::~AreaSelection() {
delete _areas;
}
Area* AreaSelection::clone() const
{
AreaSelection* areaClone = new AreaSelection();
// we want a deep copy of the Areas
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
{
areaClone->add( it.current()->clone() );
}
// areaClone->setArea( *this );
return areaClone;
}
void AreaSelection::add(Area *a)
{
// if a selection of areas was added get the areas of it
AreaSelection *selection=0L;
if ( (selection = dynamic_cast <AreaSelection*> ( a ) ) )
{
AreaList list = selection->getAreaList();
for (Area* area = list.first(); area != 0L; area = list.next() )
{
if ( _areas->find( area ) == -1 ) {
_areas->append( area ); // Must come before area->setSelected
area->setSelected( true );
}
}
}
else
{
if ( _areas->find( a ) == -1 ) {
_areas->append( a ); // Must come before a->setSelected
a->setSelected( true );
}
}
invalidate();
}
void AreaSelection::remove(Area *a)
{
if (_areas->find(a) == -1)
return;
a->setSelected( false );
_areas->remove( a );
invalidate();
}
void AreaSelection::reset()
{
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
{
it.current()->setSelected( false );
}
_areas->clear();
invalidate();
}
bool AreaSelection::contains(const TQPoint & p) const
{
bool b=false;
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
{
if ( it.current()->contains( p ) )
{
b=true;
break;
}
}
return b;
}
TQRect* AreaSelection::onSelectionPoint(const TQPoint & p, double zoom) const
{
AreaListIterator it=getAreaListIterator();
if (it.count() != 1)
return 0L;
TQRect* retRect=0L;
for ( ; it.current() != 0L; ++it )
{
if ( (retRect = it.current()->onSelectionPoint( p , zoom) ) )
{
break;
}
}
return retRect;
}
void AreaSelection::moveSelectionPoint(TQRect* selectionPoint, const TQPoint & p)
{
// It's only possible to move a SelectionPoint if only one Area is selected
if (_areas->count() != 1)
return;
_areas->getFirst()->moveSelectionPoint(selectionPoint,p);
invalidate();
}
void AreaSelection::moveBy(int dx, int dy)
{
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
it.current()->moveBy(dx,dy);
Area::moveBy( dx, dy );
invalidate();
}
TQString AreaSelection::typeString() const
{
// if there is only one Area selected
// show the name of that Area
if ( _areas->count()==0 )
return "";
else if ( _areas->count()==1 )
return _areas->getFirst()->typeString();
else
return i18n("Number of Areas");
}
Area::ShapeType AreaSelection::type() const
{
// if there is only one Area selected
// take the type of that Area
if ( _areas->count()==0 )
return Area::None;
else if ( _areas->count()==1 )
return _areas->getFirst()->type();
else
return Area::Selection;
}
void AreaSelection::updateSelectionPoints()
{
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
{
it.current()->updateSelectionPoints();
}
invalidate();
}
TQRect AreaSelection::selectionRect() const
{
if (!_selectionCacheValid)
{
_selectionCacheValid=true;
TQRect r;
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
r = r | it.current()->selectionRect();
_cachedSelectionRect=r;
}
return _cachedSelectionRect;
}
uint AreaSelection::count() const {
return _areas->count();
}
bool AreaSelection::isEmpty() const
{
return _areas->isEmpty();
}
AreaList AreaSelection::getAreaList() const {
AreaList list(*_areas);
return list;
}
AreaListIterator AreaSelection::getAreaListIterator() const {
AreaListIterator it(*_areas);
return it;
}
void AreaSelection::setArea(const Area & copy)
{
Area *area = copy.clone();
AreaSelection *selection = dynamic_cast<AreaSelection*>(area);
if (selection)
setAreaSelection(*selection);
else {
Area::setArea(copy);
invalidate();
}
}
void AreaSelection::setAreaSelection(const AreaSelection & copy)
{
AreaListIterator it=getAreaListIterator();
AreaListIterator it2=copy.getAreaListIterator();
if (it.count() != it2.count())
return;
for ( ; it.current() != 0L; ++it, ++it2 )
it.current()->setArea(*it2.current());
Area::setArea(copy);
invalidate();
}
void AreaSelection::setAreaList( const AreaList & areas )
{
delete _areas;
_areas = new AreaList(areas);
invalidate();
}
void AreaSelection::setRect(const TQRect & r)
{
if ( _areas->count()==1 )
{
_areas->getFirst()->setRect(r);
}
invalidate();
_rect=rect();
updateSelectionPoints();
}
TQRect AreaSelection::rect() const
{
if (!_rectCacheValid)
{
_rectCacheValid=true;
TQRect r;
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
r = r | it.current()->rect();
_cachedRect=r;
}
return _cachedRect;
}
int AreaSelection::addCoord(const TQPoint & p)
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->addCoord(p);
invalidate();
}
return 0;
}
void AreaSelection::insertCoord(int pos, const TQPoint & p)
{
if ( _areas->count()==1 )
{
_areas->getFirst()->insertCoord(pos, p);
invalidate();
}
}
void AreaSelection::removeCoord(int pos)
{
if ( _areas->count()==1 )
{
_areas->getFirst()->removeCoord(pos);
invalidate();
}
}
bool AreaSelection::removeSelectionPoint(TQRect * r)
{
bool result=false;
if ( _areas->count()==1 )
{
result = _areas->getFirst()->removeSelectionPoint(r);
invalidate();
}
return result;
}
SelectionPointList* AreaSelection::selectionPoints() const
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->selectionPoints();
}
return _selectionPoints;
}
void AreaSelection::moveCoord(int pos,const TQPoint & p)
{
if ( _areas->count()==1 )
{
_areas->getFirst()->moveCoord(pos,p);
invalidate();
}
}
void AreaSelection::highlightSelectionPoint(int i)
{
if ( _areas->count()==1 )
{
_areas->getFirst()->highlightSelectionPoint(i);
invalidate();
}
}
TQPointArray* AreaSelection::coords() const
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->coords();
}
return Area::coords();
}
TQString AreaSelection::attribute(const TQString & name) const
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->attribute(name);
}
return Area::attribute(name);
}
void AreaSelection::setAttribute(const TQString & name, const TQString & value)
{
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
it.current()->setAttribute(name,value);
Area::setAttribute(name,value);
}
AttributeIterator AreaSelection::firstAttribute() const
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->firstAttribute();
}
return _attributes.begin();
}
AttributeIterator AreaSelection::lastAttribute() const
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->lastAttribute();
}
return _attributes.end();
}
void AreaSelection::setMoving(bool b)
{
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
it.current()->setMoving(b);
Area::setMoving(b);
}
bool AreaSelection::isMoving() const
{
if ( _areas->count()==1 )
{
return _areas->getFirst()->isMoving();
}
return Area::isMoving();
}
/**
* Checks if an area is outside the rectangle parameter
* returns false if an area has no pixel in common with the rectangle parameter
**/
bool AreaSelection::allAreasWithin(const TQRect & r) const
{
if ( ! r.contains(rect()) )
{
AreaListIterator it=getAreaListIterator();
for ( ; it.current() != 0L; ++it )
if (!it.current()->rect().intersects(r))
return false;
}
return true;
}
void AreaSelection::draw(TQPainter &)
{}