1 // Copyright (C) 2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #include "DependencyTree_Arrow.h"
22 #include "DependencyTree_Object.h"
25 #include <SUIT_Session.h>
26 #include <SUIT_ResourceMgr.h>
33 const qreal arrowSize = 20;
35 DependencyTree_Arrow::DependencyTree_Arrow( DependencyTree_Object* theStartItem,
36 DependencyTree_Object* theEndItem,
37 QGraphicsItem* parent, QGraphicsScene* scene )
38 :QGraphicsLineItem( parent, scene ),
40 myStartItem( theStartItem ),
41 myEndItem( theEndItem )
43 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
45 myColor = resMgr->colorValue( "Geometry", "dependency_tree_arrow_color", QColor( 0, 0, 130 ) );
46 myHighlightColor = resMgr->colorValue( "Geometry", "dependency_tree_highlight_arrow_color", QColor( 0, 0, 255 ) );
47 mySelectColor = resMgr->colorValue( "Geometry", "dependency_tree_select_arrow_color", QColor( 255, 0, 0 ) );
49 myStartItem = theStartItem;
50 myEndItem = theEndItem;
52 myLine = QLineF( myStartItem->pos(), myEndItem->pos() );
53 myArrowHead = createArrowHead( myStartItem->pos(), myEndItem->pos() );
54 myReverseArrowHead = createArrowHead( myEndItem->pos(), myStartItem->pos() );
56 mySelfDependencyArrow = QRectF();
58 setPen( QPen( myColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
61 setFlag( QGraphicsItem::ItemIsSelectable, true );
65 DependencyTree_Arrow::~DependencyTree_Arrow()
69 //=================================================================================
70 // function : boundingRect()
71 // purpose : return the outer bounds of the item as a rectangle.
72 // QGraphicsView uses this to determine whether the item requires redrawing
73 //=================================================================================
74 QRectF DependencyTree_Arrow::boundingRect() const
78 if( myStartItem == myEndItem ) {
79 extra = arrowSize / 2.0 + 2.0;
80 boundingRect = mySelfDependencyArrow;
83 extra = ( pen().width() + 20 ) / 2.0;
84 boundingRect = QRectF( myLine.p1(), QSizeF( myLine.p2().x() - myLine.p1().x(),
85 myLine.p2().y() - myLine.p1().y() ) );
87 return boundingRect.normalized().adjusted( -extra, -extra, extra, extra );
90 //=================================================================================
92 // purpose : return the shape of this item to define an area of preselection
93 //=================================================================================
94 QPainterPath DependencyTree_Arrow::shape() const
98 if( myStartItem == myEndItem ) {
100 QPolygonF aPolygonBigger( mySelfDependencyArrow.normalized()
101 .adjusted( -extra, -extra, extra, extra ) );
102 QPolygonF aPolygonSmaller( mySelfDependencyArrow.normalized()
103 .adjusted( extra, extra, -extra, -extra ) );
104 path.addPolygon( aPolygonBigger.subtracted( aPolygonSmaller ) );
105 path.addPolygon(myArrowHead);
108 QPolygonF aShapePolygon;
109 QPolygon anArrowHead = myArrowHead.toPolygon();
110 QPolygon anReverseArrowHead = myReverseArrowHead.toPolygon();
111 aShapePolygon << anArrowHead.point(1) << anArrowHead.point(0) << anArrowHead.point(2) <<
112 anReverseArrowHead.point(1) << anReverseArrowHead.point(0) << anReverseArrowHead.point(2);
113 path.addPolygon( aShapePolygon );
118 //=================================================================================
119 // function : setColor()
120 // purpose : set default color for arrow
121 //=================================================================================
122 void DependencyTree_Arrow::setColor( const QColor& theColor )
127 //=================================================================================
128 // function : setHighlightColor()
129 // purpose : set color for highlighted arrow
130 //=================================================================================
131 void DependencyTree_Arrow::setHighlightColor( const QColor& theColor )
133 myHighlightColor = theColor;
136 //=================================================================================
137 // function : setSelectColor()
138 // purpose : set color for selected arrow
139 //=================================================================================
140 void DependencyTree_Arrow::setSelectColor( const QColor& theColor )
142 mySelectColor = theColor;
145 //=================================================================================
146 // function : getStartItem()
147 // purpose : get start item of arrow
148 //=================================================================================
149 DependencyTree_Object* DependencyTree_Arrow::getStartItem() const
154 //=================================================================================
155 // function : getEndItem()
156 // purpose : get end item of arrow
157 //=================================================================================
158 DependencyTree_Object* DependencyTree_Arrow::getEndItem() const
163 //=================================================================================
164 // function : setIsBiLink()
165 // purpose : set true if current arrow is bi-directional link, else set false
166 //=================================================================================
167 void DependencyTree_Arrow::setIsBiLink( bool theIsBiLink )
169 myIsBiLink = theIsBiLink;
172 //=================================================================================
173 // function : paint()
174 // purpose : paint the contents of an item in local coordinates (called by QGraphicsView)
175 //=================================================================================
176 void DependencyTree_Arrow::paint( QPainter* painter, const QStyleOptionGraphicsItem*, QWidget* )
179 painter->setBrush( mySelectColor );
180 painter->setPen( QPen( mySelectColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
182 else if( isUnderMouse() ) {
183 painter->setBrush( myHighlightColor );
184 painter->setPen( QPen( myHighlightColor, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
187 painter->setBrush( myColor );
188 painter->setPen( QPen( myColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
191 if( myStartItem == myEndItem ) {
193 QPointF p1( myStartItem->pos().x() - myStartItem->boundingRect().width()/2,
194 myStartItem->pos().y() );
195 QPointF p2( p1.x() - lineSize + myStartItem->boundingRect().height()/2, p1.y() );
196 QPointF p3( p2.x(), p2.y() - lineSize );
197 QPointF p4( p3.x() + lineSize, p3.y() );
198 QPointF p5( p4.x(), p4.y() + lineSize - myStartItem->boundingRect().height()/2 );
199 mySelfDependencyArrow = QRectF( p3.x(), p3.y(), lineSize, lineSize );
200 myArrowHead = createArrowHead( p4, p5, false );
201 QVector<QPointF> pointVector;
202 pointVector << p1 << p2 << p2 << p3 << p3 << p4 << p4 << p5;
204 painter->drawLines( pointVector);
205 painter->drawPolygon(myArrowHead);
208 if (myStartItem->collidesWithItem(myEndItem))
211 myArrowHead = createArrowHead( myStartItem->pos(), myEndItem->pos() );
212 myReverseArrowHead = createArrowHead( myEndItem->pos(), myStartItem->pos() );
214 painter->drawLine( myLine );
215 painter->drawPolygon( myArrowHead );
217 painter->drawPolygon( myReverseArrowHead );
221 //=================================================================================
222 // function : createArrowHead()
223 // purpose : create a head of arrow from start point to end point
224 //=================================================================================
225 QPolygonF DependencyTree_Arrow::createArrowHead( QPointF theStartPoint, QPointF theEndPoint,
229 QLineF centerLine( theStartPoint, theEndPoint );
230 QPolygonF endPolygon = QPolygonF( myEndItem->boundingRect() );
231 QPointF p1 = endPolygon.first() + theEndPoint;
233 QPointF intersectPoint;
235 for( int i = 1; i < endPolygon.count(); ++i ) {
236 p2 = endPolygon.at(i) + theEndPoint;
237 polyLine = QLineF( p1, p2 );
238 QLineF::IntersectType intersectType = polyLine.intersect( centerLine, &intersectPoint );
239 if( intersectType == QLineF::BoundedIntersection )
243 myLine = QLineF( intersectPoint, theStartPoint );
246 myLine = QLineF( theEndPoint, theStartPoint );
248 double angle = acos(myLine.dx() / myLine.length());
249 if( myLine.dy() >= 0 )
250 angle = ( M_PI * 2 ) - angle;
252 QPointF arrowP1 = myLine.p1() + QPointF( sin( angle + M_PI / 3 ) * arrowSize,
253 cos( angle + M_PI / 3 ) * arrowSize );
254 QPointF arrowP2 = myLine.p1() + QPointF( sin( angle + M_PI - M_PI / 3 ) * arrowSize,
255 cos( angle + M_PI - M_PI / 3 ) * arrowSize );
257 QPolygonF anArrowHead;
258 anArrowHead << myLine.p1() << arrowP1 << arrowP2;