File indexing completed on 2024-06-02 04:05:33
0001 /*************************************************************************** 0002 cmaptoolselect.cpp 0003 ------------------- 0004 begin : Tue May 1 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 "cmaptoolselect.h" 0019 0020 #include "../../../cmapmanager.h" 0021 #include "../../../cmapelement.h" 0022 #include "../../../cmapview.h" 0023 #include "../../../cmaplevel.h" 0024 #include "../../../cmappath.h" 0025 #include "../cmapcmdmoveelements.h" 0026 0027 #include <QCursor> 0028 #include <QApplication> 0029 0030 #include <KLocalizedString> 0031 0032 CMapToolSelect::CMapToolSelect(KActionCollection *actionCollection,CMapManager *manager) 0033 : CMapToolBase(actionCollection, 0034 i18n("Select"), 0035 QIcon::fromTheme("kmud_select.png"), 0036 manager,"toolsSelect",nullptr) 0037 { 0038 0039 bDragging = false; 0040 connect (&mouseDownTimer ,SIGNAL(timeout()),SLOT(slotStartDraging())); 0041 } 0042 0043 CMapToolSelect::~CMapToolSelect() 0044 { 0045 } 0046 0047 void CMapToolSelect::paint(QPainter *p) 0048 { 0049 if (!bDragging) return; 0050 0051 int gridWidth = mapManager->getMapData()->gridSize.width(); 0052 int gridHeight = mapManager->getMapData()->gridSize.height(); 0053 0054 CMapLevel *currentLevel = mapManager->getActiveView()->getCurrentlyViewedLevel(); 0055 QList<CMapElement *> lst = currentLevel->getAllElements(); 0056 if (moveDrag) 0057 { 0058 // This is a element move/drag operation 0059 p->setPen(Qt::black); 0060 0061 QPoint offset; 0062 0063 offset.setX((((int)(lastDrag.x() / gridWidth)) * gridWidth) - (((int)(mouseDrag.x()/gridWidth))*gridWidth)); 0064 offset.setY((((int)(lastDrag.y() / gridHeight)) * gridHeight) - (((int)(mouseDrag.y()/gridHeight))*gridHeight)); 0065 0066 foreach (CMapElement *element, lst) 0067 if (element->getSelected()) 0068 element->dragPaint(offset,p,currentLevel->getZone()); 0069 } 0070 else if (resizeDrag > 0) 0071 { 0072 QPoint offset; 0073 0074 offset.setX(((((int)(lastDrag.x() / gridWidth)) * gridWidth) - (((int)((mouseDrag.x()-6)/gridWidth))*gridWidth))-gridWidth); 0075 offset.setY(((((int)(lastDrag.y() / gridHeight)) * gridHeight) - (((int)((mouseDrag.y()-6)/gridHeight))*gridHeight))-gridHeight); 0076 0077 foreach (CMapElement *element, lst) 0078 if (element->getSelected()) 0079 element->resizePaint(offset,p,currentLevel->getZone(),resizeDrag); 0080 } 0081 else if (m_editDrag > 0) 0082 { 0083 foreach (CMapElement *element, lst) 0084 if (element->getElementType()==PATH && element->getEditMode()) 0085 ((CMapPath *)element)->editPaint(lastDrag,p,currentLevel->getZone(),m_editDrag); 0086 } 0087 else 0088 { 0089 // This is a element move/drag operation 0090 p->setPen(QColor(128, 128, 128, 64)); 0091 p->setBrush(QColor(0, 128, 255, 32)); 0092 p->drawRect(mouseDrag.x(),mouseDrag.y(),lastDrag.x()-mouseDrag.x(),lastDrag.y()-mouseDrag.y()); 0093 } 0094 } 0095 0096 /** Called when the tool recives a mouse press event */ 0097 void CMapToolSelect::mousePressEvent(QPoint mousePos, QMouseEvent *, CMapLevel *currentLevel) 0098 { 0099 moveDrag = false; 0100 resizeDrag = 0; 0101 m_editDrag = 0; 0102 0103 QList<CMapElement *> lst = currentLevel->getAllElements(); 0104 0105 // Check to see if the mouse was pressed in an element 0106 foreach (CMapElement *element, lst) 0107 { 0108 // Is a edit drag in operation 0109 if (element->getElementType()==PATH && element->getEditMode()) 0110 { 0111 CMapPath *path = (CMapPath *)element; 0112 m_editDrag = path->mouseInEditBox(mousePos,currentLevel->getZone()); 0113 0114 if (m_editDrag > 0) 0115 { 0116 break; 0117 } 0118 } 0119 0120 // Is a resize drag in operation 0121 resizeDrag = element->mouseInResize(mousePos,currentLevel->getZone()); 0122 if (resizeDrag > 0 && element->getSelected()) 0123 { 0124 break; 0125 } 0126 else 0127 { 0128 resizeDrag = 0; 0129 if (element->mouseInElement(mousePos)) 0130 { 0131 moveDrag = true; 0132 } 0133 } 0134 } 0135 0136 if (resizeDrag > 0 || m_editDrag > 0) 0137 { 0138 // Repaint the map without the elements being resized 0139 foreach (CMapElement *element, lst) 0140 { 0141 if (element->getSelected()) 0142 { 0143 element->setDoPaint(false); 0144 } 0145 0146 if (element->getEditMode() && element->getElementType()==PATH) 0147 { 0148 ((CMapPath *)element)->setDontPaintBend(m_editDrag); 0149 } 0150 } 0151 0152 mapManager->redrawAllViews(); 0153 } 0154 0155 if (moveDrag || resizeDrag > 0 || m_editDrag > 0) 0156 { 0157 // The mouse was pressed in an element so this is a element move/drag operation 0158 mouseDrag = mousePos; 0159 lastDrag = QPoint (-100,-100); 0160 } 0161 else 0162 { 0163 // The mouse was not pressed in a element so this is a rectangle drag selection operation 0164 mouseDrag = lastDrag = mousePos; 0165 } 0166 0167 mapManager->levelChanged(currentLevel); 0168 0169 mouseDownTimer.start(150); 0170 } 0171 0172 QPoint CMapToolSelect::alignToGrid(QPoint offset) 0173 { 0174 int gridWidth = mapManager->getMapData()->gridSize.width(); 0175 int gridHeight = mapManager->getMapData()->gridSize.height(); 0176 0177 offset.setX(offset.x() - offset.x() % gridWidth); 0178 offset.setY(offset.y() - offset.y() % gridHeight); 0179 0180 return offset; 0181 } 0182 0183 /** Called when the tool recives a mouse release event */ 0184 void CMapToolSelect::mouseReleaseEvent(QPoint mousePos, QMouseEvent *e, CMapLevel *currentLevel) 0185 { 0186 QList<CMapElement *> lst = currentLevel->getAllElements(); 0187 0188 mouseDownTimer.stop(); 0189 0190 // Was a drag operation performed 0191 if (bDragging) 0192 { 0193 // Yes a drag is in action 0194 if (moveDrag) 0195 { 0196 // An element was draged to a new position so move it 0197 moveElement(alignToGrid(mousePos) - alignToGrid(mouseDrag), currentLevel); 0198 } 0199 else if (resizeDrag > 0) 0200 { 0201 // An element was resized so change it's size 0202 resizeElements(mousePos,currentLevel); 0203 } 0204 else if (m_editDrag > 0) 0205 { 0206 foreach (CMapElement *element, lst) 0207 { 0208 if (element->getElementType()==PATH && element->getEditMode()) 0209 { 0210 mapManager->openCommandGroup(i18n("Move Bend")); 0211 CMapPath *path = (CMapPath *) element; 0212 0213 path->setDontPaintBend(0); 0214 path->moveBendWithUndo(m_editDrag,mousePos); 0215 if (path->getOpsitePath()) 0216 { 0217 path->getOpsitePath()->moveBendWithUndo(m_editDrag,mousePos); 0218 } 0219 mapManager->closeCommandGroup(); 0220 break; 0221 } 0222 } 0223 } 0224 else 0225 { 0226 bool found = false; 0227 0228 // A rectangle selection operation was performed 0229 if (!(QApplication::keyboardModifiers() & Qt::ControlModifier)) 0230 { 0231 //FIXME_jp: unselectElements should return a bool like in kmud1 0232 mapManager->unselectElements(currentLevel); 0233 found = true; 0234 } 0235 0236 int x1 = mouseDrag.x() < lastDrag.x() ? mouseDrag.x() : lastDrag.x(); 0237 int y1 = mouseDrag.y() < lastDrag.y() ? mouseDrag.y() : lastDrag.y(); 0238 int x2 = mouseDrag.x() >= lastDrag.x() ? mouseDrag.x() : lastDrag.x(); 0239 int y2 = mouseDrag.y() >= lastDrag.y() ? mouseDrag.y() : lastDrag.y(); 0240 QRect area = QRect(QPoint(x1,y1),QPoint(x2,y2)); 0241 0242 // Select the elements in the rectangle 0243 foreach (CMapElement *element, lst) 0244 { 0245 if (element->elementIn(area,currentLevel->getZone())) 0246 { 0247 element->setSelected(true); 0248 found = true; 0249 } 0250 } 0251 if (found) 0252 { 0253 mapManager->levelChanged(currentLevel); 0254 } 0255 } 0256 0257 bDragging = false; 0258 return; 0259 } 0260 0261 // If we are shift-clicking, toggle whatever is clicked on. Otherwise unselect everything, then select what got clicked on. 0262 bool shift = e->modifiers() & Qt::ShiftModifier; 0263 0264 if (!shift) 0265 mapManager->unselectElements(currentLevel); 0266 0267 foreach (CMapElement *element, lst) 0268 { 0269 if (!element->mouseInElement(mousePos)) continue; 0270 bool sel = shift ? (!element->getSelected()) : true; 0271 element->setSelected(sel); 0272 break; 0273 } 0274 0275 mapManager->getActiveView()->changed(); 0276 } 0277 0278 void CMapToolSelect::mouseDoubleClickEvent(QPoint mousePos, QMouseEvent *, CMapLevel *currentLevel) 0279 { 0280 // If we double-click on something that is not a room, do nothing 0281 QList<CMapElement *> elements = currentLevel->elementsUnderMouse(mousePos); 0282 CMapRoom *room = nullptr; 0283 foreach (CMapElement *el, elements) { 0284 room = dynamic_cast<CMapRoom *>(el); 0285 if (room) break; 0286 } 0287 if (!room) return; 0288 0289 // If we do not have a current room, set this room as one. 0290 if (!mapManager->getCurrentRoom()) { 0291 mapManager->setCurrentRoom(room); 0292 return; 0293 } 0294 0295 // If we do, speedwalk from there to this room. 0296 mapManager->walkPlayerTo(room); 0297 } 0298 0299 0300 /** Called when the tool recives a mouse move event */ 0301 void CMapToolSelect::mouseMoveEvent(QPoint mousePos, Qt::KeyboardModifiers, Qt::MouseButtons, CMapLevel *) 0302 { 0303 // If a drag operation is not in progress then return 0304 if (!bDragging) return; 0305 0306 // Make sure this is not the same position as the last one 0307 if (lastDrag!=mousePos) 0308 { 0309 lastDrag=mousePos; 0310 mapManager->getActiveView()->requestPaint(); 0311 } 0312 } 0313 0314 /** This is called when a key is pressed */ 0315 void CMapToolSelect::keyPressEvent(QKeyEvent *e) 0316 { 0317 int x = 0, y = 0; 0318 if (e->key() == Qt::Key_Left) x = -1; 0319 else if (e->key() == Qt::Key_Right) x = 1; 0320 else if (e->key() == Qt::Key_Up) y = -1; 0321 else if (e->key() == Qt::Key_Down) y = 1; 0322 else return; 0323 0324 int gridWidth = mapManager->getMapData()->gridSize.width(); 0325 int gridHeight = mapManager->getMapData()->gridSize.height(); 0326 0327 QPoint offset(gridWidth * x, gridHeight * y); 0328 moveElement(offset, mapManager->getActiveView()->getCurrentlyViewedLevel()); 0329 } 0330 0331 /** This function called when a tool is selected */ 0332 void CMapToolSelect::toolSelected(void) 0333 { 0334 CMapView *view = mapManager->getActiveView(); 0335 if (view) 0336 { 0337 view->setMouseTracking(false); 0338 view->setCursor(Qt::ArrowCursor); 0339 } 0340 } 0341 0342 /** This function is called when a tool is unselected */ 0343 void CMapToolSelect::toolUnselected(void) 0344 { 0345 CMapView *view = mapManager->getActiveView(); 0346 if (view) 0347 mapManager->unselectElements(view->getCurrentlyViewedLevel()); 0348 } 0349 0350 /** Used to move elements */ 0351 void CMapToolSelect::moveElement(QPoint offset, CMapLevel *currentLevel) 0352 { 0353 moveDrag = false; 0354 0355 offset = alignToGrid(offset); 0356 0357 CMapCmdMoveElements *cmd = new CMapCmdMoveElements(mapManager, offset); 0358 0359 bool found = false; 0360 QList<CMapElement *> lst = currentLevel->getAllElements(); 0361 foreach (CMapElement *element, lst) 0362 if (element->getSelected()) { 0363 cmd->addElement(element); 0364 found = true; 0365 } 0366 0367 if (found) 0368 mapManager->addCommand(cmd); 0369 else 0370 delete cmd; 0371 } 0372 0373 /** Used to resize the selected elements */ 0374 void CMapToolSelect::resizeElements(QPoint mousePos,CMapLevel *currentLevel) 0375 { 0376 int gridWidth = mapManager->getMapData()->gridSize.width(); 0377 int gridHeight = mapManager->getMapData()->gridSize.height(); 0378 0379 QPoint offset; 0380 offset.setX(((((int)(mousePos.x() / gridWidth)) * gridWidth) - (((int)((mouseDrag.x()-6)/gridWidth))*gridWidth))-gridWidth); 0381 offset.setY(((((int)(mousePos.y() / gridHeight)) * gridHeight) - (((int)((mouseDrag.y()-6)/gridHeight))*gridHeight))-gridHeight); 0382 0383 QList<CMapElement *> lst = currentLevel->getAllElements(); 0384 foreach (CMapElement *element, lst) 0385 if (element->getSelected()) 0386 { 0387 element->resize(offset,resizeDrag); 0388 element->setDoPaint(true); 0389 } 0390 0391 resizeDrag = 0; 0392 mapManager->levelChanged(currentLevel); 0393 } 0394 0395 ///////////////////////////////////// SLOTS ///////////////////////////////////////////////// 0396 0397 /** Called when a rectange drag opertion is performed */ 0398 void CMapToolSelect::slotStartDraging(void) 0399 { 0400 bDragging = true; 0401 mouseDownTimer.stop(); 0402 0403 CMapView *view = mapManager->getActiveView(); 0404 CMapLevel *currentLevel = view->getCurrentlyViewedLevel(); 0405 0406 if (!currentLevel) return; 0407 0408 QList<CMapElement *> lst = currentLevel->elementsUnderMouse(mouseDrag); 0409 foreach (CMapElement *element, lst) 0410 element->setSelected(true); 0411 } 0412 0413 #include "moc_cmaptoolselect.cpp"