diff options
Diffstat (limited to 'kimagemapeditor/imagemap.cpp')
-rw-r--r-- | kimagemapeditor/imagemap.cpp | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/kimagemapeditor/imagemap.cpp b/kimagemapeditor/imagemap.cpp new file mode 100644 index 00000000..665ef000 --- /dev/null +++ b/kimagemapeditor/imagemap.cpp @@ -0,0 +1,395 @@ +/*************************************************************************** + imagemap.cpp - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Sch�fer + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qpainter.h" +#include "kdebug.h" +#include <qbitmap.h> + +int round(double d) { + if ( (d-((int) d)) < 0.5 ) + return (int) d; + else + return ((int) d)+1; +} + +ImageMap::ImageMap(QWidget *parent,KImageMapEditor* _imageMapEditor) + : QScrollView(parent) +{ + imageMapEditor=_imageMapEditor; +// setPicture(QImage()); + currentAction=None; + currentArea=0L; + eraseOldArea=false; + oldArea=0L; + _zoom=1; + viewport()->setMouseTracking(true); + + +} + +ImageMap::~ImageMap(){ +} + +void ImageMap::setPicture(const QImage &_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=QPixmap(imageRect.width(),imageRect.height()); + QPainter p(&zoomedImage); + p.scale(z,z); + QPixmap pix; + pix.convertFromImage(image); + // if the picture has transparent areas, + // fill them with Gimp like background + if (pix.mask()) { + QPixmap backPix(32,32); + QPainter p2(&backPix); + p2.fillRect(0,0,32,32,QColor(156,149,156)); + p2.fillRect(0,16,16,16,QColor(98,105,98)); + p2.fillRect(16,0,16,16,QColor(98,105,98)); + p2.flush(); + p.setPen(QPen()); + p.fillRect(imageRect.left(),imageRect.top(),imageRect.width(),imageRect.height(),QBrush(QColor("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); +} + +QPoint ImageMap::translateFromZoom(const QPoint & p) const { + return QPoint(p.x()/_zoom,p.y()/_zoom); +} + +QPoint ImageMap::translateToZoom(const QPoint & p) const { + return QPoint(round(p.x()*_zoom),round(p.y()*_zoom)); +} + +QRect ImageMap::translateToZoom(const QRect & r) const { + return QRect(round(r.x()*_zoom),round(r.y()*_zoom), + round(r.width()*_zoom),round(r.height()*_zoom)); +} + +void ImageMap::contentsMouseDoubleClickEvent(QMouseEvent* e) { + QPoint point=e->pos(); + point-=imageRect.topLeft(); + point=translateFromZoom(point); + if ( currentAction==None && + (currentArea=imageMapEditor->onArea(point))) + imageMapEditor->showTagEditor(currentArea); + +} + +void ImageMap::contentsMousePressEvent(QMouseEvent* 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(QRect(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) { + + } + + QRect r; + if (oldArea) + r=oldArea->selectionRect(); + if (currentArea) { + r= r | currentArea->selectionRect(); + repaintContents(translateToZoom(r),false); + } + +} + +void ImageMap::contentsMouseReleaseEvent(QMouseEvent *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(QMouseEvent *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 + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->setRect(QRect(drawStart,drawCurrent).normalize()); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(currentArea->rect()); + } else + if (currentAction==DrawCircle) { + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->setRect(QRect(drawStart,drawCurrent).normalize()); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(currentArea->rect()); + } else + if ( currentAction==DrawPolygon ) { + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(currentArea->rect()); + } else + if ( currentAction==MoveArea ) { + QRect oldRect=translateToZoom(currentArea->selectionRect()); + currentArea->moveBy((drawCurrent-drawStart).x(),(drawCurrent-drawStart).y()); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + drawStart=drawCurrent; + imageMapEditor->slotUpdateSelectionCoords(); + } else + if ( currentAction==MoveSelectionPoint ) { + QRect oldRect=translateToZoom(currentArea->selectionRect()); + currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(); + } + imageMapEditor->slotChangeStatusCoords(drawCurrent.x(),drawCurrent.y()); +} + +void ImageMap::resizeEvent(QResizeEvent* e) { + QScrollView::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(QPainter* 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); + QRect r(currentArea->rect()); + r.moveBy(imageRect.left()-5,imageRect.top()-5); + r.setSize(r.size()+QSize(10,10)); + p->setClipRegion(r); + } +*/ + + QRect updateRect(clipx,clipy,clipw,cliph); + QPixmap doubleBuffer(updateRect.size()); // Pixmap for double-buffering + QPainter 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 + QRegion region(contentsX(),contentsY(),visibleWidth(),visibleHeight()); + region=region.subtract(QRegion(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); +// } + + +} |