1 /* 2 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 3 * 4 * This file is part of the KD Chart library. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef KCHARTLAYOUTITEMS_H 21 #define KCHARTLAYOUTITEMS_H 22 23 #include <QBrush> 24 #include <QFont> 25 #include <QFontMetricsF> 26 #include <QLayout> 27 #include <QLayoutItem> 28 #include <QPen> 29 30 #include "KChartTextAttributes.h" 31 #include "KChartMarkerAttributes.h" 32 33 QT_BEGIN_NAMESPACE 34 class QPainter; 35 class KTextDocument; 36 QT_END_NAMESPACE 37 38 // TODO remove 39 QRectF rotatedRect( const QRectF& pt, qreal rotation ); 40 41 namespace KChart { 42 class AbstractDiagram; 43 class PaintContext; 44 45 /** 46 * Base class for all layout items of KChart 47 * \internal 48 */ 49 class KCHART_EXPORT AbstractLayoutItem : public QLayoutItem 50 { 51 public: 52 AbstractLayoutItem( Qt::Alignment itemAlignment = Qt::Alignment() ) : QLayoutItem(itemAlignment)53 QLayoutItem( itemAlignment ), 54 mParent( nullptr ), 55 mParentLayout( nullptr ) {} 56 57 /** 58 * Default impl: just call paint. 59 * 60 * Derived classes like KChart::AbstractArea are providing 61 * additional action here. 62 */ 63 virtual void paintAll( QPainter& painter ); 64 65 virtual void paint( QPainter* ) = 0; 66 67 68 /** 69 * Default impl: Paint the complete item using its layouted position and size. 70 */ 71 virtual void paintCtx( PaintContext* context ); 72 73 /** 74 Inform the item about its widget: This enables the item, 75 to trigger that widget's update, whenever the size of the item's 76 contents has changed. 77 78 Thus, you need to call setParentWidget on every item, that 79 has a non-fixed size. 80 */ 81 virtual void setParentWidget( QWidget* widget ); 82 83 /** 84 Report changed size hint: ask the parent widget to recalculate the layout. 85 */ 86 virtual void sizeHintChanged() const; 87 setParentLayout(QLayout * lay)88 void setParentLayout( QLayout* lay ) 89 { 90 mParentLayout = lay; 91 } parentLayout()92 QLayout* parentLayout() 93 { 94 return mParentLayout; 95 } removeFromParentLayout()96 void removeFromParentLayout() 97 { 98 if ( mParentLayout ) { 99 if ( widget() ) 100 mParentLayout->removeWidget( widget() ); 101 else 102 mParentLayout->removeItem( this ); 103 } 104 } 105 protected: 106 QWidget* mParent; 107 QLayout* mParentLayout; 108 }; 109 110 /** 111 * Layout item showing a text 112 *\internal 113 */ 114 class KCHART_EXPORT TextLayoutItem : public AbstractLayoutItem 115 { 116 public: 117 TextLayoutItem(); 118 TextLayoutItem( const QString& text, 119 const TextAttributes& attributes, 120 const QObject* autoReferenceArea, 121 KChartEnums::MeasureOrientation autoReferenceOrientation, 122 Qt::Alignment alignment = Qt::Alignment() ); 123 124 void setAutoReferenceArea( const QObject* area ); 125 const QObject* autoReferenceArea() const; 126 127 void setText(const QString & text); 128 QString text() const; 129 130 void setTextAlignment( Qt::Alignment ); 131 Qt::Alignment textAlignment() const; 132 133 /** 134 \brief Use this to specify the text attributes to be used for this item. 135 136 \sa textAttributes 137 */ 138 void setTextAttributes( const TextAttributes& a ); 139 140 /** 141 Returns the text attributes to be used for this item. 142 143 \sa setTextAttributes 144 */ 145 TextAttributes textAttributes() const; 146 147 /** pure virtual in QLayoutItem */ 148 bool isEmpty() const override; 149 /** pure virtual in QLayoutItem */ 150 Qt::Orientations expandingDirections() const override; 151 /** pure virtual in QLayoutItem */ 152 QSize maximumSize() const override; 153 /** pure virtual in QLayoutItem */ 154 QSize minimumSize() const override; 155 /** pure virtual in QLayoutItem */ 156 QSize sizeHint() const override; 157 /** pure virtual in QLayoutItem */ 158 void setGeometry( const QRect& r ) override; 159 /** pure virtual in QLayoutItem */ 160 QRect geometry() const override; 161 162 virtual int marginWidth() const; 163 164 virtual QSize sizeHintUnrotated() const; 165 166 virtual bool intersects( const TextLayoutItem& other, const QPointF& myPos, const QPointF& otherPos ) const; 167 virtual bool intersects( const TextLayoutItem& other, const QPoint& myPos, const QPoint& otherPos ) const; 168 169 virtual qreal realFontSize() const; 170 virtual QFont realFont() const; 171 172 void paint( QPainter* ) override; 173 174 QPolygon boundingPolygon() const; 175 private: 176 bool maybeUpdateRealFont() const; 177 QSize unrotatedSizeHint( const QFont& fnt = QFont() ) const; 178 QSize unrotatedTextSize( QFont fnt = QFont() ) const; 179 QSize calcSizeHint( const QFont& font ) const; 180 int marginWidth( const QSize& textSize ) const; 181 182 qreal fitFontSizeToGeometry() const; 183 184 QRect mRect; 185 QString mText; 186 Qt::Alignment mTextAlignment; 187 TextAttributes mAttributes; 188 const QObject* mAutoReferenceArea; 189 KChartEnums::MeasureOrientation mAutoReferenceOrientation; 190 mutable QSize cachedSizeHint; 191 mutable QPolygon mCachedBoundingPolygon; 192 mutable qreal cachedFontSize; 193 mutable QFont cachedFont; 194 }; 195 196 class KCHART_EXPORT TextBubbleLayoutItem : public AbstractLayoutItem 197 { 198 public: 199 TextBubbleLayoutItem(); 200 TextBubbleLayoutItem( const QString& text, 201 const TextAttributes& attributes, 202 const QObject* autoReferenceArea, 203 KChartEnums::MeasureOrientation autoReferenceOrientation, 204 Qt::Alignment alignment = Qt::Alignment() ); 205 206 ~TextBubbleLayoutItem(); 207 208 void setAutoReferenceArea( const QObject* area ); 209 const QObject* autoReferenceArea() const; 210 211 void setText(const QString & text); 212 QString text() const; 213 214 void setTextAttributes( const TextAttributes& a ); 215 TextAttributes textAttributes() const; 216 217 /** pure virtual in QLayoutItem */ 218 bool isEmpty() const override; 219 /** pure virtual in QLayoutItem */ 220 Qt::Orientations expandingDirections() const override; 221 /** pure virtual in QLayoutItem */ 222 QSize maximumSize() const override; 223 /** pure virtual in QLayoutItem */ 224 QSize minimumSize() const override; 225 /** pure virtual in QLayoutItem */ 226 QSize sizeHint() const override; 227 /** pure virtual in QLayoutItem */ 228 void setGeometry( const QRect& r ) override; 229 /** pure virtual in QLayoutItem */ 230 QRect geometry() const override; 231 232 void paint( QPainter* painter ) override; 233 234 protected: 235 int borderWidth() const; 236 237 private: 238 TextLayoutItem* const m_text; 239 }; 240 241 /** 242 * Layout item showing a data point marker 243 * \internal 244 */ 245 class KCHART_EXPORT MarkerLayoutItem : public AbstractLayoutItem 246 { 247 public: 248 MarkerLayoutItem( AbstractDiagram* diagram, 249 const MarkerAttributes& marker, 250 const QBrush& brush, 251 const QPen& pen, 252 Qt::Alignment alignment = Qt::Alignment() ); 253 254 Qt::Orientations expandingDirections() const override; 255 QRect geometry() const override; 256 bool isEmpty() const override; 257 QSize maximumSize() const override; 258 QSize minimumSize() const override; 259 void setGeometry( const QRect& r ) override; 260 QSize sizeHint() const override; 261 262 void paint( QPainter* ) override; 263 264 static void paintIntoRect( 265 QPainter* painter, 266 const QRect& rect, 267 AbstractDiagram* diagram, 268 const MarkerAttributes& marker, 269 const QBrush& brush, 270 const QPen& pen ); 271 272 private: 273 AbstractDiagram* mDiagram; 274 QRect mRect; 275 MarkerAttributes mMarker; 276 QBrush mBrush; 277 QPen mPen; 278 }; 279 280 /** 281 * Layout item showing a coloured line 282 * \internal 283 */ 284 class KCHART_EXPORT LineLayoutItem : public AbstractLayoutItem 285 { 286 public: 287 LineLayoutItem( AbstractDiagram* diagram, 288 int length, 289 const QPen& pen, 290 Qt::Alignment mLegendLineSymbolAlignment, 291 Qt::Alignment alignment = Qt::Alignment() ); 292 293 Qt::Orientations expandingDirections() const override; 294 QRect geometry() const override; 295 bool isEmpty() const override; 296 QSize maximumSize() const override; 297 QSize minimumSize() const override; 298 void setGeometry( const QRect& r ) override; 299 QSize sizeHint() const override; 300 301 void setLegendLineSymbolAlignment(Qt::Alignment legendLineSymbolAlignment); 302 virtual Qt::Alignment legendLineSymbolAlignment() const; 303 304 void paint( QPainter* ) override; 305 306 static void paintIntoRect( 307 QPainter* painter, 308 const QRect& rect, 309 const QPen& pen, 310 Qt::Alignment lineAlignment); 311 312 private: 313 AbstractDiagram* mDiagram; //TODO: not used. remove it 314 int mLength; 315 QPen mPen; 316 QRect mRect; 317 Qt::Alignment mLegendLineSymbolAlignment; 318 }; 319 320 /** 321 * Layout item showing a coloured line and a data point marker 322 * \internal 323 */ 324 class KCHART_EXPORT LineWithMarkerLayoutItem : public AbstractLayoutItem 325 { 326 public: 327 LineWithMarkerLayoutItem( AbstractDiagram* diagram, 328 int lineLength, 329 const QPen& linePen, 330 int markerOffs, 331 const MarkerAttributes& marker, 332 const QBrush& markerBrush, 333 const QPen& markerPen, 334 Qt::Alignment alignment = Qt::Alignment() ); 335 336 Qt::Orientations expandingDirections() const override; 337 QRect geometry() const override; 338 bool isEmpty() const override; 339 QSize maximumSize() const override; 340 QSize minimumSize() const override; 341 void setGeometry( const QRect& r ) override; 342 QSize sizeHint() const override; 343 344 void paint( QPainter* ) override; 345 346 private: 347 AbstractDiagram* mDiagram; 348 QRect mRect; 349 int mLineLength; 350 QPen mLinePen; 351 int mMarkerOffs; 352 MarkerAttributes mMarker; 353 QBrush mMarkerBrush; 354 QPen mMarkerPen; 355 }; 356 357 358 /** 359 * Layout item showing a horizontal line 360 * \internal 361 */ 362 class KCHART_EXPORT HorizontalLineLayoutItem : public AbstractLayoutItem 363 { 364 public: 365 HorizontalLineLayoutItem(); 366 367 Qt::Orientations expandingDirections() const override; 368 QRect geometry() const override; 369 bool isEmpty() const override; 370 QSize maximumSize() const override; 371 QSize minimumSize() const override; 372 void setGeometry( const QRect& r ) override; 373 QSize sizeHint() const override; 374 375 void paint( QPainter* ) override; 376 377 private: 378 QRect mRect; 379 }; 380 381 /** 382 * Layout item showing a vertial line 383 * \internal 384 */ 385 class KCHART_EXPORT VerticalLineLayoutItem : public AbstractLayoutItem 386 { 387 public: 388 VerticalLineLayoutItem(); 389 390 Qt::Orientations expandingDirections() const override; 391 QRect geometry() const override; 392 bool isEmpty() const override; 393 QSize maximumSize() const override; 394 QSize minimumSize() const override; 395 void setGeometry( const QRect& r ) override; 396 QSize sizeHint() const override; 397 398 void paint( QPainter* ) override; 399 400 private: 401 QRect mRect; 402 }; 403 404 /** 405 * @brief An empty layout item 406 * \internal 407 * 408 * The AutoSpacerLayoutItem is automatically put into each corner cell of 409 * the planeLayout grid: one of its reference-layouts is a QVBoxLayout (for 410 * the top, or bottom axes resp.), the other one is a QHBoxLayout (for the 411 * left/right sided axes). 412 * 413 * The spacer reserves enough space so all of the AbstractAreas contained 414 * in the two reference-layouts can display not only their in-bounds 415 * content but also their overlapping content reaching out of their area. 416 * 417 * KChart's layouting is applying this schema: 418 \verbatim 419 +------------------+-------------------------+-----------------+ 420 | +--------------+ | +---------------------+ | +-------------+ | 421 | | | | | QVBoxLayout for | | | | | 422 | | AUTO | | | the top axis/axes | | | AUTO | | 423 | | SPACER | | +---------------------+ | | SPACER | | 424 | | ITEM | | | | | | ITEM | | 425 | | | | | | | | | | 426 | +--------------+ | +---------------------+ | +-------------+ | 427 +------------------+-------------------------+-----------------+ 428 | +--------+-----+ | +---------------------+ | +-------+-----+ | 429 | | | | | | | | | | | | 430 | | | | | | | | | | | | 431 | | QHBox- | | | | | | | Right | | | 432 | | Layout | | | | | | | | | | 433 | | | | | | | | | axes | | | 434 | | for | | | | | | | | | | 435 | | | | | | | | | layout| | | 436 | | the | | | | DIAGRAM(s) | | | | | | 437 | | | | | | | | | | | | 438 | | left | | | | | | | | | | 439 | | | | | | | | | | | | 440 | | axis | | | | | | | | | | 441 | | or | | | | | | | | | | 442 | | axes | | | | | | | | | | 443 | | | | | | | | | | | | 444 | +--------+-----+ | +---------------------+ | +-------+-----+ | 445 +------------------+-------------------------+-----------------+ 446 | +--------------+ | +---------------------+ | +-------------+ | 447 | | | | | QVBoxLayout for | | | | | 448 | | AUTO | | | the bottom axes | | | AUTO | | 449 | | SPACER | | +---------------------+ | | SPACER | | 450 | | ITEM | | | | | | ITEM | | 451 | | | | | | | | | | 452 | +--------------+ | +---------------------+ | +-------------+ | 453 +------------------+-------------------------+-----------------+ 454 \endverbatim 455 * 456 * A typical use case is an Abscissa axis with long labels: 457 \verbatim 458 2 -| 459 | 460 1 -| 461 | 462 0 -+------------------------------------ 463 | | | | | 464 Monday Tuesday Wednesday Thursday Friday 465 \endverbatim 466 * The last letters of the word "Friday" would have been 467 * cut off in previous versions of KChart - that is 468 * if you did not call KChart::Chart::setGlobalLeading(). 469 * 470 * Now the word will be shown completely because there 471 * is an auto-spacer-item taking care for the additional 472 * space needed in the lower/right corner. 473 */ 474 class KCHART_EXPORT AutoSpacerLayoutItem : public AbstractLayoutItem 475 { 476 public: 477 AutoSpacerLayoutItem( 478 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout, 479 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout ); 480 481 Qt::Orientations expandingDirections() const override; 482 QRect geometry() const override; 483 bool isEmpty() const override; 484 QSize maximumSize() const override; 485 QSize minimumSize() const override; 486 void setGeometry( const QRect& r ) override; 487 QSize sizeHint() const override; 488 489 void paint( QPainter* ) override; 490 491 private: 492 QRect mRect; 493 bool mLayoutIsAtTopPosition; 494 QHBoxLayout *mRightLeftLayout; 495 bool mLayoutIsAtLeftPosition; 496 QVBoxLayout *mTopBottomLayout; 497 498 mutable QBrush mCommonBrush; 499 mutable QSize mCachedSize; 500 }; 501 502 } 503 504 #endif /* KCHARTLAYOUTITEMS_H */ 505