Kstars

legend.cpp
1 /*
2  SPDX-FileCopyrightText: 2011 Rafał Kułaga <[email protected]>
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 
17 namespace
18 {
19 const int symbolSize = 15;
20 const int bRectWidth = 100;
21 const int bRectHeight = 45;
22 const int maxHScalePixels = 200;
23 const int maxVScalePixels = 100;
24 const int xSymbolSpacing = 100;
25 const int ySymbolSpacing = 70;
26 }
27 
28 Legend::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 
38 Legend::~Legend()
39 {
40  if (m_Painter != nullptr && m_DeletePainter)
41  {
42  delete m_Painter;
43  }
44 }
45 
46 QSize 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 
154 void 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 
170 void 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 
306 void 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 
320 void 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 
334 void 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 
417 void 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 
432 void 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 
447 void 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 
544 QPoint 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 
577 Legend::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 
587 Legend& 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 }
AlignHCenter
void begin() override
Begin painting.
int width() const const
The QPainter-based painting backend.
Definition: skyqpainter.h:28
QString number(int n, int base)
void drawRect(const QRectF &rectangle)
bool drawPointSource(const SkyPoint *loc, float mag, char sp='A') override
Draw a point source (e.g., a star).
void setPen(const QPen &pen) override
Set the pen of the painter.
float starWidth(float mag) const
Get the width of a star of magnitude mag.
Definition: skypainter.cpp:30
int x() const const
int y() const const
int width() const const
void drawText(const QPointF &position, const QString &text)
int height() const const
QString i18n(const char *text, const TYPE &arg...)
int height() const const
QString fromWCharArray(const wchar_t *string, int size)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
qreal x() const const
qreal y() const const
Canvas widget for displaying the sky bitmap; also handles user interaction events.
Definition: skymap.h:52
void end() override
End and finalize painting.
void drawLine(const QLineF &line)
void translate(const QPointF &offset)
QPaintDevice * device() const const
void setStyle(Qt::PenStyle style)
SolidLine
void setFont(const QFont &font)
QColor colorNamed(const QString &name) const
Retrieve a color by name.
Definition: colorscheme.cpp:86
SolidPattern
void setBrush(const QBrush &brush) override
Set the brush of the painter.
Legend class is used for painting legends on class inheriting QPaintDevice. Its methods enable changi...
Definition: legend.h:32
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Aug 8 2022 04:13:22 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.