00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KDChartLayoutItems.h"
00024 #include "KDTextDocument.h"
00025 #include "KDChartAbstractArea.h"
00026 #include "KDChartAbstractDiagram.h"
00027 #include "KDChartBackgroundAttributes.h"
00028 #include "KDChartFrameAttributes.h"
00029 #include "KDChartPaintContext.h"
00030 #include "KDChartPainterSaver_p.h"
00031 #include "KDChartPrintingParameters.h"
00032 #include <QTextCursor>
00033 #include <QTextBlockFormat>
00034 #include <QTextDocumentFragment>
00035 #include <QAbstractTextDocumentLayout>
00036 #include <QLayout>
00037 #include <QPainter>
00038 #include <QDebug>
00039 #include <QCoreApplication>
00040 #include <QApplication>
00041 #include <QStringList>
00042 #include <QStyle>
00043
00044 #include <KDABLibFakes>
00045
00046 #include <math.h>
00047
00048 #define PI 3.141592653589793
00049
00050
00051
00052
00053
00062 void KDChart::AbstractLayoutItem::setParentWidget( QWidget* widget )
00063 {
00064 mParent = widget;
00065 }
00066
00067 void KDChart::AbstractLayoutItem::paintAll( QPainter& painter )
00068 {
00069 paint( &painter );
00070 }
00071
00075 void KDChart::AbstractLayoutItem::paintCtx( PaintContext* context )
00076 {
00077 if( context )
00078 paint( context->painter() );
00079 }
00080
00084 void KDChart::AbstractLayoutItem::sizeHintChanged()const
00085 {
00086
00087
00088 if( mParent ) {
00089 if ( mParent->layout() )
00090 mParent->layout()->invalidate();
00091 else
00092 QApplication::postEvent( mParent, new QEvent( QEvent::LayoutRequest ) );
00093 }
00094 }
00095
00096 KDChart::TextBubbleLayoutItem::TextBubbleLayoutItem( const QString& text,
00097 const KDChart::TextAttributes& attributes,
00098 const QObject* area,
00099 KDChartEnums::MeasureOrientation orientation,
00100 Qt::Alignment alignment )
00101 : AbstractLayoutItem( alignment ),
00102 m_text( new TextLayoutItem( text, attributes, area, orientation, alignment ) )
00103 {
00104 }
00105
00106 KDChart::TextBubbleLayoutItem::TextBubbleLayoutItem()
00107 : AbstractLayoutItem( Qt::AlignLeft ),
00108 m_text( new TextLayoutItem() )
00109 {
00110 }
00111
00112 KDChart::TextBubbleLayoutItem::~TextBubbleLayoutItem()
00113 {
00114 delete m_text;
00115 }
00116
00117 void KDChart::TextBubbleLayoutItem::setAutoReferenceArea( const QObject* area )
00118 {
00119 m_text->setAutoReferenceArea( area );
00120 }
00121
00122 const QObject* KDChart::TextBubbleLayoutItem::autoReferenceArea() const
00123 {
00124 return m_text->autoReferenceArea();
00125 }
00126
00127 void KDChart::TextBubbleLayoutItem::setText( const QString& text )
00128 {
00129 m_text->setText( text );
00130 }
00131
00132 QString KDChart::TextBubbleLayoutItem::text() const
00133 {
00134 return m_text->text();
00135 }
00136
00137 void KDChart::TextBubbleLayoutItem::setTextAttributes( const TextAttributes& a )
00138 {
00139 m_text->setTextAttributes( a );
00140 }
00141
00142 KDChart::TextAttributes KDChart::TextBubbleLayoutItem::textAttributes() const
00143 {
00144 return m_text->textAttributes();
00145 }
00146
00147 bool KDChart::TextBubbleLayoutItem::isEmpty() const
00148 {
00149 return m_text->isEmpty();
00150 }
00151
00152 Qt::Orientations KDChart::TextBubbleLayoutItem::expandingDirections() const
00153 {
00154 return m_text->expandingDirections();
00155 }
00156
00157 QSize KDChart::TextBubbleLayoutItem::maximumSize() const
00158 {
00159 const int border = borderWidth();
00160 return m_text->maximumSize() + QSize( 2 * border, 2 * border );
00161 }
00162
00163 QSize KDChart::TextBubbleLayoutItem::minimumSize() const
00164 {
00165 const int border = borderWidth();
00166 return m_text->minimumSize() + QSize( 2 * border, 2 * border );
00167 }
00168
00169 QSize KDChart::TextBubbleLayoutItem::sizeHint() const
00170 {
00171 const int border = borderWidth();
00172 return m_text->sizeHint() + QSize( 2 * border, 2 * border );
00173 }
00174
00175 void KDChart::TextBubbleLayoutItem::setGeometry( const QRect& r )
00176 {
00177 const int border = borderWidth();
00178 m_text->setGeometry( r.adjusted( border, border, -border, -border ) );
00179 }
00180
00181 QRect KDChart::TextBubbleLayoutItem::geometry() const
00182 {
00183 const int border = borderWidth();
00184 return m_text->geometry().adjusted( -border, -border, border, border );
00185 }
00186
00187 void KDChart::TextBubbleLayoutItem::paint( QPainter* painter )
00188 {
00189 const QPen oldPen = painter->pen();
00190 const QBrush oldBrush = painter->brush();
00191 painter->setPen( Qt::black );
00192 painter->setBrush( QColor( 255, 255, 220 ) );
00193 painter->drawRoundRect( geometry(), 10 );
00194 painter->setPen( oldPen );
00195 painter->setBrush( oldBrush );
00196 m_text->paint( painter );
00197 }
00198
00199 int KDChart::TextBubbleLayoutItem::borderWidth() const
00200 {
00201 return 1;
00202 }
00203
00204 KDChart::TextLayoutItem::TextLayoutItem( const QString& text,
00205 const KDChart::TextAttributes& attributes,
00206 const QObject* area,
00207 KDChartEnums::MeasureOrientation orientation,
00208 Qt::Alignment alignment )
00209 : AbstractLayoutItem( alignment )
00210 , mText( text )
00211 , mTextAlignment( alignment )
00212 , mAttributes( attributes )
00213 , mAutoReferenceArea( area )
00214 , mAutoReferenceOrientation( orientation )
00215 , cachedSizeHint()
00216 , cachedFontSize( 0.0 )
00217 , cachedFont( mAttributes.font() )
00218 {
00219 }
00220
00221 KDChart::TextLayoutItem::TextLayoutItem()
00222 : AbstractLayoutItem( Qt::AlignLeft )
00223 , mText()
00224 , mTextAlignment( Qt::AlignLeft )
00225 , mAttributes()
00226 , mAutoReferenceArea( 0 )
00227 , mAutoReferenceOrientation( KDChartEnums::MeasureOrientationHorizontal )
00228 , cachedSizeHint()
00229 , cachedFontSize( 0.0 )
00230 , cachedFont( mAttributes.font() )
00231 {
00232
00233 }
00234
00235 void KDChart::TextLayoutItem::setAutoReferenceArea( const QObject* area )
00236 {
00237 mAutoReferenceArea = area;
00238 cachedSizeHint = QSize();
00239 sizeHint();
00240 }
00241
00242 const QObject* KDChart::TextLayoutItem::autoReferenceArea() const
00243 {
00244 return mAutoReferenceArea;
00245 }
00246
00247 void KDChart::TextLayoutItem::setText(const QString & text)
00248 {
00249 mText = text;
00250 cachedSizeHint = QSize();
00251 sizeHint();
00252 if( mParent )
00253 mParent->update();
00254 }
00255
00256 QString KDChart::TextLayoutItem::text() const
00257 {
00258 return mText;
00259 }
00260
00261 void KDChart::TextLayoutItem::setTextAlignment( Qt::Alignment alignment)
00262 {
00263 if( mTextAlignment == alignment )
00264 return;
00265 mTextAlignment = alignment;
00266 if( mParent )
00267 mParent->update();
00268 }
00269
00270 Qt::Alignment KDChart::TextLayoutItem::textAlignment() const
00271 {
00272 return mTextAlignment;
00273 }
00274
00280 void KDChart::TextLayoutItem::setTextAttributes( const TextAttributes &a )
00281 {
00282 mAttributes = a;
00283 cachedFont = a.font();
00284 cachedSizeHint = QSize();
00285 sizeHint();
00286 if( mParent )
00287 mParent->update();
00288 }
00289
00295 KDChart::TextAttributes KDChart::TextLayoutItem::textAttributes() const
00296 {
00297 return mAttributes;
00298 }
00299
00300
00301 Qt::Orientations KDChart::TextLayoutItem::expandingDirections() const
00302 {
00303 return 0;
00304 }
00305
00306 QRect KDChart::TextLayoutItem::geometry() const
00307 {
00308 return mRect;
00309 }
00310
00311 bool KDChart::TextLayoutItem::isEmpty() const
00312 {
00313 return false;
00314 }
00315
00316 QSize KDChart::TextLayoutItem::maximumSize() const
00317 {
00318 return sizeHint();
00319 }
00320
00321 QSize KDChart::TextLayoutItem::minimumSize() const
00322 {
00323 return sizeHint();
00324 }
00325
00326 void KDChart::TextLayoutItem::setGeometry( const QRect& r )
00327 {
00328 mRect = r;
00329 }
00330
00331 QPointF rotatedPoint( const QPointF& pt, qreal rotation, const QPointF& center )
00332 {
00333 const qreal angle = PI * rotation / 180.0;
00334 const qreal cosAngle = cos( angle );
00335 const qreal sinAngle = -sin( angle );
00336 return QPointF(
00337 (cosAngle * ( pt.x() - center.x() ) + sinAngle * ( pt.y() - center.y() ) ),
00338 (cosAngle * ( pt.y() - center.y() ) - sinAngle * ( pt.x() - center.x() ) ) ) + center;
00339 }
00340
00341
00342 QRectF rotatedRect( const QRectF& oldRect, qreal angleInt, const QPointF& center )
00343 {
00344 const QRect rect( oldRect.translated( center ).toRect() );
00345 const qreal angle = PI * angleInt / 180.0;
00346 const qreal cosAngle = cos( angle );
00347 const qreal sinAngle = sin( angle );
00348 QMatrix rotationMatrix(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
00349 QPolygon rotPts;
00350 rotPts << rotationMatrix.map(rect.topLeft())
00351 << rotationMatrix.map(rect.topRight())
00352 << rotationMatrix.map(rect.bottomRight())
00353 << rotationMatrix.map(rect.bottomLeft());
00354
00355
00356
00357 return rotPts.boundingRect();
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 qreal KDChart::TextLayoutItem::fitFontSizeToGeometry() const
00394 {
00395 QFont f = realFont();
00396 const qreal origResult = f.pointSizeF();
00397 qreal result = origResult;
00398 const QSize mySize = geometry().size();
00399 if( mySize.isNull() )
00400 return result;
00401
00402 const QString t = text();
00403 QFontMetrics fm( f );
00404 while( true )
00405 {
00406 const QSizeF textSize = rotatedRect( fm.boundingRect( t ), mAttributes.rotation() ).normalized().size();
00407
00408 if( textSize.height() <= mySize.height() && textSize.width() <= mySize.width() )
00409 return result;
00410
00411 result -= 0.5;
00412 if( result <= 0.0 )
00413 return origResult;
00414 f.setPointSizeF( result );
00415 fm = QFontMetrics( f );
00416 }
00417 }
00418
00419 qreal KDChart::TextLayoutItem::realFontSize() const
00420 {
00421 return mAttributes.calculatedFontSize( mAutoReferenceArea, mAutoReferenceOrientation );
00422 }
00423
00424
00425 bool KDChart::TextLayoutItem::realFontWasRecalculated() const
00426 {
00427 const qreal fntSiz = realFontSize();
00428 const bool bRecalcDone =
00429 ( ( ! cachedSizeHint.isValid() ) || ( cachedFontSize != fntSiz ) );
00430
00431 if( bRecalcDone && fntSiz > 0.0 ){
00432 cachedFontSize = fntSiz;
00433 cachedFont.setPointSizeF( fntSiz );
00434 }
00435 return bRecalcDone;
00436 }
00437
00438
00439 QFont KDChart::TextLayoutItem::realFont() const
00440 {
00441 realFontWasRecalculated();
00442 return cachedFont;
00443 }
00444
00445 QPolygon KDChart::TextLayoutItem::rotatedCorners() const
00446 {
00447
00448 const qreal angle = mAttributes.rotation() * PI / 180.0;
00449 QSize size = unrotatedSizeHint();
00450
00451
00452 QPointF P1( size.height() * sin( angle ), 0 );
00453 QPointF P2( size.height() * sin( angle ) + size.width() * cos( angle ), size.width() * sin( angle ) );
00454 QPointF P3( size.width() * cos( angle ), size.width() * sin( angle ) + size.height() * cos( angle ) );
00455 QPointF P4( 0, size.height() * cos( angle ) );
00456
00457 QPolygon result;
00458 result << P1.toPoint() << P2.toPoint() << P3.toPoint() << P4.toPoint();
00459 return result;
00460 }
00461
00462 bool KDChart::TextLayoutItem::intersects( const TextLayoutItem& other, const QPointF& myPos, const QPointF& otherPos ) const
00463 {
00464 return intersects( other, myPos.toPoint(), otherPos.toPoint() );
00465 }
00466
00467 bool KDChart::TextLayoutItem::intersects( const TextLayoutItem& other, const QPoint& myPos, const QPoint& otherPos ) const
00468 {
00469 if ( mAttributes.rotation() != other.mAttributes.rotation() )
00470 {
00471
00472 QPolygon myPolygon( rotatedCorners() );
00473 QPolygon otherPolygon( other.rotatedCorners() );
00474
00475
00476 myPolygon.translate( myPos );
00477 otherPolygon.translate( otherPos );
00478
00479
00480 QRegion myRegion( myPolygon );
00481 QRegion otherRegion( otherPolygon );
00482
00483
00484 return ! myRegion.intersect( otherRegion ).isEmpty();
00485
00486 } else {
00487
00488 const qreal angle = mAttributes.rotation() * PI / 180.0;
00489
00490 const QSizeF mySize( unrotatedSizeHint() );
00491 const QSizeF otherSize( other.unrotatedSizeHint() );
00492
00493
00494 QPointF myP1( mySize.height() * sin( angle ), 0.0 );
00495
00496 QPointF otherP1 = QPointF( otherSize.height() * sin( angle ), 0.0 ) + otherPos - myPos;
00497
00498
00499 myP1 = QPointF( myP1.x() * cos( -angle ), myP1.x() * sin( -angle ) );
00500 qreal r = sqrt( otherP1.x() * otherP1.x() + otherP1.y() * otherP1.y() );
00501 otherP1 = QPointF( r * cos( -angle ), r * sin( -angle ) );
00502
00503
00504 const bool res = QRectF( myP1, mySize ).intersects( QRectF( otherP1, otherSize ) );
00505
00506 return res;
00507 }
00508 }
00509
00510 QSize KDChart::TextLayoutItem::sizeHint() const
00511 {
00512 QPoint dummy;
00513 return sizeHintAndRotatedCorners(dummy,dummy,dummy,dummy);
00514 }
00515
00516 QSize KDChart::TextLayoutItem::sizeHintAndRotatedCorners(
00517 QPoint& topLeftPt, QPoint& topRightPt, QPoint& bottomRightPt, QPoint& bottomLeftPt) const
00518 {
00519 if( realFontWasRecalculated() || mAttributes.rotation() )
00520 {
00521 const QSize newSizeHint( calcSizeHint( cachedFont,
00522 topLeftPt, topRightPt, bottomRightPt, bottomLeftPt ) );
00523 if( newSizeHint != cachedSizeHint ){
00524 cachedSizeHint = newSizeHint;
00525 sizeHintChanged();
00526 }
00527 cachedTopLeft = topLeftPt;
00528 cachedTopRight = topRightPt;
00529 cachedBottomRight = bottomRightPt;
00530 cachedBottomLeft = bottomLeftPt;
00531 }else{
00532 topLeftPt = cachedTopLeft;
00533 topRightPt = cachedTopRight;
00534 bottomRightPt = cachedBottomRight;
00535 bottomLeftPt = cachedBottomLeft;
00536 }
00537
00538 return cachedSizeHint;
00539 }
00540
00541 QSize KDChart::TextLayoutItem::sizeHintUnrotated() const
00542 {
00543 realFontWasRecalculated();
00544 return unrotatedSizeHint( cachedFont );
00545 }
00546
00547
00548
00549
00550
00551 QSize KDChart::TextLayoutItem::unrotatedSizeHint( QFont fnt ) const
00552 {
00553 if ( fnt == QFont() )
00554 fnt = realFont();
00555
00556 const QFontMetricsF met( fnt, GlobalMeasureScaling::paintDevice() );
00557 QSize ret(0, 0);
00558
00559
00560
00561
00562 QStringList lines = mText.split(QString::fromAscii("\n"));
00563 for (int i = 0; i < lines.size(); ++i) {
00564 const QSize lSize = met.boundingRect(lines.at(i) ).toRect().size();
00565 ret.setWidth(qMax( ret.width(), lSize.width() ));
00566 ret.rheight() += lSize.height();
00567 }
00568
00569 int frame = QApplication::style()->pixelMetric( QStyle::PM_ButtonMargin, 0, 0 );
00570
00571 frame = qMin( frame, ret.height() * 2 / 3 );
00572
00573 ret += QSize( frame, frame );
00574 return ret;
00575
00576
00577
00578
00579 }
00580
00581
00582 QSize KDChart::TextLayoutItem::calcSizeHint(
00583 QFont fnt, QPoint& topLeftPt, QPoint& topRightPt, QPoint& bottomRightPt, QPoint& bottomLeftPt ) const
00584 {
00585 const QSize siz( unrotatedSizeHint( fnt ));
00586
00587 if( ! mAttributes.rotation() ){
00588 topLeftPt = QPoint(0,0);
00589 topRightPt = QPoint(siz.width(),0);
00590 bottomRightPt = QPoint(siz.width(),siz.height());
00591 bottomLeftPt = QPoint(0,siz.height());
00592 return siz;
00593 }
00594
00595 const QRect rect(QPoint(0, 0), siz + QSize(4,4));
00596 const qreal angle = PI * mAttributes.rotation() / 180.0;
00597 const qreal cosAngle = cos( angle );
00598 const qreal sinAngle = sin( angle );
00599 QMatrix rotationMatrix(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
00600 QPolygon rotPts;
00601 rotPts << rotationMatrix.map(rect.topLeft())
00602 << rotationMatrix.map(rect.topRight())
00603 << rotationMatrix.map(rect.bottomRight())
00604 << rotationMatrix.map(rect.bottomLeft());
00605 QSize rotSiz( rotPts.boundingRect().size() );
00606
00607 topLeftPt = rotPts[0];
00608 topRightPt = rotPts[1];
00609 bottomRightPt = rotPts[2];
00610 bottomLeftPt = rotPts[3];
00611 return rotSiz;
00612 }
00613
00614
00615 void KDChart::TextLayoutItem::paint( QPainter* painter )
00616 {
00617
00618
00619
00620 if( !mRect.isValid() )
00621 return;
00622
00623 const PainterSaver painterSaver( painter );
00624 QFont f = realFont();
00625 if ( mAttributes.autoShrink() )
00626 f.setPointSizeF( fitFontSizeToGeometry() );
00627 painter->setFont( f );
00628 QRectF rect( geometry() );
00629
00630
00631
00632
00633
00634 painter->translate( rect.center() );
00635 rect.moveTopLeft( QPointF( - rect.width() / 2, - rect.height() / 2 ) );
00636 #ifdef DEBUG_ITEMS_PAINT
00637 painter->setPen( Qt::blue );
00638 painter->drawRect( rect );
00639 painter->drawRect( QRect(QPoint((rect.topLeft().toPoint() + rect.bottomLeft().toPoint()) / 2 - QPoint(2,2)), QSize(3,3)) );
00640
00641 #endif
00642 painter->rotate( mAttributes.rotation() );
00643 rect = rotatedRect( rect, mAttributes.rotation() );
00644 #ifdef DEBUG_ITEMS_PAINT
00645 painter->setPen( Qt::red );
00646 painter->drawRect( rect );
00647 painter->drawRect( QRect(QPoint((rect.topLeft().toPoint() + rect.bottomLeft().toPoint()) / 2 - QPoint(2,2)), QSize(3,3)) );
00648
00649 #endif
00650 painter->setPen( PrintingParameters::scalePen( mAttributes.pen() ) );
00651 QFontMetrics fontMetrics( f );
00652 const int AHight = fontMetrics.boundingRect( QChar::fromAscii( 'A' ) ).height();
00653 const qreal AVCenter = fontMetrics.ascent() - AHight / 2.0;
00654
00655
00656 rect.translate( 0.0, rect.height() / 2.0 - AVCenter );
00657
00658 painter->drawText( rect, mTextAlignment, mText );
00659
00660
00661
00662
00663
00664 }
00665
00666 KDChart::HorizontalLineLayoutItem::HorizontalLineLayoutItem()
00667 : AbstractLayoutItem( Qt::AlignCenter )
00668 {
00669 }
00670
00671 Qt::Orientations KDChart::HorizontalLineLayoutItem::expandingDirections() const
00672 {
00673 return Qt::Vertical|Qt::Horizontal;
00674 }
00675
00676 QRect KDChart::HorizontalLineLayoutItem::geometry() const
00677 {
00678 return mRect;
00679 }
00680
00681 bool KDChart::HorizontalLineLayoutItem::isEmpty() const
00682 {
00683 return false;
00684 }
00685
00686 QSize KDChart::HorizontalLineLayoutItem::maximumSize() const
00687 {
00688 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00689 }
00690
00691 QSize KDChart::HorizontalLineLayoutItem::minimumSize() const
00692 {
00693 return QSize( 0, 0 );
00694 }
00695
00696 void KDChart::HorizontalLineLayoutItem::setGeometry( const QRect& r )
00697 {
00698 mRect = r;
00699 }
00700
00701 QSize KDChart::HorizontalLineLayoutItem::sizeHint() const
00702 {
00703 return QSize( -1, 3 );
00704 }
00705
00706
00707 void KDChart::HorizontalLineLayoutItem::paint( QPainter* painter )
00708 {
00709 if( !mRect.isValid() )
00710 return;
00711
00712 painter->drawLine( QPointF( mRect.left(), mRect.center().y() ),
00713 QPointF( mRect.right(), mRect.center().y() ) );
00714 }
00715
00716
00717 KDChart::VerticalLineLayoutItem::VerticalLineLayoutItem()
00718 : AbstractLayoutItem( Qt::AlignCenter )
00719 {
00720 }
00721
00722 Qt::Orientations KDChart::VerticalLineLayoutItem::expandingDirections() const
00723 {
00724 return Qt::Vertical|Qt::Vertical;
00725 }
00726
00727 QRect KDChart::VerticalLineLayoutItem::geometry() const
00728 {
00729 return mRect;
00730 }
00731
00732 bool KDChart::VerticalLineLayoutItem::isEmpty() const
00733 {
00734 return false;
00735 }
00736
00737 QSize KDChart::VerticalLineLayoutItem::maximumSize() const
00738 {
00739 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00740 }
00741
00742 QSize KDChart::VerticalLineLayoutItem::minimumSize() const
00743 {
00744 return QSize( 0, 0 );
00745 }
00746
00747 void KDChart::VerticalLineLayoutItem::setGeometry( const QRect& r )
00748 {
00749 mRect = r;
00750 }
00751
00752 QSize KDChart::VerticalLineLayoutItem::sizeHint() const
00753 {
00754 return QSize( 3, -1 );
00755 }
00756
00757
00758 void KDChart::VerticalLineLayoutItem::paint( QPainter* painter )
00759 {
00760 if( !mRect.isValid() )
00761 return;
00762
00763 painter->drawLine( QPointF( mRect.center().x(), mRect.top() ),
00764 QPointF( mRect.center().x(), mRect.bottom() ) );
00765 }
00766
00767
00768
00769 KDChart::MarkerLayoutItem::MarkerLayoutItem( KDChart::AbstractDiagram* diagram,
00770 const MarkerAttributes& marker,
00771 const QBrush& brush, const QPen& pen,
00772 Qt::Alignment alignment )
00773 : AbstractLayoutItem( alignment )
00774 , mDiagram( diagram )
00775 , mMarker( marker )
00776 , mBrush( brush )
00777 , mPen( pen )
00778 {
00779 }
00780
00781 Qt::Orientations KDChart::MarkerLayoutItem::expandingDirections() const
00782 {
00783 return 0;
00784 }
00785
00786 QRect KDChart::MarkerLayoutItem::geometry() const
00787 {
00788 return mRect;
00789 }
00790
00791 bool KDChart::MarkerLayoutItem::isEmpty() const
00792 {
00793 return false;
00794 }
00795
00796 QSize KDChart::MarkerLayoutItem::maximumSize() const
00797 {
00798 return sizeHint();
00799 }
00800
00801 QSize KDChart::MarkerLayoutItem::minimumSize() const
00802 {
00803 return sizeHint();
00804 }
00805
00806 void KDChart::MarkerLayoutItem::setGeometry( const QRect& r )
00807 {
00808 mRect = r;
00809 }
00810
00811 QSize KDChart::MarkerLayoutItem::sizeHint() const
00812 {
00813
00814 return mMarker.markerSize().toSize();
00815 }
00816
00817 void KDChart::MarkerLayoutItem::paint( QPainter* painter )
00818 {
00819 paintIntoRect( painter, mRect, mDiagram, mMarker, mBrush, mPen );
00820 }
00821
00822 void KDChart::MarkerLayoutItem::paintIntoRect(
00823 QPainter* painter,
00824 const QRect& rect,
00825 AbstractDiagram* diagram,
00826 const MarkerAttributes& marker,
00827 const QBrush& brush,
00828 const QPen& pen )
00829 {
00830 if( ! rect.isValid() )
00831 return;
00832
00833
00834
00835 const QSize siz = marker.markerSize().toSize();
00836 QPointF pos = rect.topLeft();
00837 pos += QPointF( static_cast<qreal>(( rect.width() - siz.width()) / 2.0 ),
00838 static_cast<qreal>(( rect.height() - siz.height()) / 2.0 ) );
00839
00840 #ifdef DEBUG_ITEMS_PAINT
00841 QPointF oldPos = pos;
00842 #endif
00843
00844
00845
00846 pos += QPointF( static_cast<qreal>( siz.width() ) / 2.0,
00847 static_cast<qreal>( siz.height() )/ 2.0 );
00848
00849 diagram->paintMarker( painter, marker, brush, pen, pos.toPoint(), siz );
00850
00851 #ifdef DEBUG_ITEMS_PAINT
00852 const QPen oldPen( painter->pen() );
00853 painter->setPen( Qt::red );
00854 painter->drawRect( QRect(oldPos.toPoint(), siz) );
00855 painter->setPen( oldPen );
00856 #endif
00857 }
00858
00859
00860 KDChart::LineLayoutItem::LineLayoutItem( KDChart::AbstractDiagram* diagram,
00861 int length,
00862 const QPen& pen,
00863 Qt::Alignment alignment )
00864 : AbstractLayoutItem( alignment )
00865 , mDiagram( diagram )
00866 , mLength( length )
00867 , mPen( pen )
00868 {
00869
00870 if ( pen.width() < 2 )
00871 mPen.setWidth( 2 );
00872 }
00873
00874 Qt::Orientations KDChart::LineLayoutItem::expandingDirections() const
00875 {
00876 return 0;
00877 }
00878
00879 QRect KDChart::LineLayoutItem::geometry() const
00880 {
00881 return mRect;
00882 }
00883
00884 bool KDChart::LineLayoutItem::isEmpty() const
00885 {
00886 return false;
00887 }
00888
00889 QSize KDChart::LineLayoutItem::maximumSize() const
00890 {
00891 return sizeHint();
00892 }
00893
00894 QSize KDChart::LineLayoutItem::minimumSize() const
00895 {
00896 return sizeHint();
00897 }
00898
00899 void KDChart::LineLayoutItem::setGeometry( const QRect& r )
00900 {
00901 mRect = r;
00902 }
00903
00904 QSize KDChart::LineLayoutItem::sizeHint() const
00905 {
00906 return QSize( mLength, mPen.width()+2 );
00907 }
00908
00909 void KDChart::LineLayoutItem::paint( QPainter* painter )
00910 {
00911 paintIntoRect( painter, mRect, mPen );
00912 }
00913
00914 void KDChart::LineLayoutItem::paintIntoRect(
00915 QPainter* painter,
00916 const QRect& rect,
00917 const QPen& pen )
00918 {
00919 if( ! rect.isValid() )
00920 return;
00921
00922 const QPen oldPen = painter->pen();
00923 painter->setPen( PrintingParameters::scalePen( pen ) );
00924 const qreal y = rect.center().y();
00925 painter->drawLine( QPointF( rect.left(), y ),
00926 QPointF( rect.right(), y ) );
00927 painter->setPen( oldPen );
00928 }
00929
00930
00931 KDChart::LineWithMarkerLayoutItem::LineWithMarkerLayoutItem(
00932 KDChart::AbstractDiagram* diagram,
00933 int lineLength,
00934 const QPen& linePen,
00935 int markerOffs,
00936 const MarkerAttributes& marker,
00937 const QBrush& markerBrush,
00938 const QPen& markerPen,
00939 Qt::Alignment alignment )
00940 : AbstractLayoutItem( alignment )
00941 , mDiagram( diagram )
00942 , mLineLength( lineLength )
00943 , mLinePen( linePen )
00944 , mMarkerOffs( markerOffs )
00945 , mMarker( marker )
00946 , mMarkerBrush( markerBrush )
00947 , mMarkerPen( markerPen )
00948 {
00949 }
00950
00951 Qt::Orientations KDChart::LineWithMarkerLayoutItem::expandingDirections() const
00952 {
00953 return 0;
00954 }
00955
00956 QRect KDChart::LineWithMarkerLayoutItem::geometry() const
00957 {
00958 return mRect;
00959 }
00960
00961 bool KDChart::LineWithMarkerLayoutItem::isEmpty() const
00962 {
00963 return false;
00964 }
00965
00966 QSize KDChart::LineWithMarkerLayoutItem::maximumSize() const
00967 {
00968 return sizeHint();
00969 }
00970
00971 QSize KDChart::LineWithMarkerLayoutItem::minimumSize() const
00972 {
00973 return sizeHint();
00974 }
00975
00976 void KDChart::LineWithMarkerLayoutItem::setGeometry( const QRect& r )
00977 {
00978 mRect = r;
00979 }
00980
00981 QSize KDChart::LineWithMarkerLayoutItem::sizeHint() const
00982 {
00983 const QSize sizeM = mMarker.markerSize().toSize();
00984 const QSize sizeL = QSize( mLineLength, mLinePen.width()+2 );
00985 return QSize( qMax(sizeM.width(), sizeL.width()),
00986 qMax(sizeM.height(), sizeL.height()) );
00987 }
00988
00989 void KDChart::LineWithMarkerLayoutItem::paint( QPainter* painter )
00990 {
00991
00992 LineLayoutItem::paintIntoRect( painter, mRect, mLinePen );
00993
00994
00995 const QRect r(
00996 QPoint( mRect.x()+mMarkerOffs, mRect.y() ),
00997 QSize( mMarker.markerSize().toSize().width(), mRect.height() ) );
00998 MarkerLayoutItem::paintIntoRect(
00999 painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen );
01000 }
01001
01002
01003
01004 KDChart::AutoSpacerLayoutItem::AutoSpacerLayoutItem(
01005 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
01006 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout )
01007 : AbstractLayoutItem( Qt::AlignCenter )
01008 , mLayoutIsAtTopPosition( layoutIsAtTopPosition )
01009 , mRightLeftLayout( rightLeftLayout )
01010 , mLayoutIsAtLeftPosition( layoutIsAtLeftPosition )
01011 , mTopBottomLayout( topBottomLayout )
01012 {
01013 }
01014
01015 Qt::Orientations KDChart::AutoSpacerLayoutItem::expandingDirections() const
01016 {
01017 return 0;
01018 }
01019
01020 QRect KDChart::AutoSpacerLayoutItem::geometry() const
01021 {
01022 return mRect;
01023 }
01024
01025 bool KDChart::AutoSpacerLayoutItem::isEmpty() const
01026 {
01027 return true;
01028 }
01029
01030 QSize KDChart::AutoSpacerLayoutItem::maximumSize() const
01031 {
01032 return sizeHint();
01033 }
01034
01035 QSize KDChart::AutoSpacerLayoutItem::minimumSize() const
01036 {
01037 return sizeHint();
01038 }
01039
01040 void KDChart::AutoSpacerLayoutItem::setGeometry( const QRect& r )
01041 {
01042 mRect = r;
01043 }
01044
01045
01046 static void updateCommonBrush( QBrush& commonBrush, bool& bStart, const KDChart::AbstractArea& area )
01047 {
01048 const KDChart::BackgroundAttributes ba( area.backgroundAttributes() );
01049 const bool hasSimpleBrush = (
01050 ! area.frameAttributes().isVisible() &&
01051 ba.isVisible() &&
01052 ba.pixmapMode() == KDChart::BackgroundAttributes::BackgroundPixmapModeNone &&
01053 ba.brush().gradient() == 0 );
01054 if( bStart ){
01055 bStart = false;
01056 commonBrush = hasSimpleBrush ? ba.brush() : QBrush();
01057 }else{
01058 if( ! hasSimpleBrush || ba.brush() != commonBrush )
01059 {
01060 commonBrush = QBrush();
01061 }
01062 }
01063 }
01064
01065 QSize KDChart::AutoSpacerLayoutItem::sizeHint() const
01066 {
01067 QBrush commonBrush;
01068 bool bStart=true;
01069
01070 int topBottomOverlap = 0;
01071 if( mTopBottomLayout ){
01072 for (int i = 0; i < mTopBottomLayout->count(); ++i){
01073 AbstractArea* area = dynamic_cast<AbstractArea*>(mTopBottomLayout->itemAt(i));
01074 if( area ){
01075
01076 topBottomOverlap =
01077 mLayoutIsAtLeftPosition
01078 ? qMax( topBottomOverlap, area->rightOverlap() )
01079 : qMax( topBottomOverlap, area->leftOverlap() );
01080 updateCommonBrush( commonBrush, bStart, *area );
01081 }
01082 }
01083 }
01084
01085 int leftRightOverlap = 0;
01086 if( mRightLeftLayout ){
01087 for (int i = 0; i < mRightLeftLayout->count(); ++i){
01088 AbstractArea* area = dynamic_cast<AbstractArea*>(mRightLeftLayout->itemAt(i));
01089 if( area ){
01090
01091 leftRightOverlap =
01092 mLayoutIsAtTopPosition
01093 ? qMax( leftRightOverlap, area->bottomOverlap() )
01094 : qMax( leftRightOverlap, area->topOverlap() );
01095 updateCommonBrush( commonBrush, bStart, *area );
01096 }
01097 }
01098 }
01099 if( topBottomOverlap > 0 && leftRightOverlap > 0 )
01100 mCommonBrush = commonBrush;
01101 else
01102 mCommonBrush = QBrush();
01103 mCachedSize = QSize( topBottomOverlap, leftRightOverlap );
01104
01105 return mCachedSize;
01106 }
01107
01108
01109 void KDChart::AutoSpacerLayoutItem::paint( QPainter* painter )
01110 {
01111 if( mParentLayout && mRect.isValid() && mCachedSize.isValid() &&
01112 mCommonBrush.style() != Qt::NoBrush )
01113 {
01114 QPoint p1( mRect.topLeft() );
01115 QPoint p2( mRect.bottomRight() );
01116 if( mLayoutIsAtLeftPosition )
01117 p1.rx() += mCachedSize.width() - mParentLayout->spacing();
01118 else
01119 p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
01120 if( mLayoutIsAtTopPosition ){
01121 p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
01122 p2.ry() -= 1;
01123 }else
01124 p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
01125
01126
01127
01128
01129 const QPoint oldBrushOrigin( painter->brushOrigin() );
01130 const QBrush oldBrush( painter->brush() );
01131 const QPen oldPen( painter->pen() );
01132 const QPointF newTopLeft( painter->deviceMatrix().map( p1 ) );
01133 painter->setBrushOrigin( newTopLeft );
01134 painter->setBrush( mCommonBrush );
01135 painter->setPen( Qt::NoPen );
01136 painter->drawRect( QRect( p1, p2 ) );
01137 painter->setBrushOrigin( oldBrushOrigin );
01138 painter->setBrush( oldBrush );
01139 painter->setPen( oldPen );
01140 }
01141
01142 #if 0
01143
01144 if( !mRect.isValid() )
01145 return;
01146
01147 painter->drawRect( mRect );
01148 painter->drawLine( QPointF( mRect.x(), mRect.top() ),
01149 QPointF( mRect.right(), mRect.bottom() ) );
01150 painter->drawLine( QPointF( mRect.right(), mRect.top() ),
01151 QPointF( mRect.x(), mRect.bottom() ) );
01152 #endif
01153 }