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