This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
IndoorMap/mapview/tools/ToolSelector.h
2016-06-06 22:08:53 +02:00

165 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()) {
if (!el->getMV2D()) {continue;}
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