HAL
drag_controller.cpp
Go to the documentation of this file.
5 #include <QApplication>
6 #include <QDebug>
7 
8 namespace hal {
10  : QObject(parent), mGraphWidget(gw), mDragNodeBox(nullptr), mShadowScene(nullptr)
11  {;}
12 
14  {
15  mDragNodeBox = nullptr;
16  mAdditionalBoxes.clear();
17  mDropAllowed = false;
18  mWantSwap = false;
19  GraphicsScene* sc = mGraphWidget->getContext()->getLayouter()->scene();
20  clearShadows(sc);
21  }
22 
24  {
25  if (sc && sc == mShadowScene)
26  {
27  // otherwise (if old scene deleted) items owned by scene already removed
28  for (NodeDragShadow* nds : mShadows.values())
29  {
30  sc->removeItem(nds);
31  delete nds;
32  }
33  mShadowScene->setDragController(nullptr);
34  }
35  mShadows.clear();
36  mShadowScene = nullptr;
37  }
38 
40  {
41  if (!mDropAllowed)
43  if (mWantSwap)
46  }
47 
48  void DragController::set(GraphicsNode *drgItem, const QPoint &eventPos)
49  {
50  clear();
51  if (!drgItem) return;
52  // TODO: swap modifier -> deselect all but current
53 
54  QSet<Node> nodesToMove;
57  bool isAlreadySelected = false;
58 
59  switch (drgItem->itemType())
60  {
61  case ItemType::Module:
62  nodesToMove.insert(Node(drgItem->id(),Node::Module));
63  if (selMods.contains(drgItem->id())) isAlreadySelected = true;
64  break;
65  case ItemType::Gate:
66  nodesToMove.insert(Node(drgItem->id(),Node::Gate));
67  if (selGats.contains(drgItem->id())) isAlreadySelected = true;
68  break;
69  default:
70  break;
71  }
72 
73  if (isAlreadySelected)
74  {
75  // multi-select requires that drag node was already selected before
76  for (u32 mid : selMods)
77  {
78  nodesToMove.insert(Node(mid,Node::Module));
79  }
80  for (u32 gid : selGats)
81  {
82  nodesToMove.insert(Node(gid,Node::Gate));
83  }
84  }
85 
86  auto context = mGraphWidget->getContext();
87  const GraphLayouter* layouter = context->getLayouter();
88  if (!layouter->done()) return;
89 
90  mMousedownPosition = eventPos;
91 
92  for (const Node& nd : nodesToMove)
93  {
94  NodeBox* nb = layouter->boxes().boxForNode(nd);
95  if (!nb) continue;
96  if (nb->item() == drgItem)
97  mDragNodeBox = nb;
98  else
99  mAdditionalBoxes.insert(nb);
100  }
101 
102  if (!mAdditionalBoxes.isEmpty()) mWantSwap = false;
103  }
104 
105  void DragController::setSwapIntent(bool wantSwap)
106  {
107  if (wantSwap == mWantSwap) return;
108  if (wantSwap)
109  {
110  GraphicsScene* sc = mGraphWidget->getContext()->getLayouter()->scene();
111  if (sc && sc == mShadowScene)
112  {
113  for (NodeBox* nb : mAdditionalBoxes)
114  {
115  NodeDragShadow* nds = mShadows.value(nb);
116  if (nds)
117  {
118  sc->removeItem(nds);
119  mShadows.remove(nb);
120  delete nds;
121  }
122  }
123  }
124  mAdditionalBoxes.clear();
125  }
126  mWantSwap = wantSwap;
127  }
128 
129  void DragController::addShadow(const NodeBox* nb)
130  {
131  NodeDragShadow* nds = new NodeDragShadow;
132  nds->setVisualCue(dragCue());
133  nds->start(nb->item()->pos(), nb->item()->boundingRect().size());
134  mShadowScene = mGraphWidget->getContext()->getLayouter()->scene();
135  if (mShadowScene)
136  {
137  mShadowScene->setDragController(this);
138  mShadowScene->addItem(nds);
139  mShadows.insert(nb,nds);
140  }
141  else
142  delete nds;
143  }
144 
145  void DragController::enterDrag(bool wantSwap)
146  {
147  if (!mDragNodeBox) return;
148  setSwapIntent(wantSwap);
149  mCurrentGridpos = mDragNodeBox->gridPosition();
150  mDropAllowed = false;
151  addShadow(mDragNodeBox);
152  for (NodeBox* nb : mAdditionalBoxes)
153  addShadow(nb);
154  }
155 
156  void DragController::move(const QPoint& eventPos, bool wantSwap, const QPoint& gridPos)
157  {
158  Q_UNUSED(eventPos);
159  if (!mDragNodeBox || (wantSwap == mWantSwap && gridPos == mCurrentGridpos)) return;
160 
161  setSwapIntent(wantSwap);
162  mCurrentGridpos = gridPos;
163  mDropAllowed = isDropAllowed();
164 
165  QPoint delta = mCurrentGridpos - mDragNodeBox->gridPosition();
166  for (auto it = mShadows.constBegin(); it != mShadows.constEnd(); ++it)
167  {
168  it.value()->setVisualCue(dragCue());
169  QPoint p = it.key()->gridPosition() + delta;
170  float x = mGraphWidget->getContext()->getLayouter()->gridXposition(p.x());
171  float y = mGraphWidget->getContext()->getLayouter()->gridYposition(p.y());
172  it.value()->setPos(QPointF(x,y));
173  }
174  }
175 
176  bool DragController::hasDragged(const QPoint &eventPos)
177  {
178  if (!mDragNodeBox) return false;
179  return (eventPos - mMousedownPosition).manhattanLength() >= QApplication::startDragDistance();
180  }
181 
183  {
184  if (!mDragNodeBox) return false;
185  if (mDragNodeBox->gridPosition() == mCurrentGridpos) return false;
186  const NodeBoxes& boxes = mGraphWidget->getContext()->getLayouter()->boxes();
187 
188  if (mWantSwap)
189  {
190  return (boxes.boxForPoint(mCurrentGridpos) != nullptr);
191  }
192 
193  QList<QPoint> pointsToCheck;
194  QSet<QPoint> freedPositions;
195  pointsToCheck.append(mCurrentGridpos);
196  freedPositions.insert(mDragNodeBox->gridPosition());
197 
198  QPoint delta = mCurrentGridpos - mDragNodeBox->gridPosition();
199  for (const NodeBox* nb : mAdditionalBoxes)
200  {
201  pointsToCheck.append(nb->gridPosition() + delta);
202  freedPositions.insert(nb->gridPosition());
203  }
204 
205  for (const QPoint& p : pointsToCheck)
206  {
207  if (freedPositions.contains(p)) continue;
208  if (boxes.boxForPoint(p) != nullptr) return false;
209  }
210  return true;
211  }
212 
214  {
215  GridPlacement* retval = mGraphWidget->getContext()->getLayouter()->gridPlacementFactory();
216  retval->operator[](mDragNodeBox->getNode()) = mCurrentGridpos;
217  if (mWantSwap)
218  {
219  Node targetNode = mGraphWidget->getContext()->getLayouter()->nodeAtPosition(mCurrentGridpos);
220  if (!targetNode.isNull())
221  retval->operator[](targetNode) = mDragNodeBox->gridPosition();
222  return retval;
223  }
224  if (!mAdditionalBoxes.isEmpty())
225  {
226  QPoint delta = mCurrentGridpos - mDragNodeBox->gridPosition();
227  for (const NodeBox* nb : mAdditionalBoxes)
228  {
229  retval->operator[](nb->getNode()) = nb->gridPosition() + delta;
230  }
231  }
232  return retval;
233  }
234 }
GridPlacement * finalGridPlacement() const
void move(const QPoint &eventPos, bool wantSwap, const QPoint &gridPos)
bool hasDragged(const QPoint &eventPos)
void set(GraphicsNode *drgItem, const QPoint &eventPos)
bool isDropAllowed() const
DragController(GraphWidget *gw, QObject *parent=nullptr)
NodeDragShadow::DragCue dragCue() const
void enterDrag(bool wantSwap)
void clearShadows(GraphicsScene *sc)
GraphLayouter * getLayouter() const
Base class for all specific layouters.
qreal gridXposition(int ix) const
qreal gridYposition(int iy) const
Node nodeAtPosition(const QPoint &p) const
GridPlacement * gridPlacementFactory() const
GraphicsScene * scene() const
const NodeBoxes & boxes() const
Wraps a GraphContext and a GraphGraphicsView.
Definition: graph_widget.h:55
GraphContext * getContext() const
ItemType itemType() const
Abstract base class for nodes (e.g. gates, modules)
Definition: graphics_node.h:41
Container for a GraphGraphicsView containing gates, nets, and modules.
void setDragController(DragController *dc)
The NodeBox class represents a node placed at a grid position within a hal view.
Definition: node_box.h:50
GraphicsNode * item() const
item getter for graphics item object
Definition: node_box.h:124
Node getNode() const
getNode getter for node information
Definition: node_box.h:75
QPoint gridPosition() const
Definition: node_box.h:105
The NodeBoxes class owns all NodeBox'es from hal view.
Definition: node_box.h:150
NodeBox * boxForNode(const Node &n) const
boxForNode find NodeBox by node
Definition: node_box.h:200
NodeBox * boxForPoint(const QPoint &p) const
boxForPoint find NodeBox by grid position
Definition: node_box.h:191
An item that is drawn when a node is dragged through the scene.
void setVisualCue(const DragCue cue)
The Node class object represents a module or a gate.
Definition: gui_def.h:61
@ Module
Definition: gui_def.h:63
@ Gate
Definition: gui_def.h:63
bool isNull() const
isNull test for null-Node object typically returned from functions
Definition: gui_def.h:83
const QSet< u32 > & selectedGates() const
const QSet< u32 > & selectedModules() const
SelectionRelay * gSelectionRelay
Definition: plugin_gui.cpp:83
quint32 u32
void addItem(QGraphicsItem *item)
void removeItem(QGraphicsItem *item)
void append(const T &value)
int x() const const
int y() const const
bool contains(const T &value) const const
QSet::iterator insert(const T &value)