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/imagemap.cpp

396 lines
12 KiB

/***************************************************************************
imagemap.cpp - description
-------------------
begin : Wed Apr 4 2001
copyright : (C) 2001 by Jan Schäfer
email : j_schaef@informatik.uni-kl.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. *
* *
***************************************************************************/
#include "imagemap.h"
#include "kimagemapeditor.h"
#include "tqpainter.h"
#include "kdebug.h"
#include <tqbitmap.h>
int round(double d) {
if ( (d-((int) d)) < 0.5 )
return (int) d;
else
return ((int) d)+1;
}
ImageMap::ImageMap(TQWidget *parent,KImageMapEditor* _imageMapEditor)
: TQScrollView(parent)
{
imageMapEditor=_imageMapEditor;
// setPicture(TQImage());
currentAction=None;
currentArea=0L;
eraseOldArea=false;
oldArea=0L;
_zoom=1;
viewport()->setMouseTracking(true);
}
ImageMap::~ImageMap(){
}
void ImageMap::setPicture(const TQImage &_image) {
image=_image;
zoomedImage.convertFromImage(image);
setZoom(_zoom);
}
void ImageMap::setZoom(double z) {
_zoom=z;
imageRect.setHeight(image.height()*_zoom);
imageRect.setWidth(image.width()*_zoom);
zoomedImage=TQPixmap(imageRect.width(),imageRect.height());
TQPainter p(&zoomedImage);
p.scale(z,z);
TQPixmap pix;
pix.convertFromImage(image);
// if the picture has transparent areas,
// fill them with Gimp like background
if (pix.mask()) {
TQPixmap backPix(32,32);
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();
p.setPen(TQPen());
p.fillRect(imageRect.left(),imageRect.top(),imageRect.width(),imageRect.height(),TQBrush(TQColor("black"),backPix));
}
p.drawPixmap(imageRect.left(),imageRect.top(),pix);
p.flush();
resizeContents(visibleWidth()>imageRect.width() ? visibleWidth() : imageRect.width(),
visibleHeight()>imageRect.height() ? visibleHeight() : imageRect.height());
repaintContents(0,0,contentsWidth(),contentsHeight(),true);
}
TQPoint ImageMap::translateFromZoom(const TQPoint & p) const {
return TQPoint(p.x()/_zoom,p.y()/_zoom);
}
TQPoint ImageMap::translateToZoom(const TQPoint & p) const {
return TQPoint(round(p.x()*_zoom),round(p.y()*_zoom));
}
TQRect ImageMap::translateToZoom(const TQRect & r) const {
return TQRect(round(r.x()*_zoom),round(r.y()*_zoom),
round(r.width()*_zoom),round(r.height()*_zoom));
}
void ImageMap::contentsMouseDoubleClickEvent(TQMouseEvent* e) {
TQPoint point=e->pos();
point-=imageRect.topLeft();
point=translateFromZoom(point);
if ( currentAction==None &&
(currentArea=imageMapEditor->onArea(point)))
imageMapEditor->showTagEditor(currentArea);
}
void ImageMap::contentsMousePressEvent(TQMouseEvent* e) {
drawStart=e->pos();
// Check if it's on picture if not
// move it to the picture's border
if (!imageRect.contains(drawStart)) {
if (drawStart.x()>imageRect.right())
drawStart.setX(imageRect.right());
if (drawStart.x()<imageRect.left())
drawStart.setX(imageRect.left());
if (drawStart.y()>imageRect.bottom())
drawStart.setY(imageRect.bottom());
if (drawStart.y()<imageRect.top())
drawStart.setY(imageRect.top());
}
// Translate it to picture coordinates
drawStart-=imageRect.topLeft();
drawStart=translateFromZoom(drawStart);
if (currentArea)
oldArea=new Area(*currentArea);
if ( currentAction==None ) {
if (e->button()==RightButton) {
currentArea=imageMapEditor->onArea(drawStart);
imageMapEditor->select(currentArea);
imageMapEditor->slotShowPopupMenu(e->globalPos());
} else
if ((currentArea=imageMapEditor->selected()) &&
(currentSelectionPoint=currentArea->onSelectionPoint(drawStart)))
{
currentAction=MoveSelectionPoint;
} else
if ((currentArea=imageMapEditor->onArea(drawStart))) {
currentAction=MoveArea;
imageMapEditor->select(currentArea);
} else
if (imageMapEditor->currentShapeType()!=Area::None) {
currentArea=new Area(imageMapEditor->currentShapeType());
currentArea->setRect(TQRect(drawStart,drawStart));
currentArea->setSelected(false);
if (imageMapEditor->selected())
imageMapEditor->selected()->setSelected(false);
switch (currentArea->type()) {
case Area::Rectangle : currentAction=DrawRectangle; break;
case Area::Circle : currentAction=DrawCircle; break;
case Area::Polygon :
currentAction=DrawPolygon;
currentArea->addCoord(drawStart);
currentSelectionPoint=currentArea->selectionPoints()->last();
break;
default: break;
}
}
// Clicked with the arrow at an areafree position
else {
currentArea=0L;
imageMapEditor->deselectAll();
}
} else
if ( currentAction==DrawPolygon) {
}
TQRect r;
if (oldArea)
r=oldArea->selectionRect();
if (currentArea) {
r= r | currentArea->selectionRect();
repaintContents(translateToZoom(r),false);
}
}
void ImageMap::contentsMouseReleaseEvent(TQMouseEvent *e) {
drawEnd=e->pos();
// Check if it's on picture if not
// move it to the picture's border
if (!imageRect.contains(drawEnd)) {
if (drawEnd.x()>imageRect.right())
drawEnd.setX(imageRect.right());
if (drawEnd.x()<imageRect.left())
drawEnd.setX(imageRect.left());
if (drawEnd.y()>imageRect.bottom())
drawEnd.setY(imageRect.bottom());
if (drawEnd.y()<imageRect.top())
drawEnd.setY(imageRect.top());
}
// Translate it to picture coordinates
drawEnd-=imageRect.topLeft();
drawEnd=translateFromZoom(drawEnd);
if (currentAction==DrawCircle || currentAction==DrawRectangle) {
imageMapEditor->addArea(currentArea);
imageMapEditor->select(currentArea);
//imageMapEditor->slotAreaChanged(currentArea);
currentAction=None;
} else
if (currentAction==DrawPolygon) {
// If the number of Polygonpoints is more than 2
// and clicked on the first PolygonPoint or
// the right Button was pressed the Polygon is finished
if ((currentArea->selectionPoints()->count()>2)
&& (currentArea->selectionPoints()->first()->contains(drawEnd)
|| (e->button()==RightButton)))
{
currentArea->setFinished(true);
imageMapEditor->addArea(currentArea);
currentAction=None;
} else
{
currentArea->addCoord(drawEnd);
currentSelectionPoint=currentArea->selectionPoints()->last();
}
// currentArea->addCoord(drawEnd);
// currentSelectionPoint=currentArea->selectionPoints()->last();
} else
if (currentAction==MoveArea || currentAction==MoveSelectionPoint) {
imageMapEditor->slotAreaChanged(currentArea);
currentAction=None;
}
else {
currentAction=None;
}
imageMapEditor->slotChangeStatusCoords(drawEnd.x(),drawEnd.y());
imageMapEditor->slotUpdateSelectionCoords();
if (currentArea)
repaintArea(*currentArea);
// repaintContents(0,0,contentsWidth(),contentsHeight(),false);
}
void ImageMap::contentsMouseMoveEvent(TQMouseEvent *e) {
drawCurrent=e->pos();
// If outside the image
// set it to the border
if (!imageRect.contains(drawCurrent)) {
if (drawCurrent.x()>imageRect.right())
drawCurrent.setX(imageRect.right());
if (drawCurrent.x()<imageRect.left())
drawCurrent.setX(imageRect.left());
if (drawCurrent.y()>imageRect.bottom())
drawCurrent.setY(imageRect.bottom());
if (drawCurrent.y()<imageRect.top())
drawCurrent.setY(imageRect.top());
}
// Translate to image coordinates
drawCurrent-=imageRect.topLeft();
drawCurrent=translateFromZoom(drawCurrent);
if (currentAction==DrawRectangle) {
// To avoid flicker, only repaint the minimum rect
TQRect oldRect=translateToZoom(currentArea->rect());
currentArea->setRect(TQRect(drawStart,drawCurrent).normalize());
TQRect newRect=translateToZoom(currentArea->rect());
TQRect r=oldRect | newRect;
repaintContents(r,false);
imageMapEditor->slotUpdateSelectionCoords(currentArea->rect());
} else
if (currentAction==DrawCircle) {
TQRect oldRect=translateToZoom(currentArea->rect());
currentArea->setRect(TQRect(drawStart,drawCurrent).normalize());
TQRect newRect=translateToZoom(currentArea->rect());
TQRect r=oldRect | newRect;
repaintContents(r,false);
imageMapEditor->slotUpdateSelectionCoords(currentArea->rect());
} else
if ( currentAction==DrawPolygon ) {
TQRect oldRect=translateToZoom(currentArea->rect());
currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent);
TQRect newRect=translateToZoom(currentArea->rect());
TQRect r=oldRect | newRect;
repaintContents(r,false);
imageMapEditor->slotUpdateSelectionCoords(currentArea->rect());
} else
if ( currentAction==MoveArea ) {
TQRect oldRect=translateToZoom(currentArea->selectionRect());
currentArea->moveBy((drawCurrent-drawStart).x(),(drawCurrent-drawStart).y());
TQRect newRect=translateToZoom(currentArea->selectionRect());
TQRect r=oldRect | newRect;
repaintContents(r,false);
drawStart=drawCurrent;
imageMapEditor->slotUpdateSelectionCoords();
} else
if ( currentAction==MoveSelectionPoint ) {
TQRect oldRect=translateToZoom(currentArea->selectionRect());
currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent);
TQRect newRect=translateToZoom(currentArea->selectionRect());
TQRect r=oldRect | newRect;
repaintContents(r,false);
imageMapEditor->slotUpdateSelectionCoords();
}
imageMapEditor->slotChangeStatusCoords(drawCurrent.x(),drawCurrent.y());
}
void ImageMap::resizeEvent(TQResizeEvent* e) {
TQScrollView::resizeEvent(e);
int width=(int) (image.width()*_zoom);
int height=(int) (image.height()*_zoom);
if (visibleWidth()>width)
width=visibleWidth();
if (visibleHeight()>height)
height=visibleHeight();
resizeContents(width,height);
imageRect.setLeft(0);
imageRect.setTop(0);
imageRect.setHeight(image.height()*_zoom);
imageRect.setWidth(image.width()*_zoom);
}
void ImageMap::repaintArea(const Area & a) {
repaintContents(translateToZoom(a.selectionRect()),false);
}
void ImageMap::drawContents(TQPainter* p,int clipx,int clipy,int clipw,int cliph) {
// kdDebug() << "drawing\n" << endl;
// p.scale(rect.width()*2,rect.height()*2);
// if (e->rect()!=rect()) {
// p.setClipping(true);
// p.setClipRect(e->rect());
// } else
/* if (currentAction==DrawRectangle) {
p->setClipping(true);
TQRect r(currentArea->rect());
r.moveBy(imageRect.left()-5,imageRect.top()-5);
r.setSize(r.size()+TQSize(10,10));
p->setClipRegion(r);
}
*/
TQRect updateRect(clipx,clipy,clipw,cliph);
TQPixmap doubleBuffer(updateRect.size()); // Pixmap for double-buffering
TQPainter p2(&doubleBuffer);
p2.drawPixmap(0,0,zoomedImage,clipx,clipy,clipw,cliph);
p2.translate(-updateRect.x(), -updateRect.y());
p2.scale(_zoom,_zoom);
AreaList *list=imageMapEditor->areaList();
for (Area* s=list->first();s != 0L; s=list->next())
s->draw(p2);
// Draw the current drawing Area
if (currentAction != MoveArea &&
currentAction != MoveSelectionPoint &&
currentAction != None)
{
currentArea->draw(p2);
}
p2.end();
// Copy the double buffer into the widget
p->drawPixmap(clipx,clipy,doubleBuffer);
// Erase background without flicker
TQRegion region(contentsX(),contentsY(),visibleWidth(),visibleHeight());
region=region.subtract(TQRegion(imageRect));
for (int i=0;i<region.rects().count();i++) {
p->eraseRect(region.rects()[i]);
}
// Draw our picture
// p->drawPixmap(imageRect.left(),imageRect.top(),zoomedImage);
//
//
// p->scale(_zoom,_zoom);
// p->translate(imageRect.left(),imageRect.top());
//
// AreaList *list=imageMapEditor->areaList();
// for (Area* s=list->first();s != 0L; s=list->next())
// s->draw(*p);
//
// // Draw the current drawing Area
// if (currentAction != MoveArea &&
// currentAction != MoveSelectionPoint &&
// currentAction != None)
// {
// currentArea->draw(*p);
// }
}