File indexing completed on 2024-04-14 14:11:15

0001 /*
0002     SPDX-FileCopyrightText: 2011 Rafał Kułaga <rl.kulaga@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QFont>
0010 #include <QPoint>
0011 #include <QColor>
0012 
0013 class QPaintDevice;
0014 class QPointF;
0015 class QSize;
0016 
0017 class ColorScheme;
0018 class SkyMap;
0019 class SkyQPainter;
0020 
0021 /**
0022  * \class Legend
0023  * \brief Legend class is used for painting legends on class inheriting QPaintDevice.
0024  * Its methods enable changing settings of legend such as legend type (scale only/full legend),
0025  * symbol size, sizes for symbol description's bounding rectangles, symbol spacing etc.
0026  * Typical use of this class would be to create instance of Legend class, set all properties
0027  * using appropriate methods and paint it by calling paintLegend() method, passing QPaintDevice
0028  * or QPainter subclass (useful eg. with QSvgGenerator class, which can't be painted by two QPainter
0029  * classes).
0030  * \author Rafał Kułaga
0031  */
0032 class Legend
0033 {
0034   public:
0035     /**
0036           * \brief Legend type enumeration.
0037           */
0038     enum LEGEND_TYPE
0039     {
0040         LT_FULL,
0041         LT_SCALE_MAGNITUDES,
0042         LT_SCALE_ONLY,
0043         LT_MAGNITUDES_ONLY,
0044         LT_SYMBOLS_ONLY,
0045     };
0046 
0047     /**
0048           * \brief Legend orientation enumeration.
0049           */
0050     enum LEGEND_ORIENTATION
0051     {
0052         LO_HORIZONTAL,
0053         LO_VERTICAL
0054     };
0055 
0056     /**
0057           * \brief Legend position enumeration.
0058           */
0059     enum LEGEND_POSITION
0060     {
0061         LP_UPPER_LEFT,
0062         LP_UPPER_RIGHT,
0063         LP_LOWER_LEFT,
0064         LP_LOWER_RIGHT,
0065         LP_FLOATING
0066     };
0067 
0068     /**
0069           * \brief Constructor.
0070           * \param orientation Legend orientation.
0071           * \param pos Legend position.
0072          */
0073     explicit Legend(LEGEND_ORIENTATION orientation = LO_HORIZONTAL, LEGEND_POSITION pos = LP_FLOATING);
0074 
0075     /**
0076          * \brief copy constructor
0077          * \note This class needs to be explicitly copied because of the m_Painter pointer
0078          */
0079     /** @{ */
0080     explicit Legend(const Legend &o);
0081     Legend& operator=(const Legend &o) noexcept;
0082     /** @} */
0083 
0084 
0085     /**
0086           * \brief Destructor.
0087           */
0088     ~Legend();
0089 
0090     /**
0091           * \brief Get legend type.
0092           * \return Current legend type value.
0093           */
0094     inline LEGEND_TYPE getType() const { return m_Type; }
0095 
0096     /**
0097           * \brief Get legend orientation.
0098           * \return Current legend orientation value.
0099           */
0100     inline LEGEND_ORIENTATION getOrientation() const { return m_Orientation; }
0101 
0102     /**
0103           * \brief Get legend position.
0104           * \return Current legend position value.
0105           */
0106     inline LEGEND_POSITION getPosition() const { return m_Position; }
0107 
0108     /**
0109           * \brief Get position of the floating legend.
0110           * \return Current position of the floating legend.
0111           */
0112     inline QPoint getFloatingPosition() const { return m_PositionFloating; }
0113 
0114     /**
0115           * \brief Get symbol size.
0116           * \return Current symbol size value.
0117           */
0118     inline int getSymbolSize() const { return m_SymbolSize; }
0119 
0120     /**
0121           * \brief Get symbol description's bounding rectangle width.
0122           * \return Current bounding rectangle width.
0123           */
0124     inline int getBRectWidth() const { return m_BRectWidth; }
0125 
0126     /**
0127           * \brief Get symbol description's bounding rectangle height.
0128           * \return Current bounding rectangle height.
0129           */
0130     inline int getBRectHeight() const { return m_BRectHeight; }
0131 
0132     /**
0133           * \brief Get maximal horizontal scale size in pixels.
0134           * \return Current maximal horizontal scale size in pixels.
0135           */
0136     inline int getMaxHScalePixels() const { return m_MaxHScalePixels; }
0137 
0138     /**
0139           * \brief Get maximal vertical scale size in pixels.
0140           * \brief Current maximal vertical scale size in pixels.
0141           */
0142     inline int getMaxVScalePixels() const { return m_MaxVScalePixels; }
0143 
0144     /**
0145           * \brief Get symbol image X spacing.
0146           * \return Current symbol image X spacing.
0147           */
0148     inline int getXSymbolSpacing() const { return m_XSymbolSpacing; }
0149 
0150     /**
0151           * \brief Get symbol image Y spacing.
0152           * \return Current symbol image Y spacing.
0153           */
0154     inline int getYSymbolSpacing() const { return m_YSymbolSpacing; }
0155 
0156     /**
0157           * \brief Get font.
0158           * \return Current font.
0159           */
0160     inline QFont getFont() const { return m_Font; }
0161 
0162     /**
0163           * \brief Get background color.
0164           * \return Current background color.
0165           */
0166     inline QColor getBgColor() const { return m_BgColor; }
0167 
0168     /**
0169           * \brief Check if frame around legend is drawn.
0170           * \return True if frame is drawn.
0171           */
0172     inline bool getDrawFrame() const { return m_DrawFrame; }
0173 
0174     /**
0175           * \brief Set legend type.
0176           * \param type New legend type.
0177           */
0178     inline void setType(LEGEND_TYPE type) { m_Type = type; }
0179 
0180     /**
0181           * \brief Set legend orientation.
0182           * \param orientation New legend orientation.
0183           */
0184     inline void setOrientation(LEGEND_ORIENTATION orientation) { m_Orientation = orientation; }
0185 
0186     /**
0187           * \brief Set legend position.
0188           * \param pos New legend position enumeration value.
0189           */
0190     inline void setPosition(LEGEND_POSITION pos) { m_Position = pos; }
0191 
0192     /**
0193           * \brief Set floating legend position.
0194           * \param pos New floating legend position.
0195           */
0196     inline void setFloatingPosition(QPoint pos) { m_PositionFloating = pos; }
0197 
0198     /**
0199           * \brief Set symbol size.
0200           * \param size New symbol size.
0201           */
0202     inline void setSymbolSize(int size) { m_SymbolSize = size; }
0203 
0204     /**
0205           * \brief Set symbol description's bounding rectangle width.
0206           * \param width New bounding rectangle width.
0207           */
0208     inline void setBRectWidth(int width) { m_BRectWidth = width; }
0209 
0210     /**
0211           * \brief Set symbol description's bounding rectangle height.
0212           * \param height New bounding rectangle height.
0213           */
0214     inline void setBRectHeight(int height) { m_BRectHeight = height; }
0215 
0216     /**
0217           * \brief Set maximal horizontal scale size in pixels.
0218           * \param pixels New maximal horizontal scale size in pixels.
0219           */
0220     inline void setMaxHScalePixels(int pixels) { m_MaxHScalePixels = pixels; }
0221 
0222     /**
0223           * \brief Set maximal vertical scale size in pixels.
0224           * \param pixels New maximal vertical scale size in pixels.
0225           */
0226     inline void setMaxVScalePixels(int pixels) { m_MaxVScalePixels = pixels; }
0227 
0228     /**
0229           * \brief Set symbol X spacing in pixels.
0230           * \param spacing New symbol X spacing in pixels.
0231           */
0232     inline void setXSymbolSpacing(int spacing) { m_XSymbolSpacing = spacing; }
0233 
0234     /**
0235           * \brief Set symbol Y spacing in pixels.
0236           * \param spacing New symbol Y spacing in pixels.
0237           */
0238     inline void setYSymbolSpacing(int spacing) { m_YSymbolSpacing = spacing; }
0239 
0240     /**
0241           * \brief Set font.
0242           * \param font New font.
0243           */
0244     inline void setFont(const QFont &font) { m_Font = font; }
0245 
0246     /**
0247           * \brief Set background color.
0248           * \param color New background color.
0249           */
0250     inline void setBgColor(const QColor &color) { m_BgColor = color; }
0251 
0252     /**
0253           * \brief Set if frame is drawn.
0254           * \param draw True if frame should be drawn.
0255           */
0256     inline void setDrawFrame(bool draw) { m_DrawFrame = draw; }
0257 
0258     /**
0259           * \brief Calculates size of legend that will be painted using current settings.
0260           * \return Size of legend.
0261           */
0262     QSize calculateSize();
0263 
0264     /**
0265           * \brief Paint legend on passed QPaintDevice at selected position.
0266           * \param pd QPaintDevice on which legend will be painted.
0267           */
0268     void paintLegend(QPaintDevice *pd);
0269 
0270     /**
0271           * \brief Paint legend using passed SkyQPainter.
0272           * This method is used to enable painting on QPaintDevice subclasses that can't be
0273           * painted by multiple QPainter subclasses (e.g. QSvgGenerator).
0274           * \param painter that will be used to paint legend.
0275           * \note Passed SkyQPainter should be already set up to paint at specific QPaintDevice
0276           * subclass and should be initialized by its begin() method. After legend is painted, SkyQPainter
0277           * instance _will not_ be finished, so it's necessary to call end() method manually.
0278           */
0279     void paintLegend(SkyQPainter *painter);
0280 
0281     /**
0282           * \brief Paint legend on passed QPaintDevice at selected position.
0283           * \param pd QPaintDevice on which legend will be painted.
0284           * \param type the legend type.
0285           * \param pos LEGEND_POSITION enum value.
0286           */
0287     void paintLegend(QPaintDevice *pd, LEGEND_TYPE type, LEGEND_POSITION pos);
0288 
0289     /**
0290           * \brief Paint legend using passed SkyQPainter.
0291           * This method is used to enable painting on QPaintDevice subclasses that can't be painted
0292           * by multiple QPainter subclasses (eg. QSvgGenerator).
0293           * \param painter that will be used to paint legend.
0294           * \param type the legend type.
0295           * \param pos LEGEND_POSITION enum value.
0296           * \note Passed SkyQPainter should be already set up to paint at specific QPaintDevice
0297           * subclass and should be initialized by its begin() method. After legend is painted, SkyQPainter
0298           * instance _will not_ be finished, so it's necessary to call end() method manually.
0299           */
0300     void paintLegend(SkyQPainter *painter, LEGEND_TYPE type, LEGEND_POSITION pos);
0301 
0302   private:
0303     /**
0304           * \brief Paint all symbols at passed position.
0305           * \param pos position at which symbols will be painted (upper left corner).
0306           * \note Orientation of the symbols group is determined by current legend orientation.
0307           */
0308     void paintSymbols(QPointF pos);
0309 
0310     /**
0311           * \brief Paint single symbol with specified parameters.
0312           * \param pos position at which symbol will be painted (center).
0313           * \param type symbol type (see SkyQPainter class for symbol types list).
0314           * \param e e parameter of symbol.
0315           * \param angle angle of symbol (in degrees).
0316           * \param label symbol label.
0317           */
0318     void paintSymbol(QPointF pos, int type, float e, float angle, QString label);
0319 
0320     /**
0321           * \brief Paint 'Star Magnitudes' group at passed position.
0322           * \param pos position at which 'Star Magnitudes' group will be painted (upper left corner).
0323           */
0324     void paintMagnitudes(QPointF pos);
0325 
0326     /**
0327           * \brief Paint chart scale bar at passed position.
0328           * \param pos position at which chart scale bar will be painted.
0329           * \note Orientation of chart scale bar is determined by current legend orientation. Maximal
0330           * bar size is determined by current values set by setMaxHScalePixels()/setMaxVScalePixels() method.
0331           * Exact size is adjusted to full deg/min/sec.
0332           */
0333     void paintScale(QPointF pos);
0334 
0335     /**
0336           * \brief Calculates legend position (upper left corner) based on LEGEND_POSITION enum value, paint device size and calculated legend size.
0337           * \param pos LEGEND_POSITION enum value.
0338           */
0339     QPoint positionToDeviceCoord(QPaintDevice *pd);
0340 
0341     SkyQPainter *m_Painter { nullptr };
0342     SkyMap *m_SkyMap { nullptr };
0343     bool m_DeletePainter { false };
0344 
0345     LEGEND_TYPE m_Type { LT_FULL };
0346     LEGEND_ORIENTATION m_Orientation;
0347     LEGEND_POSITION m_Position;
0348     QPoint m_PositionFloating;
0349 
0350     ColorScheme *m_cScheme { nullptr };
0351     QFont m_Font;
0352     QColor m_BgColor;
0353     bool m_DrawFrame { false };
0354 
0355     int m_SymbolSize { 0 };
0356     int m_BRectWidth { 0 };
0357     int m_BRectHeight { 0 };
0358     int m_MaxHScalePixels { 0 };
0359     int m_MaxVScalePixels { 0 };
0360     int m_XSymbolSpacing { 0 };
0361     int m_YSymbolSpacing { 0 };
0362 };