File indexing completed on 2024-05-12 04:20:34

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef KCHARTLAYOUTITEMS_H
0010 #define KCHARTLAYOUTITEMS_H
0011 
0012 #include <QBrush>
0013 #include <QFont>
0014 #include <QFontMetricsF>
0015 #include <QLayout>
0016 #include <QLayoutItem>
0017 #include <QPen>
0018 
0019 #include "KChartTextAttributes.h"
0020 #include "KChartMarkerAttributes.h"
0021 
0022 QT_BEGIN_NAMESPACE
0023 class QPainter;
0024 class KTextDocument;
0025 QT_END_NAMESPACE
0026 
0027 // TODO remove
0028 QRectF rotatedRect( const QRectF& pt, qreal rotation );
0029 
0030 namespace KChart {
0031     class AbstractDiagram;
0032     class PaintContext;
0033 
0034     /**
0035      * Base class for all layout items of KChart
0036      * \internal
0037      */
0038     class KCHART_EXPORT AbstractLayoutItem : public QLayoutItem
0039     {
0040     public:
0041         AbstractLayoutItem( Qt::Alignment itemAlignment = Qt::Alignment() ) :
0042             QLayoutItem( itemAlignment ),
0043             mParent( nullptr ),
0044             mParentLayout( nullptr ) {}
0045 
0046         /**
0047          * Default impl: just call paint.
0048          *
0049          * Derived classes like KChart::AbstractArea are providing
0050          * additional action here.
0051          */
0052         virtual void paintAll( QPainter& painter );
0053 
0054         virtual void paint( QPainter* ) = 0;
0055 
0056 
0057         /**
0058           * Default impl: Paint the complete item using its layouted position and size.
0059           */
0060         virtual void paintCtx( PaintContext* context );
0061 
0062         /**
0063             Inform the item about its widget: This enables the item,
0064             to trigger that widget's update, whenever the size of the item's
0065             contents has changed.
0066 
0067             Thus, you need to call setParentWidget on every item, that
0068             has a non-fixed size.
0069           */
0070         virtual void setParentWidget( QWidget* widget );
0071 
0072         /**
0073             Report changed size hint: ask the parent widget to recalculate the layout.
0074           */
0075         virtual void sizeHintChanged() const;
0076 
0077         void setParentLayout( QLayout* lay )
0078         {
0079             mParentLayout = lay;
0080         }
0081         QLayout* parentLayout()
0082         {
0083             return mParentLayout;
0084         }
0085         void removeFromParentLayout()
0086         {
0087             if ( mParentLayout ) {
0088                 if ( widget() )
0089                     mParentLayout->removeWidget( widget() );
0090                 else
0091                     mParentLayout->removeItem( this );
0092             }
0093         }
0094     protected:
0095         QWidget* mParent;
0096         QLayout* mParentLayout;
0097     };
0098 
0099     /**
0100      * Layout item showing a text
0101      *\internal
0102      */
0103     class KCHART_EXPORT TextLayoutItem : public AbstractLayoutItem
0104     {
0105     public:
0106         TextLayoutItem();
0107         TextLayoutItem( const QString& text,
0108                         const TextAttributes& attributes,
0109                         const QObject* autoReferenceArea,
0110                         KChartEnums::MeasureOrientation autoReferenceOrientation,
0111                         Qt::Alignment alignment = Qt::Alignment() );
0112 
0113         void setAutoReferenceArea( const QObject* area );
0114         const QObject* autoReferenceArea() const;
0115 
0116         void setText(const QString & text);
0117         QString text() const;
0118 
0119         void setTextAlignment( Qt::Alignment );
0120         Qt::Alignment textAlignment() const;
0121 
0122         /**
0123           \brief Use this to specify the text attributes to be used for this item.
0124 
0125           \sa textAttributes
0126         */
0127         void setTextAttributes( const TextAttributes& a );
0128 
0129         /**
0130           Returns the text attributes to be used for this item.
0131 
0132           \sa setTextAttributes
0133         */
0134         TextAttributes textAttributes() const;
0135 
0136         /** pure virtual in QLayoutItem */
0137         bool isEmpty() const override;
0138         /** pure virtual in QLayoutItem */
0139         Qt::Orientations expandingDirections() const override;
0140         /** pure virtual in QLayoutItem */
0141         QSize maximumSize() const override;
0142         /** pure virtual in QLayoutItem */
0143         QSize minimumSize() const override;
0144         /** pure virtual in QLayoutItem */
0145         QSize sizeHint() const override;
0146         /** pure virtual in QLayoutItem */
0147         void setGeometry( const QRect& r ) override;
0148         /** pure virtual in QLayoutItem */
0149         QRect geometry() const override;
0150 
0151         virtual int marginWidth() const;
0152 
0153         virtual QSize sizeHintUnrotated() const;
0154 
0155         virtual bool intersects( const TextLayoutItem& other, const QPointF& myPos, const QPointF& otherPos ) const;
0156         virtual bool intersects( const TextLayoutItem& other, const QPoint& myPos, const QPoint& otherPos ) const;
0157 
0158         virtual qreal realFontSize() const;
0159         virtual QFont realFont() const;
0160 
0161         void paint( QPainter* ) override;
0162 
0163         QPolygon boundingPolygon() const;
0164     private:
0165         bool maybeUpdateRealFont() const;
0166         QSize unrotatedSizeHint( const QFont& fnt = QFont() ) const;
0167         QSize unrotatedTextSize( QFont fnt = QFont() ) const;
0168         QSize calcSizeHint( const QFont& font ) const;
0169         int marginWidth( const QSize& textSize ) const;
0170 
0171         qreal fitFontSizeToGeometry() const;
0172 
0173         QRect mRect;
0174         QString mText;
0175         Qt::Alignment mTextAlignment;
0176         TextAttributes mAttributes;
0177         const QObject* mAutoReferenceArea;
0178         KChartEnums::MeasureOrientation mAutoReferenceOrientation;
0179         mutable QSize cachedSizeHint;
0180         mutable QPolygon mCachedBoundingPolygon;
0181         mutable qreal cachedFontSize;
0182         mutable QFont cachedFont;
0183     };
0184 
0185     class KCHART_EXPORT TextBubbleLayoutItem : public AbstractLayoutItem
0186     {
0187     public:
0188         TextBubbleLayoutItem();
0189         TextBubbleLayoutItem( const QString& text,
0190                               const TextAttributes& attributes,
0191                               const QObject* autoReferenceArea,
0192                               KChartEnums::MeasureOrientation autoReferenceOrientation,
0193                               Qt::Alignment alignment = Qt::Alignment() );
0194 
0195         ~TextBubbleLayoutItem() override;
0196 
0197         void setAutoReferenceArea( const QObject* area );
0198         const QObject* autoReferenceArea() const;
0199 
0200         void setText(const QString & text);
0201         QString text() const;
0202 
0203         void setTextAttributes( const TextAttributes& a );
0204         TextAttributes textAttributes() const;
0205 
0206         /** pure virtual in QLayoutItem */
0207         bool isEmpty() const override;
0208         /** pure virtual in QLayoutItem */
0209         Qt::Orientations expandingDirections() const override;
0210         /** pure virtual in QLayoutItem */
0211         QSize maximumSize() const override;
0212         /** pure virtual in QLayoutItem */
0213         QSize minimumSize() const override;
0214         /** pure virtual in QLayoutItem */
0215         QSize sizeHint() const override;
0216         /** pure virtual in QLayoutItem */
0217         void setGeometry( const QRect& r ) override;
0218         /** pure virtual in QLayoutItem */
0219         QRect geometry() const override;
0220 
0221         void paint( QPainter* painter ) override;
0222 
0223     protected:
0224         int borderWidth() const;
0225 
0226     private:
0227         TextLayoutItem* const m_text;
0228     };
0229 
0230     /**
0231      * Layout item showing a data point marker
0232      * \internal
0233      */
0234     class KCHART_EXPORT MarkerLayoutItem : public AbstractLayoutItem
0235     {
0236         public:
0237             MarkerLayoutItem( AbstractDiagram* diagram,
0238                               const MarkerAttributes& marker,
0239                               const QBrush& brush,
0240                               const QPen& pen,
0241                               Qt::Alignment alignment = Qt::Alignment() );
0242 
0243             Qt::Orientations expandingDirections() const override;
0244             QRect geometry() const override;
0245             bool isEmpty() const override;
0246             QSize maximumSize() const override;
0247             QSize minimumSize() const override;
0248             void setGeometry( const QRect& r ) override;
0249             QSize sizeHint() const override;
0250 
0251             void paint( QPainter* ) override;
0252 
0253             static void paintIntoRect(
0254                     QPainter* painter,
0255                     const QRect& rect,
0256                     AbstractDiagram* diagram,
0257                     const MarkerAttributes& marker,
0258                     const QBrush& brush,
0259                     const QPen& pen );
0260 
0261         private:
0262             AbstractDiagram* mDiagram;
0263             QRect mRect;
0264             MarkerAttributes mMarker;
0265             QBrush mBrush;
0266             QPen mPen;
0267     };
0268 
0269     /**
0270      * Layout item showing a coloured line
0271      * \internal
0272      */
0273     class KCHART_EXPORT LineLayoutItem : public AbstractLayoutItem
0274     {
0275         public:
0276             LineLayoutItem( AbstractDiagram* diagram,
0277                             int length,
0278                             const QPen& pen,
0279                             Qt::Alignment mLegendLineSymbolAlignment,
0280                             Qt::Alignment alignment = Qt::Alignment() );
0281 
0282             Qt::Orientations expandingDirections() const override;
0283             QRect geometry() const override;
0284             bool isEmpty() const override;
0285             QSize maximumSize() const override;
0286             QSize minimumSize() const override;
0287             void setGeometry( const QRect& r ) override;
0288             QSize sizeHint() const override;
0289 
0290             void setLegendLineSymbolAlignment(Qt::Alignment legendLineSymbolAlignment);
0291             virtual Qt::Alignment legendLineSymbolAlignment() const;
0292 
0293             void paint( QPainter* ) override;
0294 
0295             static void paintIntoRect(
0296                     QPainter* painter,
0297                     const QRect& rect,
0298                     const QPen& pen,
0299                     Qt::Alignment lineAlignment);
0300 
0301         private:
0302             AbstractDiagram* mDiagram;  //TODO: not used. remove it
0303             int mLength;
0304             QPen mPen;
0305             QRect mRect;
0306             Qt::Alignment mLegendLineSymbolAlignment;
0307     };
0308 
0309     /**
0310      * Layout item showing a coloured line and a data point marker
0311      * \internal
0312      */
0313     class KCHART_EXPORT LineWithMarkerLayoutItem : public AbstractLayoutItem
0314     {
0315         public:
0316             LineWithMarkerLayoutItem( AbstractDiagram* diagram,
0317                                       int lineLength,
0318                                       const QPen& linePen,
0319                                       int markerOffs,
0320                                       const MarkerAttributes& marker,
0321                                       const QBrush& markerBrush,
0322                                       const QPen& markerPen,
0323                                       Qt::Alignment alignment = Qt::Alignment() );
0324 
0325             Qt::Orientations expandingDirections() const override;
0326             QRect geometry() const override;
0327             bool isEmpty() const override;
0328             QSize maximumSize() const override;
0329             QSize minimumSize() const override;
0330             void setGeometry( const QRect& r ) override;
0331             QSize sizeHint() const override;
0332 
0333             void paint( QPainter* ) override;
0334 
0335         private:
0336             AbstractDiagram* mDiagram;
0337             QRect mRect;
0338             int mLineLength;
0339             QPen mLinePen;
0340             int mMarkerOffs;
0341             MarkerAttributes mMarker;
0342             QBrush mMarkerBrush;
0343             QPen mMarkerPen;
0344     };
0345 
0346 
0347     /**
0348      * Layout item showing a horizontal line
0349      * \internal
0350      */
0351     class KCHART_EXPORT HorizontalLineLayoutItem : public AbstractLayoutItem
0352     {
0353     public:
0354         HorizontalLineLayoutItem();
0355 
0356         Qt::Orientations expandingDirections() const override;
0357         QRect geometry() const override;
0358         bool isEmpty() const override;
0359         QSize maximumSize() const override;
0360         QSize minimumSize() const override;
0361         void setGeometry( const QRect& r ) override;
0362         QSize sizeHint() const override;
0363 
0364         void paint( QPainter* ) override;
0365 
0366     private:
0367         QRect mRect;
0368     };
0369 
0370     /**
0371      * Layout item showing a vertical line
0372      * \internal
0373      */
0374     class KCHART_EXPORT VerticalLineLayoutItem : public AbstractLayoutItem
0375     {
0376         public:
0377             VerticalLineLayoutItem();
0378 
0379             Qt::Orientations expandingDirections() const override;
0380             QRect geometry() const override;
0381             bool isEmpty() const override;
0382             QSize maximumSize() const override;
0383             QSize minimumSize() const override;
0384             void setGeometry( const QRect& r ) override;
0385             QSize sizeHint() const override;
0386 
0387             void paint( QPainter* ) override;
0388 
0389         private:
0390             QRect mRect;
0391     };
0392 
0393     /**
0394      * @brief An empty layout item
0395      * \internal
0396      *
0397      * The AutoSpacerLayoutItem is automatically put into each corner cell of
0398      * the planeLayout grid: one of its reference-layouts is a QVBoxLayout (for
0399      * the top, or bottom axes resp.), the other one is a QHBoxLayout (for the
0400      * left/right sided axes).
0401      *
0402      * The spacer reserves enough space so all of the AbstractAreas contained
0403      * in the two reference-layouts can display not only their in-bounds
0404      * content but also their overlapping content reaching out of their area.
0405      *
0406      * KChart's layouting is applying this schema:
0407 \verbatim
0408     +------------------+-------------------------+-----------------+
0409     | +--------------+ | +---------------------+ | +-------------+ |
0410     | |              | | |  QVBoxLayout for    | | |             | |
0411     | |     AUTO     | | |  the top axis/axes  | | |    AUTO     | |
0412     | |    SPACER    | | +---------------------+ | |   SPACER    | |
0413     | |     ITEM     | | |                     | | |    ITEM     | |
0414     | |              | | |                     | | |             | |
0415     | +--------------+ | +---------------------+ | +-------------+ |
0416     +------------------+-------------------------+-----------------+
0417     | +--------+-----+ | +---------------------+ | +-------+-----+ |
0418     | |        |     | | |                     | | |       |     | |
0419     | |        |     | | |                     | | |       |     | |
0420     | | QHBox- |     | | |                     | | | Right |     | |
0421     | | Layout |     | | |                     | | |       |     | |
0422     | |        |     | | |                     | | | axes  |     | |
0423     | | for    |     | | |                     | | |       |     | |
0424     | |        |     | | |                     | | | layout|     | |
0425     | | the    |     | | |      DIAGRAM(s)     | | |       |     | |
0426     | |        |     | | |                     | | |       |     | |
0427     | | left   |     | | |                     | | |       |     | |
0428     | |        |     | | |                     | | |       |     | |
0429     | | axis   |     | | |                     | | |       |     | |
0430     | | or     |     | | |                     | | |       |     | |
0431     | | axes   |     | | |                     | | |       |     | |
0432     | |        |     | | |                     | | |       |     | |
0433     | +--------+-----+ | +---------------------+ | +-------+-----+ |
0434     +------------------+-------------------------+-----------------+
0435     | +--------------+ | +---------------------+ | +-------------+ |
0436     | |              | | |   QVBoxLayout for   | | |             | |
0437     | |    AUTO      | | |   the bottom axes   | | |    AUTO     | |
0438     | |   SPACER     | | +---------------------+ | |   SPACER    | |
0439     | |    ITEM      | | |                     | | |    ITEM     | |
0440     | |              | | |                     | | |             | |
0441     | +--------------+ | +---------------------+ | +-------------+ |
0442     +------------------+-------------------------+-----------------+
0443 \endverbatim
0444      *
0445      * A typical use case is an Abscissa axis with long labels:
0446 \verbatim
0447     2 -|
0448        |
0449     1 -|
0450        |
0451     0 -+------------------------------------
0452        |        |        |        |        |
0453     Monday  Tuesday  Wednesday Thursday Friday
0454 \endverbatim
0455      * The last letters of the word "Friday" would have been
0456      * cut off in previous versions of KChart - that is
0457      * if you did not call KChart::Chart::setGlobalLeading().
0458      *
0459      * Now the word will be shown completely because there
0460      * is an auto-spacer-item taking care for the additional
0461      * space needed in the lower/right corner.
0462      */
0463     class KCHART_EXPORT AutoSpacerLayoutItem : public AbstractLayoutItem
0464     {
0465         public:
0466             AutoSpacerLayoutItem(
0467                     bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
0468                     bool layoutIsAtLeftPosition,  QVBoxLayout *topBottomLayout );
0469 
0470             Qt::Orientations expandingDirections() const override;
0471             QRect geometry() const override;
0472             bool isEmpty() const override;
0473             QSize maximumSize() const override;
0474             QSize minimumSize() const override;
0475             void setGeometry( const QRect& r ) override;
0476             QSize sizeHint() const override;
0477 
0478             void paint( QPainter* ) override;
0479 
0480         private:
0481             QRect mRect;
0482             bool mLayoutIsAtTopPosition;
0483             QHBoxLayout *mRightLeftLayout;
0484             bool mLayoutIsAtLeftPosition;
0485             QVBoxLayout *mTopBottomLayout;
0486 
0487             mutable QBrush mCommonBrush;
0488             mutable QSize mCachedSize;
0489     };
0490 
0491 }
0492 
0493 #endif /* KCHARTLAYOUTITEMS_H */