1 /*
2     SPDX-FileCopyrightText: 2011 Rafał Kułaga <rl.kulaga@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include <QFont>
10 #include <QPoint>
11 #include <QColor>
12 
13 class QPaintDevice;
14 class QPointF;
15 class QSize;
16 
17 class ColorScheme;
18 class SkyMap;
19 class SkyQPainter;
20 
21 /**
22  * \class Legend
23  * \brief Legend class is used for painting legends on class inheriting QPaintDevice.
24  * Its methods enable changing settings of legend such as legend type (scale only/full legend),
25  * symbol size, sizes for symbol description's bounding rectangles, symbol spacing etc.
26  * Typical use of this class would be to create instance of Legend class, set all properties
27  * using appropriate methods and paint it by calling paintLegend() method, passing QPaintDevice
28  * or QPainter subclass (useful eg. with QSvgGenerator class, which can't be painted by two QPainter
29  * classes).
30  * \author Rafał Kułaga
31  */
32 class Legend
33 {
34   public:
35     /**
36           * \brief Legend type enumeration.
37           */
38     enum LEGEND_TYPE
39     {
40         LT_FULL,
41         LT_SCALE_MAGNITUDES,
42         LT_SCALE_ONLY,
43         LT_MAGNITUDES_ONLY,
44         LT_SYMBOLS_ONLY,
45     };
46 
47     /**
48           * \brief Legend orientation enumeration.
49           */
50     enum LEGEND_ORIENTATION
51     {
52         LO_HORIZONTAL,
53         LO_VERTICAL
54     };
55 
56     /**
57           * \brief Legend position enumeration.
58           */
59     enum LEGEND_POSITION
60     {
61         LP_UPPER_LEFT,
62         LP_UPPER_RIGHT,
63         LP_LOWER_LEFT,
64         LP_LOWER_RIGHT,
65         LP_FLOATING
66     };
67 
68     /**
69           * \brief Constructor.
70           * \param orientation Legend orientation.
71           * \param pos Legend position.
72          */
73     explicit Legend(LEGEND_ORIENTATION orientation = LO_HORIZONTAL, LEGEND_POSITION pos = LP_FLOATING);
74 
75     /**
76          * \brief copy constructor
77          * \note This class needs to be explicitly copied because of the m_Painter pointer
78          */
79     /** @{ */
80     explicit Legend(const Legend &o);
81     Legend& operator=(const Legend &o) noexcept;
82     /** @} */
83 
84 
85     /**
86           * \brief Destructor.
87           */
88     ~Legend();
89 
90     /**
91           * \brief Get legend type.
92           * \return Current legend type value.
93           */
getType()94     inline LEGEND_TYPE getType() const { return m_Type; }
95 
96     /**
97           * \brief Get legend orientation.
98           * \return Current legend orientation value.
99           */
getOrientation()100     inline LEGEND_ORIENTATION getOrientation() const { return m_Orientation; }
101 
102     /**
103           * \brief Get legend position.
104           * \return Current legend position value.
105           */
getPosition()106     inline LEGEND_POSITION getPosition() const { return m_Position; }
107 
108     /**
109           * \brief Get position of the floating legend.
110           * \return Current position of the floating legend.
111           */
getFloatingPosition()112     inline QPoint getFloatingPosition() const { return m_PositionFloating; }
113 
114     /**
115           * \brief Get symbol size.
116           * \return Current symbol size value.
117           */
getSymbolSize()118     inline int getSymbolSize() const { return m_SymbolSize; }
119 
120     /**
121           * \brief Get symbol description's bounding rectangle width.
122           * \return Current bounding rectangle width.
123           */
getBRectWidth()124     inline int getBRectWidth() const { return m_BRectWidth; }
125 
126     /**
127           * \brief Get symbol description's bounding rectangle height.
128           * \return Current bounding rectangle height.
129           */
getBRectHeight()130     inline int getBRectHeight() const { return m_BRectHeight; }
131 
132     /**
133           * \brief Get maximal horizontal scale size in pixels.
134           * \return Current maximal horizontal scale size in pixels.
135           */
getMaxHScalePixels()136     inline int getMaxHScalePixels() const { return m_MaxHScalePixels; }
137 
138     /**
139           * \brief Get maximal vertical scale size in pixels.
140           * \brief Current maximal vertical scale size in pixels.
141           */
getMaxVScalePixels()142     inline int getMaxVScalePixels() const { return m_MaxVScalePixels; }
143 
144     /**
145           * \brief Get symbol image X spacing.
146           * \return Current symbol image X spacing.
147           */
getXSymbolSpacing()148     inline int getXSymbolSpacing() const { return m_XSymbolSpacing; }
149 
150     /**
151           * \brief Get symbol image Y spacing.
152           * \return Current symbol image Y spacing.
153           */
getYSymbolSpacing()154     inline int getYSymbolSpacing() const { return m_YSymbolSpacing; }
155 
156     /**
157           * \brief Get font.
158           * \return Current font.
159           */
getFont()160     inline QFont getFont() const { return m_Font; }
161 
162     /**
163           * \brief Get background color.
164           * \return Current background color.
165           */
getBgColor()166     inline QColor getBgColor() const { return m_BgColor; }
167 
168     /**
169           * \brief Check if frame around legend is drawn.
170           * \return True if frame is drawn.
171           */
getDrawFrame()172     inline bool getDrawFrame() const { return m_DrawFrame; }
173 
174     /**
175           * \brief Set legend type.
176           * \param type New legend type.
177           */
setType(LEGEND_TYPE type)178     inline void setType(LEGEND_TYPE type) { m_Type = type; }
179 
180     /**
181           * \brief Set legend orientation.
182           * \param orientation New legend orientation.
183           */
setOrientation(LEGEND_ORIENTATION orientation)184     inline void setOrientation(LEGEND_ORIENTATION orientation) { m_Orientation = orientation; }
185 
186     /**
187           * \brief Set legend position.
188           * \param pos New legend position enumeration value.
189           */
setPosition(LEGEND_POSITION pos)190     inline void setPosition(LEGEND_POSITION pos) { m_Position = pos; }
191 
192     /**
193           * \brief Set floating legend position.
194           * \param pos New floating legend position.
195           */
setFloatingPosition(QPoint pos)196     inline void setFloatingPosition(QPoint pos) { m_PositionFloating = pos; }
197 
198     /**
199           * \brief Set symbol size.
200           * \param size New symbol size.
201           */
setSymbolSize(int size)202     inline void setSymbolSize(int size) { m_SymbolSize = size; }
203 
204     /**
205           * \brief Set symbol description's bounding rectangle width.
206           * \param width New bounding rectangle width.
207           */
setBRectWidth(int width)208     inline void setBRectWidth(int width) { m_BRectWidth = width; }
209 
210     /**
211           * \brief Set symbol description's bounding rectangle height.
212           * \param height New bounding rectangle height.
213           */
setBRectHeight(int height)214     inline void setBRectHeight(int height) { m_BRectHeight = height; }
215 
216     /**
217           * \brief Set maximal horizontal scale size in pixels.
218           * \param pixels New maximal horizontal scale size in pixels.
219           */
setMaxHScalePixels(int pixels)220     inline void setMaxHScalePixels(int pixels) { m_MaxHScalePixels = pixels; }
221 
222     /**
223           * \brief Set maximal vertical scale size in pixels.
224           * \param pixels New maximal vertical scale size in pixels.
225           */
setMaxVScalePixels(int pixels)226     inline void setMaxVScalePixels(int pixels) { m_MaxVScalePixels = pixels; }
227 
228     /**
229           * \brief Set symbol X spacing in pixels.
230           * \param spacing New symbol X spacing in pixels.
231           */
setXSymbolSpacing(int spacing)232     inline void setXSymbolSpacing(int spacing) { m_XSymbolSpacing = spacing; }
233 
234     /**
235           * \brief Set symbol Y spacing in pixels.
236           * \param spacing New symbol Y spacing in pixels.
237           */
setYSymbolSpacing(int spacing)238     inline void setYSymbolSpacing(int spacing) { m_YSymbolSpacing = spacing; }
239 
240     /**
241           * \brief Set font.
242           * \param font New font.
243           */
setFont(const QFont & font)244     inline void setFont(const QFont &font) { m_Font = font; }
245 
246     /**
247           * \brief Set background color.
248           * \param color New background color.
249           */
setBgColor(const QColor & color)250     inline void setBgColor(const QColor &color) { m_BgColor = color; }
251 
252     /**
253           * \brief Set if frame is drawn.
254           * \param draw True if frame should be drawn.
255           */
setDrawFrame(bool draw)256     inline void setDrawFrame(bool draw) { m_DrawFrame = draw; }
257 
258     /**
259           * \brief Calculates size of legend that will be painted using current settings.
260           * \return Size of legend.
261           */
262     QSize calculateSize();
263 
264     /**
265           * \brief Paint legend on passed QPaintDevice at selected position.
266           * \param pd QPaintDevice on which legend will be painted.
267           */
268     void paintLegend(QPaintDevice *pd);
269 
270     /**
271           * \brief Paint legend using passed SkyQPainter.
272           * This method is used to enable painting on QPaintDevice subclasses that can't be
273           * painted by multiple QPainter subclasses (e.g. QSvgGenerator).
274           * \param painter that will be used to paint legend.
275           * \note Passed SkyQPainter should be already set up to paint at specific QPaintDevice
276           * subclass and should be initialized by its begin() method. After legend is painted, SkyQPainter
277           * instance _will not_ be finished, so it's necessary to call end() method manually.
278           */
279     void paintLegend(SkyQPainter *painter);
280 
281     /**
282           * \brief Paint legend on passed QPaintDevice at selected position.
283           * \param pd QPaintDevice on which legend will be painted.
284           * \param type the legend type.
285           * \param pos LEGEND_POSITION enum value.
286           */
287     void paintLegend(QPaintDevice *pd, LEGEND_TYPE type, LEGEND_POSITION pos);
288 
289     /**
290           * \brief Paint legend using passed SkyQPainter.
291           * This method is used to enable painting on QPaintDevice subclasses that can't be painted
292           * by multiple QPainter subclasses (eg. QSvgGenerator).
293           * \param painter that will be used to paint legend.
294           * \param type the legend type.
295           * \param pos LEGEND_POSITION enum value.
296           * \note Passed SkyQPainter should be already set up to paint at specific QPaintDevice
297           * subclass and should be initialized by its begin() method. After legend is painted, SkyQPainter
298           * instance _will not_ be finished, so it's necessary to call end() method manually.
299           */
300     void paintLegend(SkyQPainter *painter, LEGEND_TYPE type, LEGEND_POSITION pos);
301 
302   private:
303     /**
304           * \brief Paint all symbols at passed position.
305           * \param pos position at which symbols will be painted (upper left corner).
306           * \note Orientation of the symbols group is determined by current legend orientation.
307           */
308     void paintSymbols(QPointF pos);
309 
310     /**
311           * \brief Paint single symbol with specified parameters.
312           * \param pos position at which symbol will be painted (center).
313           * \param type symbol type (see SkyQPainter class for symbol types list).
314           * \param e e parameter of symbol.
315           * \param angle angle of symbol (in degrees).
316           * \param label symbol label.
317           */
318     void paintSymbol(QPointF pos, int type, float e, float angle, QString label);
319 
320     /**
321           * \brief Paint 'Star Magnitudes' group at passed position.
322           * \param pos position at which 'Star Magnitudes' group will be painted (upper left corner).
323           */
324     void paintMagnitudes(QPointF pos);
325 
326     /**
327           * \brief Paint chart scale bar at passed position.
328           * \param pos position at which chart scale bar will be painted.
329           * \note Orientation of chart scale bar is determined by current legend orientation. Maximal
330           * bar size is determined by current values set by setMaxHScalePixels()/setMaxVScalePixels() method.
331           * Exact size is adjusted to full deg/min/sec.
332           */
333     void paintScale(QPointF pos);
334 
335     /**
336           * \brief Calculates legend position (upper left corner) based on LEGEND_POSITION enum value, paint device size and calculated legend size.
337           * \param pos LEGEND_POSITION enum value.
338           */
339     QPoint positionToDeviceCoord(QPaintDevice *pd);
340 
341     SkyQPainter *m_Painter { nullptr };
342     SkyMap *m_SkyMap { nullptr };
343     bool m_DeletePainter { false };
344 
345     LEGEND_TYPE m_Type { LT_FULL };
346     LEGEND_ORIENTATION m_Orientation;
347     LEGEND_POSITION m_Position;
348     QPoint m_PositionFloating;
349 
350     ColorScheme *m_cScheme { nullptr };
351     QFont m_Font;
352     QColor m_BgColor;
353     bool m_DrawFrame { false };
354 
355     int m_SymbolSize { 0 };
356     int m_BRectWidth { 0 };
357     int m_BRectHeight { 0 };
358     int m_MaxHScalePixels { 0 };
359     int m_MaxVScalePixels { 0 };
360     int m_XSymbolSpacing { 0 };
361     int m_YSymbolSpacing { 0 };
362 };
363