File indexing completed on 2023-10-01 04:14:06
0001 /****************************************************************f*********** 0002 cmapelement.cpp 0003 ------------------- 0004 begin : Sat Mar 10 2001 0005 copyright : (C) 2001 by Kmud Developer Team 0006 email : kmud-devel@kmud.de 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 ***************************************************************************/ 0017 0018 #include "cmapelement.h" 0019 0020 #include <stdlib.h> 0021 0022 #include <kdebug.h> 0023 #include <klocale.h> 0024 #include <kconfiggroup.h> 0025 0026 #include "cmaplevel.h" 0027 #include "cmapmanager.h" 0028 #include "cmapcmdelementproperties.h" 0029 #include "cmapview.h" 0030 0031 #define RESIZE_SIZE 10 0032 #define RESIZE_SIZE_HALF 5 0033 0034 CMapElement::CMapElement(CMapManager *manager,QRect rect,CMapLevel *level) : QObject (nullptr) 0035 { 0036 mapManager = manager; 0037 position = rect; 0038 mapLevel = level; 0039 selected = false; 0040 editing = false; 0041 doPaint = true; 0042 0043 if (mapManager->getZone(true)) 0044 mapManager->addedElement(this); 0045 0046 connect(this,SIGNAL(deleteElement(CMapElement *,bool)),manager,SLOT(deleteElement(CMapElement *,bool))); 0047 } 0048 0049 CMapElement::CMapElement(CMapManager *manager,CMapLevel *level) 0050 { 0051 mapManager = manager; 0052 mapLevel = level; 0053 selected = false; 0054 editing = false; 0055 doPaint = true; 0056 0057 mapManager->addedElement(this); 0058 } 0059 0060 CMapElement::~CMapElement() 0061 { 0062 if (mapLevel) 0063 mapManager->getActiveView()->deletedElement(mapLevel); 0064 } 0065 0066 /** This method is used to get the level that the element is in */ 0067 CMapLevel *CMapElement::getLevel(void) 0068 { 0069 return mapLevel; 0070 } 0071 0072 /** This method is used to set the level that the element is in */ 0073 void CMapElement::setLevel(CMapLevel *level) 0074 { 0075 mapLevel = level; 0076 mapManager->changedElement(this); 0077 } 0078 0079 void CMapElement::paint(QPainter *p,CMapZone *zone) 0080 { 0081 paintElementResize(p,getLowPos(),getSize(),zone); 0082 0083 // If the room is selected then draw the selection indicator 0084 if (getSelected()) 0085 { 0086 //FIXME_jp: Move this somewere else so that it's only caled when the element position changes 0087 generateResizePositions(); 0088 paintResizeHandles (p, resizePos); 0089 } 0090 } 0091 0092 /** This method is used to paint the resize handles 0093 * @param p The painter used to do the painting 0094 * @param resizePos The positions of the handles to be painted */ 0095 void CMapElement::paintResizeHandles(QPainter *p, QList<QRect> &resizePos) 0096 { 0097 p->setPen(getManager()->getMapData()->selectedColor); 0098 p->setBrush(getManager()->getMapData()->selectedColor); 0099 0100 foreach (QRect rect, resizePos) 0101 p->drawRect(rect); 0102 } 0103 0104 CMapZone *CMapElement::getZone(void) 0105 { 0106 if (mapLevel) 0107 return mapLevel->getZone(); 0108 else 0109 return nullptr; 0110 } 0111 0112 /** Used to find out if the mouse is in the element */ 0113 bool CMapElement::mouseInElement(QPoint mousePos) 0114 { 0115 QRect rect = position; 0116 0117 if (rect.left() == rect.right()) 0118 { 0119 rect.setLeft(rect.left()-5); 0120 rect.setRight(rect.right()+5); 0121 } 0122 0123 if (rect.top() == rect.bottom()) 0124 { 0125 rect.setTop(rect.top()-5); 0126 rect.setBottom(rect.bottom()+5); 0127 } 0128 0129 QRegion region(rect,QRegion::Rectangle); 0130 0131 return region.contains(mousePos); 0132 } 0133 0134 /** This method is used to set the elements edit mode state */ 0135 void CMapElement::setEditMode(bool edit) 0136 { 0137 bool oldEdit = editing; 0138 editing = edit; 0139 0140 if (oldEdit!=editing) 0141 { 0142 if (edit) 0143 editModeSetEvent(); 0144 else 0145 editModeUnsetEvent(); 0146 } 0147 } 0148 0149 /** This method is used to find out if the element is in edit mode */ 0150 bool CMapElement::getEditMode(void) 0151 { 0152 return editing; 0153 } 0154 0155 /** Used to find out if the mouse is in the resize box 0156 * @param mousePos The position of the mouse pointer 0157 * @param currentZone A pointer to the current zone 0158 * @return the ID of the resize box, or 0 if not in any */ 0159 int CMapElement::mouseInResize(QPoint mousePos,CMapZone *) 0160 { 0161 int num = 1; 0162 0163 foreach (QRect rect, resizePos) 0164 { 0165 QRegion region(rect,QRegion::Rectangle); 0166 if (region.contains(mousePos)) 0167 return num; 0168 num++; 0169 } 0170 0171 return 0; 0172 } 0173 0174 /** Used to find out if the mouse is in the resize box 0175 * @param mousePos The position of the mouse pointer 0176 * @param currentZone A pointer to the current zone 0177 * @return the ID of the resize box, or 0 if not in any */ 0178 bool CMapElement::elementIn(QRect rect,CMapZone *) 0179 { 0180 QRegion region( rect,QRegion::Rectangle); 0181 0182 return region.contains(position); 0183 } 0184 0185 /** Used to move the element relative to it's current position */ 0186 void CMapElement::moveBy(QPoint offset) 0187 { 0188 position.translate(offset.x(),offset.y()); 0189 } 0190 0191 /** This is used to paint a element while it is being resized 0192 * @param offset The offset of the mouse pointer since the start of the resize operation 0193 * @param p The painter to paint the element too 0194 * @param currentZone The current zone being viewed 0195 * @param resizeId The id of the resize handle being moved */ 0196 void CMapElement::resizePaint(QPoint offset,QPainter *p,CMapZone *currentZone,int resizeId) 0197 { 0198 signed int offsetx = offset.x(); 0199 signed int offsety = offset.y(); 0200 QPoint pos = getLowPos(); 0201 QSize size = getSize(); 0202 0203 // Calc new positions 0204 calcResizeCords(&size,&pos,&offsetx,&offsety,&offset,resizeId); 0205 0206 // Paint the element 0207 paintElementResize(p,pos,size,currentZone); 0208 0209 // Paint resize handles 0210 QList<QRect> tmpResizePos; 0211 generateResizePositions(QRect(pos,size), tmpResizePos); 0212 paintResizeHandles(p, tmpResizePos); 0213 } 0214 0215 void CMapElement::calcResizeCords(QSize *size,QPoint *pos,signed int *offsetx,signed int *offsety,QPoint *offset,int resizeId) 0216 { 0217 int gridWidth = getManager()->getMapData()->gridSize.width(); 0218 int gridHeight = getManager()->getMapData()->gridSize.height(); 0219 0220 switch (resizeId) 0221 { 0222 case 1 : if (size->height()-*offsety<=0) // NORTH 0223 { 0224 offset->setY(size->height()-gridHeight); 0225 *offsety=size->height()-gridHeight; 0226 } 0227 if (size->height()-*offsety >= gridHeight) 0228 { 0229 pos->setY(pos->y()+*offsety); 0230 if (*offsety>0) 0231 *size-=QSize(0,abs(*offsety)); 0232 else 0233 *size+=QSize(0,abs(*offsety)); 0234 } 0235 break; 0236 case 2 : if (size->height()-*offsety<=0) // NORTHEAST 0237 { 0238 offset->setY(size->height()-gridHeight); 0239 *offsety=size->height()-gridHeight; 0240 } 0241 if (size->height()-*offsety >= gridHeight) 0242 { 0243 pos->setY(pos->y()+offset->y()); 0244 if (*offsety>0) 0245 size->setHeight(size->height()-abs(*offsety)); 0246 else 0247 size->setHeight(size->height()+abs(*offsety)); 0248 } 0249 size->setWidth(size->width()+*offsetx); 0250 break; 0251 case 3 : *size+=QSize(*offsetx,0); // EAST 0252 break; 0253 case 4 : *size+=QSize(*offsetx,*offsety); // SOUTHEAST 0254 break; 0255 case 5 : *size+=QSize(0,*offsety); // SOUTH 0256 break; 0257 case 6 : *size+=QSize(0,*offsety); // SOUTHWEST 0258 if (size->width()-*offsetx<=0) 0259 { 0260 offset->setX(size->width()-gridWidth); 0261 *offsetx = size->width()-gridWidth; 0262 } 0263 if (size->width()-*offsetx >= gridWidth) 0264 { 0265 pos->setX(pos->x()+*offsetx); 0266 if (*offsetx>0) 0267 size->setWidth(size->width()-abs(*offsetx)); 0268 else 0269 size->setWidth(size->width()+abs(*offsetx)); 0270 } 0271 0272 break; 0273 case 7 : if (size->width()-*offsetx<=0) // WEST 0274 { 0275 offset->setX(size->width()-gridWidth); 0276 *offsetx = size->width()-gridWidth; 0277 } 0278 if (size->width()-*offsetx >= gridWidth) 0279 { 0280 pos->setX(pos->x()+*offsetx); 0281 if (*offsetx>0) 0282 size->setWidth(size->width()-abs(*offsetx)); 0283 else 0284 size->setWidth(size->width()+abs(*offsetx)); 0285 } 0286 break; 0287 case 8 : if (size->width()-*offsetx<=0) // NORTHWEST 0288 { 0289 offset->setX(size->width()-gridWidth); 0290 *offsetx = size->width()-gridWidth; 0291 } 0292 if (size->height()-*offsety<=0) 0293 { 0294 offset->setY(size->height()-gridHeight); 0295 *offsety=size->height()-gridHeight; 0296 } 0297 if (size->width()-*offsetx >= gridWidth && 0298 size->height()-*offsety >= gridHeight) 0299 { 0300 *pos+=*offset; 0301 if (*offsetx>0) 0302 size->setWidth(size->width()-abs(*offsetx)); 0303 else 0304 size->setWidth(size->width()+abs(*offsetx)); 0305 0306 if (*offsety>0) 0307 size->setHeight(size->height()-abs(*offsety)); 0308 else 0309 size->setHeight(size->height()+abs(*offsety)); 0310 } 0311 break; 0312 0313 default : break; 0314 } 0315 0316 if (size->width() < gridWidth) 0317 { 0318 size->setWidth(gridWidth); 0319 } 0320 0321 if (size->height() < gridHeight) 0322 { 0323 size->setHeight(gridHeight); 0324 } 0325 } 0326 0327 /** This is used to resize the element */ 0328 void CMapElement::resize(QPoint offset,int resizeId) 0329 { 0330 QSize size = getSize(); 0331 QPoint pos = getLowPos(); 0332 signed int offsetx = offset.x(); 0333 signed int offsety = offset.y(); 0334 0335 // Clac the new positions 0336 calcResizeCords(&size,&pos,&offsetx,&offsety,&offset,resizeId); 0337 0338 0339 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(mapManager,i18n("Resize Element"),this); 0340 KConfigGroup grp = cmd->getOrgProperties(); 0341 grp.writeEntry("X",getX()); 0342 grp.writeEntry("Y",getY()); 0343 grp.writeEntry("Width",getWidth()); 0344 grp.writeEntry("Height",getHeight()); 0345 grp = cmd->getNewProperties(); 0346 grp.writeEntry("X",pos.x()); 0347 grp.writeEntry("Y",pos.y()); 0348 grp.writeEntry("Width",size.width()); 0349 grp.writeEntry("Height",size.height()); 0350 mapManager->addCommand(cmd); 0351 /* 0352 setLowPos(pos); 0353 setSize(size); 0354 */ 0355 } 0356 0357 /** Used to set the position of the top left of the element */ 0358 void CMapElement::setLowPos(QPoint pos) 0359 { 0360 int width = position.width(); 0361 int height = position.height(); 0362 position.setX(pos.x()); 0363 position.setY(pos.y()); 0364 position.setWidth(width); 0365 position.setHeight(height); 0366 0367 geometryChanged(); 0368 } 0369 0370 0371 /** This method is used to calculate the positions of the resize handles */ 0372 void CMapElement::generateResizePositions() 0373 { 0374 generateResizePositions(getRect(), resizePos); 0375 } 0376 0377 /** This method is used to calc the resize handle positions for a rectangle 0378 * object and add them to a list 0379 * @param rect The coridantes of the object 0380 * @param resizePos The list to add the positions too */ 0381 void CMapElement::generateResizePositions(QRect rect, QList<QRect> &resizePos) 0382 { 0383 int width = rect.width(); 0384 int height = rect.height(); 0385 int x1 = rect.left()+1; 0386 int y1 = rect.top()+1; 0387 int x2 = rect.right(); 0388 int y2 = rect.bottom(); 0389 0390 resizePos.clear(); 0391 resizePos.append(QRect(x1+(width/2)-5,y1-4,7,7)); // NORTH 0392 resizePos.append(QRect(x2-4,y1-4,7,7)); // NORTHEAST 0393 resizePos.append(QRect(x2-4,y1+(height/2)-5,7,7)); // EAST 0394 resizePos.append(QRect(x2-4,y2-4,7,7)); // SOUTHEAST 0395 resizePos.append(QRect(x1+(width/2)-5,y2-4,7,7)); // SOUTH 0396 resizePos.append(QRect(x1-4,y2-4,7,7)); // SOUTHWEST 0397 resizePos.append(QRect(x1-4,y1+(height/2)-5,7,7)); // WEST 0398 resizePos.append(QRect(x1-4,y1-4,7,7)); // NORTHWEST 0399 } 0400 0401 /** Used to load the properties of the element from a list of properties */ 0402 void CMapElement::loadProperties(KConfigGroup grp) 0403 { 0404 QPoint lowPos = getLowPos(); 0405 lowPos.setX(grp.readEntry("X",getX())); 0406 lowPos.setY(grp.readEntry("Y",getY())); 0407 setLowPos(lowPos); 0408 QSize size = getSize(); 0409 size.setWidth(grp.readEntry("Width",getWidth())); 0410 size.setHeight(grp.readEntry("Height",getHeight())); 0411 setSize(size); 0412 } 0413 0414 /** Used to save the properties of the element to a list of properties */ 0415 void CMapElement::saveProperties(KConfigGroup grp) 0416 { 0417 grp.writeEntry("Type",(int)getElementType()); 0418 grp.writeEntry("X",getX()); 0419 grp.writeEntry("Y",getY()); 0420 grp.writeEntry("Width",getWidth()); 0421 grp.writeEntry("Height",getHeight()); 0422 if (getZone()) 0423 grp.writeEntry("Zone",getZone()->getZoneID()); 0424 else 0425 grp.writeEntry("Zone",-1); 0426 0427 CMapLevel *level = getLevel(); 0428 if (level) 0429 { 0430 grp.writeEntry("Level",level->getLevelID()); 0431 } 0432 } 0433 0434 /** Used to save the element as an XML object 0435 * @param properties The XML object to save the properties too 0436 * @param doc The XML Document */ 0437 void CMapElement::saveQDomElement(QDomDocument *,QDomElement *properties) 0438 { 0439 if (properties) 0440 { 0441 properties->setAttribute("Type",(int)getElementType()); 0442 properties->setAttribute("X",getX()); 0443 properties->setAttribute("Y",getY()); 0444 properties->setAttribute("Width",getWidth()); 0445 properties->setAttribute("Height",getHeight()); 0446 } 0447 else 0448 { 0449 kDebug() << "CMapElement::saveQDomElement - properties pointer is null"; 0450 } 0451 } 0452 0453 /** Used to load the properties from a XML object */ 0454 void CMapElement::loadQDomElement(QDomElement *properties) 0455 { 0456 if (properties) 0457 { 0458 int x = properties->attribute("X",QString::number(getX())).toInt(); 0459 int y = properties->attribute("Y",QString::number(getY())).toInt(); 0460 setLowPos(QPoint (x,y)); 0461 0462 setWidth(properties->attribute("Width",QString::number(getWidth())).toInt()); 0463 setHeight(properties->attribute("Height",QString::number(getHeight())).toInt()); 0464 } 0465 } 0466 0467 /** This method is used to put a element in a selected state 0468 * @param sel The selected state to set the element too */ 0469 void CMapElement::setSelected(bool sel) 0470 { 0471 selected = sel; 0472 mapManager->changedElement(this); 0473 } 0474 0475 /** This method is used to get the selected state of the element 0476 * @return The selected state of the element */ 0477 bool CMapElement::getSelected(void) 0478 { 0479 return selected; 0480 } 0481 0482 /** 0483 * This is used to read a color value from a XML object 0484 * @param e The XML object 0485 * @param key The key of the color to read 0486 * @param defaultCol If the color is not found then this will be used 0487 * @return The Color value 0488 */ 0489 QColor CMapElement::readColor(QDomElement *e,QString key,QColor defaultCol) 0490 { 0491 if (!e) 0492 { 0493 return defaultCol; 0494 } 0495 0496 // Find Color element 0497 QDomNode n = e->namedItem(key); 0498 if (n.isNull()) 0499 { 0500 return defaultCol; 0501 } 0502 0503 QDomElement e2 = n.toElement(); 0504 if (e2.isNull() ) 0505 { 0506 return defaultCol; 0507 } 0508 0509 // Get color values 0510 QString red = e2.attribute("Red","Not Found"); 0511 QString green = e2.attribute("Green","Not Found"); 0512 QString blue = e2.attribute("Blue","Not Found"); 0513 0514 if (red=="Not Found" || green=="Not Found" || blue=="Not Found") 0515 { 0516 return defaultCol; 0517 } 0518 0519 QColor col(red.toInt(),green.toInt(),blue.toInt()); 0520 0521 return col; 0522 } 0523 0524 /** 0525 * This is used to write a color value to a XML object 0526 * @param doc The XML document 0527 * @param e The XML object 0528 * @param key The key of the color to write 0529 * @param col The color value to write 0530 */ 0531 void CMapElement::writeColor(QDomDocument *doc,QDomElement *e,QString key,QColor col) 0532 { 0533 QDomElement color = doc->createElement (key); 0534 0535 color.setAttribute("Red",col.red()); 0536 color.setAttribute("Green",col.green()); 0537 color.setAttribute("Blue",col.blue()); 0538 0539 e->appendChild(color); 0540 } 0541 0542 /** 0543 * This method is used to read a int value from a XML object 0544 * @param e The XML object 0545 * @param key The key of the int to read 0546 * @param defaultCol If the int is not found then this will be used 0547 * @return The int value 0548 */ 0549 int CMapElement::readInt(QDomElement *e,QString key,int i) 0550 { 0551 return e->attribute(key,QString::number(i)).toInt(); 0552 } 0553 0554 /** 0555 * This metod is used to write a int value to a XML object 0556 * @param doc The XML document 0557 * @param e The XML object 0558 * @param key The key of the int to write 0559 * @param i The int value to write 0560 */ 0561 void CMapElement::writeInt(QDomDocument *,QDomElement *e,QString key,int i) 0562 { 0563 e->setAttribute(key,i); 0564 } 0565 0566 0567 /** 0568 * This method is used to read a boolean value from a XML object 0569 * @param e The XML object 0570 * @param key The key of the boolean to read 0571 * @param defaultCol If the boolean is not found then this will be used 0572 * @return The boolean value 0573 */ 0574 bool CMapElement::readBool(QDomElement *e,QString key,bool b) 0575 { 0576 QString defaultStr = b ? "true" : "false"; 0577 return (e->attribute(key,defaultStr)=="true"); 0578 } 0579 0580 /** 0581 * This metod is used to write a boolean value to a XML object 0582 * @param doc The XML document 0583 * @param e The XML object 0584 * @param key The key of the boolean to write 0585 * @param b The bolean value to write 0586 */ 0587 void CMapElement::writeBool(QDomElement *e,QString key,bool b) 0588 { 0589 e->setAttribute(key, b ? "true" : "false"); 0590 } 0591 0592 #include "moc_cmapelement.cpp"