0.3.1
[qanava.git] / src / qanNodeItem.cpp
blobfe6a808d56a046b89486974ffab060e831b9df2f
1 /*
2 Qanava - Graph drawing library for QT
3 Copyright (C) 2006 Benoit AUTHEMAN
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //-----------------------------------------------------------------------------
21 // This file is a part of the Qanava software.
23 // \file qanNodeItem.cpp
24 // \author Benoit Autheman (benoit@libqanava.org)
25 // \date 2004 October 13
26 //-----------------------------------------------------------------------------
29 // Qanava headers
30 #include "./qanNodeItem.h"
33 // QT headers
34 #include <QFont>
35 #include <QPainter>
36 #include <QPixmap>
37 #include <QGraphicsTextItem>
38 #include <QGraphicsPixmapItem>
39 #include <QGraphicsScene>
40 #include <QStyleOptionGraphicsItem>
41 #include <QGraphicsTextItem>
44 namespace qan { // ::qan
47 /* Node Constructor/Destructor *///--------------------------------------------
48 /*!
49 The following style options are supported:
50 <ul>
51 <li> <b>'backcolor':</b> Background color, when there is no background image defined.
52 <li> <b>'bordercolor':</b> Color of the item border.
53 <li> <b>'backimage':</b> Background image (scaled to fit the item size).
54 <li> <b>'maximumwidth':</b> Maximum width of the item, content is cropped to fit this with limit.
55 <li> <b>'maximumheight':</b> Maximum height of the item, content is cropped to fit this height limit.
56 <li> <b>'fontsize':</b> Base size for the font used to display the item label.
57 <li> <b>'icon':</b> Display an icon centered in the left of the item.
58 <li> <b>'hasshadow':</b> Set this value to false to supress the node shadow.
59 </ul>
61 An item with an empty style is transparent with no background nor border.
63 \param origin Uper left corner of the rectangular item.
64 \param label Text label to be displayed in the node text area (can be multi line HTML tagged text).
65 \param style Advanced style to pass optionnal display parameters.
67 NodeItem::NodeItem( Node& node, Style::Manager& styleManager, Style& style,
68 QGraphicsItem* parent, QGraphicsScene* scene,
69 QPointF origin, const QString& label ) :
70 AbstractNodeItem( node, styleManager, &style ),
71 QGraphicsRectItem( parent, scene ),
72 _dimension( 170.0, 45.0 ),
73 _label( label ),
74 _shadowColor( ),
75 _shadowOffset( 1.0 ),
76 _labelItem( 0 )
78 setRect( origin.x( ), origin.y( ), _dimension.x( ), _dimension.y( ) );
79 setFlag( QGraphicsItem::ItemIsMovable );
80 setZValue( 2.0 );
82 updateItem( );
85 NodeItem::~NodeItem( )
87 foreach ( EdgeItem* edge, _edges )
88 edge->disconnectEdge( );
91 void NodeItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget )
94 /*QBrush b;
95 b.setStyle( Qt::SolidPattern );
96 b.setColor( _shadowColor );
97 painter->setBrush( b );
99 QPen p( Qt::red );
100 painter->setPen( p );
102 QRectF r = boundingRect( );
103 painter->drawRoundRect( r );*/
106 // Draw background pixmap
107 if ( !_backPixmap.isNull( ) )
109 QBrush b = brush( );
110 b.setStyle( Qt::NoBrush );
111 setBrush( b ); // Remove default backcolor (usefull if we have an alpha channel)
113 QRectF backRect = boundingRect( );
114 QRectF srcRect( 0., 0., _backPixmap.width( ), _backPixmap.height( ) );
115 painter->drawPixmap( backRect, _backPixmap, srcRect );
118 QGraphicsRectItem::paint( painter, option, widget );
120 // Draw the item icon centered vertically
121 if ( !_icon.isNull( ) )
123 QPointF iconPos( 1.0, 1.0 );
124 if ( _dimension.y( ) > _icon.height( ) )
125 iconPos.ry( ) += ( _dimension.y( ) - _icon.height( ) ) / 2.;
126 painter->drawPixmap( iconPos, _icon );
130 void NodeItem::updateItem( )
132 if ( getStyle( ) == 0 )
133 return;
135 QColor backColor = QColor( 255, 255, 255 );
137 if ( !getStyle( )->has( "nobackground" ) )
139 QBrush b = brush( );
140 b.setStyle( Qt::NoBrush );
141 setBrush( b );
144 if ( getStyle( )->has( "backcolor" ) )
146 backColor = getStyle( )->getColor( "backcolor" );
147 QBrush b = brush( );
148 b.setStyle( Qt::SolidPattern );
149 b.setColor( backColor );
150 setBrush( b );
152 else
153 setBrush( QColor( 255, 255, 255 ) );
155 QColor borderColor = QColor( 0, 0, 0 );
156 if ( getStyle( )->has( "bordercolor" ) )
158 borderColor = getStyle( )->getColor( "bordercolor" );
159 setPen( borderColor );
162 // Compute the _label size once it is laid out as rich text html
163 if ( _label.size( ) > 0 )
165 QFont font;
166 if ( getStyle( )->has( "fontsize" ) )
168 int fontSize = getStyle( )->getT< int >( "fontsize" );
169 font.setPointSize( fontSize > 0 ? fontSize : 11 );
171 _labelItem = new QGraphicsTextItem( this, scene( ) );
172 _labelItem->setHtml( _label );
173 _labelItem->setFont( font );
177 // Updating node geometry and content
179 // Check for item maximum dimension (if specified)
180 double maximumWidth = -1.;
181 double maximumHeight = -1.;
182 if ( getStyle( )->has( "maximumwidth" ) )
183 maximumWidth = getStyle( )->getT< int >( "maximumwidth" );
184 if ( getStyle( )->has( "maximumheight" ) )
185 maximumHeight = getStyle( )->getT< int >( "maximumheight" );
187 // Compute the item height according to the _label size once formatted and displayed
188 if ( _labelItem != 0 /*_labelDocument != 0 && _labelLayout != 0*/ )
190 // Do not resize the item larger than its maximum allowed size
191 double textLayoutWidth = _labelItem->boundingRect( ).width( ) + 2.;
192 double textLayoutHeight = _labelItem->boundingRect( ).height( ) + 2.;
193 _dimension.setX( maximumWidth > 0. ? std::min( textLayoutWidth, maximumWidth ) : textLayoutWidth );
194 _dimension.setY( maximumHeight > 0. ? std::min( textLayoutHeight, maximumHeight ) : textLayoutHeight );
197 // Resize the whole item to fit (eventual) icon size
198 if ( getStyle( )->has( "icon" ) )
200 QImage icon = getStyleManager( ).getImage( getStyle( )->getImageName( "icon" ) );
201 if ( !icon.isNull( ) )
202 _icon = QPixmap::fromImage( icon, Qt::OrderedAlphaDither );
205 if ( !_icon.isNull( ) )
207 double w = _dimension.x( ) + _icon.width( ) + 1.;
208 _dimension.setX( maximumWidth != -1 ? std::min( w, maximumWidth ) : w );
210 double h = std::max( _icon.height( ) + 1., _dimension.y( ) );
211 _dimension.setY( maximumHeight != -1 ? std::min( h, maximumHeight ) : h );
213 double textMarginX = 2;
214 double textMarginY = 0;
215 double textX = textMarginX;
216 if ( !_icon.isNull( ) ) // Draw the text right of the icon
217 textX += _icon.width( );
218 double textY = textMarginY;
220 QRectF clipRect( textX, textY, _dimension.x( ) - textMarginX, _dimension.y( ) - textMarginY );
221 _labelItem->translate( textX, textY );
224 // Update the background image
225 if ( getStyle( )->has( "backimage" ) )
227 QImage backImage = getStyleManager( ).getImage( getStyle( )->getImageName( "backimage" ) );
228 if ( !backImage.isNull( ) )
230 QImage image = backImage.scaled( ( int )_dimension.x( ) - 1, ( int )_dimension.y( ) - 1 ); // -1 for the border
231 if ( !image.isNull( ) )
232 _backPixmap = QPixmap::fromImage( image, Qt::OrderedAlphaDither );
236 if ( getStyle( )->has( "hasshadow" ) && getStyle( )->getT< bool >( "hasshadow" ) )
238 if ( getStyle( )->has( "shadowcolor" ) )
239 _shadowColor = getStyle( )->getColor( "shadowcolor" );
240 else
241 _shadowColor = QColor( 105, 105, 105 );
242 if ( getStyle( )->has( "shadowoffset" ) )
243 _shadowOffset = getStyle( )->getT< int >( "shadowoffset" );
244 else
245 _shadowOffset = 3.;
247 // Setup the two rectangle sub items who are modelling shadow
248 // Two rect are needed, because a unique subitem modelling shadow cannot have
249 // a zvalue inferior to the rect item modelling the node (BTW, it may be faster
250 // to render two small rect than a big one)
251 QGraphicsRectItem* shadowBottom = new QGraphicsRectItem( this, scene( ) );
252 shadowBottom->setRect( _shadowOffset, _dimension.y( ) + 1.0, _dimension.x( ), _shadowOffset );
253 QBrush b;
254 b.setStyle( Qt::SolidPattern );
255 b.setColor( _shadowColor );
256 shadowBottom->setBrush( b );
257 shadowBottom->setPen( QPen( _shadowColor ) );
259 QGraphicsRectItem* shadowRight = new QGraphicsRectItem( this, scene( ) );
260 shadowRight->setRect( _dimension.x( ) + 1.0, _shadowOffset, _shadowOffset, _dimension.y( ) + 1.0 );
261 shadowRight->setBrush( b );
262 shadowRight->setPen( QPen( _shadowColor ) );
264 else
265 _shadowColor = QColor( ); // Invalid color since there is no shadow
267 // Set item geometry
268 setRect( 0., 0., _dimension.x( ), _dimension.y( ) );
269 getNode( ).setDimension( _dimension.x( ), _dimension.y( ) );
273 QVariant NodeItem::itemChange( GraphicsItemChange change, const QVariant& value )
275 if ( change == ItemPositionChange || change == ItemMatrixChange )
276 updateEdges( );
277 return QGraphicsItem::itemChange( change, value );
279 //-----------------------------------------------------------------------------
281 } // ::qan