30 #include "KDChartPainterSaver_p.h"
32 #include <QTextCursor>
33 #include <QTextBlockFormat>
34 #include <QTextDocumentFragment>
35 #include <QAbstractTextDocumentLayout>
39 #include <QCoreApplication>
40 #include <QApplication>
41 #include <QStringList>
44 #include <KDABLibFakes>
86 if ( mParent->layout() )
87 mParent->layout()->invalidate();
89 QApplication::postEvent( mParent,
new QEvent( QEvent::LayoutRequest ) );
97 Qt::Alignment alignment )
99 m_text( new
TextLayoutItem( text, attributes, area, orientation, alignment ) )
116 m_text->setAutoReferenceArea( area );
121 return m_text->autoReferenceArea();
126 m_text->setText( text );
131 return m_text->text();
136 m_text->setTextAttributes( a );
141 return m_text->textAttributes();
146 return m_text->isEmpty();
151 return m_text->expandingDirections();
156 const int border = borderWidth();
157 return m_text->maximumSize() + QSize( 2 * border, 2 * border );
162 const int border = borderWidth();
163 return m_text->minimumSize() + QSize( 2 * border, 2 * border );
168 const int border = borderWidth();
169 return m_text->sizeHint() + QSize( 2 * border, 2 * border );
174 const int border = borderWidth();
175 m_text->setGeometry( r.adjusted( border, border, -border, -border ) );
180 const int border = borderWidth();
181 return m_text->geometry().adjusted( -border, -border, border, border );
186 const QPen oldPen = painter->pen();
187 const QBrush oldBrush = painter->brush();
188 painter->setPen( Qt::black );
189 painter->setBrush( QColor( 255, 255, 220 ) );
190 painter->drawRoundRect( geometry(), 10 );
191 painter->setPen( oldPen );
192 painter->setBrush( oldBrush );
193 m_text->paint( painter );
205 Qt::Alignment alignment )
208 , mTextAlignment( alignment )
209 , mAttributes( attributes )
210 , mAutoReferenceArea( area )
211 , mAutoReferenceOrientation( orientation )
213 , cachedFontSize( 0.0 )
214 , cachedFont( mAttributes.font() )
221 , mTextAlignment( Qt::AlignLeft )
223 , mAutoReferenceArea( 0 )
224 , mAutoReferenceOrientation(
KDChartEnums::MeasureOrientationHorizontal )
226 , cachedFontSize( 0.0 )
227 , cachedFont( mAttributes.font() )
234 mAutoReferenceArea = area;
235 cachedSizeHint = QSize();
241 return mAutoReferenceArea;
247 cachedSizeHint = QSize();
260 if ( mTextAlignment == alignment )
262 mTextAlignment = alignment;
269 return mTextAlignment;
280 cachedFont = a.
font();
281 cachedSizeHint = QSize();
332 QPointF center = rect.center();
333 t.translate( center.x(), center.y() );
334 t.rotate( rotation );
335 t.translate( -center.x(), -center.y() );
336 return t.mapRect( rect );
339 qreal KDChart::TextLayoutItem::fitFontSizeToGeometry()
const
341 QFont f = realFont();
342 const qreal origResult = f.pointSizeF();
343 qreal result = origResult;
344 const qreal minSize = mAttributes.minimalFontSize().value();
345 const QSize mySize = geometry().size();
346 if ( mySize.isNull() ) {
350 QFontMetrics fm( f );
352 const QSizeF textSize =
rotatedRect( fm.boundingRect( mText ), mAttributes.rotation() ).normalized().size();
354 if ( textSize.height() <= mySize.height() && textSize.width() <= mySize.width() ) {
359 if ( minSize > 0 && result < minSize ) {
361 }
else if ( result <= 0.0 ) {
364 f.setPointSizeF( result );
365 fm = QFontMetrics( f );
371 return mAttributes.calculatedFontSize( mAutoReferenceArea, mAutoReferenceOrientation );
374 bool KDChart::TextLayoutItem::maybeUpdateRealFont()
const
376 const qreal fntSiz = realFontSize();
377 const bool doUpdate = !cachedSizeHint.isValid() || cachedFontSize != fntSiz;
379 if ( doUpdate && fntSiz > 0.0 ) {
380 cachedFontSize = fntSiz;
381 cachedFont.setPointSizeF( fntSiz );
388 maybeUpdateRealFont();
395 return mCachedBoundingPolygon;
400 return intersects( other, myPos.toPoint(), otherPos.toPoint() );
405 QRegion myRegion( boundingPolygon().translated( myPos - otherPos ) );
408 return myRegion.intersects( otherRegion );
414 if ( maybeUpdateRealFont() || mAttributes.rotation() || !cachedSizeHint.isValid() ) {
415 const QSize newSizeHint( calcSizeHint( cachedFont ) );
416 Q_ASSERT( newSizeHint.isValid() );
417 if ( newSizeHint != cachedSizeHint ) {
418 cachedSizeHint = newSizeHint;
422 return cachedSizeHint;
427 maybeUpdateRealFont();
428 return unrotatedSizeHint( cachedFont );
435 QSize KDChart::TextLayoutItem::unrotatedTextSize( QFont fnt )
const
437 if ( fnt == QFont() ) {
442 QRect veryLarge( 0, 0, 100000, 100000 );
444 return fm.boundingRect( veryLarge, Qt::AlignLeft | Qt::AlignTop, mText ).size().toSize();
449 return marginWidth( unrotatedTextSize() );
454 return qMin ( QApplication::style()->pixelMetric( QStyle::PM_ButtonMargin, 0, 0 ),
456 textSize.height() * 2 / 3 );
459 QSize KDChart::TextLayoutItem::unrotatedSizeHint(
const QFont& fnt )
const
461 QSize ret = unrotatedTextSize( fnt );
462 const int margin = marginWidth( ret );
463 ret += QSize( margin, margin );
467 QSize KDChart::TextLayoutItem::calcSizeHint(
const QFont& font )
const
469 const QSize size = unrotatedSizeHint( font );
470 QPoint topLeft( -size.width() * 0.5, -size.height() * 0.5 );
471 if ( !mAttributes.rotation() ) {
472 mCachedBoundingPolygon.resize( 4 );
475 mCachedBoundingPolygon[ 0 ] = topLeft;
476 mCachedBoundingPolygon[ 1 ] = topLeft + QPoint( size.width(), 0 );
477 mCachedBoundingPolygon[ 2 ] = topLeft + QPoint( size.width(), size.height() );
478 mCachedBoundingPolygon[ 3 ] = topLeft + QPoint( 0, size.height() );
482 const QRect rect( topLeft, size );
484 t.rotate( mAttributes.rotation() );
485 mCachedBoundingPolygon = t.mapToPolygon( rect );
487 return mCachedBoundingPolygon.boundingRect().size();
492 if ( !mRect.isValid() ) {
495 const PainterSaver painterSaver( painter );
496 QFont f = realFont();
497 if ( mAttributes.autoShrink() ) {
500 painter->setFont( f );
502 QSize innerSize = unrotatedTextSize();
503 QRectF rect = QRectF( QPointF( 0, 0 ), innerSize );
504 rect.translate( -rect.center() );
505 painter->translate( mRect.center() );
506 painter->rotate( mAttributes.rotation() );
507 #ifdef DEBUG_ITEMS_PAINT
508 painter->setPen( Qt::red );
509 painter->drawRect( rect );
515 document->setPageSize( rect.size() );
516 document->setHtml( mText );
517 QAbstractTextDocumentLayout::PaintContext paintcontext;
520 paintcontext.clip = rect;
521 document->documentLayout()->draw( painter, paintcontext );
523 painter->drawText( rect, mTextAlignment, mText );
534 return Qt::Horizontal;
549 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
554 return QSize( 0, 0 );
564 return QSize( -1, 3 );
570 if ( !mRect.isValid() )
573 painter->drawLine( QPointF( mRect.left(), mRect.center().y() ),
574 QPointF( mRect.right(), mRect.center().y() ) );
600 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
605 return QSize( 0, 0 );
615 return QSize( 3, -1 );
621 if ( !mRect.isValid() )
624 painter->drawLine( QPointF( mRect.center().x(), mRect.top() ),
625 QPointF( mRect.center().x(), mRect.bottom() ) );
632 const QBrush& brush,
const QPen& pen,
633 Qt::Alignment alignment )
635 , mDiagram( diagram )
675 return mMarker.markerSize().toSize();
680 paintIntoRect( painter, mRect, mDiagram, mMarker, mBrush, mPen );
691 if ( !rect.isValid() )
696 const QSize siz = marker.
markerSize().toSize();
697 QPointF pos = rect.topLeft();
698 pos += QPointF(
static_cast<qreal
>(( rect.width() - siz.width()) / 2.0 ),
699 static_cast<qreal
>(( rect.height() - siz.height()) / 2.0 ) );
701 #ifdef DEBUG_ITEMS_PAINT
702 QPointF oldPos = pos;
707 pos += QPointF(
static_cast<qreal
>( siz.width() ) / 2.0,
708 static_cast<qreal
>( siz.height() )/ 2.0 );
710 diagram->
paintMarker( painter, marker, brush, pen, pos.toPoint(), siz );
712 #ifdef DEBUG_ITEMS_PAINT
713 const QPen oldPen( painter->pen() );
714 painter->setPen( Qt::red );
715 painter->drawRect( QRect( oldPos.toPoint(), siz ) );
716 painter->setPen( oldPen );
724 Qt::Alignment legendLineSymbolAlignment,
725 Qt::Alignment alignment )
727 , mDiagram( diagram )
730 , mLegendLineSymbolAlignment(legendLineSymbolAlignment)
733 if ( pen.width() < 2 )
769 return QSize( mLength, mPen.width() + 2 );
775 if (mLegendLineSymbolAlignment == legendLineSymbolAlignment)
778 mLegendLineSymbolAlignment = legendLineSymbolAlignment;
783 return mLegendLineSymbolAlignment;
788 paintIntoRect( painter, mRect, mPen, mLegendLineSymbolAlignment );
795 Qt::Alignment lineAlignment)
797 if ( ! rect.isValid() )
800 const QPen oldPen = painter->pen();
803 if (lineAlignment == Qt::AlignTop)
805 else if (lineAlignment == Qt::AlignBottom)
808 y = rect.center().y();
810 painter->drawLine( QPointF( rect.left(), y ),
811 QPointF( rect.right(), y ) );
812 painter->setPen( oldPen );
822 const QBrush& markerBrush,
823 const QPen& markerPen,
824 Qt::Alignment alignment )
826 , mDiagram( diagram )
827 , mLineLength( lineLength )
828 , mLinePen( linePen )
829 , mMarkerOffs( markerOffs )
831 , mMarkerBrush( markerBrush )
832 , mMarkerPen( markerPen )
868 const QSize lineSize( mLineLength, mLinePen.width() + 2 );
869 return lineSize.expandedTo( mMarker.markerSize().toSize() );
879 QPoint( mRect.x()+mMarkerOffs, mRect.y() ),
880 QSize( mMarker.markerSize().toSize().width(), mRect.height() ) );
882 painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen );
886 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
887 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout )
889 , mLayoutIsAtTopPosition( layoutIsAtTopPosition )
890 , mRightLeftLayout( rightLeftLayout )
891 , mLayoutIsAtLeftPosition( layoutIsAtLeftPosition )
892 , mTopBottomLayout( topBottomLayout )
930 const bool hasSimpleBrush = (
934 ba.
brush().gradient() == 0 );
937 commonBrush = hasSimpleBrush ? ba.
brush() : QBrush();
939 if ( ! hasSimpleBrush || ba.
brush() != commonBrush )
941 commonBrush = QBrush();
951 int topBottomOverlap = 0;
952 if ( mTopBottomLayout ) {
953 for (
int i = 0; i < mTopBottomLayout->count(); ++i) {
957 topBottomOverlap = qMax( topBottomOverlap,
965 int leftRightOverlap = 0;
966 if ( mRightLeftLayout ) {
967 for (
int i = 0; i < mRightLeftLayout->count(); ++i) {
971 leftRightOverlap = qMax( leftRightOverlap,
978 if ( topBottomOverlap > 0 && leftRightOverlap > 0 )
979 mCommonBrush = commonBrush;
981 mCommonBrush = QBrush();
982 mCachedSize = QSize( topBottomOverlap, leftRightOverlap );
990 if ( mParentLayout && mRect.isValid() && mCachedSize.isValid() &&
991 mCommonBrush.style() != Qt::NoBrush )
993 QPoint p1( mRect.topLeft() );
994 QPoint p2( mRect.bottomRight() );
995 if ( mLayoutIsAtLeftPosition )
996 p1.rx() += mCachedSize.width() - mParentLayout->spacing();
998 p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
999 if ( mLayoutIsAtTopPosition ) {
1000 p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
1003 p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
1008 const QPoint oldBrushOrigin( painter->brushOrigin() );
1009 const QBrush oldBrush( painter->brush() );
1010 const QPen oldPen( painter->pen() );
1011 const QPointF newTopLeft( painter->deviceMatrix().map( p1 ) );
1012 painter->setBrushOrigin( newTopLeft );
1013 painter->setBrush( mCommonBrush );
1014 painter->setPen( Qt::NoPen );
1015 painter->drawRect( QRect( p1, p2 ) );
1016 painter->setBrushOrigin( oldBrushOrigin );
1017 painter->setBrush( oldBrush );
1018 painter->setPen( oldPen );
1023 if ( !mRect.isValid() )
1026 painter->drawRect( mRect );
1027 painter->drawLine( QPointF( mRect.topLeft(), mRect.bottomRight() ) );
1028 painter->drawLine( QPointF( mRect.topRight(), mRect.bottomLeft() ) );