Kstars

legend.cpp
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#include "legend.h"
8
9#include "colorscheme.h"
10#include "kstarsdata.h"
11#include "skymap.h"
12#include "skyqpainter.h"
13#include "Options.h"
14
15#include <QBrush>
16
17namespace
18{
19const int symbolSize = 15;
20const int bRectWidth = 100;
21const int bRectHeight = 45;
22const int maxHScalePixels = 200;
23const int maxVScalePixels = 100;
24const int xSymbolSpacing = 100;
25const int ySymbolSpacing = 70;
26}
27
28Legend::Legend(LEGEND_ORIENTATION orientation, LEGEND_POSITION pos)
29 : m_SkyMap(SkyMap::Instance()), m_Orientation(orientation),
30 m_Position(pos), m_PositionFloating(QPoint(0, 0)), m_cScheme(KStarsData::Instance()->colorScheme()),
31 m_SymbolSize(symbolSize), m_BRectWidth(bRectWidth), m_BRectHeight(bRectHeight),
32 m_MaxHScalePixels(maxHScalePixels), m_MaxVScalePixels(maxVScalePixels), m_XSymbolSpacing(xSymbolSpacing),
33 m_YSymbolSpacing(ySymbolSpacing)
34{
35 m_BgColor = m_cScheme->colorNamed("SkyColor");
36}
37
38Legend::~Legend()
39{
40 if (m_Painter != nullptr && m_DeletePainter)
41 {
42 delete m_Painter;
43 }
44}
45
46QSize Legend::calculateSize()
47{
48 int width = 0;
49 int height = 0;
50
51 switch (m_Orientation)
52 {
53 case LO_HORIZONTAL:
54 {
55 switch (m_Type)
56 {
57 case LT_SCALE_ONLY:
58 {
59 width = 40 + m_MaxHScalePixels;
60 height = 60;
61 break;
62 }
63
64 case LT_MAGNITUDES_ONLY:
65 {
66 width = 140;
67 height = 70;
68 break;
69 }
70
71 case LT_SYMBOLS_ONLY:
72 {
73 width = 7 * m_XSymbolSpacing;
74 height = 20 + m_SymbolSize + m_BRectHeight;
75 break;
76 }
77
78 case LT_SCALE_MAGNITUDES:
79 {
80 width = 160 + m_MaxHScalePixels;
81 height = 70;
82 break;
83 }
84
85 case LT_FULL:
86 {
87 width = 7 * m_XSymbolSpacing;
88 height = 20 + m_SymbolSize + m_BRectHeight + 70;
89 break;
90 }
91
92 default:
93 break; // should never happen
94 }
95 }
96
97 break;
98
99 case LO_VERTICAL:
100 {
101 switch (m_Type)
102 {
103 case LT_SCALE_ONLY:
104 {
105 width = 120;
106 height = 40 + m_MaxVScalePixels;
107 break;
108 }
109
110 case LT_MAGNITUDES_ONLY:
111 {
112 width = 140;
113 height = 70;
114 break;
115 }
116
117 case LT_SYMBOLS_ONLY:
118 {
119 width = 120;
120 height = 7 * m_YSymbolSpacing;
121 break;
122 }
123
124 case LT_SCALE_MAGNITUDES:
125 {
126 width = 120;
127 height = 100 + m_MaxVScalePixels;
128 break;
129 }
130
131 case LT_FULL:
132 {
133 width = 120;
134 height = 100 + 7 * m_YSymbolSpacing + m_MaxVScalePixels;
135 break;
136 }
137
138 default:
139 break; // should never happen
140 }
141
142 break;
143 }
144
145 default:
146 {
147 return QSize();
148 }
149 }
150
151 return QSize(width, height);
152}
153
154void Legend::paintLegend(QPaintDevice *pd)
155{
156 if (m_Painter)
157 {
158 delete m_Painter;
159 }
160
161 m_Painter = new SkyQPainter(m_SkyMap, pd);
162 m_DeletePainter = true;
163 m_Painter->begin();
164
165 paintLegend(m_Painter);
166
167 m_Painter->end();
168}
169
170void Legend::paintLegend(SkyQPainter *painter)
171{
172 if (!m_DeletePainter)
173 {
174 m_Painter = painter;
175 }
176
177 if (m_Position != LP_FLOATING)
178 {
179 m_PositionFloating = positionToDeviceCoord(painter->device());
180 }
181
182 m_Painter->translate(m_PositionFloating.x(), m_PositionFloating.y());
183
184 m_Painter->setFont(m_Font);
185
186 QBrush backgroundBrush(m_BgColor, Qt::SolidPattern);
187 QPen backgroundPen(m_cScheme->colorNamed("SNameColor"));
188 backgroundPen.setStyle(Qt::SolidLine);
189
190 // set brush & pen
191 m_Painter->setBrush(backgroundBrush);
192 m_Painter->setPen(backgroundPen);
193
194 QSize size = calculateSize();
195 if (m_DrawFrame)
196 {
197 m_Painter->drawRect(1, 1, size.width(), size.height());
198 }
199
200 else
201 {
202 QPen noLinePen;
203 noLinePen.setStyle(Qt::NoPen);
204
205 m_Painter->setPen(noLinePen);
206 m_Painter->drawRect(1, 1, size.width(), size.height());
207
208 m_Painter->setPen(backgroundPen);
209 }
210
211 switch (m_Orientation)
212 {
213 case LO_HORIZONTAL:
214 {
215 switch (m_Type)
216 {
217 case LT_SCALE_ONLY:
218 {
219 paintScale(QPointF(20, 20));
220 break;
221 }
222
223 case LT_MAGNITUDES_ONLY:
224 {
225 paintMagnitudes(QPointF(20, 20));
226 break;
227 }
228
229 case LT_SYMBOLS_ONLY:
230 {
231 paintSymbols(QPointF(20, 20));
232 break;
233 }
234
235 case LT_SCALE_MAGNITUDES:
236 {
237 paintMagnitudes(QPointF(20, 20));
238 paintScale(QPointF(150, 20));
239 break;
240 }
241
242 case LT_FULL:
243 {
244 paintSymbols(QPointF(20, 20));
245 paintMagnitudes(QPointF(10, 40 + m_SymbolSize + m_BRectHeight));
246 paintScale(QPointF(200, 40 + m_SymbolSize + m_BRectHeight));
247 break;
248 }
249
250 default:
251 break; // should never happen
252 }
253
254 break;
255 }
256
257 case LO_VERTICAL:
258 {
259 switch (m_Type)
260 {
261 case LT_SCALE_ONLY:
262 {
263 paintScale(QPointF(20, 20));
264 break;
265 }
266
267 case LT_MAGNITUDES_ONLY:
268 {
269 paintMagnitudes(QPointF(20, 20));
270 break;
271 }
272
273 case LT_SYMBOLS_ONLY:
274 {
275 paintSymbols(QPointF(20, 20));
276 break;
277 }
278
279 case LT_SCALE_MAGNITUDES:
280 {
281 paintMagnitudes(QPointF(7, 20));
282 paintScale(QPointF(20, 80));
283 break;
284 }
285
286 case LT_FULL:
287 {
288 paintSymbols(QPointF(30, 20));
289 paintMagnitudes(QPointF(7, 30 + 7 * m_YSymbolSpacing));
290 paintScale(QPointF(20, 90 + 7 * m_YSymbolSpacing));
291 break;
292 }
293
294 default:
295 break; // should never happen
296 }
297
298 break;
299 }
300
301 default:
302 break; // should never happen
303 }
304}
305
306void Legend::paintLegend(QPaintDevice *pd, LEGEND_TYPE type, LEGEND_POSITION pos)
307{
308 LEGEND_TYPE prevType = m_Type;
309 LEGEND_POSITION prevPos = m_Position;
310
311 m_Type = type;
312 m_Position = pos;
313
314 paintLegend(pd);
315
316 m_Type = prevType;
317 m_Position = prevPos;
318}
319
320void Legend::paintLegend(SkyQPainter *painter, LEGEND_TYPE type, LEGEND_POSITION pos)
321{
322 LEGEND_TYPE prevType = m_Type;
323 LEGEND_POSITION prevPos = m_Position;
324
325 m_Type = type;
326 m_Position = pos;
327
328 paintLegend(painter);
329
330 m_Type = prevType;
331 m_Position = prevPos;
332}
333
334void Legend::paintSymbols(QPointF pos)
335{
336 qreal x = pos.x();
337 qreal y = pos.y();
338
339 x += 30;
340
341 switch (m_Orientation)
342 {
343 case Legend::LO_HORIZONTAL:
344 {
345 // paint Open Cluster/Asterism symbol
346 QString label1 = i18n("Open Cluster") + '\n' + i18n("Asterism");
347 paintSymbol(QPointF(x, y), 3, 1, 0, label1);
348 x += m_XSymbolSpacing;
349
350 // paint Globular Cluster symbol
351 paintSymbol(QPointF(x, y), 4, 1, 0, i18n("Globular Cluster"));
352 x += m_XSymbolSpacing;
353
354 // paint Gaseous Nebula/Dark Nebula symbol
355 QString label3 = i18n("Gaseous Nebula") + '\n' + i18n("Dark Nebula");
356 paintSymbol(QPointF(x, y), 5, 1, 0, label3);
357 x += m_XSymbolSpacing;
358
359 // paint Planetary Nebula symbol
360 paintSymbol(QPointF(x, y), 6, 1, 0, i18n("Planetary Nebula"));
361 x += m_XSymbolSpacing;
362
363 // paint Supernova Remnant
364 paintSymbol(QPointF(x, y), 7, 1, 0, i18n("Supernova Remnant"));
365 x += m_XSymbolSpacing;
366
367 // paint Galaxy/Quasar
368 QString label6 = i18n("Galaxy") + '\n' + i18n("Quasar");
369 paintSymbol(QPointF(x, y), 8, 0.5, 60, label6);
370 x += m_XSymbolSpacing;
371
372 // paint Galaxy Cluster
373 paintSymbol(QPointF(x, y), 14, 1, 0, i18n("Galactic Cluster"));
374
375 break;
376 }
377
378 case Legend::LO_VERTICAL:
379 {
380 // paint Open Cluster/Asterism symbol
381 QString label1 = i18n("Open Cluster") + '\n' + i18n("Asterism");
382 paintSymbol(QPointF(x, y), 3, 1, 0, label1);
383 y += m_YSymbolSpacing;
384
385 // paint Globular Cluster symbol
386 paintSymbol(QPointF(x, y), 4, 1, 0, i18n("Globular Cluster"));
387 y += m_YSymbolSpacing;
388
389 // paint Gaseous Nebula/Dark Nebula symbol
390 QString label3 = i18n("Gaseous Nebula") + '\n' + i18n("Dark Nebula");
391 paintSymbol(QPointF(x, y), 5, 1, 0, label3);
392 y += m_YSymbolSpacing;
393
394 // paint Planetary Nebula symbol
395 paintSymbol(QPointF(x, y), 6, 1, 0, i18n("Planetary Nebula"));
396 y += m_YSymbolSpacing;
397
398 // paint Supernova Remnant
399 paintSymbol(QPointF(x, y), 7, 1, 0, i18n("Supernova Remnant"));
400 y += m_YSymbolSpacing;
401
402 // paint Galaxy/Quasar
403 QString label6 = i18n("Galaxy") + '\n' + i18n("Quasar");
404 paintSymbol(QPointF(x, y), 8, 0.5, 60, label6);
405 y += m_YSymbolSpacing;
406
407 // paint Galaxy Cluster
408 paintSymbol(QPointF(x, y), 14, 1, 0, i18n("Galactic Cluster"));
409
410 break;
411 }
412 default:
413 return; // should never happen
414 }
415}
416
417void Legend::paintSymbol(QPointF pos, int type, float e, float angle, QString label)
418{
419 qreal x = pos.x();
420 qreal y = pos.y();
421 qreal bRectHalfWidth = (qreal)m_BRectWidth / 2;
422
423 // paint symbol
424 m_Painter->drawDeepSkySymbol(pos, type, m_SymbolSize, e, angle);
425 QRectF bRect(QPoint(x - bRectHalfWidth, y + m_SymbolSize),
426 QPoint(x + bRectHalfWidth, y + m_SymbolSize + m_BRectHeight));
427 //m_Painter->drawRect(bRect);
428 // paint label
429 m_Painter->drawText(bRect, label, QTextOption(Qt::AlignHCenter));
430}
431
432void Legend::paintMagnitudes(QPointF pos)
433{
434 qreal x = pos.x();
435 qreal y = pos.y();
436
437 m_Painter->drawText(x, y, i18n("Star Magnitudes:"));
438 y += 15;
439
440 for (int i = 1; i <= 9; i += 2)
441 {
442 m_Painter->drawPointSource(QPointF(x + i * 10, y), m_Painter->starWidth(i));
443 m_Painter->drawText(x + i * 10 - 4, y + 20, QString::number(i));
444 }
445}
446
447void Legend::paintScale(QPointF pos)
448{
449 qreal maxScalePixels;
450
451 switch (m_Orientation)
452 {
453 case LO_HORIZONTAL:
454 {
455 maxScalePixels = m_MaxHScalePixels;
456 break;
457 }
458
459 case LO_VERTICAL:
460 {
461 maxScalePixels = m_MaxVScalePixels;
462 break;
463 }
464
465 default:
466 return; // should never happen
467 }
468
469 qreal maxArcsec = maxScalePixels * 57.3 * 3600 / Options::zoomFactor();
470
471 int deg = 0;
472 int arcmin = 0;
473 int arcsec = 0;
474
475 QString lab;
476 if (maxArcsec >= 3600)
477 {
478 deg = maxArcsec / 3600;
479 lab = QString::number(deg) + QString::fromWCharArray(L"\u00B0");
480 }
481
482 else if (maxArcsec >= 60)
483 {
484 arcmin = maxArcsec / 60;
485 lab = QString::number(arcmin) + '\'';
486 }
487
488 else
489 {
490 arcsec = maxArcsec;
491 lab = QString::number(arcsec) + "\"";
492 }
493
494 int actualArcsec = 3600 * deg + 60 * arcmin + arcsec;
495
496 qreal size = actualArcsec * Options::zoomFactor() / 57.3 / 3600;
497
498 qreal x = pos.x();
499 qreal y = pos.y();
500
501 switch (m_Orientation)
502 {
503 case LO_HORIZONTAL:
504 {
505 m_Painter->drawText(pos, i18n("Chart Scale:"));
506 y += 15;
507
508 m_Painter->drawLine(x, y, x + size, y);
509 // paint line endings
510 m_Painter->drawLine(x, y - 5, x, y + 5);
511 m_Painter->drawLine(x + size, y - 5, x + size, y + 5);
512
513 // paint scale text
514 QRectF bRect(QPoint(x, y), QPoint(x + size, y + 20));
515 m_Painter->drawText(bRect, lab, QTextOption(Qt::AlignHCenter));
516
517 break;
518 }
519
520 case LO_VERTICAL:
521 {
522 m_Painter->drawText(pos, i18n("Chart Scale:"));
523 y += 10;
524 x += 40;
525
526 m_Painter->drawLine(x, y, x, y + size);
527 // paint line endings
528 m_Painter->drawLine(x - 5, y, x + 5, y);
529 m_Painter->drawLine(x - 5, y + size, x + 5, y + size);
530
531 // paint scale text
532 QRectF bRect(QPoint(x + 5, y), QPoint(x + 20, y + size));
533 //m_Painter->drawRect(bRect);
534 m_Painter->drawText(bRect, lab, QTextOption(Qt::AlignVCenter));
535
536 break;
537 }
538
539 default:
540 return; // should never happen
541 }
542}
543
544QPoint Legend::positionToDeviceCoord(QPaintDevice *pd)
545{
546 QSize legendSize = calculateSize();
547
548 switch (m_Position)
549 {
550 case LP_UPPER_LEFT: // position: upper left corner
551 {
552 return QPoint(0, 0);
553 }
554
555 case LP_UPPER_RIGHT: // position: upper right corner
556 {
557 return QPoint(pd->width() - legendSize.width(), 0);
558 }
559
560 case LP_LOWER_LEFT: // position: lower left corner
561 {
562 return QPoint(0, pd->height() - legendSize.height());
563 }
564
565 case LP_LOWER_RIGHT: // position: lower right corner
566 {
567 return QPoint(pd->width() - legendSize.width(), pd->height() - legendSize.height());
568 }
569
570 default: // legend is floating
571 {
572 return QPoint();
573 }
574 }
575}
576
577Legend::Legend(const Legend &o)
578 : m_Painter(nullptr), m_SkyMap(o.m_SkyMap), m_DeletePainter(o.m_DeletePainter), m_Type(o.m_Type),
579 m_Orientation(o.m_Orientation), m_Position(o.m_Position), m_PositionFloating(o.m_PositionFloating),
580 m_cScheme(o.m_cScheme), m_Font(o.m_Font), m_BgColor(o.m_BgColor), m_DrawFrame(o.m_DrawFrame),
581 m_SymbolSize(o.m_SymbolSize), m_BRectWidth(o.m_BRectWidth), m_BRectHeight(o.m_BRectHeight),
582 m_MaxHScalePixels(o.m_MaxHScalePixels), m_MaxVScalePixels(o.m_MaxVScalePixels),
583 m_XSymbolSpacing(o.m_XSymbolSpacing), m_YSymbolSpacing(o.m_YSymbolSpacing)
584{
585}
586
587Legend& Legend::operator=(const Legend &o) noexcept
588{
589 m_SkyMap = o.m_SkyMap;
590 m_DeletePainter = o.m_DeletePainter;
591 m_Type = o.m_Type;
592 m_Orientation = o.m_Orientation;
593 m_Position = o.m_Position;
594 m_PositionFloating = o.m_PositionFloating;
595 m_cScheme = o.m_cScheme;
596 m_Font = o.m_Font;
597 m_BgColor = o.m_BgColor;
598 m_DrawFrame = o.m_DrawFrame;
599 m_SymbolSize = o.m_SymbolSize;
600 m_BRectWidth = o.m_BRectWidth;
601 m_BRectHeight = o.m_BRectHeight;
602 m_MaxHScalePixels = o.m_MaxHScalePixels;
603 m_MaxVScalePixels = o.m_MaxVScalePixels;
604 m_XSymbolSpacing = o.m_XSymbolSpacing;
605 m_YSymbolSpacing = o.m_YSymbolSpacing;
606 return *this;
607}
QColor colorNamed(const QString &name) const
Retrieve a color by name.
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
This is the canvas on which the sky is painted.
Definition skymap.h:54
float starWidth(float mag) const
Get the width of a star of magnitude mag.
The QPainter-based painting backend.
Definition skyqpainter.h:31
void end() override
End and finalize painting.
bool drawPointSource(const SkyPoint *loc, float mag, char sp='A') override
Draw a point source (e.g., a star).
void setBrush(const QBrush &brush) override
Set the brush of the painter.
void setPen(const QPen &pen) override
Set the pen of the painter.
void begin() override
Begin painting.
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
int height() const const
int width() const const
QPaintDevice * device() const const
void drawLine(const QLine &line)
void drawRect(const QRect &rectangle)
void drawText(const QPoint &position, const QString &text)
void setFont(const QFont &font)
void translate(const QPoint &offset)
void setStyle(Qt::PenStyle style)
int x() const const
int y() const const
qreal x() const const
qreal y() const const
int height() const const
int width() const const
QString fromWCharArray(const wchar_t *string, qsizetype size)
QString number(double n, char format, int precision)
AlignHCenter
SolidPattern
SolidLine
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.