164 lines
3.8 KiB
C++
164 lines
3.8 KiB
C++
#ifndef TOOLSELECTOR_H
|
|
#define TOOLSELECTOR_H
|
|
|
|
#include "Tool.h"
|
|
#include "../model/MapModelElement.h"
|
|
#include "../MapView2D.h"
|
|
#include "../model/MapModel.h"
|
|
|
|
|
|
class ToolSelector : public Tool {
|
|
|
|
Q_OBJECT
|
|
|
|
private:
|
|
|
|
/** the currently focused MapElement (if any) */
|
|
MapModelElement* focused = nullptr;
|
|
|
|
/** whether the mouse-button is currently pressed */
|
|
bool mouseIsDown = false;
|
|
|
|
public:
|
|
|
|
virtual ~ToolSelector() {;}
|
|
|
|
|
|
virtual void mousePressEvent(MapView2D* m, QMouseEvent* e) override {
|
|
|
|
if (e->button() != Qt::MouseButton::LeftButton) {return;}
|
|
|
|
mouseIsDown = true;
|
|
|
|
const Scaler& s = m->getScaler();
|
|
Point2 p2(s.xsm(e->x()), s.ysm(e->y()));
|
|
//Point3 p3(s.xsm(e->x()), s.ysm(e->y()), 0);
|
|
|
|
const float g = m->getScaler().sm(10); // increase each BBox by 10 px (needed mainly for hor/ver lines)
|
|
|
|
// get all elements with bounding-box matchings
|
|
std::vector<MapModelElement*> possible;
|
|
for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) {
|
|
BBox2 bbox = el->getMV2D()->getBoundingBox(); // elements 3D bbox
|
|
bbox.grow(Point2(g, g)); // grow a little (needed for straight lines)
|
|
if (bbox.contains(p2)) {possible.push_back(el);} // intersection?
|
|
}
|
|
|
|
// among those, find the best-matching one (smallest distance to an intersection)
|
|
auto lambda = [&] (const MapModelElement* el1, const MapModelElement* el2) {return el1->getMV2D()->getMinDistanceXY(p2) < el2->getMV2D()->getMinDistanceXY(p2);};
|
|
auto it = std::min_element(possible.begin(), possible.end(), lambda);
|
|
MapModelElement* el = (it == possible.end()) ? (nullptr) : (*it);
|
|
|
|
|
|
|
|
// focus changed? -> unfocus the old one (if any)
|
|
if (setFocused(el)) {
|
|
|
|
;
|
|
|
|
} else {
|
|
|
|
// focus kept. provide the currently focused element with events
|
|
if (focused) {focused->getMV2D()->mousePressed(m, p2);}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/** needed eg. when the focused element gets invalid (switching visible layers) */
|
|
void layerChange(MapView2D* m) override {
|
|
(void) m;
|
|
setFocused(nullptr);
|
|
}
|
|
|
|
private:
|
|
|
|
/**
|
|
* @brief change the currently focused element. throws an event.
|
|
* @param el the to-be-focused element or null
|
|
* @return true if the focused element has changed. false otherwise
|
|
*/
|
|
bool setFocused(MapModelElement* el) {
|
|
|
|
// whether the focus has changed or not
|
|
const bool focusChanged = (focused != el);
|
|
|
|
if (focusChanged) {
|
|
|
|
// unfocus the old one (if any)
|
|
if (focused) {focused->getMV2D()->unfocus();}
|
|
|
|
// set the currently focused object (if any)
|
|
focused = el;
|
|
|
|
// focus the new one (if any)
|
|
if (focused) {focused->getMV2D()->focus();}
|
|
|
|
emit onMapElementSelected(el);
|
|
|
|
}
|
|
|
|
// done
|
|
return focusChanged;
|
|
|
|
}
|
|
|
|
virtual void mouseMoveEvent(MapView2D* m, QMouseEvent* e) override {
|
|
|
|
const Scaler& s = m->getScaler();
|
|
Point2 p2(s.xsm(e->x()), s.ysm(e->y()));
|
|
|
|
// mouse pressed?
|
|
if (mouseIsDown) {
|
|
|
|
// provide the focused element with the mouse event?
|
|
if (focused) {focused->getMV2D()->mouseMove(m, p2); return;}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual void mouseReleaseEvent(MapView2D* m, QMouseEvent* e) override {
|
|
|
|
const Scaler& s = m->getScaler();
|
|
Point2 p2(s.xsm(e->x()), s.ysm(e->y()));
|
|
|
|
// provide the focused element with the mouse event?
|
|
if (focused) {focused->getMV2D()->mouseReleased(m, p2);}
|
|
|
|
mouseIsDown = false;
|
|
|
|
}
|
|
|
|
virtual void keyPressEvent(MapView2D* m, QKeyEvent* e) override {
|
|
(void) m;
|
|
|
|
if (focused) {
|
|
|
|
// pass it to the element which may consume this event
|
|
if (focused->getMV2D()->keyPressEvent(m, e)) {return;}
|
|
|
|
// not consumed -> additional options
|
|
|
|
// ESCAPE -> unfocus
|
|
if (e->key() == Qt::Key_Escape) {setFocused(nullptr);}
|
|
|
|
// DELETE -> delete
|
|
if (e->key() == Qt::Key_Delete) {
|
|
focused->deleteMe();
|
|
setFocused(nullptr);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
signals:
|
|
|
|
/** map element was selected */
|
|
void onMapElementSelected(MapModelElement* el);
|
|
|
|
};
|
|
|
|
#endif // TOOLSELECTOR_H
|