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.
396 lines
12 KiB
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);
|
|
// }
|
|
|
|
|
|
}
|