Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/Rubberbands/rubberband.h
T
2026-08-13 18:33:10 +02:00

320 lines
14 KiB
Objective-C
Executable File

/**
**
** @RDE_HEADER@
** Definition of base class for 2D rubberbands
** $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
**
** -----------------------------------------------------------------------------------------------
*/
#pragma once
#include "rubberband_base.h"
#include <Map/map.h>
#include <Common/ref_pointer.h>
#include <QtCore/QFlags>
#include <QtCore/QPointer>
#include <memory>
namespace Esri {
namespace ArcGISRuntime {
class MapGraphicsView;
class Point;
} }
namespace SituationMap
{
/**
Namespace for all rubberband stuff (is part of namespace SituationMap)
*/
namespace RB
{
class RubberbandDrawable;
class RubberbandHandle;
/**
@class Rubberband rubberband.h
@brief Base class of all 2D rubberbands
Rubberbands are used to create or modifiy 2D geometries like lines, circles, polygons etc. by processing
Qt input events like keyboard and mouse events. To create a rubberband the RubberbandFactory has to be used.
At end of rubberband processing the signal \c abort or\c apply are emitted. To delete the rubberband the
function deleteMySelf must be called. To use the delete operator is dangerous because at end of signal
processing some program code may be performed.
Example to how to use rubberband:
@code
SituationMap::Map & map = ...
const RubberbandFactory & rubberbandFactory = map.rubberbandFactory();
RubberbandPointFeature * rubberband = rubberbandFactory.create<RubberbandPointFeature>();
if (rubberband != nullptr)
{
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::apply, [=](SiMapRubBnd::Rubberband * rubberband )
{
// rubberband has finished input
if (rubberband)
{
const QVector<QPointF> & vertexList = rubberband->coordinateVector();
// do something with vertexList
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
}
} );
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::abort, this, [=](SiMapRubBnd::Rubberband * rubberband )
{
// Rubberband has been aborted by user
if (rubberband)
{
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
}
} );
}
@endcode
Following keyboard commands are available in active rubberbands:
| Key | Modifier | Funktion |
| :----: |:-------: | :--------------------------------------------------------------------------- |
| Esc | | Rubberband abbrechen |
| Return | | Rubberband abschließen und Eingabe übernehmen wenn möglich, sonst Abbruch |
| Left | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach links schieben |
| Right | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach rechts schieben |
| Up | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach oben schieben |
| Down | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach unten schieben |
| Left | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach links schieben |
| Right | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach rechts schieben |
| Up | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach oben schieben |
| Down | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach unten schieben |
@see EventDispatcher
@see RubberbandBase, Rubberband, RubberbandPointFeature, RubberbandPointCluster, RubberbandMultiPointFeature, RubberbandRectangle, RubberbandEllipse, RubberbandCorridor, RubberbandArrow
*/
class SITUATIONMAP_EXPORT Rubberband : public RubberbandBase
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Because class EventDispatcher::EventActionInterface is a pure virtual interface function the classic way of declaration would be
*
* SITUATIONMAP_EXPORT Rubberband : public QObject, public virtual EventDispatcher::EventActionInterface
*
* But with Visual Studio 2013 virtual inheritance combined with constructor delegation doesn't work and may crash the program. In
* this case the virtual inheritance of EventActionInterface isn't need because in the derived classes multiple inheritance will
* not be used.
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
Q_OBJECT
public:
/**
@defgroup States Internal state of the rubberband
@{
*/
enum RubberbandState : unsigned int
{
ConstructionState = 1 << 0, ///< Construction state is active when a geomtrie is been build new
ModificationState = 1 << 1, ///< Modification state is active when a existing geometrie is been modified
SelectedState = 1 << 2, ///< Selection state is active, one ore more handles are selected
MultiSelectedState = 1 << 3, ///< multiple handles can be selected
ConstructionWidthState = 1 << 4 ///< Initial define of a width e.b. for corridors
}; /* RubberbandSate */
Q_DECLARE_FLAGS(RubberbandStates,RubberbandState)
/** @} */
/**
@name Construction & Destruction
@{
*/
private:
friend class RubberbandFreeHand;
friend class RubberbandPointFeature;
friend class RubberbandMultiPointFeature;
friend class RubberbandMultiEllipseFeature;
friend class RubberbandRectangle;
friend class RubberbandStateSelect;
friend class RubberbandTransformMove;
friend class RubberbandTransformRotate;
friend class RubberbandTransformScale;
/**
Constructs a Rubberband for a situation map. Use \c RubberbandFactor to create a rubberband.
In case of the user actions the autoDelete mechanism can be used to delete the rubberband. Sometimes
the application wants to finish a running rubberband. This can be done by calling \c deleteMySelf. The
rubberband will be destroyed also automatically if the parent QObject or the map (see
SituationMap::Map::beginDestroy signal) will be destroyed.
@param map Pointer to SituationMap::Map
@param parent Pointer to QObject to use as parent.
@isActive If set to false the Rubberband is not active and have to be actived to start the input.
@see RubberbandFactory
*/
explicit Rubberband( SituationMap::Map * map, QObject * parent, bool isActive = true );
public:
Q_DISABLE_COPY(Rubberband)
virtual ~Rubberband();
/** @} */
/**
@addtogroup States Methodes to query and modify rubberband states
@{
*/
inline bool isEnabledConstructionState() const { return _state.testFlag(RubberbandState::ConstructionState); }
inline bool isEnabledModificationState() const { return _state.testFlag(RubberbandState::ModificationState); }
inline bool isEnabledSelectedState() const { return _state.testFlag(RubberbandState::SelectedState); }
inline bool isEnabledMultiSelectedState() const { return _state.testFlag(RubberbandState::MultiSelectedState); }
inline void enableConstructionState() { disenableModificationState(); }
inline void enableModificationState() { disenableConstructionState(); }
inline void enableSelectedState() { _state |= RubberbandState::SelectedState; }
inline void enableMultiSelectedState() { _state |= RubberbandState::MultiSelectedState; }
inline void disenableConstructionState() { _state &= ~QFlags<RubberbandState>(RubberbandState::ConstructionState); _state |= RubberbandState::ModificationState; }
inline void disenableModificationState() { _state &= ~QFlags<RubberbandState>(RubberbandState::ModificationState); _state |= RubberbandState::ConstructionState; }
inline void disenableSelectedState() { _state &= ~QFlags<RubberbandState>(RubberbandState::SelectedState); }
inline void disenableMultiSelectedState() { _state &= ~QFlags<RubberbandState>(RubberbandState::MultiSelectedState); }
//@}
/**
@name EventHandlerInterface Methodes of AbstractEventDispatcher::EventActionInterface
The interface between EventDispatcher and Rubberband are defined in class AbstractEventDispatcher.
To Implement the interface these methodes have to be override again in the derived classes of the Rubberband class. */
/**
@{
*/
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) override;
bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) override;
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
void resetAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
/** @} */
/**
@name Preview Setting Methodes to define visual behaviour of rubberband preview
@{
*/
inline void setPreviewSidc (const QString & sidc ) { _previewSidc = sidc; update(); } ///< Defines tactical symbol for preview
inline void setPreviewOffset (const QPoint & off ) { _previewCursorOffset = off; update(); } ///< set offset to cursor position for preview pixmap
inline void setPreviewSize (unsigned int size ) { _previewSize = size; update(); } ///< set size of preview pixmap
inline QString getPreviewSidc() const { return _previewSidc; } ///< get code of tactical preview symbol
inline const QPoint getPreviewOffset() const { return _previewCursorOffset; } ///< get offset to cursor position for preview pixmap
inline unsigned int getPreviewSize() const { return _previewSize; } ///< get size of preview pixmap
/** @} */
/**
Returns Sidc code of preview symbol (if defined)
*/
inline QString previewSidc() const { return _previewSidc; }
/**
Sets a QPixmap to use for drawing symbol preview image
@param symbolImage a nice QPixmap
*/
void connectPreviewPixmap( const QPixmap & symbolPixmap );
/**
Returns count of coordinates
*/
virtual unsigned int coordinateCount() const override;
protected:
void deSelectHandles();
void update() override;
/**
Returns the rubberband handle at screen position (x,y) or nullptr if there isn't any handle at this
position.
*/
RubberbandHandle * pickHandle( int x, int y ) const;
/**
Moves preview image to QGraphicView position (x,y) in window coordinates.
*/
void adjustConnectedPreviewPixmap( int x, int y );
/**
Shows a icon near the cursor to mark failing constrains.
*/
void markFailedConstrains( const QPointF & scenePos, bool on );
/*
Forward declaration of internal container class for member variables. The derived classes of Rubberband
often have also a declaration of InternalData for there own internal members.
*/
struct InternalData;
InternalData * _internal;
RubberbandStates _state;
QString _previewSidc;
QPoint _previewCursorOffset;
unsigned int _previewSize;
AdvancedSymbology::SymbolResultWatcher _previewSymbolResultWatcher;
QRectF sceneBbox() const override;
protected slots:
void onPreviewSymbolResultReady();
}; /* Rubberband */
} } /* namespace SituationMap::RB */