/*************************************************************************** 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 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.bottom()) drawStart.setY(imageRect.bottom()); if (drawStart.y()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.bottom()) drawEnd.setY(imageRect.bottom()); if (drawEnd.y()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.bottom()) drawCurrent.setY(imageRect.bottom()); if (drawCurrent.y()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;ieraseRect(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); // } }