1
#include "Interaction/MoveTrackPointInteraction.h"
4
#include "Command/DocumentCommands.h"
5
#include "Command/RoadCommands.h"
6
#include "Command/TrackPointCommands.h"
7
#include "Maps/Coord.h"
8
#include "Maps/MapDocument.h"
9
#include "Maps/Projection.h"
10
#include "Maps/TrackPoint.h"
11
#include "Utils/LineF.h"
12
#include "Utils/MDiscardableDialog.h"
14
#include <QtGui/QCursor>
15
#include <QtGui/QMouseEvent>
16
#include <QtGui/QPixmap>
17
#include <QMessageBox>
21
MoveTrackPointInteraction::MoveTrackPointInteraction(MapView* aView)
22
: FeatureSnapInteraction(aView), StartDragPosition(0,0)
26
MoveTrackPointInteraction::~MoveTrackPointInteraction(void)
30
QString MoveTrackPointInteraction::toHtml()
33
help = (MainWindow::tr("LEFT-CLICK to select;LEFT-DRAG to move"));
35
QStringList helpList = help.split(";");
38
desc = QString("<big><b>%1</b></big>").arg(MainWindow::tr("Move node Interaction"));
42
"<small><i>" + QString(metaObject()->className()) + "</i></small><br/>"
45
S += "<ul style=\"margin-left: 0px; padding-left: 0px;\">";
46
for (int i=0; i<helpList.size(); ++i) {
47
S+= "<li>" + helpList[i] + "</li>";
50
S += "</body></html>";
56
QCursor MoveTrackPointInteraction::cursor() const
58
QPixmap pm(":/Icons/move.xpm");
64
void MoveTrackPointInteraction::snapMousePressEvent(QMouseEvent * event, MapFeature* aLast)
66
QList<MapFeature*> sel;
67
if (view()->isSelectionLocked()) {
68
if (view()->properties()->selection(0))
69
sel.append(view()->properties()->selection(0));
78
OriginalPosition.clear();
79
StartDragPosition = XY_TO_COORD(event->pos());
80
for (int j=0; j<sel.size(); j++) {
81
if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(sel[j]))
85
StartDragPosition = Pt->position();
87
else if (Road* R = dynamic_cast<Road*>(sel[j])) {
88
for (int i=0; i<R->size(); ++i)
89
if (std::find(Moving.begin(),Moving.end(),R->get(i)) == Moving.end())
90
Moving.push_back(R->getNode(i));
94
for (int i=0; i<Moving.size(); ++i)
96
OriginalPosition.push_back(Moving[i]->position());
97
addToNoSnap(Moving[i]);
101
void MoveTrackPointInteraction::snapMouseReleaseEvent(QMouseEvent * event, MapFeature* Closer)
103
if (Moving.size() && !panning())
105
CommandList* theList;
106
if (Moving.size() > 1)
107
theList = new CommandList(MainWindow::tr("Move Nodes").arg(Moving[0]->id()), Moving[0]);
109
theList = new CommandList(MainWindow::tr("Move Node %1").arg(Moving[0]->id()), Moving[0]);
110
Coord Diff(calculateNewPosition(event,Closer, theList)-StartDragPosition);
111
for (int i=0; i<Moving.size(); ++i)
113
Moving[i]->setPosition(OriginalPosition[i]);
114
if (Moving[i]->layer()->isTrack())
115
theList->add(new MoveTrackPointCommand(Moving[i],OriginalPosition[i]+Diff, Moving[i]->layer()));
117
theList->add(new MoveTrackPointCommand(Moving[i],OriginalPosition[i]+Diff, document()->getDirtyOrOriginLayer(Moving[i]->layer())));
120
// If moving a single node (not a track node), see if it got dropped onto another node
121
if (Moving.size() == 1 && !Moving[0]->layer()->isTrack())
123
Coord newPos = OriginalPosition[0] + Diff;
124
QList<TrackPoint*> samePosPts;
125
for (VisibleFeatureIterator it(document()); !it.isEnd(); ++it)
127
TrackPoint* visPt = CAST_NODE(it.get());
128
if (visPt && visPt->layer()->classType() != MapLayer::TrackMapLayerType)
130
if (visPt == Moving[0])
133
if (visPt->position() == newPos)
135
samePosPts.push_back(visPt);
139
// Ensure the node being moved is at the end of the list.
140
// (This is not the node that all nodes will be merged into,
141
// they are always merged into a node that already was at that position.)
142
samePosPts.push_back(Moving[0]);
144
if (samePosPts.size() > 1) // Ignore the node we're moving, see if there are more
146
MDiscardableMessage dlg(view(),
147
MainWindow::tr("Nodes at the same position found."),
148
MainWindow::tr("Do you want to merge all nodes at the drop position?"));
149
if (dlg.check() == QDialog::Accepted)
151
// Merge all nodes from the same position
153
// from MainWindow::on_nodeMergeAction_triggered()
154
// Merge all nodes into the first node that has been found (not the node being moved)
155
MapFeature* F = samePosPts[0];
156
// Change the command description to reflect the merge
157
theList->setDescription(MainWindow::tr("Merge Nodes into %1").arg(F->id()));
158
theList->setFeature(F);
160
// from mergeNodes(theDocument, theList, theProperties);
161
QList<MapFeature*> alt;
162
TrackPoint* merged = samePosPts[0];
163
alt.push_back(merged);
164
for (int i = 1; i < samePosPts.size(); ++i) {
165
MapFeature::mergeTags(document(), theList, merged, samePosPts[i]);
166
theList->add(new RemoveFeatureCommand(document(), samePosPts[i], alt));
169
view()->properties()->setSelection(F);
174
document()->addHistory(theList);
175
view()->invalidate(true, false);
178
OriginalPosition.clear();
182
void MoveTrackPointInteraction::snapMouseMoveEvent(QMouseEvent* event, MapFeature* Closer)
184
if (Moving.size() && !panning())
186
Coord Diff = calculateNewPosition(event,Closer,NULL)-StartDragPosition;
187
for (int i=0; i<Moving.size(); ++i)
188
Moving[i]->setPosition(OriginalPosition[i]+Diff);
189
view()->invalidate(true, false);
193
Coord MoveTrackPointInteraction::calculateNewPosition(QMouseEvent *event, MapFeature *aLast, CommandList* theList)
195
Coord TargetC = XY_TO_COORD(event->pos());
196
if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(aLast))
197
return Pt->position();
198
else if (Road* R = dynamic_cast<Road*>(aLast))
200
QPoint Target(TargetC.lat(),TargetC.lon());
201
LineF L1(R->getNode(0)->position(),R->getNode(1)->position());
202
double Dist = L1.capDistance(TargetC);
203
QPoint BestTarget = L1.project(Target).toPoint();
205
for (int i=2; i<R->size(); ++i)
207
LineF L2(R->getNode(i-1)->position(),R->getNode(i)->position());
208
double Dist2 = L2.capDistance(TargetC);
212
BestTarget = L2.project(Target).toPoint();
216
if (theList && (Moving.size() == 1))
218
RoadAddTrackPointCommand(R,Moving[0],BestIdx,document()->getDirtyOrOriginLayer(R->layer())));
219
return Coord(BestTarget.x(),BestTarget.y());