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 if ( mAttributes.rotation() != other.mAttributes.
rotation() )
408 QPolygon myPolygon = boundingPolygon().translated( myPos );
409 QPolygon otherPolygon = other.
boundingPolygon().translated( otherPos );
412 QRegion myRegion( myPolygon );
413 QRegion otherRegion( otherPolygon );
416 return ! myRegion.intersected( otherRegion ).isEmpty();
420 const qreal angle = DEGTORAD( mAttributes.rotation() );
422 const QSizeF mySize( unrotatedSizeHint() );
423 const QSizeF otherSize( other.unrotatedSizeHint() );
426 QPointF myP1( mySize.height() * sin( angle ), 0.0 );
428 QPointF otherP1 = QPointF( otherSize.height() * sin( angle ), 0.0 ) + otherPos - myPos;
431 myP1 = QPointF( myP1.x() * cos( -angle ), myP1.x() * sin( -angle ) );
432 qreal r = sqrt( otherP1.x() * otherP1.x() + otherP1.y() * otherP1.y() );
433 if ( myP1.x() == otherP1.x() ) {
434 otherP1 = QPointF( r * sin( -angle ), r * cos( -angle ) );
435 }
else if ( myP1.y() == otherP1.y() ) {
436 otherP1 = QPointF( r * cos( -angle ), r * sin( -angle ) );
439 return QRectF( myP1, mySize ).intersects( QRectF( otherP1, otherSize ) );
446 if ( maybeUpdateRealFont() || mAttributes.rotation() || !cachedSizeHint.isValid() ) {
447 const QSize newSizeHint( calcSizeHint( cachedFont ) );
448 Q_ASSERT( newSizeHint.isValid() );
449 if ( newSizeHint != cachedSizeHint ) {
450 cachedSizeHint = newSizeHint;
454 return cachedSizeHint;
459 maybeUpdateRealFont();
460 return unrotatedSizeHint( cachedFont );
467 QSize KDChart::TextLayoutItem::unrotatedTextSize( QFont fnt )
const
469 if ( fnt == QFont() ) {
474 QRect veryLarge( 0, 0, 100000, 100000 );
476 return fm.boundingRect( veryLarge, Qt::AlignLeft | Qt::AlignTop, mText ).size().toSize();
481 return marginWidth( unrotatedTextSize() );
486 return qMin ( QApplication::style()->pixelMetric( QStyle::PM_ButtonMargin, 0, 0 ),
488 textSize.height() * 2 / 3 );
491 QSize KDChart::TextLayoutItem::unrotatedSizeHint(
const QFont& fnt )
const
493 QSize ret = unrotatedTextSize( fnt );
494 const int margin = marginWidth( ret );
495 ret += QSize( margin, margin );
499 QSize KDChart::TextLayoutItem::calcSizeHint(
const QFont& font )
const
501 const QSize size = unrotatedSizeHint( font );
502 QPoint topLeft( -size.width() * 0.5, -size.height() * 0.5 );
503 if ( !mAttributes.rotation() ) {
504 mCachedBoundingPolygon.resize( 4 );
507 mCachedBoundingPolygon[ 0 ] = topLeft;
508 mCachedBoundingPolygon[ 1 ] = topLeft + QPoint( size.width(), 0 );
509 mCachedBoundingPolygon[ 2 ] = topLeft + QPoint( size.width(), size.height() );
510 mCachedBoundingPolygon[ 3 ] = topLeft + QPoint( 0, size.height() );
514 const QRect rect( topLeft, size );
516 t.rotate( mAttributes.rotation() );
517 mCachedBoundingPolygon = t.mapToPolygon( rect );
519 return mCachedBoundingPolygon.boundingRect().size();
524 if ( !mRect.isValid() ) {
527 const PainterSaver painterSaver( painter );
528 QFont f = realFont();
529 if ( mAttributes.autoShrink() ) {
532 painter->setFont( f );
534 QSize innerSize = unrotatedTextSize();
535 QRectF rect = QRectF( QPointF( 0, 0 ), innerSize );
536 rect.translate( -rect.center() );
537 painter->translate( mRect.center() );
538 painter->rotate( mAttributes.rotation() );
539 #ifdef DEBUG_ITEMS_PAINT
540 painter->setPen( Qt::red );
541 painter->drawRect( rect );
547 document->setPageSize( rect.size() );
548 document->setHtml( mText );
549 QAbstractTextDocumentLayout::PaintContext paintcontext;
552 paintcontext.clip = rect;
553 document->documentLayout()->draw( painter, paintcontext );
555 painter->drawText( rect, mTextAlignment, mText );
566 return Qt::Vertical|Qt::Horizontal;
581 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
586 return QSize( 0, 0 );
596 return QSize( -1, 3 );
602 if ( !mRect.isValid() )
605 painter->drawLine( QPointF( mRect.left(), mRect.center().y() ),
606 QPointF( mRect.right(), mRect.center().y() ) );
617 return Qt::Vertical|Qt::Vertical;
632 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
637 return QSize( 0, 0 );
647 return QSize( 3, -1 );
653 if ( !mRect.isValid() )
656 painter->drawLine( QPointF( mRect.center().x(), mRect.top() ),
657 QPointF( mRect.center().x(), mRect.bottom() ) );
664 const QBrush& brush,
const QPen& pen,
665 Qt::Alignment alignment )
667 , mDiagram( diagram )
707 return mMarker.markerSize().toSize();
712 paintIntoRect( painter, mRect, mDiagram, mMarker, mBrush, mPen );
723 if ( ! rect.isValid() )
728 const QSize siz = marker.
markerSize().toSize();
729 QPointF pos = rect.topLeft();
730 pos += QPointF( static_cast<qreal>(( rect.width() - siz.width()) / 2.0 ),
731 static_cast<qreal
>(( rect.height() - siz.height()) / 2.0 ) );
733 #ifdef DEBUG_ITEMS_PAINT
734 QPointF oldPos = pos;
739 pos += QPointF( static_cast<qreal>( siz.width() ) / 2.0,
740 static_cast<qreal>( siz.height() )/ 2.0 );
742 diagram->
paintMarker( painter, marker, brush, pen, pos.toPoint(), siz );
744 #ifdef DEBUG_ITEMS_PAINT
745 const QPen oldPen( painter->pen() );
746 painter->setPen( Qt::red );
747 painter->drawRect( QRect(oldPos.toPoint(), siz) );
748 painter->setPen( oldPen );
756 Qt::Alignment legendLineSymbolAlignment,
757 Qt::Alignment alignment )
759 , mDiagram( diagram )
762 , mLegendLineSymbolAlignment(legendLineSymbolAlignment)
765 if ( pen.width() < 2 )
801 return QSize( mLength, mPen.width()+2 );
807 if (mLegendLineSymbolAlignment == legendLineSymbolAlignment)
810 mLegendLineSymbolAlignment = legendLineSymbolAlignment;
815 return mLegendLineSymbolAlignment;
820 paintIntoRect( painter, mRect, mPen, mLegendLineSymbolAlignment );
827 Qt::Alignment lineAlignment)
829 if ( ! rect.isValid() )
832 const QPen oldPen = painter->pen();
835 if (lineAlignment == Qt::AlignTop)
837 else if (lineAlignment == Qt::AlignBottom)
840 y = rect.center().y();
842 painter->drawLine( QPointF( rect.left(), y ),
843 QPointF( rect.right(), y ) );
844 painter->setPen( oldPen );
854 const QBrush& markerBrush,
855 const QPen& markerPen,
856 Qt::Alignment alignment )
858 , mDiagram( diagram )
859 , mLineLength( lineLength )
860 , mLinePen( linePen )
861 , mMarkerOffs( markerOffs )
863 , mMarkerBrush( markerBrush )
864 , mMarkerPen( markerPen )
900 const QSize sizeM = mMarker.markerSize().toSize();
901 const QSize sizeL = QSize( mLineLength, mLinePen.width()+2 );
902 return QSize( qMax(sizeM.width(), sizeL.width()),
903 qMax(sizeM.height(), sizeL.height()) );
913 QPoint( mRect.x()+mMarkerOffs, mRect.y() ),
914 QSize( mMarker.markerSize().toSize().width(), mRect.height() ) );
916 painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen );
920 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
921 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout )
923 , mLayoutIsAtTopPosition( layoutIsAtTopPosition )
924 , mRightLeftLayout( rightLeftLayout )
925 , mLayoutIsAtLeftPosition( layoutIsAtLeftPosition )
926 , mTopBottomLayout( topBottomLayout )
964 const bool hasSimpleBrush = (
968 ba.brush().gradient() == 0 );
971 commonBrush = hasSimpleBrush ? ba.
brush() : QBrush();
973 if ( ! hasSimpleBrush || ba.brush() != commonBrush )
975 commonBrush = QBrush();
985 int topBottomOverlap = 0;
986 if ( mTopBottomLayout ) {
987 for (
int i = 0; i < mTopBottomLayout->count(); ++i) {
991 topBottomOverlap = qMax( topBottomOverlap,
999 int leftRightOverlap = 0;
1000 if ( mRightLeftLayout ) {
1001 for (
int i = 0; i < mRightLeftLayout->count(); ++i) {
1005 leftRightOverlap = qMax( leftRightOverlap,
1012 if ( topBottomOverlap > 0 && leftRightOverlap > 0 )
1013 mCommonBrush = commonBrush;
1015 mCommonBrush = QBrush();
1016 mCachedSize = QSize( topBottomOverlap, leftRightOverlap );
1024 if ( mParentLayout && mRect.isValid() && mCachedSize.isValid() &&
1025 mCommonBrush.style() != Qt::NoBrush )
1027 QPoint p1( mRect.topLeft() );
1028 QPoint p2( mRect.bottomRight() );
1029 if ( mLayoutIsAtLeftPosition )
1030 p1.rx() += mCachedSize.width() - mParentLayout->spacing();
1032 p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
1033 if ( mLayoutIsAtTopPosition ) {
1034 p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
1037 p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
1042 const QPoint oldBrushOrigin( painter->brushOrigin() );
1043 const QBrush oldBrush( painter->brush() );
1044 const QPen oldPen( painter->pen() );
1045 const QPointF newTopLeft( painter->deviceMatrix().map( p1 ) );
1046 painter->setBrushOrigin( newTopLeft );
1047 painter->setBrush( mCommonBrush );
1048 painter->setPen( Qt::NoPen );
1049 painter->drawRect( QRect( p1, p2 ) );
1050 painter->setBrushOrigin( oldBrushOrigin );
1051 painter->setBrush( oldBrush );
1052 painter->setPen( oldPen );
1057 if ( !mRect.isValid() )
1060 painter->drawRect( mRect );
1061 painter->drawLine( QPointF( mRect.topLeft(), mRect.bottomRight() ) );
1062 painter->drawLine( QPointF( mRect.topRight(), mRect.bottomLeft() ) );