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 qreal minSize = mAttributes.minimalFontSize().value();
00399 const QSize mySize = geometry().size();
00400 if( mySize.isNull() )
00401 return result;
00402
00403 const QString t = text();
00404 QFontMetrics fm( f );
00405 while( true )
00406 {
00407 const QSizeF textSize = rotatedRect( fm.boundingRect( t ), mAttributes.rotation() ).normalized().size();
00408
00409 if( textSize.height() <= mySize.height() && textSize.width() <= mySize.width() )
00410 return result;
00411
00412 result -= 0.5;
00413 if ( minSize > 0 && result < minSize )
00414 return result += 0.5;
00415 if( result <= 0.0 )
00416 return origResult;
00417 f.setPointSizeF( result );
00418 fm = QFontMetrics( f );
00419 }
00420 }
00421
00422 qreal KDChart::TextLayoutItem::realFontSize() const
00423 {
00424 return mAttributes.calculatedFontSize( mAutoReferenceArea, mAutoReferenceOrientation );
00425 }
00426
00427
00428 bool KDChart::TextLayoutItem::realFontWasRecalculated() const
00429 {
00430 const qreal fntSiz = realFontSize();
00431 const bool bRecalcDone =
00432 ( ( ! cachedSizeHint.isValid() ) || ( cachedFontSize != fntSiz ) );
00433
00434 if( bRecalcDone && fntSiz > 0.0 ){
00435 cachedFontSize = fntSiz;
00436 cachedFont.setPointSizeF( fntSiz );
00437 }
00438 return bRecalcDone;
00439 }
00440
00441
00442 QFont KDChart::TextLayoutItem::realFont() const
00443 {
00444 realFontWasRecalculated();
00445 return cachedFont;
00446 }
00447
00448 QPolygon KDChart::TextLayoutItem::rotatedCorners() const
00449 {
00450
00451 const qreal angle = mAttributes.rotation() * PI / 180.0;
00452 QSize size = unrotatedSizeHint();
00453
00454
00455 QPointF P1( size.height() * sin( angle ), 0 );
00456 QPointF P2( size.height() * sin( angle ) + size.width() * cos( angle ), size.width() * sin( angle ) );
00457 QPointF P3( size.width() * cos( angle ), size.width() * sin( angle ) + size.height() * cos( angle ) );
00458 QPointF P4( 0, size.height() * cos( angle ) );
00459
00460 QPolygon result;
00461 result << P1.toPoint() << P2.toPoint() << P3.toPoint() << P4.toPoint();
00462 return result;
00463 }
00464
00465 bool KDChart::TextLayoutItem::intersects( const TextLayoutItem& other, const QPointF& myPos, const QPointF& otherPos ) const
00466 {
00467 return intersects( other, myPos.toPoint(), otherPos.toPoint() );
00468 }
00469
00470 bool KDChart::TextLayoutItem::intersects( const TextLayoutItem& other, const QPoint& myPos, const QPoint& otherPos ) const
00471 {
00472 if ( mAttributes.rotation() != other.mAttributes.rotation() )
00473 {
00474
00475 QPolygon myPolygon( rotatedCorners() );
00476 QPolygon otherPolygon( other.rotatedCorners() );
00477
00478
00479 myPolygon.translate( myPos );
00480 otherPolygon.translate( otherPos );
00481
00482
00483 QRegion myRegion( myPolygon );
00484 QRegion otherRegion( otherPolygon );
00485
00486
00487 return ! myRegion.intersect( otherRegion ).isEmpty();
00488
00489 } else {
00490
00491 const qreal angle = mAttributes.rotation() * PI / 180.0;
00492
00493 const QSizeF mySize( unrotatedSizeHint() );
00494 const QSizeF otherSize( other.unrotatedSizeHint() );
00495
00496
00497 QPointF myP1( mySize.height() * sin( angle ), 0.0 );
00498
00499 QPointF otherP1 = QPointF( otherSize.height() * sin( angle ), 0.0 ) + otherPos - myPos;
00500
00501
00502 myP1 = QPointF( myP1.x() * cos( -angle ), myP1.x() * sin( -angle ) );
00503 qreal r = sqrt( otherP1.x() * otherP1.x() + otherP1.y() * otherP1.y() );
00504 otherP1 = QPointF( r * cos( -angle ), r * sin( -angle ) );
00505
00506
00507 const bool res = QRectF( myP1, mySize ).intersects( QRectF( otherP1, otherSize ) );
00508
00509 return res;
00510 }
00511 }
00512
00513 QSize KDChart::TextLayoutItem::sizeHint() const
00514 {
00515 QPoint dummy;
00516 return sizeHintAndRotatedCorners(dummy,dummy,dummy,dummy);
00517 }
00518
00519 QSize KDChart::TextLayoutItem::sizeHintAndRotatedCorners(
00520 QPoint& topLeftPt, QPoint& topRightPt, QPoint& bottomRightPt, QPoint& bottomLeftPt) const
00521 {
00522 if( realFontWasRecalculated() || mAttributes.rotation() )
00523 {
00524 const QSize newSizeHint( calcSizeHint( cachedFont,
00525 topLeftPt, topRightPt, bottomRightPt, bottomLeftPt ) );
00526 if( newSizeHint != cachedSizeHint ){
00527 cachedSizeHint = newSizeHint;
00528 sizeHintChanged();
00529 }
00530 cachedTopLeft = topLeftPt;
00531 cachedTopRight = topRightPt;
00532 cachedBottomRight = bottomRightPt;
00533 cachedBottomLeft = bottomLeftPt;
00534 }else{
00535 topLeftPt = cachedTopLeft;
00536 topRightPt = cachedTopRight;
00537 bottomRightPt = cachedBottomRight;
00538 bottomLeftPt = cachedBottomLeft;
00539 }
00540
00541 return cachedSizeHint;
00542 }
00543
00544 QSize KDChart::TextLayoutItem::sizeHintUnrotated() const
00545 {
00546 realFontWasRecalculated();
00547 return unrotatedSizeHint( cachedFont );
00548 }
00549
00550
00551
00552
00553
00554 QSize KDChart::TextLayoutItem::unrotatedSizeHint( QFont fnt ) const
00555 {
00556 if ( fnt == QFont() )
00557 fnt = realFont();
00558
00559 const QFontMetricsF met( fnt, GlobalMeasureScaling::paintDevice() );
00560 QSize ret(0, 0);
00561
00562
00563
00564
00565 QStringList lines = mText.split(QString::fromAscii("\n"));
00566 for (int i = 0; i < lines.size(); ++i) {
00567 const QSize lSize = met.boundingRect(lines.at(i) ).toRect().size();
00568 ret.setWidth(qMax( ret.width(), lSize.width() ));
00569 ret.rheight() += lSize.height();
00570 }
00571
00572 int frame = QApplication::style()->pixelMetric( QStyle::PM_ButtonMargin, 0, 0 );
00573
00574 frame = qMin( frame, ret.height() * 2 / 3 );
00575
00576 ret += QSize( frame, frame );
00577 return ret;
00578
00579
00580
00581
00582 }
00583
00584
00585 QSize KDChart::TextLayoutItem::calcSizeHint(
00586 QFont fnt, QPoint& topLeftPt, QPoint& topRightPt, QPoint& bottomRightPt, QPoint& bottomLeftPt ) const
00587 {
00588 const QSize siz( unrotatedSizeHint( fnt ));
00589
00590 if( ! mAttributes.rotation() ){
00591 topLeftPt = QPoint(0,0);
00592 topRightPt = QPoint(siz.width(),0);
00593 bottomRightPt = QPoint(siz.width(),siz.height());
00594 bottomLeftPt = QPoint(0,siz.height());
00595 return siz;
00596 }
00597
00598 const QRect rect(QPoint(0, 0), siz + QSize(4,4));
00599 const qreal angle = PI * mAttributes.rotation() / 180.0;
00600 const qreal cosAngle = cos( angle );
00601 const qreal sinAngle = sin( angle );
00602 QMatrix rotationMatrix(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
00603 QPolygon rotPts;
00604 rotPts << rotationMatrix.map(rect.topLeft())
00605 << rotationMatrix.map(rect.topRight())
00606 << rotationMatrix.map(rect.bottomRight())
00607 << rotationMatrix.map(rect.bottomLeft());
00608 QSize rotSiz( rotPts.boundingRect().size() );
00609
00610 topLeftPt = rotPts[0];
00611 topRightPt = rotPts[1];
00612 bottomRightPt = rotPts[2];
00613 bottomLeftPt = rotPts[3];
00614 return rotSiz;
00615 }
00616
00617
00618 void KDChart::TextLayoutItem::paint( QPainter* painter )
00619 {
00620
00621
00622
00623 if( !mRect.isValid() )
00624 return;
00625
00626 const PainterSaver painterSaver( painter );
00627 QFont f = realFont();
00628 if ( mAttributes.autoShrink() )
00629 f.setPointSizeF( fitFontSizeToGeometry() );
00630 painter->setFont( f );
00631 QRectF rect( geometry() );
00632
00633
00634
00635
00636
00637 painter->translate( rect.center() );
00638 rect.moveTopLeft( QPointF( - rect.width() / 2, - rect.height() / 2 ) );
00639 #ifdef DEBUG_ITEMS_PAINT
00640 painter->setPen( Qt::blue );
00641 painter->drawRect( rect );
00642 painter->drawRect( QRect(QPoint((rect.topLeft().toPoint() + rect.bottomLeft().toPoint()) / 2 - QPoint(2,2)), QSize(3,3)) );
00643
00644 #endif
00645 painter->rotate( mAttributes.rotation() );
00646 rect = rotatedRect( rect, mAttributes.rotation() );
00647 #ifdef DEBUG_ITEMS_PAINT
00648 painter->setPen( Qt::red );
00649 painter->drawRect( rect );
00650 painter->drawRect( QRect(QPoint((rect.topLeft().toPoint() + rect.bottomLeft().toPoint()) / 2 - QPoint(2,2)), QSize(3,3)) );
00651
00652 #endif
00653 painter->setPen( PrintingParameters::scalePen( mAttributes.pen() ) );
00654
00655
00656
00657
00658
00659
00660
00661
00662 painter->drawText( rect, mTextAlignment, mText );
00663
00664
00665
00666
00667
00668
00669 }
00670
00671 KDChart::HorizontalLineLayoutItem::HorizontalLineLayoutItem()
00672 : AbstractLayoutItem( Qt::AlignCenter )
00673 {
00674 }
00675
00676 Qt::Orientations KDChart::HorizontalLineLayoutItem::expandingDirections() const
00677 {
00678 return Qt::Vertical|Qt::Horizontal;
00679 }
00680
00681 QRect KDChart::HorizontalLineLayoutItem::geometry() const
00682 {
00683 return mRect;
00684 }
00685
00686 bool KDChart::HorizontalLineLayoutItem::isEmpty() const
00687 {
00688 return false;
00689 }
00690
00691 QSize KDChart::HorizontalLineLayoutItem::maximumSize() const
00692 {
00693 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00694 }
00695
00696 QSize KDChart::HorizontalLineLayoutItem::minimumSize() const
00697 {
00698 return QSize( 0, 0 );
00699 }
00700
00701 void KDChart::HorizontalLineLayoutItem::setGeometry( const QRect& r )
00702 {
00703 mRect = r;
00704 }
00705
00706 QSize KDChart::HorizontalLineLayoutItem::sizeHint() const
00707 {
00708 return QSize( -1, 3 );
00709 }
00710
00711
00712 void KDChart::HorizontalLineLayoutItem::paint( QPainter* painter )
00713 {
00714 if( !mRect.isValid() )
00715 return;
00716
00717 painter->drawLine( QPointF( mRect.left(), mRect.center().y() ),
00718 QPointF( mRect.right(), mRect.center().y() ) );
00719 }
00720
00721
00722 KDChart::VerticalLineLayoutItem::VerticalLineLayoutItem()
00723 : AbstractLayoutItem( Qt::AlignCenter )
00724 {
00725 }
00726
00727 Qt::Orientations KDChart::VerticalLineLayoutItem::expandingDirections() const
00728 {
00729 return Qt::Vertical|Qt::Vertical;
00730 }
00731
00732 QRect KDChart::VerticalLineLayoutItem::geometry() const
00733 {
00734 return mRect;
00735 }
00736
00737 bool KDChart::VerticalLineLayoutItem::isEmpty() const
00738 {
00739 return false;
00740 }
00741
00742 QSize KDChart::VerticalLineLayoutItem::maximumSize() const
00743 {
00744 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00745 }
00746
00747 QSize KDChart::VerticalLineLayoutItem::minimumSize() const
00748 {
00749 return QSize( 0, 0 );
00750 }
00751
00752 void KDChart::VerticalLineLayoutItem::setGeometry( const QRect& r )
00753 {
00754 mRect = r;
00755 }
00756
00757 QSize KDChart::VerticalLineLayoutItem::sizeHint() const
00758 {
00759 return QSize( 3, -1 );
00760 }
00761
00762
00763 void KDChart::VerticalLineLayoutItem::paint( QPainter* painter )
00764 {
00765 if( !mRect.isValid() )
00766 return;
00767
00768 painter->drawLine( QPointF( mRect.center().x(), mRect.top() ),
00769 QPointF( mRect.center().x(), mRect.bottom() ) );
00770 }
00771
00772
00773
00774 KDChart::MarkerLayoutItem::MarkerLayoutItem( KDChart::AbstractDiagram* diagram,
00775 const MarkerAttributes& marker,
00776 const QBrush& brush, const QPen& pen,
00777 Qt::Alignment alignment )
00778 : AbstractLayoutItem( alignment )
00779 , mDiagram( diagram )
00780 , mMarker( marker )
00781 , mBrush( brush )
00782 , mPen( pen )
00783 {
00784 }
00785
00786 Qt::Orientations KDChart::MarkerLayoutItem::expandingDirections() const
00787 {
00788 return 0;
00789 }
00790
00791 QRect KDChart::MarkerLayoutItem::geometry() const
00792 {
00793 return mRect;
00794 }
00795
00796 bool KDChart::MarkerLayoutItem::isEmpty() const
00797 {
00798 return false;
00799 }
00800
00801 QSize KDChart::MarkerLayoutItem::maximumSize() const
00802 {
00803 return sizeHint();
00804 }
00805
00806 QSize KDChart::MarkerLayoutItem::minimumSize() const
00807 {
00808 return sizeHint();
00809 }
00810
00811 void KDChart::MarkerLayoutItem::setGeometry( const QRect& r )
00812 {
00813 mRect = r;
00814 }
00815
00816 QSize KDChart::MarkerLayoutItem::sizeHint() const
00817 {
00818
00819 return mMarker.markerSize().toSize();
00820 }
00821
00822 void KDChart::MarkerLayoutItem::paint( QPainter* painter )
00823 {
00824 paintIntoRect( painter, mRect, mDiagram, mMarker, mBrush, mPen );
00825 }
00826
00827 void KDChart::MarkerLayoutItem::paintIntoRect(
00828 QPainter* painter,
00829 const QRect& rect,
00830 AbstractDiagram* diagram,
00831 const MarkerAttributes& marker,
00832 const QBrush& brush,
00833 const QPen& pen )
00834 {
00835 if( ! rect.isValid() )
00836 return;
00837
00838
00839
00840 const QSize siz = marker.markerSize().toSize();
00841 QPointF pos = rect.topLeft();
00842 pos += QPointF( static_cast<qreal>(( rect.width() - siz.width()) / 2.0 ),
00843 static_cast<qreal>(( rect.height() - siz.height()) / 2.0 ) );
00844
00845 #ifdef DEBUG_ITEMS_PAINT
00846 QPointF oldPos = pos;
00847 #endif
00848
00849
00850
00851 pos += QPointF( static_cast<qreal>( siz.width() ) / 2.0,
00852 static_cast<qreal>( siz.height() )/ 2.0 );
00853
00854 diagram->paintMarker( painter, marker, brush, pen, pos.toPoint(), siz );
00855
00856 #ifdef DEBUG_ITEMS_PAINT
00857 const QPen oldPen( painter->pen() );
00858 painter->setPen( Qt::red );
00859 painter->drawRect( QRect(oldPos.toPoint(), siz) );
00860 painter->setPen( oldPen );
00861 #endif
00862 }
00863
00864
00865 KDChart::LineLayoutItem::LineLayoutItem( KDChart::AbstractDiagram* diagram,
00866 int length,
00867 const QPen& pen,
00868 Qt::Alignment alignment )
00869 : AbstractLayoutItem( alignment )
00870 , mDiagram( diagram )
00871 , mLength( length )
00872 , mPen( pen )
00873 {
00874
00875 if ( pen.width() < 2 )
00876 mPen.setWidth( 2 );
00877 }
00878
00879 Qt::Orientations KDChart::LineLayoutItem::expandingDirections() const
00880 {
00881 return 0;
00882 }
00883
00884 QRect KDChart::LineLayoutItem::geometry() const
00885 {
00886 return mRect;
00887 }
00888
00889 bool KDChart::LineLayoutItem::isEmpty() const
00890 {
00891 return false;
00892 }
00893
00894 QSize KDChart::LineLayoutItem::maximumSize() const
00895 {
00896 return sizeHint();
00897 }
00898
00899 QSize KDChart::LineLayoutItem::minimumSize() const
00900 {
00901 return sizeHint();
00902 }
00903
00904 void KDChart::LineLayoutItem::setGeometry( const QRect& r )
00905 {
00906 mRect = r;
00907 }
00908
00909 QSize KDChart::LineLayoutItem::sizeHint() const
00910 {
00911 return QSize( mLength, mPen.width()+2 );
00912 }
00913
00914 void KDChart::LineLayoutItem::paint( QPainter* painter )
00915 {
00916 paintIntoRect( painter, mRect, mPen );
00917 }
00918
00919 void KDChart::LineLayoutItem::paintIntoRect(
00920 QPainter* painter,
00921 const QRect& rect,
00922 const QPen& pen )
00923 {
00924 if( ! rect.isValid() )
00925 return;
00926
00927 const QPen oldPen = painter->pen();
00928 painter->setPen( PrintingParameters::scalePen( pen ) );
00929 const qreal y = rect.center().y();
00930 painter->drawLine( QPointF( rect.left(), y ),
00931 QPointF( rect.right(), y ) );
00932 painter->setPen( oldPen );
00933 }
00934
00935
00936 KDChart::LineWithMarkerLayoutItem::LineWithMarkerLayoutItem(
00937 KDChart::AbstractDiagram* diagram,
00938 int lineLength,
00939 const QPen& linePen,
00940 int markerOffs,
00941 const MarkerAttributes& marker,
00942 const QBrush& markerBrush,
00943 const QPen& markerPen,
00944 Qt::Alignment alignment )
00945 : AbstractLayoutItem( alignment )
00946 , mDiagram( diagram )
00947 , mLineLength( lineLength )
00948 , mLinePen( linePen )
00949 , mMarkerOffs( markerOffs )
00950 , mMarker( marker )
00951 , mMarkerBrush( markerBrush )
00952 , mMarkerPen( markerPen )
00953 {
00954 }
00955
00956 Qt::Orientations KDChart::LineWithMarkerLayoutItem::expandingDirections() const
00957 {
00958 return 0;
00959 }
00960
00961 QRect KDChart::LineWithMarkerLayoutItem::geometry() const
00962 {
00963 return mRect;
00964 }
00965
00966 bool KDChart::LineWithMarkerLayoutItem::isEmpty() const
00967 {
00968 return false;
00969 }
00970
00971 QSize KDChart::LineWithMarkerLayoutItem::maximumSize() const
00972 {
00973 return sizeHint();
00974 }
00975
00976 QSize KDChart::LineWithMarkerLayoutItem::minimumSize() const
00977 {
00978 return sizeHint();
00979 }
00980
00981 void KDChart::LineWithMarkerLayoutItem::setGeometry( const QRect& r )
00982 {
00983 mRect = r;
00984 }
00985
00986 QSize KDChart::LineWithMarkerLayoutItem::sizeHint() const
00987 {
00988 const QSize sizeM = mMarker.markerSize().toSize();
00989 const QSize sizeL = QSize( mLineLength, mLinePen.width()+2 );
00990 return QSize( qMax(sizeM.width(), sizeL.width()),
00991 qMax(sizeM.height(), sizeL.height()) );
00992 }
00993
00994 void KDChart::LineWithMarkerLayoutItem::paint( QPainter* painter )
00995 {
00996
00997 LineLayoutItem::paintIntoRect( painter, mRect, mLinePen );
00998
00999
01000 const QRect r(
01001 QPoint( mRect.x()+mMarkerOffs, mRect.y() ),
01002 QSize( mMarker.markerSize().toSize().width(), mRect.height() ) );
01003 MarkerLayoutItem::paintIntoRect(
01004 painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen );
01005 }
01006
01007
01008
01009 KDChart::AutoSpacerLayoutItem::AutoSpacerLayoutItem(
01010 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
01011 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout )
01012 : AbstractLayoutItem( Qt::AlignCenter )
01013 , mLayoutIsAtTopPosition( layoutIsAtTopPosition )
01014 , mRightLeftLayout( rightLeftLayout )
01015 , mLayoutIsAtLeftPosition( layoutIsAtLeftPosition )
01016 , mTopBottomLayout( topBottomLayout )
01017 {
01018 }
01019
01020 Qt::Orientations KDChart::AutoSpacerLayoutItem::expandingDirections() const
01021 {
01022 return 0;
01023 }
01024
01025 QRect KDChart::AutoSpacerLayoutItem::geometry() const
01026 {
01027 return mRect;
01028 }
01029
01030 bool KDChart::AutoSpacerLayoutItem::isEmpty() const
01031 {
01032 return true;
01033 }
01034
01035 QSize KDChart::AutoSpacerLayoutItem::maximumSize() const
01036 {
01037 return sizeHint();
01038 }
01039
01040 QSize KDChart::AutoSpacerLayoutItem::minimumSize() const
01041 {
01042 return sizeHint();
01043 }
01044
01045 void KDChart::AutoSpacerLayoutItem::setGeometry( const QRect& r )
01046 {
01047 mRect = r;
01048 }
01049
01050
01051 static void updateCommonBrush( QBrush& commonBrush, bool& bStart, const KDChart::AbstractArea& area )
01052 {
01053 const KDChart::BackgroundAttributes ba( area.backgroundAttributes() );
01054 const bool hasSimpleBrush = (
01055 ! area.frameAttributes().isVisible() &&
01056 ba.isVisible() &&
01057 ba.pixmapMode() == KDChart::BackgroundAttributes::BackgroundPixmapModeNone &&
01058 ba.brush().gradient() == 0 );
01059 if( bStart ){
01060 bStart = false;
01061 commonBrush = hasSimpleBrush ? ba.brush() : QBrush();
01062 }else{
01063 if( ! hasSimpleBrush || ba.brush() != commonBrush )
01064 {
01065 commonBrush = QBrush();
01066 }
01067 }
01068 }
01069
01070 QSize KDChart::AutoSpacerLayoutItem::sizeHint() const
01071 {
01072 QBrush commonBrush;
01073 bool bStart=true;
01074
01075 int topBottomOverlap = 0;
01076 if( mTopBottomLayout ){
01077 for (int i = 0; i < mTopBottomLayout->count(); ++i){
01078 AbstractArea* area = dynamic_cast<AbstractArea*>(mTopBottomLayout->itemAt(i));
01079 if( area ){
01080
01081 topBottomOverlap =
01082 mLayoutIsAtLeftPosition
01083 ? qMax( topBottomOverlap, area->rightOverlap() )
01084 : qMax( topBottomOverlap, area->leftOverlap() );
01085 updateCommonBrush( commonBrush, bStart, *area );
01086 }
01087 }
01088 }
01089
01090 int leftRightOverlap = 0;
01091 if( mRightLeftLayout ){
01092 for (int i = 0; i < mRightLeftLayout->count(); ++i){
01093 AbstractArea* area = dynamic_cast<AbstractArea*>(mRightLeftLayout->itemAt(i));
01094 if( area ){
01095
01096 leftRightOverlap =
01097 mLayoutIsAtTopPosition
01098 ? qMax( leftRightOverlap, area->bottomOverlap() )
01099 : qMax( leftRightOverlap, area->topOverlap() );
01100 updateCommonBrush( commonBrush, bStart, *area );
01101 }
01102 }
01103 }
01104 if( topBottomOverlap > 0 && leftRightOverlap > 0 )
01105 mCommonBrush = commonBrush;
01106 else
01107 mCommonBrush = QBrush();
01108 mCachedSize = QSize( topBottomOverlap, leftRightOverlap );
01109
01110 return mCachedSize;
01111 }
01112
01113
01114 void KDChart::AutoSpacerLayoutItem::paint( QPainter* painter )
01115 {
01116 if( mParentLayout && mRect.isValid() && mCachedSize.isValid() &&
01117 mCommonBrush.style() != Qt::NoBrush )
01118 {
01119 QPoint p1( mRect.topLeft() );
01120 QPoint p2( mRect.bottomRight() );
01121 if( mLayoutIsAtLeftPosition )
01122 p1.rx() += mCachedSize.width() - mParentLayout->spacing();
01123 else
01124 p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
01125 if( mLayoutIsAtTopPosition ){
01126 p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
01127 p2.ry() -= 1;
01128 }else
01129 p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
01130
01131
01132
01133
01134 const QPoint oldBrushOrigin( painter->brushOrigin() );
01135 const QBrush oldBrush( painter->brush() );
01136 const QPen oldPen( painter->pen() );
01137 const QPointF newTopLeft( painter->deviceMatrix().map( p1 ) );
01138 painter->setBrushOrigin( newTopLeft );
01139 painter->setBrush( mCommonBrush );
01140 painter->setPen( Qt::NoPen );
01141 painter->drawRect( QRect( p1, p2 ) );
01142 painter->setBrushOrigin( oldBrushOrigin );
01143 painter->setBrush( oldBrush );
01144 painter->setPen( oldPen );
01145 }
01146
01147 #if 0
01148
01149 if( !mRect.isValid() )
01150 return;
01151
01152 painter->drawRect( mRect );
01153 painter->drawLine( QPointF( mRect.x(), mRect.top() ),
01154 QPointF( mRect.right(), mRect.bottom() ) );
01155 painter->drawLine( QPointF( mRect.right(), mRect.top() ),
01156 QPointF( mRect.x(), mRect.bottom() ) );
01157 #endif
01158 }