1 // Copyright (C) 2012-2019 The VPaint Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution
3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 #include "AnimatedCycleWidget.h"
18 #include "VectorAnimationComplex/InbetweenCell.h"
19 #include "VectorAnimationComplex/KeyCell.h"
20 #include "VectorAnimationComplex/InbetweenEdge.h"
21 #include "VectorAnimationComplex/InbetweenFace.h"
22 #include "VectorAnimationComplex/KeyEdge.h"
23 #include "VectorAnimationComplex/VAC.h"
24
25 #include <QVBoxLayout>
26 #include <QVector2D>
27 #include <QGraphicsSceneMouseEvent>
28 #include <QMouseEvent>
29 #include <QPushButton>
30
31 #include "Global.h"
32 #include "MainWindow.h"
33 #include "Scene.h"
34
35 #include "Random.h"
36
37 #include <QtDebug>
38
39 namespace
40 {
41 const double ARROW_LENGTH = 30;
42 }
43
GraphicsNodeItem(AnimatedCycleNode * node,AnimatedCycleWidget * widget)44 GraphicsNodeItem::GraphicsNodeItem(AnimatedCycleNode * node, AnimatedCycleWidget * widget) :
45 node_(node),
46 widget_(widget),
47 isMoved_(false)
48 {
49 // Set path and color
50 if(node_->cell()->toKeyVertex())
51 {
52 setBrush(QColor(255,170,170));
53 width_ = 20;
54 height_ = 20;
55 }
56 else if(node_->cell()->toKeyEdge())
57 {
58 setBrush(QColor(170,204,255));
59 width_ = 60;
60 height_ = 20;
61 }
62 else if(node_->cell()->toInbetweenVertex())
63 {
64 setBrush(QColor(255,218,218));
65 width_ = 20;
66 height_ = 60;
67 }
68 else if(node_->cell()->toInbetweenEdge())
69 {
70 setBrush(QColor(235,243,255));
71 width_ = 60;
72 height_ = 60;
73 }
74 setPath_();
75
76 // Create text label as a child item
77 text_ = new QGraphicsTextItem(QString(), this);
78 text_->setFont(QFont("arial",7));
79 updateText();
80
81 // Moake item movable
82 setFlag(ItemIsMovable, true);
83
84 // Observe cell
85 observe(node_->cell());
86 }
87
~GraphicsNodeItem()88 GraphicsNodeItem::~GraphicsNodeItem()
89 {
90 // Unobserve cell
91 unobserve(node_->cell());
92 }
93
observedCellDeleted(Cell *)94 void GraphicsNodeItem::observedCellDeleted(Cell *)
95 {
96 // Commit suicide properly
97 widget_->deleteItem(this);
98 }
99
updateText()100 void GraphicsNodeItem::updateText()
101 {
102 QString string;
103 string.setNum(node_->cell()->id());
104 if(node_->cell()->toEdgeCell())
105 (node_->side()) ? (string += "+") : (string += "-");
106
107 text_->setPlainText(string);
108
109 double textWidth = text_->boundingRect().width();
110 double textHeight = text_->boundingRect().height();
111 text_->setPos(-0.5*textWidth,-0.5*textHeight);
112 }
113
setPath_()114 void GraphicsNodeItem::setPath_()
115 {
116 QPainterPath path;
117 EdgeCell * edge = node()->cell()->toEdgeCell();
118 if(edge && edge->isClosed())
119 {
120 path.moveTo(-0.5*width_-10,-0.5*height_); // A
121 path.lineTo(0.5*width_-10,-0.5*height_); // B
122 path.cubicTo(0.5*width_-5,-0.5*height_,0.5*width_,-0.5*height_+5,0.5*width_,-0.5*height_+10); // C
123 path.lineTo(0.5*width_,0.5*height_-10); // D
124 path.cubicTo(0.5*width_,0.5*height_-5,0.5*width_-5,0.5*height_,0.5*width_-10,0.5*height_); //E
125 path.lineTo(-0.5*width_-10,0.5*height_); // F
126 path.cubicTo(-0.5*width_-5,0.5*height_,-0.5*width_,0.5*height_-5,-0.5*width_,0.5*height_-10); // G
127 path.lineTo(-0.5*width_,-0.5*height_+10); // H
128 path.cubicTo(-0.5*width_,-0.5*height_+5,-0.5*width_-5,-0.5*height_,-0.5*width_-10,-0.5*height_); // I
129 }
130 else
131 {
132 path.addRoundedRect(-0.5*width_,-0.5*height_,width_,height_,10,10);
133 }
134 setPath(path);
135 }
136
width() const137 double GraphicsNodeItem::width() const
138 {
139 return width_;
140 }
141
height() const142 double GraphicsNodeItem::height() const
143 {
144 return height_;
145 }
146
setWidth(double w)147 void GraphicsNodeItem::setWidth(double w)
148 {
149 width_ = w;
150 setPath_();
151 }
152
setHeight(int i)153 void GraphicsNodeItem::setHeight(int i)
154 {
155 height_ = i*60 + (i-1)*(20+2*ARROW_LENGTH);
156 setPath_();
157 }
158
setFixedY(double y)159 void GraphicsNodeItem::setFixedY(double y)
160 {
161 y_ = y;
162 setY(y_);
163 }
164
mousePressEvent(QGraphicsSceneMouseEvent * event)165 void GraphicsNodeItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
166 {
167 if(event->button() == Qt::LeftButton)
168 {
169 isMoved_ = true;
170 QGraphicsPathItem::mousePressEvent(event);
171 }
172 else if(event->button() == Qt::RightButton)
173 {
174 //qDebug() << "press" << node()->cell()->id();
175 }
176 else
177 {
178 QGraphicsPathItem::mousePressEvent(event);
179 }
180 }
181
mouseMoveEvent(QGraphicsSceneMouseEvent * event)182 void GraphicsNodeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
183 {
184 QGraphicsPathItem::mouseMoveEvent(event);
185 double eps = 1.0e-4;
186 double delta = y_ - y();
187 if( delta < -eps || eps < delta )
188 setY(y_);
189 }
190
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)191 void GraphicsNodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
192 {
193 if(event->button() == Qt::LeftButton)
194 {
195 isMoved_ = false;
196 QGraphicsPathItem::mouseReleaseEvent(event);
197 }
198 else if (event->button() == Qt::RightButton)
199 {
200 //QGraphicsItem * item = scene()->itemAt(event->pos(), view)
201 //qDebug() << "release" << node()->cell()->id();
202 }
203 else
204 {
205 QGraphicsPathItem::mouseReleaseEvent(event);
206 }
207 }
208
isMoved() const209 bool GraphicsNodeItem::isMoved() const
210 {
211 return isMoved_;
212 }
213
node() const214 AnimatedCycleNode * GraphicsNodeItem::node() const
215 {
216 return node_;
217 }
218
next()219 GraphicsNodeItem * GraphicsNodeItem::next()
220 {
221 return widget_->next(this);
222 }
previous()223 GraphicsNodeItem * GraphicsNodeItem::previous()
224 {
225 return widget_->previous(this);
226 }
before()227 GraphicsNodeItem * GraphicsNodeItem::before()
228 {
229 return widget_->before(this);
230 }
after()231 GraphicsNodeItem * GraphicsNodeItem::after()
232 {
233 return widget_->after(this);
234 }
235
236
237
GraphicsArrowItem()238 GraphicsArrowItem::GraphicsArrowItem() :
239 QGraphicsPolygonItem()
240 {
241 setPen(QPen(Qt::black));
242 setBrush(QBrush(Qt::black));
243 }
244
setEndPoints(const QPointF & p1,const QPointF & p2)245 void GraphicsArrowItem::setEndPoints(const QPointF & p1, const QPointF & p2)
246 {
247 QPolygonF polygon;
248 QVector2D u(p2-p1);
249 u.normalize();
250 QVector2D v(-u.y(),u.x());
251
252 double lineHalfWidth = 1;
253 double arrowHalfWidth = 5;
254 double arrowLength = 5;
255
256 polygon << p1 + (lineHalfWidth*v).toPointF()
257 << p2 + (lineHalfWidth*v - arrowLength*u).toPointF()
258 << p2 + (arrowHalfWidth*v - arrowLength*u).toPointF()
259 << p2
260 << p2 + (-arrowHalfWidth*v - arrowLength*u).toPointF()
261 << p2 + (-lineHalfWidth*v - arrowLength*u).toPointF()
262 << p1 + (-lineHalfWidth*v).toPointF();
263
264 setPolygon(polygon);
265 }
266
267
268
269
270
271
AnimatedCycleGraphicsView(QGraphicsScene * scene,AnimatedCycleWidget * animatedCycleWidget)272 AnimatedCycleGraphicsView::AnimatedCycleGraphicsView(QGraphicsScene * scene, AnimatedCycleWidget * animatedCycleWidget) :
273 QGraphicsView(scene),
274 animatedCycleWidget_(animatedCycleWidget)
275 {
276 //setTransformationAnchor(AnchorUnderMouse);
277 }
278
paintEvent(QPaintEvent * event)279 void AnimatedCycleGraphicsView::paintEvent(QPaintEvent * event)
280 {
281 QGraphicsView::paintEvent(event);
282 }
283
wheelEvent(QWheelEvent * event)284 void AnimatedCycleGraphicsView::wheelEvent(QWheelEvent *event)
285 {
286 setTransformationAnchor(AnchorUnderMouse);
287 double ratio = 1.0 / pow( 0.8f, (double) event->delta() / (double) 120.0f);
288 scale(ratio, ratio);
289 }
290
nodeItemAt(const QPoint & pos)291 GraphicsNodeItem * AnimatedCycleGraphicsView::nodeItemAt(const QPoint & pos)
292 {
293 GraphicsNodeItem * res = 0;
294
295 QGraphicsItem * item = itemAt(pos);
296 GraphicsNodeItem * nodeItem = qgraphicsitem_cast<GraphicsNodeItem*>(item);
297 GraphicsArrowItem * arrowItem = qgraphicsitem_cast<GraphicsArrowItem*>(item);
298 QGraphicsTextItem * textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item);
299
300 if(nodeItem)
301 {
302 res = nodeItem;
303 }
304 else if(arrowItem)
305 {
306 res = 0;
307 }
308 else if(textItem)
309 {
310 item = item->parentItem();
311 nodeItem = qgraphicsitem_cast<GraphicsNodeItem*>(item);
312 if(nodeItem)
313 {
314 res = nodeItem;
315 }
316 else
317 {
318 res = 0;
319 }
320 }
321
322 return res;
323 }
324
arrowItemAt(const QPoint & pos)325 GraphicsArrowItem * AnimatedCycleGraphicsView::arrowItemAt(const QPoint & pos)
326 {
327 return qgraphicsitem_cast<GraphicsArrowItem*>(itemAt(pos));
328 }
329
mousePressEvent(QMouseEvent * event)330 void AnimatedCycleGraphicsView::mousePressEvent(QMouseEvent * event)
331 {
332 if(event->button() == Qt::MidButton)
333 {
334 setTransformationAnchor(AnchorUnderMouse);
335 setInteractive(false);
336 setDragMode(ScrollHandDrag);
337 QMouseEvent fake(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers());
338 QGraphicsView::mousePressEvent(&fake);
339 }
340 else if(event->button() == Qt::LeftButton && global()->keyboardModifiers().testFlag(Qt::AltModifier))
341 {
342 GraphicsArrowItem * arrowItem = arrowItemAt(event->pos());
343 GraphicsNodeItem * nodeItem = nodeItemAt(event->pos());
344 if(arrowItem)
345 {
346 animatedCycleWidget_->deleteArrow(arrowItem);
347 animatedCycleWidget_->save();
348 }
349 else if(nodeItem)
350 {
351 animatedCycleWidget_->deleteItem(nodeItem);
352 animatedCycleWidget_->save();
353 }
354 }
355 else if(event->button() == Qt::LeftButton && global()->keyboardModifiers().testFlag(Qt::ControlModifier))
356 {
357 GraphicsNodeItem * nodeItem = nodeItemAt(event->pos());
358 if(nodeItem)
359 {
360 nodeItem->node()->setSide(!nodeItem->node()->side());
361 nodeItem->updateText();
362 animatedCycleWidget_->save();
363 }
364 }
365 else if(event->button() == Qt::RightButton)
366 {
367 itemAtPress_ = nodeItemAt(event->pos());
368 }
369 else
370 {
371 QGraphicsView::mousePressEvent(event);
372 }
373 }
374
mouseMoveEvent(QMouseEvent * event)375 void AnimatedCycleGraphicsView::mouseMoveEvent(QMouseEvent * event)
376 {
377 QGraphicsView::mouseMoveEvent(event);
378 }
379
mouseReleaseEvent(QMouseEvent * event)380 void AnimatedCycleGraphicsView::mouseReleaseEvent(QMouseEvent * event)
381 {
382 if(event->button() == Qt::MidButton)
383 {
384 QMouseEvent fake(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers());
385 QGraphicsView::mouseReleaseEvent(&fake);
386 setDragMode(NoDrag);
387 setInteractive(true);
388 }
389 else if(event->button() == Qt::RightButton)
390 {
391 GraphicsNodeItem * item = nodeItemAt(event->pos());
392 if(item && itemAtPress_)
393 {
394 InbetweenCell * pressedInbetween = itemAtPress_->node()->cell()->toInbetweenCell();
395 InbetweenCell * releasedInbetween = item->node()->cell()->toInbetweenCell();
396
397 KeyCell * pressedKey = itemAtPress_->node()->cell()->toKeyCell();
398 KeyCell * releasedKey = item->node()->cell()->toKeyCell();
399
400 const int PREVIOUS = 0;
401 const int NEXT = 1;
402 const int BEFORE = 2;
403 const int AFTER = 3;
404 const int PREVIOUS_OR_NEXT = 4;
405 int arrowType = PREVIOUS;
406
407 // Determine arrow type
408 if( (pressedKey && releasedKey) || (pressedInbetween && releasedInbetween) )
409 {
410 arrowType = PREVIOUS_OR_NEXT;
411 }
412 else if (pressedKey && releasedInbetween)
413 {
414 int t = pressedKey->time().frame();
415 int t1 = releasedInbetween->beforeTime().frame();
416 int t2 = releasedInbetween->afterTime().frame();
417
418 if(t <= t1)
419 arrowType = AFTER;
420 else if(t >= t2)
421 arrowType = BEFORE;
422 else
423 arrowType = PREVIOUS_OR_NEXT;
424 }
425 else
426 {
427 assert(pressedInbetween && releasedKey);
428
429 int t = releasedKey->time().frame();
430 int t1 = pressedInbetween->beforeTime().frame();
431 int t2 = pressedInbetween->afterTime().frame();
432
433 if(t <= t1)
434 arrowType = BEFORE;
435 else if(t >= t2)
436 arrowType = AFTER;
437 else
438 arrowType = PREVIOUS_OR_NEXT;
439 }
440
441 // set pointer
442 if(arrowType == PREVIOUS_OR_NEXT)
443 {
444 if(global()->keyboardModifiers().testFlag(Qt::ControlModifier))
445 arrowType = PREVIOUS;
446 else
447 arrowType = NEXT;
448 }
449 if(arrowType == PREVIOUS)
450 animatedCycleWidget_->setPrevious(itemAtPress_,item);
451 else if(arrowType == NEXT)
452 animatedCycleWidget_->setNext(itemAtPress_,item);
453 else if(arrowType == BEFORE)
454 animatedCycleWidget_->setBefore(itemAtPress_,item);
455 else if(arrowType == AFTER)
456 animatedCycleWidget_->setAfter(itemAtPress_,item);
457
458
459 animatedCycleWidget_->save();
460 }
461 }
462 else
463 {
464 QGraphicsView::mouseReleaseEvent(event);
465 }
466 }
467
AnimatedCycleWidget(QWidget * parent)468 AnimatedCycleWidget::AnimatedCycleWidget(QWidget *parent) :
469 QWidget(parent),
470 isReadOnly_(true),
471 inbetweenFace_(0)
472 {
473 scene_ = new QGraphicsScene();
474 view_ = new AnimatedCycleGraphicsView(scene_, this);
475 view_->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
476
477 QPushButton * addSelectedCellsButton = new QPushButton("add selected cells");
478 QPushButton * saveButton = new QPushButton("save");
479 QPushButton * loadButton = new QPushButton("load");
480 connect(addSelectedCellsButton, SIGNAL(clicked()), this, SLOT(addSelectedCells()));
481 connect(saveButton, SIGNAL(clicked()), this, SLOT(save()));
482 connect(loadButton, SIGNAL(clicked()), this, SLOT(load()));
483 editorButtons_ = new QHBoxLayout();
484 editorButtons_->addWidget(addSelectedCellsButton);
485 //editorButtons_->addWidget(saveButton);
486 editorButtons_->addWidget(loadButton);
487
488
489 QVBoxLayout * layout = new QVBoxLayout();
490 layout->addWidget(view_);
491 layout->addLayout(editorButtons_);
492 setLayout(layout);
493
494 timer_.setInterval(16);
495 connect(&timer_, SIGNAL(timeout()), this, SLOT(animate()));
496 }
497
498
createNodeAndItem(Cell * cell)499 void AnimatedCycleWidget::createNodeAndItem(Cell * cell)
500 {
501 AnimatedCycleNode * node = new AnimatedCycleNode(cell);
502 if(!animatedCycle_.first())
503 {
504 animatedCycle_.setFirst(node);
505
506 // Caution: the line below would cause a crash, as node ownership is transfered
507 // to the temp object AnimatedCycle(node) which is destroyed after the copy occured.
508 //animatedCycle_ = AnimatedCycle(node);
509 }
510
511 createItem(node);
512 }
513
createItem(AnimatedCycleNode * node)514 void AnimatedCycleWidget::createItem(AnimatedCycleNode * node)
515 {
516 GraphicsNodeItem * item = new GraphicsNodeItem(node, this);
517 scene_->addItem(item);
518 nodeToItem_[node] = item;
519 }
520
addSelectedCells()521 void AnimatedCycleWidget::addSelectedCells()
522 {
523 VectorAnimationComplex::VAC * vac = global()->mainWindow()->scene()->activeVAC();
524 if (vac)
525 {
526 CellSet selectedCells = vac->selectedCells();
527
528 foreach(Cell * cell, selectedCells)
529 createNodeAndItem(cell);
530
531 computeItemHeightAndY();
532
533 save();
534 }
535 }
536
537
start()538 void AnimatedCycleWidget::start()
539 {
540 timer_.start();
541 }
542
stop()543 void AnimatedCycleWidget::stop()
544 {
545 timer_.stop();
546 }
547
~AnimatedCycleWidget()548 AnimatedCycleWidget::~AnimatedCycleWidget()
549 {
550 clearAnimatedCycle(); // important: cells must be unobserved
551 delete scene_;
552 }
553
setReadOnly(bool b)554 void AnimatedCycleWidget::setReadOnly(bool b)
555 {
556 isReadOnly_ = b;
557 }
558
isReadOnly() const559 bool AnimatedCycleWidget::isReadOnly() const
560 {
561 return isReadOnly_;
562 }
563
clearScene()564 void AnimatedCycleWidget::clearScene()
565 {
566 // Delete all items
567 view_->setScene(0);
568 delete scene_;
569
570 // Create new empty scene
571 scene_ = new QGraphicsScene();
572
573 // Set scene properties
574 view_->setTransformationAnchor(QGraphicsView::NoAnchor);
575 view_->setScene(scene_);
576
577 // Clear maps and sets
578 nodeToItem_.clear();
579 nodeToItem_[0] = 0;
580 itemToNextArrow_.clear();
581 itemToPreviousArrow_.clear();
582 itemToNextArrowBorder_.clear();
583 itemToPreviousArrowBorder_.clear();
584 itemToAfterArrow_.clear();
585 itemToBeforeArrow_.clear();
586 }
587
observedCellDeleted(Cell *)588 void AnimatedCycleWidget::observedCellDeleted(Cell *)
589 {
590 clearAnimatedCycle();
591 }
592
clearAnimatedCycle()593 void AnimatedCycleWidget::clearAnimatedCycle()
594 {
595 // Break connection between widget and vac
596 if(inbetweenFace_)
597 {
598 unobserve(inbetweenFace_);
599 inbetweenFace_ = 0;
600 }
601
602 // Clear scene
603 clearScene();
604 }
605
setAnimatedCycle(InbetweenFace * inbetweenFace,int indexCycle)606 void AnimatedCycleWidget::setAnimatedCycle(InbetweenFace * inbetweenFace, int indexCycle)
607 {
608 // Clear
609 clearAnimatedCycle();
610
611 // Set new animated cycle
612 if(inbetweenFace && indexCycle >= 0 && indexCycle < inbetweenFace->numAnimatedCycles())
613 {
614 inbetweenFace_ = inbetweenFace;
615 indexCycle_ = indexCycle;
616
617 observe(inbetweenFace_);
618
619 load();
620 }
621 }
622
setAnimatedCycle(const AnimatedCycle & animatedCycle)623 void AnimatedCycleWidget::setAnimatedCycle(const AnimatedCycle & animatedCycle)
624 {
625 // Clear scene
626 clearAnimatedCycle();
627
628 // Set new animated cycle
629 animatedCycle_ = animatedCycle;
630
631 // Create items
632 computeSceneFromAnimatedCycle();
633 }
634
load()635 void AnimatedCycleWidget::load()
636 {
637 clearScene();
638
639 if(inbetweenFace_ && indexCycle_ >= 0 && indexCycle_ < inbetweenFace_->numAnimatedCycles())
640 {
641 animatedCycle_ = inbetweenFace_->animatedCycle(indexCycle_);
642 computeSceneFromAnimatedCycle();
643 start();
644 }
645 }
646
save()647 void AnimatedCycleWidget::save()
648 {
649 if(inbetweenFace_ && indexCycle_ >= 0 && indexCycle_ < inbetweenFace_->numAnimatedCycles())
650 {
651 inbetweenFace_->setCycle(indexCycle_,animatedCycle_);
652
653 VectorAnimationComplex::VAC * vac = inbetweenFace_->vac();
654 emit vac->needUpdatePicking();
655 emit vac->changed();
656 emit vac->checkpoint();
657 }
658 }
659
getAnimatedCycle() const660 AnimatedCycle AnimatedCycleWidget::getAnimatedCycle() const
661 {
662 return animatedCycle_;
663 }
664
665
setBefore(GraphicsNodeItem * item,GraphicsNodeItem * itemBefore)666 void AnimatedCycleWidget::setBefore(GraphicsNodeItem * item, GraphicsNodeItem * itemBefore)
667 {
668 // Delete existing arrow
669 if(itemToBeforeArrow_.contains(item))
670 {
671 delete itemToBeforeArrow_[item];
672 itemToBeforeArrow_.remove(item);
673 }
674
675 // Set node pointer value
676 item->node()->setBefore(itemBefore->node());
677
678 // Create arrow
679 GraphicsArrowItem * arrow = new GraphicsArrowItem();
680 scene_->addItem(arrow);
681 itemToBeforeArrow_[item] = arrow;
682 }
683
setAfter(GraphicsNodeItem * item,GraphicsNodeItem * itemAfter)684 void AnimatedCycleWidget::setAfter(GraphicsNodeItem * item, GraphicsNodeItem * itemAfter)
685 {
686 // Delete existing arrow
687 if(itemToAfterArrow_.contains(item))
688 {
689 delete itemToAfterArrow_[item];
690 itemToAfterArrow_.remove(item);
691 }
692
693 // Set node pointer value
694 item->node()->setAfter(itemAfter->node());
695
696 // Create arrow
697 GraphicsArrowItem * arrow = new GraphicsArrowItem();
698 scene_->addItem(arrow);
699 itemToAfterArrow_[item] = arrow;
700 }
701
setPrevious(GraphicsNodeItem * item,GraphicsNodeItem * itemPrevious)702 void AnimatedCycleWidget::setPrevious(GraphicsNodeItem * item, GraphicsNodeItem * itemPrevious)
703 {
704 // Delete existing arrow
705 if(itemToPreviousArrow_.contains(item))
706 {
707 delete itemToPreviousArrow_[item];
708 itemToPreviousArrow_.remove(item);
709 }
710 if(itemToPreviousArrowBorder_.contains(item))
711 {
712 delete itemToPreviousArrowBorder_[item];
713 itemToPreviousArrowBorder_.remove(item);
714 }
715
716 // Set node pointer value
717 item->node()->setPrevious(itemPrevious->node());
718
719 // Create arrow
720 GraphicsArrowItem * arrow = new GraphicsArrowItem();
721 scene_->addItem(arrow);
722 Qt::KeyboardModifiers modifiers = global()->keyboardModifiers();
723 if(modifiers.testFlag(Qt::AltModifier))
724 itemToPreviousArrowBorder_[item] = arrow;
725 else
726 itemToPreviousArrow_[item] = arrow;
727 }
728
setNext(GraphicsNodeItem * item,GraphicsNodeItem * itemNext)729 void AnimatedCycleWidget::setNext(GraphicsNodeItem * item, GraphicsNodeItem * itemNext)
730 {
731 // Delete existing arrow
732 if(itemToNextArrow_.contains(item))
733 {
734 delete itemToNextArrow_[item];
735 itemToNextArrow_.remove(item);
736 }
737 if(itemToNextArrowBorder_.contains(item))
738 {
739 delete itemToNextArrowBorder_[item];
740 itemToNextArrowBorder_.remove(item);
741 }
742
743 // Set node pointer value
744 item->node()->setNext(itemNext->node());
745
746 // Create arrow
747 GraphicsArrowItem * arrow = new GraphicsArrowItem();
748 scene_->addItem(arrow);
749 Qt::KeyboardModifiers modifiers = global()->keyboardModifiers();
750 if(modifiers.testFlag(Qt::AltModifier))
751 itemToNextArrowBorder_[item] = arrow;
752 else
753 itemToNextArrow_[item] = arrow;
754 }
755
deleteArrow(GraphicsArrowItem * arrowItem)756 void AnimatedCycleWidget::deleteArrow(GraphicsArrowItem * arrowItem)
757 {
758 typedef QMap<GraphicsNodeItem*, GraphicsArrowItem*> Map;
759 typedef Map::iterator Iterator;
760 typedef Map* MapPtr;
761
762 const int NUM_MAPS = 6;
763 MapPtr maps[NUM_MAPS] = { &itemToNextArrow_ ,
764 &itemToPreviousArrow_ ,
765 &itemToNextArrowBorder_ ,
766 &itemToPreviousArrowBorder_ ,
767 &itemToAfterArrow_ ,
768 &itemToBeforeArrow_ };
769
770 for(int i=0; i<NUM_MAPS; ++i)
771 {
772 for(Iterator it=maps[i]->begin(); it!=maps[i]->end(); ++it)
773 {
774 if(it.value() == arrowItem)
775 {
776 if(i==0 || i==2)
777 it.key()->node()->setNext(0);
778 else if(i==1 || i==3)
779 it.key()->node()->setPrevious(0);
780 else if(i==4)
781 it.key()->node()->setAfter(0);
782 else if(i==5)
783 it.key()->node()->setBefore(0);
784
785 maps[i]->erase(it);
786 delete arrowItem;
787 return;
788 }
789 }
790 }
791 }
792
deleteItem(GraphicsNodeItem * item)793 void AnimatedCycleWidget::deleteItem(GraphicsNodeItem * item)
794 {
795 // Get node corresponding to item
796 AnimatedCycleNode * node = item->node();
797
798 // Get arrows starting or ending at item
799 QSet<GraphicsArrowItem*> arrowItems;
800 typedef QMap<GraphicsNodeItem*, GraphicsArrowItem*> Map;
801 typedef Map::iterator Iterator;
802 typedef Map* MapPtr;
803 const int NUM_MAPS = 6;
804 MapPtr maps[NUM_MAPS] = { &itemToNextArrow_ ,
805 &itemToPreviousArrow_ ,
806 &itemToNextArrowBorder_ ,
807 &itemToPreviousArrowBorder_ ,
808 &itemToAfterArrow_ ,
809 &itemToBeforeArrow_ };
810 for(int i=0; i<NUM_MAPS; ++i)
811 {
812 for(Iterator it=maps[i]->begin(); it!=maps[i]->end(); ++it)
813 {
814 // Get start-arrow-end
815 AnimatedCycleNode * startNode = it.key()->node();
816 GraphicsArrowItem * arrowItem = it.value();
817 AnimatedCycleNode * endNode = 0;
818 if(i==0 || i==2)
819 endNode = startNode->next();
820 else if(i==1 || i==3)
821 endNode = startNode->previous();
822 else if(i==4)
823 endNode = startNode->after();
824 else if(i==5)
825 endNode = startNode->before();
826
827 // Determine if arrow should be deleted
828 if(startNode == node || endNode == node)
829 arrowItems << arrowItem;
830 }
831 }
832
833 // Delete arrows starting or ending at item
834 foreach(GraphicsArrowItem * arrowItem, arrowItems)
835 deleteArrow(arrowItem);
836
837 // Delete node and item
838 scene_->removeItem(item);
839 nodeToItem_.remove(node);
840 delete item; // must be first, since it calls node->cell()
841 delete node;
842
843 // Update "first" node of animated cycle
844 if(animatedCycle_.first() == node)
845 {
846 QMap<AnimatedCycleNode*, GraphicsNodeItem*>::iterator it = nodeToItem_.begin();
847
848 if(it == nodeToItem_.end())
849 {
850 animatedCycle_.setFirst(0);
851 }
852 else
853 {
854 AnimatedCycleNode * first = it.key();
855 if(!first)
856 {
857 ++it;
858 if(it != nodeToItem_.end())
859 first = it.key();
860 }
861
862 while(first && first->before())
863 first = first->before();
864
865 animatedCycle_.setFirst(first);
866 }
867 }
868 }
869
computeSceneFromAnimatedCycle()870 void AnimatedCycleWidget::computeSceneFromAnimatedCycle()
871 {
872 // Clear scene
873 clearScene();
874
875 // Get start nodes
876 QSet<AnimatedCycleNode*> startNodes;
877 AnimatedCycleNode * startNode = animatedCycle_.first();
878 while(startNode)
879 {
880 startNodes << startNode;
881 startNode = startNode->after();
882 }
883
884 // Create items
885 foreach(AnimatedCycleNode * node, animatedCycle_.nodes())
886 {
887 GraphicsNodeItem * item = new GraphicsNodeItem(node, this);
888 scene_->addItem(item);
889 nodeToItem_[node] = item;
890 }
891
892 // Set item height and Y
893 computeItemHeightAndY();
894
895 // Create arrows
896 foreach(AnimatedCycleNode * node, animatedCycle_.nodes())
897 {
898 GraphicsNodeItem * item = nodeToItem_[node];
899
900 if(node->next()) // can be false if cycle is invalid
901 {
902 GraphicsArrowItem * arrow = new GraphicsArrowItem();
903 scene_->addItem(arrow);
904 if(!startNodes.contains(node->next()))
905 itemToNextArrow_[item] = arrow;
906 else
907 itemToNextArrowBorder_[item] = arrow;
908 }
909
910 if(node->previous()) // can be false if cycle is invalid
911 {
912 GraphicsArrowItem * arrow = new GraphicsArrowItem();
913 scene_->addItem(arrow);
914 if(!startNodes.contains(node))
915 itemToPreviousArrow_[item] = arrow;
916 else
917 itemToPreviousArrowBorder_[item] = arrow;
918 }
919
920 if(node->after())
921 {
922 GraphicsArrowItem * arrow = new GraphicsArrowItem();
923 scene_->addItem(arrow);
924 itemToAfterArrow_[item] = arrow;
925 }
926
927 if(node->before())
928 {
929 GraphicsArrowItem * arrow = new GraphicsArrowItem();
930 scene_->addItem(arrow);
931 itemToBeforeArrow_[item] = arrow;
932 }
933 }
934 }
935
computeItemHeightAndY()936 void AnimatedCycleWidget::computeItemHeightAndY()
937 {
938 typedef QMap<AnimatedCycleNode*, GraphicsNodeItem*>::iterator Iterator;
939
940 // Get key times
941 QSet<int> keyTimes;
942 for(Iterator it = nodeToItem_.begin(); it != nodeToItem_.end(); ++it)
943 {
944 AnimatedCycleNode * node = it.key();
945 if(!node)
946 continue;
947
948 Cell * cell = node->cell();
949 InbetweenCell * inbetweenCell = cell->toInbetweenCell();
950
951 if(inbetweenCell)
952 {
953 int tBefore = inbetweenCell->beforeTime().frame();
954 int tAfter = inbetweenCell->afterTime().frame();
955 keyTimes << tBefore << tAfter;
956 }
957 else
958 {
959 int t = cell->toKeyCell()->time().frame();
960 keyTimes << t;
961 }
962 }
963
964 // Sort key times and compute height and Y of items
965 QList<int> keyTimesSorted = keyTimes.toList();
966 qSort(keyTimesSorted);
967 for(Iterator it = nodeToItem_.begin(); it != nodeToItem_.end(); ++it)
968 {
969 AnimatedCycleNode * node = it.key();
970 if(!node)
971 continue;
972
973 GraphicsNodeItem * item = it.value();
974 Cell * cell = node->cell();
975 InbetweenCell * inbetweenCell = cell->toInbetweenCell();
976
977 if(inbetweenCell)
978 {
979 int tBefore = inbetweenCell->beforeTime().frame();
980 int tAfter = inbetweenCell->afterTime().frame();
981
982 int idBefore = 0;
983 int idAfter = 0;
984 for(int i=0; i<keyTimesSorted.size(); ++i)
985 {
986 if(keyTimesSorted[i]==tBefore)
987 idBefore = i;
988
989 if(keyTimesSorted[i]==tAfter)
990 idAfter = i;
991 }
992
993 item->setHeight(idAfter-idBefore);
994
995 double yBefore = idBefore * (80 + 2*ARROW_LENGTH);
996 double yAfter = idAfter * (80 + 2*ARROW_LENGTH);
997
998 item->setFixedY(0.5 * (yAfter + yBefore));
999 }
1000 else
1001 {
1002 int t = cell->toKeyCell()->time().frame();
1003
1004 int id = 0;
1005 for(int i=0; i<keyTimesSorted.size(); ++i)
1006 {
1007 if(keyTimesSorted[i]==t)
1008 id = i;
1009 }
1010
1011 item->setFixedY(id * (80 + 2*ARROW_LENGTH));
1012 }
1013 }
1014 }
1015
next(GraphicsNodeItem * item)1016 GraphicsNodeItem * AnimatedCycleWidget::next(GraphicsNodeItem * item)
1017 {
1018 return nodeToItem_[item->node()->next()];
1019 }
previous(GraphicsNodeItem * item)1020 GraphicsNodeItem * AnimatedCycleWidget::previous(GraphicsNodeItem * item)
1021 {
1022 return nodeToItem_[item->node()->previous()];
1023 }
before(GraphicsNodeItem * item)1024 GraphicsNodeItem * AnimatedCycleWidget::before(GraphicsNodeItem * item)
1025 {
1026 return nodeToItem_[item->node()->before()];
1027 }
after(GraphicsNodeItem * item)1028 GraphicsNodeItem * AnimatedCycleWidget::after(GraphicsNodeItem * item)
1029 {
1030 return nodeToItem_[item->node()->after()];
1031 }
1032
mousePressEvent(QMouseEvent * event)1033 void AnimatedCycleWidget::mousePressEvent(QMouseEvent * event)
1034 {
1035 QWidget::mousePressEvent(event);
1036 }
1037
animate()1038 void AnimatedCycleWidget::animate()
1039 {
1040 // Compute delta between current and target
1041 QMap<GraphicsNodeItem*, double> deltaX;
1042 QMap<GraphicsNodeItem*, int> deltaXNum;
1043 QMap<GraphicsNodeItem*, double> deltaMinX;
1044 QMap<GraphicsNodeItem*, double> deltaMaxX;
1045
1046 // Get all items
1047 QSet<GraphicsNodeItem*> items;
1048 foreach(QGraphicsItem * i, scene_->items())
1049 {
1050 GraphicsNodeItem * item = qgraphicsitem_cast<GraphicsNodeItem *>(i);
1051 if(item)
1052 items << item;
1053 }
1054
1055 // Initialize values
1056 foreach(GraphicsNodeItem * item, items)
1057 {
1058 deltaX[item] = 0;
1059 deltaXNum[item] = 0;
1060 deltaMinX[item] = -10000;// std::numeric_limits<double>::lowest();
1061 deltaMaxX[item] = 10000;// std::numeric_limits<double>::max();
1062 }
1063
1064 // Next arrow contribution
1065 QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*> it(itemToNextArrow_);
1066 while(it.hasNext())
1067 {
1068 it.next();
1069
1070 GraphicsNodeItem * item = it.key();
1071 GraphicsNodeItem * nextItem = item->next();
1072
1073 if(!item || !nextItem)
1074 continue;
1075
1076 double start = item->pos().x() + 0.5*item->width();
1077 double end = nextItem->pos().x() - 0.5*nextItem->width();
1078 double vec = end - start;
1079 double delta = ARROW_LENGTH - vec;
1080
1081 //deltaX[nextItem] += delta;
1082 //deltaXNum[nextItem] += 1;
1083 deltaMinX[nextItem] = std::max(delta,deltaMinX[nextItem]);
1084
1085 //deltaX[item] += -delta;
1086 //deltaXNum[item] += 1;
1087 deltaMaxX[item] = std::min(-delta,deltaMaxX[item]);
1088 }
1089
1090 // Previous arrow contribution
1091 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToPreviousArrow_);
1092 while(it.hasNext())
1093 {
1094 it.next();
1095
1096 GraphicsNodeItem * nextItem = it.key();
1097 GraphicsNodeItem * item = nextItem->previous();
1098
1099 if(!item || !nextItem)
1100 continue;
1101
1102 double start = item->pos().x() + 0.5*item->width();
1103 double end = nextItem->pos().x() - 0.5*nextItem->width();
1104 double vec = end - start;
1105 double delta = ARROW_LENGTH - vec;
1106
1107 //deltaX[nextItem] += delta;
1108 //deltaXNum[nextItem] += 1;
1109 deltaMinX[nextItem] = std::max(delta,deltaMinX[nextItem]);
1110
1111 //deltaX[item] += -delta;
1112 //deltaXNum[item] += 1;
1113 deltaMaxX[item] = std::min(-delta,deltaMaxX[item]);
1114 }
1115
1116
1117 // Increase width of inbetween edges
1118 foreach(GraphicsNodeItem * item, items)
1119 {
1120 InbetweenEdge * inbetweenEdge = item->node()->cell()->toInbetweenEdge();
1121 if(inbetweenEdge)
1122 {
1123 // get after items
1124 double lastRight = 0;
1125 double widthAfterItems = 0;
1126 GraphicsNodeItem * firstAfterItem = item->after();
1127 GraphicsNodeItem * afterItem = firstAfterItem;
1128 if(afterItem)
1129 {
1130 lastRight = afterItem->x() + 0.5*afterItem->width();
1131 widthAfterItems += afterItem->width();
1132 afterItem = afterItem->next();
1133 }
1134 while(afterItem && afterItem != firstAfterItem && afterItem->before() == item)
1135 {
1136 double right = afterItem->x() + 0.5*afterItem->width();
1137 if(right-lastRight < 0)
1138 widthAfterItems += afterItem->width();
1139 else
1140 widthAfterItems += right-lastRight;
1141 lastRight = right;
1142 afterItem = afterItem->next();
1143 }
1144
1145 // get before items
1146 double lastLeft = 0;
1147 double widthBeforeItems = 0;
1148 GraphicsNodeItem * firstBeforeItem = item->before();
1149 GraphicsNodeItem * beforeItem = firstBeforeItem;
1150 if(beforeItem)
1151 {
1152 lastLeft = beforeItem->x() - 0.5*beforeItem->width();
1153 widthBeforeItems += beforeItem->width();
1154 beforeItem = beforeItem->previous();
1155 }
1156 while(beforeItem && beforeItem != firstBeforeItem && beforeItem->after() == item)
1157 {
1158 double left = beforeItem->x() - 0.5*beforeItem->width();
1159 if(lastLeft-left < 0)
1160 widthBeforeItems += beforeItem->width();
1161 else
1162 widthBeforeItems += lastLeft-left;
1163 lastLeft = left;
1164 beforeItem = beforeItem->previous();
1165 }
1166
1167 // grow inbetween edge
1168 double widthBeforeAfter = std::max(widthBeforeItems,widthAfterItems);
1169 if(60 /*item->width()*/ < widthBeforeAfter)
1170 {
1171 item->setWidth(/*0.999 **/ widthBeforeAfter);
1172 }
1173 }
1174 }
1175
1176 // After arrow contribution
1177 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToAfterArrow_);
1178 while(it.hasNext())
1179 {
1180 it.next();
1181 GraphicsNodeItem * item = it.key();
1182
1183 // Idea: for inbetween cells, keep double arrows vertical
1184 if(item->node()->cell()->toInbetweenCell())
1185 {
1186 GraphicsNodeItem * afterItem = item->after();
1187 GraphicsNodeItem * beforeAfterItem = afterItem->before();
1188
1189 if(beforeAfterItem == item)
1190 {
1191 double delta = afterItem->pos().x()-0.5*afterItem->width() - (item->pos().x()-0.5*item->width());
1192 deltaX[item] += delta;
1193 deltaXNum[item] += 1;
1194 deltaX[afterItem] += -delta;
1195 deltaXNum[afterItem] += 1;
1196 }
1197 }
1198 }
1199
1200
1201 // Before arrow contribution
1202 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToBeforeArrow_);
1203 while(it.hasNext())
1204 {
1205 it.next();
1206 GraphicsNodeItem * item = it.key();
1207
1208 // Idea: for inbetween cells, keep double arrows vertical
1209 if(item->node()->cell()->toInbetweenCell())
1210 {
1211 GraphicsNodeItem * beforeItem = item->before();
1212 GraphicsNodeItem * afterBeforeItem = beforeItem->after();
1213 if(afterBeforeItem == item)
1214 {
1215 double delta = beforeItem->pos().x()+0.5*beforeItem->width() - (item->pos().x()+0.5*item->width());
1216 deltaX[item] += delta;
1217 deltaXNum[item] += 1;
1218 deltaX[beforeItem] += -delta;
1219 deltaXNum[beforeItem] += 1;
1220 }
1221 }
1222 }
1223
1224 // Compute average of delta
1225 foreach(GraphicsNodeItem * item, items)
1226 {
1227 if(deltaMinX[item] > deltaMaxX[item])
1228 {
1229 deltaX[item] = 0.5 * (deltaMinX[item] + deltaMaxX[item]);
1230 }
1231 else
1232 {
1233 if(deltaXNum[item] > 0)
1234 deltaX[item] /= deltaXNum[item];
1235
1236 deltaX[item] = std::max( deltaX[item] , deltaMinX[item] );
1237 deltaX[item] = std::min( deltaX[item] , deltaMaxX[item] );
1238 }
1239 }
1240
1241 // Move nodes
1242 //double ratio = 0.99;
1243 QMapIterator<GraphicsNodeItem*, double> it3(deltaX);
1244 while(it3.hasNext())
1245 {
1246 it3.next();
1247
1248 GraphicsNodeItem * item = it3.key();
1249 double delta = it3.value();
1250 double ratio = 0.8;//Random::random(0.8,0.95);
1251 if(!item->isMoved())
1252 item->moveBy(ratio*delta, 0);
1253 }
1254
1255 // update arrows
1256 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToNextArrow_);
1257 while(it.hasNext())
1258 {
1259 it.next();
1260
1261 GraphicsNodeItem * item = it.key();
1262 GraphicsNodeItem * nextItem = item->next();
1263 GraphicsArrowItem * nextArrow = it.value();
1264
1265 double y1 = item->pos().y();
1266 if(!nextItem->node()->cell()->toInbetweenEdge())
1267 y1 = nextItem->pos().y();
1268 double y2 = y1;
1269 double y1min = item->y() - 0.5*item->height()+10;
1270 double y1max = item->y() + 0.5*item->height()-10;
1271 double y2min = nextItem->y() - 0.5*nextItem->height()+10;
1272 double y2max = nextItem->y() + 0.5*nextItem->height()-10;
1273 if(y1 < y1min)
1274 y1 = y1min;
1275 if(y1 > y1max)
1276 y1 = y1max;
1277 if(y2 < y2min)
1278 y2 = y2min;
1279 if(y2 > y2max)
1280 y2 = y2max;
1281
1282 QPointF startVec(item->x()+0.5*item->width(),y1);
1283 QPointF endVec(nextItem->x()-0.5*nextItem->width(),y2);
1284
1285 nextArrow->setEndPoints(startVec,endVec);
1286 }
1287 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToPreviousArrow_);
1288 while(it.hasNext())
1289 {
1290 it.next();
1291
1292 GraphicsNodeItem * item = it.key();
1293 GraphicsNodeItem * previousItem = item->previous();
1294 GraphicsArrowItem * previousArrow = it.value();
1295
1296 double y1 = item->pos().y();
1297 if(!previousItem->node()->cell()->toInbetweenEdge())
1298 y1 = previousItem->pos().y();
1299 double y2 = y1;
1300 double y1min = item->y() - 0.5*item->height()+10;
1301 double y1max = item->y() + 0.5*item->height()-10;
1302 double y2min = previousItem->y() - 0.5*previousItem->height()+10;
1303 double y2max = previousItem->y() + 0.5*previousItem->height()-10;
1304 if(y1 < y1min)
1305 y1 = y1min;
1306 if(y1 > y1max)
1307 y1 = y1max;
1308 if(y2 < y2min)
1309 y2 = y2min;
1310 if(y2 > y2max)
1311 y2 = y2max;
1312
1313 QPointF startVec(item->x()-0.5*item->width(),y1);
1314 QPointF endVec(previousItem->x()+0.5*previousItem->width(),y2);
1315
1316 previousArrow->setEndPoints(startVec,endVec);
1317 }
1318 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToNextArrowBorder_);
1319 while(it.hasNext())
1320 {
1321 it.next();
1322
1323 GraphicsNodeItem * item = it.key();
1324 GraphicsNodeItem * nextItem = item->next();
1325 GraphicsArrowItem * nextArrow = it.value();
1326
1327 double y1 = item->pos().y();
1328 if(!nextItem->node()->cell()->toInbetweenEdge())
1329 y1 = nextItem->pos().y();
1330 double y2 = y1;
1331 double y1min = item->y() - 0.5*item->height()+10;
1332 double y1max = item->y() + 0.5*item->height()-10;
1333 double y2min = nextItem->y() - 0.5*nextItem->height()+10;
1334 double y2max = nextItem->y() + 0.5*nextItem->height()-10;
1335 if(y1 < y1min)
1336 y1 = y1min;
1337 if(y1 > y1max)
1338 y1 = y1max;
1339 if(y2 < y2min)
1340 y2 = y2min;
1341 if(y2 > y2max)
1342 y2 = y2max;
1343
1344 QPointF startVec(item->x()+0.5*item->width(),y1);
1345 QPointF endVec(item->x()+0.5*item->width()+ARROW_LENGTH,y2);
1346
1347 nextArrow->setEndPoints(startVec,endVec);
1348 }
1349 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToPreviousArrowBorder_);
1350 while(it.hasNext())
1351 {
1352 it.next();
1353
1354 GraphicsNodeItem * item = it.key();
1355 GraphicsNodeItem * previousItem = item->previous();
1356 GraphicsArrowItem * previousArrow = it.value();
1357
1358 double y1 = item->pos().y();
1359 if(!previousItem->node()->cell()->toInbetweenEdge())
1360 y1 = previousItem->pos().y();
1361 double y2 = y1;
1362 double y1min = item->y() - 0.5*item->height()+10;
1363 double y1max = item->y() + 0.5*item->height()-10;
1364 double y2min = previousItem->y() - 0.5*previousItem->height()+10;
1365 double y2max = previousItem->y() + 0.5*previousItem->height()-10;
1366 if(y1 < y1min)
1367 y1 = y1min;
1368 if(y1 > y1max)
1369 y1 = y1max;
1370 if(y2 < y2min)
1371 y2 = y2min;
1372 if(y2 > y2max)
1373 y2 = y2max;
1374
1375 QPointF startVec(item->x()-0.5*item->width(),y1);
1376 QPointF endVec(item->x()-0.5*item->width()-ARROW_LENGTH,y2);
1377
1378 previousArrow->setEndPoints(startVec,endVec);
1379 }
1380 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToAfterArrow_);
1381 while(it.hasNext())
1382 {
1383 it.next();
1384
1385 GraphicsNodeItem * item = it.key();
1386 GraphicsNodeItem * afterItem = item->after();
1387 GraphicsArrowItem * afterArrow = it.value();
1388
1389 double x1 = item->pos().x();
1390 if(!afterItem->node()->cell()->toInbetweenEdge())
1391 x1 = afterItem->pos().x();
1392 double x2 = x1;
1393 double x1min = item->x() - 0.5*item->width()+10;
1394 double x1max = item->x() + 0.5*item->width()-10;
1395 double x2min = afterItem->x() - 0.5*afterItem->width()+10;
1396 double x2max = afterItem->x() + 0.5*afterItem->width()-10;
1397 if(x1 < x1min)
1398 x1 = x1min;
1399 if(x1 > x1max)
1400 x1 = x1max;
1401 if(x2 < x2min)
1402 x2 = x2min;
1403 if(x2 > x2max)
1404 x2 = x2max;
1405
1406 QPointF startVec(x1,item->y()+0.5*item->height());
1407 QPointF endVec(x2, afterItem->y() - 0.5*afterItem->height());
1408
1409 afterArrow->setEndPoints(startVec,endVec);
1410 }
1411 it = QMapIterator<GraphicsNodeItem*, GraphicsArrowItem*>(itemToBeforeArrow_);
1412 while(it.hasNext())
1413 {
1414 it.next();
1415
1416 GraphicsNodeItem * item = it.key();
1417 GraphicsNodeItem * beforeItem = item->before();
1418 GraphicsArrowItem * beforeArrow = it.value();
1419
1420 double x1 = item->pos().x();
1421 if(!beforeItem->node()->cell()->toInbetweenEdge())
1422 x1 = beforeItem->pos().x();
1423 double x2 = x1;
1424 double x1min = item->x() - 0.5*item->width()+10;
1425 double x1max = item->x() + 0.5*item->width()-10;
1426 double x2min = beforeItem->x() - 0.5*beforeItem->width()+10;
1427 double x2max = beforeItem->x() + 0.5*beforeItem->width()-10;
1428 if(x1 < x1min)
1429 x1 = x1min;
1430 if(x1 > x1max)
1431 x1 = x1max;
1432 if(x2 < x2min)
1433 x2 = x2min;
1434 if(x2 > x2max)
1435 x2 = x2max;
1436
1437
1438 QPointF startVec(x1,item->y()-0.5*item->height());
1439 QPointF endVec(x2, beforeItem->y() + 0.5*beforeItem->height());
1440
1441 beforeArrow->setEndPoints(startVec,endVec);
1442 }
1443 }
1444
1445
1446