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 QFontMetrics fontMetrics( f );
00655 const int AHight = fontMetrics.boundingRect( QChar::fromAscii( 'A' ) ).height();
00656 const qreal AVCenter = fontMetrics.ascent() - AHight / 2.0;
00657
00658
00659 rect.translate( 0.0, rect.height() / 2.0 - AVCenter );
00660
00661 painter->drawText( rect, mTextAlignment, mText );
00662
00663
00664
00665
00666
00667 }
00668
00669 KDChart::HorizontalLineLayoutItem::HorizontalLineLayoutItem()
00670 : AbstractLayoutItem( Qt::AlignCenter )
00671 {
00672 }
00673
00674 Qt::Orientations KDChart::HorizontalLineLayoutItem::expandingDirections() const
00675 {
00676 return Qt::Vertical|Qt::Horizontal;
00677 }
00678
00679 QRect KDChart::HorizontalLineLayoutItem::geometry() const
00680 {
00681 return mRect;
00682 }
00683
00684 bool KDChart::HorizontalLineLayoutItem::isEmpty() const
00685 {
00686 return false;
00687 }
00688
00689 QSize KDChart::HorizontalLineLayoutItem::maximumSize() const
00690 {
00691 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00692 }
00693
00694 QSize KDChart::HorizontalLineLayoutItem::minimumSize() const
00695 {
00696 return QSize( 0, 0 );
00697 }
00698
00699 void KDChart::HorizontalLineLayoutItem::setGeometry( const QRect& r )
00700 {
00701 mRect = r;
00702 }
00703
00704 QSize KDChart::HorizontalLineLayoutItem::sizeHint() const
00705 {
00706 return QSize( -1, 3 );
00707 }
00708
00709
00710 void KDChart::HorizontalLineLayoutItem::paint( QPainter* painter )
00711 {
00712 if( !mRect.isValid() )
00713 return;
00714
00715 painter->drawLine( QPointF( mRect.left(), mRect.center().y() ),
00716 QPointF( mRect.right(), mRect.center().y() ) );
00717 }
00718
00719
00720 KDChart::VerticalLineLayoutItem::VerticalLineLayoutItem()
00721 : AbstractLayoutItem( Qt::AlignCenter )
00722 {
00723 }
00724
00725 Qt::Orientations KDChart::VerticalLineLayoutItem::expandingDirections() const
00726 {
00727 return Qt::Vertical|Qt::Vertical;
00728 }
00729
00730 QRect KDChart::VerticalLineLayoutItem::geometry() const
00731 {
00732 return mRect;
00733 }
00734
00735 bool KDChart::VerticalLineLayoutItem::isEmpty() const
00736 {
00737 return false;
00738 }
00739
00740 QSize KDChart::VerticalLineLayoutItem::maximumSize() const
00741 {
00742 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00743 }
00744
00745 QSize KDChart::VerticalLineLayoutItem::minimumSize() const
00746 {
00747 return QSize( 0, 0 );
00748 }
00749
00750 void KDChart::VerticalLineLayoutItem::setGeometry( const QRect& r )
00751 {
00752 mRect = r;
00753 }
00754
00755 QSize KDChart::VerticalLineLayoutItem::sizeHint() const
00756 {
00757 return QSize( 3, -1 );
00758 }
00759
00760
00761 void KDChart::VerticalLineLayoutItem::paint( QPainter* painter )
00762 {
00763 if( !mRect.isValid() )
00764 return;
00765
00766 painter->drawLine( QPointF( mRect.center().x(), mRect.top() ),
00767 QPointF( mRect.center().x(), mRect.bottom() ) );
00768 }
00769
00770
00771
00772 KDChart::MarkerLayoutItem::MarkerLayoutItem( KDChart::AbstractDiagram* diagram,
00773 const MarkerAttributes& marker,
00774 const QBrush& brush, const QPen& pen,
00775 Qt::Alignment alignment )
00776 : AbstractLayoutItem( alignment )
00777 , mDiagram( diagram )
00778 , mMarker( marker )
00779 , mBrush( brush )
00780 , mPen( pen )
00781 {
00782 }
00783
00784 Qt::Orientations KDChart::MarkerLayoutItem::expandingDirections() const
00785 {
00786 return 0;
00787 }
00788
00789 QRect KDChart::MarkerLayoutItem::geometry() const
00790 {
00791 return mRect;
00792 }
00793
00794 bool KDChart::MarkerLayoutItem::isEmpty() const
00795 {
00796 return false;
00797 }
00798
00799 QSize KDChart::MarkerLayoutItem::maximumSize() const
00800 {
00801 return sizeHint();
00802 }
00803
00804 QSize KDChart::MarkerLayoutItem::minimumSize() const
00805 {
00806 return sizeHint();
00807 }
00808
00809 void KDChart::MarkerLayoutItem::setGeometry( const QRect& r )
00810 {
00811 mRect = r;
00812 }
00813
00814 QSize KDChart::MarkerLayoutItem::sizeHint() const
00815 {
00816
00817 return mMarker.markerSize().toSize();
00818 }
00819
00820 void KDChart::MarkerLayoutItem::paint( QPainter* painter )
00821 {
00822 paintIntoRect( painter, mRect, mDiagram, mMarker, mBrush, mPen );
00823 }
00824
00825 void KDChart::MarkerLayoutItem::paintIntoRect(
00826 QPainter* painter,
00827 const QRect& rect,
00828 AbstractDiagram* diagram,
00829 const MarkerAttributes& marker,
00830 const QBrush& brush,
00831 const QPen& pen )
00832 {
00833 if( ! rect.isValid() )
00834 return;
00835
00836
00837
00838 const QSize siz = marker.markerSize().toSize();
00839 QPointF pos = rect.topLeft();
00840 pos += QPointF( static_cast<qreal>(( rect.width() - siz.width()) / 2.0 ),
00841 static_cast<qreal>(( rect.height() - siz.height()) / 2.0 ) );
00842
00843 #ifdef DEBUG_ITEMS_PAINT
00844 QPointF oldPos = pos;
00845 #endif
00846
00847
00848
00849 pos += QPointF( static_cast<qreal>( siz.width() ) / 2.0,
00850 static_cast<qreal>( siz.height() )/ 2.0 );
00851
00852 diagram->paintMarker( painter, marker, brush, pen, pos.toPoint(), siz );
00853
00854 #ifdef DEBUG_ITEMS_PAINT
00855 const QPen oldPen( painter->pen() );
00856 painter->setPen( Qt::red );
00857 painter->drawRect( QRect(oldPos.toPoint(), siz) );
00858 painter->setPen( oldPen );
00859 #endif
00860 }
00861
00862
00863 KDChart::LineLayoutItem::LineLayoutItem( KDChart::AbstractDiagram* diagram,
00864 int length,
00865 const QPen& pen,
00866 Qt::Alignment alignment )
00867 : AbstractLayoutItem( alignment )
00868 , mDiagram( diagram )
00869 , mLength( length )
00870 , mPen( pen )
00871 {
00872
00873 if ( pen.width() < 2 )
00874 mPen.setWidth( 2 );
00875 }
00876
00877 Qt::Orientations KDChart::LineLayoutItem::expandingDirections() const
00878 {
00879 return 0;
00880 }
00881
00882 QRect KDChart::LineLayoutItem::geometry() const
00883 {
00884 return mRect;
00885 }
00886
00887 bool KDChart::LineLayoutItem::isEmpty() const
00888 {
00889 return false;
00890 }
00891
00892 QSize KDChart::LineLayoutItem::maximumSize() const
00893 {
00894 return sizeHint();
00895 }
00896
00897 QSize KDChart::LineLayoutItem::minimumSize() const
00898 {
00899 return sizeHint();
00900 }
00901
00902 void KDChart::LineLayoutItem::setGeometry( const QRect& r )
00903 {
00904 mRect = r;
00905 }
00906
00907 QSize KDChart::LineLayoutItem::sizeHint() const
00908 {
00909 return QSize( mLength, mPen.width()+2 );
00910 }
00911
00912 void KDChart::LineLayoutItem::paint( QPainter* painter )
00913 {
00914 paintIntoRect( painter, mRect, mPen );
00915 }
00916
00917 void KDChart::LineLayoutItem::paintIntoRect(
00918 QPainter* painter,
00919 const QRect& rect,
00920 const QPen& pen )
00921 {
00922 if( ! rect.isValid() )
00923 return;
00924
00925 const QPen oldPen = painter->pen();
00926 painter->setPen( PrintingParameters::scalePen( pen ) );
00927 const qreal y = rect.center().y();
00928 painter->drawLine( QPointF( rect.left(), y ),
00929 QPointF( rect.right(), y ) );
00930 painter->setPen( oldPen );
00931 }
00932
00933
00934 KDChart::LineWithMarkerLayoutItem::LineWithMarkerLayoutItem(
00935 KDChart::AbstractDiagram* diagram,
00936 int lineLength,
00937 const QPen& linePen,
00938 int markerOffs,
00939 const MarkerAttributes& marker,
00940 const QBrush& markerBrush,
00941 const QPen& markerPen,
00942 Qt::Alignment alignment )
00943 : AbstractLayoutItem( alignment )
00944 , mDiagram( diagram )
00945 , mLineLength( lineLength )
00946 , mLinePen( linePen )
00947 , mMarkerOffs( markerOffs )
00948 , mMarker( marker )
00949 , mMarkerBrush( markerBrush )
00950 , mMarkerPen( markerPen )
00951 {
00952 }
00953
00954 Qt::Orientations KDChart::LineWithMarkerLayoutItem::expandingDirections() const
00955 {
00956 return 0;
00957 }
00958
00959 QRect KDChart::LineWithMarkerLayoutItem::geometry() const
00960 {
00961 return mRect;
00962 }
00963
00964 bool KDChart::LineWithMarkerLayoutItem::isEmpty() const
00965 {
00966 return false;
00967 }
00968
00969 QSize KDChart::LineWithMarkerLayoutItem::maximumSize() const
00970 {
00971 return sizeHint();
00972 }
00973
00974 QSize KDChart::LineWithMarkerLayoutItem::minimumSize() const
00975 {
00976 return sizeHint();
00977 }
00978
00979 void KDChart::LineWithMarkerLayoutItem::setGeometry( const QRect& r )
00980 {
00981 mRect = r;
00982 }
00983
00984 QSize KDChart::LineWithMarkerLayoutItem::sizeHint() const
00985 {
00986 const QSize sizeM = mMarker.markerSize().toSize();
00987 const QSize sizeL = QSize( mLineLength, mLinePen.width()+2 );
00988 return QSize( qMax(sizeM.width(), sizeL.width()),
00989 qMax(sizeM.height(), sizeL.height()) );
00990 }
00991
00992 void KDChart::LineWithMarkerLayoutItem::paint( QPainter* painter )
00993 {
00994
00995 LineLayoutItem::paintIntoRect( painter, mRect, mLinePen );
00996
00997
00998 const QRect r(
00999 QPoint( mRect.x()+mMarkerOffs, mRect.y() ),
01000 QSize( mMarker.markerSize().toSize().width(), mRect.height() ) );
01001 MarkerLayoutItem::paintIntoRect(
01002 painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen );
01003 }
01004
01005
01006
01007 KDChart::AutoSpacerLayoutItem::AutoSpacerLayoutItem(
01008 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
01009 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout )
01010 : AbstractLayoutItem( Qt::AlignCenter )
01011 , mLayoutIsAtTopPosition( layoutIsAtTopPosition )
01012 , mRightLeftLayout( rightLeftLayout )
01013 , mLayoutIsAtLeftPosition( layoutIsAtLeftPosition )
01014 , mTopBottomLayout( topBottomLayout )
01015 {
01016 }
01017
01018 Qt::Orientations KDChart::AutoSpacerLayoutItem::expandingDirections() const
01019 {
01020 return 0;
01021 }
01022
01023 QRect KDChart::AutoSpacerLayoutItem::geometry() const
01024 {
01025 return mRect;
01026 }
01027
01028 bool KDChart::AutoSpacerLayoutItem::isEmpty() const
01029 {
01030 return true;
01031 }
01032
01033 QSize KDChart::AutoSpacerLayoutItem::maximumSize() const
01034 {
01035 return sizeHint();
01036 }
01037
01038 QSize KDChart::AutoSpacerLayoutItem::minimumSize() const
01039 {
01040 return sizeHint();
01041 }
01042
01043 void KDChart::AutoSpacerLayoutItem::setGeometry( const QRect& r )
01044 {
01045 mRect = r;
01046 }
01047
01048
01049 static void updateCommonBrush( QBrush& commonBrush, bool& bStart, const KDChart::AbstractArea& area )
01050 {
01051 const KDChart::BackgroundAttributes ba( area.backgroundAttributes() );
01052 const bool hasSimpleBrush = (
01053 ! area.frameAttributes().isVisible() &&
01054 ba.isVisible() &&
01055 ba.pixmapMode() == KDChart::BackgroundAttributes::BackgroundPixmapModeNone &&
01056 ba.brush().gradient() == 0 );
01057 if( bStart ){
01058 bStart = false;
01059 commonBrush = hasSimpleBrush ? ba.brush() : QBrush();
01060 }else{
01061 if( ! hasSimpleBrush || ba.brush() != commonBrush )
01062 {
01063 commonBrush = QBrush();
01064 }
01065 }
01066 }
01067
01068 QSize KDChart::AutoSpacerLayoutItem::sizeHint() const
01069 {
01070 QBrush commonBrush;
01071 bool bStart=true;
01072
01073 int topBottomOverlap = 0;
01074 if( mTopBottomLayout ){
01075 for (int i = 0; i < mTopBottomLayout->count(); ++i){
01076 AbstractArea* area = dynamic_cast<AbstractArea*>(mTopBottomLayout->itemAt(i));
01077 if( area ){
01078
01079 topBottomOverlap =
01080 mLayoutIsAtLeftPosition
01081 ? qMax( topBottomOverlap, area->rightOverlap() )
01082 : qMax( topBottomOverlap, area->leftOverlap() );
01083 updateCommonBrush( commonBrush, bStart, *area );
01084 }
01085 }
01086 }
01087
01088 int leftRightOverlap = 0;
01089 if( mRightLeftLayout ){
01090 for (int i = 0; i < mRightLeftLayout->count(); ++i){
01091 AbstractArea* area = dynamic_cast<AbstractArea*>(mRightLeftLayout->itemAt(i));
01092 if( area ){
01093
01094 leftRightOverlap =
01095 mLayoutIsAtTopPosition
01096 ? qMax( leftRightOverlap, area->bottomOverlap() )
01097 : qMax( leftRightOverlap, area->topOverlap() );
01098 updateCommonBrush( commonBrush, bStart, *area );
01099 }
01100 }
01101 }
01102 if( topBottomOverlap > 0 && leftRightOverlap > 0 )
01103 mCommonBrush = commonBrush;
01104 else
01105 mCommonBrush = QBrush();
01106 mCachedSize = QSize( topBottomOverlap, leftRightOverlap );
01107
01108 return mCachedSize;
01109 }
01110
01111
01112 void KDChart::AutoSpacerLayoutItem::paint( QPainter* painter )
01113 {
01114 if( mParentLayout && mRect.isValid() && mCachedSize.isValid() &&
01115 mCommonBrush.style() != Qt::NoBrush )
01116 {
01117 QPoint p1( mRect.topLeft() );
01118 QPoint p2( mRect.bottomRight() );
01119 if( mLayoutIsAtLeftPosition )
01120 p1.rx() += mCachedSize.width() - mParentLayout->spacing();
01121 else
01122 p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
01123 if( mLayoutIsAtTopPosition ){
01124 p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
01125 p2.ry() -= 1;
01126 }else
01127 p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
01128
01129
01130
01131
01132 const QPoint oldBrushOrigin( painter->brushOrigin() );
01133 const QBrush oldBrush( painter->brush() );
01134 const QPen oldPen( painter->pen() );
01135 const QPointF newTopLeft( painter->deviceMatrix().map( p1 ) );
01136 painter->setBrushOrigin( newTopLeft );
01137 painter->setBrush( mCommonBrush );
01138 painter->setPen( Qt::NoPen );
01139 painter->drawRect( QRect( p1, p2 ) );
01140 painter->setBrushOrigin( oldBrushOrigin );
01141 painter->setBrush( oldBrush );
01142 painter->setPen( oldPen );
01143 }
01144
01145 #if 0
01146
01147 if( !mRect.isValid() )
01148 return;
01149
01150 painter->drawRect( mRect );
01151 painter->drawLine( QPointF( mRect.x(), mRect.top() ),
01152 QPointF( mRect.right(), mRect.bottom() ) );
01153 painter->drawLine( QPointF( mRect.right(), mRect.top() ),
01154 QPointF( mRect.x(), mRect.bottom() ) );
01155 #endif
01156 }