/** ** ** @RDE_HEADER@ ** Implementation of rubberband class to define point feature geoemtry ** $Id$ ** $HeadURL$ ** $Author$ ** ** ----------------------------------------------------------------------------------------------- ** ** Hardware-Environment: Intel-PC ** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5 ** ** Language ........: C++ 11 ** ** ----------------------------------------------------------------------------------------------- ** ** Author ...........: Jörg Turla, SPD G, Tel. 3132 ** ** ----------------------------------------------------------------------------------------------- ** ** Notes .........: ** ** 27.03.2015, JT : First edition for use with Qt5 ** ** ----------------------------------------------------------------------------------------------- */ #include "rubberband_free_hand.h" #include "rubberband_point_handle.h" #include "rubberband_drawable.h" #include "drawable_line.h" #include "drawable_painter_path.h" #include "rubberband_handle_proxy.h" #include "rubberband_internal.h" #include "rubberband_base_internal.h" #include namespace SituationMap { namespace RB { struct RubberbandFreeHand::InternalData { QVector _coordinateList; QVector _inOneGoIndex; QPoint _lastWindowPos; bool _coordinateRecordingActive = false; SituationMap::RefPointer _cursorPreviewLine; SituationMap::RefPointer _cursorPreviewCloseLine; SituationMap::RefPointer _pathItem; }; /* RubberbandFreeHand::InternalData */ RubberbandFreeHand::RubberbandFreeHand( SituationMap::Map * map, QObject * parent ) : Rubberband(map,parent) , _internal(new RubberbandFreeHand::InternalData) , _isClosed(false) { } /* RubberbandFreeHand::RubberbandFreeHand */ RubberbandFreeHand::~RubberbandFreeHand() { delete _internal; _internal = nullptr; } /* RubberbandFreeHand::~RubberbandFreeHand */ bool RubberbandFreeHand::selectAction( AbstractEventDispatcher * causer, int x, int y ) { if (Rubberband::selectAction(causer, x, y)) { deactivateButtons(); _internal->_coordinateRecordingActive = true; _internal->_inOneGoIndex << _internal->_coordinateList.size(); return movePickedAction(causer,x,y); } return false; } /* RubberbandFreeHand::selectAction */ bool RubberbandFreeHand::movePickedAction( AbstractEventDispatcher *, int x, int y ) { if (_internal->_coordinateRecordingActive) { QPointF scenePos(pixel2ScenePosition(x,y)); if (_internal->_coordinateList.isEmpty()) { _internal->_lastWindowPos.setX(x); _internal->_lastWindowPos.setY(y); _internal->_coordinateList.append(RubberbandDrawable::RubberbandCoordinate(Rubberband::_internal->_mapView,scenePos)); return true; } if ((std::abs(_internal->_lastWindowPos.x() - x) > 2) || (std::abs(_internal->_lastWindowPos.y() - y) > 2)) { _internal->_lastWindowPos.setX(x); _internal->_lastWindowPos.setY(y); _internal->_coordinateList.append(RubberbandDrawable::RubberbandCoordinate(Rubberband::_internal->_mapView,scenePos)); } update(); return true; } return false; } /* RubberbandFreeHand::movePickedAction */ bool RubberbandFreeHand::moveAction( AbstractEventDispatcher *, int x, int y ) { if (!_internal->_coordinateList.isEmpty()) { const RubberbandDrawable::RubberbandCoordinate & firstPos = _internal->_coordinateList.first(); const RubberbandDrawable::RubberbandCoordinate & lastPos = _internal->_coordinateList.last(); QPointF scenePos(pixel2ScenePosition(x,y)); if (!_internal->_cursorPreviewLine) _internal->_cursorPreviewLine = new DrawableLine( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene ); if ((isClosedEnabled()) && (!_internal->_cursorPreviewCloseLine)) { _internal->_cursorPreviewCloseLine = new DrawableLine( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene ); } _internal -> _cursorPreviewLine -> setVisibility( true ); _internal -> _cursorPreviewLine -> setDrawColor( _handleSelectionColor ); _internal -> _cursorPreviewLine -> setLine( lastPos, RubberbandDrawable::RubberbandCoordinate( Rubberband::_internal->_mapView, scenePos )); if (_internal->_cursorPreviewCloseLine) { _internal -> _cursorPreviewCloseLine -> setVisibility( true ); _internal -> _cursorPreviewCloseLine -> setDrawColor( _handleSelectionColor ); _internal -> _cursorPreviewCloseLine -> setLine( firstPos, RubberbandDrawable::RubberbandCoordinate( Rubberband::_internal->_mapView, scenePos )); } } return false; } /* RubberbandFreeHand::moveAction */ bool RubberbandFreeHand::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y ) { _internal->_coordinateRecordingActive = false; if (Rubberband::setCoordinateAction(causer,x,y)) { QPointF scenePos(pixel2ScenePosition(x,y)); activateButtons(); _baseInternal->buttonProxyActive( scenePos ); } return false; } /* RubberbandFreeHand::setCoordinateAction */ void RubberbandFreeHand::activateButtons() { _baseInternal->_hasUndoButton = true; _baseInternal->_applyIsPossible = true; _baseInternal->_undoIsPossible = !_internal->_inOneGoIndex.isEmpty(); Rubberband::activateButtons(); } /* RubberbandFreeHand::activateButtons */ bool RubberbandFreeHand::undoAction( AbstractEventDispatcher*, int, int ) { if (!_internal->_inOneGoIndex.isEmpty()) { unsigned int coordinateIdx = _internal->_inOneGoIndex.takeLast(); while (coordinateIdx < (unsigned int)_internal->_coordinateList.size()) { _internal->_coordinateList.removeLast(); } update(); activateButtons(); } return true; } /* RubberbandFreeHand::undoAction */ bool RubberbandFreeHand::completeStateAction( AbstractEventDispatcher * causer, int x, int y ) { if (rubberbandIsAlive()) { return applyAndEndAction(causer,x,y); } return false; } /* RubberbandFreeHand::completeStateAction */ unsigned int RubberbandFreeHand::coordinateCount() const { return _internal->_coordinateList.size(); } /* RubberbandFreeHand::coordinateCount */ QVector RubberbandFreeHand::coordinateVector( CoordinateSystem cs ) const { QVector coordinateVector; coordinateVector.reserve(_internal->_coordinateList.size()); for (const RubberbandDrawable::RubberbandCoordinate &pos : qAsConst(_internal->_coordinateList)) coordinateVector.push_back(projectCoordinateFromMap( cs, pos._mapCoordinate )); return coordinateVector; } /* RubberbandFreeHand::coordinateVector */ QPointF RubberbandFreeHand::singleCoordinate(unsigned int idx, CoordinateSystem cs ) const { if (idx >= (unsigned int)_internal->_coordinateList.size()) return QPointF(); const Esri::ArcGISRuntime::Point & pos = _internal->_coordinateList.at(idx)._mapCoordinate; return projectCoordinateFromMap( cs, pos ); } /* RubberbandFreeHand::singleCoordinate */ void RubberbandFreeHand::update() { if (_internal->_coordinateList.size() > 1) { if (!_internal->_pathItem) { _internal->_pathItem = new DrawablePainterPath( Rubberband::_internal->_mapView ); } _internal -> _pathItem -> setVisibility(true); _internal -> _pathItem -> setLineWidth( 2 ); _internal -> _pathItem -> enableClosedLine( _isClosed ); _internal -> _pathItem -> setDrawColor( _drawColor ); _internal -> _pathItem -> setFillColor( _fillColor ); _internal -> _pathItem -> setPath( _internal->_coordinateList ); } else { if (_internal -> _pathItem) _internal->_pathItem->setVisibility(false); if (_internal->_coordinateList.isEmpty()) { if (_internal -> _cursorPreviewLine ) _internal -> _cursorPreviewLine -> setVisibility(false); if (_internal -> _cursorPreviewCloseLine) _internal -> _cursorPreviewCloseLine -> setVisibility(false); } } if (!_internal->_coordinateList.isEmpty()) { QPointF bottomRight( std::numeric_limits::min(), std::numeric_limits::min() ); for (const RubberbandDrawable::RubberbandCoordinate &coordinate : qAsConst(_internal->_coordinateList)) { const QPointF & p = coordinate._sceneCoordinate; if (bottomRight.x() < p.x()) bottomRight.setX(p.x()); if (bottomRight.y() < p.y()) bottomRight.setY(p.y()); } if (isButtonBoxPositionFixed()) { RubberbandBase::_baseInternal->_buttonBoxSceneAnchor = bottomRight; } } } /* RubberbandFreeHand::update */ } } /* namespace SituationMap::RB */