qt: add missing initializers (CID 1325722)
[metze/wireshark/wip.git] / ui / qt / qcustomplot.cpp
1 /***************************************************************************
2 **                                                                        **
3 **  QCustomPlot, an easy to use, modern plotting widget for Qt            **
4 **  Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer               **
5 **                                                                        **
6 **  This program is free software: you can redistribute it and/or modify  **
7 **  it under the terms of the GNU General Public License as published by  **
8 **  the Free Software Foundation, either version 2 of the License, or     **
9 **  (at your option) any later version.                                   **
10 **                                                                        **
11 **  This program is distributed in the hope that it will be useful,       **
12 **  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
13 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
14 **  GNU General Public License for more details.                          **
15 **                                                                        **
16 **  You should have received a copy of the GNU General Public License     **
17 **  along with this program.  If not, see http://www.gnu.org/licenses/.   **
18 **                                                                        **
19 ****************************************************************************
20 **           Author: Emanuel Eichhammer                                   **
21 **  Website/Contact: http://www.qcustomplot.com/                          **
22 ** Emanuel Eichhammer has granted Wireshark permission to use QCustomPlot **
23 ** under the terms of the GNU General Public License version 2.           **
24 **             Date: 27.12.14                                             **
25 **          Version: 1.3.0                                                **
26 ****************************************************************************/
27
28 #include "qcustomplot.h"
29
30
31
32 ////////////////////////////////////////////////////////////////////////////////////////////////////
33 //////////////////// QCPPainter
34 ////////////////////////////////////////////////////////////////////////////////////////////////////
35
36 /*! \class QCPPainter
37   \brief QPainter subclass used internally
38
39   This QPainter subclass is used to provide some extended functionality e.g. for tweaking position
40   consistency between antialiased and non-antialiased painting. Further it provides workarounds
41   for QPainter quirks.
42
43   \warning This class intentionally hides non-virtual functions of QPainter, e.g. setPen, save and
44   restore. So while it is possible to pass a QCPPainter instance to a function that expects a
45   QPainter pointer, some of the workarounds and tweaks will be unavailable to the function (because
46   it will call the base class implementations of the functions actually hidden by QCPPainter).
47 */
48
49 /*!
50   Creates a new QCPPainter instance and sets default values
51 */
52 QCPPainter::QCPPainter() :
53   QPainter(),
54   mModes(pmDefault),
55   mIsAntialiasing(false)
56 {
57   // don't setRenderHint(QPainter::NonCosmeticDefautPen) here, because painter isn't active yet and
58   // a call to begin() will follow
59 }
60
61 /*!
62   Creates a new QCPPainter instance on the specified paint \a device and sets default values. Just
63   like the analogous QPainter constructor, begins painting on \a device immediately.
64
65   Like \ref begin, this method sets QPainter::NonCosmeticDefaultPen in Qt versions before Qt5.
66 */
67 QCPPainter::QCPPainter(QPaintDevice *device) :
68   QPainter(device),
69   mModes(pmDefault),
70   mIsAntialiasing(false)
71 {
72 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
73   if (isActive())
74     setRenderHint(QPainter::NonCosmeticDefaultPen);
75 #endif
76 }
77
78 QCPPainter::~QCPPainter()
79 {
80 }
81
82 /*!
83   Sets the pen of the painter and applies certain fixes to it, depending on the mode of this
84   QCPPainter.
85
86   \note this function hides the non-virtual base class implementation.
87 */
88 void QCPPainter::setPen(const QPen &pen)
89 {
90   QPainter::setPen(pen);
91   if (mModes.testFlag(pmNonCosmetic))
92     makeNonCosmetic();
93 }
94
95 /*! \overload
96
97   Sets the pen (by color) of the painter and applies certain fixes to it, depending on the mode of
98   this QCPPainter.
99
100   \note this function hides the non-virtual base class implementation.
101 */
102 void QCPPainter::setPen(const QColor &color)
103 {
104   QPainter::setPen(color);
105   if (mModes.testFlag(pmNonCosmetic))
106     makeNonCosmetic();
107 }
108
109 /*! \overload
110
111   Sets the pen (by style) of the painter and applies certain fixes to it, depending on the mode of
112   this QCPPainter.
113
114   \note this function hides the non-virtual base class implementation.
115 */
116 void QCPPainter::setPen(Qt::PenStyle penStyle)
117 {
118   QPainter::setPen(penStyle);
119   if (mModes.testFlag(pmNonCosmetic))
120     makeNonCosmetic();
121 }
122
123 /*! \overload
124
125   Works around a Qt bug introduced with Qt 4.8 which makes drawing QLineF unpredictable when
126   antialiasing is disabled. Thus when antialiasing is disabled, it rounds the \a line to
127   integer coordinates and then passes it to the original drawLine.
128
129   \note this function hides the non-virtual base class implementation.
130 */
131 void QCPPainter::drawLine(const QLineF &line)
132 {
133   if (mIsAntialiasing || mModes.testFlag(pmVectorized))
134     QPainter::drawLine(line);
135   else
136     QPainter::drawLine(line.toLine());
137 }
138
139 /*!
140   Sets whether painting uses antialiasing or not. Use this method instead of using setRenderHint
141   with QPainter::Antialiasing directly, as it allows QCPPainter to regain pixel exactness between
142   antialiased and non-antialiased painting (Since Qt < 5.0 uses slightly different coordinate systems for
143   AA/Non-AA painting).
144 */
145 void QCPPainter::setAntialiasing(bool enabled)
146 {
147   setRenderHint(QPainter::Antialiasing, enabled);
148   if (mIsAntialiasing != enabled)
149   {
150     mIsAntialiasing = enabled;
151     if (!mModes.testFlag(pmVectorized)) // antialiasing half-pixel shift only needed for rasterized outputs
152     {
153       if (mIsAntialiasing)
154         translate(0.5, 0.5);
155       else
156         translate(-0.5, -0.5);
157     }
158   }
159 }
160
161 /*!
162   Sets the mode of the painter. This controls whether the painter shall adjust its
163   fixes/workarounds optimized for certain output devices.
164 */
165 void QCPPainter::setModes(QCPPainter::PainterModes modes)
166 {
167   mModes = modes;
168 }
169
170 /*!
171   Sets the QPainter::NonCosmeticDefaultPen in Qt versions before Qt5 after beginning painting on \a
172   device. This is necessary to get cosmetic pen consistency across Qt versions, because since Qt5,
173   all pens are non-cosmetic by default, and in Qt4 this render hint must be set to get that
174   behaviour.
175
176   The Constructor \ref QCPPainter(QPaintDevice *device) which directly starts painting also sets
177   the render hint as appropriate.
178
179   \note this function hides the non-virtual base class implementation.
180 */
181 bool QCPPainter::begin(QPaintDevice *device)
182 {
183   bool result = QPainter::begin(device);
184 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
185   if (result)
186     setRenderHint(QPainter::NonCosmeticDefaultPen);
187 #endif
188   return result;
189 }
190
191 /*! \overload
192
193   Sets the mode of the painter. This controls whether the painter shall adjust its
194   fixes/workarounds optimized for certain output devices.
195 */
196 void QCPPainter::setMode(QCPPainter::PainterMode mode, bool enabled)
197 {
198   if (!enabled && mModes.testFlag(mode))
199     mModes &= ~mode;
200   else if (enabled && !mModes.testFlag(mode))
201     mModes |= mode;
202 }
203
204 /*!
205   Saves the painter (see QPainter::save). Since QCPPainter adds some new internal state to
206   QPainter, the save/restore functions are reimplemented to also save/restore those members.
207
208   \note this function hides the non-virtual base class implementation.
209
210   \see restore
211 */
212 void QCPPainter::save()
213 {
214   mAntialiasingStack.push(mIsAntialiasing);
215   QPainter::save();
216 }
217
218 /*!
219   Restores the painter (see QPainter::restore). Since QCPPainter adds some new internal state to
220   QPainter, the save/restore functions are reimplemented to also save/restore those members.
221
222   \note this function hides the non-virtual base class implementation.
223
224   \see save
225 */
226 void QCPPainter::restore()
227 {
228   if (!mAntialiasingStack.isEmpty())
229     mIsAntialiasing = mAntialiasingStack.pop();
230   else
231     qDebug() << Q_FUNC_INFO << "Unbalanced save/restore";
232   QPainter::restore();
233 }
234
235 /*!
236   Changes the pen width to 1 if it currently is 0. This function is called in the \ref setPen
237   overrides when the \ref pmNonCosmetic mode is set.
238 */
239 void QCPPainter::makeNonCosmetic()
240 {
241   if (qFuzzyIsNull(pen().widthF()))
242   {
243     QPen p = pen();
244     p.setWidth(1);
245     QPainter::setPen(p);
246   }
247 }
248
249
250 ////////////////////////////////////////////////////////////////////////////////////////////////////
251 //////////////////// QCPScatterStyle
252 ////////////////////////////////////////////////////////////////////////////////////////////////////
253
254 /*! \class QCPScatterStyle
255   \brief Represents the visual appearance of scatter points
256
257   This class holds information about shape, color and size of scatter points. In plottables like
258   QCPGraph it is used to store how scatter points shall be drawn. For example, \ref
259   QCPGraph::setScatterStyle takes a QCPScatterStyle instance.
260
261   A scatter style consists of a shape (\ref setShape), a line color (\ref setPen) and possibly a
262   fill (\ref setBrush), if the shape provides a fillable area. Further, the size of the shape can
263   be controlled with \ref setSize.
264
265   \section QCPScatterStyle-defining Specifying a scatter style
266
267   You can set all these configurations either by calling the respective functions on an instance:
268   \code
269   QCPScatterStyle myScatter;
270   myScatter.setShape(QCPScatterStyle::ssCircle);
271   myScatter.setPen(Qt::blue);
272   myScatter.setBrush(Qt::white);
273   myScatter.setSize(5);
274   customPlot->graph(0)->setScatterStyle(myScatter);
275   \endcode
276
277   Or you can use one of the various constructors that take different parameter combinations, making
278   it easy to specify a scatter style in a single call, like so:
279   \code
280   customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, Qt::white, 5));
281   \endcode
282
283   \section QCPScatterStyle-undefinedpen Leaving the color/pen up to the plottable
284
285   There are two constructors which leave the pen undefined: \ref QCPScatterStyle() and \ref
286   QCPScatterStyle(ScatterShape shape, double size). If those constructors are used, a call to \ref
287   isPenDefined will return false. It leads to scatter points that inherit the pen from the
288   plottable that uses the scatter style. Thus, if such a scatter style is passed to QCPGraph, the line
289   color of the graph (\ref QCPGraph::setPen) will be used by the scatter points. This makes
290   it very convenient to set up typical scatter settings:
291
292   \code
293   customPlot->graph(0)->setScatterStyle(QCPScatterStyle::ssPlus);
294   \endcode
295
296   Notice that it wasn't even necessary to explicitly call a QCPScatterStyle constructor. This works
297   because QCPScatterStyle provides a constructor that can transform a \ref ScatterShape directly
298   into a QCPScatterStyle instance (that's the \ref QCPScatterStyle(ScatterShape shape, double size)
299   constructor with a default for \a size). In those cases, C++ allows directly supplying a \ref
300   ScatterShape, where actually a QCPScatterStyle is expected.
301
302   \section QCPScatterStyle-custompath-and-pixmap Custom shapes and pixmaps
303
304   QCPScatterStyle supports drawing custom shapes and arbitrary pixmaps as scatter points.
305
306   For custom shapes, you can provide a QPainterPath with the desired shape to the \ref
307   setCustomPath function or call the constructor that takes a painter path. The scatter shape will
308   automatically be set to \ref ssCustom.
309
310   For pixmaps, you call \ref setPixmap with the desired QPixmap. Alternatively you can use the
311   constructor that takes a QPixmap. The scatter shape will automatically be set to \ref ssPixmap.
312   Note that \ref setSize does not influence the appearance of the pixmap.
313 */
314
315 /* start documentation of inline functions */
316
317 /*! \fn bool QCPScatterStyle::isNone() const
318
319   Returns whether the scatter shape is \ref ssNone.
320
321   \see setShape
322 */
323
324 /*! \fn bool QCPScatterStyle::isPenDefined() const
325
326   Returns whether a pen has been defined for this scatter style.
327
328   The pen is undefined if a constructor is called that does not carry \a pen as parameter. Those are
329   \ref QCPScatterStyle() and \ref QCPScatterStyle(ScatterShape shape, double size). If the pen is
330   left undefined, the scatter color will be inherited from the plottable that uses this scatter
331   style.
332
333   \see setPen
334 */
335
336 /* end documentation of inline functions */
337
338 /*!
339   Creates a new QCPScatterStyle instance with size set to 6. No shape, pen or brush is defined.
340
341   Since the pen is undefined (\ref isPenDefined returns false), the scatter color will be inherited
342   from the plottable that uses this scatter style.
343 */
344 QCPScatterStyle::QCPScatterStyle() :
345   mSize(6),
346   mShape(ssNone),
347   mPen(Qt::NoPen),
348   mBrush(Qt::NoBrush),
349   mPenDefined(false)
350 {
351 }
352
353 /*!
354   Creates a new QCPScatterStyle instance with shape set to \a shape and size to \a size. No pen or
355   brush is defined.
356
357   Since the pen is undefined (\ref isPenDefined returns false), the scatter color will be inherited
358   from the plottable that uses this scatter style.
359 */
360 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, double size) :
361   mSize(size),
362   mShape(shape),
363   mPen(Qt::NoPen),
364   mBrush(Qt::NoBrush),
365   mPenDefined(false)
366 {
367 }
368
369 /*!
370   Creates a new QCPScatterStyle instance with shape set to \a shape, the pen color set to \a color,
371   and size to \a size. No brush is defined, i.e. the scatter point will not be filled.
372 */
373 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) :
374   mSize(size),
375   mShape(shape),
376   mPen(QPen(color)),
377   mBrush(Qt::NoBrush),
378   mPenDefined(true)
379 {
380 }
381
382 /*!
383   Creates a new QCPScatterStyle instance with shape set to \a shape, the pen color set to \a color,
384   the brush color to \a fill (with a solid pattern), and size to \a size.
385 */
386 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) :
387   mSize(size),
388   mShape(shape),
389   mPen(QPen(color)),
390   mBrush(QBrush(fill)),
391   mPenDefined(true)
392 {
393 }
394
395 /*!
396   Creates a new QCPScatterStyle instance with shape set to \a shape, the pen set to \a pen, the
397   brush to \a brush, and size to \a size.
398
399   \warning In some cases it might be tempting to directly use a pen style like <tt>Qt::NoPen</tt> as \a pen
400   and a color like <tt>Qt::blue</tt> as \a brush. Notice however, that the corresponding call\n
401   <tt>QCPScatterStyle(QCPScatterShape::ssCircle, Qt::NoPen, Qt::blue, 5)</tt>\n
402   doesn't necessarily lead C++ to use this constructor in some cases, but might mistake
403   <tt>Qt::NoPen</tt> for a QColor and use the
404   \ref QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size)
405   constructor instead (which will lead to an unexpected look of the scatter points). To prevent
406   this, be more explicit with the parameter types. For example, use <tt>QBrush(Qt::blue)</tt>
407   instead of just <tt>Qt::blue</tt>, to clearly point out to the compiler that this constructor is
408   wanted.
409 */
410 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) :
411   mSize(size),
412   mShape(shape),
413   mPen(pen),
414   mBrush(brush),
415   mPenDefined(pen.style() != Qt::NoPen)
416 {
417 }
418
419 /*!
420   Creates a new QCPScatterStyle instance which will show the specified \a pixmap. The scatter shape
421   is set to \ref ssPixmap.
422 */
423 QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) :
424   mSize(5),
425   mShape(ssPixmap),
426   mPen(Qt::NoPen),
427   mBrush(Qt::NoBrush),
428   mPixmap(pixmap),
429   mPenDefined(false)
430 {
431 }
432
433 /*!
434   Creates a new QCPScatterStyle instance with a custom shape that is defined via \a customPath. The
435   scatter shape is set to \ref ssCustom.
436
437   The custom shape line will be drawn with \a pen and filled with \a brush. The size has a slightly
438   different meaning than for built-in scatter points: The custom path will be drawn scaled by a
439   factor of \a size/6.0. Since the default \a size is 6, the custom path will appear at a its
440   natural size by default. To double the size of the path for example, set \a size to 12.
441 */
442 QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) :
443   mSize(size),
444   mShape(ssCustom),
445   mPen(pen),
446   mBrush(brush),
447   mCustomPath(customPath),
448   mPenDefined(pen.style() != Qt::NoPen)
449 {
450 }
451
452 /*!
453   Sets the size (pixel diameter) of the drawn scatter points to \a size.
454
455   \see setShape
456 */
457 void QCPScatterStyle::setSize(double size)
458 {
459   mSize = size;
460 }
461
462 /*!
463   Sets the shape to \a shape.
464
465   Note that the calls \ref setPixmap and \ref setCustomPath automatically set the shape to \ref
466   ssPixmap and \ref ssCustom, respectively.
467
468   \see setSize
469 */
470 void QCPScatterStyle::setShape(QCPScatterStyle::ScatterShape shape)
471 {
472   mShape = shape;
473 }
474
475 /*!
476   Sets the pen that will be used to draw scatter points to \a pen.
477
478   If the pen was previously undefined (see \ref isPenDefined), the pen is considered defined after
479   a call to this function, even if \a pen is <tt>Qt::NoPen</tt>.
480
481   \see setBrush
482 */
483 void QCPScatterStyle::setPen(const QPen &pen)
484 {
485   mPenDefined = true;
486   mPen = pen;
487 }
488
489 /*!
490   Sets the brush that will be used to fill scatter points to \a brush. Note that not all scatter
491   shapes have fillable areas. For example, \ref ssPlus does not while \ref ssCircle does.
492
493   \see setPen
494 */
495 void QCPScatterStyle::setBrush(const QBrush &brush)
496 {
497   mBrush = brush;
498 }
499
500 /*!
501   Sets the pixmap that will be drawn as scatter point to \a pixmap.
502
503   Note that \ref setSize does not influence the appearance of the pixmap.
504
505   The scatter shape is automatically set to \ref ssPixmap.
506 */
507 void QCPScatterStyle::setPixmap(const QPixmap &pixmap)
508 {
509   setShape(ssPixmap);
510   mPixmap = pixmap;
511 }
512
513 /*!
514   Sets the custom shape that will be drawn as scatter point to \a customPath.
515
516   The scatter shape is automatically set to \ref ssCustom.
517 */
518 void QCPScatterStyle::setCustomPath(const QPainterPath &customPath)
519 {
520   setShape(ssCustom);
521   mCustomPath = customPath;
522 }
523
524 /*!
525   Applies the pen and the brush of this scatter style to \a painter. If this scatter style has an
526   undefined pen (\ref isPenDefined), sets the pen of \a painter to \a defaultPen instead.
527
528   This function is used by plottables (or any class that wants to draw scatters) just before a
529   number of scatters with this style shall be drawn with the \a painter.
530
531   \see drawShape
532 */
533 void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const
534 {
535   painter->setPen(mPenDefined ? mPen : defaultPen);
536   painter->setBrush(mBrush);
537 }
538
539 /*!
540   Draws the scatter shape with \a painter at position \a pos.
541
542   This function does not modify the pen or the brush on the painter, as \ref applyTo is meant to be
543   called before scatter points are drawn with \ref drawShape.
544
545   \see applyTo
546 */
547 void QCPScatterStyle::drawShape(QCPPainter *painter, QPointF pos) const
548 {
549   drawShape(painter, pos.x(), pos.y());
550 }
551
552 /*! \overload
553   Draws the scatter shape with \a painter at position \a x and \a y.
554 */
555 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const
556 {
557   double w = mSize/2.0;
558   switch (mShape)
559   {
560     case ssNone: break;
561     case ssDot:
562     {
563       painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y));
564       break;
565     }
566     case ssCross:
567     {
568       painter->drawLine(QLineF(x-w, y-w, x+w, y+w));
569       painter->drawLine(QLineF(x-w, y+w, x+w, y-w));
570       break;
571     }
572     case ssPlus:
573     {
574       painter->drawLine(QLineF(x-w,   y, x+w,   y));
575       painter->drawLine(QLineF(  x, y+w,   x, y-w));
576       break;
577     }
578     case ssCircle:
579     {
580       painter->drawEllipse(QPointF(x , y), w, w);
581       break;
582     }
583     case ssDisc:
584     {
585       QBrush b = painter->brush();
586       painter->setBrush(painter->pen().color());
587       painter->drawEllipse(QPointF(x , y), w, w);
588       painter->setBrush(b);
589       break;
590     }
591     case ssSquare:
592     {
593       painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
594       break;
595     }
596     case ssDiamond:
597     {
598       painter->drawLine(QLineF(x-w,   y,   x, y-w));
599       painter->drawLine(QLineF(  x, y-w, x+w,   y));
600       painter->drawLine(QLineF(x+w,   y,   x, y+w));
601       painter->drawLine(QLineF(  x, y+w, x-w,   y));
602       break;
603     }
604     case ssStar:
605     {
606       painter->drawLine(QLineF(x-w,   y, x+w,   y));
607       painter->drawLine(QLineF(  x, y+w,   x, y-w));
608       painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707));
609       painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707));
610       break;
611     }
612     case ssTriangle:
613     {
614        painter->drawLine(QLineF(x-w, y+0.755*w, x+w, y+0.755*w));
615        painter->drawLine(QLineF(x+w, y+0.755*w,   x, y-0.977*w));
616        painter->drawLine(QLineF(  x, y-0.977*w, x-w, y+0.755*w));
617       break;
618     }
619     case ssTriangleInverted:
620     {
621        painter->drawLine(QLineF(x-w, y-0.755*w, x+w, y-0.755*w));
622        painter->drawLine(QLineF(x+w, y-0.755*w,   x, y+0.977*w));
623        painter->drawLine(QLineF(  x, y+0.977*w, x-w, y-0.755*w));
624       break;
625     }
626     case ssCrossSquare:
627     {
628        painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95));
629        painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w));
630        painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
631       break;
632     }
633     case ssPlusSquare:
634     {
635        painter->drawLine(QLineF(x-w,   y, x+w*0.95,   y));
636        painter->drawLine(QLineF(  x, y+w,        x, y-w));
637        painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
638       break;
639     }
640     case ssCrossCircle:
641     {
642        painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670));
643        painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707));
644        painter->drawEllipse(QPointF(x, y), w, w);
645       break;
646     }
647     case ssPlusCircle:
648     {
649        painter->drawLine(QLineF(x-w,   y, x+w,   y));
650        painter->drawLine(QLineF(  x, y+w,   x, y-w));
651        painter->drawEllipse(QPointF(x, y), w, w);
652       break;
653     }
654     case ssPeace:
655     {
656        painter->drawLine(QLineF(x, y-w,         x,       y+w));
657        painter->drawLine(QLineF(x,   y, x-w*0.707, y+w*0.707));
658        painter->drawLine(QLineF(x,   y, x+w*0.707, y+w*0.707));
659        painter->drawEllipse(QPointF(x, y), w, w);
660       break;
661     }
662     case ssPixmap:
663     {
664       painter->drawPixmap(x-mPixmap.width()*0.5, y-mPixmap.height()*0.5, mPixmap);
665       break;
666     }
667     case ssCustom:
668     {
669       QTransform oldTransform = painter->transform();
670       painter->translate(x, y);
671       painter->scale(mSize/6.0, mSize/6.0);
672       painter->drawPath(mCustomPath);
673       painter->setTransform(oldTransform);
674       break;
675     }
676   }
677 }
678
679
680 ////////////////////////////////////////////////////////////////////////////////////////////////////
681 //////////////////// QCPLayer
682 ////////////////////////////////////////////////////////////////////////////////////////////////////
683
684 /*! \class QCPLayer
685   \brief A layer that may contain objects, to control the rendering order
686
687   The Layering system of QCustomPlot is the mechanism to control the rendering order of the
688   elements inside the plot.
689
690   It is based on the two classes QCPLayer and QCPLayerable. QCustomPlot holds an ordered list of
691   one or more instances of QCPLayer (see QCustomPlot::addLayer, QCustomPlot::layer,
692   QCustomPlot::moveLayer, etc.). When replotting, QCustomPlot goes through the list of layers
693   bottom to top and successively draws the layerables of the layers.
694
695   A QCPLayer contains an ordered list of QCPLayerable instances. QCPLayerable is an abstract base
696   class from which almost all visible objects derive, like axes, grids, graphs, items, etc.
697
698   Initially, QCustomPlot has five layers: "background", "grid", "main", "axes" and "legend" (in
699   that order). The top two layers "axes" and "legend" contain the default axes and legend, so they
700   will be drawn on top. In the middle, there is the "main" layer. It is initially empty and set as
701   the current layer (see QCustomPlot::setCurrentLayer). This means, all new plottables, items etc.
702   are created on this layer by default. Then comes the "grid" layer which contains the QCPGrid
703   instances (which belong tightly to QCPAxis, see \ref QCPAxis::grid). The Axis rect background
704   shall be drawn behind everything else, thus the default QCPAxisRect instance is placed on the
705   "background" layer. Of course, the layer affiliation of the individual objects can be changed as
706   required (\ref QCPLayerable::setLayer).
707
708   Controlling the ordering of objects is easy: Create a new layer in the position you want it to
709   be, e.g. above "main", with QCustomPlot::addLayer. Then set the current layer with
710   QCustomPlot::setCurrentLayer to that new layer and finally create the objects normally. They will
711   be placed on the new layer automatically, due to the current layer setting. Alternatively you
712   could have also ignored the current layer setting and just moved the objects with
713   QCPLayerable::setLayer to the desired layer after creating them.
714
715   It is also possible to move whole layers. For example, If you want the grid to be shown in front
716   of all plottables/items on the "main" layer, just move it above "main" with
717   QCustomPlot::moveLayer.
718
719   The rendering order within one layer is simply by order of creation or insertion. The item
720   created last (or added last to the layer), is drawn on top of all other objects on that layer.
721
722   When a layer is deleted, the objects on it are not deleted with it, but fall on the layer below
723   the deleted layer, see QCustomPlot::removeLayer.
724 */
725
726 /* start documentation of inline functions */
727
728 /*! \fn QList<QCPLayerable*> QCPLayer::children() const
729
730   Returns a list of all layerables on this layer. The order corresponds to the rendering order:
731   layerables with higher indices are drawn above layerables with lower indices.
732 */
733
734 /*! \fn int QCPLayer::index() const
735
736   Returns the index this layer has in the QCustomPlot. The index is the integer number by which this layer can be
737   accessed via \ref QCustomPlot::layer.
738
739   Layers with higher indices will be drawn above layers with lower indices.
740 */
741
742 /* end documentation of inline functions */
743
744 /*!
745   Creates a new QCPLayer instance.
746
747   Normally you shouldn't directly instantiate layers, use \ref QCustomPlot::addLayer instead.
748
749   \warning It is not checked that \a layerName is actually a unique layer name in \a parentPlot.
750   This check is only performed by \ref QCustomPlot::addLayer.
751 */
752 QCPLayer::QCPLayer(QCustomPlot *parentPlot, const QString &layerName) :
753   QObject(parentPlot),
754   mParentPlot(parentPlot),
755   mName(layerName),
756   mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function
757   mVisible(true)
758 {
759   // Note: no need to make sure layerName is unique, because layer
760   // management is done with QCustomPlot functions.
761 }
762
763 QCPLayer::~QCPLayer()
764 {
765   // If child layerables are still on this layer, detach them, so they don't try to reach back to this
766   // then invalid layer once they get deleted/moved themselves. This only happens when layers are deleted
767   // directly, like in the QCustomPlot destructor. (The regular layer removal procedure for the user is to
768   // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.)
769
770   while (!mChildren.isEmpty())
771     mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild()
772
773   if (mParentPlot->currentLayer() == this)
774     qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or 0 beforehand.";
775 }
776
777 /*!
778   Sets whether this layer is visible or not. If \a visible is set to false, all layerables on this
779   layer will be invisible.
780
781   This function doesn't change the visibility property of the layerables (\ref
782   QCPLayerable::setVisible), but the \ref QCPLayerable::realVisibility of each layerable takes the
783   visibility of the parent layer into account.
784 */
785 void QCPLayer::setVisible(bool visible)
786 {
787   mVisible = visible;
788 }
789
790 /*! \internal
791
792   Adds the \a layerable to the list of this layer. If \a prepend is set to true, the layerable will
793   be prepended to the list, i.e. be drawn beneath the other layerables already in the list.
794
795   This function does not change the \a mLayer member of \a layerable to this layer. (Use
796   QCPLayerable::setLayer to change the layer of an object, not this function.)
797
798   \see removeChild
799 */
800 void QCPLayer::addChild(QCPLayerable *layerable, bool prepend)
801 {
802   if (!mChildren.contains(layerable))
803   {
804     if (prepend)
805       mChildren.prepend(layerable);
806     else
807       mChildren.append(layerable);
808   } else
809     qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast<quintptr>(layerable);
810 }
811
812 /*! \internal
813
814   Removes the \a layerable from the list of this layer.
815
816   This function does not change the \a mLayer member of \a layerable. (Use QCPLayerable::setLayer
817   to change the layer of an object, not this function.)
818
819   \see addChild
820 */
821 void QCPLayer::removeChild(QCPLayerable *layerable)
822 {
823   if (!mChildren.removeOne(layerable))
824     qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast<quintptr>(layerable);
825 }
826
827
828 ////////////////////////////////////////////////////////////////////////////////////////////////////
829 //////////////////// QCPLayerable
830 ////////////////////////////////////////////////////////////////////////////////////////////////////
831
832 /*! \class QCPLayerable
833   \brief Base class for all drawable objects
834
835   This is the abstract base class most visible objects derive from, e.g. plottables, axes, grid
836   etc.
837
838   Every layerable is on a layer (QCPLayer) which allows controlling the rendering order by stacking
839   the layers accordingly.
840
841   For details about the layering mechanism, see the QCPLayer documentation.
842 */
843
844 /* start documentation of inline functions */
845
846 /*! \fn QCPLayerable *QCPLayerable::parentLayerable() const
847
848   Returns the parent layerable of this layerable. The parent layerable is used to provide
849   visibility hierarchies in conjunction with the method \ref realVisibility. This way, layerables
850   only get drawn if their parent layerables are visible, too.
851
852   Note that a parent layerable is not necessarily also the QObject parent for memory management.
853   Further, a layerable doesn't always have a parent layerable, so this function may return 0.
854
855   A parent layerable is set implicitly with when placed inside layout elements and doesn't need to be
856   set manually by the user.
857 */
858
859 /* end documentation of inline functions */
860 /* start documentation of pure virtual functions */
861
862 /*! \fn virtual void QCPLayerable::applyDefaultAntialiasingHint(QCPPainter *painter) const = 0
863   \internal
864
865   This function applies the default antialiasing setting to the specified \a painter, using the
866   function \ref applyAntialiasingHint. It is the antialiasing state the painter is put in, when
867   \ref draw is called on the layerable. If the layerable has multiple entities whose antialiasing
868   setting may be specified individually, this function should set the antialiasing state of the
869   most prominent entity. In this case however, the \ref draw function usually calls the specialized
870   versions of this function before drawing each entity, effectively overriding the setting of the
871   default antialiasing hint.
872
873   <b>First example:</b> QCPGraph has multiple entities that have an antialiasing setting: The graph
874   line, fills, scatters and error bars. Those can be configured via QCPGraph::setAntialiased,
875   QCPGraph::setAntialiasedFill, QCPGraph::setAntialiasedScatters etc. Consequently, there isn't
876   only the QCPGraph::applyDefaultAntialiasingHint function (which corresponds to the graph line's
877   antialiasing), but specialized ones like QCPGraph::applyFillAntialiasingHint and
878   QCPGraph::applyScattersAntialiasingHint. So before drawing one of those entities, QCPGraph::draw
879   calls the respective specialized applyAntialiasingHint function.
880
881   <b>Second example:</b> QCPItemLine consists only of a line so there is only one antialiasing
882   setting which can be controlled with QCPItemLine::setAntialiased. (This function is inherited by
883   all layerables. The specialized functions, as seen on QCPGraph, must be added explicitly to the
884   respective layerable subclass.) Consequently it only has the normal
885   QCPItemLine::applyDefaultAntialiasingHint. The \ref QCPItemLine::draw function doesn't need to
886   care about setting any antialiasing states, because the default antialiasing hint is already set
887   on the painter when the \ref draw function is called, and that's the state it wants to draw the
888   line with.
889 */
890
891 /*! \fn virtual void QCPLayerable::draw(QCPPainter *painter) const = 0
892   \internal
893
894   This function draws the layerable with the specified \a painter. It is only called by
895   QCustomPlot, if the layerable is visible (\ref setVisible).
896
897   Before this function is called, the painter's antialiasing state is set via \ref
898   applyDefaultAntialiasingHint, see the documentation there. Further, the clipping rectangle was
899   set to \ref clipRect.
900 */
901
902 /* end documentation of pure virtual functions */
903 /* start documentation of signals */
904
905 /*! \fn void QCPLayerable::layerChanged(QCPLayer *newLayer);
906
907   This signal is emitted when the layer of this layerable changes, i.e. this layerable is moved to
908   a different layer.
909
910   \see setLayer
911 */
912
913 /* end documentation of signals */
914
915 /*!
916   Creates a new QCPLayerable instance.
917
918   Since QCPLayerable is an abstract base class, it can't be instantiated directly. Use one of the
919   derived classes.
920
921   If \a plot is provided, it automatically places itself on the layer named \a targetLayer. If \a
922   targetLayer is an empty string, it places itself on the current layer of the plot (see \ref
923   QCustomPlot::setCurrentLayer).
924
925   It is possible to provide 0 as \a plot. In that case, you should assign a parent plot at a later
926   time with \ref initializeParentPlot.
927
928   The layerable's parent layerable is set to \a parentLayerable, if provided. Direct layerable parents
929   are mainly used to control visibility in a hierarchy of layerables. This means a layerable is
930   only drawn, if all its ancestor layerables are also visible. Note that \a parentLayerable does
931   not become the QObject-parent (for memory management) of this layerable, \a plot does.
932 */
933 QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) :
934   QObject(plot),
935   mVisible(true),
936   mParentPlot(plot),
937   mParentLayerable(parentLayerable),
938   mLayer(0),
939   mAntialiased(true)
940 {
941   if (mParentPlot)
942   {
943     if (targetLayer.isEmpty())
944       setLayer(mParentPlot->currentLayer());
945     else if (!setLayer(targetLayer))
946       qDebug() << Q_FUNC_INFO << "setting QCPlayerable initial layer to" << targetLayer << "failed.";
947   }
948 }
949
950 QCPLayerable::~QCPLayerable()
951 {
952   if (mLayer)
953   {
954     mLayer->removeChild(this);
955     mLayer = 0;
956   }
957 }
958
959 /*!
960   Sets the visibility of this layerable object. If an object is not visible, it will not be drawn
961   on the QCustomPlot surface, and user interaction with it (e.g. click and selection) is not
962   possible.
963 */
964 void QCPLayerable::setVisible(bool on)
965 {
966   mVisible = on;
967 }
968
969 /*!
970   Sets the \a layer of this layerable object. The object will be placed on top of the other objects
971   already on \a layer.
972
973   Returns true on success, i.e. if \a layer is a valid layer.
974 */
975 bool QCPLayerable::setLayer(QCPLayer *layer)
976 {
977   return moveToLayer(layer, false);
978 }
979
980 /*! \overload
981   Sets the layer of this layerable object by name
982
983   Returns true on success, i.e. if \a layerName is a valid layer name.
984 */
985 bool QCPLayerable::setLayer(const QString &layerName)
986 {
987   if (!mParentPlot)
988   {
989     qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
990     return false;
991   }
992   if (QCPLayer *layer = mParentPlot->layer(layerName))
993   {
994     return setLayer(layer);
995   } else
996   {
997     qDebug() << Q_FUNC_INFO << "there is no layer with name" << layerName;
998     return false;
999   }
1000 }
1001
1002 /*!
1003   Sets whether this object will be drawn antialiased or not.
1004
1005   Note that antialiasing settings may be overridden by QCustomPlot::setAntialiasedElements and
1006   QCustomPlot::setNotAntialiasedElements.
1007 */
1008 void QCPLayerable::setAntialiased(bool enabled)
1009 {
1010   mAntialiased = enabled;
1011 }
1012
1013 /*!
1014   Returns whether this layerable is visible, taking the visibility of the layerable parent and the
1015   visibility of the layer this layerable is on into account. This is the method that is consulted
1016   to decide whether a layerable shall be drawn or not.
1017
1018   If this layerable has a direct layerable parent (usually set via hierarchies implemented in
1019   subclasses, like in the case of QCPLayoutElement), this function returns true only if this
1020   layerable has its visibility set to true and the parent layerable's \ref realVisibility returns
1021   true.
1022
1023   If this layerable doesn't have a direct layerable parent, returns the state of this layerable's
1024   visibility.
1025 */
1026 bool QCPLayerable::realVisibility() const
1027 {
1028   return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility());
1029 }
1030
1031 /*!
1032   This function is used to decide whether a click hits a layerable object or not.
1033
1034   \a pos is a point in pixel coordinates on the QCustomPlot surface. This function returns the
1035   shortest pixel distance of this point to the object. If the object is either invisible or the
1036   distance couldn't be determined, -1.0 is returned. Further, if \a onlySelectable is true and the
1037   object is not selectable, -1.0 is returned, too.
1038
1039   If the item is represented not by single lines but by an area like QCPItemRect or QCPItemText, a
1040   click inside the area returns a constant value greater zero (typically the selectionTolerance of
1041   the parent QCustomPlot multiplied by 0.99). If the click lies outside the area, this function
1042   returns -1.0.
1043
1044   Providing a constant value for area objects allows selecting line objects even when they are
1045   obscured by such area objects, by clicking close to the lines (i.e. closer than
1046   0.99*selectionTolerance).
1047
1048   The actual setting of the selection state is not done by this function. This is handled by the
1049   parent QCustomPlot when the mouseReleaseEvent occurs, and the finally selected object is notified
1050   via the selectEvent/deselectEvent methods.
1051
1052   \a details is an optional output parameter. Every layerable subclass may place any information
1053   in \a details. This information will be passed to \ref selectEvent when the parent QCustomPlot
1054   decides on the basis of this selectTest call, that the object was successfully selected. The
1055   subsequent call to \ref selectEvent will carry the \a details. This is useful for multi-part
1056   objects (like QCPAxis). This way, a possibly complex calculation to decide which part was clicked
1057   is only done once in \ref selectTest. The result (i.e. the actually clicked part) can then be
1058   placed in \a details. So in the subsequent \ref selectEvent, the decision which part was
1059   selected doesn't have to be done a second time for a single selection operation.
1060
1061   You may pass 0 as \a details to indicate that you are not interested in those selection details.
1062
1063   \see selectEvent, deselectEvent, QCustomPlot::setInteractions
1064 */
1065 double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
1066 {
1067   Q_UNUSED(pos)
1068   Q_UNUSED(onlySelectable)
1069   Q_UNUSED(details)
1070   return -1.0;
1071 }
1072
1073 /*! \internal
1074
1075   Sets the parent plot of this layerable. Use this function once to set the parent plot if you have
1076   passed 0 in the constructor. It can not be used to move a layerable from one QCustomPlot to
1077   another one.
1078
1079   Note that, unlike when passing a non-null parent plot in the constructor, this function does not
1080   make \a parentPlot the QObject-parent of this layerable. If you want this, call
1081   QObject::setParent(\a parentPlot) in addition to this function.
1082
1083   Further, you will probably want to set a layer (\ref setLayer) after calling this function, to
1084   make the layerable appear on the QCustomPlot.
1085
1086   The parent plot change will be propagated to subclasses via a call to \ref parentPlotInitialized
1087   so they can react accordingly (e.g. also initialize the parent plot of child layerables, like
1088   QCPLayout does).
1089 */
1090 void QCPLayerable::initializeParentPlot(QCustomPlot *parentPlot)
1091 {
1092   if (mParentPlot)
1093   {
1094     qDebug() << Q_FUNC_INFO << "called with mParentPlot already initialized";
1095     return;
1096   }
1097
1098   if (!parentPlot)
1099     qDebug() << Q_FUNC_INFO << "called with parentPlot zero";
1100
1101   mParentPlot = parentPlot;
1102   parentPlotInitialized(mParentPlot);
1103 }
1104
1105 /*! \internal
1106
1107   Sets the parent layerable of this layerable to \a parentLayerable. Note that \a parentLayerable does not
1108   become the QObject-parent (for memory management) of this layerable.
1109
1110   The parent layerable has influence on the return value of the \ref realVisibility method. Only
1111   layerables with a fully visible parent tree will return true for \ref realVisibility, and thus be
1112   drawn.
1113
1114   \see realVisibility
1115 */
1116 void QCPLayerable::setParentLayerable(QCPLayerable *parentLayerable)
1117 {
1118   mParentLayerable = parentLayerable;
1119 }
1120
1121 /*! \internal
1122
1123   Moves this layerable object to \a layer. If \a prepend is true, this object will be prepended to
1124   the new layer's list, i.e. it will be drawn below the objects already on the layer. If it is
1125   false, the object will be appended.
1126
1127   Returns true on success, i.e. if \a layer is a valid layer.
1128 */
1129 bool QCPLayerable::moveToLayer(QCPLayer *layer, bool prepend)
1130 {
1131   if (layer && !mParentPlot)
1132   {
1133     qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
1134     return false;
1135   }
1136   if (layer && layer->parentPlot() != mParentPlot)
1137   {
1138     qDebug() << Q_FUNC_INFO << "layer" << layer->name() << "is not in same QCustomPlot as this layerable";
1139     return false;
1140   }
1141
1142   QCPLayer *oldLayer = mLayer;
1143   if (mLayer)
1144     mLayer->removeChild(this);
1145   mLayer = layer;
1146   if (mLayer)
1147     mLayer->addChild(this, prepend);
1148   if (mLayer != oldLayer)
1149     emit layerChanged(mLayer);
1150   return true;
1151 }
1152
1153 /*! \internal
1154
1155   Sets the QCPainter::setAntialiasing state on the provided \a painter, depending on the \a
1156   localAntialiased value as well as the overrides \ref QCustomPlot::setAntialiasedElements and \ref
1157   QCustomPlot::setNotAntialiasedElements. Which override enum this function takes into account is
1158   controlled via \a overrideElement.
1159 */
1160 void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const
1161 {
1162   if (mParentPlot && mParentPlot->notAntialiasedElements().testFlag(overrideElement))
1163     painter->setAntialiasing(false);
1164   else if (mParentPlot && mParentPlot->antialiasedElements().testFlag(overrideElement))
1165     painter->setAntialiasing(true);
1166   else
1167     painter->setAntialiasing(localAntialiased);
1168 }
1169
1170 /*! \internal
1171
1172   This function is called by \ref initializeParentPlot, to allow subclasses to react on the setting
1173   of a parent plot. This is the case when 0 was passed as parent plot in the constructor, and the
1174   parent plot is set at a later time.
1175
1176   For example, QCPLayoutElement/QCPLayout hierarchies may be created independently of any
1177   QCustomPlot at first. When they are then added to a layout inside the QCustomPlot, the top level
1178   element of the hierarchy gets its parent plot initialized with \ref initializeParentPlot. To
1179   propagate the parent plot to all the children of the hierarchy, the top level element then uses
1180   this function to pass the parent plot on to its child elements.
1181
1182   The default implementation does nothing.
1183
1184   \see initializeParentPlot
1185 */
1186 void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot)
1187 {
1188    Q_UNUSED(parentPlot)
1189 }
1190
1191 /*! \internal
1192
1193   Returns the selection category this layerable shall belong to. The selection category is used in
1194   conjunction with \ref QCustomPlot::setInteractions to control which objects are selectable and
1195   which aren't.
1196
1197   Subclasses that don't fit any of the normal \ref QCP::Interaction values can use \ref
1198   QCP::iSelectOther. This is what the default implementation returns.
1199
1200   \see QCustomPlot::setInteractions
1201 */
1202 QCP::Interaction QCPLayerable::selectionCategory() const
1203 {
1204   return QCP::iSelectOther;
1205 }
1206
1207 /*! \internal
1208
1209   Returns the clipping rectangle of this layerable object. By default, this is the viewport of the
1210   parent QCustomPlot. Specific subclasses may reimplement this function to provide different
1211   clipping rects.
1212
1213   The returned clipping rect is set on the painter before the draw function of the respective
1214   object is called.
1215 */
1216 QRect QCPLayerable::clipRect() const
1217 {
1218   if (mParentPlot)
1219     return mParentPlot->viewport();
1220   else
1221     return QRect();
1222 }
1223
1224 /*! \internal
1225
1226   This event is called when the layerable shall be selected, as a consequence of a click by the
1227   user. Subclasses should react to it by setting their selection state appropriately. The default
1228   implementation does nothing.
1229
1230   \a event is the mouse event that caused the selection. \a additive indicates, whether the user
1231   was holding the multi-select-modifier while performing the selection (see \ref
1232   QCustomPlot::setMultiSelectModifier). if \a additive is true, the selection state must be toggled
1233   (i.e. become selected when unselected and unselected when selected).
1234
1235   Every selectEvent is preceded by a call to \ref selectTest, which has returned positively (i.e.
1236   returned a value greater than 0 and less than the selection tolerance of the parent QCustomPlot).
1237   The \a details data you output from \ref selectTest is fed back via \a details here. You may
1238   use it to transport any kind of information from the selectTest to the possibly subsequent
1239   selectEvent. Usually \a details is used to transfer which part was clicked, if it is a layerable
1240   that has multiple individually selectable parts (like QCPAxis). This way selectEvent doesn't need
1241   to do the calculation again to find out which part was actually clicked.
1242
1243   \a selectionStateChanged is an output parameter. If the pointer is non-null, this function must
1244   set the value either to true or false, depending on whether the selection state of this layerable
1245   was actually changed. For layerables that only are selectable as a whole and not in parts, this
1246   is simple: if \a additive is true, \a selectionStateChanged must also be set to true, because the
1247   selection toggles. If \a additive is false, \a selectionStateChanged is only set to true, if the
1248   layerable was previously unselected and now is switched to the selected state.
1249
1250   \see selectTest, deselectEvent
1251 */
1252 void QCPLayerable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
1253 {
1254   Q_UNUSED(event)
1255   Q_UNUSED(additive)
1256   Q_UNUSED(details)
1257   Q_UNUSED(selectionStateChanged)
1258 }
1259
1260 /*! \internal
1261
1262   This event is called when the layerable shall be deselected, either as consequence of a user
1263   interaction or a call to \ref QCustomPlot::deselectAll. Subclasses should react to it by
1264   unsetting their selection appropriately.
1265
1266   just as in \ref selectEvent, the output parameter \a selectionStateChanged (if non-null), must
1267   return true or false when the selection state of this layerable has changed or not changed,
1268   respectively.
1269
1270   \see selectTest, selectEvent
1271 */
1272 void QCPLayerable::deselectEvent(bool *selectionStateChanged)
1273 {
1274   Q_UNUSED(selectionStateChanged)
1275 }
1276
1277
1278 ////////////////////////////////////////////////////////////////////////////////////////////////////
1279 //////////////////// QCPRange
1280 ////////////////////////////////////////////////////////////////////////////////////////////////////
1281 /*! \class QCPRange
1282   \brief Represents the range an axis is encompassing.
1283
1284   contains a \a lower and \a upper double value and provides convenience input, output and
1285   modification functions.
1286
1287   \see QCPAxis::setRange
1288 */
1289
1290 /*!
1291   Minimum range size (\a upper - \a lower) the range changing functions will accept. Smaller
1292   intervals would cause errors due to the 11-bit exponent of double precision numbers,
1293   corresponding to a minimum magnitude of roughly 1e-308.
1294   \see validRange, maxRange
1295 */
1296 const double QCPRange::minRange = 1e-280;
1297
1298 /*!
1299   Maximum values (negative and positive) the range will accept in range-changing functions.
1300   Larger absolute values would cause errors due to the 11-bit exponent of double precision numbers,
1301   corresponding to a maximum magnitude of roughly 1e308.
1302   Since the number of planck-volumes in the entire visible universe is only ~1e183, this should
1303   be enough.
1304   \see validRange, minRange
1305 */
1306 const double QCPRange::maxRange = 1e250;
1307
1308 /*!
1309   Constructs a range with \a lower and \a upper set to zero.
1310 */
1311 QCPRange::QCPRange() :
1312   lower(0),
1313   upper(0)
1314 {
1315 }
1316
1317 /*! \overload
1318   Constructs a range with the specified \a lower and \a upper values.
1319 */
1320 QCPRange::QCPRange(double lower, double upper) :
1321   lower(lower),
1322   upper(upper)
1323 {
1324   normalize();
1325 }
1326
1327 /*!
1328   Returns the size of the range, i.e. \a upper-\a lower
1329 */
1330 double QCPRange::size() const
1331 {
1332   return upper-lower;
1333 }
1334
1335 /*!
1336   Returns the center of the range, i.e. (\a upper+\a lower)*0.5
1337 */
1338 double QCPRange::center() const
1339 {
1340   return (upper+lower)*0.5;
1341 }
1342
1343 /*!
1344   Makes sure \a lower is numerically smaller than \a upper. If this is not the case, the values
1345   are swapped.
1346 */
1347 void QCPRange::normalize()
1348 {
1349   if (lower > upper)
1350     qSwap(lower, upper);
1351 }
1352
1353 /*!
1354   Expands this range such that \a otherRange is contained in the new range. It is assumed that both
1355   this range and \a otherRange are normalized (see \ref normalize).
1356
1357   If \a otherRange is already inside the current range, this function does nothing.
1358
1359   \see expanded
1360 */
1361 void QCPRange::expand(const QCPRange &otherRange)
1362 {
1363   if (lower > otherRange.lower)
1364     lower = otherRange.lower;
1365   if (upper < otherRange.upper)
1366     upper = otherRange.upper;
1367 }
1368
1369
1370 /*!
1371   Returns an expanded range that contains this and \a otherRange. It is assumed that both this
1372   range and \a otherRange are normalized (see \ref normalize).
1373
1374   \see expand
1375 */
1376 QCPRange QCPRange::expanded(const QCPRange &otherRange) const
1377 {
1378   QCPRange result = *this;
1379   result.expand(otherRange);
1380   return result;
1381 }
1382
1383 /*!
1384   Returns a sanitized version of the range. Sanitized means for logarithmic scales, that
1385   the range won't span the positive and negative sign domain, i.e. contain zero. Further
1386   \a lower will always be numerically smaller (or equal) to \a upper.
1387
1388   If the original range does span positive and negative sign domains or contains zero,
1389   the returned range will try to approximate the original range as good as possible.
1390   If the positive interval of the original range is wider than the negative interval, the
1391   returned range will only contain the positive interval, with lower bound set to \a rangeFac or
1392   \a rangeFac *\a upper, whichever is closer to zero. Same procedure is used if the negative interval
1393   is wider than the positive interval, this time by changing the \a upper bound.
1394 */
1395 QCPRange QCPRange::sanitizedForLogScale() const
1396 {
1397   double rangeFac = 1e-3;
1398   QCPRange sanitizedRange(lower, upper);
1399   sanitizedRange.normalize();
1400   // can't have range spanning negative and positive values in log plot, so change range to fix it
1401   //if (qFuzzyCompare(sanitizedRange.lower+1, 1) && !qFuzzyCompare(sanitizedRange.upper+1, 1))
1402   if (sanitizedRange.lower == 0.0 && sanitizedRange.upper != 0.0)
1403   {
1404     // case lower is 0
1405     if (rangeFac < sanitizedRange.upper*rangeFac)
1406       sanitizedRange.lower = rangeFac;
1407     else
1408       sanitizedRange.lower = sanitizedRange.upper*rangeFac;
1409   } //else if (!qFuzzyCompare(lower+1, 1) && qFuzzyCompare(upper+1, 1))
1410   else if (sanitizedRange.lower != 0.0 && sanitizedRange.upper == 0.0)
1411   {
1412     // case upper is 0
1413     if (-rangeFac > sanitizedRange.lower*rangeFac)
1414       sanitizedRange.upper = -rangeFac;
1415     else
1416       sanitizedRange.upper = sanitizedRange.lower*rangeFac;
1417   } else if (sanitizedRange.lower < 0 && sanitizedRange.upper > 0)
1418   {
1419     // find out whether negative or positive interval is wider to decide which sign domain will be chosen
1420     if (-sanitizedRange.lower > sanitizedRange.upper)
1421     {
1422       // negative is wider, do same as in case upper is 0
1423       if (-rangeFac > sanitizedRange.lower*rangeFac)
1424         sanitizedRange.upper = -rangeFac;
1425       else
1426         sanitizedRange.upper = sanitizedRange.lower*rangeFac;
1427     } else
1428     {
1429       // positive is wider, do same as in case lower is 0
1430       if (rangeFac < sanitizedRange.upper*rangeFac)
1431         sanitizedRange.lower = rangeFac;
1432       else
1433         sanitizedRange.lower = sanitizedRange.upper*rangeFac;
1434     }
1435   }
1436   // due to normalization, case lower>0 && upper<0 should never occur, because that implies upper<lower
1437   return sanitizedRange;
1438 }
1439
1440 /*!
1441   Returns a sanitized version of the range. Sanitized means for linear scales, that
1442   \a lower will always be numerically smaller (or equal) to \a upper.
1443 */
1444 QCPRange QCPRange::sanitizedForLinScale() const
1445 {
1446   QCPRange sanitizedRange(lower, upper);
1447   sanitizedRange.normalize();
1448   return sanitizedRange;
1449 }
1450
1451 /*!
1452   Returns true when \a value lies within or exactly on the borders of the range.
1453 */
1454 bool QCPRange::contains(double value) const
1455 {
1456   return value >= lower && value <= upper;
1457 }
1458
1459 /*!
1460   Checks, whether the specified range is within valid bounds, which are defined
1461   as QCPRange::maxRange and QCPRange::minRange.
1462   A valid range means:
1463   \li range bounds within -maxRange and maxRange
1464   \li range size above minRange
1465   \li range size below maxRange
1466 */
1467 bool QCPRange::validRange(double lower, double upper)
1468 {
1469   /*
1470   return (lower > -maxRange &&
1471           upper < maxRange &&
1472           qAbs(lower-upper) > minRange &&
1473           (lower < -minRange || lower > minRange) &&
1474           (upper < -minRange || upper > minRange));
1475           */
1476   return (lower > -maxRange &&
1477           upper < maxRange &&
1478           qAbs(lower-upper) > minRange &&
1479           qAbs(lower-upper) < maxRange);
1480 }
1481
1482 /*!
1483   \overload
1484   Checks, whether the specified range is within valid bounds, which are defined
1485   as QCPRange::maxRange and QCPRange::minRange.
1486   A valid range means:
1487   \li range bounds within -maxRange and maxRange
1488   \li range size above minRange
1489   \li range size below maxRange
1490 */
1491 bool QCPRange::validRange(const QCPRange &range)
1492 {
1493   /*
1494   return (range.lower > -maxRange &&
1495           range.upper < maxRange &&
1496           qAbs(range.lower-range.upper) > minRange &&
1497           qAbs(range.lower-range.upper) < maxRange &&
1498           (range.lower < -minRange || range.lower > minRange) &&
1499           (range.upper < -minRange || range.upper > minRange));
1500           */
1501   return (range.lower > -maxRange &&
1502           range.upper < maxRange &&
1503           qAbs(range.lower-range.upper) > minRange &&
1504           qAbs(range.lower-range.upper) < maxRange);
1505 }
1506
1507
1508 ////////////////////////////////////////////////////////////////////////////////////////////////////
1509 //////////////////// QCPMarginGroup
1510 ////////////////////////////////////////////////////////////////////////////////////////////////////
1511
1512 /*! \class QCPMarginGroup
1513   \brief A margin group allows synchronization of margin sides if working with multiple layout elements.
1514
1515   QCPMarginGroup allows you to tie a margin side of two or more layout elements together, such that
1516   they will all have the same size, based on the largest required margin in the group.
1517
1518   \n
1519   \image html QCPMarginGroup.png "Demonstration of QCPMarginGroup"
1520   \n
1521
1522   In certain situations it is desirable that margins at specific sides are synchronized across
1523   layout elements. For example, if one QCPAxisRect is below another one in a grid layout, it will
1524   provide a cleaner look to the user if the left and right margins of the two axis rects are of the
1525   same size. The left axis of the top axis rect will then be at the same horizontal position as the
1526   left axis of the lower axis rect, making them appear aligned. The same applies for the right
1527   axes. This is what QCPMarginGroup makes possible.
1528
1529   To add/remove a specific side of a layout element to/from a margin group, use the \ref
1530   QCPLayoutElement::setMarginGroup method. To completely break apart the margin group, either call
1531   \ref clear, or just delete the margin group.
1532
1533   \section QCPMarginGroup-example Example
1534
1535   First create a margin group:
1536   \code
1537   QCPMarginGroup *group = new QCPMarginGroup(customPlot);
1538   \endcode
1539   Then set this group on the layout element sides:
1540   \code
1541   customPlot->axisRect(0)->setMarginGroup(QCP::msLeft|QCP::msRight, group);
1542   customPlot->axisRect(1)->setMarginGroup(QCP::msLeft|QCP::msRight, group);
1543   \endcode
1544   Here, we've used the first two axis rects of the plot and synchronized their left margins with
1545   each other and their right margins with each other.
1546 */
1547
1548 /* start documentation of inline functions */
1549
1550 /*! \fn QList<QCPLayoutElement*> QCPMarginGroup::elements(QCP::MarginSide side) const
1551
1552   Returns a list of all layout elements that have their margin \a side associated with this margin
1553   group.
1554 */
1555
1556 /* end documentation of inline functions */
1557
1558 /*!
1559   Creates a new QCPMarginGroup instance in \a parentPlot.
1560 */
1561 QCPMarginGroup::QCPMarginGroup(QCustomPlot *parentPlot) :
1562   QObject(parentPlot),
1563   mParentPlot(parentPlot)
1564 {
1565   mChildren.insert(QCP::msLeft, QList<QCPLayoutElement*>());
1566   mChildren.insert(QCP::msRight, QList<QCPLayoutElement*>());
1567   mChildren.insert(QCP::msTop, QList<QCPLayoutElement*>());
1568   mChildren.insert(QCP::msBottom, QList<QCPLayoutElement*>());
1569 }
1570
1571 QCPMarginGroup::~QCPMarginGroup()
1572 {
1573   clear();
1574 }
1575
1576 /*!
1577   Returns whether this margin group is empty. If this function returns true, no layout elements use
1578   this margin group to synchronize margin sides.
1579 */
1580 bool QCPMarginGroup::isEmpty() const
1581 {
1582   QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
1583   while (it.hasNext())
1584   {
1585     it.next();
1586     if (!it.value().isEmpty())
1587       return false;
1588   }
1589   return true;
1590 }
1591
1592 /*!
1593   Clears this margin group. The synchronization of the margin sides that use this margin group is
1594   lifted and they will use their individual margin sizes again.
1595 */
1596 void QCPMarginGroup::clear()
1597 {
1598   // make all children remove themselves from this margin group:
1599   QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
1600   while (it.hasNext())
1601   {
1602     it.next();
1603     const QList<QCPLayoutElement*> elements = it.value();
1604     for (int i=elements.size()-1; i>=0; --i)
1605       elements.at(i)->setMarginGroup(it.key(), 0); // removes itself from mChildren via removeChild
1606   }
1607 }
1608
1609 /*! \internal
1610
1611   Returns the synchronized common margin for \a side. This is the margin value that will be used by
1612   the layout element on the respective side, if it is part of this margin group.
1613
1614   The common margin is calculated by requesting the automatic margin (\ref
1615   QCPLayoutElement::calculateAutoMargin) of each element associated with \a side in this margin
1616   group, and choosing the largest returned value. (QCPLayoutElement::minimumMargins is taken into
1617   account, too.)
1618 */
1619 int QCPMarginGroup::commonMargin(QCP::MarginSide side) const
1620 {
1621   // query all automatic margins of the layout elements in this margin group side and find maximum:
1622   int result = 0;
1623   const QList<QCPLayoutElement*> elements = mChildren.value(side);
1624   for (int i=0; i<elements.size(); ++i)
1625   {
1626     if (!elements.at(i)->autoMargins().testFlag(side))
1627       continue;
1628     int m = qMax(elements.at(i)->calculateAutoMargin(side), QCP::getMarginValue(elements.at(i)->minimumMargins(), side));
1629     if (m > result)
1630       result = m;
1631   }
1632   return result;
1633 }
1634
1635 /*! \internal
1636
1637   Adds \a element to the internal list of child elements, for the margin \a side.
1638
1639   This function does not modify the margin group property of \a element.
1640 */
1641 void QCPMarginGroup::addChild(QCP::MarginSide side, QCPLayoutElement *element)
1642 {
1643   if (!mChildren[side].contains(element))
1644     mChildren[side].append(element);
1645   else
1646     qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast<quintptr>(element);
1647 }
1648
1649 /*! \internal
1650
1651   Removes \a element from the internal list of child elements, for the margin \a side.
1652
1653   This function does not modify the margin group property of \a element.
1654 */
1655 void QCPMarginGroup::removeChild(QCP::MarginSide side, QCPLayoutElement *element)
1656 {
1657   if (!mChildren[side].removeOne(element))
1658     qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast<quintptr>(element);
1659 }
1660
1661
1662 ////////////////////////////////////////////////////////////////////////////////////////////////////
1663 //////////////////// QCPLayoutElement
1664 ////////////////////////////////////////////////////////////////////////////////////////////////////
1665
1666 /*! \class QCPLayoutElement
1667   \brief The abstract base class for all objects that form \ref thelayoutsystem "the layout system".
1668
1669   This is an abstract base class. As such, it can't be instantiated directly, rather use one of its subclasses.
1670
1671   A Layout element is a rectangular object which can be placed in layouts. It has an outer rect
1672   (QCPLayoutElement::outerRect) and an inner rect (\ref QCPLayoutElement::rect). The difference
1673   between outer and inner rect is called its margin. The margin can either be set to automatic or
1674   manual (\ref setAutoMargins) on a per-side basis. If a side is set to manual, that margin can be
1675   set explicitly with \ref setMargins and will stay fixed at that value. If it's set to automatic,
1676   the layout element subclass will control the value itself (via \ref calculateAutoMargin).
1677
1678   Layout elements can be placed in layouts (base class QCPLayout) like QCPLayoutGrid. The top level
1679   layout is reachable via \ref QCustomPlot::plotLayout, and is a \ref QCPLayoutGrid. Since \ref
1680   QCPLayout itself derives from \ref QCPLayoutElement, layouts can be nested.
1681
1682   Thus in QCustomPlot one can divide layout elements into two categories: The ones that are
1683   invisible by themselves, because they don't draw anything. Their only purpose is to manage the
1684   position and size of other layout elements. This category of layout elements usually use
1685   QCPLayout as base class. Then there is the category of layout elements which actually draw
1686   something. For example, QCPAxisRect, QCPLegend and QCPPlotTitle are of this category. This does
1687   not necessarily mean that the latter category can't have child layout elements. QCPLegend for
1688   instance, actually derives from QCPLayoutGrid and the individual legend items are child layout
1689   elements in the grid layout.
1690 */
1691
1692 /* start documentation of inline functions */
1693
1694 /*! \fn QCPLayout *QCPLayoutElement::layout() const
1695
1696   Returns the parent layout of this layout element.
1697 */
1698
1699 /*! \fn QRect QCPLayoutElement::rect() const
1700
1701   Returns the inner rect of this layout element. The inner rect is the outer rect (\ref
1702   setOuterRect) shrinked by the margins (\ref setMargins, \ref setAutoMargins).
1703
1704   In some cases, the area between outer and inner rect is left blank. In other cases the margin
1705   area is used to display peripheral graphics while the main content is in the inner rect. This is
1706   where automatic margin calculation becomes interesting because it allows the layout element to
1707   adapt the margins to the peripheral graphics it wants to draw. For example, \ref QCPAxisRect
1708   draws the axis labels and tick labels in the margin area, thus needs to adjust the margins (if
1709   \ref setAutoMargins is enabled) according to the space required by the labels of the axes.
1710 */
1711
1712 /*! \fn virtual void QCPLayoutElement::mousePressEvent(QMouseEvent *event)
1713
1714   This event is called, if the mouse was pressed while being inside the outer rect of this layout
1715   element.
1716 */
1717
1718 /*! \fn virtual void QCPLayoutElement::mouseMoveEvent(QMouseEvent *event)
1719
1720   This event is called, if the mouse is moved inside the outer rect of this layout element.
1721 */
1722
1723 /*! \fn virtual void QCPLayoutElement::mouseReleaseEvent(QMouseEvent *event)
1724
1725   This event is called, if the mouse was previously pressed inside the outer rect of this layout
1726   element and is now released.
1727 */
1728
1729 /*! \fn virtual void QCPLayoutElement::mouseDoubleClickEvent(QMouseEvent *event)
1730
1731   This event is called, if the mouse is double-clicked inside the outer rect of this layout
1732   element.
1733 */
1734
1735 /*! \fn virtual void QCPLayoutElement::wheelEvent(QWheelEvent *event)
1736
1737   This event is called, if the mouse wheel is scrolled while the cursor is inside the rect of this
1738   layout element.
1739 */
1740
1741 /* end documentation of inline functions */
1742
1743 /*!
1744   Creates an instance of QCPLayoutElement and sets default values.
1745 */
1746 QCPLayoutElement::QCPLayoutElement(QCustomPlot *parentPlot) :
1747   QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout)
1748   mParentLayout(0),
1749   mMinimumSize(),
1750   mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX),
1751   mRect(0, 0, 0, 0),
1752   mOuterRect(0, 0, 0, 0),
1753   mMargins(0, 0, 0, 0),
1754   mMinimumMargins(0, 0, 0, 0),
1755   mAutoMargins(QCP::msAll)
1756 {
1757 }
1758
1759 QCPLayoutElement::~QCPLayoutElement()
1760 {
1761   setMarginGroup(QCP::msAll, 0); // unregister at margin groups, if there are any
1762   // unregister at layout:
1763   if (qobject_cast<QCPLayout*>(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor
1764     mParentLayout->take(this);
1765 }
1766
1767 /*!
1768   Sets the outer rect of this layout element. If the layout element is inside a layout, the layout
1769   sets the position and size of this layout element using this function.
1770
1771   Calling this function externally has no effect, since the layout will overwrite any changes to
1772   the outer rect upon the next replot.
1773
1774   The layout element will adapt its inner \ref rect by applying the margins inward to the outer rect.
1775
1776   \see rect
1777 */
1778 void QCPLayoutElement::setOuterRect(const QRect &rect)
1779 {
1780   if (mOuterRect != rect)
1781   {
1782     mOuterRect = rect;
1783     mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
1784   }
1785 }
1786
1787 /*!
1788   Sets the margins of this layout element. If \ref setAutoMargins is disabled for some or all
1789   sides, this function is used to manually set the margin on those sides. Sides that are still set
1790   to be handled automatically are ignored and may have any value in \a margins.
1791
1792   The margin is the distance between the outer rect (controlled by the parent layout via \ref
1793   setOuterRect) and the inner \ref rect (which usually contains the main content of this layout
1794   element).
1795
1796   \see setAutoMargins
1797 */
1798 void QCPLayoutElement::setMargins(const QMargins &margins)
1799 {
1800   if (mMargins != margins)
1801   {
1802     mMargins = margins;
1803     mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
1804   }
1805 }
1806
1807 /*!
1808   If \ref setAutoMargins is enabled on some or all margins, this function is used to provide
1809   minimum values for those margins.
1810
1811   The minimum values are not enforced on margin sides that were set to be under manual control via
1812   \ref setAutoMargins.
1813
1814   \see setAutoMargins
1815 */
1816 void QCPLayoutElement::setMinimumMargins(const QMargins &margins)
1817 {
1818   if (mMinimumMargins != margins)
1819   {
1820     mMinimumMargins = margins;
1821   }
1822 }
1823
1824 /*!
1825   Sets on which sides the margin shall be calculated automatically. If a side is calculated
1826   automatically, a minimum margin value may be provided with \ref setMinimumMargins. If a side is
1827   set to be controlled manually, the value may be specified with \ref setMargins.
1828
1829   Margin sides that are under automatic control may participate in a \ref QCPMarginGroup (see \ref
1830   setMarginGroup), to synchronize (align) it with other layout elements in the plot.
1831
1832   \see setMinimumMargins, setMargins
1833 */
1834 void QCPLayoutElement::setAutoMargins(QCP::MarginSides sides)
1835 {
1836   mAutoMargins = sides;
1837 }
1838
1839 /*!
1840   Sets the minimum size for the inner \ref rect of this layout element. A parent layout tries to
1841   respect the \a size here by changing row/column sizes in the layout accordingly.
1842
1843   If the parent layout size is not sufficient to satisfy all minimum size constraints of its child
1844   layout elements, the layout may set a size that is actually smaller than \a size. QCustomPlot
1845   propagates the layout's size constraints to the outside by setting its own minimum QWidget size
1846   accordingly, so violations of \a size should be exceptions.
1847 */
1848 void QCPLayoutElement::setMinimumSize(const QSize &size)
1849 {
1850   if (mMinimumSize != size)
1851   {
1852     mMinimumSize = size;
1853     if (mParentLayout)
1854       mParentLayout->sizeConstraintsChanged();
1855   }
1856 }
1857
1858 /*! \overload
1859
1860   Sets the minimum size for the inner \ref rect of this layout element.
1861 */
1862 void QCPLayoutElement::setMinimumSize(int width, int height)
1863 {
1864   setMinimumSize(QSize(width, height));
1865 }
1866
1867 /*!
1868   Sets the maximum size for the inner \ref rect of this layout element. A parent layout tries to
1869   respect the \a size here by changing row/column sizes in the layout accordingly.
1870 */
1871 void QCPLayoutElement::setMaximumSize(const QSize &size)
1872 {
1873   if (mMaximumSize != size)
1874   {
1875     mMaximumSize = size;
1876     if (mParentLayout)
1877       mParentLayout->sizeConstraintsChanged();
1878   }
1879 }
1880
1881 /*! \overload
1882
1883   Sets the maximum size for the inner \ref rect of this layout element.
1884 */
1885 void QCPLayoutElement::setMaximumSize(int width, int height)
1886 {
1887   setMaximumSize(QSize(width, height));
1888 }
1889
1890 /*!
1891   Sets the margin \a group of the specified margin \a sides.
1892
1893   Margin groups allow synchronizing specified margins across layout elements, see the documentation
1894   of \ref QCPMarginGroup.
1895
1896   To unset the margin group of \a sides, set \a group to 0.
1897
1898   Note that margin groups only work for margin sides that are set to automatic (\ref
1899   setAutoMargins).
1900 */
1901 void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group)
1902 {
1903   QVector<QCP::MarginSide> sideVector;
1904   if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft);
1905   if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight);
1906   if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop);
1907   if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom);
1908
1909   for (int i=0; i<sideVector.size(); ++i)
1910   {
1911     QCP::MarginSide side = sideVector.at(i);
1912     if (marginGroup(side) != group)
1913     {
1914       QCPMarginGroup *oldGroup = marginGroup(side);
1915       if (oldGroup) // unregister at old group
1916         oldGroup->removeChild(side, this);
1917
1918       if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there
1919       {
1920         mMarginGroups.remove(side);
1921       } else // setting to a new group
1922       {
1923         mMarginGroups[side] = group;
1924         group->addChild(side, this);
1925       }
1926     }
1927   }
1928 }
1929
1930 /*!
1931   Updates the layout element and sub-elements. This function is automatically called before every
1932   replot by the parent layout element. It is called multiple times, once for every \ref
1933   UpdatePhase. The phases are run through in the order of the enum values. For details about what
1934   happens at the different phases, see the documentation of \ref UpdatePhase.
1935
1936   Layout elements that have child elements should call the \ref update method of their child
1937   elements, and pass the current \a phase unchanged.
1938
1939   The default implementation executes the automatic margin mechanism in the \ref upMargins phase.
1940   Subclasses should make sure to call the base class implementation.
1941 */
1942 void QCPLayoutElement::update(UpdatePhase phase)
1943 {
1944   if (phase == upMargins)
1945   {
1946     if (mAutoMargins != QCP::msNone)
1947     {
1948       // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group:
1949       QMargins newMargins = mMargins;
1950       foreach (QCP::MarginSide side, QList<QCP::MarginSide>() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom)
1951       {
1952         if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically
1953         {
1954           if (mMarginGroups.contains(side))
1955             QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group
1956           else
1957             QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly
1958           // apply minimum margin restrictions:
1959           if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side))
1960             QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side));
1961         }
1962       }
1963       setMargins(newMargins);
1964     }
1965   }
1966 }
1967
1968 /*!
1969   Returns the minimum size this layout element (the inner \ref rect) may be compressed to.
1970
1971   if a minimum size (\ref setMinimumSize) was not set manually, parent layouts consult this
1972   function to determine the minimum allowed size of this layout element. (A manual minimum size is
1973   considered set if it is non-zero.)
1974 */
1975 QSize QCPLayoutElement::minimumSizeHint() const
1976 {
1977   return mMinimumSize;
1978 }
1979
1980 /*!
1981   Returns the maximum size this layout element (the inner \ref rect) may be expanded to.
1982
1983   if a maximum size (\ref setMaximumSize) was not set manually, parent layouts consult this
1984   function to determine the maximum allowed size of this layout element. (A manual maximum size is
1985   considered set if it is smaller than Qt's QWIDGETSIZE_MAX.)
1986 */
1987 QSize QCPLayoutElement::maximumSizeHint() const
1988 {
1989   return mMaximumSize;
1990 }
1991
1992 /*!
1993   Returns a list of all child elements in this layout element. If \a recursive is true, all
1994   sub-child elements are included in the list, too.
1995
1996   \warning There may be entries with value 0 in the returned list. (For example, QCPLayoutGrid may have
1997   empty cells which yield 0 at the respective index.)
1998 */
1999 QList<QCPLayoutElement*> QCPLayoutElement::elements(bool recursive) const
2000 {
2001   Q_UNUSED(recursive)
2002   return QList<QCPLayoutElement*>();
2003 }
2004
2005 /*!
2006   Layout elements are sensitive to events inside their outer rect. If \a pos is within the outer
2007   rect, this method returns a value corresponding to 0.99 times the parent plot's selection
2008   tolerance. However, layout elements are not selectable by default. So if \a onlySelectable is
2009   true, -1.0 is returned.
2010
2011   See \ref QCPLayerable::selectTest for a general explanation of this virtual method.
2012
2013   QCPLayoutElement subclasses may reimplement this method to provide more specific selection test
2014   behaviour.
2015 */
2016 double QCPLayoutElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
2017 {
2018   Q_UNUSED(details)
2019
2020   if (onlySelectable)
2021     return -1;
2022
2023   if (QRectF(mOuterRect).contains(pos))
2024   {
2025     if (mParentPlot)
2026       return mParentPlot->selectionTolerance()*0.99;
2027     else
2028     {
2029       qDebug() << Q_FUNC_INFO << "parent plot not defined";
2030       return -1;
2031     }
2032   } else
2033     return -1;
2034 }
2035
2036 /*! \internal
2037
2038   propagates the parent plot initialization to all child elements, by calling \ref
2039   QCPLayerable::initializeParentPlot on them.
2040 */
2041 void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot)
2042 {
2043   foreach (QCPLayoutElement* el, elements(false))
2044   {
2045     if (!el->parentPlot())
2046       el->initializeParentPlot(parentPlot);
2047   }
2048 }
2049
2050 /*! \internal
2051
2052   Returns the margin size for this \a side. It is used if automatic margins is enabled for this \a
2053   side (see \ref setAutoMargins). If a minimum margin was set with \ref setMinimumMargins, the
2054   returned value will not be smaller than the specified minimum margin.
2055
2056   The default implementation just returns the respective manual margin (\ref setMargins) or the
2057   minimum margin, whichever is larger.
2058 */
2059 int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side)
2060 {
2061   return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side));
2062 }
2063
2064 ////////////////////////////////////////////////////////////////////////////////////////////////////
2065 //////////////////// QCPLayout
2066 ////////////////////////////////////////////////////////////////////////////////////////////////////
2067
2068 /*! \class QCPLayout
2069   \brief The abstract base class for layouts
2070
2071   This is an abstract base class for layout elements whose main purpose is to define the position
2072   and size of other child layout elements. In most cases, layouts don't draw anything themselves
2073   (but there are exceptions to this, e.g. QCPLegend).
2074
2075   QCPLayout derives from QCPLayoutElement, and thus can itself be nested in other layouts.
2076
2077   QCPLayout introduces a common interface for accessing and manipulating the child elements. Those
2078   functions are most notably \ref elementCount, \ref elementAt, \ref takeAt, \ref take, \ref
2079   simplify, \ref removeAt, \ref remove and \ref clear. Individual subclasses may add more functions
2080   to this interface which are more specialized to the form of the layout. For example, \ref
2081   QCPLayoutGrid adds functions that take row and column indices to access cells of the layout grid
2082   more conveniently.
2083
2084   Since this is an abstract base class, you can't instantiate it directly. Rather use one of its
2085   subclasses like QCPLayoutGrid or QCPLayoutInset.
2086
2087   For a general introduction to the layout system, see the dedicated documentation page \ref
2088   thelayoutsystem "The Layout System".
2089 */
2090
2091 /* start documentation of pure virtual functions */
2092
2093 /*! \fn virtual int QCPLayout::elementCount() const = 0
2094
2095   Returns the number of elements/cells in the layout.
2096
2097   \see elements, elementAt
2098 */
2099
2100 /*! \fn virtual QCPLayoutElement* QCPLayout::elementAt(int index) const = 0
2101
2102   Returns the element in the cell with the given \a index. If \a index is invalid, returns 0.
2103
2104   Note that even if \a index is valid, the respective cell may be empty in some layouts (e.g.
2105   QCPLayoutGrid), so this function may return 0 in those cases. You may use this function to check
2106   whether a cell is empty or not.
2107
2108   \see elements, elementCount, takeAt
2109 */
2110
2111 /*! \fn virtual QCPLayoutElement* QCPLayout::takeAt(int index) = 0
2112
2113   Removes the element with the given \a index from the layout and returns it.
2114
2115   If the \a index is invalid or the cell with that index is empty, returns 0.
2116
2117   Note that some layouts don't remove the respective cell right away but leave an empty cell after
2118   successful removal of the layout element. To collapse empty cells, use \ref simplify.
2119
2120   \see elementAt, take
2121 */
2122
2123 /*! \fn virtual bool QCPLayout::take(QCPLayoutElement* element) = 0
2124
2125   Removes the specified \a element from the layout and returns true on success.
2126
2127   If the \a element isn't in this layout, returns false.
2128
2129   Note that some layouts don't remove the respective cell right away but leave an empty cell after
2130   successful removal of the layout element. To collapse empty cells, use \ref simplify.
2131
2132   \see takeAt
2133 */
2134
2135 /* end documentation of pure virtual functions */
2136
2137 /*!
2138   Creates an instance of QCPLayout and sets default values. Note that since QCPLayout
2139   is an abstract base class, it can't be instantiated directly.
2140 */
2141 QCPLayout::QCPLayout()
2142 {
2143 }
2144
2145 /*!
2146   First calls the QCPLayoutElement::update base class implementation to update the margins on this
2147   layout.
2148
2149   Then calls \ref updateLayout which subclasses reimplement to reposition and resize their cells.
2150
2151   Finally, \ref update is called on all child elements.
2152 */
2153 void QCPLayout::update(UpdatePhase phase)
2154 {
2155   QCPLayoutElement::update(phase);
2156
2157   // set child element rects according to layout:
2158   if (phase == upLayout)
2159     updateLayout();
2160
2161   // propagate update call to child elements:
2162   const int elCount = elementCount();
2163   for (int i=0; i<elCount; ++i)
2164   {
2165     if (QCPLayoutElement *el = elementAt(i))
2166       el->update(phase);
2167   }
2168 }
2169
2170 /* inherits documentation from base class */
2171 QList<QCPLayoutElement*> QCPLayout::elements(bool recursive) const
2172 {
2173   const int c = elementCount();
2174   QList<QCPLayoutElement*> result;
2175 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2176   result.reserve(c);
2177 #endif
2178   for (int i=0; i<c; ++i)
2179     result.append(elementAt(i));
2180   if (recursive)
2181   {
2182     for (int i=0; i<c; ++i)
2183     {
2184       if (result.at(i))
2185         result << result.at(i)->elements(recursive);
2186     }
2187   }
2188   return result;
2189 }
2190
2191 /*!
2192   Simplifies the layout by collapsing empty cells. The exact behavior depends on subclasses, the
2193   default implementation does nothing.
2194
2195   Not all layouts need simplification. For example, QCPLayoutInset doesn't use explicit
2196   simplification while QCPLayoutGrid does.
2197 */
2198 void QCPLayout::simplify()
2199 {
2200 }
2201
2202 /*!
2203   Removes and deletes the element at the provided \a index. Returns true on success. If \a index is
2204   invalid or points to an empty cell, returns false.
2205
2206   This function internally uses \ref takeAt to remove the element from the layout and then deletes
2207   the returned element.
2208
2209   \see remove, takeAt
2210 */
2211 bool QCPLayout::removeAt(int index)
2212 {
2213   if (QCPLayoutElement *el = takeAt(index))
2214   {
2215     delete el;
2216     return true;
2217   } else
2218     return false;
2219 }
2220
2221 /*!
2222   Removes and deletes the provided \a element. Returns true on success. If \a element is not in the
2223   layout, returns false.
2224
2225   This function internally uses \ref takeAt to remove the element from the layout and then deletes
2226   the element.
2227
2228   \see removeAt, take
2229 */
2230 bool QCPLayout::remove(QCPLayoutElement *element)
2231 {
2232   if (take(element))
2233   {
2234     delete element;
2235     return true;
2236   } else
2237     return false;
2238 }
2239
2240 /*!
2241   Removes and deletes all layout elements in this layout.
2242
2243   \see remove, removeAt
2244 */
2245 void QCPLayout::clear()
2246 {
2247   for (int i=elementCount()-1; i>=0; --i)
2248   {
2249     if (elementAt(i))
2250       removeAt(i);
2251   }
2252   simplify();
2253 }
2254
2255 /*!
2256   Subclasses call this method to report changed (minimum/maximum) size constraints.
2257
2258   If the parent of this layout is again a QCPLayout, forwards the call to the parent's \ref
2259   sizeConstraintsChanged. If the parent is a QWidget (i.e. is the \ref QCustomPlot::plotLayout of
2260   QCustomPlot), calls QWidget::updateGeometry, so if the QCustomPlot widget is inside a Qt QLayout,
2261   it may update itself and resize cells accordingly.
2262 */
2263 void QCPLayout::sizeConstraintsChanged() const
2264 {
2265   if (QWidget *w = qobject_cast<QWidget*>(parent()))
2266     w->updateGeometry();
2267   else if (QCPLayout *l = qobject_cast<QCPLayout*>(parent()))
2268     l->sizeConstraintsChanged();
2269 }
2270
2271 /*! \internal
2272
2273   Subclasses reimplement this method to update the position and sizes of the child elements/cells
2274   via calling their \ref QCPLayoutElement::setOuterRect. The default implementation does nothing.
2275
2276   The geometry used as a reference is the inner \ref rect of this layout. Child elements should stay
2277   within that rect.
2278
2279   \ref getSectionSizes may help with the reimplementation of this function.
2280
2281   \see update
2282 */
2283 void QCPLayout::updateLayout()
2284 {
2285 }
2286
2287
2288 /*! \internal
2289
2290   Associates \a el with this layout. This is done by setting the \ref QCPLayoutElement::layout, the
2291   \ref QCPLayerable::parentLayerable and the QObject parent to this layout.
2292
2293   Further, if \a el didn't previously have a parent plot, calls \ref
2294   QCPLayerable::initializeParentPlot on \a el to set the paret plot.
2295
2296   This method is used by subclass specific methods that add elements to the layout. Note that this
2297   method only changes properties in \a el. The removal from the old layout and the insertion into
2298   the new layout must be done additionally.
2299 */
2300 void QCPLayout::adoptElement(QCPLayoutElement *el)
2301 {
2302   if (el)
2303   {
2304     el->mParentLayout = this;
2305     el->setParentLayerable(this);
2306     el->setParent(this);
2307     if (!el->parentPlot())
2308       el->initializeParentPlot(mParentPlot);
2309   } else
2310     qDebug() << Q_FUNC_INFO << "Null element passed";
2311 }
2312
2313 /*! \internal
2314
2315   Disassociates \a el from this layout. This is done by setting the \ref QCPLayoutElement::layout
2316   and the \ref QCPLayerable::parentLayerable to zero. The QObject parent is set to the parent
2317   QCustomPlot.
2318
2319   This method is used by subclass specific methods that remove elements from the layout (e.g. \ref
2320   take or \ref takeAt). Note that this method only changes properties in \a el. The removal from
2321   the old layout must be done additionally.
2322 */
2323 void QCPLayout::releaseElement(QCPLayoutElement *el)
2324 {
2325   if (el)
2326   {
2327     el->mParentLayout = 0;
2328     el->setParentLayerable(0);
2329     el->setParent(mParentPlot);
2330     // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot
2331   } else
2332     qDebug() << Q_FUNC_INFO << "Null element passed";
2333 }
2334
2335 /*! \internal
2336
2337   This is a helper function for the implementation of \ref updateLayout in subclasses.
2338
2339   It calculates the sizes of one-dimensional sections with provided constraints on maximum section
2340   sizes, minimum section sizes, relative stretch factors and the final total size of all sections.
2341
2342   The QVector entries refer to the sections. Thus all QVectors must have the same size.
2343
2344   \a maxSizes gives the maximum allowed size of each section. If there shall be no maximum size
2345   imposed, set all vector values to Qt's QWIDGETSIZE_MAX.
2346
2347   \a minSizes gives the minimum allowed size of each section. If there shall be no minimum size
2348   imposed, set all vector values to zero. If the \a minSizes entries add up to a value greater than
2349   \a totalSize, sections will be scaled smaller than the proposed minimum sizes. (In other words,
2350   not exceeding the allowed total size is taken to be more important than not going below minimum
2351   section sizes.)
2352
2353   \a stretchFactors give the relative proportions of the sections to each other. If all sections
2354   shall be scaled equally, set all values equal. If the first section shall be double the size of
2355   each individual other section, set the first number of \a stretchFactors to double the value of
2356   the other individual values (e.g. {2, 1, 1, 1}).
2357
2358   \a totalSize is the value that the final section sizes will add up to. Due to rounding, the
2359   actual sum may differ slightly. If you want the section sizes to sum up to exactly that value,
2360   you could distribute the remaining difference on the sections.
2361
2362   The return value is a QVector containing the section sizes.
2363 */
2364 QVector<int> QCPLayout::getSectionSizes(QVector<int> maxSizes, QVector<int> minSizes, QVector<double> stretchFactors, int totalSize) const
2365 {
2366   if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size())
2367   {
2368     qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors;
2369     return QVector<int>();
2370   }
2371   if (stretchFactors.isEmpty())
2372     return QVector<int>();
2373   int sectionCount = stretchFactors.size();
2374   QVector<double> sectionSizes(sectionCount);
2375   // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections):
2376   int minSizeSum = 0;
2377   for (int i=0; i<sectionCount; ++i)
2378     minSizeSum += minSizes.at(i);
2379   if (totalSize < minSizeSum)
2380   {
2381     // new stretch factors are minimum sizes and minimum sizes are set to zero:
2382     for (int i=0; i<sectionCount; ++i)
2383     {
2384       stretchFactors[i] = minSizes.at(i);
2385       minSizes[i] = 0;
2386     }
2387   }
2388
2389   QList<int> minimumLockedSections;
2390   QList<int> unfinishedSections;
2391   for (int i=0; i<sectionCount; ++i)
2392     unfinishedSections.append(i);
2393   double freeSize = totalSize;
2394
2395   int outerIterations = 0;
2396   while (!unfinishedSections.isEmpty() && outerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
2397   {
2398     ++outerIterations;
2399     int innerIterations = 0;
2400     while (!unfinishedSections.isEmpty() && innerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
2401     {
2402       ++innerIterations;
2403       // find section that hits its maximum next:
2404       int nextId = -1;
2405       double nextMax = 1e12;
2406       for (int i=0; i<unfinishedSections.size(); ++i)
2407       {
2408         int secId = unfinishedSections.at(i);
2409         double hitsMaxAt = (maxSizes.at(secId)-sectionSizes.at(secId))/stretchFactors.at(secId);
2410         if (hitsMaxAt < nextMax)
2411         {
2412           nextMax = hitsMaxAt;
2413           nextId = secId;
2414         }
2415       }
2416       // check if that maximum is actually within the bounds of the total size (i.e. can we stretch all remaining sections so far that the found section
2417       // actually hits its maximum, without exceeding the total size when we add up all sections)
2418       double stretchFactorSum = 0;
2419       for (int i=0; i<unfinishedSections.size(); ++i)
2420         stretchFactorSum += stretchFactors.at(unfinishedSections.at(i));
2421       double nextMaxLimit = freeSize/stretchFactorSum;
2422       if (nextMax < nextMaxLimit) // next maximum is actually hit, move forward to that point and fix the size of that section
2423       {
2424         for (int i=0; i<unfinishedSections.size(); ++i)
2425         {
2426           sectionSizes[unfinishedSections.at(i)] += nextMax*stretchFactors.at(unfinishedSections.at(i)); // increment all sections
2427           freeSize -= nextMax*stretchFactors.at(unfinishedSections.at(i));
2428         }
2429         unfinishedSections.removeOne(nextId); // exclude the section that is now at maximum from further changes
2430       } else // next maximum isn't hit, just distribute rest of free space on remaining sections
2431       {
2432         for (int i=0; i<unfinishedSections.size(); ++i)
2433           sectionSizes[unfinishedSections.at(i)] += nextMaxLimit*stretchFactors.at(unfinishedSections.at(i)); // increment all sections
2434         unfinishedSections.clear();
2435       }
2436     }
2437     if (innerIterations == sectionCount*2)
2438       qDebug() << Q_FUNC_INFO << "Exceeded maximum expected inner iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2439
2440     // now check whether the resulting section sizes violate minimum restrictions:
2441     bool foundMinimumViolation = false;
2442     for (int i=0; i<sectionSizes.size(); ++i)
2443     {
2444       if (minimumLockedSections.contains(i))
2445         continue;
2446       if (sectionSizes.at(i) < minSizes.at(i)) // section violates minimum
2447       {
2448         sectionSizes[i] = minSizes.at(i); // set it to minimum
2449         foundMinimumViolation = true; // make sure we repeat the whole optimization process
2450         minimumLockedSections.append(i);
2451       }
2452     }
2453     if (foundMinimumViolation)
2454     {
2455       freeSize = totalSize;
2456       for (int i=0; i<sectionCount; ++i)
2457       {
2458         if (!minimumLockedSections.contains(i)) // only put sections that haven't hit their minimum back into the pool
2459           unfinishedSections.append(i);
2460         else
2461           freeSize -= sectionSizes.at(i); // remove size of minimum locked sections from available space in next round
2462       }
2463       // reset all section sizes to zero that are in unfinished sections (all others have been set to their minimum):
2464       for (int i=0; i<unfinishedSections.size(); ++i)
2465         sectionSizes[unfinishedSections.at(i)] = 0;
2466     }
2467   }
2468   if (outerIterations == sectionCount*2)
2469     qDebug() << Q_FUNC_INFO << "Exceeded maximum expected outer iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2470
2471   QVector<int> result(sectionCount);
2472   for (int i=0; i<sectionCount; ++i)
2473     result[i] = qRound(sectionSizes.at(i));
2474   return result;
2475 }
2476
2477
2478 ////////////////////////////////////////////////////////////////////////////////////////////////////
2479 //////////////////// QCPLayoutGrid
2480 ////////////////////////////////////////////////////////////////////////////////////////////////////
2481
2482 /*! \class QCPLayoutGrid
2483   \brief A layout that arranges child elements in a grid
2484
2485   Elements are laid out in a grid with configurable stretch factors (\ref setColumnStretchFactor,
2486   \ref setRowStretchFactor) and spacing (\ref setColumnSpacing, \ref setRowSpacing).
2487
2488   Elements can be added to cells via \ref addElement. The grid is expanded if the specified row or
2489   column doesn't exist yet. Whether a cell contains a valid layout element can be checked with \ref
2490   hasElement, that element can be retrieved with \ref element. If rows and columns that only have
2491   empty cells shall be removed, call \ref simplify. Removal of elements is either done by just
2492   adding the element to a different layout or by using the QCPLayout interface \ref take or \ref
2493   remove.
2494
2495   Row and column insertion can be performed with \ref insertRow and \ref insertColumn.
2496 */
2497
2498 /*!
2499   Creates an instance of QCPLayoutGrid and sets default values.
2500 */
2501 QCPLayoutGrid::QCPLayoutGrid() :
2502   mColumnSpacing(5),
2503   mRowSpacing(5)
2504 {
2505 }
2506
2507 QCPLayoutGrid::~QCPLayoutGrid()
2508 {
2509   // clear all child layout elements. This is important because only the specific layouts know how
2510   // to handle removing elements (clear calls virtual removeAt method to do that).
2511   clear();
2512 }
2513
2514 /*!
2515   Returns the element in the cell in \a row and \a column.
2516
2517   Returns 0 if either the row/column is invalid or if the cell is empty. In those cases, a qDebug
2518   message is printed. To check whether a cell exists and isn't empty, use \ref hasElement.
2519
2520   \see addElement, hasElement
2521 */
2522 QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const
2523 {
2524   if (row >= 0 && row < mElements.size())
2525   {
2526     if (column >= 0 && column < mElements.first().size())
2527     {
2528       if (QCPLayoutElement *result = mElements.at(row).at(column))
2529         return result;
2530       else
2531         qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column;
2532     } else
2533       qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column;
2534   } else
2535     qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column;
2536   return 0;
2537 }
2538
2539 /*!
2540   Returns the number of rows in the layout.
2541
2542   \see columnCount
2543 */
2544 int QCPLayoutGrid::rowCount() const
2545 {
2546   return mElements.size();
2547 }
2548
2549 /*!
2550   Returns the number of columns in the layout.
2551
2552   \see rowCount
2553 */
2554 int QCPLayoutGrid::columnCount() const
2555 {
2556   if (mElements.size() > 0)
2557     return mElements.first().size();
2558   else
2559     return 0;
2560 }
2561
2562 /*!
2563   Adds the \a element to cell with \a row and \a column. If \a element is already in a layout, it
2564   is first removed from there. If \a row or \a column don't exist yet, the layout is expanded
2565   accordingly.
2566
2567   Returns true if the element was added successfully, i.e. if the cell at \a row and \a column
2568   didn't already have an element.
2569
2570   \see element, hasElement, take, remove
2571 */
2572 bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element)
2573 {
2574   if (element)
2575   {
2576     if (!hasElement(row, column))
2577     {
2578       if (element->layout()) // remove from old layout first
2579         element->layout()->take(element);
2580       expandTo(row+1, column+1);
2581       mElements[row][column] = element;
2582       adoptElement(element);
2583       return true;
2584     } else
2585       qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column;
2586   } else
2587     qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column;
2588   return false;
2589 }
2590
2591 /*!
2592   Returns whether the cell at \a row and \a column exists and contains a valid element, i.e. isn't
2593   empty.
2594
2595   \see element
2596 */
2597 bool QCPLayoutGrid::hasElement(int row, int column)
2598 {
2599   if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount())
2600     return mElements.at(row).at(column);
2601   else
2602     return false;
2603 }
2604
2605 /*!
2606   Sets the stretch \a factor of \a column.
2607
2608   Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond
2609   their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref
2610   QCPLayoutElement::setMaximumSize), regardless of the stretch factor.
2611
2612   The default stretch factor of newly created rows/columns is 1.
2613
2614   \see setColumnStretchFactors, setRowStretchFactor
2615 */
2616 void QCPLayoutGrid::setColumnStretchFactor(int column, double factor)
2617 {
2618   if (column >= 0 && column < columnCount())
2619   {
2620     if (factor > 0)
2621       mColumnStretchFactors[column] = factor;
2622     else
2623       qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
2624   } else
2625     qDebug() << Q_FUNC_INFO << "Invalid column:" << column;
2626 }
2627
2628 /*!
2629   Sets the stretch \a factors of all columns. \a factors must have the size \ref columnCount.
2630
2631   Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond
2632   their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref
2633   QCPLayoutElement::setMaximumSize), regardless of the stretch factor.
2634
2635   The default stretch factor of newly created rows/columns is 1.
2636
2637   \see setColumnStretchFactor, setRowStretchFactors
2638 */
2639 void QCPLayoutGrid::setColumnStretchFactors(const QList<double> &factors)
2640 {
2641   if (factors.size() == mColumnStretchFactors.size())
2642   {
2643     mColumnStretchFactors = factors;
2644     for (int i=0; i<mColumnStretchFactors.size(); ++i)
2645     {
2646       if (mColumnStretchFactors.at(i) <= 0)
2647       {
2648         qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mColumnStretchFactors.at(i);
2649         mColumnStretchFactors[i] = 1;
2650       }
2651     }
2652   } else
2653     qDebug() << Q_FUNC_INFO << "Column count not equal to passed stretch factor count:" << factors;
2654 }
2655
2656 /*!
2657   Sets the stretch \a factor of \a row.
2658
2659   Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond
2660   their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref
2661   QCPLayoutElement::setMaximumSize), regardless of the stretch factor.
2662
2663   The default stretch factor of newly created rows/columns is 1.
2664
2665   \see setColumnStretchFactors, setRowStretchFactor
2666 */
2667 void QCPLayoutGrid::setRowStretchFactor(int row, double factor)
2668 {
2669   if (row >= 0 && row < rowCount())
2670   {
2671     if (factor > 0)
2672       mRowStretchFactors[row] = factor;
2673     else
2674       qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
2675   } else
2676     qDebug() << Q_FUNC_INFO << "Invalid row:" << row;
2677 }
2678
2679 /*!
2680   Sets the stretch \a factors of all rows. \a factors must have the size \ref rowCount.
2681
2682   Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond
2683   their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref
2684   QCPLayoutElement::setMaximumSize), regardless of the stretch factor.
2685
2686   The default stretch factor of newly created rows/columns is 1.
2687
2688   \see setRowStretchFactor, setColumnStretchFactors
2689 */
2690 void QCPLayoutGrid::setRowStretchFactors(const QList<double> &factors)
2691 {
2692   if (factors.size() == mRowStretchFactors.size())
2693   {
2694     mRowStretchFactors = factors;
2695     for (int i=0; i<mRowStretchFactors.size(); ++i)
2696     {
2697       if (mRowStretchFactors.at(i) <= 0)
2698       {
2699         qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mRowStretchFactors.at(i);
2700         mRowStretchFactors[i] = 1;
2701       }
2702     }
2703   } else
2704     qDebug() << Q_FUNC_INFO << "Row count not equal to passed stretch factor count:" << factors;
2705 }
2706
2707 /*!
2708   Sets the gap that is left blank between columns to \a pixels.
2709
2710   \see setRowSpacing
2711 */
2712 void QCPLayoutGrid::setColumnSpacing(int pixels)
2713 {
2714   mColumnSpacing = pixels;
2715 }
2716
2717 /*!
2718   Sets the gap that is left blank between rows to \a pixels.
2719
2720   \see setColumnSpacing
2721 */
2722 void QCPLayoutGrid::setRowSpacing(int pixels)
2723 {
2724   mRowSpacing = pixels;
2725 }
2726
2727 /*!
2728   Expands the layout to have \a newRowCount rows and \a newColumnCount columns. So the last valid
2729   row index will be \a newRowCount-1, the last valid column index will be \a newColumnCount-1.
2730
2731   If the current column/row count is already larger or equal to \a newColumnCount/\a newRowCount,
2732   this function does nothing in that dimension.
2733
2734   Newly created cells are empty, new rows and columns have the stretch factor 1.
2735
2736   Note that upon a call to \ref addElement, the layout is expanded automatically to contain the
2737   specified row and column, using this function.
2738
2739   \see simplify
2740 */
2741 void QCPLayoutGrid::expandTo(int newRowCount, int newColumnCount)
2742 {
2743   // add rows as necessary:
2744   while (rowCount() < newRowCount)
2745   {
2746     mElements.append(QList<QCPLayoutElement*>());
2747     mRowStretchFactors.append(1);
2748   }
2749   // go through rows and expand columns as necessary:
2750   int newColCount = qMax(columnCount(), newColumnCount);
2751   for (int i=0; i<rowCount(); ++i)
2752   {
2753     while (mElements.at(i).size() < newColCount)
2754       mElements[i].append(0);
2755   }
2756   while (mColumnStretchFactors.size() < newColCount)
2757     mColumnStretchFactors.append(1);
2758 }
2759
2760 /*!
2761   Inserts a new row with empty cells at the row index \a newIndex. Valid values for \a newIndex
2762   range from 0 (inserts a row at the top) to \a rowCount (appends a row at the bottom).
2763
2764   \see insertColumn
2765 */
2766 void QCPLayoutGrid::insertRow(int newIndex)
2767 {
2768   if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
2769   {
2770     expandTo(1, 1);
2771     return;
2772   }
2773
2774   if (newIndex < 0)
2775     newIndex = 0;
2776   if (newIndex > rowCount())
2777     newIndex = rowCount();
2778
2779   mRowStretchFactors.insert(newIndex, 1);
2780   QList<QCPLayoutElement*> newRow;
2781   for (int col=0; col<columnCount(); ++col)
2782     newRow.append((QCPLayoutElement*)0);
2783   mElements.insert(newIndex, newRow);
2784 }
2785
2786 /*!
2787   Inserts a new column with empty cells at the column index \a newIndex. Valid values for \a
2788   newIndex range from 0 (inserts a row at the left) to \a rowCount (appends a row at the right).
2789
2790   \see insertRow
2791 */
2792 void QCPLayoutGrid::insertColumn(int newIndex)
2793 {
2794   if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
2795   {
2796     expandTo(1, 1);
2797     return;
2798   }
2799
2800   if (newIndex < 0)
2801     newIndex = 0;
2802   if (newIndex > columnCount())
2803     newIndex = columnCount();
2804
2805   mColumnStretchFactors.insert(newIndex, 1);
2806   for (int row=0; row<rowCount(); ++row)
2807     mElements[row].insert(newIndex, (QCPLayoutElement*)0);
2808 }
2809
2810 /* inherits documentation from base class */
2811 void QCPLayoutGrid::updateLayout()
2812 {
2813   QVector<int> minColWidths, minRowHeights, maxColWidths, maxRowHeights;
2814   getMinimumRowColSizes(&minColWidths, &minRowHeights);
2815   getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
2816
2817   int totalRowSpacing = (rowCount()-1) * mRowSpacing;
2818   int totalColSpacing = (columnCount()-1) * mColumnSpacing;
2819   QVector<int> colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing);
2820   QVector<int> rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing);
2821
2822   // go through cells and set rects accordingly:
2823   int yOffset = mRect.top();
2824   for (int row=0; row<rowCount(); ++row)
2825   {
2826     if (row > 0)
2827       yOffset += rowHeights.at(row-1)+mRowSpacing;
2828     int xOffset = mRect.left();
2829     for (int col=0; col<columnCount(); ++col)
2830     {
2831       if (col > 0)
2832         xOffset += colWidths.at(col-1)+mColumnSpacing;
2833       if (mElements.at(row).at(col))
2834         mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row)));
2835     }
2836   }
2837 }
2838
2839 /* inherits documentation from base class */
2840 int QCPLayoutGrid::elementCount() const
2841 {
2842   return rowCount()*columnCount();
2843 }
2844
2845 /* inherits documentation from base class */
2846 QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const
2847 {
2848   int colC = columnCount();
2849   if (index >= 0 && colC && index < elementCount())
2850     return mElements.at(index / colC).at(index % colC);
2851   else
2852     return 0;
2853 }
2854
2855 /* inherits documentation from base class */
2856 QCPLayoutElement *QCPLayoutGrid::takeAt(int index)
2857 {
2858
2859     int colC = columnCount();
2860     if(colC == 0)
2861       return 0;
2862
2863   if (QCPLayoutElement *el = elementAt(index))
2864   {
2865
2866     releaseElement(el);
2867     mElements[index / colC][index % colC] = 0;
2868     return el;
2869   } else
2870   {
2871     qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
2872     return 0;
2873   }
2874 }
2875
2876 /* inherits documentation from base class */
2877 bool QCPLayoutGrid::take(QCPLayoutElement *element)
2878 {
2879   if (element)
2880   {
2881     for (int i=0; i<elementCount(); ++i)
2882     {
2883       if (elementAt(i) == element)
2884       {
2885         takeAt(i);
2886         return true;
2887       }
2888     }
2889     qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
2890   } else
2891     qDebug() << Q_FUNC_INFO << "Can't take null element";
2892   return false;
2893 }
2894
2895 /* inherits documentation from base class */
2896 QList<QCPLayoutElement*> QCPLayoutGrid::elements(bool recursive) const
2897 {
2898   QList<QCPLayoutElement*> result;
2899   int colC = columnCount();
2900   int rowC = rowCount();
2901 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2902   result.reserve(colC*rowC);
2903 #endif
2904   for (int row=0; row<rowC; ++row)
2905   {
2906     for (int col=0; col<colC; ++col)
2907     {
2908       result.append(mElements.at(row).at(col));
2909     }
2910   }
2911   if (recursive)
2912   {
2913     int c = result.size();
2914     for (int i=0; i<c; ++i)
2915     {
2916       if (result.at(i))
2917         result << result.at(i)->elements(recursive);
2918     }
2919   }
2920   return result;
2921 }
2922
2923 /*!
2924   Simplifies the layout by collapsing rows and columns which only contain empty cells.
2925 */
2926 void QCPLayoutGrid::simplify()
2927 {
2928   // remove rows with only empty cells:
2929   for (int row=rowCount()-1; row>=0; --row)
2930   {
2931     bool hasElements = false;
2932     for (int col=0; col<columnCount(); ++col)
2933     {
2934       if (mElements.at(row).at(col))
2935       {
2936         hasElements = true;
2937         break;
2938       }
2939     }
2940     if (!hasElements)
2941     {
2942       mRowStretchFactors.removeAt(row);
2943       mElements.removeAt(row);
2944       if (mElements.isEmpty()) // removed last element, also remove stretch factor (wouldn't happen below because also columnCount changed to 0 now)
2945         mColumnStretchFactors.clear();
2946     }
2947   }
2948
2949   // remove columns with only empty cells:
2950   for (int col=columnCount()-1; col>=0; --col)
2951   {
2952     bool hasElements = false;
2953     for (int row=0; row<rowCount(); ++row)
2954     {
2955       if (mElements.at(row).at(col))
2956       {
2957         hasElements = true;
2958         break;
2959       }
2960     }
2961     if (!hasElements)
2962     {
2963       mColumnStretchFactors.removeAt(col);
2964       for (int row=0; row<rowCount(); ++row)
2965         mElements[row].removeAt(col);
2966     }
2967   }
2968 }
2969
2970 /* inherits documentation from base class */
2971 QSize QCPLayoutGrid::minimumSizeHint() const
2972 {
2973   QVector<int> minColWidths, minRowHeights;
2974   getMinimumRowColSizes(&minColWidths, &minRowHeights);
2975   QSize result(0, 0);
2976   for (int i=0; i<minColWidths.size(); ++i)
2977     result.rwidth() += minColWidths.at(i);
2978   for (int i=0; i<minRowHeights.size(); ++i)
2979     result.rheight() += minRowHeights.at(i);
2980   result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing + mMargins.left() + mMargins.right();
2981   result.rheight() += qMax(0, rowCount()-1) * mRowSpacing + mMargins.top() + mMargins.bottom();
2982   return result;
2983 }
2984
2985 /* inherits documentation from base class */
2986 QSize QCPLayoutGrid::maximumSizeHint() const
2987 {
2988   QVector<int> maxColWidths, maxRowHeights;
2989   getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
2990
2991   QSize result(0, 0);
2992   for (int i=0; i<maxColWidths.size(); ++i)
2993     result.setWidth(qMin(result.width()+maxColWidths.at(i), QWIDGETSIZE_MAX));
2994   for (int i=0; i<maxRowHeights.size(); ++i)
2995     result.setHeight(qMin(result.height()+maxRowHeights.at(i), QWIDGETSIZE_MAX));
2996   result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing + mMargins.left() + mMargins.right();
2997   result.rheight() += qMax(0, rowCount()-1) * mRowSpacing + mMargins.top() + mMargins.bottom();
2998   return result;
2999 }
3000
3001 /*! \internal
3002
3003   Places the minimum column widths and row heights into \a minColWidths and \a minRowHeights
3004   respectively.
3005
3006   The minimum height of a row is the largest minimum height of any element in that row. The minimum
3007   width of a column is the largest minimum width of any element in that column.
3008
3009   This is a helper function for \ref updateLayout.
3010
3011   \see getMaximumRowColSizes
3012 */
3013 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, QVector<int> *minRowHeights) const
3014 {
3015   *minColWidths = QVector<int>(columnCount(), 0);
3016   *minRowHeights = QVector<int>(rowCount(), 0);
3017   for (int row=0; row<rowCount(); ++row)
3018   {
3019     for (int col=0; col<columnCount(); ++col)
3020     {
3021       if (mElements.at(row).at(col))
3022       {
3023         QSize minHint = mElements.at(row).at(col)->minimumSizeHint();
3024         QSize min = mElements.at(row).at(col)->minimumSize();
3025         QSize final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height());
3026         if (minColWidths->at(col) < final.width())
3027           (*minColWidths)[col] = final.width();
3028         if (minRowHeights->at(row) < final.height())
3029           (*minRowHeights)[row] = final.height();
3030       }
3031     }
3032   }
3033 }
3034
3035 /*! \internal
3036
3037   Places the maximum column widths and row heights into \a maxColWidths and \a maxRowHeights
3038   respectively.
3039
3040   The maximum height of a row is the smallest maximum height of any element in that row. The
3041   maximum width of a column is the smallest maximum width of any element in that column.
3042
3043   This is a helper function for \ref updateLayout.
3044
3045   \see getMinimumRowColSizes
3046 */
3047 void QCPLayoutGrid::getMaximumRowColSizes(QVector<int> *maxColWidths, QVector<int> *maxRowHeights) const
3048 {
3049   *maxColWidths = QVector<int>(columnCount(), QWIDGETSIZE_MAX);
3050   *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX);
3051   for (int row=0; row<rowCount(); ++row)
3052   {
3053     for (int col=0; col<columnCount(); ++col)
3054     {
3055       if (mElements.at(row).at(col))
3056       {
3057         QSize maxHint = mElements.at(row).at(col)->maximumSizeHint();
3058         QSize max = mElements.at(row).at(col)->maximumSize();
3059         QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height());
3060         if (maxColWidths->at(col) > final.width())
3061           (*maxColWidths)[col] = final.width();
3062         if (maxRowHeights->at(row) > final.height())
3063           (*maxRowHeights)[row] = final.height();
3064       }
3065     }
3066   }
3067 }
3068
3069
3070 ////////////////////////////////////////////////////////////////////////////////////////////////////
3071 //////////////////// QCPLayoutInset
3072 ////////////////////////////////////////////////////////////////////////////////////////////////////
3073 /*! \class QCPLayoutInset
3074   \brief A layout that places child elements aligned to the border or arbitrarily positioned
3075
3076   Elements are placed either aligned to the border or at arbitrary position in the area of the
3077   layout. Which placement applies is controlled with the \ref InsetPlacement (\ref
3078   setInsetPlacement).
3079
3080   Elements are added via \ref addElement(QCPLayoutElement *element, Qt::Alignment alignment) or
3081   addElement(QCPLayoutElement *element, const QRectF &rect). If the first method is used, the inset
3082   placement will default to \ref ipBorderAligned and the element will be aligned according to the
3083   \a alignment parameter. The second method defaults to \ref ipFree and allows placing elements at
3084   arbitrary position and size, defined by \a rect.
3085
3086   The alignment or rect can be set via \ref setInsetAlignment or \ref setInsetRect, respectively.
3087
3088   This is the layout that every QCPAxisRect has as \ref QCPAxisRect::insetLayout.
3089 */
3090
3091 /* start documentation of inline functions */
3092
3093 /*! \fn virtual void QCPLayoutInset::simplify()
3094
3095   The QCPInsetLayout does not need simplification since it can never have empty cells due to its
3096   linear index structure. This method does nothing.
3097 */
3098
3099 /* end documentation of inline functions */
3100
3101 /*!
3102   Creates an instance of QCPLayoutInset and sets default values.
3103 */
3104 QCPLayoutInset::QCPLayoutInset()
3105 {
3106 }
3107
3108 QCPLayoutInset::~QCPLayoutInset()
3109 {
3110   // clear all child layout elements. This is important because only the specific layouts know how
3111   // to handle removing elements (clear calls virtual removeAt method to do that).
3112   clear();
3113 }
3114
3115 /*!
3116   Returns the placement type of the element with the specified \a index.
3117 */
3118 QCPLayoutInset::InsetPlacement QCPLayoutInset::insetPlacement(int index) const
3119 {
3120   if (elementAt(index))
3121     return mInsetPlacement.at(index);
3122   else
3123   {
3124     qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3125     return ipFree;
3126   }
3127 }
3128
3129 /*!
3130   Returns the alignment of the element with the specified \a index. The alignment only has a
3131   meaning, if the inset placement (\ref setInsetPlacement) is \ref ipBorderAligned.
3132 */
3133 Qt::Alignment QCPLayoutInset::insetAlignment(int index) const
3134 {
3135   if (elementAt(index))
3136     return mInsetAlignment.at(index);
3137   else
3138   {
3139     qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3140     return 0;
3141   }
3142 }
3143
3144 /*!
3145   Returns the rect of the element with the specified \a index. The rect only has a
3146   meaning, if the inset placement (\ref setInsetPlacement) is \ref ipFree.
3147 */
3148 QRectF QCPLayoutInset::insetRect(int index) const
3149 {
3150   if (elementAt(index))
3151     return mInsetRect.at(index);
3152   else
3153   {
3154     qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3155     return QRectF();
3156   }
3157 }
3158
3159 /*!
3160   Sets the inset placement type of the element with the specified \a index to \a placement.
3161
3162   \see InsetPlacement
3163 */
3164 void QCPLayoutInset::setInsetPlacement(int index, QCPLayoutInset::InsetPlacement placement)
3165 {
3166   if (elementAt(index))
3167     mInsetPlacement[index] = placement;
3168   else
3169     qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3170 }
3171
3172 /*!
3173   If the inset placement (\ref setInsetPlacement) is \ref ipBorderAligned, this function
3174   is used to set the alignment of the element with the specified \a index to \a alignment.
3175
3176   \a alignment is an or combination of the following alignment flags: Qt::AlignLeft,
3177   Qt::AlignHCenter, Qt::AlighRight, Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom. Any other
3178   alignment flags will be ignored.
3179 */
3180 void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment)
3181 {
3182   if (elementAt(index))
3183     mInsetAlignment[index] = alignment;
3184   else
3185     qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3186 }
3187
3188 /*!
3189   If the inset placement (\ref setInsetPlacement) is \ref ipFree, this function is used to set the
3190   position and size of the element with the specified \a index to \a rect.
3191
3192   \a rect is given in fractions of the whole inset layout rect. So an inset with rect (0, 0, 1, 1)
3193   will span the entire layout. An inset with rect (0.6, 0.1, 0.35, 0.35) will be in the top right
3194   corner of the layout, with 35% width and height of the parent layout.
3195
3196   Note that the minimum and maximum sizes of the embedded element (\ref
3197   QCPLayoutElement::setMinimumSize, \ref QCPLayoutElement::setMaximumSize) are enforced.
3198 */
3199 void QCPLayoutInset::setInsetRect(int index, const QRectF &rect)
3200 {
3201   if (elementAt(index))
3202     mInsetRect[index] = rect;
3203   else
3204     qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3205 }
3206
3207 /* inherits documentation from base class */
3208 void QCPLayoutInset::updateLayout()
3209 {
3210   for (int i=0; i<mElements.size(); ++i)
3211   {
3212     QRect insetRect;
3213     QSize finalMinSize, finalMaxSize;
3214     QSize minSizeHint = mElements.at(i)->minimumSizeHint();
3215     QSize maxSizeHint = mElements.at(i)->maximumSizeHint();
3216     finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 ? mElements.at(i)->minimumSize().width() : minSizeHint.width());
3217     finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 ? mElements.at(i)->minimumSize().height() : minSizeHint.height());
3218     finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().width() : maxSizeHint.width());
3219     finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().height() : maxSizeHint.height());
3220     if (mInsetPlacement.at(i) == ipFree)
3221     {
3222       insetRect = QRect(rect().x()+rect().width()*mInsetRect.at(i).x(),
3223                         rect().y()+rect().height()*mInsetRect.at(i).y(),
3224                         rect().width()*mInsetRect.at(i).width(),
3225                         rect().height()*mInsetRect.at(i).height());
3226       if (insetRect.size().width() < finalMinSize.width())
3227         insetRect.setWidth(finalMinSize.width());
3228       if (insetRect.size().height() < finalMinSize.height())
3229         insetRect.setHeight(finalMinSize.height());
3230       if (insetRect.size().width() > finalMaxSize.width())
3231         insetRect.setWidth(finalMaxSize.width());
3232       if (insetRect.size().height() > finalMaxSize.height())
3233         insetRect.setHeight(finalMaxSize.height());
3234     } else if (mInsetPlacement.at(i) == ipBorderAligned)
3235     {
3236       insetRect.setSize(finalMinSize);
3237       Qt::Alignment al = mInsetAlignment.at(i);
3238       if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x());
3239       else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width());
3240       else insetRect.moveLeft(rect().x()+rect().width()*0.5-finalMinSize.width()*0.5); // default to Qt::AlignHCenter
3241       if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y());
3242       else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height());
3243       else insetRect.moveTop(rect().y()+rect().height()*0.5-finalMinSize.height()*0.5); // default to Qt::AlignVCenter
3244     }
3245     mElements.at(i)->setOuterRect(insetRect);
3246   }
3247 }
3248
3249 /* inherits documentation from base class */
3250 int QCPLayoutInset::elementCount() const
3251 {
3252   return mElements.size();
3253 }
3254
3255 /* inherits documentation from base class */
3256 QCPLayoutElement *QCPLayoutInset::elementAt(int index) const
3257 {
3258   if (index >= 0 && index < mElements.size())
3259     return mElements.at(index);
3260   else
3261     return 0;
3262 }
3263
3264 /* inherits documentation from base class */
3265 QCPLayoutElement *QCPLayoutInset::takeAt(int index)
3266 {
3267   if (QCPLayoutElement *el = elementAt(index))
3268   {
3269     releaseElement(el);
3270     mElements.removeAt(index);
3271     mInsetPlacement.removeAt(index);
3272     mInsetAlignment.removeAt(index);
3273     mInsetRect.removeAt(index);
3274     return el;
3275   } else
3276   {
3277     qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
3278     return 0;
3279   }
3280 }
3281
3282 /* inherits documentation from base class */
3283 bool QCPLayoutInset::take(QCPLayoutElement *element)
3284 {
3285   if (element)
3286   {
3287     for (int i=0; i<elementCount(); ++i)
3288     {
3289       if (elementAt(i) == element)
3290       {
3291         takeAt(i);
3292         return true;
3293       }
3294     }
3295     qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
3296   } else
3297     qDebug() << Q_FUNC_INFO << "Can't take null element";
3298   return false;
3299 }
3300
3301 /*!
3302   The inset layout is sensitive to events only at areas where its (visible) child elements are
3303   sensitive. If the selectTest method of any of the child elements returns a positive number for \a
3304   pos, this method returns a value corresponding to 0.99 times the parent plot's selection
3305   tolerance. The inset layout is not selectable itself by default. So if \a onlySelectable is true,
3306   -1.0 is returned.
3307
3308   See \ref QCPLayerable::selectTest for a general explanation of this virtual method.
3309 */
3310 double QCPLayoutInset::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
3311 {
3312   Q_UNUSED(details)
3313   if (onlySelectable)
3314     return -1;
3315
3316   for (int i=0; i<mElements.size(); ++i)
3317   {
3318     // inset layout shall only return positive selectTest, if actually an inset object is at pos
3319     // else it would block the entire underlying QCPAxisRect with its surface.
3320     if (mElements.at(i)->realVisibility() && mElements.at(i)->selectTest(pos, onlySelectable) >= 0)
3321       return mParentPlot->selectionTolerance()*0.99;
3322   }
3323   return -1;
3324 }
3325
3326 /*!
3327   Adds the specified \a element to the layout as an inset aligned at the border (\ref
3328   setInsetAlignment is initialized with \ref ipBorderAligned). The alignment is set to \a
3329   alignment.
3330
3331   \a alignment is an or combination of the following alignment flags: Qt::AlignLeft,
3332   Qt::AlignHCenter, Qt::AlighRight, Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom. Any other
3333   alignment flags will be ignored.
3334
3335   \see addElement(QCPLayoutElement *element, const QRectF &rect)
3336 */
3337 void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment)
3338 {
3339   if (element)
3340   {
3341     if (element->layout()) // remove from old layout first
3342       element->layout()->take(element);
3343     mElements.append(element);
3344     mInsetPlacement.append(ipBorderAligned);
3345     mInsetAlignment.append(alignment);
3346     mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4));
3347     adoptElement(element);
3348   } else
3349     qDebug() << Q_FUNC_INFO << "Can't add null element";
3350 }
3351
3352 /*!
3353   Adds the specified \a element to the layout as an inset with free positioning/sizing (\ref
3354   setInsetAlignment is initialized with \ref ipFree). The position and size is set to \a
3355   rect.
3356
3357   \a rect is given in fractions of the whole inset layout rect. So an inset with rect (0, 0, 1, 1)
3358   will span the entire layout. An inset with rect (0.6, 0.1, 0.35, 0.35) will be in the top right
3359   corner of the layout, with 35% width and height of the parent layout.
3360
3361   \see addElement(QCPLayoutElement *element, Qt::Alignment alignment)
3362 */
3363 void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect)
3364 {
3365   if (element)
3366   {
3367     if (element->layout()) // remove from old layout first
3368       element->layout()->take(element);
3369     mElements.append(element);
3370     mInsetPlacement.append(ipFree);
3371     mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop);
3372     mInsetRect.append(rect);
3373     adoptElement(element);
3374   } else
3375     qDebug() << Q_FUNC_INFO << "Can't add null element";
3376 }
3377
3378
3379 ////////////////////////////////////////////////////////////////////////////////////////////////////
3380 //////////////////// QCPLineEnding
3381 ////////////////////////////////////////////////////////////////////////////////////////////////////
3382
3383 /*! \class QCPLineEnding
3384   \brief Handles the different ending decorations for line-like items
3385
3386   \image html QCPLineEnding.png "The various ending styles currently supported"
3387
3388   For every ending a line-like item has, an instance of this class exists. For example, QCPItemLine
3389   has two endings which can be set with QCPItemLine::setHead and QCPItemLine::setTail.
3390
3391   The styles themselves are defined via the enum QCPLineEnding::EndingStyle. Most decorations can
3392   be modified regarding width and length, see \ref setWidth and \ref setLength. The direction of
3393   the ending decoration (e.g. direction an arrow is pointing) is controlled by the line-like item.
3394   For example, when both endings of a QCPItemLine are set to be arrows, they will point to opposite
3395   directions, e.g. "outward". This can be changed by \ref setInverted, which would make the
3396   respective arrow point inward.
3397
3398   Note that due to the overloaded QCPLineEnding constructor, you may directly specify a
3399   QCPLineEnding::EndingStyle where actually a QCPLineEnding is expected, e.g. \code
3400   myItemLine->setHead(QCPLineEnding::esSpikeArrow) \endcode
3401 */
3402
3403 /*!
3404   Creates a QCPLineEnding instance with default values (style \ref esNone).
3405 */
3406 QCPLineEnding::QCPLineEnding() :
3407   mStyle(esNone),
3408   mWidth(8),
3409   mLength(10),
3410   mInverted(false)
3411 {
3412 }
3413
3414 /*!
3415   Creates a QCPLineEnding instance with the specified values.
3416 */
3417 QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) :
3418   mStyle(style),
3419   mWidth(width),
3420   mLength(length),
3421   mInverted(inverted)
3422 {
3423 }
3424
3425 /*!
3426   Sets the style of the ending decoration.
3427 */
3428 void QCPLineEnding::setStyle(QCPLineEnding::EndingStyle style)
3429 {
3430   mStyle = style;
3431 }
3432
3433 /*!
3434   Sets the width of the ending decoration, if the style supports it. On arrows, for example, the
3435   width defines the size perpendicular to the arrow's pointing direction.
3436
3437   \see setLength
3438 */
3439 void QCPLineEnding::setWidth(double width)
3440 {
3441   mWidth = width;
3442 }
3443
3444 /*!
3445   Sets the length of the ending decoration, if the style supports it. On arrows, for example, the
3446   length defines the size in pointing direction.
3447
3448   \see setWidth
3449 */
3450 void QCPLineEnding::setLength(double length)
3451 {
3452   mLength = length;
3453 }
3454
3455 /*!
3456   Sets whether the ending decoration shall be inverted. For example, an arrow decoration will point
3457   inward when \a inverted is set to true.
3458
3459   Note that also the \a width direction is inverted. For symmetrical ending styles like arrows or
3460   discs, this doesn't make a difference. However, asymmetric styles like \ref esHalfBar are
3461   affected by it, which can be used to control to which side the half bar points to.
3462 */
3463 void QCPLineEnding::setInverted(bool inverted)
3464 {
3465   mInverted = inverted;
3466 }
3467
3468 /*! \internal
3469
3470   Returns the maximum pixel radius the ending decoration might cover, starting from the position
3471   the decoration is drawn at (typically a line ending/\ref QCPItemPosition of an item).
3472
3473   This is relevant for clipping. Only omit painting of the decoration when the position where the
3474   decoration is supposed to be drawn is farther away from the clipping rect than the returned
3475   distance.
3476 */
3477 double QCPLineEnding::boundingDistance() const
3478 {
3479   switch (mStyle)
3480   {
3481     case esNone:
3482       return 0;
3483
3484     case esFlatArrow:
3485     case esSpikeArrow:
3486     case esLineArrow:
3487     case esSkewedBar:
3488       return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length
3489
3490     case esDisc:
3491     case esSquare:
3492     case esDiamond:
3493     case esBar:
3494     case esHalfBar:
3495       return mWidth*1.42; // items that only have a width -> width*sqrt(2)
3496
3497   }
3498   return 0;
3499 }
3500
3501 /*!
3502   Starting from the origin of this line ending (which is style specific), returns the length
3503   covered by the line ending symbol, in backward direction.
3504
3505   For example, the \ref esSpikeArrow has a shorter real length than a \ref esFlatArrow, even if
3506   both have the same \ref setLength value, because the spike arrow has an inward curved back, which
3507   reduces the length along its center axis (the drawing origin for arrows is at the tip).
3508
3509   This function is used for precise, style specific placement of line endings, for example in
3510   QCPAxes.
3511 */
3512 double QCPLineEnding::realLength() const
3513 {
3514   switch (mStyle)
3515   {
3516     case esNone:
3517     case esLineArrow:
3518     case esSkewedBar:
3519     case esBar:
3520     case esHalfBar:
3521       return 0;
3522
3523     case esFlatArrow:
3524       return mLength;
3525
3526     case esDisc:
3527     case esSquare:
3528     case esDiamond:
3529       return mWidth*0.5;
3530
3531     case esSpikeArrow:
3532       return mLength*0.8;
3533   }
3534   return 0;
3535 }
3536
3537 /*! \internal
3538
3539   Draws the line ending with the specified \a painter at the position \a pos. The direction of the
3540   line ending is controlled with \a dir.
3541 */
3542 void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const
3543 {
3544   if (mStyle == esNone)
3545     return;
3546
3547   QVector2D lengthVec(dir.normalized());
3548   if (lengthVec.isNull())
3549     lengthVec = QVector2D(1, 0);
3550   QVector2D widthVec(-lengthVec.y(), lengthVec.x());
3551   lengthVec *= (float)(mLength*(mInverted ? -1 : 1));
3552   widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1));
3553
3554   QPen penBackup = painter->pen();
3555   QBrush brushBackup = painter->brush();
3556   QPen miterPen = penBackup;
3557   miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey
3558   QBrush brush(painter->pen().color(), Qt::SolidPattern);
3559   switch (mStyle)
3560   {
3561     case esNone: break;
3562     case esFlatArrow:
3563     {
3564       QPointF points[3] = {pos.toPointF(),
3565                            (pos-lengthVec+widthVec).toPointF(),
3566                            (pos-lengthVec-widthVec).toPointF()
3567                           };
3568       painter->setPen(miterPen);
3569       painter->setBrush(brush);
3570       painter->drawConvexPolygon(points, 3);
3571       painter->setBrush(brushBackup);
3572       painter->setPen(penBackup);
3573       break;
3574     }
3575     case esSpikeArrow:
3576     {
3577       QPointF points[4] = {pos.toPointF(),
3578                            (pos-lengthVec+widthVec).toPointF(),
3579                            (pos-lengthVec*0.8f).toPointF(),
3580                            (pos-lengthVec-widthVec).toPointF()
3581                           };
3582       painter->setPen(miterPen);
3583       painter->setBrush(brush);
3584       painter->drawConvexPolygon(points, 4);
3585       painter->setBrush(brushBackup);
3586       painter->setPen(penBackup);
3587       break;
3588     }
3589     case esLineArrow:
3590     {
3591       QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(),
3592                            pos.toPointF(),
3593                            (pos-lengthVec-widthVec).toPointF()
3594                           };
3595       painter->setPen(miterPen);
3596       painter->drawPolyline(points, 3);
3597       painter->setPen(penBackup);
3598       break;
3599     }
3600     case esDisc:
3601     {
3602       painter->setBrush(brush);
3603       painter->drawEllipse(pos.toPointF(),  mWidth*0.5, mWidth*0.5);
3604       painter->setBrush(brushBackup);
3605       break;
3606     }
3607     case esSquare:
3608     {
3609       QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3610       QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(),
3611                            (pos-widthVecPerp-widthVec).toPointF(),
3612                            (pos+widthVecPerp-widthVec).toPointF(),
3613                            (pos+widthVecPerp+widthVec).toPointF()
3614                           };
3615       painter->setPen(miterPen);
3616       painter->setBrush(brush);
3617       painter->drawConvexPolygon(points, 4);
3618       painter->setBrush(brushBackup);
3619       painter->setPen(penBackup);
3620       break;
3621     }
3622     case esDiamond:
3623     {
3624       QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3625       QPointF points[4] = {(pos-widthVecPerp).toPointF(),
3626                            (pos-widthVec).toPointF(),
3627                            (pos+widthVecPerp).toPointF(),
3628                            (pos+widthVec).toPointF()
3629                           };
3630       painter->setPen(miterPen);
3631       painter->setBrush(brush);
3632       painter->drawConvexPolygon(points, 4);
3633       painter->setBrush(brushBackup);
3634       painter->setPen(penBackup);
3635       break;
3636     }
3637     case esBar:
3638     {
3639       painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF());
3640       break;
3641     }
3642     case esHalfBar:
3643     {
3644       painter->drawLine((pos+widthVec).toPointF(), pos.toPointF());
3645       break;
3646     }
3647     case esSkewedBar:
3648     {
3649       if (qFuzzyIsNull(painter->pen().widthF()) && !painter->modes().testFlag(QCPPainter::pmNonCosmetic))
3650       {
3651         // if drawing with cosmetic pen (perfectly thin stroke, happens only in vector exports), draw bar exactly on tip of line
3652         painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)).toPointF(),
3653                           (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)).toPointF());
3654       } else
3655       {
3656         // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly
3657         painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF(),
3658                           (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF());
3659       }
3660       break;
3661     }
3662   }
3663 }
3664
3665 /*! \internal
3666   \overload
3667
3668   Draws the line ending. The direction is controlled with the \a angle parameter in radians.
3669 */
3670 void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, double angle) const
3671 {
3672   draw(painter, pos, QVector2D(qCos(angle), qSin(angle)));
3673 }
3674
3675
3676 ////////////////////////////////////////////////////////////////////////////////////////////////////
3677 //////////////////// QCPGrid
3678 ////////////////////////////////////////////////////////////////////////////////////////////////////
3679
3680 /*! \class QCPGrid
3681   \brief Responsible for drawing the grid of a QCPAxis.
3682
3683   This class is tightly bound to QCPAxis. Every axis owns a grid instance and uses it to draw the
3684   grid lines, sub grid lines and zero-line. You can interact with the grid of an axis via \ref
3685   QCPAxis::grid. Normally, you don't need to create an instance of QCPGrid yourself.
3686
3687   The axis and grid drawing was split into two classes to allow them to be placed on different
3688   layers (both QCPAxis and QCPGrid inherit from QCPLayerable). Thus it is possible to have the grid
3689   in the background and the axes in the foreground, and any plottables/items in between. This
3690   described situation is the default setup, see the QCPLayer documentation.
3691 */
3692
3693 /*!
3694   Creates a QCPGrid instance and sets default values.
3695
3696   You shouldn't instantiate grids on their own, since every QCPAxis brings its own QCPGrid.
3697 */
3698 QCPGrid::QCPGrid(QCPAxis *parentAxis) :
3699   QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
3700   mParentAxis(parentAxis)
3701 {
3702   // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called
3703   setParent(parentAxis);
3704   setPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
3705   setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
3706   setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine));
3707   setSubGridVisible(false);
3708   setAntialiased(false);
3709   setAntialiasedSubGrid(false);
3710   setAntialiasedZeroLine(false);
3711 }
3712
3713 /*!
3714   Sets whether grid lines at sub tick marks are drawn.
3715
3716   \see setSubGridPen
3717 */
3718 void QCPGrid::setSubGridVisible(bool visible)
3719 {
3720   mSubGridVisible = visible;
3721 }
3722
3723 /*!
3724   Sets whether sub grid lines are drawn antialiased.
3725 */
3726 void QCPGrid::setAntialiasedSubGrid(bool enabled)
3727 {
3728   mAntialiasedSubGrid = enabled;
3729 }
3730
3731 /*!
3732   Sets whether zero lines are drawn antialiased.
3733 */
3734 void QCPGrid::setAntialiasedZeroLine(bool enabled)
3735 {
3736   mAntialiasedZeroLine = enabled;
3737 }
3738
3739 /*!
3740   Sets the pen with which (major) grid lines are drawn.
3741 */
3742 void QCPGrid::setPen(const QPen &pen)
3743 {
3744   mPen = pen;
3745 }
3746
3747 /*!
3748   Sets the pen with which sub grid lines are drawn.
3749 */
3750 void QCPGrid::setSubGridPen(const QPen &pen)
3751 {
3752   mSubGridPen = pen;
3753 }
3754
3755 /*!
3756   Sets the pen with which zero lines are drawn.
3757
3758   Zero lines are lines at value coordinate 0 which may be drawn with a different pen than other grid
3759   lines. To disable zero lines and just draw normal grid lines at zero, set \a pen to Qt::NoPen.
3760 */
3761 void QCPGrid::setZeroLinePen(const QPen &pen)
3762 {
3763   mZeroLinePen = pen;
3764 }
3765
3766 /*! \internal
3767
3768   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
3769   before drawing the major grid lines.
3770
3771   This is the antialiasing state the painter passed to the \ref draw method is in by default.
3772
3773   This function takes into account the local setting of the antialiasing flag as well as the
3774   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
3775   QCustomPlot::setNotAntialiasedElements.
3776
3777   \see setAntialiased
3778 */
3779 void QCPGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const
3780 {
3781   applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid);
3782 }
3783
3784 /*! \internal
3785
3786   Draws grid lines and sub grid lines at the positions of (sub) ticks of the parent axis, spanning
3787   over the complete axis rect. Also draws the zero line, if appropriate (\ref setZeroLinePen).
3788 */
3789 void QCPGrid::draw(QCPPainter *painter)
3790 {
3791   if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3792
3793   if (mSubGridVisible)
3794     drawSubGridLines(painter);
3795   drawGridLines(painter);
3796 }
3797
3798 /*! \internal
3799
3800   Draws the main grid lines and possibly a zero line with the specified painter.
3801
3802   This is a helper function called by \ref draw.
3803 */
3804 void QCPGrid::drawGridLines(QCPPainter *painter) const
3805 {
3806   if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3807
3808   int lowTick = mParentAxis->mLowestVisibleTick;
3809   int highTick = mParentAxis->mHighestVisibleTick;
3810   double t; // helper variable, result of coordinate-to-pixel transforms
3811   if (mParentAxis->orientation() == Qt::Horizontal)
3812   {
3813     // draw zeroline:
3814     int zeroLineIndex = -1;
3815     if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
3816     {
3817       applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine);
3818       painter->setPen(mZeroLinePen);
3819       double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero
3820       for (int i=lowTick; i <= highTick; ++i)
3821       {
3822         if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
3823         {
3824           zeroLineIndex = i;
3825           t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
3826           painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3827           break;
3828         }
3829       }
3830     }
3831     // draw grid lines:
3832     applyDefaultAntialiasingHint(painter);
3833     painter->setPen(mPen);
3834     for (int i=lowTick; i <= highTick; ++i)
3835     {
3836       if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
3837       t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
3838       painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3839     }
3840   } else
3841   {
3842     // draw zeroline:
3843     int zeroLineIndex = -1;
3844     if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
3845     {
3846       applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine);
3847       painter->setPen(mZeroLinePen);
3848       double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero
3849       for (int i=lowTick; i <= highTick; ++i)
3850       {
3851         if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
3852         {
3853           zeroLineIndex = i;
3854           t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
3855           painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3856           break;
3857         }
3858       }
3859     }
3860     // draw grid lines:
3861     applyDefaultAntialiasingHint(painter);
3862     painter->setPen(mPen);
3863     for (int i=lowTick; i <= highTick; ++i)
3864     {
3865       if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
3866       t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
3867       painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3868     }
3869   }
3870 }
3871
3872 /*! \internal
3873
3874   Draws the sub grid lines with the specified painter.
3875
3876   This is a helper function called by \ref draw.
3877 */
3878 void QCPGrid::drawSubGridLines(QCPPainter *painter) const
3879 {
3880   if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3881
3882   applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid);
3883   double t; // helper variable, result of coordinate-to-pixel transforms
3884   painter->setPen(mSubGridPen);
3885   if (mParentAxis->orientation() == Qt::Horizontal)
3886   {
3887     for (int i=0; i<mParentAxis->mSubTickVector.size(); ++i)
3888     {
3889       t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // x
3890       painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3891     }
3892   } else
3893   {
3894     for (int i=0; i<mParentAxis->mSubTickVector.size(); ++i)
3895     {
3896       t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // y
3897       painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3898     }
3899   }
3900 }
3901
3902
3903 ////////////////////////////////////////////////////////////////////////////////////////////////////
3904 //////////////////// QCPAxis
3905 ////////////////////////////////////////////////////////////////////////////////////////////////////
3906
3907 /*! \class QCPAxis
3908   \brief Manages a single axis inside a QCustomPlot.
3909
3910   Usually doesn't need to be instantiated externally. Access %QCustomPlot's default four axes via
3911   QCustomPlot::xAxis (bottom), QCustomPlot::yAxis (left), QCustomPlot::xAxis2 (top) and
3912   QCustomPlot::yAxis2 (right).
3913
3914   Axes are always part of an axis rect, see QCPAxisRect.
3915   \image html AxisNamesOverview.png
3916   <center>Naming convention of axis parts</center>
3917   \n
3918
3919   \image html AxisRectSpacingOverview.png
3920   <center>Overview of the spacings and paddings that define the geometry of an axis. The dashed gray line
3921   on the left represents the QCustomPlot widget border.</center>
3922
3923 */
3924
3925 /* start of documentation of inline functions */
3926
3927 /*! \fn Qt::Orientation QCPAxis::orientation() const
3928
3929   Returns the orientation of this axis. The axis orientation (horizontal or vertical) is deduced
3930   from the axis type (left, top, right or bottom).
3931
3932   \see orientation(AxisType type)
3933 */
3934
3935 /*! \fn QCPGrid *QCPAxis::grid() const
3936
3937   Returns the \ref QCPGrid instance belonging to this axis. Access it to set details about the way the
3938   grid is displayed.
3939 */
3940
3941 /*! \fn static Qt::Orientation QCPAxis::orientation(AxisType type)
3942
3943   Returns the orientation of the specified axis type
3944
3945   \see orientation()
3946 */
3947
3948 /* end of documentation of inline functions */
3949 /* start of documentation of signals */
3950
3951 /*! \fn void QCPAxis::ticksRequest()
3952
3953   This signal is emitted when \ref setAutoTicks is false and the axis is about to generate tick
3954   labels for a replot.
3955
3956   Modifying the tick positions can be done with \ref setTickVector. If you also want to control the
3957   tick labels, set \ref setAutoTickLabels to false and also provide the labels with \ref
3958   setTickVectorLabels.
3959
3960   If you only want static ticks you probably don't need this signal, since you can just set the
3961   tick vector (and possibly tick label vector) once. However, if you want to provide ticks (and
3962   maybe labels) dynamically, e.g. depending on the current axis range, connect a slot to this
3963   signal and set the vector/vectors there.
3964 */
3965
3966 /*! \fn void QCPAxis::rangeChanged(const QCPRange &newRange)
3967
3968   This signal is emitted when the range of this axis has changed. You can connect it to the \ref
3969   setRange slot of another axis to communicate the new range to the other axis, in order for it to
3970   be synchronized.
3971 */
3972
3973 /*! \fn void QCPAxis::rangeChanged(const QCPRange &newRange, const QCPRange &oldRange)
3974   \overload
3975
3976   Additionally to the new range, this signal also provides the previous range held by the axis as
3977   \a oldRange.
3978 */
3979
3980 /*! \fn void QCPAxis::scaleTypeChanged(QCPAxis::ScaleType scaleType);
3981
3982   This signal is emitted when the scale type changes, by calls to \ref setScaleType
3983 */
3984
3985 /*! \fn void QCPAxis::selectionChanged(QCPAxis::SelectableParts selection)
3986
3987   This signal is emitted when the selection state of this axis has changed, either by user interaction
3988   or by a direct call to \ref setSelectedParts.
3989 */
3990
3991 /*! \fn void QCPAxis::selectableChanged(const QCPAxis::SelectableParts &parts);
3992
3993   This signal is emitted when the selectability changes, by calls to \ref setSelectableParts
3994 */
3995
3996 /* end of documentation of signals */
3997
3998 /*!
3999   Constructs an Axis instance of Type \a type for the axis rect \a parent.
4000
4001   Usually it isn't necessary to instantiate axes directly, because you can let QCustomPlot create
4002   them for you with \ref QCPAxisRect::addAxis. If you want to use own QCPAxis-subclasses however,
4003   create them manually and then inject them also via \ref QCPAxisRect::addAxis.
4004 */
4005 QCPAxis::QCPAxis(QCPAxisRect *parent, AxisType type) :
4006   QCPLayerable(parent->parentPlot(), QString(), parent),
4007   // axis base:
4008   mAxisType(type),
4009   mAxisRect(parent),
4010   mPadding(5),
4011   mOrientation(orientation(type)),
4012   mSelectableParts(spAxis | spTickLabels | spAxisLabel),
4013   mSelectedParts(spNone),
4014   mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4015   mSelectedBasePen(QPen(Qt::blue, 2)),
4016   // axis label:
4017   mLabel(),
4018   mLabelFont(mParentPlot->font()),
4019   mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
4020   mLabelColor(Qt::black),
4021   mSelectedLabelColor(Qt::blue),
4022   // tick labels:
4023   mTickLabels(true),
4024   mAutoTickLabels(true),
4025   mTickLabelType(ltNumber),
4026   mTickLabelFont(mParentPlot->font()),
4027   mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
4028   mTickLabelColor(Qt::black),
4029   mSelectedTickLabelColor(Qt::blue),
4030   mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")),
4031   mDateTimeSpec(Qt::LocalTime),
4032   mNumberPrecision(6),
4033   mNumberFormatChar('g'),
4034   mNumberBeautifulPowers(true),
4035   // ticks and subticks:
4036   mTicks(true),
4037   mTickStep(1),
4038   mSubTickCount(4),
4039   mAutoTickCount(6),
4040   mAutoTicks(true),
4041   mAutoTickStep(true),
4042   mAutoSubTicks(true),
4043   mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4044   mSelectedTickPen(QPen(Qt::blue, 2)),
4045   mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4046   mSelectedSubTickPen(QPen(Qt::blue, 2)),
4047   // scale and range:
4048   mRange(0, 5),
4049   mRangeReversed(false),
4050   mScaleType(stLinear),
4051   mScaleLogBase(10),
4052   mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)),
4053   // internal members:
4054   mGrid(new QCPGrid(this)),
4055   mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())),
4056   mLowestVisibleTick(0),
4057   mHighestVisibleTick(-1),
4058   mCachedMarginValid(false),
4059   mCachedMargin(0)
4060 {
4061   mGrid->setVisible(false);
4062   setAntialiased(false);
4063   setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again
4064
4065   if (type == atTop)
4066   {
4067     setTickLabelPadding(3);
4068     setLabelPadding(6);
4069   } else if (type == atRight)
4070   {
4071     setTickLabelPadding(7);
4072     setLabelPadding(12);
4073   } else if (type == atBottom)
4074   {
4075     setTickLabelPadding(3);
4076     setLabelPadding(3);
4077   } else if (type == atLeft)
4078   {
4079     setTickLabelPadding(5);
4080     setLabelPadding(10);
4081   }
4082 }
4083
4084 QCPAxis::~QCPAxis()
4085 {
4086   delete mAxisPainter;
4087 }
4088
4089 /* No documentation as it is a property getter */
4090 int QCPAxis::tickLabelPadding() const
4091 {
4092   return mAxisPainter->tickLabelPadding;
4093 }
4094
4095 /* No documentation as it is a property getter */
4096 double QCPAxis::tickLabelRotation() const
4097 {
4098   return mAxisPainter->tickLabelRotation;
4099 }
4100
4101 /* No documentation as it is a property getter */
4102 QCPAxis::LabelSide QCPAxis::tickLabelSide() const
4103 {
4104   return mAxisPainter->tickLabelSide;
4105 }
4106
4107 /* No documentation as it is a property getter */
4108 QString QCPAxis::numberFormat() const
4109 {
4110   QString result;
4111   result.append(mNumberFormatChar);
4112   if (mNumberBeautifulPowers)
4113   {
4114     result.append(QLatin1Char('b'));
4115     if (mAxisPainter->numberMultiplyCross)
4116       result.append(QLatin1Char('c'));
4117   }
4118   return result;
4119 }
4120
4121 /* No documentation as it is a property getter */
4122 int QCPAxis::tickLengthIn() const
4123 {
4124   return mAxisPainter->tickLengthIn;
4125 }
4126
4127 /* No documentation as it is a property getter */
4128 int QCPAxis::tickLengthOut() const
4129 {
4130   return mAxisPainter->tickLengthOut;
4131 }
4132
4133 /* No documentation as it is a property getter */
4134 int QCPAxis::subTickLengthIn() const
4135 {
4136   return mAxisPainter->subTickLengthIn;
4137 }
4138
4139 /* No documentation as it is a property getter */
4140 int QCPAxis::subTickLengthOut() const
4141 {
4142   return mAxisPainter->subTickLengthOut;
4143 }
4144
4145 /* No documentation as it is a property getter */
4146 int QCPAxis::labelPadding() const
4147 {
4148   return mAxisPainter->labelPadding;
4149 }
4150
4151 /* No documentation as it is a property getter */
4152 int QCPAxis::offset() const
4153 {
4154   return mAxisPainter->offset;
4155 }
4156
4157 /* No documentation as it is a property getter */
4158 QCPLineEnding QCPAxis::lowerEnding() const
4159 {
4160   return mAxisPainter->lowerEnding;
4161 }
4162
4163 /* No documentation as it is a property getter */
4164 QCPLineEnding QCPAxis::upperEnding() const
4165 {
4166   return mAxisPainter->upperEnding;
4167 }
4168
4169 /*!
4170   Sets whether the axis uses a linear scale or a logarithmic scale. If \a type is set to \ref
4171   stLogarithmic, the logarithm base can be set with \ref setScaleLogBase. In logarithmic axis
4172   scaling, major tick marks appear at all powers of the logarithm base. Properties like tick step
4173   (\ref setTickStep) don't apply in logarithmic scaling. If you wish a decimal base but less major
4174   ticks, consider choosing a logarithm base of 100, 1000 or even higher.
4175
4176   If \a type is \ref stLogarithmic and the number format (\ref setNumberFormat) uses the 'b' option
4177   (beautifully typeset decimal powers), the display usually is "1 [multiplication sign] 10
4178   [superscript] n", which looks unnatural for logarithmic scaling (the "1 [multiplication sign]"
4179   part). To only display the decimal power, set the number precision to zero with
4180   \ref setNumberPrecision.
4181 */
4182 void QCPAxis::setScaleType(QCPAxis::ScaleType type)
4183 {
4184   if (mScaleType != type)
4185   {
4186     mScaleType = type;
4187     if (mScaleType == stLogarithmic)
4188       setRange(mRange.sanitizedForLogScale());
4189     mCachedMarginValid = false;
4190     emit scaleTypeChanged(mScaleType);
4191   }
4192 }
4193
4194 /*!
4195   If \ref setScaleType is set to \ref stLogarithmic, \a base will be the logarithm base of the
4196   scaling. In logarithmic axis scaling, major tick marks appear at all powers of \a base.
4197
4198   Properties like tick step (\ref setTickStep) don't apply in logarithmic scaling. If you wish a decimal base but
4199   less major ticks, consider choosing \a base 100, 1000 or even higher.
4200 */
4201 void QCPAxis::setScaleLogBase(double base)
4202 {
4203   if (base > 1)
4204   {
4205     mScaleLogBase = base;
4206     mScaleLogBaseLogInv = 1.0/qLn(mScaleLogBase); // buffer for faster baseLog() calculation
4207     mCachedMarginValid = false;
4208   } else
4209     qDebug() << Q_FUNC_INFO << "Invalid logarithmic scale base (must be greater 1):" << base;
4210 }
4211
4212 /*!
4213   Sets the range of the axis.
4214
4215   This slot may be connected with the \ref rangeChanged signal of another axis so this axis
4216   is always synchronized with the other axis range, when it changes.
4217
4218   To invert the direction of an axis, use \ref setRangeReversed.
4219 */
4220 void QCPAxis::setRange(const QCPRange &range)
4221 {
4222   if (range.lower == mRange.lower && range.upper == mRange.upper)
4223     return;
4224
4225   if (!QCPRange::validRange(range)) return;
4226   QCPRange oldRange = mRange;
4227   if (mScaleType == stLogarithmic)
4228   {
4229     mRange = range.sanitizedForLogScale();
4230   } else
4231   {
4232     mRange = range.sanitizedForLinScale();
4233   }
4234   mCachedMarginValid = false;
4235   emit rangeChanged(mRange);
4236   emit rangeChanged(mRange, oldRange);
4237 }
4238
4239 /*!
4240   Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface.
4241   (When \ref QCustomPlot::setInteractions contains iSelectAxes.)
4242
4243   However, even when \a selectable is set to a value not allowing the selection of a specific part,
4244   it is still possible to set the selection of this part manually, by calling \ref setSelectedParts
4245   directly.
4246
4247   \see SelectablePart, setSelectedParts
4248 */
4249 void QCPAxis::setSelectableParts(const SelectableParts &selectable)
4250 {
4251   if (mSelectableParts != selectable)
4252   {
4253     mSelectableParts = selectable;
4254     emit selectableChanged(mSelectableParts);
4255   }
4256 }
4257
4258 /*!
4259   Sets the selected state of the respective axis parts described by \ref SelectablePart. When a part
4260   is selected, it uses a different pen/font.
4261
4262   The entire selection mechanism for axes is handled automatically when \ref
4263   QCustomPlot::setInteractions contains iSelectAxes. You only need to call this function when you
4264   wish to change the selection state manually.
4265
4266   This function can change the selection state of a part, independent of the \ref setSelectableParts setting.
4267
4268   emits the \ref selectionChanged signal when \a selected is different from the previous selection state.
4269
4270   \see SelectablePart, setSelectableParts, selectTest, setSelectedBasePen, setSelectedTickPen, setSelectedSubTickPen,
4271   setSelectedTickLabelFont, setSelectedLabelFont, setSelectedTickLabelColor, setSelectedLabelColor
4272 */
4273 void QCPAxis::setSelectedParts(const SelectableParts &selected)
4274 {
4275   if (mSelectedParts != selected)
4276   {
4277     mSelectedParts = selected;
4278     emit selectionChanged(mSelectedParts);
4279   }
4280 }
4281
4282 /*!
4283   \overload
4284
4285   Sets the lower and upper bound of the axis range.
4286
4287   To invert the direction of an axis, use \ref setRangeReversed.
4288
4289   There is also a slot to set a range, see \ref setRange(const QCPRange &range).
4290 */
4291 void QCPAxis::setRange(double lower, double upper)
4292 {
4293   if (lower == mRange.lower && upper == mRange.upper)
4294     return;
4295
4296   if (!QCPRange::validRange(lower, upper)) return;
4297   QCPRange oldRange = mRange;
4298   mRange.lower = lower;
4299   mRange.upper = upper;
4300   if (mScaleType == stLogarithmic)
4301   {
4302     mRange = mRange.sanitizedForLogScale();
4303   } else
4304   {
4305     mRange = mRange.sanitizedForLinScale();
4306   }
4307   mCachedMarginValid = false;
4308   emit rangeChanged(mRange);
4309   emit rangeChanged(mRange, oldRange);
4310 }
4311
4312 /*!
4313   \overload
4314
4315   Sets the range of the axis.
4316
4317   The \a position coordinate indicates together with the \a alignment parameter, where the new
4318   range will be positioned. \a size defines the size of the new axis range. \a alignment may be
4319   Qt::AlignLeft, Qt::AlignRight or Qt::AlignCenter. This will cause the left border, right border,
4320   or center of the range to be aligned with \a position. Any other values of \a alignment will
4321   default to Qt::AlignCenter.
4322 */
4323 void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment)
4324 {
4325   if (alignment == Qt::AlignLeft)
4326     setRange(position, position+size);
4327   else if (alignment == Qt::AlignRight)
4328     setRange(position-size, position);
4329   else // alignment == Qt::AlignCenter
4330     setRange(position-size/2.0, position+size/2.0);
4331 }
4332
4333 /*!
4334   Sets the lower bound of the axis range. The upper bound is not changed.
4335   \see setRange
4336 */
4337 void QCPAxis::setRangeLower(double lower)
4338 {
4339   if (mRange.lower == lower)
4340     return;
4341
4342   QCPRange oldRange = mRange;
4343   mRange.lower = lower;
4344   if (mScaleType == stLogarithmic)
4345   {
4346     mRange = mRange.sanitizedForLogScale();
4347   } else
4348   {
4349     mRange = mRange.sanitizedForLinScale();
4350   }
4351   mCachedMarginValid = false;
4352   emit rangeChanged(mRange);
4353   emit rangeChanged(mRange, oldRange);
4354 }
4355
4356 /*!
4357   Sets the upper bound of the axis range. The lower bound is not changed.
4358   \see setRange
4359 */
4360 void QCPAxis::setRangeUpper(double upper)
4361 {
4362   if (mRange.upper == upper)
4363     return;
4364
4365   QCPRange oldRange = mRange;
4366   mRange.upper = upper;
4367   if (mScaleType == stLogarithmic)
4368   {
4369     mRange = mRange.sanitizedForLogScale();
4370   } else
4371   {
4372     mRange = mRange.sanitizedForLinScale();
4373   }
4374   mCachedMarginValid = false;
4375   emit rangeChanged(mRange);
4376   emit rangeChanged(mRange, oldRange);
4377 }
4378
4379 /*!
4380   Sets whether the axis range (direction) is displayed reversed. Normally, the values on horizontal
4381   axes increase left to right, on vertical axes bottom to top. When \a reversed is set to true, the
4382   direction of increasing values is inverted.
4383
4384   Note that the range and data interface stays the same for reversed axes, e.g. the \a lower part
4385   of the \ref setRange interface will still reference the mathematically smaller number than the \a
4386   upper part.
4387 */
4388 void QCPAxis::setRangeReversed(bool reversed)
4389 {
4390   if (mRangeReversed != reversed)
4391   {
4392     mRangeReversed = reversed;
4393     mCachedMarginValid = false;
4394   }
4395 }
4396
4397 /*!
4398   Sets whether the tick positions should be calculated automatically (either from an automatically
4399   generated tick step or a tick step provided manually via \ref setTickStep, see \ref setAutoTickStep).
4400
4401   If \a on is set to false, you must provide the tick positions manually via \ref setTickVector.
4402   For these manual ticks you may let QCPAxis generate the appropriate labels automatically by
4403   leaving \ref setAutoTickLabels set to true. If you also wish to control the displayed labels
4404   manually, set \ref setAutoTickLabels to false and provide the label strings with \ref
4405   setTickVectorLabels.
4406
4407   If you need dynamically calculated tick vectors (and possibly tick label vectors), set the
4408   vectors in a slot connected to the \ref ticksRequest signal.
4409
4410   \see setAutoTickLabels, setAutoSubTicks, setAutoTickCount, setAutoTickStep
4411 */
4412 void QCPAxis::setAutoTicks(bool on)
4413 {
4414   if (mAutoTicks != on)
4415   {
4416     mAutoTicks = on;
4417     mCachedMarginValid = false;
4418   }
4419 }
4420
4421 /*!
4422   When \ref setAutoTickStep is true, \a approximateCount determines how many ticks should be
4423   generated in the visible range, approximately.
4424
4425   It's not guaranteed that this number of ticks is met exactly, but approximately within a
4426   tolerance of about two.
4427
4428   Only values greater than zero are accepted as \a approximateCount.
4429
4430   \see setAutoTickStep, setAutoTicks, setAutoSubTicks
4431 */
4432 void QCPAxis::setAutoTickCount(int approximateCount)
4433 {
4434   if (mAutoTickCount != approximateCount)
4435   {
4436     if (approximateCount > 0)
4437     {
4438       mAutoTickCount = approximateCount;
4439       mCachedMarginValid = false;
4440     } else
4441       qDebug() << Q_FUNC_INFO << "approximateCount must be greater than zero:" << approximateCount;
4442   }
4443 }
4444
4445 /*!
4446   Sets whether the tick labels are generated automatically. Depending on the tick label type (\ref
4447   ltNumber or \ref ltDateTime), the labels will either show the coordinate as floating point
4448   number (\ref setNumberFormat), or a date/time formatted according to \ref setDateTimeFormat.
4449
4450   If \a on is set to false, you should provide the tick labels via \ref setTickVectorLabels. This
4451   is usually used in a combination with \ref setAutoTicks set to false for complete control over
4452   tick positions and labels, e.g. when the ticks should be at multiples of pi and show "2pi", "3pi"
4453   etc. as tick labels.
4454
4455   If you need dynamically calculated tick vectors (and possibly tick label vectors), set the
4456   vectors in a slot connected to the \ref ticksRequest signal.
4457
4458   \see setAutoTicks
4459 */
4460 void QCPAxis::setAutoTickLabels(bool on)
4461 {
4462   if (mAutoTickLabels != on)
4463   {
4464     mAutoTickLabels = on;
4465     mCachedMarginValid = false;
4466   }
4467 }
4468
4469 /*!
4470   Sets whether the tick step, i.e. the interval between two (major) ticks, is calculated
4471   automatically. If \a on is set to true, the axis finds a tick step that is reasonable for human
4472   readable plots.
4473
4474   The number of ticks the algorithm aims for within the visible range can be specified with \ref
4475   setAutoTickCount.
4476
4477   If \a on is set to false, you may set the tick step manually with \ref setTickStep.
4478
4479   \see setAutoTicks, setAutoSubTicks, setAutoTickCount
4480 */
4481 void QCPAxis::setAutoTickStep(bool on)
4482 {
4483   if (mAutoTickStep != on)
4484   {
4485     mAutoTickStep = on;
4486     mCachedMarginValid = false;
4487   }
4488 }
4489
4490 /*!
4491   Sets whether the number of sub ticks in one tick interval is determined automatically. This
4492   works, as long as the tick step mantissa is a multiple of 0.5. When \ref setAutoTickStep is
4493   enabled, this is always the case.
4494
4495   When \a on is set to false, you may set the sub tick count with \ref setSubTickCount manually.
4496
4497   \see setAutoTickCount, setAutoTicks, setAutoTickStep
4498 */
4499 void QCPAxis::setAutoSubTicks(bool on)
4500 {
4501   if (mAutoSubTicks != on)
4502   {
4503     mAutoSubTicks = on;
4504     mCachedMarginValid = false;
4505   }
4506 }
4507
4508 /*!
4509   Sets whether tick marks are displayed.
4510
4511   Note that setting \a show to false does not imply that tick labels are invisible, too. To achieve
4512   that, see \ref setTickLabels.
4513 */
4514 void QCPAxis::setTicks(bool show)
4515 {
4516   if (mTicks != show)
4517   {
4518     mTicks = show;
4519     mCachedMarginValid = false;
4520   }
4521 }
4522
4523 /*!
4524   Sets whether tick labels are displayed. Tick labels are the numbers drawn next to tick marks.
4525 */
4526 void QCPAxis::setTickLabels(bool show)
4527 {
4528   if (mTickLabels != show)
4529   {
4530     mTickLabels = show;
4531     mCachedMarginValid = false;
4532   }
4533 }
4534
4535 /*!
4536   Sets the distance between the axis base line (including any outward ticks) and the tick labels.
4537   \see setLabelPadding, setPadding
4538 */
4539 void QCPAxis::setTickLabelPadding(int padding)
4540 {
4541   if (mAxisPainter->tickLabelPadding != padding)
4542   {
4543     mAxisPainter->tickLabelPadding = padding;
4544     mCachedMarginValid = false;
4545   }
4546 }
4547
4548 /*!
4549   Sets whether the tick labels display numbers or dates/times.
4550
4551   If \a type is set to \ref ltNumber, the format specifications of \ref setNumberFormat apply.
4552
4553   If \a type is set to \ref ltDateTime, the format specifications of \ref setDateTimeFormat apply.
4554
4555   In QCustomPlot, date/time coordinates are <tt>double</tt> numbers representing the seconds since
4556   1970-01-01T00:00:00 UTC. This format can be retrieved from QDateTime objects with the
4557   QDateTime::toTime_t() function. Since this only gives a resolution of one second, there is also
4558   the QDateTime::toMSecsSinceEpoch() function which returns the timespan described above in
4559   milliseconds. Divide its return value by 1000.0 to get a value with the format needed for
4560   date/time plotting, with a resolution of one millisecond.
4561
4562   Using the toMSecsSinceEpoch function allows dates that go back to 2nd January 4713 B.C.
4563   (represented by a negative number), unlike the toTime_t function, which works with unsigned
4564   integers and thus only goes back to 1st January 1970. So both for range and accuracy, use of
4565   toMSecsSinceEpoch()/1000.0 should be preferred as key coordinate for date/time axes.
4566
4567   \see setTickLabels
4568 */
4569 void QCPAxis::setTickLabelType(LabelType type)
4570 {
4571   if (mTickLabelType != type)
4572   {
4573     mTickLabelType = type;
4574     mCachedMarginValid = false;
4575   }
4576 }
4577
4578 /*!
4579   Sets the font of the tick labels.
4580
4581   \see setTickLabels, setTickLabelColor
4582 */
4583 void QCPAxis::setTickLabelFont(const QFont &font)
4584 {
4585   if (font != mTickLabelFont)
4586   {
4587     mTickLabelFont = font;
4588     mCachedMarginValid = false;
4589   }
4590 }
4591
4592 /*!
4593   Sets the color of the tick labels.
4594
4595   \see setTickLabels, setTickLabelFont
4596 */
4597 void QCPAxis::setTickLabelColor(const QColor &color)
4598 {
4599   if (color != mTickLabelColor)
4600   {
4601     mTickLabelColor = color;
4602     mCachedMarginValid = false;
4603   }
4604 }
4605
4606 /*!
4607   Sets the rotation of the tick labels. If \a degrees is zero, the labels are drawn normally. Else,
4608   the tick labels are drawn rotated by \a degrees clockwise. The specified angle is bound to values
4609   from -90 to 90 degrees.
4610
4611   If \a degrees is exactly -90, 0 or 90, the tick labels are centered on the tick coordinate. For
4612   other angles, the label is drawn with an offset such that it seems to point toward or away from
4613   the tick mark.
4614 */
4615 void QCPAxis::setTickLabelRotation(double degrees)
4616 {
4617   if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation))
4618   {
4619     mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0);
4620     mCachedMarginValid = false;
4621   }
4622 }
4623
4624 /*!
4625   Sets whether the tick labels (numbers) shall appear inside or outside the axis rect.
4626
4627   The usual and default setting is \ref lsOutside. Very compact plots sometimes require tick labels
4628   to be inside the axis rect, to save space. If \a side is set to \ref lsInside, the tick labels
4629   appear on the inside are additionally clipped to the axis rect.
4630 */
4631 void QCPAxis::setTickLabelSide(LabelSide side)
4632 {
4633   mAxisPainter->tickLabelSide = side;
4634   mCachedMarginValid = false;
4635 }
4636
4637 /*!
4638   Sets the format in which dates and times are displayed as tick labels, if \ref setTickLabelType is \ref ltDateTime.
4639   for details about the \a format string, see the documentation of QDateTime::toString().
4640
4641   Newlines can be inserted with "\n".
4642
4643   \see setDateTimeSpec
4644 */
4645 void QCPAxis::setDateTimeFormat(const QString &format)
4646 {
4647   if (mDateTimeFormat != format)
4648   {
4649     mDateTimeFormat = format;
4650     mCachedMarginValid = false;
4651   }
4652 }
4653
4654 /*!
4655   Sets the time spec that is used for the date time values when \ref setTickLabelType is \ref
4656   ltDateTime.
4657
4658   The default value of QDateTime objects (and also QCustomPlot) is <tt>Qt::LocalTime</tt>. However,
4659   if the date time values passed to QCustomPlot are given in the UTC spec, set \a
4660   timeSpec to <tt>Qt::UTC</tt> to get the correct axis labels.
4661
4662   \see setDateTimeFormat
4663 */
4664 void QCPAxis::setDateTimeSpec(const Qt::TimeSpec &timeSpec)
4665 {
4666   mDateTimeSpec = timeSpec;
4667 }
4668
4669 /*!
4670   Sets the number format for the numbers drawn as tick labels (if tick label type is \ref
4671   ltNumber). This \a formatCode is an extended version of the format code used e.g. by
4672   QString::number() and QLocale::toString(). For reference about that, see the "Argument Formats"
4673   section in the detailed description of the QString class. \a formatCode is a string of one, two
4674   or three characters. The first character is identical to the normal format code used by Qt. In
4675   short, this means: 'e'/'E' scientific format, 'f' fixed format, 'g'/'G' scientific or fixed,
4676   whichever is shorter.
4677
4678   The second and third characters are optional and specific to QCustomPlot:\n
4679   If the first char was 'e' or 'g', numbers are/might be displayed in the scientific format, e.g.
4680   "5.5e9", which is ugly in a plot. So when the second char of \a formatCode is set to 'b' (for
4681   "beautiful"), those exponential numbers are formatted in a more natural way, i.e. "5.5
4682   [multiplication sign] 10 [superscript] 9". By default, the multiplication sign is a centered dot.
4683   If instead a cross should be shown (as is usual in the USA), the third char of \a formatCode can
4684   be set to 'c'. The inserted multiplication signs are the UTF-8 characters 215 (0xD7) for the
4685   cross and 183 (0xB7) for the dot.
4686
4687   If the scale type (\ref setScaleType) is \ref stLogarithmic and the \a formatCode uses the 'b'
4688   option (beautifully typeset decimal powers), the display usually is "1 [multiplication sign] 10
4689   [superscript] n", which looks unnatural for logarithmic scaling (the "1 [multiplication sign]"
4690   part). To only display the decimal power, set the number precision to zero with \ref
4691   setNumberPrecision.
4692
4693   Examples for \a formatCode:
4694   \li \c g normal format code behaviour. If number is small, fixed format is used, if number is large,
4695   normal scientific format is used
4696   \li \c gb If number is small, fixed format is used, if number is large, scientific format is used with
4697   beautifully typeset decimal powers and a dot as multiplication sign
4698   \li \c ebc All numbers are in scientific format with beautifully typeset decimal power and a cross as
4699   multiplication sign
4700   \li \c fb illegal format code, since fixed format doesn't support (or need) beautifully typeset decimal
4701   powers. Format code will be reduced to 'f'.
4702   \li \c hello illegal format code, since first char is not 'e', 'E', 'f', 'g' or 'G'. Current format
4703   code will not be changed.
4704 */
4705 void QCPAxis::setNumberFormat(const QString &formatCode)
4706 {
4707   if (formatCode.isEmpty())
4708   {
4709     qDebug() << Q_FUNC_INFO << "Passed formatCode is empty";
4710     return;
4711   }
4712   mCachedMarginValid = false;
4713
4714   // interpret first char as number format char:
4715   QString allowedFormatChars(QLatin1String("eEfgG"));
4716   if (allowedFormatChars.contains(formatCode.at(0)))
4717   {
4718     mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1());
4719   } else
4720   {
4721     qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode;
4722     return;
4723   }
4724   if (formatCode.length() < 2)
4725   {
4726     mNumberBeautifulPowers = false;
4727     mAxisPainter->numberMultiplyCross = false;
4728     return;
4729   }
4730
4731   // interpret second char as indicator for beautiful decimal powers:
4732   if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g')))
4733   {
4734     mNumberBeautifulPowers = true;
4735   } else
4736   {
4737     qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
4738     return;
4739   }
4740   if (formatCode.length() < 3)
4741   {
4742     mAxisPainter->numberMultiplyCross = false;
4743     return;
4744   }
4745
4746   // interpret third char as indicator for dot or cross multiplication symbol:
4747   if (formatCode.at(2) == QLatin1Char('c'))
4748   {
4749     mAxisPainter->numberMultiplyCross = true;
4750   } else if (formatCode.at(2) == QLatin1Char('d'))
4751   {
4752     mAxisPainter->numberMultiplyCross = false;
4753   } else
4754   {
4755     qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
4756     return;
4757   }
4758 }
4759
4760 /*!
4761   Sets the precision of the tick label numbers. See QLocale::toString(double i, char f, int prec)
4762   for details. The effect of precisions are most notably for number Formats starting with 'e', see
4763   \ref setNumberFormat
4764
4765   If the scale type (\ref setScaleType) is \ref stLogarithmic and the number format (\ref
4766   setNumberFormat) uses the 'b' format code (beautifully typeset decimal powers), the display
4767   usually is "1 [multiplication sign] 10 [superscript] n", which looks unnatural for logarithmic
4768   scaling (the redundant "1 [multiplication sign]" part). To only display the decimal power "10
4769   [superscript] n", set \a precision to zero.
4770 */
4771 void QCPAxis::setNumberPrecision(int precision)
4772 {
4773   if (mNumberPrecision != precision)
4774   {
4775     mNumberPrecision = precision;
4776     mCachedMarginValid = false;
4777   }
4778 }
4779
4780 /*!
4781   If \ref setAutoTickStep is set to false, use this function to set the tick step manually.
4782   The tick step is the interval between (major) ticks, in plot coordinates.
4783   \see setSubTickCount
4784 */
4785 void QCPAxis::setTickStep(double step)
4786 {
4787   if (mTickStep != step)
4788   {
4789     mTickStep = step;
4790     mCachedMarginValid = false;
4791   }
4792 }
4793
4794 /*!
4795   If you want full control over what ticks (and possibly labels) the axes show, this function is
4796   used to set the coordinates at which ticks will appear.\ref setAutoTicks must be disabled, else
4797   the provided tick vector will be overwritten with automatically generated tick coordinates upon
4798   replot. The labels of the ticks can be generated automatically when \ref setAutoTickLabels is
4799   left enabled. If it is disabled, you can set the labels manually with \ref setTickVectorLabels.
4800
4801   \a vec is a vector containing the positions of the ticks, in plot coordinates.
4802
4803   \warning \a vec must be sorted in ascending order, no additional checks are made to ensure this.
4804
4805   \see setTickVectorLabels
4806 */
4807 void QCPAxis::setTickVector(const QVector<double> &vec)
4808 {
4809   // don't check whether mTickVector != vec here, because it takes longer than we would save
4810   mTickVector = vec;
4811   mCachedMarginValid = false;
4812 }
4813
4814 /*!
4815   If you want full control over what ticks and labels the axes show, this function is used to set a
4816   number of QStrings that will be displayed at the tick positions which you need to provide with
4817   \ref setTickVector. These two vectors should have the same size. (Note that you need to disable
4818   \ref setAutoTicks and \ref setAutoTickLabels first.)
4819
4820   \a vec is a vector containing the labels of the ticks. The entries correspond to the respective
4821   indices in the tick vector, passed via \ref setTickVector.
4822
4823   \see setTickVector
4824 */
4825 void QCPAxis::setTickVectorLabels(const QVector<QString> &vec)
4826 {
4827   // don't check whether mTickVectorLabels != vec here, because it takes longer than we would save
4828   mTickVectorLabels = vec;
4829   mCachedMarginValid = false;
4830 }
4831
4832 /*!
4833   Sets the length of the ticks in pixels. \a inside is the length the ticks will reach inside the
4834   plot and \a outside is the length they will reach outside the plot. If \a outside is greater than
4835   zero, the tick labels and axis label will increase their distance to the axis accordingly, so
4836   they won't collide with the ticks.
4837
4838   \see setSubTickLength, setTickLengthIn, setTickLengthOut
4839 */
4840 void QCPAxis::setTickLength(int inside, int outside)
4841 {
4842   setTickLengthIn(inside);
4843   setTickLengthOut(outside);
4844 }
4845
4846 /*!
4847   Sets the length of the inward ticks in pixels. \a inside is the length the ticks will reach
4848   inside the plot.
4849
4850   \see setTickLengthOut, setTickLength, setSubTickLength
4851 */
4852 void QCPAxis::setTickLengthIn(int inside)
4853 {
4854   if (mAxisPainter->tickLengthIn != inside)
4855   {
4856     mAxisPainter->tickLengthIn = inside;
4857   }
4858 }
4859
4860 /*!
4861   Sets the length of the outward ticks in pixels. \a outside is the length the ticks will reach
4862   outside the plot. If \a outside is greater than zero, the tick labels and axis label will
4863   increase their distance to the axis accordingly, so they won't collide with the ticks.
4864
4865   \see setTickLengthIn, setTickLength, setSubTickLength
4866 */
4867 void QCPAxis::setTickLengthOut(int outside)
4868 {
4869   if (mAxisPainter->tickLengthOut != outside)
4870   {
4871     mAxisPainter->tickLengthOut = outside;
4872     mCachedMarginValid = false; // only outside tick length can change margin
4873   }
4874 }
4875
4876 /*!
4877   Sets the number of sub ticks in one (major) tick step. A sub tick count of three for example,
4878   divides the tick intervals in four sub intervals.
4879
4880   By default, the number of sub ticks is chosen automatically in a reasonable manner as long as the
4881   mantissa of the tick step is a multiple of 0.5. When \ref setAutoTickStep is enabled, this is
4882   always the case.
4883
4884   If you want to disable automatic sub tick count and use this function to set the count manually,
4885   see \ref setAutoSubTicks.
4886 */
4887 void QCPAxis::setSubTickCount(int count)
4888 {
4889   mSubTickCount = count;
4890 }
4891
4892 /*!
4893   Sets the length of the subticks in pixels. \a inside is the length the subticks will reach inside
4894   the plot and \a outside is the length they will reach outside the plot. If \a outside is greater
4895   than zero, the tick labels and axis label will increase their distance to the axis accordingly,
4896   so they won't collide with the ticks.
4897
4898   \see setTickLength, setSubTickLengthIn, setSubTickLengthOut
4899 */
4900 void QCPAxis::setSubTickLength(int inside, int outside)
4901 {
4902   setSubTickLengthIn(inside);
4903   setSubTickLengthOut(outside);
4904 }
4905
4906 /*!
4907   Sets the length of the inward subticks in pixels. \a inside is the length the subticks will reach inside
4908   the plot.
4909
4910   \see setSubTickLengthOut, setSubTickLength, setTickLength
4911 */
4912 void QCPAxis::setSubTickLengthIn(int inside)
4913 {
4914   if (mAxisPainter->subTickLengthIn != inside)
4915   {
4916     mAxisPainter->subTickLengthIn = inside;
4917   }
4918 }
4919
4920 /*!
4921   Sets the length of the outward subticks in pixels. \a outside is the length the subticks will reach
4922   outside the plot. If \a outside is greater than zero, the tick labels will increase their
4923   distance to the axis accordingly, so they won't collide with the ticks.
4924
4925   \see setSubTickLengthIn, setSubTickLength, setTickLength
4926 */
4927 void QCPAxis::setSubTickLengthOut(int outside)
4928 {
4929   if (mAxisPainter->subTickLengthOut != outside)
4930   {
4931     mAxisPainter->subTickLengthOut = outside;
4932     mCachedMarginValid = false; // only outside tick length can change margin
4933   }
4934 }
4935
4936 /*!
4937   Sets the pen, the axis base line is drawn with.
4938
4939   \see setTickPen, setSubTickPen
4940 */
4941 void QCPAxis::setBasePen(const QPen &pen)
4942 {
4943   mBasePen = pen;
4944 }
4945
4946 /*!
4947   Sets the pen, tick marks will be drawn with.
4948
4949   \see setTickLength, setBasePen
4950 */
4951 void QCPAxis::setTickPen(const QPen &pen)
4952 {
4953   mTickPen = pen;
4954 }
4955
4956 /*!
4957   Sets the pen, subtick marks will be drawn with.
4958
4959   \see setSubTickCount, setSubTickLength, setBasePen
4960 */
4961 void QCPAxis::setSubTickPen(const QPen &pen)
4962 {
4963   mSubTickPen = pen;
4964 }
4965
4966 /*!
4967   Sets the font of the axis label.
4968
4969   \see setLabelColor
4970 */
4971 void QCPAxis::setLabelFont(const QFont &font)
4972 {
4973   if (mLabelFont != font)
4974   {
4975     mLabelFont = font;
4976     mCachedMarginValid = false;
4977   }
4978 }
4979
4980 /*!
4981   Sets the color of the axis label.
4982
4983   \see setLabelFont
4984 */
4985 void QCPAxis::setLabelColor(const QColor &color)
4986 {
4987   mLabelColor = color;
4988 }
4989
4990 /*!
4991   Sets the text of the axis label that will be shown below/above or next to the axis, depending on
4992   its orientation. To disable axis labels, pass an empty string as \a str.
4993 */
4994 void QCPAxis::setLabel(const QString &str)
4995 {
4996   if (mLabel != str)
4997   {
4998     mLabel = str;
4999     mCachedMarginValid = false;
5000   }
5001 }
5002
5003 /*!
5004   Sets the distance between the tick labels and the axis label.
5005
5006   \see setTickLabelPadding, setPadding
5007 */
5008 void QCPAxis::setLabelPadding(int padding)
5009 {
5010   if (mAxisPainter->labelPadding != padding)
5011   {
5012     mAxisPainter->labelPadding = padding;
5013     mCachedMarginValid = false;
5014   }
5015 }
5016
5017 /*!
5018   Sets the padding of the axis.
5019
5020   When \ref QCPAxisRect::setAutoMargins is enabled, the padding is the additional outer most space,
5021   that is left blank.
5022
5023   The axis padding has no meaning if \ref QCPAxisRect::setAutoMargins is disabled.
5024
5025   \see setLabelPadding, setTickLabelPadding
5026 */
5027 void QCPAxis::setPadding(int padding)
5028 {
5029   if (mPadding != padding)
5030   {
5031     mPadding = padding;
5032     mCachedMarginValid = false;
5033   }
5034 }
5035
5036 /*!
5037   Sets the offset the axis has to its axis rect side.
5038
5039   If an axis rect side has multiple axes and automatic margin calculation is enabled for that side,
5040   only the offset of the inner most axis has meaning (even if it is set to be invisible). The
5041   offset of the other, outer axes is controlled automatically, to place them at appropriate
5042   positions.
5043 */
5044 void QCPAxis::setOffset(int offset)
5045 {
5046   mAxisPainter->offset = offset;
5047 }
5048
5049 /*!
5050   Sets the font that is used for tick labels when they are selected.
5051
5052   \see setTickLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5053 */
5054 void QCPAxis::setSelectedTickLabelFont(const QFont &font)
5055 {
5056   if (font != mSelectedTickLabelFont)
5057   {
5058     mSelectedTickLabelFont = font;
5059     // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
5060   }
5061 }
5062
5063 /*!
5064   Sets the font that is used for the axis label when it is selected.
5065
5066   \see setLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5067 */
5068 void QCPAxis::setSelectedLabelFont(const QFont &font)
5069 {
5070   mSelectedLabelFont = font;
5071   // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
5072 }
5073
5074 /*!
5075   Sets the color that is used for tick labels when they are selected.
5076
5077   \see setTickLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5078 */
5079 void QCPAxis::setSelectedTickLabelColor(const QColor &color)
5080 {
5081   if (color != mSelectedTickLabelColor)
5082   {
5083     mSelectedTickLabelColor = color;
5084   }
5085 }
5086
5087 /*!
5088   Sets the color that is used for the axis label when it is selected.
5089
5090   \see setLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5091 */
5092 void QCPAxis::setSelectedLabelColor(const QColor &color)
5093 {
5094   mSelectedLabelColor = color;
5095 }
5096
5097 /*!
5098   Sets the pen that is used to draw the axis base line when selected.
5099
5100   \see setBasePen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5101 */
5102 void QCPAxis::setSelectedBasePen(const QPen &pen)
5103 {
5104   mSelectedBasePen = pen;
5105 }
5106
5107 /*!
5108   Sets the pen that is used to draw the (major) ticks when selected.
5109
5110   \see setTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5111 */
5112 void QCPAxis::setSelectedTickPen(const QPen &pen)
5113 {
5114   mSelectedTickPen = pen;
5115 }
5116
5117 /*!
5118   Sets the pen that is used to draw the subticks when selected.
5119
5120   \see setSubTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions
5121 */
5122 void QCPAxis::setSelectedSubTickPen(const QPen &pen)
5123 {
5124   mSelectedSubTickPen = pen;
5125 }
5126
5127 /*!
5128   Sets the style for the lower axis ending. See the documentation of QCPLineEnding for available
5129   styles.
5130
5131   For horizontal axes, this method refers to the left ending, for vertical axes the bottom ending.
5132   Note that this meaning does not change when the axis range is reversed with \ref
5133   setRangeReversed.
5134
5135   \see setUpperEnding
5136 */
5137 void QCPAxis::setLowerEnding(const QCPLineEnding &ending)
5138 {
5139   mAxisPainter->lowerEnding = ending;
5140 }
5141
5142 /*!
5143   Sets the style for the upper axis ending. See the documentation of QCPLineEnding for available
5144   styles.
5145
5146   For horizontal axes, this method refers to the right ending, for vertical axes the top ending.
5147   Note that this meaning does not change when the axis range is reversed with \ref
5148   setRangeReversed.
5149
5150   \see setLowerEnding
5151 */
5152 void QCPAxis::setUpperEnding(const QCPLineEnding &ending)
5153 {
5154   mAxisPainter->upperEnding = ending;
5155 }
5156
5157 /*!
5158   If the scale type (\ref setScaleType) is \ref stLinear, \a diff is added to the lower and upper
5159   bounds of the range. The range is simply moved by \a diff.
5160
5161   If the scale type is \ref stLogarithmic, the range bounds are multiplied by \a diff. This
5162   corresponds to an apparent "linear" move in logarithmic scaling by a distance of log(diff).
5163 */
5164 void QCPAxis::moveRange(double diff)
5165 {
5166   QCPRange oldRange = mRange;
5167   if (mScaleType == stLinear)
5168   {
5169     mRange.lower += diff;
5170     mRange.upper += diff;
5171   } else // mScaleType == stLogarithmic
5172   {
5173     mRange.lower *= diff;
5174     mRange.upper *= diff;
5175   }
5176   mCachedMarginValid = false;
5177   emit rangeChanged(mRange);
5178   emit rangeChanged(mRange, oldRange);
5179 }
5180
5181 /*!
5182   Scales the range of this axis by \a factor around the coordinate \a center. For example, if \a
5183   factor is 2.0, \a center is 1.0, then the axis range will double its size, and the point at
5184   coordinate 1.0 won't have changed its position in the QCustomPlot widget (i.e. coordinates
5185   around 1.0 will have moved symmetrically closer to 1.0).
5186 */
5187 void QCPAxis::scaleRange(double factor, double center)
5188 {
5189   QCPRange oldRange = mRange;
5190   if (mScaleType == stLinear)
5191   {
5192     QCPRange newRange;
5193     newRange.lower = (mRange.lower-center)*factor + center;
5194     newRange.upper = (mRange.upper-center)*factor + center;
5195     if (QCPRange::validRange(newRange))
5196       mRange = newRange.sanitizedForLinScale();
5197   } else // mScaleType == stLogarithmic
5198   {
5199     if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range
5200     {
5201       QCPRange newRange;
5202       newRange.lower = qPow(mRange.lower/center, factor)*center;
5203       newRange.upper = qPow(mRange.upper/center, factor)*center;
5204       if (QCPRange::validRange(newRange))
5205         mRange = newRange.sanitizedForLogScale();
5206     } else
5207       qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
5208   }
5209   mCachedMarginValid = false;
5210   emit rangeChanged(mRange);
5211   emit rangeChanged(mRange, oldRange);
5212 }
5213
5214 /*!
5215   Scales the range of this axis to have a certain scale \a ratio to \a otherAxis. The scaling will
5216   be done around the center of the current axis range.
5217
5218   For example, if \a ratio is 1, this axis is the \a yAxis and \a otherAxis is \a xAxis, graphs
5219   plotted with those axes will appear in a 1:1 aspect ratio, independent of the aspect ratio the
5220   axis rect has.
5221
5222   This is an operation that changes the range of this axis once, it doesn't fix the scale ratio
5223   indefinitely. Note that calling this function in the constructor of the QCustomPlot's parent
5224   won't have the desired effect, since the widget dimensions aren't defined yet, and a resizeEvent
5225   will follow.
5226 */
5227 void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio)
5228 {
5229   int otherPixelSize, ownPixelSize;
5230
5231   if (otherAxis->orientation() == Qt::Horizontal)
5232     otherPixelSize = otherAxis->axisRect()->width();
5233   else
5234     otherPixelSize = otherAxis->axisRect()->height();
5235
5236   if (orientation() == Qt::Horizontal)
5237     ownPixelSize = axisRect()->width();
5238   else
5239     ownPixelSize = axisRect()->height();
5240
5241   double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/(double)otherPixelSize;
5242   setRange(range().center(), newRangeSize, Qt::AlignCenter);
5243 }
5244
5245 /*!
5246   Changes the axis range such that all plottables associated with this axis are fully visible in
5247   that dimension.
5248
5249   \see QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes
5250 */
5251 void QCPAxis::rescale(bool onlyVisiblePlottables)
5252 {
5253   QList<QCPAbstractPlottable*> p = plottables();
5254   QCPRange newRange;
5255   bool haveRange = false;
5256   for (int i=0; i<p.size(); ++i)
5257   {
5258     if (!p.at(i)->realVisibility() && onlyVisiblePlottables)
5259       continue;
5260     QCPRange plottableRange;
5261     bool currentFoundRange;
5262     QCPAbstractPlottable::SignDomain signDomain = QCPAbstractPlottable::sdBoth;
5263     if (mScaleType == stLogarithmic)
5264       signDomain = (mRange.upper < 0 ? QCPAbstractPlottable::sdNegative : QCPAbstractPlottable::sdPositive);
5265     if (p.at(i)->keyAxis() == this)
5266       plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain);
5267     else
5268       plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain);
5269     if (currentFoundRange)
5270     {
5271       if (!haveRange)
5272         newRange = plottableRange;
5273       else
5274         newRange.expand(plottableRange);
5275       haveRange = true;
5276     }
5277   }
5278   if (haveRange)
5279   {
5280     if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
5281     {
5282       double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
5283       if (mScaleType == stLinear)
5284       {
5285         newRange.lower = center-mRange.size()/2.0;
5286         newRange.upper = center+mRange.size()/2.0;
5287       } else // mScaleType == stLogarithmic
5288       {
5289         newRange.lower = center/qSqrt(mRange.upper/mRange.lower);
5290         newRange.upper = center*qSqrt(mRange.upper/mRange.lower);
5291       }
5292     }
5293     setRange(newRange);
5294   }
5295 }
5296
5297 /*!
5298   Transforms \a value, in pixel coordinates of the QCustomPlot widget, to axis coordinates.
5299 */
5300 double QCPAxis::pixelToCoord(double value) const
5301 {
5302   if (orientation() == Qt::Horizontal)
5303   {
5304     if (mScaleType == stLinear)
5305     {
5306       if (!mRangeReversed)
5307         return (value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.lower;
5308       else
5309         return -(value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.upper;
5310     } else // mScaleType == stLogarithmic
5311     {
5312       if (!mRangeReversed)
5313         return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/(double)mAxisRect->width())*mRange.lower;
5314       else
5315         return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/(double)mAxisRect->width())*mRange.upper;
5316     }
5317   } else // orientation() == Qt::Vertical
5318   {
5319     if (mScaleType == stLinear)
5320     {
5321       if (!mRangeReversed)
5322         return (mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.lower;
5323       else
5324         return -(mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.upper;
5325     } else // mScaleType == stLogarithmic
5326     {
5327       if (!mRangeReversed)
5328         return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/(double)mAxisRect->height())*mRange.lower;
5329       else
5330         return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/(double)mAxisRect->height())*mRange.upper;
5331     }
5332   }
5333 }
5334
5335 /*!
5336   Transforms \a value, in coordinates of the axis, to pixel coordinates of the QCustomPlot widget.
5337 */
5338 double QCPAxis::coordToPixel(double value) const
5339 {
5340   if (orientation() == Qt::Horizontal)
5341   {
5342     if (mScaleType == stLinear)
5343     {
5344       if (!mRangeReversed)
5345         return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left();
5346       else
5347         return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left();
5348     } else // mScaleType == stLogarithmic
5349     {
5350       if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range
5351         return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200;
5352       else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range
5353         return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200;
5354       else
5355       {
5356         if (!mRangeReversed)
5357           return baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
5358         else
5359           return baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
5360       }
5361     }
5362   } else // orientation() == Qt::Vertical
5363   {
5364     if (mScaleType == stLinear)
5365     {
5366       if (!mRangeReversed)
5367         return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height();
5368       else
5369         return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height();
5370     } else // mScaleType == stLogarithmic
5371     {
5372       if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range
5373         return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200;
5374       else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range
5375         return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200;
5376       else
5377       {
5378         if (!mRangeReversed)
5379           return mAxisRect->bottom()-baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height();
5380         else
5381           return mAxisRect->bottom()-baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height();
5382       }
5383     }
5384   }
5385 }
5386
5387 /*!
5388   Returns the part of the axis that is hit by \a pos (in pixels). The return value of this function
5389   is independent of the user-selectable parts defined with \ref setSelectableParts. Further, this
5390   function does not change the current selection state of the axis.
5391
5392   If the axis is not visible (\ref setVisible), this function always returns \ref spNone.
5393
5394   \see setSelectedParts, setSelectableParts, QCustomPlot::setInteractions
5395 */
5396 QCPAxis::SelectablePart QCPAxis::getPartAt(const QPointF &pos) const
5397 {
5398   if (!mVisible)
5399     return spNone;
5400
5401   if (mAxisPainter->axisSelectionBox().contains(pos.toPoint()))
5402     return spAxis;
5403   else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint()))
5404     return spTickLabels;
5405   else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint()))
5406     return spAxisLabel;
5407   else
5408     return spNone;
5409 }
5410
5411 /* inherits documentation from base class */
5412 double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
5413 {
5414   if (!mParentPlot) return -1;
5415   SelectablePart part = getPartAt(pos);
5416   if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone)
5417     return -1;
5418
5419   if (details)
5420     details->setValue(part);
5421   return mParentPlot->selectionTolerance()*0.99;
5422 }
5423
5424 /*!
5425   Returns a list of all the plottables that have this axis as key or value axis.
5426
5427   If you are only interested in plottables of type QCPGraph, see \ref graphs.
5428
5429   \see graphs, items
5430 */
5431 QList<QCPAbstractPlottable*> QCPAxis::plottables() const
5432 {
5433   QList<QCPAbstractPlottable*> result;
5434   if (!mParentPlot) return result;
5435
5436   for (int i=0; i<mParentPlot->mPlottables.size(); ++i)
5437   {
5438     if (mParentPlot->mPlottables.at(i)->keyAxis() == this ||mParentPlot->mPlottables.at(i)->valueAxis() == this)
5439       result.append(mParentPlot->mPlottables.at(i));
5440   }
5441   return result;
5442 }
5443
5444 /*!
5445   Returns a list of all the graphs that have this axis as key or value axis.
5446
5447   \see plottables, items
5448 */
5449 QList<QCPGraph*> QCPAxis::graphs() const
5450 {
5451   QList<QCPGraph*> result;
5452   if (!mParentPlot) return result;
5453
5454   for (int i=0; i<mParentPlot->mGraphs.size(); ++i)
5455   {
5456     if (mParentPlot->mGraphs.at(i)->keyAxis() == this || mParentPlot->mGraphs.at(i)->valueAxis() == this)
5457       result.append(mParentPlot->mGraphs.at(i));
5458   }
5459   return result;
5460 }
5461
5462 /*!
5463   Returns a list of all the items that are associated with this axis. An item is considered
5464   associated with an axis if at least one of its positions uses the axis as key or value axis.
5465
5466   \see plottables, graphs
5467 */
5468 QList<QCPAbstractItem*> QCPAxis::items() const
5469 {
5470   QList<QCPAbstractItem*> result;
5471   if (!mParentPlot) return result;
5472
5473   for (int itemId=0; itemId<mParentPlot->mItems.size(); ++itemId)
5474   {
5475     QList<QCPItemPosition*> positions = mParentPlot->mItems.at(itemId)->positions();
5476     for (int posId=0; posId<positions.size(); ++posId)
5477     {
5478       if (positions.at(posId)->keyAxis() == this || positions.at(posId)->valueAxis() == this)
5479       {
5480         result.append(mParentPlot->mItems.at(itemId));
5481         break;
5482       }
5483     }
5484   }
5485   return result;
5486 }
5487
5488 /*!
5489   Transforms a margin side to the logically corresponding axis type. (QCP::msLeft to
5490   QCPAxis::atLeft, QCP::msRight to QCPAxis::atRight, etc.)
5491 */
5492 QCPAxis::AxisType QCPAxis::marginSideToAxisType(QCP::MarginSide side)
5493 {
5494   switch (side)
5495   {
5496     case QCP::msLeft: return atLeft;
5497     case QCP::msRight: return atRight;
5498     case QCP::msTop: return atTop;
5499     case QCP::msBottom: return atBottom;
5500     default: break;
5501   }
5502   qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << (int)side;
5503   return atLeft;
5504 }
5505
5506 /*!
5507   Returns the axis type that describes the opposite axis of an axis with the specified \a type.
5508 */
5509 QCPAxis::AxisType QCPAxis::opposite(QCPAxis::AxisType type)
5510 {
5511   switch (type)
5512   {
5513     case atLeft: return atRight; break;
5514     case atRight: return atLeft; break;
5515     case atBottom: return atTop; break;
5516     case atTop: return atBottom; break;
5517     default: qDebug() << Q_FUNC_INFO << "invalid axis type"; return atLeft; break;
5518   }
5519 }
5520
5521 /*! \internal
5522
5523   This function is called to prepare the tick vector, sub tick vector and tick label vector. If
5524   \ref setAutoTicks is set to true, appropriate tick values are determined automatically via \ref
5525   generateAutoTicks. If it's set to false, the signal ticksRequest is emitted, which can be used to
5526   provide external tick positions. Then the sub tick vectors and tick label vectors are created.
5527 */
5528 void QCPAxis::setupTickVectors()
5529 {
5530   if (!mParentPlot) return;
5531   if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return;
5532
5533   // fill tick vectors, either by auto generating or by notifying user to fill the vectors himself
5534   if (mAutoTicks)
5535   {
5536     generateAutoTicks();
5537   } else
5538   {
5539     emit ticksRequest();
5540   }
5541
5542   visibleTickBounds(mLowestVisibleTick, mHighestVisibleTick);
5543   if (mTickVector.isEmpty())
5544   {
5545     mSubTickVector.clear();
5546     return;
5547   }
5548
5549   // generate subticks between ticks:
5550   mSubTickVector.resize((mTickVector.size()-1)*mSubTickCount);
5551   if (mSubTickCount > 0)
5552   {
5553     double subTickStep = 0;
5554     double subTickPosition = 0;
5555     int subTickIndex = 0;
5556     bool done = false;
5557     int lowTick = mLowestVisibleTick > 0 ? mLowestVisibleTick-1 : mLowestVisibleTick;
5558     int highTick = mHighestVisibleTick < mTickVector.size()-1 ? mHighestVisibleTick+1 : mHighestVisibleTick;
5559     for (int i=lowTick+1; i<=highTick; ++i)
5560     {
5561       subTickStep = (mTickVector.at(i)-mTickVector.at(i-1))/(double)(mSubTickCount+1);
5562       for (int k=1; k<=mSubTickCount; ++k)
5563       {
5564         subTickPosition = mTickVector.at(i-1) + k*subTickStep;
5565         if (subTickPosition < mRange.lower)
5566           continue;
5567         if (subTickPosition > mRange.upper)
5568         {
5569           done = true;
5570           break;
5571         }
5572         mSubTickVector[subTickIndex] = subTickPosition;
5573         subTickIndex++;
5574       }
5575       if (done) break;
5576     }
5577     mSubTickVector.resize(subTickIndex);
5578   }
5579
5580   // generate tick labels according to tick positions:
5581   if (mAutoTickLabels)
5582   {
5583     int vecsize = mTickVector.size();
5584     mTickVectorLabels.resize(vecsize);
5585     if (mTickLabelType == ltNumber)
5586     {
5587       for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i)
5588         mTickVectorLabels[i] = mParentPlot->locale().toString(mTickVector.at(i), mNumberFormatChar.toLatin1(), mNumberPrecision);
5589     } else if (mTickLabelType == ltDateTime)
5590     {
5591       for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i)
5592       {
5593 #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) // use fromMSecsSinceEpoch function if available, to gain sub-second accuracy on tick labels (e.g. for format "hh:mm:ss:zzz")
5594         mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromTime_t(mTickVector.at(i)).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
5595 #else
5596         mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromMSecsSinceEpoch(mTickVector.at(i)*1000).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
5597 #endif
5598       }
5599     }
5600   } else // mAutoTickLabels == false
5601   {
5602     if (mAutoTicks) // ticks generated automatically, but not ticklabels, so emit ticksRequest here for labels
5603     {
5604       emit ticksRequest();
5605     }
5606     // make sure provided tick label vector has correct (minimal) length:
5607     if (mTickVectorLabels.size() < mTickVector.size())
5608       mTickVectorLabels.resize(mTickVector.size());
5609   }
5610 }
5611
5612 /*! \internal
5613
5614   If \ref setAutoTicks is set to true, this function is called by \ref setupTickVectors to
5615   generate reasonable tick positions (and subtick count). The algorithm tries to create
5616   approximately <tt>mAutoTickCount</tt> ticks (set via \ref setAutoTickCount).
5617
5618   If the scale is logarithmic, \ref setAutoTickCount is ignored, and one tick is generated at every
5619   power of the current logarithm base, set via \ref setScaleLogBase.
5620 */
5621 void QCPAxis::generateAutoTicks()
5622 {
5623   if (mScaleType == stLinear)
5624   {
5625     if (mAutoTickStep)
5626     {
5627       // Generate tick positions according to linear scaling:
5628       mTickStep = mRange.size()/(double)(mAutoTickCount+1e-10); // mAutoTickCount ticks on average, the small addition is to prevent jitter on exact integers
5629       double magnitudeFactor = qPow(10.0, qFloor(qLn(mTickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc.
5630       double tickStepMantissa = mTickStep/magnitudeFactor;
5631       if (tickStepMantissa < 5)
5632       {
5633         // round digit after decimal point to 0.5
5634         mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor;
5635       } else
5636       {
5637         // round to first digit in multiples of 2
5638         mTickStep = (int)(tickStepMantissa/2.0)*2.0*magnitudeFactor;
5639       }
5640     }
5641     if (mAutoSubTicks)
5642       mSubTickCount = calculateAutoSubTickCount(mTickStep);
5643     // Generate tick positions according to mTickStep:
5644     qint64 firstStep = floor(mRange.lower/mTickStep); // do not use qFloor here, or we'll lose 64 bit precision
5645     qint64 lastStep = ceil(mRange.upper/mTickStep); // do not use qCeil here, or we'll lose 64 bit precision
5646     int tickcount = lastStep-firstStep+1;
5647     if (tickcount < 0) tickcount = 0;
5648     mTickVector.resize(tickcount);
5649     for (int i=0; i<tickcount; ++i)
5650       mTickVector[i] = (firstStep+i)*mTickStep;
5651   } else // mScaleType == stLogarithmic
5652   {
5653     // Generate tick positions according to logbase scaling:
5654     if (mRange.lower > 0 && mRange.upper > 0) // positive range
5655     {
5656       double lowerMag = basePow(qFloor(baseLog(mRange.lower)));
5657       double currentMag = lowerMag;
5658       mTickVector.clear();
5659       mTickVector.append(currentMag);
5660       while (currentMag < mRange.upper && currentMag > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
5661       {
5662         currentMag *= mScaleLogBase;
5663         mTickVector.append(currentMag);
5664       }
5665     } else if (mRange.lower < 0 && mRange.upper < 0) // negative range
5666     {
5667       double lowerMag = -basePow(qCeil(baseLog(-mRange.lower)));
5668       double currentMag = lowerMag;
5669       mTickVector.clear();
5670       mTickVector.append(currentMag);
5671       while (currentMag < mRange.upper && currentMag < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
5672       {
5673         currentMag /= mScaleLogBase;
5674         mTickVector.append(currentMag);
5675       }
5676     } else // invalid range for logarithmic scale, because lower and upper have different sign
5677     {
5678       mTickVector.clear();
5679       qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << mRange.lower << "-" << mRange.upper;
5680     }
5681   }
5682 }
5683
5684 /*! \internal
5685
5686   Called by generateAutoTicks when \ref setAutoSubTicks is set to true. Depending on the \a
5687   tickStep between two major ticks on the axis, a different number of sub ticks is appropriate. For
5688   Example taking 4 sub ticks for a \a tickStep of 1 makes more sense than taking 5 sub ticks,
5689   because this corresponds to a sub tick step of 0.2, instead of the less intuitive 0.16667. Note
5690   that a subtick count of 4 means dividing the major tick step into 5 sections.
5691
5692   This is implemented by a hand made lookup for integer tick steps as well as fractional tick steps
5693   with a fractional part of (approximately) 0.5. If a tick step is different (i.e. has no
5694   fractional part close to 0.5), the currently set sub tick count (\ref setSubTickCount) is
5695   returned.
5696 */
5697 int QCPAxis::calculateAutoSubTickCount(double tickStep) const
5698 {
5699   int result = mSubTickCount; // default to current setting, if no proper value can be found
5700
5701   // get mantissa of tickstep:
5702   double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc.
5703   double tickStepMantissa = tickStep/magnitudeFactor;
5704
5705   // separate integer and fractional part of mantissa:
5706   double epsilon = 0.01;
5707   double intPartf;
5708   int intPart;
5709   double fracPart = modf(tickStepMantissa, &intPartf);
5710   intPart = intPartf;
5711
5712   // handle cases with (almost) integer mantissa:
5713   if (fracPart < epsilon || 1.0-fracPart < epsilon)
5714   {
5715     if (1.0-fracPart < epsilon)
5716       ++intPart;
5717     switch (intPart)
5718     {
5719       case 1: result = 4; break; // 1.0 -> 0.2 substep
5720       case 2: result = 3; break; // 2.0 -> 0.5 substep
5721       case 3: result = 2; break; // 3.0 -> 1.0 substep
5722       case 4: result = 3; break; // 4.0 -> 1.0 substep
5723       case 5: result = 4; break; // 5.0 -> 1.0 substep
5724       case 6: result = 2; break; // 6.0 -> 2.0 substep
5725       case 7: result = 6; break; // 7.0 -> 1.0 substep
5726       case 8: result = 3; break; // 8.0 -> 2.0 substep
5727       case 9: result = 2; break; // 9.0 -> 3.0 substep
5728     }
5729   } else
5730   {
5731     // handle cases with significantly fractional mantissa:
5732     if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa
5733     {
5734       switch (intPart)
5735       {
5736         case 1: result = 2; break; // 1.5 -> 0.5 substep
5737         case 2: result = 4; break; // 2.5 -> 0.5 substep
5738         case 3: result = 4; break; // 3.5 -> 0.7 substep
5739         case 4: result = 2; break; // 4.5 -> 1.5 substep
5740         case 5: result = 4; break; // 5.5 -> 1.1 substep (won't occur with autoTickStep from here on)
5741         case 6: result = 4; break; // 6.5 -> 1.3 substep
5742         case 7: result = 2; break; // 7.5 -> 2.5 substep
5743         case 8: result = 4; break; // 8.5 -> 1.7 substep
5744         case 9: result = 4; break; // 9.5 -> 1.9 substep
5745       }
5746     }
5747     // if mantissa fraction isn't 0.0 or 0.5, don't bother finding good sub tick marks, leave default
5748   }
5749
5750   return result;
5751 }
5752
5753 /* inherits documentation from base class */
5754 void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
5755 {
5756   Q_UNUSED(event)
5757   SelectablePart part = details.value<SelectablePart>();
5758   if (mSelectableParts.testFlag(part))
5759   {
5760     SelectableParts selBefore = mSelectedParts;
5761     setSelectedParts(additive ? mSelectedParts^part : part);
5762     if (selectionStateChanged)
5763       *selectionStateChanged = mSelectedParts != selBefore;
5764   }
5765 }
5766
5767 /* inherits documentation from base class */
5768 void QCPAxis::deselectEvent(bool *selectionStateChanged)
5769 {
5770   SelectableParts selBefore = mSelectedParts;
5771   setSelectedParts(mSelectedParts & ~mSelectableParts);
5772   if (selectionStateChanged)
5773     *selectionStateChanged = mSelectedParts != selBefore;
5774 }
5775
5776 /*! \internal
5777
5778   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
5779   before drawing axis lines.
5780
5781   This is the antialiasing state the painter passed to the \ref draw method is in by default.
5782
5783   This function takes into account the local setting of the antialiasing flag as well as the
5784   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
5785   QCustomPlot::setNotAntialiasedElements.
5786
5787   \see setAntialiased
5788 */
5789 void QCPAxis::applyDefaultAntialiasingHint(QCPPainter *painter) const
5790 {
5791   applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes);
5792 }
5793
5794 /*! \internal
5795
5796   Draws the axis with the specified \a painter, using the internal QCPAxisPainterPrivate instance.
5797
5798 */
5799 void QCPAxis::draw(QCPPainter *painter)
5800 {
5801   const int lowTick = mLowestVisibleTick;
5802   const int highTick = mHighestVisibleTick;
5803   QVector<double> subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
5804   QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
5805   QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
5806   tickPositions.reserve(highTick-lowTick+1);
5807   tickLabels.reserve(highTick-lowTick+1);
5808   subTickPositions.reserve(mSubTickVector.size());
5809
5810   if (mTicks)
5811   {
5812     for (int i=lowTick; i<=highTick; ++i)
5813     {
5814       tickPositions.append(coordToPixel(mTickVector.at(i)));
5815       if (mTickLabels)
5816         tickLabels.append(mTickVectorLabels.at(i));
5817     }
5818
5819     if (mSubTickCount > 0)
5820     {
5821       const int subTickCount = mSubTickVector.size();
5822       for (int i=0; i<subTickCount; ++i) // no need to check bounds because subticks are always only created inside current mRange
5823         subTickPositions.append(coordToPixel(mSubTickVector.at(i)));
5824     }
5825   }
5826   // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to draw the axis.
5827   // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
5828   mAxisPainter->type = mAxisType;
5829   mAxisPainter->basePen = getBasePen();
5830   mAxisPainter->labelFont = getLabelFont();
5831   mAxisPainter->labelColor = getLabelColor();
5832   mAxisPainter->label = mLabel;
5833   mAxisPainter->substituteExponent = mAutoTickLabels && mNumberBeautifulPowers && mTickLabelType == ltNumber;
5834   mAxisPainter->tickPen = getTickPen();
5835   mAxisPainter->subTickPen = getSubTickPen();
5836   mAxisPainter->tickLabelFont = getTickLabelFont();
5837   mAxisPainter->tickLabelColor = getTickLabelColor();
5838   mAxisPainter->axisRect = mAxisRect->rect();
5839   mAxisPainter->viewportRect = mParentPlot->viewport();
5840   mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic;
5841   mAxisPainter->reversedEndings = mRangeReversed;
5842   mAxisPainter->tickPositions = tickPositions;
5843   mAxisPainter->tickLabels = tickLabels;
5844   mAxisPainter->subTickPositions = subTickPositions;
5845   mAxisPainter->draw(painter);
5846 }
5847
5848 /*! \internal
5849
5850   Returns via \a lowIndex and \a highIndex, which ticks in the current tick vector are visible in
5851   the current range. The return values are indices of the tick vector, not the positions of the
5852   ticks themselves.
5853
5854   The actual use of this function is when an external tick vector is provided, since it might
5855   exceed far beyond the currently displayed range, and would cause unnecessary calculations e.g. of
5856   subticks.
5857
5858   If all ticks are outside the axis range, an inverted range is returned, i.e. highIndex will be
5859   smaller than lowIndex. There is one case, where this function returns indices that are not really
5860   visible in the current axis range: When the tick spacing is larger than the axis range size and
5861   one tick is below the axis range and the next tick is already above the axis range. Because in
5862   such cases it is usually desirable to know the tick pair, to draw proper subticks.
5863 */
5864 void QCPAxis::visibleTickBounds(int &lowIndex, int &highIndex) const
5865 {
5866   bool lowFound = false;
5867   bool highFound = false;
5868   lowIndex = 0;
5869   highIndex = -1;
5870
5871   for (int i=0; i < mTickVector.size(); ++i)
5872   {
5873     if (mTickVector.at(i) >= mRange.lower)
5874     {
5875       lowFound = true;
5876       lowIndex = i;
5877       break;
5878     }
5879   }
5880   for (int i=mTickVector.size()-1; i >= 0; --i)
5881   {
5882     if (mTickVector.at(i) <= mRange.upper)
5883     {
5884       highFound = true;
5885       highIndex = i;
5886       break;
5887     }
5888   }
5889
5890   if (!lowFound && highFound)
5891     lowIndex = highIndex+1;
5892   else if (lowFound && !highFound)
5893     highIndex = lowIndex-1;
5894 }
5895
5896 /*! \internal
5897
5898   A log function with the base mScaleLogBase, used mostly for coordinate transforms in logarithmic
5899   scales with arbitrary log base. Uses the buffered mScaleLogBaseLogInv for faster calculation.
5900   This is set to <tt>1.0/qLn(mScaleLogBase)</tt> in \ref setScaleLogBase.
5901
5902   \see basePow, setScaleLogBase, setScaleType
5903 */
5904 double QCPAxis::baseLog(double value) const
5905 {
5906   return qLn(value)*mScaleLogBaseLogInv;
5907 }
5908
5909 /*! \internal
5910
5911   A power function with the base mScaleLogBase, used mostly for coordinate transforms in
5912   logarithmic scales with arbitrary log base.
5913
5914   \see baseLog, setScaleLogBase, setScaleType
5915 */
5916 double QCPAxis::basePow(double value) const
5917 {
5918   return qPow(mScaleLogBase, value);
5919 }
5920
5921 /*! \internal
5922
5923   Returns the pen that is used to draw the axis base line. Depending on the selection state, this
5924   is either mSelectedBasePen or mBasePen.
5925 */
5926 QPen QCPAxis::getBasePen() const
5927 {
5928   return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen;
5929 }
5930
5931 /*! \internal
5932
5933   Returns the pen that is used to draw the (major) ticks. Depending on the selection state, this
5934   is either mSelectedTickPen or mTickPen.
5935 */
5936 QPen QCPAxis::getTickPen() const
5937 {
5938   return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen;
5939 }
5940
5941 /*! \internal
5942
5943   Returns the pen that is used to draw the subticks. Depending on the selection state, this
5944   is either mSelectedSubTickPen or mSubTickPen.
5945 */
5946 QPen QCPAxis::getSubTickPen() const
5947 {
5948   return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen;
5949 }
5950
5951 /*! \internal
5952
5953   Returns the font that is used to draw the tick labels. Depending on the selection state, this
5954   is either mSelectedTickLabelFont or mTickLabelFont.
5955 */
5956 QFont QCPAxis::getTickLabelFont() const
5957 {
5958   return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont;
5959 }
5960
5961 /*! \internal
5962
5963   Returns the font that is used to draw the axis label. Depending on the selection state, this
5964   is either mSelectedLabelFont or mLabelFont.
5965 */
5966 QFont QCPAxis::getLabelFont() const
5967 {
5968   return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont;
5969 }
5970
5971 /*! \internal
5972
5973   Returns the color that is used to draw the tick labels. Depending on the selection state, this
5974   is either mSelectedTickLabelColor or mTickLabelColor.
5975 */
5976 QColor QCPAxis::getTickLabelColor() const
5977 {
5978   return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor;
5979 }
5980
5981 /*! \internal
5982
5983   Returns the color that is used to draw the axis label. Depending on the selection state, this
5984   is either mSelectedLabelColor or mLabelColor.
5985 */
5986 QColor QCPAxis::getLabelColor() const
5987 {
5988   return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor;
5989 }
5990
5991 /*! \internal
5992
5993   Returns the appropriate outward margin for this axis. It is needed if \ref
5994   QCPAxisRect::setAutoMargins is set to true on the parent axis rect. An axis with axis type \ref
5995   atLeft will return an appropriate left margin, \ref atBottom will return an appropriate bottom
5996   margin and so forth. For the calculation, this function goes through similar steps as \ref draw,
5997   so changing one function likely requires the modification of the other one as well.
5998
5999   The margin consists of the outward tick length, tick label padding, tick label size, label
6000   padding, label size, and padding.
6001
6002   The margin is cached internally, so repeated calls while leaving the axis range, fonts, etc.
6003   unchanged are very fast.
6004 */
6005 int QCPAxis::calculateMargin()
6006 {
6007   if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis
6008     return 0;
6009
6010   if (mCachedMarginValid)
6011     return mCachedMargin;
6012
6013   // run through similar steps as QCPAxis::draw, and calculate margin needed to fit axis and its labels
6014   int margin = 0;
6015
6016   int lowTick, highTick;
6017   visibleTickBounds(lowTick, highTick);
6018   QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
6019   QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
6020   tickPositions.reserve(highTick-lowTick+1);
6021   tickLabels.reserve(highTick-lowTick+1);
6022   if (mTicks)
6023   {
6024     for (int i=lowTick; i<=highTick; ++i)
6025     {
6026       tickPositions.append(coordToPixel(mTickVector.at(i)));
6027       if (mTickLabels)
6028         tickLabels.append(mTickVectorLabels.at(i));
6029     }
6030   }
6031   // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size.
6032   // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
6033   mAxisPainter->type = mAxisType;
6034   mAxisPainter->labelFont = getLabelFont();
6035   mAxisPainter->label = mLabel;
6036   mAxisPainter->tickLabelFont = mTickLabelFont;
6037   mAxisPainter->axisRect = mAxisRect->rect();
6038   mAxisPainter->viewportRect = mParentPlot->viewport();
6039   mAxisPainter->tickPositions = tickPositions;
6040   mAxisPainter->tickLabels = tickLabels;
6041   margin += mAxisPainter->size();
6042   margin += mPadding;
6043
6044   mCachedMargin = margin;
6045   mCachedMarginValid = true;
6046   return margin;
6047 }
6048
6049 /* inherits documentation from base class */
6050 QCP::Interaction QCPAxis::selectionCategory() const
6051 {
6052   return QCP::iSelectAxes;
6053 }
6054
6055
6056 ////////////////////////////////////////////////////////////////////////////////////////////////////
6057 //////////////////// QCPAxisPainterPrivate
6058 ////////////////////////////////////////////////////////////////////////////////////////////////////
6059
6060 /*! \class QCPAxisPainterPrivate
6061
6062   \internal
6063   \brief (Private)
6064
6065   This is a private class and not part of the public QCustomPlot interface.
6066
6067   It is used by QCPAxis to do the low-level drawing of axis backbone, tick marks, tick labels and
6068   axis label. It also buffers the labels to reduce replot times. The parameters are configured by
6069   directly accessing the public member variables.
6070 */
6071
6072 /*!
6073   Constructs a QCPAxisPainterPrivate instance. Make sure to not create a new instance on every
6074   redraw, to utilize the caching mechanisms.
6075 */
6076 QCPAxisPainterPrivate::QCPAxisPainterPrivate(QCustomPlot *parentPlot) :
6077   type(QCPAxis::atLeft),
6078   basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6079   lowerEnding(QCPLineEnding::esNone),
6080   upperEnding(QCPLineEnding::esNone),
6081   labelPadding(0),
6082   tickLabelPadding(0),
6083   tickLabelRotation(0),
6084   tickLabelSide(QCPAxis::lsOutside),
6085   substituteExponent(true),
6086   numberMultiplyCross(false),
6087   tickLengthIn(5),
6088   tickLengthOut(0),
6089   subTickLengthIn(2),
6090   subTickLengthOut(0),
6091   tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6092   subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6093   offset(0),
6094   abbreviateDecimalPowers(false),
6095   reversedEndings(false),
6096   mParentPlot(parentPlot),
6097   mLabelCache(16) // cache at most 16 (tick) labels
6098 {
6099 }
6100
6101 QCPAxisPainterPrivate::~QCPAxisPainterPrivate()
6102 {
6103 }
6104
6105 /*! \internal
6106
6107   Draws the axis with the specified \a painter.
6108
6109   The selection boxes (mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox) are set
6110   here, too.
6111 */
6112 void QCPAxisPainterPrivate::draw(QCPPainter *painter)
6113 {
6114   QByteArray newHash = generateLabelParameterHash();
6115   if (newHash != mLabelParameterHash)
6116   {
6117     mLabelCache.clear();
6118     mLabelParameterHash = newHash;
6119   }
6120
6121   QPoint origin;
6122   switch (type)
6123   {
6124     case QCPAxis::atLeft:   origin = axisRect.bottomLeft() +QPoint(-offset, 0); break;
6125     case QCPAxis::atRight:  origin = axisRect.bottomRight()+QPoint(+offset, 0); break;
6126     case QCPAxis::atTop:    origin = axisRect.topLeft()    +QPoint(0, -offset); break;
6127     case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break;
6128   }
6129
6130   double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes)
6131   switch (type)
6132   {
6133     case QCPAxis::atTop: yCor = -1; break;
6134     case QCPAxis::atRight: xCor = 1; break;
6135     default: break;
6136   }
6137
6138   int margin = 0;
6139   // draw baseline:
6140   QLineF baseLine;
6141   painter->setPen(basePen);
6142   if (QCPAxis::orientation(type) == Qt::Horizontal)
6143     baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor));
6144   else
6145     baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor));
6146   if (reversedEndings)
6147     baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later
6148   painter->drawLine(baseLine);
6149
6150   // draw ticks:
6151   if (!tickPositions.isEmpty())
6152   {
6153     painter->setPen(tickPen);
6154     int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis)
6155     if (QCPAxis::orientation(type) == Qt::Horizontal)
6156     {
6157       for (int i=0; i<tickPositions.size(); ++i)
6158         painter->drawLine(QLineF(tickPositions.at(i)+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPositions.at(i)+xCor, origin.y()+tickLengthIn*tickDir+yCor));
6159     } else
6160     {
6161       for (int i=0; i<tickPositions.size(); ++i)
6162         painter->drawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPositions.at(i)+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPositions.at(i)+yCor));
6163     }
6164   }
6165
6166   // draw subticks:
6167   if (!subTickPositions.isEmpty())
6168   {
6169     painter->setPen(subTickPen);
6170     // direction of ticks ("inward" is right for left axis and left for right axis)
6171     int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1;
6172     if (QCPAxis::orientation(type) == Qt::Horizontal)
6173     {
6174       for (int i=0; i<subTickPositions.size(); ++i)
6175         painter->drawLine(QLineF(subTickPositions.at(i)+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPositions.at(i)+xCor, origin.y()+subTickLengthIn*tickDir+yCor));
6176     } else
6177     {
6178       for (int i=0; i<subTickPositions.size(); ++i)
6179         painter->drawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPositions.at(i)+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPositions.at(i)+yCor));
6180     }
6181   }
6182   margin += qMax(0, qMax(tickLengthOut, subTickLengthOut));
6183
6184   // draw axis base endings:
6185   bool antialiasingBackup = painter->antialiasing();
6186   painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't
6187   painter->setBrush(QBrush(basePen.color()));
6188   QVector2D baseLineVector(baseLine.dx(), baseLine.dy());
6189   if (lowerEnding.style() != QCPLineEnding::esNone)
6190     lowerEnding.draw(painter, QVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector);
6191   if (upperEnding.style() != QCPLineEnding::esNone)
6192     upperEnding.draw(painter, QVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector);
6193   painter->setAntialiasing(antialiasingBackup);
6194
6195   // tick labels:
6196   QRect oldClipRect;
6197   if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect
6198   {
6199     oldClipRect = painter->clipRegion().boundingRect();
6200     painter->setClipRect(axisRect);
6201   }
6202   QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label
6203   if (!tickLabels.isEmpty())
6204   {
6205     if (tickLabelSide == QCPAxis::lsOutside)
6206       margin += tickLabelPadding;
6207     painter->setFont(tickLabelFont);
6208     painter->setPen(QPen(tickLabelColor));
6209     const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size());
6210     int distanceToAxis = margin;
6211     if (tickLabelSide == QCPAxis::lsInside)
6212       distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
6213     for (int i=0; i<maxLabelIndex; ++i)
6214       placeTickLabel(painter, tickPositions.at(i), distanceToAxis, tickLabels.at(i), &tickLabelsSize);
6215     if (tickLabelSide == QCPAxis::lsOutside)
6216       margin += (QCPAxis::orientation(type) == Qt::Horizontal) ? tickLabelsSize.height() : tickLabelsSize.width();
6217   }
6218   if (tickLabelSide == QCPAxis::lsInside)
6219     painter->setClipRect(oldClipRect);
6220
6221   // axis label:
6222   QRect labelBounds;
6223   if (!label.isEmpty())
6224   {
6225     margin += labelPadding;
6226     painter->setFont(labelFont);
6227     painter->setPen(QPen(labelColor));
6228     labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label);
6229     if (type == QCPAxis::atLeft)
6230     {
6231       QTransform oldTransform = painter->transform();
6232       painter->translate((origin.x()-margin-labelBounds.height()), origin.y());
6233       painter->rotate(-90);
6234       painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6235       painter->setTransform(oldTransform);
6236     }
6237     else if (type == QCPAxis::atRight)
6238     {
6239       QTransform oldTransform = painter->transform();
6240       painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height());
6241       painter->rotate(90);
6242       painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6243       painter->setTransform(oldTransform);
6244     }
6245     else if (type == QCPAxis::atTop)
6246       painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6247     else if (type == QCPAxis::atBottom)
6248       painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6249   }
6250
6251   // set selection boxes:
6252   int selectionTolerance = 0;
6253   if (mParentPlot)
6254     selectionTolerance = mParentPlot->selectionTolerance();
6255   else
6256     qDebug() << Q_FUNC_INFO << "mParentPlot is null";
6257   int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance);
6258   int selAxisInSize = selectionTolerance;
6259   int selTickLabelSize;
6260   int selTickLabelOffset;
6261   if (tickLabelSide == QCPAxis::lsOutside)
6262   {
6263     selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6264     selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding;
6265   } else
6266   {
6267     selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6268     selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
6269   }
6270   int selLabelSize = labelBounds.height();
6271   int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding;
6272   if (type == QCPAxis::atLeft)
6273   {
6274     mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom());
6275     mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom());
6276     mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom());
6277   } else if (type == QCPAxis::atRight)
6278   {
6279     mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom());
6280     mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom());
6281     mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom());
6282   } else if (type == QCPAxis::atTop)
6283   {
6284     mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize);
6285     mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset);
6286     mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset);
6287   } else if (type == QCPAxis::atBottom)
6288   {
6289     mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize);
6290     mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset);
6291     mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset);
6292   }
6293   mAxisSelectionBox = mAxisSelectionBox.normalized();
6294   mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized();
6295   mLabelSelectionBox = mLabelSelectionBox.normalized();
6296   // draw hitboxes for debug purposes:
6297   //painter->setBrush(Qt::NoBrush);
6298   //painter->drawRects(QVector<QRect>() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox);
6299 }
6300
6301 /*! \internal
6302
6303   Returns the size ("margin" in QCPAxisRect context, so measured perpendicular to the axis backbone
6304   direction) needed to fit the axis.
6305 */
6306 int QCPAxisPainterPrivate::size() const
6307 {
6308   int result = 0;
6309
6310   // get length of tick marks pointing outwards:
6311   if (!tickPositions.isEmpty())
6312     result += qMax(0, qMax(tickLengthOut, subTickLengthOut));
6313
6314   // calculate size of tick labels:
6315   if (tickLabelSide == QCPAxis::lsOutside)
6316   {
6317     QSize tickLabelsSize(0, 0);
6318     if (!tickLabels.isEmpty())
6319     {
6320       for (int i=0; i<tickLabels.size(); ++i)
6321         getMaxTickLabelSize(tickLabelFont, tickLabels.at(i), &tickLabelsSize);
6322       result += QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width();
6323     result += tickLabelPadding;
6324     }
6325   }
6326
6327   // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees):
6328   if (!label.isEmpty())
6329   {
6330     QFontMetrics fontMetrics(labelFont);
6331     QRect bounds;
6332     bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label);
6333     result += bounds.height() + labelPadding;
6334   }
6335
6336   return result;
6337 }
6338
6339 /*! \internal
6340
6341   Clears the internal label cache. Upon the next \ref draw, all labels will be created new. This
6342   method is called automatically in \ref draw, if any parameters have changed that invalidate the
6343   cached labels, such as font, color, etc.
6344 */
6345 void QCPAxisPainterPrivate::clearCache()
6346 {
6347   mLabelCache.clear();
6348 }
6349
6350 /*! \internal
6351
6352   Returns a hash that allows uniquely identifying whether the label parameters have changed such
6353   that the cached labels must be refreshed (\ref clearCache). It is used in \ref draw. If the
6354   return value of this method hasn't changed since the last redraw, the respective label parameters
6355   haven't changed and cached labels may be used.
6356 */
6357 QByteArray QCPAxisPainterPrivate::generateLabelParameterHash() const
6358 {
6359   QByteArray result;
6360   result.append(QByteArray::number(tickLabelRotation));
6361   result.append(QByteArray::number((int)tickLabelSide));
6362   result.append(QByteArray::number((int)substituteExponent));
6363   result.append(QByteArray::number((int)numberMultiplyCross));
6364   result.append(tickLabelColor.name().toLatin1()+QByteArray::number(tickLabelColor.alpha(), 16));
6365   result.append(tickLabelFont.toString().toLatin1());
6366   return result;
6367 }
6368
6369 /*! \internal
6370
6371   Draws a single tick label with the provided \a painter, utilizing the internal label cache to
6372   significantly speed up drawing of labels that were drawn in previous calls. The tick label is
6373   always bound to an axis, the distance to the axis is controllable via \a distanceToAxis in
6374   pixels. The pixel position in the axis direction is passed in the \a position parameter. Hence
6375   for the bottom axis, \a position would indicate the horizontal pixel position (not coordinate),
6376   at which the label should be drawn.
6377
6378   In order to later draw the axis label in a place that doesn't overlap with the tick labels, the
6379   largest tick label size is needed. This is acquired by passing a \a tickLabelsSize to the \ref
6380   drawTickLabel calls during the process of drawing all tick labels of one axis. In every call, \a
6381   tickLabelsSize is expanded, if the drawn label exceeds the value \a tickLabelsSize currently
6382   holds.
6383
6384   The label is drawn with the font and pen that are currently set on the \a painter. To draw
6385   superscripted powers, the font is temporarily made smaller by a fixed factor (see \ref
6386   getTickLabelData).
6387 */
6388 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize)
6389 {
6390   // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly!
6391   if (text.isEmpty()) return;
6392   QSize finalSize;
6393   QPointF labelAnchor;
6394   switch (type)
6395   {
6396     case QCPAxis::atLeft:   labelAnchor = QPointF(axisRect.left()-distanceToAxis-offset, position); break;
6397     case QCPAxis::atRight:  labelAnchor = QPointF(axisRect.right()+distanceToAxis+offset, position); break;
6398     case QCPAxis::atTop:    labelAnchor = QPointF(position, axisRect.top()-distanceToAxis-offset); break;
6399     case QCPAxis::atBottom: labelAnchor = QPointF(position, axisRect.bottom()+distanceToAxis+offset); break;
6400   }
6401   if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled
6402   {
6403     if (!mLabelCache.contains(text))  // no cached label exists, create it
6404     {
6405       CachedLabel *newCachedLabel = new CachedLabel;
6406       TickLabelData labelData = getTickLabelData(painter->font(), text);
6407       newCachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft();
6408 #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
6409       QSize clSize = labelData.rotatedTotalBounds.size();
6410       clSize *= painter->device()->devicePixelRatio();
6411       newCachedLabel->pixmap = QPixmap(clSize);
6412       newCachedLabel->pixmap.setDevicePixelRatio(painter->device()->devicePixelRatio());
6413 #else
6414       newCachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size());
6415 #endif
6416       newCachedLabel->pixmap.fill(Qt::transparent);
6417       QCPPainter cachePainter(&newCachedLabel->pixmap);
6418       cachePainter.setPen(painter->pen());
6419       drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData);
6420       mLabelCache.insert(text, newCachedLabel, 1);
6421     }
6422     // draw cached label:
6423     const CachedLabel *cachedLabel = mLabelCache.object(text);
6424     // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
6425     if (tickLabelSide == QCPAxis::lsOutside)
6426     {
6427       if (QCPAxis::orientation(type) == Qt::Horizontal)
6428       {
6429         if (labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width() > viewportRect.right() ||
6430             labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left())
6431           return;
6432       } else
6433       {
6434         if (labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height() >viewportRect.bottom() ||
6435             labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top())
6436           return;
6437       }
6438     }
6439     painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap);
6440     finalSize = cachedLabel->pixmap.size();
6441   } else // label caching disabled, draw text directly on surface:
6442   {
6443     TickLabelData labelData = getTickLabelData(painter->font(), text);
6444     QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData);
6445     // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
6446     if (tickLabelSide == QCPAxis::lsOutside)
6447     {
6448       if (QCPAxis::orientation(type) == Qt::Horizontal)
6449       {
6450         if (finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() ||
6451             finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left())
6452           return;
6453       } else
6454       {
6455         if (finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() ||
6456             finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top())
6457           return;
6458       }
6459     }
6460     drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData);
6461     finalSize = labelData.rotatedTotalBounds.size();
6462   }
6463
6464   // expand passed tickLabelsSize if current tick label is larger:
6465   if (finalSize.width() > tickLabelsSize->width())
6466     tickLabelsSize->setWidth(finalSize.width());
6467   if (finalSize.height() > tickLabelsSize->height())
6468     tickLabelsSize->setHeight(finalSize.height());
6469 }
6470
6471 /*! \internal
6472
6473   This is a \ref placeTickLabel helper function.
6474
6475   Draws the tick label specified in \a labelData with \a painter at the pixel positions \a x and \a
6476   y. This function is used by \ref placeTickLabel to create new tick labels for the cache, or to
6477   directly draw the labels on the QCustomPlot surface when label caching is disabled, i.e. when
6478   QCP::phCacheLabels plotting hint is not set.
6479 */
6480 void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const
6481 {
6482   // backup painter settings that we're about to change:
6483   QTransform oldTransform = painter->transform();
6484   QFont oldFont = painter->font();
6485
6486   // transform painter to position/rotation:
6487   painter->translate(x, y);
6488   if (!qFuzzyIsNull(tickLabelRotation))
6489     painter->rotate(tickLabelRotation);
6490
6491   // draw text:
6492   if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used
6493   {
6494     painter->setFont(labelData.baseFont);
6495     painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart);
6496     painter->setFont(labelData.expFont);
6497     painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip,  labelData.expPart);
6498   } else
6499   {
6500     painter->setFont(labelData.baseFont);
6501     painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart);
6502   }
6503
6504   // reset painter settings to what it was before:
6505   painter->setTransform(oldTransform);
6506   painter->setFont(oldFont);
6507 }
6508
6509 /*! \internal
6510
6511   This is a \ref placeTickLabel helper function.
6512
6513   Transforms the passed \a text and \a font to a tickLabelData structure that can then be further
6514   processed by \ref getTickLabelDrawOffset and \ref drawTickLabel. It splits the text into base and
6515   exponent if necessary (member substituteExponent) and calculates appropriate bounding boxes.
6516 */
6517 QCPAxisPainterPrivate::TickLabelData QCPAxisPainterPrivate::getTickLabelData(const QFont &font, const QString &text) const
6518 {
6519   TickLabelData result;
6520
6521   // determine whether beautiful decimal powers should be used
6522   bool useBeautifulPowers = false;
6523   int ePos = -1;
6524   if (substituteExponent)
6525   {
6526     ePos = text.indexOf(QLatin1Char('e'));
6527     if (ePos > -1)
6528       useBeautifulPowers = true;
6529   }
6530
6531   // calculate text bounding rects and do string preparation for beautiful decimal powers:
6532   result.baseFont = font;
6533   if (result.baseFont.pointSizeF() > 0) // On some rare systems, this sometimes is initialized with -1 (Qt bug?), so we check here before possibly setting a negative value in the next line
6534     result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding
6535   if (useBeautifulPowers)
6536   {
6537     // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent:
6538     result.basePart = text.left(ePos);
6539     // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base:
6540     if (abbreviateDecimalPowers && result.basePart == QLatin1String("1"))
6541       result.basePart = QLatin1String("10");
6542     else
6543       result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10");
6544     result.expPart = text.mid(ePos+1);
6545     // clip "+" and leading zeros off expPart:
6546     while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e'
6547       result.expPart.remove(1, 1);
6548     if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+'))
6549       result.expPart.remove(0, 1);
6550     // prepare smaller font for exponent:
6551     result.expFont = font;
6552     result.expFont.setPointSize(result.expFont.pointSize()*0.75);
6553     // calculate bounding rects of base part, exponent part and total one:
6554     result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart);
6555     result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart);
6556     result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA
6557   } else // useBeautifulPowers == false
6558   {
6559     result.basePart = text;
6560     result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart);
6561   }
6562   result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler
6563
6564   // calculate possibly different bounding rect after rotation:
6565   result.rotatedTotalBounds = result.totalBounds;
6566   if (!qFuzzyIsNull(tickLabelRotation))
6567   {
6568     QTransform transform;
6569     transform.rotate(tickLabelRotation);
6570     result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds);
6571   }
6572
6573   return result;
6574 }
6575
6576 /*! \internal
6577
6578   This is a \ref placeTickLabel helper function.
6579
6580   Calculates the offset at which the top left corner of the specified tick label shall be drawn.
6581   The offset is relative to a point right next to the tick the label belongs to.
6582
6583   This function is thus responsible for e.g. centering tick labels under ticks and positioning them
6584   appropriately when they are rotated.
6585 */
6586 QPointF QCPAxisPainterPrivate::getTickLabelDrawOffset(const TickLabelData &labelData) const
6587 {
6588   /*
6589     calculate label offset from base point at tick (non-trivial, for best visual appearance): short
6590     explanation for bottom axis: The anchor, i.e. the point in the label that is placed
6591     horizontally under the corresponding tick is always on the label side that is closer to the
6592     axis (e.g. the left side of the text when we're rotating clockwise). On that side, the height
6593     is halved and the resulting point is defined the anchor. This way, a 90 degree rotated text
6594     will be centered under the tick (i.e. displaced horizontally by half its height). At the same
6595     time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick
6596     labels.
6597   */
6598   bool doRotation = !qFuzzyIsNull(tickLabelRotation);
6599   bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes.
6600   double radians = tickLabelRotation/180.0*M_PI;
6601   int x=0, y=0;
6602   if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label
6603   {
6604     if (doRotation)
6605     {
6606       if (tickLabelRotation > 0)
6607       {
6608         x = -qCos(radians)*labelData.totalBounds.width();
6609         y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0;
6610       } else
6611       {
6612         x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height();
6613         y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0;
6614       }
6615     } else
6616     {
6617       x = -labelData.totalBounds.width();
6618       y = -labelData.totalBounds.height()/2.0;
6619     }
6620   } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label
6621   {
6622     if (doRotation)
6623     {
6624       if (tickLabelRotation > 0)
6625       {
6626         x = +qSin(radians)*labelData.totalBounds.height();
6627         y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0;
6628       } else
6629       {
6630         x = 0;
6631         y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0;
6632       }
6633     } else
6634     {
6635       x = 0;
6636       y = -labelData.totalBounds.height()/2.0;
6637     }
6638   } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label
6639   {
6640     if (doRotation)
6641     {
6642       if (tickLabelRotation > 0)
6643       {
6644         x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0;
6645         y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height();
6646       } else
6647       {
6648         x = -qSin(-radians)*labelData.totalBounds.height()/2.0;
6649         y = -qCos(-radians)*labelData.totalBounds.height();
6650       }
6651     } else
6652     {
6653       x = -labelData.totalBounds.width()/2.0;
6654       y = -labelData.totalBounds.height();
6655     }
6656   } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label
6657   {
6658     if (doRotation)
6659     {
6660       if (tickLabelRotation > 0)
6661       {
6662         x = +qSin(radians)*labelData.totalBounds.height()/2.0;
6663         y = 0;
6664       } else
6665       {
6666         x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0;
6667         y = +qSin(-radians)*labelData.totalBounds.width();
6668       }
6669     } else
6670     {
6671       x = -labelData.totalBounds.width()/2.0;
6672       y = 0;
6673     }
6674   }
6675
6676   return QPointF(x, y);
6677 }
6678
6679 /*! \internal
6680
6681   Simulates the steps done by \ref placeTickLabel by calculating bounding boxes of the text label
6682   to be drawn, depending on number format etc. Since only the largest tick label is wanted for the
6683   margin calculation, the passed \a tickLabelsSize is only expanded, if it's currently set to a
6684   smaller width/height.
6685 */
6686 void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text,  QSize *tickLabelsSize) const
6687 {
6688   // note: this function must return the same tick label sizes as the placeTickLabel function.
6689   QSize finalSize;
6690   if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label
6691   {
6692     const CachedLabel *cachedLabel = mLabelCache.object(text);
6693     finalSize = cachedLabel->pixmap.size();
6694   } else // label caching disabled or no label with this text cached:
6695   {
6696     TickLabelData labelData = getTickLabelData(font, text);
6697     finalSize = labelData.rotatedTotalBounds.size();
6698   }
6699
6700   // expand passed tickLabelsSize if current tick label is larger:
6701   if (finalSize.width() > tickLabelsSize->width())
6702     tickLabelsSize->setWidth(finalSize.width());
6703   if (finalSize.height() > tickLabelsSize->height())
6704     tickLabelsSize->setHeight(finalSize.height());
6705 }
6706
6707
6708 ////////////////////////////////////////////////////////////////////////////////////////////////////
6709 //////////////////// QCPAbstractPlottable
6710 ////////////////////////////////////////////////////////////////////////////////////////////////////
6711
6712 /*! \class QCPAbstractPlottable
6713   \brief The abstract base class for all data representing objects in a plot.
6714
6715   It defines a very basic interface like name, pen, brush, visibility etc. Since this class is
6716   abstract, it can't be instantiated. Use one of the subclasses or create a subclass yourself to
6717   create new ways of displaying data (see "Creating own plottables" below).
6718
6719   All further specifics are in the subclasses, for example:
6720   \li A normal graph with possibly a line, scatter points and error bars: \ref QCPGraph
6721   (typically created with \ref QCustomPlot::addGraph)
6722   \li A parametric curve: \ref QCPCurve
6723   \li A bar chart: \ref QCPBars
6724   \li A statistical box plot: \ref QCPStatisticalBox
6725   \li A color encoded two-dimensional map: \ref QCPColorMap
6726   \li An OHLC/Candlestick chart: \ref QCPFinancial
6727
6728   \section plottables-subclassing Creating own plottables
6729
6730   To create an own plottable, you implement a subclass of QCPAbstractPlottable. These are the pure
6731   virtual functions, you must implement:
6732   \li \ref clearData
6733   \li \ref selectTest
6734   \li \ref draw
6735   \li \ref drawLegendIcon
6736   \li \ref getKeyRange
6737   \li \ref getValueRange
6738
6739   See the documentation of those functions for what they need to do.
6740
6741   For drawing your plot, you can use the \ref coordsToPixels functions to translate a point in plot
6742   coordinates to pixel coordinates. This function is quite convenient, because it takes the
6743   orientation of the key and value axes into account for you (x and y are swapped when the key axis
6744   is vertical and the value axis horizontal). If you are worried about performance (i.e. you need
6745   to translate many points in a loop like QCPGraph), you can directly use \ref
6746   QCPAxis::coordToPixel. However, you must then take care about the orientation of the axis
6747   yourself.
6748
6749   Here are some important members you inherit from QCPAbstractPlottable:
6750   <table>
6751   <tr>
6752     <td>QCustomPlot *\b mParentPlot</td>
6753     <td>A pointer to the parent QCustomPlot instance. The parent plot is inferred from the axes that are passed in the constructor.</td>
6754   </tr><tr>
6755     <td>QString \b mName</td>
6756     <td>The name of the plottable.</td>
6757   </tr><tr>
6758     <td>QPen \b mPen</td>
6759     <td>The generic pen of the plottable. You should use this pen for the most prominent data representing lines in the plottable (e.g QCPGraph uses this pen for its graph lines and scatters)</td>
6760   </tr><tr>
6761     <td>QPen \b mSelectedPen</td>
6762     <td>The generic pen that should be used when the plottable is selected (hint: \ref mainPen gives you the right pen, depending on selection state).</td>
6763   </tr><tr>
6764     <td>QBrush \b mBrush</td>
6765     <td>The generic brush of the plottable. You should use this brush for the most prominent fillable structures in the plottable (e.g. QCPGraph uses this brush to control filling under the graph)</td>
6766   </tr><tr>
6767     <td>QBrush \b mSelectedBrush</td>
6768     <td>The generic brush that should be used when the plottable is selected (hint: \ref mainBrush gives you the right brush, depending on selection state).</td>
6769   </tr><tr>
6770     <td>QPointer<QCPAxis>\b mKeyAxis, \b mValueAxis</td>
6771     <td>The key and value axes this plottable is attached to. Call their QCPAxis::coordToPixel functions to translate coordinates to pixels in either the key or value dimension.
6772         Make sure to check whether the pointer is null before using it. If one of the axes is null, don't draw the plottable.</td>
6773   </tr><tr>
6774     <td>bool \b mSelected</td>
6775     <td>indicates whether the plottable is selected or not.</td>
6776   </tr>
6777   </table>
6778 */
6779
6780 /* start of documentation of pure virtual functions */
6781
6782 /*! \fn void QCPAbstractPlottable::clearData() = 0
6783   Clears all data in the plottable.
6784 */
6785
6786 /*! \fn void QCPAbstractPlottable::drawLegendIcon(QCPPainter *painter, const QRect &rect) const = 0
6787   \internal
6788
6789   called by QCPLegend::draw (via QCPPlottableLegendItem::draw) to create a graphical representation
6790   of this plottable inside \a rect, next to the plottable name.
6791 */
6792
6793 /*! \fn QCPRange QCPAbstractPlottable::getKeyRange(bool &foundRange, SignDomain inSignDomain) const = 0
6794   \internal
6795
6796   called by rescaleAxes functions to get the full data key bounds. For logarithmic plots, one can
6797   set \a inSignDomain to either \ref sdNegative or \ref sdPositive in order to restrict the
6798   returned range to that sign domain. E.g. when only negative range is wanted, set \a inSignDomain
6799   to \ref sdNegative and all positive points will be ignored for range calculation. For no
6800   restriction, just set \a inSignDomain to \ref sdBoth (default). \a foundRange is an output
6801   parameter that indicates whether a range could be found or not. If this is false, you shouldn't
6802   use the returned range (e.g. no points in data).
6803
6804   Note that \a foundRange is not the same as \ref QCPRange::validRange, since the range returned by
6805   this function may have size zero, which wouldn't count as a valid range.
6806
6807   \see rescaleAxes, getValueRange
6808 */
6809
6810 /*! \fn QCPRange QCPAbstractPlottable::getValueRange(bool &foundRange, SignDomain inSignDomain) const = 0
6811   \internal
6812
6813   called by rescaleAxes functions to get the full data value bounds. For logarithmic plots, one can
6814   set \a inSignDomain to either \ref sdNegative or \ref sdPositive in order to restrict the
6815   returned range to that sign domain. E.g. when only negative range is wanted, set \a inSignDomain
6816   to \ref sdNegative and all positive points will be ignored for range calculation. For no
6817   restriction, just set \a inSignDomain to \ref sdBoth (default). \a foundRange is an output
6818   parameter that indicates whether a range could be found or not. If this is false, you shouldn't
6819   use the returned range (e.g. no points in data).
6820
6821   Note that \a foundRange is not the same as \ref QCPRange::validRange, since the range returned by
6822   this function may have size zero, which wouldn't count as a valid range.
6823
6824   \see rescaleAxes, getKeyRange
6825 */
6826
6827 /* end of documentation of pure virtual functions */
6828 /* start of documentation of signals */
6829
6830 /*! \fn void QCPAbstractPlottable::selectionChanged(bool selected)
6831
6832   This signal is emitted when the selection state of this plottable has changed, either by user
6833   interaction or by a direct call to \ref setSelected.
6834 */
6835
6836 /*! \fn void QCPAbstractPlottable::selectableChanged(bool selectable);
6837
6838   This signal is emitted when the selectability of this plottable has changed.
6839
6840   \see setSelectable
6841 */
6842
6843 /* end of documentation of signals */
6844
6845 /*!
6846   Constructs an abstract plottable which uses \a keyAxis as its key axis ("x") and \a valueAxis as
6847   its value axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance
6848   and have perpendicular orientations. If either of these restrictions is violated, a corresponding
6849   message is printed to the debug output (qDebug), the construction is not aborted, though.
6850
6851   Since QCPAbstractPlottable is an abstract class that defines the basic interface to plottables,
6852   it can't be directly instantiated.
6853
6854   You probably want one of the subclasses like \ref QCPGraph or \ref QCPCurve instead.
6855 */
6856 QCPAbstractPlottable::QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis) :
6857   QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()),
6858   mName(),
6859   mAntialiasedFill(true),
6860   mAntialiasedScatters(true),
6861   mAntialiasedErrorBars(false),
6862   mPen(Qt::black),
6863   mSelectedPen(Qt::black),
6864   mBrush(Qt::NoBrush),
6865   mSelectedBrush(Qt::NoBrush),
6866   mKeyAxis(keyAxis),
6867   mValueAxis(valueAxis),
6868   mSelectable(true),
6869   mSelected(false)
6870 {
6871   if (keyAxis->parentPlot() != valueAxis->parentPlot())
6872     qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis.";
6873   if (keyAxis->orientation() == valueAxis->orientation())
6874     qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other.";
6875 }
6876
6877 /*!
6878    The name is the textual representation of this plottable as it is displayed in the legend
6879    (\ref QCPLegend). It may contain any UTF-8 characters, including newlines.
6880 */
6881 void QCPAbstractPlottable::setName(const QString &name)
6882 {
6883   mName = name;
6884 }
6885
6886 /*!
6887   Sets whether fills of this plottable is drawn antialiased or not.
6888
6889   Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref
6890   QCustomPlot::setNotAntialiasedElements.
6891 */
6892 void QCPAbstractPlottable::setAntialiasedFill(bool enabled)
6893 {
6894   mAntialiasedFill = enabled;
6895 }
6896
6897 /*!
6898   Sets whether the scatter symbols of this plottable are drawn antialiased or not.
6899
6900   Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref
6901   QCustomPlot::setNotAntialiasedElements.
6902 */
6903 void QCPAbstractPlottable::setAntialiasedScatters(bool enabled)
6904 {
6905   mAntialiasedScatters = enabled;
6906 }
6907
6908 /*!
6909   Sets whether the error bars of this plottable are drawn antialiased or not.
6910
6911   Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref
6912   QCustomPlot::setNotAntialiasedElements.
6913 */
6914 void QCPAbstractPlottable::setAntialiasedErrorBars(bool enabled)
6915 {
6916   mAntialiasedErrorBars = enabled;
6917 }
6918
6919
6920 /*!
6921   The pen is used to draw basic lines that make up the plottable representation in the
6922   plot.
6923
6924   For example, the \ref QCPGraph subclass draws its graph lines and scatter points
6925   with this pen.
6926
6927   \see setBrush
6928 */
6929 void QCPAbstractPlottable::setPen(const QPen &pen)
6930 {
6931   mPen = pen;
6932 }
6933
6934 /*!
6935   When the plottable is selected, this pen is used to draw basic lines instead of the normal
6936   pen set via \ref setPen.
6937
6938   \see setSelected, setSelectable, setSelectedBrush, selectTest
6939 */
6940 void QCPAbstractPlottable::setSelectedPen(const QPen &pen)
6941 {
6942   mSelectedPen = pen;
6943 }
6944
6945 /*!
6946   The brush is used to draw basic fills of the plottable representation in the
6947   plot. The Fill can be a color, gradient or texture, see the usage of QBrush.
6948
6949   For example, the \ref QCPGraph subclass draws the fill under the graph with this brush, when
6950   it's not set to Qt::NoBrush.
6951
6952   \see setPen
6953 */
6954 void QCPAbstractPlottable::setBrush(const QBrush &brush)
6955 {
6956   mBrush = brush;
6957 }
6958
6959 /*!
6960   When the plottable is selected, this brush is used to draw fills instead of the normal
6961   brush set via \ref setBrush.
6962
6963   \see setSelected, setSelectable, setSelectedPen, selectTest
6964 */
6965 void QCPAbstractPlottable::setSelectedBrush(const QBrush &brush)
6966 {
6967   mSelectedBrush = brush;
6968 }
6969
6970 /*!
6971   The key axis of a plottable can be set to any axis of a QCustomPlot, as long as it is orthogonal
6972   to the plottable's value axis. This function performs no checks to make sure this is the case.
6973   The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and the
6974   y-axis (QCustomPlot::yAxis) as value axis.
6975
6976   Normally, the key and value axes are set in the constructor of the plottable (or \ref
6977   QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface).
6978
6979   \see setValueAxis
6980 */
6981 void QCPAbstractPlottable::setKeyAxis(QCPAxis *axis)
6982 {
6983   mKeyAxis = axis;
6984 }
6985
6986 /*!
6987   The value axis of a plottable can be set to any axis of a QCustomPlot, as long as it is
6988   orthogonal to the plottable's key axis. This function performs no checks to make sure this is the
6989   case. The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and
6990   the y-axis (QCustomPlot::yAxis) as value axis.
6991
6992   Normally, the key and value axes are set in the constructor of the plottable (or \ref
6993   QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface).
6994
6995   \see setKeyAxis
6996 */
6997 void QCPAbstractPlottable::setValueAxis(QCPAxis *axis)
6998 {
6999   mValueAxis = axis;
7000 }
7001
7002 /*!
7003   Sets whether the user can (de-)select this plottable by clicking on the QCustomPlot surface.
7004   (When \ref QCustomPlot::setInteractions contains iSelectPlottables.)
7005
7006   However, even when \a selectable was set to false, it is possible to set the selection manually,
7007   by calling \ref setSelected directly.
7008
7009   \see setSelected
7010 */
7011 void QCPAbstractPlottable::setSelectable(bool selectable)
7012 {
7013   if (mSelectable != selectable)
7014   {
7015     mSelectable = selectable;
7016     emit selectableChanged(mSelectable);
7017   }
7018 }
7019
7020 /*!
7021   Sets whether this plottable is selected or not. When selected, it uses a different pen and brush
7022   to draw its lines and fills, see \ref setSelectedPen and \ref setSelectedBrush.
7023
7024   The entire selection mechanism for plottables is handled automatically when \ref
7025   QCustomPlot::setInteractions contains iSelectPlottables. You only need to call this function when
7026   you wish to change the selection state manually.
7027
7028   This function can change the selection state even when \ref setSelectable was set to false.
7029
7030   emits the \ref selectionChanged signal when \a selected is different from the previous selection state.
7031
7032   \see setSelectable, selectTest
7033 */
7034 void QCPAbstractPlottable::setSelected(bool selected)
7035 {
7036   if (mSelected != selected)
7037   {
7038     mSelected = selected;
7039     emit selectionChanged(mSelected);
7040   }
7041 }
7042
7043 /*!
7044   Rescales the key and value axes associated with this plottable to contain all displayed data, so
7045   the whole plottable is visible. If the scaling of an axis is logarithmic, rescaleAxes will make
7046   sure not to rescale to an illegal range i.e. a range containing different signs and/or zero.
7047   Instead it will stay in the current sign domain and ignore all parts of the plottable that lie
7048   outside of that domain.
7049
7050   \a onlyEnlarge makes sure the ranges are only expanded, never reduced. So it's possible to show
7051   multiple plottables in their entirety by multiple calls to rescaleAxes where the first call has
7052   \a onlyEnlarge set to false (the default), and all subsequent set to true.
7053
7054   \see rescaleKeyAxis, rescaleValueAxis, QCustomPlot::rescaleAxes, QCPAxis::rescale
7055 */
7056 void QCPAbstractPlottable::rescaleAxes(bool onlyEnlarge) const
7057 {
7058   rescaleKeyAxis(onlyEnlarge);
7059   rescaleValueAxis(onlyEnlarge);
7060 }
7061
7062 /*!
7063   Rescales the key axis of the plottable so the whole plottable is visible.
7064
7065   See \ref rescaleAxes for detailed behaviour.
7066 */
7067 void QCPAbstractPlottable::rescaleKeyAxis(bool onlyEnlarge) const
7068 {
7069   QCPAxis *keyAxis = mKeyAxis.data();
7070   if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
7071
7072   SignDomain signDomain = sdBoth;
7073   if (keyAxis->scaleType() == QCPAxis::stLogarithmic)
7074     signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive);
7075
7076   bool foundRange;
7077   QCPRange newRange = getKeyRange(foundRange, signDomain);
7078   if (foundRange)
7079   {
7080     if (onlyEnlarge)
7081       newRange.expand(keyAxis->range());
7082     if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
7083     {
7084       double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
7085       if (keyAxis->scaleType() == QCPAxis::stLinear)
7086       {
7087         newRange.lower = center-keyAxis->range().size()/2.0;
7088         newRange.upper = center+keyAxis->range().size()/2.0;
7089       } else // scaleType() == stLogarithmic
7090       {
7091         newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower);
7092         newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower);
7093       }
7094     }
7095     keyAxis->setRange(newRange);
7096   }
7097 }
7098
7099 /*!
7100   Rescales the value axis of the plottable so the whole plottable is visible.
7101
7102   Returns true if the axis was actually scaled. This might not be the case if this plottable has an
7103   invalid range, e.g. because it has no data points.
7104
7105   See \ref rescaleAxes for detailed behaviour.
7106 */
7107 void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge) const
7108 {
7109   QCPAxis *valueAxis = mValueAxis.data();
7110   if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; }
7111
7112   SignDomain signDomain = sdBoth;
7113   if (valueAxis->scaleType() == QCPAxis::stLogarithmic)
7114     signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive);
7115
7116   bool foundRange;
7117   QCPRange newRange = getValueRange(foundRange, signDomain);
7118   if (foundRange)
7119   {
7120     if (onlyEnlarge)
7121       newRange.expand(valueAxis->range());
7122     if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
7123     {
7124       double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
7125       if (valueAxis->scaleType() == QCPAxis::stLinear)
7126       {
7127         newRange.lower = center-valueAxis->range().size()/2.0;
7128         newRange.upper = center+valueAxis->range().size()/2.0;
7129       } else // scaleType() == stLogarithmic
7130       {
7131         newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower);
7132         newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower);
7133       }
7134     }
7135     valueAxis->setRange(newRange);
7136   }
7137 }
7138
7139 /*!
7140   Adds this plottable to the legend of the parent QCustomPlot (QCustomPlot::legend).
7141
7142   Normally, a QCPPlottableLegendItem is created and inserted into the legend. If the plottable
7143   needs a more specialized representation in the legend, this function will take this into account
7144   and instead create the specialized subclass of QCPAbstractLegendItem.
7145
7146   Returns true on success, i.e. when the legend exists and a legend item associated with this plottable isn't already in
7147   the legend.
7148
7149   \see removeFromLegend, QCPLegend::addItem
7150 */
7151 bool QCPAbstractPlottable::addToLegend()
7152 {
7153   if (!mParentPlot || !mParentPlot->legend)
7154     return false;
7155
7156   if (!mParentPlot->legend->hasItemWithPlottable(this))
7157   {
7158     mParentPlot->legend->addItem(new QCPPlottableLegendItem(mParentPlot->legend, this));
7159     return true;
7160   } else
7161     return false;
7162 }
7163
7164 /*!
7165   Removes the plottable from the legend of the parent QCustomPlot. This means the
7166   QCPAbstractLegendItem (usually a QCPPlottableLegendItem) that is associated with this plottable
7167   is removed.
7168
7169   Returns true on success, i.e. if the legend exists and a legend item associated with this
7170   plottable was found and removed.
7171
7172   \see addToLegend, QCPLegend::removeItem
7173 */
7174 bool QCPAbstractPlottable::removeFromLegend() const
7175 {
7176   if (!mParentPlot->legend)
7177     return false;
7178
7179   if (QCPPlottableLegendItem *lip = mParentPlot->legend->itemWithPlottable(this))
7180     return mParentPlot->legend->removeItem(lip);
7181   else
7182     return false;
7183 }
7184
7185 /* inherits documentation from base class */
7186 QRect QCPAbstractPlottable::clipRect() const
7187 {
7188   if (mKeyAxis && mValueAxis)
7189     return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect();
7190   else
7191     return QRect();
7192 }
7193
7194 /* inherits documentation from base class */
7195 QCP::Interaction QCPAbstractPlottable::selectionCategory() const
7196 {
7197   return QCP::iSelectPlottables;
7198 }
7199
7200 /*! \internal
7201
7202   Convenience function for transforming a key/value pair to pixels on the QCustomPlot surface,
7203   taking the orientations of the axes associated with this plottable into account (e.g. whether key
7204   represents x or y).
7205
7206   \a key and \a value are transformed to the coodinates in pixels and are written to \a x and \a y.
7207
7208   \see pixelsToCoords, QCPAxis::coordToPixel
7209 */
7210 void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const
7211 {
7212   QCPAxis *keyAxis = mKeyAxis.data();
7213   QCPAxis *valueAxis = mValueAxis.data();
7214   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
7215
7216   if (keyAxis->orientation() == Qt::Horizontal)
7217   {
7218     x = keyAxis->coordToPixel(key);
7219     y = valueAxis->coordToPixel(value);
7220   } else
7221   {
7222     y = keyAxis->coordToPixel(key);
7223     x = valueAxis->coordToPixel(value);
7224   }
7225 }
7226
7227 /*! \internal
7228   \overload
7229
7230   Returns the input as pixel coordinates in a QPointF.
7231 */
7232 const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const
7233 {
7234   QCPAxis *keyAxis = mKeyAxis.data();
7235   QCPAxis *valueAxis = mValueAxis.data();
7236   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
7237
7238   if (keyAxis->orientation() == Qt::Horizontal)
7239     return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value));
7240   else
7241     return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key));
7242 }
7243
7244 /*! \internal
7245
7246   Convenience function for transforming a x/y pixel pair on the QCustomPlot surface to plot coordinates,
7247   taking the orientations of the axes associated with this plottable into account (e.g. whether key
7248   represents x or y).
7249
7250   \a x and \a y are transformed to the plot coodinates and are written to \a key and \a value.
7251
7252   \see coordsToPixels, QCPAxis::coordToPixel
7253 */
7254 void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const
7255 {
7256   QCPAxis *keyAxis = mKeyAxis.data();
7257   QCPAxis *valueAxis = mValueAxis.data();
7258   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
7259
7260   if (keyAxis->orientation() == Qt::Horizontal)
7261   {
7262     key = keyAxis->pixelToCoord(x);
7263     value = valueAxis->pixelToCoord(y);
7264   } else
7265   {
7266     key = keyAxis->pixelToCoord(y);
7267     value = valueAxis->pixelToCoord(x);
7268   }
7269 }
7270
7271 /*! \internal
7272   \overload
7273
7274   Returns the pixel input \a pixelPos as plot coordinates \a key and \a value.
7275 */
7276 void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const
7277 {
7278   pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value);
7279 }
7280
7281 /*! \internal
7282
7283   Returns the pen that should be used for drawing lines of the plottable. Returns mPen when the
7284   graph is not selected and mSelectedPen when it is.
7285 */
7286 QPen QCPAbstractPlottable::mainPen() const
7287 {
7288   return mSelected ? mSelectedPen : mPen;
7289 }
7290
7291 /*! \internal
7292
7293   Returns the brush that should be used for drawing fills of the plottable. Returns mBrush when the
7294   graph is not selected and mSelectedBrush when it is.
7295 */
7296 QBrush QCPAbstractPlottable::mainBrush() const
7297 {
7298   return mSelected ? mSelectedBrush : mBrush;
7299 }
7300
7301 /*! \internal
7302
7303   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
7304   before drawing plottable lines.
7305
7306   This is the antialiasing state the painter passed to the \ref draw method is in by default.
7307
7308   This function takes into account the local setting of the antialiasing flag as well as the
7309   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
7310   QCustomPlot::setNotAntialiasedElements.
7311
7312   \see setAntialiased, applyFillAntialiasingHint, applyScattersAntialiasingHint, applyErrorBarsAntialiasingHint
7313 */
7314 void QCPAbstractPlottable::applyDefaultAntialiasingHint(QCPPainter *painter) const
7315 {
7316   applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables);
7317 }
7318
7319 /*! \internal
7320
7321   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
7322   before drawing plottable fills.
7323
7324   This function takes into account the local setting of the antialiasing flag as well as the
7325   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
7326   QCustomPlot::setNotAntialiasedElements.
7327
7328   \see setAntialiased, applyDefaultAntialiasingHint, applyScattersAntialiasingHint, applyErrorBarsAntialiasingHint
7329 */
7330 void QCPAbstractPlottable::applyFillAntialiasingHint(QCPPainter *painter) const
7331 {
7332   applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills);
7333 }
7334
7335 /*! \internal
7336
7337   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
7338   before drawing plottable scatter points.
7339
7340   This function takes into account the local setting of the antialiasing flag as well as the
7341   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
7342   QCustomPlot::setNotAntialiasedElements.
7343
7344   \see setAntialiased, applyFillAntialiasingHint, applyDefaultAntialiasingHint, applyErrorBarsAntialiasingHint
7345 */
7346 void QCPAbstractPlottable::applyScattersAntialiasingHint(QCPPainter *painter) const
7347 {
7348   applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters);
7349 }
7350
7351 /*! \internal
7352
7353   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
7354   before drawing plottable error bars.
7355
7356   This function takes into account the local setting of the antialiasing flag as well as the
7357   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
7358   QCustomPlot::setNotAntialiasedElements.
7359
7360   \see setAntialiased, applyFillAntialiasingHint, applyScattersAntialiasingHint, applyDefaultAntialiasingHint
7361 */
7362 void QCPAbstractPlottable::applyErrorBarsAntialiasingHint(QCPPainter *painter) const
7363 {
7364   applyAntialiasingHint(painter, mAntialiasedErrorBars, QCP::aeErrorBars);
7365 }
7366
7367 /*! \internal
7368
7369   Finds the shortest squared distance of \a point to the line segment defined by \a start and \a
7370   end.
7371
7372   This function may be used to help with the implementation of the \ref selectTest function for
7373   specific plottables.
7374
7375   \note This function is identical to QCPAbstractItem::distSqrToLine
7376 */
7377 double QCPAbstractPlottable::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
7378 {
7379   QVector2D a(start);
7380   QVector2D b(end);
7381   QVector2D p(point);
7382   QVector2D v(b-a);
7383
7384   double vLengthSqr = v.lengthSquared();
7385   if (!qFuzzyIsNull(vLengthSqr))
7386   {
7387     double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
7388     if (mu < 0)
7389       return (a-p).lengthSquared();
7390     else if (mu > 1)
7391       return (b-p).lengthSquared();
7392     else
7393       return ((a + mu*v)-p).lengthSquared();
7394   } else
7395     return (a-p).lengthSquared();
7396 }
7397
7398 /* inherits documentation from base class */
7399 void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
7400 {
7401   Q_UNUSED(event)
7402   Q_UNUSED(details)
7403   if (mSelectable)
7404   {
7405     bool selBefore = mSelected;
7406     setSelected(additive ? !mSelected : true);
7407     if (selectionStateChanged)
7408       *selectionStateChanged = mSelected != selBefore;
7409   }
7410 }
7411
7412 /* inherits documentation from base class */
7413 void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged)
7414 {
7415   if (mSelectable)
7416   {
7417     bool selBefore = mSelected;
7418     setSelected(false);
7419     if (selectionStateChanged)
7420       *selectionStateChanged = mSelected != selBefore;
7421   }
7422 }
7423
7424
7425 ////////////////////////////////////////////////////////////////////////////////////////////////////
7426 //////////////////// QCPItemAnchor
7427 ////////////////////////////////////////////////////////////////////////////////////////////////////
7428
7429 /*! \class QCPItemAnchor
7430   \brief An anchor of an item to which positions can be attached to.
7431
7432   An item (QCPAbstractItem) may have one or more anchors. Unlike QCPItemPosition, an anchor doesn't
7433   control anything on its item, but provides a way to tie other items via their positions to the
7434   anchor.
7435
7436   For example, a QCPItemRect is defined by its positions \a topLeft and \a bottomRight.
7437   Additionally it has various anchors like \a top, \a topRight or \a bottomLeft etc. So you can
7438   attach the \a start (which is a QCPItemPosition) of a QCPItemLine to one of the anchors by
7439   calling QCPItemPosition::setParentAnchor on \a start, passing the wanted anchor of the
7440   QCPItemRect. This way the start of the line will now always follow the respective anchor location
7441   on the rect item.
7442
7443   Note that QCPItemPosition derives from QCPItemAnchor, so every position can also serve as an
7444   anchor to other positions.
7445
7446   To learn how to provide anchors in your own item subclasses, see the subclassing section of the
7447   QCPAbstractItem documentation.
7448 */
7449
7450 /* start documentation of inline functions */
7451
7452 /*! \fn virtual QCPItemPosition *QCPItemAnchor::toQCPItemPosition()
7453
7454   Returns 0 if this instance is merely a QCPItemAnchor, and a valid pointer of type QCPItemPosition* if
7455   it actually is a QCPItemPosition (which is a subclass of QCPItemAnchor).
7456
7457   This safe downcast functionality could also be achieved with a dynamic_cast. However, QCustomPlot avoids
7458   dynamic_cast to work with projects that don't have RTTI support enabled (e.g. -fno-rtti flag with
7459   gcc compiler).
7460 */
7461
7462 /* end documentation of inline functions */
7463
7464 /*!
7465   Creates a new QCPItemAnchor. You shouldn't create QCPItemAnchor instances directly, even if
7466   you want to make a new item subclass. Use \ref QCPAbstractItem::createAnchor instead, as
7467   explained in the subclassing section of the QCPAbstractItem documentation.
7468 */
7469 QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId) :
7470   mName(name),
7471   mParentPlot(parentPlot),
7472   mParentItem(parentItem),
7473   mAnchorId(anchorId)
7474 {
7475 }
7476
7477 QCPItemAnchor::~QCPItemAnchor()
7478 {
7479   // unregister as parent at children:
7480   foreach (QCPItemPosition *child, mChildrenX.toList())
7481   {
7482     if (child->parentAnchorX() == this)
7483       child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX
7484   }
7485   foreach (QCPItemPosition *child, mChildrenY.toList())
7486   {
7487     if (child->parentAnchorY() == this)
7488       child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY
7489   }
7490 }
7491
7492 /*!
7493   Returns the final absolute pixel position of the QCPItemAnchor on the QCustomPlot surface.
7494
7495   The pixel information is internally retrieved via QCPAbstractItem::anchorPixelPosition of the
7496   parent item, QCPItemAnchor is just an intermediary.
7497 */
7498 QPointF QCPItemAnchor::pixelPoint() const
7499 {
7500   if (mParentItem)
7501   {
7502     if (mAnchorId > -1)
7503     {
7504       return mParentItem->anchorPixelPoint(mAnchorId);
7505     } else
7506     {
7507       qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId;
7508       return QPointF();
7509     }
7510   } else
7511   {
7512     qDebug() << Q_FUNC_INFO << "no parent item set";
7513     return QPointF();
7514   }
7515 }
7516
7517 /*! \internal
7518
7519   Adds \a pos to the childX list of this anchor, which keeps track of which children use this
7520   anchor as parent anchor for the respective coordinate. This is necessary to notify the children
7521   prior to destruction of the anchor.
7522
7523   Note that this function does not change the parent setting in \a pos.
7524 */
7525 void QCPItemAnchor::addChildX(QCPItemPosition *pos)
7526 {
7527   if (!mChildrenX.contains(pos))
7528     mChildrenX.insert(pos);
7529   else
7530     qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
7531 }
7532
7533 /*! \internal
7534
7535   Removes \a pos from the childX list of this anchor.
7536
7537   Note that this function does not change the parent setting in \a pos.
7538 */
7539 void QCPItemAnchor::removeChildX(QCPItemPosition *pos)
7540 {
7541   if (!mChildrenX.remove(pos))
7542     qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
7543 }
7544
7545 /*! \internal
7546
7547   Adds \a pos to the childY list of this anchor, which keeps track of which children use this
7548   anchor as parent anchor for the respective coordinate. This is necessary to notify the children
7549   prior to destruction of the anchor.
7550
7551   Note that this function does not change the parent setting in \a pos.
7552 */
7553 void QCPItemAnchor::addChildY(QCPItemPosition *pos)
7554 {
7555   if (!mChildrenY.contains(pos))
7556     mChildrenY.insert(pos);
7557   else
7558     qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
7559 }
7560
7561 /*! \internal
7562
7563   Removes \a pos from the childY list of this anchor.
7564
7565   Note that this function does not change the parent setting in \a pos.
7566 */
7567 void QCPItemAnchor::removeChildY(QCPItemPosition *pos)
7568 {
7569   if (!mChildrenY.remove(pos))
7570     qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
7571 }
7572
7573
7574 ////////////////////////////////////////////////////////////////////////////////////////////////////
7575 //////////////////// QCPItemPosition
7576 ////////////////////////////////////////////////////////////////////////////////////////////////////
7577
7578 /*! \class QCPItemPosition
7579   \brief Manages the position of an item.
7580
7581   Every item has at least one public QCPItemPosition member pointer which provides ways to position the
7582   item on the QCustomPlot surface. Some items have multiple positions, for example QCPItemRect has two:
7583   \a topLeft and \a bottomRight.
7584
7585   QCPItemPosition has a type (\ref PositionType) that can be set with \ref setType. This type
7586   defines how coordinates passed to \ref setCoords are to be interpreted, e.g. as absolute pixel
7587   coordinates, as plot coordinates of certain axes, etc. For more advanced plots it is also
7588   possible to assign different types per X/Y coordinate of the position (see \ref setTypeX, \ref
7589   setTypeY). This way an item could be positioned at a fixed pixel distance from the top in the Y
7590   direction, while following a plot coordinate in the X direction.
7591
7592   A QCPItemPosition may have a parent QCPItemAnchor, see \ref setParentAnchor. This way you can tie
7593   multiple items together. If the QCPItemPosition has a parent, its coordinates (\ref setCoords)
7594   are considered to be absolute pixels in the reference frame of the parent anchor, where (0, 0)
7595   means directly ontop of the parent anchor. For example, You could attach the \a start position of
7596   a QCPItemLine to the \a bottom anchor of a QCPItemText to make the starting point of the line
7597   always be centered under the text label, no matter where the text is moved to. For more advanced
7598   plots, it is possible to assign different parent anchors per X/Y coordinate of the position, see
7599   \ref setParentAnchorX, \ref setParentAnchorY. This way an item could follow another item in the X
7600   direction but stay at a fixed position in the Y direction. Or even follow item A in X, and item B
7601   in Y.
7602
7603   Note that every QCPItemPosition inherits from QCPItemAnchor and thus can itself be used as parent
7604   anchor for other positions.
7605
7606   To set the apparent pixel position on the QCustomPlot surface directly, use \ref setPixelPoint. This
7607   works no matter what type this QCPItemPosition is or what parent-child situation it is in, as \ref
7608   setPixelPoint transforms the coordinates appropriately, to make the position appear at the specified
7609   pixel values.
7610 */
7611
7612 /* start documentation of inline functions */
7613
7614 /*! \fn QCPItemPosition::PositionType *QCPItemPosition::type() const
7615
7616   Returns the current position type.
7617
7618   If different types were set for X and Y (\ref setTypeX, \ref setTypeY), this method returns the
7619   type of the X coordinate. In that case rather use \a typeX() and \a typeY().
7620
7621   \see setType
7622 */
7623
7624 /*! \fn QCPItemAnchor *QCPItemPosition::parentAnchor() const
7625
7626   Returns the current parent anchor.
7627
7628   If different parent anchors were set for X and Y (\ref setParentAnchorX, \ref setParentAnchorY),
7629   this method returns the parent anchor of the Y coordinate. In that case rather use \a
7630   parentAnchorX() and \a parentAnchorY().
7631
7632   \see setParentAnchor
7633 */
7634
7635 /* end documentation of inline functions */
7636
7637 /*!
7638   Creates a new QCPItemPosition. You shouldn't create QCPItemPosition instances directly, even if
7639   you want to make a new item subclass. Use \ref QCPAbstractItem::createPosition instead, as
7640   explained in the subclassing section of the QCPAbstractItem documentation.
7641 */
7642 QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name) :
7643   QCPItemAnchor(parentPlot, parentItem, name),
7644   mPositionTypeX(ptAbsolute),
7645   mPositionTypeY(ptAbsolute),
7646   mKey(0),
7647   mValue(0),
7648   mParentAnchorX(0),
7649   mParentAnchorY(0)
7650 {
7651 }
7652
7653 QCPItemPosition::~QCPItemPosition()
7654 {
7655   // unregister as parent at children:
7656   // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then
7657   //       the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint
7658   foreach (QCPItemPosition *child, mChildrenX.toList())
7659   {
7660     if (child->parentAnchorX() == this)
7661       child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX
7662   }
7663   foreach (QCPItemPosition *child, mChildrenY.toList())
7664   {
7665     if (child->parentAnchorY() == this)
7666       child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY
7667   }
7668   // unregister as child in parent:
7669   if (mParentAnchorX)
7670     mParentAnchorX->removeChildX(this);
7671   if (mParentAnchorY)
7672     mParentAnchorY->removeChildY(this);
7673 }
7674
7675 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
7676 QCPAxisRect *QCPItemPosition::axisRect() const
7677 {
7678   return mAxisRect.data();
7679 }
7680
7681 /*!
7682   Sets the type of the position. The type defines how the coordinates passed to \ref setCoords
7683   should be handled and how the QCPItemPosition should behave in the plot.
7684
7685   The possible values for \a type can be separated in two main categories:
7686
7687   \li The position is regarded as a point in plot coordinates. This corresponds to \ref ptPlotCoords
7688   and requires two axes that define the plot coordinate system. They can be specified with \ref setAxes.
7689   By default, the QCustomPlot's x- and yAxis are used.
7690
7691   \li The position is fixed on the QCustomPlot surface, i.e. independent of axis ranges. This
7692   corresponds to all other types, i.e. \ref ptAbsolute, \ref ptViewportRatio and \ref
7693   ptAxisRectRatio. They differ only in the way the absolute position is described, see the
7694   documentation of \ref PositionType for details. For \ref ptAxisRectRatio, note that you can specify
7695   the axis rect with \ref setAxisRect. By default this is set to the main axis rect.
7696
7697   Note that the position type \ref ptPlotCoords is only available (and sensible) when the position
7698   has no parent anchor (\ref setParentAnchor).
7699
7700   If the type is changed, the apparent pixel position on the plot is preserved. This means
7701   the coordinates as retrieved with coords() and set with \ref setCoords may change in the process.
7702
7703   This method sets the type for both X and Y directions. It is also possible to set different types
7704   for X and Y, see \ref setTypeX, \ref setTypeY.
7705 */
7706 void QCPItemPosition::setType(QCPItemPosition::PositionType type)
7707 {
7708   setTypeX(type);
7709   setTypeY(type);
7710 }
7711
7712 /*!
7713   This method sets the position type of the X coordinate to \a type.
7714
7715   For a detailed description of what a position type is, see the documentation of \ref setType.
7716
7717   \see setType, setTypeY
7718 */
7719 void QCPItemPosition::setTypeX(QCPItemPosition::PositionType type)
7720 {
7721   if (mPositionTypeX != type)
7722   {
7723     // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
7724     // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning.
7725     bool retainPixelPosition = true;
7726     if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis))
7727       retainPixelPosition = false;
7728     if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect))
7729       retainPixelPosition = false;
7730
7731     QPointF pixel;
7732     if (retainPixelPosition)
7733       pixel = pixelPoint();
7734
7735     mPositionTypeX = type;
7736
7737     if (retainPixelPosition)
7738       setPixelPoint(pixel);
7739   }
7740 }
7741
7742 /*!
7743   This method sets the position type of the Y coordinate to \a type.
7744
7745   For a detailed description of what a position type is, see the documentation of \ref setType.
7746
7747   \see setType, setTypeX
7748 */
7749 void QCPItemPosition::setTypeY(QCPItemPosition::PositionType type)
7750 {
7751   if (mPositionTypeY != type)
7752   {
7753     // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
7754     // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning.
7755     bool retainPixelPosition = true;
7756     if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis))
7757       retainPixelPosition = false;
7758     if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect))
7759       retainPixelPosition = false;
7760
7761     QPointF pixel;
7762     if (retainPixelPosition)
7763       pixel = pixelPoint();
7764
7765     mPositionTypeY = type;
7766
7767     if (retainPixelPosition)
7768       setPixelPoint(pixel);
7769   }
7770 }
7771
7772 /*!
7773   Sets the parent of this QCPItemPosition to \a parentAnchor. This means the position will now
7774   follow any position changes of the anchor. The local coordinate system of positions with a parent
7775   anchor always is absolute pixels, with (0, 0) being exactly on top of the parent anchor. (Hence
7776   the type shouldn't be set to \ref ptPlotCoords for positions with parent anchors.)
7777
7778   if \a keepPixelPosition is true, the current pixel position of the QCPItemPosition is preserved
7779   during reparenting. If it's set to false, the coordinates are set to (0, 0), i.e. the position
7780   will be exactly on top of the parent anchor.
7781
7782   To remove this QCPItemPosition from any parent anchor, set \a parentAnchor to 0.
7783
7784   If the QCPItemPosition previously had no parent and the type is \ref ptPlotCoords, the type is
7785   set to \ref ptAbsolute, to keep the position in a valid state.
7786
7787   This method sets the parent anchor for both X and Y directions. It is also possible to set
7788   different parents for X and Y, see \ref setParentAnchorX, \ref setParentAnchorY.
7789 */
7790 bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7791 {
7792   bool successX = setParentAnchorX(parentAnchor, keepPixelPosition);
7793   bool successY = setParentAnchorY(parentAnchor, keepPixelPosition);
7794   return successX && successY;
7795 }
7796
7797 /*!
7798   This method sets the parent anchor of the X coordinate to \a parentAnchor.
7799
7800   For a detailed description of what a parent anchor is, see the documentation of \ref setParentAnchor.
7801
7802   \see setParentAnchor, setParentAnchorY
7803 */
7804 bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7805 {
7806   // make sure self is not assigned as parent:
7807   if (parentAnchor == this)
7808   {
7809     qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
7810     return false;
7811   }
7812   // make sure no recursive parent-child-relationships are created:
7813   QCPItemAnchor *currentParent = parentAnchor;
7814   while (currentParent)
7815   {
7816     if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
7817     {
7818       // is a QCPItemPosition, might have further parent, so keep iterating
7819       if (currentParentPos == this)
7820       {
7821         qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
7822         return false;
7823       }
7824       currentParent = currentParentPos->parentAnchorX();
7825     } else
7826     {
7827       // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
7828       // same, to prevent a position being child of an anchor which itself depends on the position,
7829       // because they're both on the same item:
7830       if (currentParent->mParentItem == mParentItem)
7831       {
7832         qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
7833         return false;
7834       }
7835       break;
7836     }
7837   }
7838
7839   // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
7840   if (!mParentAnchorX && mPositionTypeX == ptPlotCoords)
7841     setTypeX(ptAbsolute);
7842
7843   // save pixel position:
7844   QPointF pixelP;
7845   if (keepPixelPosition)
7846     pixelP = pixelPoint();
7847   // unregister at current parent anchor:
7848   if (mParentAnchorX)
7849     mParentAnchorX->removeChildX(this);
7850   // register at new parent anchor:
7851   if (parentAnchor)
7852     parentAnchor->addChildX(this);
7853   mParentAnchorX = parentAnchor;
7854   // restore pixel position under new parent:
7855   if (keepPixelPosition)
7856     setPixelPoint(pixelP);
7857   else
7858     setCoords(0, coords().y());
7859   return true;
7860 }
7861
7862 /*!
7863   This method sets the parent anchor of the Y coordinate to \a parentAnchor.
7864
7865   For a detailed description of what a parent anchor is, see the documentation of \ref setParentAnchor.
7866
7867   \see setParentAnchor, setParentAnchorX
7868 */
7869 bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7870 {
7871   // make sure self is not assigned as parent:
7872   if (parentAnchor == this)
7873   {
7874     qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
7875     return false;
7876   }
7877   // make sure no recursive parent-child-relationships are created:
7878   QCPItemAnchor *currentParent = parentAnchor;
7879   while (currentParent)
7880   {
7881     if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
7882     {
7883       // is a QCPItemPosition, might have further parent, so keep iterating
7884       if (currentParentPos == this)
7885       {
7886         qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
7887         return false;
7888       }
7889       currentParent = currentParentPos->parentAnchorY();
7890     } else
7891     {
7892       // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
7893       // same, to prevent a position being child of an anchor which itself depends on the position,
7894       // because they're both on the same item:
7895       if (currentParent->mParentItem == mParentItem)
7896       {
7897         qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
7898         return false;
7899       }
7900       break;
7901     }
7902   }
7903
7904   // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
7905   if (!mParentAnchorY && mPositionTypeY == ptPlotCoords)
7906     setTypeY(ptAbsolute);
7907
7908   // save pixel position:
7909   QPointF pixelP;
7910   if (keepPixelPosition)
7911     pixelP = pixelPoint();
7912   // unregister at current parent anchor:
7913   if (mParentAnchorY)
7914     mParentAnchorY->removeChildY(this);
7915   // register at new parent anchor:
7916   if (parentAnchor)
7917     parentAnchor->addChildY(this);
7918   mParentAnchorY = parentAnchor;
7919   // restore pixel position under new parent:
7920   if (keepPixelPosition)
7921     setPixelPoint(pixelP);
7922   else
7923     setCoords(coords().x(), 0);
7924   return true;
7925 }
7926
7927 /*!
7928   Sets the coordinates of this QCPItemPosition. What the coordinates mean, is defined by the type
7929   (\ref setType, \ref setTypeX, \ref setTypeY).
7930
7931   For example, if the type is \ref ptAbsolute, \a key and \a value mean the x and y pixel position
7932   on the QCustomPlot surface. In that case the origin (0, 0) is in the top left corner of the
7933   QCustomPlot viewport. If the type is \ref ptPlotCoords, \a key and \a value mean a point in the
7934   plot coordinate system defined by the axes set by \ref setAxes. By default those are the
7935   QCustomPlot's xAxis and yAxis. See the documentation of \ref setType for other available
7936   coordinate types and their meaning.
7937
7938   If different types were configured for X and Y (\ref setTypeX, \ref setTypeY), \a key and \a
7939   value must also be provided in the different coordinate systems. Here, the X type refers to \a
7940   key, and the Y type refers to \a value.
7941
7942   \see setPixelPoint
7943 */
7944 void QCPItemPosition::setCoords(double key, double value)
7945 {
7946   mKey = key;
7947   mValue = value;
7948 }
7949
7950 /*! \overload
7951
7952   Sets the coordinates as a QPointF \a pos where pos.x has the meaning of \a key and pos.y the
7953   meaning of \a value of the \ref setCoords(double key, double value) method.
7954 */
7955 void QCPItemPosition::setCoords(const QPointF &pos)
7956 {
7957   setCoords(pos.x(), pos.y());
7958 }
7959
7960 /*!
7961   Returns the final absolute pixel position of the QCPItemPosition on the QCustomPlot surface. It
7962   includes all effects of type (\ref setType) and possible parent anchors (\ref setParentAnchor).
7963
7964   \see setPixelPoint
7965 */
7966 QPointF QCPItemPosition::pixelPoint() const
7967 {
7968   QPointF result;
7969
7970   // determine X:
7971   switch (mPositionTypeX)
7972   {
7973     case ptAbsolute:
7974     {
7975       result.rx() = mKey;
7976       if (mParentAnchorX)
7977         result.rx() += mParentAnchorX->pixelPoint().x();
7978       break;
7979     }
7980     case ptViewportRatio:
7981     {
7982       result.rx() = mKey*mParentPlot->viewport().width();
7983       if (mParentAnchorX)
7984         result.rx() += mParentAnchorX->pixelPoint().x();
7985       else
7986         result.rx() += mParentPlot->viewport().left();
7987       break;
7988     }
7989     case ptAxisRectRatio:
7990     {
7991       if (mAxisRect)
7992       {
7993         result.rx() = mKey*mAxisRect.data()->width();
7994         if (mParentAnchorX)
7995           result.rx() += mParentAnchorX->pixelPoint().x();
7996         else
7997           result.rx() += mAxisRect.data()->left();
7998       } else
7999         qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
8000       break;
8001     }
8002     case ptPlotCoords:
8003     {
8004       if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
8005         result.rx() = mKeyAxis.data()->coordToPixel(mKey);
8006       else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
8007         result.rx() = mValueAxis.data()->coordToPixel(mValue);
8008       else
8009         qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
8010       break;
8011     }
8012   }
8013
8014   // determine Y:
8015   switch (mPositionTypeY)
8016   {
8017     case ptAbsolute:
8018     {
8019       result.ry() = mValue;
8020       if (mParentAnchorY)
8021         result.ry() += mParentAnchorY->pixelPoint().y();
8022       break;
8023     }
8024     case ptViewportRatio:
8025     {
8026       result.ry() = mValue*mParentPlot->viewport().height();
8027       if (mParentAnchorY)
8028         result.ry() += mParentAnchorY->pixelPoint().y();
8029       else
8030         result.ry() += mParentPlot->viewport().top();
8031       break;
8032     }
8033     case ptAxisRectRatio:
8034     {
8035       if (mAxisRect)
8036       {
8037         result.ry() = mValue*mAxisRect.data()->height();
8038         if (mParentAnchorY)
8039           result.ry() += mParentAnchorY->pixelPoint().y();
8040         else
8041           result.ry() += mAxisRect.data()->top();
8042       } else
8043         qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
8044       break;
8045     }
8046     case ptPlotCoords:
8047     {
8048       if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
8049         result.ry() = mKeyAxis.data()->coordToPixel(mKey);
8050       else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
8051         result.ry() = mValueAxis.data()->coordToPixel(mValue);
8052       else
8053         qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
8054       break;
8055     }
8056   }
8057
8058   return result;
8059 }
8060
8061 /*!
8062   When \ref setType is \ref ptPlotCoords, this function may be used to specify the axes the
8063   coordinates set with \ref setCoords relate to. By default they are set to the initial xAxis and
8064   yAxis of the QCustomPlot.
8065 */
8066 void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis)
8067 {
8068   mKeyAxis = keyAxis;
8069   mValueAxis = valueAxis;
8070 }
8071
8072 /*!
8073   When \ref setType is \ref ptAxisRectRatio, this function may be used to specify the axis rect the
8074   coordinates set with \ref setCoords relate to. By default this is set to the main axis rect of
8075   the QCustomPlot.
8076 */
8077 void QCPItemPosition::setAxisRect(QCPAxisRect *axisRect)
8078 {
8079   mAxisRect = axisRect;
8080 }
8081
8082 /*!
8083   Sets the apparent pixel position. This works no matter what type (\ref setType) this
8084   QCPItemPosition is or what parent-child situation it is in, as coordinates are transformed
8085   appropriately, to make the position finally appear at the specified pixel values.
8086
8087   Only if the type is \ref ptAbsolute and no parent anchor is set, this function's effect is
8088   identical to that of \ref setCoords.
8089
8090   \see pixelPoint, setCoords
8091 */
8092 void QCPItemPosition::setPixelPoint(const QPointF &pixelPoint)
8093 {
8094   double x = pixelPoint.x();
8095   double y = pixelPoint.y();
8096
8097   switch (mPositionTypeX)
8098   {
8099     case ptAbsolute:
8100     {
8101       if (mParentAnchorX)
8102         x -= mParentAnchorX->pixelPoint().x();
8103       break;
8104     }
8105     case ptViewportRatio:
8106     {
8107       if (mParentAnchorX)
8108         x -= mParentAnchorX->pixelPoint().x();
8109       else
8110         x -= mParentPlot->viewport().left();
8111       x /= (double)mParentPlot->viewport().width();
8112       break;
8113     }
8114     case ptAxisRectRatio:
8115     {
8116       if (mAxisRect)
8117       {
8118         if (mParentAnchorX)
8119           x -= mParentAnchorX->pixelPoint().x();
8120         else
8121           x -= mAxisRect.data()->left();
8122         x /= (double)mAxisRect.data()->width();
8123       } else
8124         qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
8125       break;
8126     }
8127     case ptPlotCoords:
8128     {
8129       if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
8130         x = mKeyAxis.data()->pixelToCoord(x);
8131       else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
8132         y = mValueAxis.data()->pixelToCoord(x);
8133       else
8134         qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
8135       break;
8136     }
8137   }
8138
8139   switch (mPositionTypeY)
8140   {
8141     case ptAbsolute:
8142     {
8143       if (mParentAnchorY)
8144         y -= mParentAnchorY->pixelPoint().y();
8145       break;
8146     }
8147     case ptViewportRatio:
8148     {
8149       if (mParentAnchorY)
8150         y -= mParentAnchorY->pixelPoint().y();
8151       else
8152         y -= mParentPlot->viewport().top();
8153       y /= (double)mParentPlot->viewport().height();
8154       break;
8155     }
8156     case ptAxisRectRatio:
8157     {
8158       if (mAxisRect)
8159       {
8160         if (mParentAnchorY)
8161           y -= mParentAnchorY->pixelPoint().y();
8162         else
8163           y -= mAxisRect.data()->top();
8164         y /= (double)mAxisRect.data()->height();
8165       } else
8166         qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
8167       break;
8168     }
8169     case ptPlotCoords:
8170     {
8171       if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
8172         x = mKeyAxis.data()->pixelToCoord(y);
8173       else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
8174         y = mValueAxis.data()->pixelToCoord(y);
8175       else
8176         qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
8177       break;
8178     }
8179   }
8180
8181   setCoords(x, y);
8182 }
8183
8184
8185 ////////////////////////////////////////////////////////////////////////////////////////////////////
8186 //////////////////// QCPAbstractItem
8187 ////////////////////////////////////////////////////////////////////////////////////////////////////
8188
8189 /*! \class QCPAbstractItem
8190   \brief The abstract base class for all items in a plot.
8191
8192   In QCustomPlot, items are supplemental graphical elements that are neither plottables
8193   (QCPAbstractPlottable) nor axes (QCPAxis). While plottables are always tied to two axes and thus
8194   plot coordinates, items can also be placed in absolute coordinates independent of any axes. Each
8195   specific item has at least one QCPItemPosition member which controls the positioning. Some items
8196   are defined by more than one coordinate and thus have two or more QCPItemPosition members (For
8197   example, QCPItemRect has \a topLeft and \a bottomRight).
8198
8199   This abstract base class defines a very basic interface like visibility and clipping. Since this
8200   class is abstract, it can't be instantiated. Use one of the subclasses or create a subclass
8201   yourself to create new items.
8202
8203   The built-in items are:
8204   <table>
8205   <tr><td>QCPItemLine</td><td>A line defined by a start and an end point. May have different ending styles on each side (e.g. arrows).</td></tr>
8206   <tr><td>QCPItemStraightLine</td><td>A straight line defined by a start and a direction point. Unlike QCPItemLine, the straight line is infinitely long and has no endings.</td></tr>
8207   <tr><td>QCPItemCurve</td><td>A curve defined by start, end and two intermediate control points. May have different ending styles on each side (e.g. arrows).</td></tr>
8208   <tr><td>QCPItemRect</td><td>A rectangle</td></tr>
8209   <tr><td>QCPItemEllipse</td><td>An ellipse</td></tr>
8210   <tr><td>QCPItemPixmap</td><td>An arbitrary pixmap</td></tr>
8211   <tr><td>QCPItemText</td><td>A text label</td></tr>
8212   <tr><td>QCPItemBracket</td><td>A bracket which may be used to reference/highlight certain parts in the plot.</td></tr>
8213   <tr><td>QCPItemTracer</td><td>An item that can be attached to a QCPGraph and sticks to its data points, given a key coordinate.</td></tr>
8214   </table>
8215
8216   \section items-clipping Clipping
8217
8218   Items are by default clipped to the main axis rect (they are only visible inside the axis rect).
8219   To make an item visible outside that axis rect, disable clipping via \ref setClipToAxisRect
8220   "setClipToAxisRect(false)".
8221
8222   On the other hand if you want the item to be clipped to a different axis rect, specify it via
8223   \ref setClipAxisRect. This clipAxisRect property of an item is only used for clipping behaviour, and
8224   in principle is independent of the coordinate axes the item might be tied to via its position
8225   members (\ref QCPItemPosition::setAxes). However, it is common that the axis rect for clipping
8226   also contains the axes used for the item positions.
8227
8228   \section items-using Using items
8229
8230   First you instantiate the item you want to use and add it to the plot:
8231   \code
8232   QCPItemLine *line = new QCPItemLine(customPlot);
8233   customPlot->addItem(line);
8234   \endcode
8235   by default, the positions of the item are bound to the x- and y-Axis of the plot. So we can just
8236   set the plot coordinates where the line should start/end:
8237   \code
8238   line->start->setCoords(-0.1, 0.8);
8239   line->end->setCoords(1.1, 0.2);
8240   \endcode
8241   If we don't want the line to be positioned in plot coordinates but a different coordinate system,
8242   e.g. absolute pixel positions on the QCustomPlot surface, we need to change the position type like this:
8243   \code
8244   line->start->setType(QCPItemPosition::ptAbsolute);
8245   line->end->setType(QCPItemPosition::ptAbsolute);
8246   \endcode
8247   Then we can set the coordinates, this time in pixels:
8248   \code
8249   line->start->setCoords(100, 200);
8250   line->end->setCoords(450, 320);
8251   \endcode
8252   and make the line visible on the entire QCustomPlot, by disabling clipping to the axis rect:
8253   \code
8254   line->setClipToAxisRect(false);
8255   \endcode
8256
8257   For more advanced plots, it is even possible to set different types and parent anchors per X/Y
8258   coordinate of an item position, using for example \ref QCPItemPosition::setTypeX or \ref
8259   QCPItemPosition::setParentAnchorX. For details, see the documentation of \ref QCPItemPosition.
8260
8261   \section items-subclassing Creating own items
8262
8263   To create an own item, you implement a subclass of QCPAbstractItem. These are the pure
8264   virtual functions, you must implement:
8265   \li \ref selectTest
8266   \li \ref draw
8267
8268   See the documentation of those functions for what they need to do.
8269
8270   \subsection items-positioning Allowing the item to be positioned
8271
8272   As mentioned, item positions are represented by QCPItemPosition members. Let's assume the new item shall
8273   have only one point as its position (as opposed to two like a rect or multiple like a polygon). You then add
8274   a public member of type QCPItemPosition like so:
8275
8276   \code QCPItemPosition * const myPosition;\endcode
8277
8278   the const makes sure the pointer itself can't be modified from the user of your new item (the QCPItemPosition
8279   instance it points to, can be modified, of course).
8280   The initialization of this pointer is made easy with the \ref createPosition function. Just assign
8281   the return value of this function to each QCPItemPosition in the constructor of your item. \ref createPosition
8282   takes a string which is the name of the position, typically this is identical to the variable name.
8283   For example, the constructor of QCPItemExample could look like this:
8284
8285   \code
8286   QCPItemExample::QCPItemExample(QCustomPlot *parentPlot) :
8287     QCPAbstractItem(parentPlot),
8288     myPosition(createPosition("myPosition"))
8289   {
8290     // other constructor code
8291   }
8292   \endcode
8293
8294   \subsection items-drawing The draw function
8295
8296   To give your item a visual representation, reimplement the \ref draw function and use the passed
8297   QCPPainter to draw the item. You can retrieve the item position in pixel coordinates from the
8298   position member(s) via \ref QCPItemPosition::pixelPoint.
8299
8300   To optimize performance you should calculate a bounding rect first (don't forget to take the pen
8301   width into account), check whether it intersects the \ref clipRect, and only draw the item at all
8302   if this is the case.
8303
8304   \subsection items-selection The selectTest function
8305
8306   Your implementation of the \ref selectTest function may use the helpers \ref distSqrToLine and
8307   \ref rectSelectTest. With these, the implementation of the selection test becomes significantly
8308   simpler for most items. See the documentation of \ref selectTest for what the function parameters
8309   mean and what the function should return.
8310
8311   \subsection anchors Providing anchors
8312
8313   Providing anchors (QCPItemAnchor) starts off like adding a position. First you create a public
8314   member, e.g.
8315
8316   \code QCPItemAnchor * const bottom;\endcode
8317
8318   and create it in the constructor with the \ref createAnchor function, assigning it a name and an
8319   anchor id (an integer enumerating all anchors on the item, you may create an own enum for this).
8320   Since anchors can be placed anywhere, relative to the item's position(s), your item needs to
8321   provide the position of every anchor with the reimplementation of the \ref anchorPixelPoint(int
8322   anchorId) function.
8323
8324   In essence the QCPItemAnchor is merely an intermediary that itself asks your item for the pixel
8325   position when anything attached to the anchor needs to know the coordinates.
8326 */
8327
8328 /* start of documentation of inline functions */
8329
8330 /*! \fn QList<QCPItemPosition*> QCPAbstractItem::positions() const
8331
8332   Returns all positions of the item in a list.
8333
8334   \see anchors, position
8335 */
8336
8337 /*! \fn QList<QCPItemAnchor*> QCPAbstractItem::anchors() const
8338
8339   Returns all anchors of the item in a list. Note that since a position (QCPItemPosition) is always
8340   also an anchor, the list will also contain the positions of this item.
8341
8342   \see positions, anchor
8343 */
8344
8345 /* end of documentation of inline functions */
8346 /* start documentation of pure virtual functions */
8347
8348 /*! \fn void QCPAbstractItem::draw(QCPPainter *painter) = 0
8349   \internal
8350
8351   Draws this item with the provided \a painter.
8352
8353   The cliprect of the provided painter is set to the rect returned by \ref clipRect before this
8354   function is called. The clipRect depends on the clipping settings defined by \ref
8355   setClipToAxisRect and \ref setClipAxisRect.
8356 */
8357
8358 /* end documentation of pure virtual functions */
8359 /* start documentation of signals */
8360
8361 /*! \fn void QCPAbstractItem::selectionChanged(bool selected)
8362   This signal is emitted when the selection state of this item has changed, either by user interaction
8363   or by a direct call to \ref setSelected.
8364 */
8365
8366 /* end documentation of signals */
8367
8368 /*!
8369   Base class constructor which initializes base class members.
8370 */
8371 QCPAbstractItem::QCPAbstractItem(QCustomPlot *parentPlot) :
8372   QCPLayerable(parentPlot),
8373   mClipToAxisRect(false),
8374   mSelectable(true),
8375   mSelected(false)
8376 {
8377   QList<QCPAxisRect*> rects = parentPlot->axisRects();
8378   if (rects.size() > 0)
8379   {
8380     setClipToAxisRect(true);
8381     setClipAxisRect(rects.first());
8382   }
8383 }
8384
8385 QCPAbstractItem::~QCPAbstractItem()
8386 {
8387   // don't delete mPositions because every position is also an anchor and thus in mAnchors
8388   qDeleteAll(mAnchors);
8389 }
8390
8391 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
8392 QCPAxisRect *QCPAbstractItem::clipAxisRect() const
8393 {
8394   return mClipAxisRect.data();
8395 }
8396
8397 /*!
8398   Sets whether the item shall be clipped to an axis rect or whether it shall be visible on the
8399   entire QCustomPlot. The axis rect can be set with \ref setClipAxisRect.
8400
8401   \see setClipAxisRect
8402 */
8403 void QCPAbstractItem::setClipToAxisRect(bool clip)
8404 {
8405   mClipToAxisRect = clip;
8406   if (mClipToAxisRect)
8407     setParentLayerable(mClipAxisRect.data());
8408 }
8409
8410 /*!
8411   Sets the clip axis rect. It defines the rect that will be used to clip the item when \ref
8412   setClipToAxisRect is set to true.
8413
8414   \see setClipToAxisRect
8415 */
8416 void QCPAbstractItem::setClipAxisRect(QCPAxisRect *rect)
8417 {
8418   mClipAxisRect = rect;
8419   if (mClipToAxisRect)
8420     setParentLayerable(mClipAxisRect.data());
8421 }
8422
8423 /*!
8424   Sets whether the user can (de-)select this item by clicking on the QCustomPlot surface.
8425   (When \ref QCustomPlot::setInteractions contains QCustomPlot::iSelectItems.)
8426
8427   However, even when \a selectable was set to false, it is possible to set the selection manually,
8428   by calling \ref setSelected.
8429
8430   \see QCustomPlot::setInteractions, setSelected
8431 */
8432 void QCPAbstractItem::setSelectable(bool selectable)
8433 {
8434   if (mSelectable != selectable)
8435   {
8436     mSelectable = selectable;
8437     emit selectableChanged(mSelectable);
8438   }
8439 }
8440
8441 /*!
8442   Sets whether this item is selected or not. When selected, it might use a different visual
8443   appearance (e.g. pen and brush), this depends on the specific item though.
8444
8445   The entire selection mechanism for items is handled automatically when \ref
8446   QCustomPlot::setInteractions contains QCustomPlot::iSelectItems. You only need to call this
8447   function when you wish to change the selection state manually.
8448
8449   This function can change the selection state even when \ref setSelectable was set to false.
8450
8451   emits the \ref selectionChanged signal when \a selected is different from the previous selection state.
8452
8453   \see setSelectable, selectTest
8454 */
8455 void QCPAbstractItem::setSelected(bool selected)
8456 {
8457   if (mSelected != selected)
8458   {
8459     mSelected = selected;
8460     emit selectionChanged(mSelected);
8461   }
8462 }
8463
8464 /*!
8465   Returns the QCPItemPosition with the specified \a name. If this item doesn't have a position by
8466   that name, returns 0.
8467
8468   This function provides an alternative way to access item positions. Normally, you access
8469   positions direcly by their member pointers (which typically have the same variable name as \a
8470   name).
8471
8472   \see positions, anchor
8473 */
8474 QCPItemPosition *QCPAbstractItem::position(const QString &name) const
8475 {
8476   for (int i=0; i<mPositions.size(); ++i)
8477   {
8478     if (mPositions.at(i)->name() == name)
8479       return mPositions.at(i);
8480   }
8481   qDebug() << Q_FUNC_INFO << "position with name not found:" << name;
8482   return 0;
8483 }
8484
8485 /*!
8486   Returns the QCPItemAnchor with the specified \a name. If this item doesn't have an anchor by
8487   that name, returns 0.
8488
8489   This function provides an alternative way to access item anchors. Normally, you access
8490   anchors direcly by their member pointers (which typically have the same variable name as \a
8491   name).
8492
8493   \see anchors, position
8494 */
8495 QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const
8496 {
8497   for (int i=0; i<mAnchors.size(); ++i)
8498   {
8499     if (mAnchors.at(i)->name() == name)
8500       return mAnchors.at(i);
8501   }
8502   qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name;
8503   return 0;
8504 }
8505
8506 /*!
8507   Returns whether this item has an anchor with the specified \a name.
8508
8509   Note that you can check for positions with this function, too. This is because every position is
8510   also an anchor (QCPItemPosition inherits from QCPItemAnchor).
8511
8512   \see anchor, position
8513 */
8514 bool QCPAbstractItem::hasAnchor(const QString &name) const
8515 {
8516   for (int i=0; i<mAnchors.size(); ++i)
8517   {
8518     if (mAnchors.at(i)->name() == name)
8519       return true;
8520   }
8521   return false;
8522 }
8523
8524 /*! \internal
8525
8526   Returns the rect the visual representation of this item is clipped to. This depends on the
8527   current setting of \ref setClipToAxisRect as well as the axis rect set with \ref setClipAxisRect.
8528
8529   If the item is not clipped to an axis rect, the \ref QCustomPlot::viewport rect is returned.
8530
8531   \see draw
8532 */
8533 QRect QCPAbstractItem::clipRect() const
8534 {
8535   if (mClipToAxisRect && mClipAxisRect)
8536     return mClipAxisRect.data()->rect();
8537   else
8538     return mParentPlot->viewport();
8539 }
8540
8541 /*! \internal
8542
8543   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
8544   before drawing item lines.
8545
8546   This is the antialiasing state the painter passed to the \ref draw method is in by default.
8547
8548   This function takes into account the local setting of the antialiasing flag as well as the
8549   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
8550   QCustomPlot::setNotAntialiasedElements.
8551
8552   \see setAntialiased
8553 */
8554 void QCPAbstractItem::applyDefaultAntialiasingHint(QCPPainter *painter) const
8555 {
8556   applyAntialiasingHint(painter, mAntialiased, QCP::aeItems);
8557 }
8558
8559 /*! \internal
8560
8561   Finds the shortest squared distance of \a point to the line segment defined by \a start and \a
8562   end.
8563
8564   This function may be used to help with the implementation of the \ref selectTest function for
8565   specific items.
8566
8567   \note This function is identical to QCPAbstractPlottable::distSqrToLine
8568
8569   \see rectSelectTest
8570 */
8571 double QCPAbstractItem::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
8572 {
8573   QVector2D a(start);
8574   QVector2D b(end);
8575   QVector2D p(point);
8576   QVector2D v(b-a);
8577
8578   double vLengthSqr = v.lengthSquared();
8579   if (!qFuzzyIsNull(vLengthSqr))
8580   {
8581     double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
8582     if (mu < 0)
8583       return (a-p).lengthSquared();
8584     else if (mu > 1)
8585       return (b-p).lengthSquared();
8586     else
8587       return ((a + mu*v)-p).lengthSquared();
8588   } else
8589     return (a-p).lengthSquared();
8590 }
8591
8592 /*! \internal
8593
8594   A convenience function which returns the selectTest value for a specified \a rect and a specified
8595   click position \a pos. \a filledRect defines whether a click inside the rect should also be
8596   considered a hit or whether only the rect border is sensitive to hits.
8597
8598   This function may be used to help with the implementation of the \ref selectTest function for
8599   specific items.
8600
8601   For example, if your item consists of four rects, call this function four times, once for each
8602   rect, in your \ref selectTest reimplementation. Finally, return the minimum of all four returned
8603   values which were greater or equal to zero. (Because this function may return -1.0 when \a pos
8604   doesn't hit \a rect at all). If all calls returned -1.0, return -1.0, too, because your item
8605   wasn't hit.
8606
8607   \see distSqrToLine
8608 */
8609 double QCPAbstractItem::rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const
8610 {
8611   double result = -1;
8612
8613   // distance to border:
8614   QList<QLineF> lines;
8615   lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight())
8616         << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight());
8617   double minDistSqr = std::numeric_limits<double>::max();
8618   for (int i=0; i<lines.size(); ++i)
8619   {
8620     double distSqr = distSqrToLine(lines.at(i).p1(), lines.at(i).p2(), pos);
8621     if (distSqr < minDistSqr)
8622       minDistSqr = distSqr;
8623   }
8624   result = qSqrt(minDistSqr);
8625
8626   // filled rect, allow click inside to count as hit:
8627   if (filledRect && result > mParentPlot->selectionTolerance()*0.99)
8628   {
8629     if (rect.contains(pos))
8630       result = mParentPlot->selectionTolerance()*0.99;
8631   }
8632   return result;
8633 }
8634
8635 /*! \internal
8636
8637   Returns the pixel position of the anchor with Id \a anchorId. This function must be reimplemented in
8638   item subclasses if they want to provide anchors (QCPItemAnchor).
8639
8640   For example, if the item has two anchors with id 0 and 1, this function takes one of these anchor
8641   ids and returns the respective pixel points of the specified anchor.
8642
8643   \see createAnchor
8644 */
8645 QPointF QCPAbstractItem::anchorPixelPoint(int anchorId) const
8646 {
8647   qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId;
8648   return QPointF();
8649 }
8650
8651 /*! \internal
8652
8653   Creates a QCPItemPosition, registers it with this item and returns a pointer to it. The specified
8654   \a name must be a unique string that is usually identical to the variable name of the position
8655   member (This is needed to provide the name-based \ref position access to positions).
8656
8657   Don't delete positions created by this function manually, as the item will take care of it.
8658
8659   Use this function in the constructor (initialization list) of the specific item subclass to
8660   create each position member. Don't create QCPItemPositions with \b new yourself, because they
8661   won't be registered with the item properly.
8662
8663   \see createAnchor
8664 */
8665 QCPItemPosition *QCPAbstractItem::createPosition(const QString &name)
8666 {
8667   if (hasAnchor(name))
8668     qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
8669   QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name);
8670   mPositions.append(newPosition);
8671   mAnchors.append(newPosition); // every position is also an anchor
8672   newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis);
8673   newPosition->setType(QCPItemPosition::ptPlotCoords);
8674   if (mParentPlot->axisRect())
8675     newPosition->setAxisRect(mParentPlot->axisRect());
8676   newPosition->setCoords(0, 0);
8677   return newPosition;
8678 }
8679
8680 /*! \internal
8681
8682   Creates a QCPItemAnchor, registers it with this item and returns a pointer to it. The specified
8683   \a name must be a unique string that is usually identical to the variable name of the anchor
8684   member (This is needed to provide the name based \ref anchor access to anchors).
8685
8686   The \a anchorId must be a number identifying the created anchor. It is recommended to create an
8687   enum (e.g. "AnchorIndex") for this on each item that uses anchors. This id is used by the anchor
8688   to identify itself when it calls QCPAbstractItem::anchorPixelPoint. That function then returns
8689   the correct pixel coordinates for the passed anchor id.
8690
8691   Don't delete anchors created by this function manually, as the item will take care of it.
8692
8693   Use this function in the constructor (initialization list) of the specific item subclass to
8694   create each anchor member. Don't create QCPItemAnchors with \b new yourself, because then they
8695   won't be registered with the item properly.
8696
8697   \see createPosition
8698 */
8699 QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId)
8700 {
8701   if (hasAnchor(name))
8702     qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
8703   QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId);
8704   mAnchors.append(newAnchor);
8705   return newAnchor;
8706 }
8707
8708 /* inherits documentation from base class */
8709 void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
8710 {
8711   Q_UNUSED(event)
8712   Q_UNUSED(details)
8713   if (mSelectable)
8714   {
8715     bool selBefore = mSelected;
8716     setSelected(additive ? !mSelected : true);
8717     if (selectionStateChanged)
8718       *selectionStateChanged = mSelected != selBefore;
8719   }
8720 }
8721
8722 /* inherits documentation from base class */
8723 void QCPAbstractItem::deselectEvent(bool *selectionStateChanged)
8724 {
8725   if (mSelectable)
8726   {
8727     bool selBefore = mSelected;
8728     setSelected(false);
8729     if (selectionStateChanged)
8730       *selectionStateChanged = mSelected != selBefore;
8731   }
8732 }
8733
8734 /* inherits documentation from base class */
8735 QCP::Interaction QCPAbstractItem::selectionCategory() const
8736 {
8737   return QCP::iSelectItems;
8738 }
8739
8740
8741 /*! \file */
8742
8743
8744
8745 ////////////////////////////////////////////////////////////////////////////////////////////////////
8746 //////////////////// QCustomPlot
8747 ////////////////////////////////////////////////////////////////////////////////////////////////////
8748
8749 /*! \class QCustomPlot
8750
8751   \brief The central class of the library. This is the QWidget which displays the plot and
8752   interacts with the user.
8753
8754   For tutorials on how to use QCustomPlot, see the website\n
8755   http://www.qcustomplot.com/
8756 */
8757
8758 /* start of documentation of inline functions */
8759
8760 /*! \fn QRect QCustomPlot::viewport() const
8761
8762   Returns the viewport rect of this QCustomPlot instance. The viewport is the area the plot is
8763   drawn in, all mechanisms, e.g. margin caluclation take the viewport to be the outer border of the
8764   plot. The viewport normally is the rect() of the QCustomPlot widget, i.e. a rect with top left
8765   (0, 0) and size of the QCustomPlot widget.
8766
8767   Don't confuse the viewport with the axis rect (QCustomPlot::axisRect). An axis rect is typically
8768   an area enclosed by four axes, where the graphs/plottables are drawn in. The viewport is larger
8769   and contains also the axes themselves, their tick numbers, their labels, the plot title etc.
8770
8771   Only when saving to a file (see \ref savePng, \ref savePdf etc.) the viewport is temporarily
8772   modified to allow saving plots with sizes independent of the current widget size.
8773 */
8774
8775 /*! \fn QCPLayoutGrid *QCustomPlot::plotLayout() const
8776
8777   Returns the top level layout of this QCustomPlot instance. It is a \ref QCPLayoutGrid, initially containing just
8778   one cell with the main QCPAxisRect inside.
8779 */
8780
8781 /* end of documentation of inline functions */
8782 /* start of documentation of signals */
8783
8784 /*! \fn void QCustomPlot::mouseDoubleClick(QMouseEvent *event)
8785
8786   This signal is emitted when the QCustomPlot receives a mouse double click event.
8787 */
8788
8789 /*! \fn void QCustomPlot::mousePress(QMouseEvent *event)
8790
8791   This signal is emitted when the QCustomPlot receives a mouse press event.
8792
8793   It is emitted before QCustomPlot handles any other mechanism like range dragging. So a slot
8794   connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeDrag or \ref
8795   QCPAxisRect::setRangeDragAxes.
8796 */
8797
8798 /*! \fn void QCustomPlot::mouseMove(QMouseEvent *event)
8799
8800   This signal is emitted when the QCustomPlot receives a mouse move event.
8801
8802   It is emitted before QCustomPlot handles any other mechanism like range dragging. So a slot
8803   connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeDrag or \ref
8804   QCPAxisRect::setRangeDragAxes.
8805
8806   \warning It is discouraged to change the drag-axes with \ref QCPAxisRect::setRangeDragAxes here,
8807   because the dragging starting point was saved the moment the mouse was pressed. Thus it only has
8808   a meaning for the range drag axes that were set at that moment. If you want to change the drag
8809   axes, consider doing this in the \ref mousePress signal instead.
8810 */
8811
8812 /*! \fn void QCustomPlot::mouseRelease(QMouseEvent *event)
8813
8814   This signal is emitted when the QCustomPlot receives a mouse release event.
8815
8816   It is emitted before QCustomPlot handles any other mechanisms like object selection. So a
8817   slot connected to this signal can still influence the behaviour e.g. with \ref setInteractions or
8818   \ref QCPAbstractPlottable::setSelectable.
8819 */
8820
8821 /*! \fn void QCustomPlot::mouseWheel(QMouseEvent *event)
8822
8823   This signal is emitted when the QCustomPlot receives a mouse wheel event.
8824
8825   It is emitted before QCustomPlot handles any other mechanisms like range zooming. So a slot
8826   connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeZoom, \ref
8827   QCPAxisRect::setRangeZoomAxes or \ref QCPAxisRect::setRangeZoomFactor.
8828 */
8829
8830 /*! \fn void QCustomPlot::plottableClick(QCPAbstractPlottable *plottable, QMouseEvent *event)
8831
8832   This signal is emitted when a plottable is clicked.
8833
8834   \a event is the mouse event that caused the click and \a plottable is the plottable that received
8835   the click.
8836
8837   \see plottableDoubleClick
8838 */
8839
8840 /*! \fn void QCustomPlot::plottableDoubleClick(QCPAbstractPlottable *plottable, QMouseEvent *event)
8841
8842   This signal is emitted when a plottable is double clicked.
8843
8844   \a event is the mouse event that caused the click and \a plottable is the plottable that received
8845   the click.
8846
8847   \see plottableClick
8848 */
8849
8850 /*! \fn void QCustomPlot::itemClick(QCPAbstractItem *item, QMouseEvent *event)
8851
8852   This signal is emitted when an item is clicked.
8853
8854   \a event is the mouse event that caused the click and \a item is the item that received the
8855   click.
8856
8857   \see itemDoubleClick
8858 */
8859
8860 /*! \fn void QCustomPlot::itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event)
8861
8862   This signal is emitted when an item is double clicked.
8863
8864   \a event is the mouse event that caused the click and \a item is the item that received the
8865   click.
8866
8867   \see itemClick
8868 */
8869
8870 /*! \fn void QCustomPlot::axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
8871
8872   This signal is emitted when an axis is clicked.
8873
8874   \a event is the mouse event that caused the click, \a axis is the axis that received the click and
8875   \a part indicates the part of the axis that was clicked.
8876
8877   \see axisDoubleClick
8878 */
8879
8880 /*! \fn void QCustomPlot::axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
8881
8882   This signal is emitted when an axis is double clicked.
8883
8884   \a event is the mouse event that caused the click, \a axis is the axis that received the click and
8885   \a part indicates the part of the axis that was clicked.
8886
8887   \see axisClick
8888 */
8889
8890 /*! \fn void QCustomPlot::legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event)
8891
8892   This signal is emitted when a legend (item) is clicked.
8893
8894   \a event is the mouse event that caused the click, \a legend is the legend that received the
8895   click and \a item is the legend item that received the click. If only the legend and no item is
8896   clicked, \a item is 0. This happens for a click inside the legend padding or the space between
8897   two items.
8898
8899   \see legendDoubleClick
8900 */
8901
8902 /*! \fn void QCustomPlot::legendDoubleClick(QCPLegend *legend,  QCPAbstractLegendItem *item, QMouseEvent *event)
8903
8904   This signal is emitted when a legend (item) is double clicked.
8905
8906   \a event is the mouse event that caused the click, \a legend is the legend that received the
8907   click and \a item is the legend item that received the click. If only the legend and no item is
8908   clicked, \a item is 0. This happens for a click inside the legend padding or the space between
8909   two items.
8910
8911   \see legendClick
8912 */
8913
8914 /*! \fn void QCustomPlot:: titleClick(QMouseEvent *event, QCPPlotTitle *title)
8915
8916   This signal is emitted when a plot title is clicked.
8917
8918   \a event is the mouse event that caused the click and \a title is the plot title that received
8919   the click.
8920
8921   \see titleDoubleClick
8922 */
8923
8924 /*! \fn void QCustomPlot::titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title)
8925
8926   This signal is emitted when a plot title is double clicked.
8927
8928   \a event is the mouse event that caused the click and \a title is the plot title that received
8929   the click.
8930
8931   \see titleClick
8932 */
8933
8934 /*! \fn void QCustomPlot::selectionChangedByUser()
8935
8936   This signal is emitted after the user has changed the selection in the QCustomPlot, e.g. by
8937   clicking. It is not emitted when the selection state of an object has changed programmatically by
8938   a direct call to setSelected() on an object or by calling \ref deselectAll.
8939
8940   In addition to this signal, selectable objects also provide individual signals, for example
8941   QCPAxis::selectionChanged or QCPAbstractPlottable::selectionChanged. Note that those signals are
8942   emitted even if the selection state is changed programmatically.
8943
8944   See the documentation of \ref setInteractions for details about the selection mechanism.
8945
8946   \see selectedPlottables, selectedGraphs, selectedItems, selectedAxes, selectedLegends
8947 */
8948
8949 /*! \fn void QCustomPlot::beforeReplot()
8950
8951   This signal is emitted immediately before a replot takes place (caused by a call to the slot \ref
8952   replot).
8953
8954   It is safe to mutually connect the replot slot with this signal on two QCustomPlots to make them
8955   replot synchronously, it won't cause an infinite recursion.
8956
8957   \see replot, afterReplot
8958 */
8959
8960 /*! \fn void QCustomPlot::afterReplot()
8961
8962   This signal is emitted immediately after a replot has taken place (caused by a call to the slot \ref
8963   replot).
8964
8965   It is safe to mutually connect the replot slot with this signal on two QCustomPlots to make them
8966   replot synchronously, it won't cause an infinite recursion.
8967
8968   \see replot, beforeReplot
8969 */
8970
8971 /* end of documentation of signals */
8972 /* start of documentation of public members */
8973
8974 /*! \var QCPAxis *QCustomPlot::xAxis
8975
8976   A pointer to the primary x Axis (bottom) of the main axis rect of the plot.
8977
8978   QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref
8979   yAxis2) and the \ref legend. They make it very easy working with plots that only have a single
8980   axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the
8981   layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref
8982   QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the
8983   default legend is removed due to manipulation of the layout system (e.g. by removing the main
8984   axis rect), the corresponding pointers become 0.
8985 */
8986
8987 /*! \var QCPAxis *QCustomPlot::yAxis
8988
8989   A pointer to the primary y Axis (left) of the main axis rect of the plot.
8990
8991   QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref
8992   yAxis2) and the \ref legend. They make it very easy working with plots that only have a single
8993   axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the
8994   layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref
8995   QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the
8996   default legend is removed due to manipulation of the layout system (e.g. by removing the main
8997   axis rect), the corresponding pointers become 0.
8998 */
8999
9000 /*! \var QCPAxis *QCustomPlot::xAxis2
9001
9002   A pointer to the secondary x Axis (top) of the main axis rect of the plot. Secondary axes are
9003   invisible by default. Use QCPAxis::setVisible to change this (or use \ref
9004   QCPAxisRect::setupFullAxesBox).
9005
9006   QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref
9007   yAxis2) and the \ref legend. They make it very easy working with plots that only have a single
9008   axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the
9009   layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref
9010   QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the
9011   default legend is removed due to manipulation of the layout system (e.g. by removing the main
9012   axis rect), the corresponding pointers become 0.
9013 */
9014
9015 /*! \var QCPAxis *QCustomPlot::yAxis2
9016
9017   A pointer to the secondary y Axis (right) of the main axis rect of the plot. Secondary axes are
9018   invisible by default. Use QCPAxis::setVisible to change this (or use \ref
9019   QCPAxisRect::setupFullAxesBox).
9020
9021   QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref
9022   yAxis2) and the \ref legend. They make it very easy working with plots that only have a single
9023   axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the
9024   layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref
9025   QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the
9026   default legend is removed due to manipulation of the layout system (e.g. by removing the main
9027   axis rect), the corresponding pointers become 0.
9028 */
9029
9030 /*! \var QCPLegend *QCustomPlot::legend
9031
9032   A pointer to the default legend of the main axis rect. The legend is invisible by default. Use
9033   QCPLegend::setVisible to change this.
9034
9035   QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref
9036   yAxis2) and the \ref legend. They make it very easy working with plots that only have a single
9037   axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the
9038   layout system\endlink to add multiple legends to the plot, use the layout system interface to
9039   access the new legend. For example, legends can be placed inside an axis rect's \ref
9040   QCPAxisRect::insetLayout "inset layout", and must then also be accessed via the inset layout. If
9041   the default legend is removed due to manipulation of the layout system (e.g. by removing the main
9042   axis rect), the corresponding pointer becomes 0.
9043 */
9044
9045 /* end of documentation of public members */
9046
9047 /*!
9048   Constructs a QCustomPlot and sets reasonable default values.
9049 */
9050 QCustomPlot::QCustomPlot(QWidget *parent) :
9051   QWidget(parent),
9052   xAxis(0),
9053   yAxis(0),
9054   xAxis2(0),
9055   yAxis2(0),
9056   legend(0),
9057   mPlotLayout(0),
9058   mAutoAddPlottableToLegend(true),
9059   mAntialiasedElements(QCP::aeNone),
9060   mNotAntialiasedElements(QCP::aeNone),
9061   mInteractions(0),
9062   mSelectionTolerance(8),
9063   mNoAntialiasingOnDrag(false),
9064   mBackgroundBrush(Qt::white, Qt::SolidPattern),
9065   mBackgroundScaled(true),
9066   mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
9067   mCurrentLayer(0),
9068   mPlottingHints(QCP::phCacheLabels|QCP::phForceRepaint),
9069   mMultiSelectModifier(Qt::ControlModifier),
9070   mPaintBuffer(size()),
9071   mMouseEventElement(0),
9072   mReplotting(false)
9073 {
9074   setAttribute(Qt::WA_NoMousePropagation);
9075   setAttribute(Qt::WA_OpaquePaintEvent);
9076   setMouseTracking(true);
9077   QLocale currentLocale = locale();
9078   currentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
9079   setLocale(currentLocale);
9080
9081 #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
9082   QSize pbSize = mPaintBuffer.size();
9083   pbSize *= devicePixelRatio();
9084   mPaintBuffer = QPixmap(pbSize);
9085   mPaintBuffer.setDevicePixelRatio(devicePixelRatio());
9086 #endif
9087
9088   // create initial layers:
9089   mLayers.append(new QCPLayer(this, QLatin1String("background")));
9090   mLayers.append(new QCPLayer(this, QLatin1String("grid")));
9091   mLayers.append(new QCPLayer(this, QLatin1String("main")));
9092   mLayers.append(new QCPLayer(this, QLatin1String("axes")));
9093   mLayers.append(new QCPLayer(this, QLatin1String("legend")));
9094   updateLayerIndices();
9095   setCurrentLayer(QLatin1String("main"));
9096
9097   // create initial layout, axis rect and legend:
9098   mPlotLayout = new QCPLayoutGrid;
9099   mPlotLayout->initializeParentPlot(this);
9100   mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry
9101   mPlotLayout->setLayer(QLatin1String("main"));
9102   QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true);
9103   mPlotLayout->addElement(0, 0, defaultAxisRect);
9104   xAxis = defaultAxisRect->axis(QCPAxis::atBottom);
9105   yAxis = defaultAxisRect->axis(QCPAxis::atLeft);
9106   xAxis2 = defaultAxisRect->axis(QCPAxis::atTop);
9107   yAxis2 = defaultAxisRect->axis(QCPAxis::atRight);
9108   legend = new QCPLegend;
9109   legend->setVisible(false);
9110   defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop);
9111   defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12));
9112
9113   defaultAxisRect->setLayer(QLatin1String("background"));
9114   xAxis->setLayer(QLatin1String("axes"));
9115   yAxis->setLayer(QLatin1String("axes"));
9116   xAxis2->setLayer(QLatin1String("axes"));
9117   yAxis2->setLayer(QLatin1String("axes"));
9118   xAxis->grid()->setLayer(QLatin1String("grid"));
9119   yAxis->grid()->setLayer(QLatin1String("grid"));
9120   xAxis2->grid()->setLayer(QLatin1String("grid"));
9121   yAxis2->grid()->setLayer(QLatin1String("grid"));
9122   legend->setLayer(QLatin1String("legend"));
9123
9124   setViewport(rect()); // needs to be called after mPlotLayout has been created
9125
9126   replot();
9127 }
9128
9129 QCustomPlot::~QCustomPlot()
9130 {
9131   clearPlottables();
9132   clearItems();
9133
9134   if (mPlotLayout)
9135   {
9136     delete mPlotLayout;
9137     mPlotLayout = 0;
9138   }
9139
9140   mCurrentLayer = 0;
9141   qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed
9142   mLayers.clear();
9143 }
9144
9145 /*!
9146   Sets which elements are forcibly drawn antialiased as an \a or combination of QCP::AntialiasedElement.
9147
9148   This overrides the antialiasing settings for whole element groups, normally controlled with the
9149   \a setAntialiasing function on the individual elements. If an element is neither specified in
9150   \ref setAntialiasedElements nor in \ref setNotAntialiasedElements, the antialiasing setting on
9151   each individual element instance is used.
9152
9153   For example, if \a antialiasedElements contains \ref QCP::aePlottables, all plottables will be
9154   drawn antialiased, no matter what the specific QCPAbstractPlottable::setAntialiased value was set
9155   to.
9156
9157   if an element in \a antialiasedElements is already set in \ref setNotAntialiasedElements, it is
9158   removed from there.
9159
9160   \see setNotAntialiasedElements
9161 */
9162 void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements)
9163 {
9164   mAntialiasedElements = antialiasedElements;
9165
9166   // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9167   if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9168     mNotAntialiasedElements |= ~mAntialiasedElements;
9169 }
9170
9171 /*!
9172   Sets whether the specified \a antialiasedElement is forcibly drawn antialiased.
9173
9174   See \ref setAntialiasedElements for details.
9175
9176   \see setNotAntialiasedElement
9177 */
9178 void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled)
9179 {
9180   if (!enabled && mAntialiasedElements.testFlag(antialiasedElement))
9181     mAntialiasedElements &= ~antialiasedElement;
9182   else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement))
9183     mAntialiasedElements |= antialiasedElement;
9184
9185   // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9186   if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9187     mNotAntialiasedElements |= ~mAntialiasedElements;
9188 }
9189
9190 /*!
9191   Sets which elements are forcibly drawn not antialiased as an \a or combination of
9192   QCP::AntialiasedElement.
9193
9194   This overrides the antialiasing settings for whole element groups, normally controlled with the
9195   \a setAntialiasing function on the individual elements. If an element is neither specified in
9196   \ref setAntialiasedElements nor in \ref setNotAntialiasedElements, the antialiasing setting on
9197   each individual element instance is used.
9198
9199   For example, if \a notAntialiasedElements contains \ref QCP::aePlottables, no plottables will be
9200   drawn antialiased, no matter what the specific QCPAbstractPlottable::setAntialiased value was set
9201   to.
9202
9203   if an element in \a notAntialiasedElements is already set in \ref setAntialiasedElements, it is
9204   removed from there.
9205
9206   \see setAntialiasedElements
9207 */
9208 void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements &notAntialiasedElements)
9209 {
9210   mNotAntialiasedElements = notAntialiasedElements;
9211
9212   // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9213   if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9214     mAntialiasedElements |= ~mNotAntialiasedElements;
9215 }
9216
9217 /*!
9218   Sets whether the specified \a notAntialiasedElement is forcibly drawn not antialiased.
9219
9220   See \ref setNotAntialiasedElements for details.
9221
9222   \see setAntialiasedElement
9223 */
9224 void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled)
9225 {
9226   if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement))
9227     mNotAntialiasedElements &= ~notAntialiasedElement;
9228   else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement))
9229     mNotAntialiasedElements |= notAntialiasedElement;
9230
9231   // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9232   if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9233     mAntialiasedElements |= ~mNotAntialiasedElements;
9234 }
9235
9236 /*!
9237   If set to true, adding a plottable (e.g. a graph) to the QCustomPlot automatically also adds the
9238   plottable to the legend (QCustomPlot::legend).
9239
9240   \see addPlottable, addGraph, QCPLegend::addItem
9241 */
9242 void QCustomPlot::setAutoAddPlottableToLegend(bool on)
9243 {
9244   mAutoAddPlottableToLegend = on;
9245 }
9246
9247 /*!
9248   Sets the possible interactions of this QCustomPlot as an or-combination of \ref QCP::Interaction
9249   enums. There are the following types of interactions:
9250
9251   <b>Axis range manipulation</b> is controlled via \ref QCP::iRangeDrag and \ref QCP::iRangeZoom. When the
9252   respective interaction is enabled, the user may drag axes ranges and zoom with the mouse wheel.
9253   For details how to control which axes the user may drag/zoom and in what orientations, see \ref
9254   QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeDragAxes,
9255   \ref QCPAxisRect::setRangeZoomAxes.
9256
9257   <b>Plottable selection</b> is controlled by \ref QCP::iSelectPlottables. If \ref QCP::iSelectPlottables is
9258   set, the user may select plottables (graphs, curves, bars,...) by clicking on them or in their
9259   vicinity (\ref setSelectionTolerance). Whether the user can actually select a plottable can
9260   further be restricted with the \ref QCPAbstractPlottable::setSelectable function on the specific
9261   plottable. To find out whether a specific plottable is selected, call
9262   QCPAbstractPlottable::selected(). To retrieve a list of all currently selected plottables, call
9263   \ref selectedPlottables. If you're only interested in QCPGraphs, you may use the convenience
9264   function \ref selectedGraphs.
9265
9266   <b>Item selection</b> is controlled by \ref QCP::iSelectItems. If \ref QCP::iSelectItems is set, the user
9267   may select items (QCPItemLine, QCPItemText,...) by clicking on them or in their vicinity. To find
9268   out whether a specific item is selected, call QCPAbstractItem::selected(). To retrieve a list of
9269   all currently selected items, call \ref selectedItems.
9270
9271   <b>Axis selection</b> is controlled with \ref QCP::iSelectAxes. If \ref QCP::iSelectAxes is set, the user
9272   may select parts of the axes by clicking on them. What parts exactly (e.g. Axis base line, tick
9273   labels, axis label) are selectable can be controlled via \ref QCPAxis::setSelectableParts for
9274   each axis. To retrieve a list of all axes that currently contain selected parts, call \ref
9275   selectedAxes. Which parts of an axis are selected, can be retrieved with QCPAxis::selectedParts().
9276
9277   <b>Legend selection</b> is controlled with \ref QCP::iSelectLegend. If this is set, the user may
9278   select the legend itself or individual items by clicking on them. What parts exactly are
9279   selectable can be controlled via \ref QCPLegend::setSelectableParts. To find out whether the
9280   legend or any of its child items are selected, check the value of QCPLegend::selectedParts. To
9281   find out which child items are selected, call \ref QCPLegend::selectedItems.
9282
9283   <b>All other selectable elements</b> The selection of all other selectable objects (e.g.
9284   QCPPlotTitle, or your own layerable subclasses) is controlled with \ref QCP::iSelectOther. If set, the
9285   user may select those objects by clicking on them. To find out which are currently selected, you
9286   need to check their selected state explicitly.
9287
9288   If the selection state has changed by user interaction, the \ref selectionChangedByUser signal is
9289   emitted. Each selectable object additionally emits an individual selectionChanged signal whenever
9290   their selection state has changed, i.e. not only by user interaction.
9291
9292   To allow multiple objects to be selected by holding the selection modifier (\ref
9293   setMultiSelectModifier), set the flag \ref QCP::iMultiSelect.
9294
9295   \note In addition to the selection mechanism presented here, QCustomPlot always emits
9296   corresponding signals, when an object is clicked or double clicked. see \ref plottableClick and
9297   \ref plottableDoubleClick for example.
9298
9299   \see setInteraction, setSelectionTolerance
9300 */
9301 void QCustomPlot::setInteractions(const QCP::Interactions &interactions)
9302 {
9303   mInteractions = interactions;
9304 }
9305
9306 /*!
9307   Sets the single \a interaction of this QCustomPlot to \a enabled.
9308
9309   For details about the interaction system, see \ref setInteractions.
9310
9311   \see setInteractions
9312 */
9313 void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled)
9314 {
9315   if (!enabled && mInteractions.testFlag(interaction))
9316     mInteractions &= ~interaction;
9317   else if (enabled && !mInteractions.testFlag(interaction))
9318     mInteractions |= interaction;
9319 }
9320
9321 /*!
9322   Sets the tolerance that is used to decide whether a click selects an object (e.g. a plottable) or
9323   not.
9324
9325   If the user clicks in the vicinity of the line of e.g. a QCPGraph, it's only regarded as a
9326   potential selection when the minimum distance between the click position and the graph line is
9327   smaller than \a pixels. Objects that are defined by an area (e.g. QCPBars) only react to clicks
9328   directly inside the area and ignore this selection tolerance. In other words, it only has meaning
9329   for parts of objects that are too thin to exactly hit with a click and thus need such a
9330   tolerance.
9331
9332   \see setInteractions, QCPLayerable::selectTest
9333 */
9334 void QCustomPlot::setSelectionTolerance(int pixels)
9335 {
9336   mSelectionTolerance = pixels;
9337 }
9338
9339 /*!
9340   Sets whether antialiasing is disabled for this QCustomPlot while the user is dragging axes
9341   ranges. If many objects, especially plottables, are drawn antialiased, this greatly improves
9342   performance during dragging. Thus it creates a more responsive user experience. As soon as the
9343   user stops dragging, the last replot is done with normal antialiasing, to restore high image
9344   quality.
9345
9346   \see setAntialiasedElements, setNotAntialiasedElements
9347 */
9348 void QCustomPlot::setNoAntialiasingOnDrag(bool enabled)
9349 {
9350   mNoAntialiasingOnDrag = enabled;
9351 }
9352
9353 /*!
9354   Sets the plotting hints for this QCustomPlot instance as an \a or combination of QCP::PlottingHint.
9355
9356   \see setPlottingHint
9357 */
9358 void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints)
9359 {
9360   mPlottingHints = hints;
9361 }
9362
9363 /*!
9364   Sets the specified plotting \a hint to \a enabled.
9365
9366   \see setPlottingHints
9367 */
9368 void QCustomPlot::setPlottingHint(QCP::PlottingHint hint, bool enabled)
9369 {
9370   QCP::PlottingHints newHints = mPlottingHints;
9371   if (!enabled)
9372     newHints &= ~hint;
9373   else
9374     newHints |= hint;
9375
9376   if (newHints != mPlottingHints)
9377     setPlottingHints(newHints);
9378 }
9379
9380 /*!
9381   Sets the keyboard modifier that will be recognized as multi-select-modifier.
9382
9383   If \ref QCP::iMultiSelect is specified in \ref setInteractions, the user may select multiple objects
9384   by clicking on them one after the other while holding down \a modifier.
9385
9386   By default the multi-select-modifier is set to Qt::ControlModifier.
9387
9388   \see setInteractions
9389 */
9390 void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier)
9391 {
9392   mMultiSelectModifier = modifier;
9393 }
9394
9395 /*!
9396   Sets the viewport of this QCustomPlot. The Viewport is the area that the top level layout
9397   (QCustomPlot::plotLayout()) uses as its rect. Normally, the viewport is the entire widget rect.
9398
9399   This function is used to allow arbitrary size exports with \ref toPixmap, \ref savePng, \ref
9400   savePdf, etc. by temporarily changing the viewport size.
9401 */
9402 void QCustomPlot::setViewport(const QRect &rect)
9403 {
9404   mViewport = rect;
9405   if (mPlotLayout)
9406     mPlotLayout->setOuterRect(mViewport);
9407 }
9408
9409 /*!
9410   Sets \a pm as the viewport background pixmap (see \ref setViewport). The pixmap is always drawn
9411   below all other objects in the plot.
9412
9413   For cases where the provided pixmap doesn't have the same size as the viewport, scaling can be
9414   enabled with \ref setBackgroundScaled and the scaling mode (whether and how the aspect ratio is
9415   preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call,
9416   consider using the overloaded version of this function.
9417
9418   If a background brush was set with \ref setBackground(const QBrush &brush), the viewport will
9419   first be filled with that brush, before drawing the background pixmap. This can be useful for
9420   background pixmaps with translucent areas.
9421
9422   \see setBackgroundScaled, setBackgroundScaledMode
9423 */
9424 void QCustomPlot::setBackground(const QPixmap &pm)
9425 {
9426   mBackgroundPixmap = pm;
9427   mScaledBackgroundPixmap = QPixmap();
9428 }
9429
9430 /*!
9431   Sets the background brush of the viewport (see \ref setViewport).
9432
9433   Before drawing everything else, the background is filled with \a brush. If a background pixmap
9434   was set with \ref setBackground(const QPixmap &pm), this brush will be used to fill the viewport
9435   before the background pixmap is drawn. This can be useful for background pixmaps with translucent
9436   areas.
9437
9438   Set \a brush to Qt::NoBrush or Qt::Transparent to leave background transparent. This can be
9439   useful for exporting to image formats which support transparency, e.g. \ref savePng.
9440
9441   \see setBackgroundScaled, setBackgroundScaledMode
9442 */
9443 void QCustomPlot::setBackground(const QBrush &brush)
9444 {
9445   mBackgroundBrush = brush;
9446 }
9447
9448 /*! \overload
9449
9450   Allows setting the background pixmap of the viewport, whether it shall be scaled and how it
9451   shall be scaled in one call.
9452
9453   \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode
9454 */
9455 void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
9456 {
9457   mBackgroundPixmap = pm;
9458   mScaledBackgroundPixmap = QPixmap();
9459   mBackgroundScaled = scaled;
9460   mBackgroundScaledMode = mode;
9461 }
9462
9463 /*!
9464   Sets whether the viewport background pixmap shall be scaled to fit the viewport. If \a scaled is
9465   set to true, control whether and how the aspect ratio of the original pixmap is preserved with
9466   \ref setBackgroundScaledMode.
9467
9468   Note that the scaled version of the original pixmap is buffered, so there is no performance
9469   penalty on replots. (Except when the viewport dimensions are changed continuously.)
9470
9471   \see setBackground, setBackgroundScaledMode
9472 */
9473 void QCustomPlot::setBackgroundScaled(bool scaled)
9474 {
9475   mBackgroundScaled = scaled;
9476 }
9477
9478 /*!
9479   If scaling of the viewport background pixmap is enabled (\ref setBackgroundScaled), use this
9480   function to define whether and how the aspect ratio of the original pixmap is preserved.
9481
9482   \see setBackground, setBackgroundScaled
9483 */
9484 void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode)
9485 {
9486   mBackgroundScaledMode = mode;
9487 }
9488
9489 /*!
9490   Returns the plottable with \a index. If the index is invalid, returns 0.
9491
9492   There is an overloaded version of this function with no parameter which returns the last added
9493   plottable, see QCustomPlot::plottable()
9494
9495   \see plottableCount, addPlottable
9496 */
9497 QCPAbstractPlottable *QCustomPlot::plottable(int index)
9498 {
9499   if (index >= 0 && index < mPlottables.size())
9500   {
9501     return mPlottables.at(index);
9502   } else
9503   {
9504     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9505     return 0;
9506   }
9507 }
9508
9509 /*! \overload
9510
9511   Returns the last plottable that was added with \ref addPlottable. If there are no plottables in
9512   the plot, returns 0.
9513
9514   \see plottableCount, addPlottable
9515 */
9516 QCPAbstractPlottable *QCustomPlot::plottable()
9517 {
9518   if (!mPlottables.isEmpty())
9519   {
9520     return mPlottables.last();
9521   } else
9522     return 0;
9523 }
9524
9525 /*!
9526   Adds the specified plottable to the plot and, if \ref setAutoAddPlottableToLegend is enabled, to
9527   the legend (QCustomPlot::legend). QCustomPlot takes ownership of the plottable.
9528
9529   Returns true on success, i.e. when \a plottable isn't already in the plot and the parent plot of
9530   \a plottable is this QCustomPlot (the latter is controlled by what axes were passed in the
9531   plottable's constructor).
9532
9533   \see plottable, plottableCount, removePlottable, clearPlottables
9534 */
9535 bool QCustomPlot::addPlottable(QCPAbstractPlottable *plottable)
9536 {
9537   if (mPlottables.contains(plottable))
9538   {
9539     qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast<quintptr>(plottable);
9540     return false;
9541   }
9542   if (plottable->parentPlot() != this)
9543   {
9544     qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(plottable);
9545     return false;
9546   }
9547
9548   mPlottables.append(plottable);
9549   // possibly add plottable to legend:
9550   if (mAutoAddPlottableToLegend)
9551     plottable->addToLegend();
9552   // special handling for QCPGraphs to maintain the simple graph interface:
9553   if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
9554     mGraphs.append(graph);
9555   if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor)
9556     plottable->setLayer(currentLayer());
9557   return true;
9558 }
9559
9560 /*!
9561   Removes the specified plottable from the plot and, if necessary, from the legend (QCustomPlot::legend).
9562
9563   Returns true on success.
9564
9565   \see addPlottable, clearPlottables
9566 */
9567 bool QCustomPlot::removePlottable(QCPAbstractPlottable *plottable)
9568 {
9569   if (!mPlottables.contains(plottable))
9570   {
9571     qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast<quintptr>(plottable);
9572     return false;
9573   }
9574
9575   // remove plottable from legend:
9576   plottable->removeFromLegend();
9577   // special handling for QCPGraphs to maintain the simple graph interface:
9578   if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
9579     mGraphs.removeOne(graph);
9580   // remove plottable:
9581   delete plottable;
9582   mPlottables.removeOne(plottable);
9583   return true;
9584 }
9585
9586 /*! \overload
9587
9588   Removes the plottable by its \a index.
9589 */
9590 bool QCustomPlot::removePlottable(int index)
9591 {
9592   if (index >= 0 && index < mPlottables.size())
9593     return removePlottable(mPlottables[index]);
9594   else
9595   {
9596     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9597     return false;
9598   }
9599 }
9600
9601 /*!
9602   Removes all plottables from the plot (and the QCustomPlot::legend, if necessary).
9603
9604   Returns the number of plottables removed.
9605
9606   \see removePlottable
9607 */
9608 int QCustomPlot::clearPlottables()
9609 {
9610   int c = mPlottables.size();
9611   for (int i=c-1; i >= 0; --i)
9612     removePlottable(mPlottables[i]);
9613   return c;
9614 }
9615
9616 /*!
9617   Returns the number of currently existing plottables in the plot
9618
9619   \see plottable, addPlottable
9620 */
9621 int QCustomPlot::plottableCount() const
9622 {
9623   return mPlottables.size();
9624 }
9625
9626 /*!
9627   Returns a list of the selected plottables. If no plottables are currently selected, the list is empty.
9628
9629   There is a convenience function if you're only interested in selected graphs, see \ref selectedGraphs.
9630
9631   \see setInteractions, QCPAbstractPlottable::setSelectable, QCPAbstractPlottable::setSelected
9632 */
9633 QList<QCPAbstractPlottable*> QCustomPlot::selectedPlottables() const
9634 {
9635   QList<QCPAbstractPlottable*> result;
9636   foreach (QCPAbstractPlottable *plottable, mPlottables)
9637   {
9638     if (plottable->selected())
9639       result.append(plottable);
9640   }
9641   return result;
9642 }
9643
9644 /*!
9645   Returns the plottable at the pixel position \a pos. Plottables that only consist of single lines
9646   (like graphs) have a tolerance band around them, see \ref setSelectionTolerance. If multiple
9647   plottables come into consideration, the one closest to \a pos is returned.
9648
9649   If \a onlySelectable is true, only plottables that are selectable
9650   (QCPAbstractPlottable::setSelectable) are considered.
9651
9652   If there is no plottable at \a pos, the return value is 0.
9653
9654   \see itemAt, layoutElementAt
9655 */
9656 QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable) const
9657 {
9658   QCPAbstractPlottable *resultPlottable = 0;
9659   double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
9660
9661   foreach (QCPAbstractPlottable *plottable, mPlottables)
9662   {
9663     if (onlySelectable && !plottable->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPabstractPlottable::selectable
9664       continue;
9665     if ((plottable->keyAxis()->axisRect()->rect() & plottable->valueAxis()->axisRect()->rect()).contains(pos.toPoint())) // only consider clicks inside the rect that is spanned by the plottable's key/value axes
9666     {
9667       double currentDistance = plottable->selectTest(pos, false);
9668       if (currentDistance >= 0 && currentDistance < resultDistance)
9669       {
9670         resultPlottable = plottable;
9671         resultDistance = currentDistance;
9672       }
9673     }
9674   }
9675
9676   return resultPlottable;
9677 }
9678
9679 /*!
9680   Returns whether this QCustomPlot instance contains the \a plottable.
9681
9682   \see addPlottable
9683 */
9684 bool QCustomPlot::hasPlottable(QCPAbstractPlottable *plottable) const
9685 {
9686   return mPlottables.contains(plottable);
9687 }
9688
9689 /*!
9690   Returns the graph with \a index. If the index is invalid, returns 0.
9691
9692   There is an overloaded version of this function with no parameter which returns the last created
9693   graph, see QCustomPlot::graph()
9694
9695   \see graphCount, addGraph
9696 */
9697 QCPGraph *QCustomPlot::graph(int index) const
9698 {
9699   if (index >= 0 && index < mGraphs.size())
9700   {
9701     return mGraphs.at(index);
9702   } else
9703   {
9704     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9705     return 0;
9706   }
9707 }
9708
9709 /*! \overload
9710
9711   Returns the last graph, that was created with \ref addGraph. If there are no graphs in the plot,
9712   returns 0.
9713
9714   \see graphCount, addGraph
9715 */
9716 QCPGraph *QCustomPlot::graph() const
9717 {
9718   if (!mGraphs.isEmpty())
9719   {
9720     return mGraphs.last();
9721   } else
9722     return 0;
9723 }
9724
9725 /*!
9726   Creates a new graph inside the plot. If \a keyAxis and \a valueAxis are left unspecified (0), the
9727   bottom (xAxis) is used as key and the left (yAxis) is used as value axis. If specified, \a
9728   keyAxis and \a valueAxis must reside in this QCustomPlot.
9729
9730   \a keyAxis will be used as key axis (typically "x") and \a valueAxis as value axis (typically
9731   "y") for the graph.
9732
9733   Returns a pointer to the newly created graph, or 0 if adding the graph failed.
9734
9735   \see graph, graphCount, removeGraph, clearGraphs
9736 */
9737 QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis)
9738 {
9739   if (!keyAxis) keyAxis = xAxis;
9740   if (!valueAxis) valueAxis = yAxis;
9741   if (!keyAxis || !valueAxis)
9742   {
9743     qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
9744     return 0;
9745   }
9746   if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this)
9747   {
9748     qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
9749     return 0;
9750   }
9751
9752   QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis);
9753   if (addPlottable(newGraph))
9754   {
9755     newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size()));
9756     return newGraph;
9757   } else
9758   {
9759     delete newGraph;
9760     return 0;
9761   }
9762 }
9763
9764 /*!
9765   Removes the specified \a graph from the plot and, if necessary, from the QCustomPlot::legend. If
9766   any other graphs in the plot have a channel fill set towards the removed graph, the channel fill
9767   property of those graphs is reset to zero (no channel fill).
9768
9769   Returns true on success.
9770
9771   \see clearGraphs
9772 */
9773 bool QCustomPlot::removeGraph(QCPGraph *graph)
9774 {
9775   return removePlottable(graph);
9776 }
9777
9778 /*! \overload
9779
9780   Removes the graph by its \a index.
9781 */
9782 bool QCustomPlot::removeGraph(int index)
9783 {
9784   if (index >= 0 && index < mGraphs.size())
9785     return removeGraph(mGraphs[index]);
9786   else
9787     return false;
9788 }
9789
9790 /*!
9791   Removes all graphs from the plot (and the QCustomPlot::legend, if necessary).
9792
9793   Returns the number of graphs removed.
9794
9795   \see removeGraph
9796 */
9797 int QCustomPlot::clearGraphs()
9798 {
9799   int c = mGraphs.size();
9800   for (int i=c-1; i >= 0; --i)
9801     removeGraph(mGraphs[i]);
9802   return c;
9803 }
9804
9805 /*!
9806   Returns the number of currently existing graphs in the plot
9807
9808   \see graph, addGraph
9809 */
9810 int QCustomPlot::graphCount() const
9811 {
9812   return mGraphs.size();
9813 }
9814
9815 /*!
9816   Returns a list of the selected graphs. If no graphs are currently selected, the list is empty.
9817
9818   If you are not only interested in selected graphs but other plottables like QCPCurve, QCPBars,
9819   etc., use \ref selectedPlottables.
9820
9821   \see setInteractions, selectedPlottables, QCPAbstractPlottable::setSelectable, QCPAbstractPlottable::setSelected
9822 */
9823 QList<QCPGraph*> QCustomPlot::selectedGraphs() const
9824 {
9825   QList<QCPGraph*> result;
9826   foreach (QCPGraph *graph, mGraphs)
9827   {
9828     if (graph->selected())
9829       result.append(graph);
9830   }
9831   return result;
9832 }
9833
9834 /*!
9835   Returns the item with \a index. If the index is invalid, returns 0.
9836
9837   There is an overloaded version of this function with no parameter which returns the last added
9838   item, see QCustomPlot::item()
9839
9840   \see itemCount, addItem
9841 */
9842 QCPAbstractItem *QCustomPlot::item(int index) const
9843 {
9844   if (index >= 0 && index < mItems.size())
9845   {
9846     return mItems.at(index);
9847   } else
9848   {
9849     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9850     return 0;
9851   }
9852 }
9853
9854 /*! \overload
9855
9856   Returns the last item, that was added with \ref addItem. If there are no items in the plot,
9857   returns 0.
9858
9859   \see itemCount, addItem
9860 */
9861 QCPAbstractItem *QCustomPlot::item() const
9862 {
9863   if (!mItems.isEmpty())
9864   {
9865     return mItems.last();
9866   } else
9867     return 0;
9868 }
9869
9870 /*!
9871   Adds the specified item to the plot. QCustomPlot takes ownership of the item.
9872
9873   Returns true on success, i.e. when \a item wasn't already in the plot and the parent plot of \a
9874   item is this QCustomPlot.
9875
9876   \see item, itemCount, removeItem, clearItems
9877 */
9878 bool QCustomPlot::addItem(QCPAbstractItem *item)
9879 {
9880   if (!mItems.contains(item) && item->parentPlot() == this)
9881   {
9882     mItems.append(item);
9883     return true;
9884   } else
9885   {
9886     qDebug() << Q_FUNC_INFO << "item either already in list or not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(item);
9887     return false;
9888   }
9889 }
9890
9891 /*!
9892   Removes the specified item from the plot.
9893
9894   Returns true on success.
9895
9896   \see addItem, clearItems
9897 */
9898 bool QCustomPlot::removeItem(QCPAbstractItem *item)
9899 {
9900   if (mItems.contains(item))
9901   {
9902     delete item;
9903     mItems.removeOne(item);
9904     return true;
9905   } else
9906   {
9907     qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast<quintptr>(item);
9908     return false;
9909   }
9910 }
9911
9912 /*! \overload
9913
9914   Removes the item by its \a index.
9915 */
9916 bool QCustomPlot::removeItem(int index)
9917 {
9918   if (index >= 0 && index < mItems.size())
9919     return removeItem(mItems[index]);
9920   else
9921   {
9922     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9923     return false;
9924   }
9925 }
9926
9927 /*!
9928   Removes all items from the plot.
9929
9930   Returns the number of items removed.
9931
9932   \see removeItem
9933 */
9934 int QCustomPlot::clearItems()
9935 {
9936   int c = mItems.size();
9937   for (int i=c-1; i >= 0; --i)
9938     removeItem(mItems[i]);
9939   return c;
9940 }
9941
9942 /*!
9943   Returns the number of currently existing items in the plot
9944
9945   \see item, addItem
9946 */
9947 int QCustomPlot::itemCount() const
9948 {
9949   return mItems.size();
9950 }
9951
9952 /*!
9953   Returns a list of the selected items. If no items are currently selected, the list is empty.
9954
9955   \see setInteractions, QCPAbstractItem::setSelectable, QCPAbstractItem::setSelected
9956 */
9957 QList<QCPAbstractItem*> QCustomPlot::selectedItems() const
9958 {
9959   QList<QCPAbstractItem*> result;
9960   foreach (QCPAbstractItem *item, mItems)
9961   {
9962     if (item->selected())
9963       result.append(item);
9964   }
9965   return result;
9966 }
9967
9968 /*!
9969   Returns the item at the pixel position \a pos. Items that only consist of single lines (e.g. \ref
9970   QCPItemLine or \ref QCPItemCurve) have a tolerance band around them, see \ref
9971   setSelectionTolerance. If multiple items come into consideration, the one closest to \a pos is
9972   returned.
9973
9974   If \a onlySelectable is true, only items that are selectable (QCPAbstractItem::setSelectable) are
9975   considered.
9976
9977   If there is no item at \a pos, the return value is 0.
9978
9979   \see plottableAt, layoutElementAt
9980 */
9981 QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const
9982 {
9983   QCPAbstractItem *resultItem = 0;
9984   double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
9985
9986   foreach (QCPAbstractItem *item, mItems)
9987   {
9988     if (onlySelectable && !item->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable
9989       continue;
9990     if (!item->clipToAxisRect() || item->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it
9991     {
9992       double currentDistance = item->selectTest(pos, false);
9993       if (currentDistance >= 0 && currentDistance < resultDistance)
9994       {
9995         resultItem = item;
9996         resultDistance = currentDistance;
9997       }
9998     }
9999   }
10000
10001   return resultItem;
10002 }
10003
10004 /*!
10005   Returns whether this QCustomPlot contains the \a item.
10006
10007   \see addItem
10008 */
10009 bool QCustomPlot::hasItem(QCPAbstractItem *item) const
10010 {
10011   return mItems.contains(item);
10012 }
10013
10014 /*!
10015   Returns the layer with the specified \a name. If there is no layer with the specified name, 0 is
10016   returned.
10017
10018   Layer names are case-sensitive.
10019
10020   \see addLayer, moveLayer, removeLayer
10021 */
10022 QCPLayer *QCustomPlot::layer(const QString &name) const
10023 {
10024   foreach (QCPLayer *layer, mLayers)
10025   {
10026     if (layer->name() == name)
10027       return layer;
10028   }
10029   return 0;
10030 }
10031
10032 /*! \overload
10033
10034   Returns the layer by \a index. If the index is invalid, 0 is returned.
10035
10036   \see addLayer, moveLayer, removeLayer
10037 */
10038 QCPLayer *QCustomPlot::layer(int index) const
10039 {
10040   if (index >= 0 && index < mLayers.size())
10041   {
10042     return mLayers.at(index);
10043   } else
10044   {
10045     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
10046     return 0;
10047   }
10048 }
10049
10050 /*!
10051   Returns the layer that is set as current layer (see \ref setCurrentLayer).
10052 */
10053 QCPLayer *QCustomPlot::currentLayer() const
10054 {
10055   return mCurrentLayer;
10056 }
10057
10058 /*!
10059   Sets the layer with the specified \a name to be the current layer. All layerables (\ref
10060   QCPLayerable), e.g. plottables and items, are created on the current layer.
10061
10062   Returns true on success, i.e. if there is a layer with the specified \a name in the QCustomPlot.
10063
10064   Layer names are case-sensitive.
10065
10066   \see addLayer, moveLayer, removeLayer, QCPLayerable::setLayer
10067 */
10068 bool QCustomPlot::setCurrentLayer(const QString &name)
10069 {
10070   if (QCPLayer *newCurrentLayer = layer(name))
10071   {
10072     return setCurrentLayer(newCurrentLayer);
10073   } else
10074   {
10075     qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name;
10076     return false;
10077   }
10078 }
10079
10080 /*! \overload
10081
10082   Sets the provided \a layer to be the current layer.
10083
10084   Returns true on success, i.e. when \a layer is a valid layer in the QCustomPlot.
10085
10086   \see addLayer, moveLayer, removeLayer
10087 */
10088 bool QCustomPlot::setCurrentLayer(QCPLayer *layer)
10089 {
10090   if (!mLayers.contains(layer))
10091   {
10092     qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10093     return false;
10094   }
10095
10096   mCurrentLayer = layer;
10097   return true;
10098 }
10099
10100 /*!
10101   Returns the number of currently existing layers in the plot
10102
10103   \see layer, addLayer
10104 */
10105 int QCustomPlot::layerCount() const
10106 {
10107   return mLayers.size();
10108 }
10109
10110 /*!
10111   Adds a new layer to this QCustomPlot instance. The new layer will have the name \a name, which
10112   must be unique. Depending on \a insertMode, it is positioned either below or above \a otherLayer.
10113
10114   Returns true on success, i.e. if there is no other layer named \a name and \a otherLayer is a
10115   valid layer inside this QCustomPlot.
10116
10117   If \a otherLayer is 0, the highest layer in the QCustomPlot will be used.
10118
10119   For an explanation of what layers are in QCustomPlot, see the documentation of \ref QCPLayer.
10120
10121   \see layer, moveLayer, removeLayer
10122 */
10123 bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
10124 {
10125   if (!otherLayer)
10126     otherLayer = mLayers.last();
10127   if (!mLayers.contains(otherLayer))
10128   {
10129     qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
10130     return false;
10131   }
10132   if (layer(name))
10133   {
10134     qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name;
10135     return false;
10136   }
10137
10138   QCPLayer *newLayer = new QCPLayer(this, name);
10139   mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer);
10140   updateLayerIndices();
10141   return true;
10142 }
10143
10144 /*!
10145   Removes the specified \a layer and returns true on success.
10146
10147   All layerables (e.g. plottables and items) on the removed layer will be moved to the layer below
10148   \a layer. If \a layer is the bottom layer, the layerables are moved to the layer above. In both
10149   cases, the total rendering order of all layerables in the QCustomPlot is preserved.
10150
10151   If \a layer is the current layer (\ref setCurrentLayer), the layer below (or above, if bottom
10152   layer) becomes the new current layer.
10153
10154   It is not possible to remove the last layer of the plot.
10155
10156   \see layer, addLayer, moveLayer
10157 */
10158 bool QCustomPlot::removeLayer(QCPLayer *layer)
10159 {
10160   if (!mLayers.contains(layer))
10161   {
10162     qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10163     return false;
10164   }
10165   if (mLayers.size() < 2)
10166   {
10167     qDebug() << Q_FUNC_INFO << "can't remove last layer";
10168     return false;
10169   }
10170
10171   // append all children of this layer to layer below (if this is lowest layer, prepend to layer above)
10172   int removedIndex = layer->index();
10173   bool isFirstLayer = removedIndex==0;
10174   QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1);
10175   QList<QCPLayerable*> children = layer->children();
10176   if (isFirstLayer) // prepend in reverse order (so order relative to each other stays the same)
10177   {
10178     for (int i=children.size()-1; i>=0; --i)
10179       children.at(i)->moveToLayer(targetLayer, true);
10180   } else  // append normally
10181   {
10182     for (int i=0; i<children.size(); ++i)
10183       children.at(i)->moveToLayer(targetLayer, false);
10184   }
10185   // if removed layer is current layer, change current layer to layer below/above:
10186   if (layer == mCurrentLayer)
10187     setCurrentLayer(targetLayer);
10188   // remove layer:
10189   delete layer;
10190   mLayers.removeOne(layer);
10191   updateLayerIndices();
10192   return true;
10193 }
10194
10195 /*!
10196   Moves the specified \a layer either above or below \a otherLayer. Whether it's placed above or
10197   below is controlled with \a insertMode.
10198
10199   Returns true on success, i.e. when both \a layer and \a otherLayer are valid layers in the
10200   QCustomPlot.
10201
10202   \see layer, addLayer, moveLayer
10203 */
10204 bool QCustomPlot::moveLayer(QCPLayer *layer, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
10205 {
10206   if (!mLayers.contains(layer))
10207   {
10208     qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10209     return false;
10210   }
10211   if (!mLayers.contains(otherLayer))
10212   {
10213     qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
10214     return false;
10215   }
10216
10217   mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0));
10218   updateLayerIndices();
10219   return true;
10220 }
10221
10222 /*!
10223   Returns the number of axis rects in the plot.
10224
10225   All axis rects can be accessed via QCustomPlot::axisRect().
10226
10227   Initially, only one axis rect exists in the plot.
10228
10229   \see axisRect, axisRects
10230 */
10231 int QCustomPlot::axisRectCount() const
10232 {
10233   return axisRects().size();
10234 }
10235
10236 /*!
10237   Returns the axis rect with \a index.
10238
10239   Initially, only one axis rect (with index 0) exists in the plot. If multiple axis rects were
10240   added, all of them may be accessed with this function in a linear fashion (even when they are
10241   nested in a layout hierarchy or inside other axis rects via QCPAxisRect::insetLayout).
10242
10243   \see axisRectCount, axisRects
10244 */
10245 QCPAxisRect *QCustomPlot::axisRect(int index) const
10246 {
10247   const QList<QCPAxisRect*> rectList = axisRects();
10248   if (index >= 0 && index < rectList.size())
10249   {
10250     return rectList.at(index);
10251   } else
10252   {
10253     qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index;
10254     return 0;
10255   }
10256 }
10257
10258 /*!
10259   Returns all axis rects in the plot.
10260
10261   \see axisRectCount, axisRect
10262 */
10263 QList<QCPAxisRect*> QCustomPlot::axisRects() const
10264 {
10265   QList<QCPAxisRect*> result;
10266   QStack<QCPLayoutElement*> elementStack;
10267   if (mPlotLayout)
10268     elementStack.push(mPlotLayout);
10269
10270   while (!elementStack.isEmpty())
10271   {
10272     foreach (QCPLayoutElement *element, elementStack.pop()->elements(false))
10273     {
10274       if (element)
10275       {
10276         elementStack.push(element);
10277         if (QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(element))
10278           result.append(ar);
10279       }
10280     }
10281   }
10282
10283   return result;
10284 }
10285
10286 /*!
10287   Returns the layout element at pixel position \a pos. If there is no element at that position,
10288   returns 0.
10289
10290   Only visible elements are used. If \ref QCPLayoutElement::setVisible on the element itself or on
10291   any of its parent elements is set to false, it will not be considered.
10292
10293   \see itemAt, plottableAt
10294 */
10295 QCPLayoutElement *QCustomPlot::layoutElementAt(const QPointF &pos) const
10296 {
10297   QCPLayoutElement *currentElement = mPlotLayout;
10298   bool searchSubElements = true;
10299   while (searchSubElements && currentElement)
10300   {
10301     searchSubElements = false;
10302     foreach (QCPLayoutElement *subElement, currentElement->elements(false))
10303     {
10304       if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0)
10305       {
10306         currentElement = subElement;
10307         searchSubElements = true;
10308         break;
10309       }
10310     }
10311   }
10312   return currentElement;
10313 }
10314
10315 /*!
10316   Returns the axes that currently have selected parts, i.e. whose selection state is not \ref
10317   QCPAxis::spNone.
10318
10319   \see selectedPlottables, selectedLegends, setInteractions, QCPAxis::setSelectedParts,
10320   QCPAxis::setSelectableParts
10321 */
10322 QList<QCPAxis*> QCustomPlot::selectedAxes() const
10323 {
10324   QList<QCPAxis*> result, allAxes;
10325   foreach (QCPAxisRect *rect, axisRects())
10326     allAxes << rect->axes();
10327
10328   foreach (QCPAxis *axis, allAxes)
10329   {
10330     if (axis->selectedParts() != QCPAxis::spNone)
10331       result.append(axis);
10332   }
10333
10334   return result;
10335 }
10336
10337 /*!
10338   Returns the legends that currently have selected parts, i.e. whose selection state is not \ref
10339   QCPLegend::spNone.
10340
10341   \see selectedPlottables, selectedAxes, setInteractions, QCPLegend::setSelectedParts,
10342   QCPLegend::setSelectableParts, QCPLegend::selectedItems
10343 */
10344 QList<QCPLegend*> QCustomPlot::selectedLegends() const
10345 {
10346   QList<QCPLegend*> result;
10347
10348   QStack<QCPLayoutElement*> elementStack;
10349   if (mPlotLayout)
10350     elementStack.push(mPlotLayout);
10351
10352   while (!elementStack.isEmpty())
10353   {
10354     foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false))
10355     {
10356       if (subElement)
10357       {
10358         elementStack.push(subElement);
10359         if (QCPLegend *leg = qobject_cast<QCPLegend*>(subElement))
10360         {
10361           if (leg->selectedParts() != QCPLegend::spNone)
10362             result.append(leg);
10363         }
10364       }
10365     }
10366   }
10367
10368   return result;
10369 }
10370
10371 /*!
10372   Deselects all layerables (plottables, items, axes, legends,...) of the QCustomPlot.
10373
10374   Since calling this function is not a user interaction, this does not emit the \ref
10375   selectionChangedByUser signal. The individual selectionChanged signals are emitted though, if the
10376   objects were previously selected.
10377
10378   \see setInteractions, selectedPlottables, selectedItems, selectedAxes, selectedLegends
10379 */
10380 void QCustomPlot::deselectAll()
10381 {
10382   foreach (QCPLayer *layer, mLayers)
10383   {
10384     foreach (QCPLayerable *layerable, layer->children())
10385       layerable->deselectEvent(0);
10386   }
10387 }
10388
10389 /*!
10390   Causes a complete replot into the internal buffer. Finally, update() is called, to redraw the
10391   buffer on the QCustomPlot widget surface. This is the method that must be called to make changes,
10392   for example on the axis ranges or data points of graphs, visible.
10393
10394   Under a few circumstances, QCustomPlot causes a replot by itself. Those are resize events of the
10395   QCustomPlot widget and user interactions (object selection and range dragging/zooming).
10396
10397   Before the replot happens, the signal \ref beforeReplot is emitted. After the replot, \ref
10398   afterReplot is emitted. It is safe to mutually connect the replot slot with any of those two
10399   signals on two QCustomPlots to make them replot synchronously, it won't cause an infinite
10400   recursion.
10401 */
10402 void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority)
10403 {
10404   if (mReplotting) // incase signals loop back to replot slot
10405     return;
10406   mReplotting = true;
10407   emit beforeReplot();
10408
10409   mPaintBuffer.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent);
10410   QCPPainter painter;
10411   painter.begin(&mPaintBuffer);
10412   if (painter.isActive())
10413   {
10414     painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem
10415     if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush)
10416       painter.fillRect(mViewport, mBackgroundBrush);
10417     draw(&painter);
10418     painter.end();
10419     if ((refreshPriority == rpHint && mPlottingHints.testFlag(QCP::phForceRepaint)) || refreshPriority==rpImmediate)
10420       repaint();
10421     else
10422       update();
10423   } else // might happen if QCustomPlot has width or height zero
10424     qDebug() << Q_FUNC_INFO << "Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero.";
10425
10426   emit afterReplot();
10427   mReplotting = false;
10428 }
10429
10430 /*!
10431   Rescales the axes such that all plottables (like graphs) in the plot are fully visible.
10432
10433   if \a onlyVisiblePlottables is set to true, only the plottables that have their visibility set to true
10434   (QCPLayerable::setVisible), will be used to rescale the axes.
10435
10436   \see QCPAbstractPlottable::rescaleAxes, QCPAxis::rescale
10437 */
10438 void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables)
10439 {
10440   QList<QCPAxis*> allAxes;
10441   foreach (QCPAxisRect *rect, axisRects())
10442     allAxes << rect->axes();
10443
10444   foreach (QCPAxis *axis, allAxes)
10445     axis->rescale(onlyVisiblePlottables);
10446 }
10447
10448 /*!
10449   Saves a PDF with the vectorized plot to the file \a fileName. The axis ratio as well as the scale
10450   of texts and lines will be derived from the specified \a width and \a height. This means, the
10451   output will look like the normal on-screen output of a QCustomPlot widget with the corresponding
10452   pixel width and height. If either \a width or \a height is zero, the exported image will have the
10453   same dimensions as the QCustomPlot widget currently has.
10454
10455   \a noCosmeticPen disables the use of cosmetic pens when drawing to the PDF file. Cosmetic pens
10456   are pens with numerical width 0, which are always drawn as a one pixel wide line, no matter what
10457   zoom factor is set in the PDF-Viewer. For more information about cosmetic pens, see the QPainter
10458   and QPen documentation.
10459
10460   The objects of the plot will appear in the current selection state. If you don't want any
10461   selected objects to be painted in their selected look, deselect everything with \ref deselectAll
10462   before calling this function.
10463
10464   Returns true on success.
10465
10466   \warning
10467   \li If you plan on editing the exported PDF file with a vector graphics editor like
10468   Inkscape, it is advised to set \a noCosmeticPen to true to avoid losing those cosmetic lines
10469   (which might be quite many, because cosmetic pens are the default for e.g. axes and tick marks).
10470   \li If calling this function inside the constructor of the parent of the QCustomPlot widget
10471   (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide
10472   explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this
10473   function uses the current width and height of the QCustomPlot widget. However, in Qt, these
10474   aren't defined yet inside the constructor, so you would get an image that has strange
10475   widths/heights.
10476
10477   \a pdfCreator and \a pdfTitle may be used to set the according metadata fields in the resulting
10478   PDF file.
10479
10480   \note On Android systems, this method does nothing and issues an according qDebug warning
10481   message. This is also the case if for other reasons the define flag QT_NO_PRINTER is set.
10482
10483   \see savePng, saveBmp, saveJpg, saveRastered
10484 */
10485 bool QCustomPlot::savePdf(const QString &fileName, bool noCosmeticPen, int width, int height, const QString &pdfCreator, const QString &pdfTitle)
10486 {
10487   bool success = false;
10488 #ifdef QT_NO_PRINTER
10489   Q_UNUSED(fileName)
10490   Q_UNUSED(noCosmeticPen)
10491   Q_UNUSED(width)
10492   Q_UNUSED(height)
10493   qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created.";
10494 #else
10495   int newWidth, newHeight;
10496   if (width == 0 || height == 0)
10497   {
10498     newWidth = this->width();
10499     newHeight = this->height();
10500   } else
10501   {
10502     newWidth = width;
10503     newHeight = height;
10504   }
10505
10506   QPrinter printer(QPrinter::ScreenResolution);
10507   printer.setOutputFileName(fileName);
10508   printer.setOutputFormat(QPrinter::PdfFormat);
10509   printer.setColorMode(QPrinter::Color);
10510   printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator);
10511   printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle);
10512   QRect oldViewport = viewport();
10513   setViewport(QRect(0, 0, newWidth, newHeight));
10514 #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
10515   printer.setFullPage(true);
10516   printer.setPaperSize(viewport().size(), QPrinter::DevicePixel);
10517 #else
10518   QPageLayout pageLayout;
10519   pageLayout.setMode(QPageLayout::FullPageMode);
10520   pageLayout.setOrientation(QPageLayout::Portrait);
10521   pageLayout.setMargins(QMarginsF(0, 0, 0, 0));
10522   pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch));
10523   printer.setPageLayout(pageLayout);
10524 #endif
10525   QCPPainter printpainter;
10526   if (printpainter.begin(&printer))
10527   {
10528     printpainter.setMode(QCPPainter::pmVectorized);
10529     printpainter.setMode(QCPPainter::pmNoCaching);
10530     printpainter.setMode(QCPPainter::pmNonCosmetic, noCosmeticPen);
10531     printpainter.setWindow(mViewport);
10532     if (mBackgroundBrush.style() != Qt::NoBrush &&
10533         mBackgroundBrush.color() != Qt::white &&
10534         mBackgroundBrush.color() != Qt::transparent &&
10535         mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent
10536       printpainter.fillRect(viewport(), mBackgroundBrush);
10537     draw(&printpainter);
10538     printpainter.end();
10539     success = true;
10540   }
10541   setViewport(oldViewport);
10542 #endif // QT_NO_PRINTER
10543   return success;
10544 }
10545
10546 /*!
10547   Saves a PNG image file to \a fileName on disc. The output plot will have the dimensions \a width
10548   and \a height in pixels. If either \a width or \a height is zero, the exported image will have
10549   the same dimensions as the QCustomPlot widget currently has. Line widths and texts etc. are not
10550   scaled up when larger widths/heights are used. If you want that effect, use the \a scale parameter.
10551
10552   For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an
10553   image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths,
10554   texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full
10555   200*200 pixel resolution.
10556
10557   If you use a high scaling factor, it is recommended to enable antialiasing for all elements via
10558   temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows
10559   QCustomPlot to place objects with sub-pixel accuracy.
10560
10561   \warning If calling this function inside the constructor of the parent of the QCustomPlot widget
10562   (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide
10563   explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this
10564   function uses the current width and height of the QCustomPlot widget. However, in Qt, these
10565   aren't defined yet inside the constructor, so you would get an image that has strange
10566   widths/heights.
10567
10568   The objects of the plot will appear in the current selection state. If you don't want any selected
10569   objects to be painted in their selected look, deselect everything with \ref deselectAll before calling
10570   this function.
10571
10572   If you want the PNG to have a transparent background, call \ref setBackground(const QBrush
10573   &brush) with no brush (Qt::NoBrush) or a transparent color (Qt::transparent), before saving.
10574
10575   PNG compression can be controlled with the \a quality parameter which must be between 0 and 100 or
10576   -1 to use the default setting.
10577
10578   Returns true on success. If this function fails, most likely the PNG format isn't supported by
10579   the system, see Qt docs about QImageWriter::supportedImageFormats().
10580
10581   \see savePdf, saveBmp, saveJpg, saveRastered
10582 */
10583 bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality)
10584 {
10585   return saveRastered(fileName, width, height, scale, "PNG", quality);
10586 }
10587
10588 /*!
10589   Saves a JPG image file to \a fileName on disc. The output plot will have the dimensions \a width
10590   and \a height in pixels. If either \a width or \a height is zero, the exported image will have
10591   the same dimensions as the QCustomPlot widget currently has. Line widths and texts etc. are not
10592   scaled up when larger widths/heights are used. If you want that effect, use the \a scale parameter.
10593
10594   For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an
10595   image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths,
10596   texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full
10597   200*200 pixel resolution.
10598
10599   If you use a high scaling factor, it is recommended to enable antialiasing for all elements via
10600   temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows
10601   QCustomPlot to place objects with sub-pixel accuracy.
10602
10603   \warning If calling this function inside the constructor of the parent of the QCustomPlot widget
10604   (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide
10605   explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this
10606   function uses the current width and height of the QCustomPlot widget. However, in Qt, these
10607   aren't defined yet inside the constructor, so you would get an image that has strange
10608   widths/heights.
10609
10610   The objects of the plot will appear in the current selection state. If you don't want any selected
10611   objects to be painted in their selected look, deselect everything with \ref deselectAll before calling
10612   this function.
10613
10614   JPG compression can be controlled with the \a quality parameter which must be between 0 and 100 or
10615   -1 to use the default setting.
10616
10617   Returns true on success. If this function fails, most likely the JPG format isn't supported by
10618   the system, see Qt docs about QImageWriter::supportedImageFormats().
10619
10620   \see savePdf, savePng, saveBmp, saveRastered
10621 */
10622 bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality)
10623 {
10624   return saveRastered(fileName, width, height, scale, "JPG", quality);
10625 }
10626
10627 /*!
10628   Saves a BMP image file to \a fileName on disc. The output plot will have the dimensions \a width
10629   and \a height in pixels. If either \a width or \a height is zero, the exported image will have
10630   the same dimensions as the QCustomPlot widget currently has. Line widths and texts etc. are not
10631   scaled up when larger widths/heights are used. If you want that effect, use the \a scale parameter.
10632
10633   For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an
10634   image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths,
10635   texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full
10636   200*200 pixel resolution.
10637
10638   If you use a high scaling factor, it is recommended to enable antialiasing for all elements via
10639   temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows
10640   QCustomPlot to place objects with sub-pixel accuracy.
10641
10642   \warning If calling this function inside the constructor of the parent of the QCustomPlot widget
10643   (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide
10644   explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this
10645   function uses the current width and height of the QCustomPlot widget. However, in Qt, these
10646   aren't defined yet inside the constructor, so you would get an image that has strange
10647   widths/heights.
10648
10649   The objects of the plot will appear in the current selection state. If you don't want any selected
10650   objects to be painted in their selected look, deselect everything with \ref deselectAll before calling
10651   this function.
10652
10653   Returns true on success. If this function fails, most likely the BMP format isn't supported by
10654   the system, see Qt docs about QImageWriter::supportedImageFormats().
10655
10656   \see savePdf, savePng, saveJpg, saveRastered
10657 */
10658 bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale)
10659 {
10660   return saveRastered(fileName, width, height, scale, "BMP");
10661 }
10662
10663 /*! \internal
10664
10665   Returns a minimum size hint that corresponds to the minimum size of the top level layout
10666   (\ref plotLayout). To prevent QCustomPlot from being collapsed to size/width zero, set a minimum
10667   size (setMinimumSize) either on the whole QCustomPlot or on any layout elements inside the plot.
10668   This is especially important, when placed in a QLayout where other components try to take in as
10669   much space as possible (e.g. QMdiArea).
10670 */
10671 QSize QCustomPlot::minimumSizeHint() const
10672 {
10673   return mPlotLayout->minimumSizeHint();
10674 }
10675
10676 /*! \internal
10677
10678   Returns a size hint that is the same as \ref minimumSizeHint.
10679
10680 */
10681 QSize QCustomPlot::sizeHint() const
10682 {
10683   return mPlotLayout->minimumSizeHint();
10684 }
10685
10686 /*! \internal
10687
10688   Event handler for when the QCustomPlot widget needs repainting. This does not cause a \ref replot, but
10689   draws the internal buffer on the widget surface.
10690 */
10691 void QCustomPlot::paintEvent(QPaintEvent *event)
10692 {
10693   Q_UNUSED(event);
10694   QPainter painter(this);
10695   painter.drawPixmap(0, 0, mPaintBuffer);
10696 }
10697
10698 /*! \internal
10699
10700   Event handler for a resize of the QCustomPlot widget. Causes the internal buffer to be resized to
10701   the new size. The viewport (which becomes the outer rect of mPlotLayout) is resized
10702   appropriately. Finally a \ref replot is performed.
10703 */
10704 void QCustomPlot::resizeEvent(QResizeEvent *event)
10705 {
10706   // resize and repaint the buffer:
10707 #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
10708   QSize pbSize = event->size();
10709   pbSize *= devicePixelRatio();
10710   mPaintBuffer = QPixmap(pbSize);
10711   mPaintBuffer.setDevicePixelRatio(devicePixelRatio());
10712 #else
10713   mPaintBuffer = QPixmap(event->size());
10714 #endif
10715   setViewport(rect());
10716   replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts
10717 }
10718
10719 /*! \internal
10720
10721  Event handler for when a double click occurs. Emits the \ref mouseDoubleClick signal, then emits
10722  the specialized signals when certain objecs are clicked (e.g. \ref plottableDoubleClick, \ref
10723  axisDoubleClick, etc.). Finally determines the affected layout element and forwards the event to
10724  it.
10725
10726  \see mousePressEvent, mouseReleaseEvent
10727 */
10728 void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event)
10729 {
10730   emit mouseDoubleClick(event);
10731
10732   QVariant details;
10733   QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details);
10734
10735   // emit specialized object double click signals:
10736   if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(clickedLayerable))
10737     emit plottableDoubleClick(ap, event);
10738   else if (QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10739     emit axisDoubleClick(ax, details.value<QCPAxis::SelectablePart>(), event);
10740   else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10741     emit itemDoubleClick(ai, event);
10742   else if (QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10743     emit legendDoubleClick(lg, 0, event);
10744   else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(clickedLayerable))
10745     emit legendDoubleClick(li->parentLegend(), li, event);
10746   else if (QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10747     emit titleDoubleClick(event, pt);
10748
10749   // call double click event of affected layout element:
10750   if (QCPLayoutElement *el = layoutElementAt(event->pos()))
10751     el->mouseDoubleClickEvent(event);
10752
10753   // call release event of affected layout element (as in mouseReleaseEvent, since the mouseDoubleClick replaces the second release event in double click case):
10754   if (mMouseEventElement)
10755   {
10756     mMouseEventElement->mouseReleaseEvent(event);
10757     mMouseEventElement = 0;
10758   }
10759
10760   //QWidget::mouseDoubleClickEvent(event); don't call base class implementation because it would just cause a mousePress/ReleaseEvent, which we don't want.
10761 }
10762
10763 /*! \internal
10764
10765   Event handler for when a mouse button is pressed. Emits the mousePress signal. Then determines
10766   the affected layout element and forwards the event to it.
10767
10768   \see mouseMoveEvent, mouseReleaseEvent
10769 */
10770 void QCustomPlot::mousePressEvent(QMouseEvent *event)
10771 {
10772   emit mousePress(event);
10773   mMousePressPos = event->pos(); // need this to determine in releaseEvent whether it was a click (no position change between press and release)
10774
10775   // call event of affected layout element:
10776   mMouseEventElement = layoutElementAt(event->pos());
10777   if (mMouseEventElement)
10778     mMouseEventElement->mousePressEvent(event);
10779
10780   QWidget::mousePressEvent(event);
10781 }
10782
10783 /*! \internal
10784
10785   Event handler for when the cursor is moved. Emits the \ref mouseMove signal.
10786
10787   If a layout element has mouse capture focus (a mousePressEvent happened on top of the layout
10788   element before), the mouseMoveEvent is forwarded to that element.
10789
10790   \see mousePressEvent, mouseReleaseEvent
10791 */
10792 void QCustomPlot::mouseMoveEvent(QMouseEvent *event)
10793 {
10794   emit mouseMove(event);
10795
10796   // call event of affected layout element:
10797   if (mMouseEventElement)
10798     mMouseEventElement->mouseMoveEvent(event);
10799
10800   QWidget::mouseMoveEvent(event);
10801 }
10802
10803 /*! \internal
10804
10805   Event handler for when a mouse button is released. Emits the \ref mouseRelease signal.
10806
10807   If the mouse was moved less than a certain threshold in any direction since the \ref
10808   mousePressEvent, it is considered a click which causes the selection mechanism (if activated via
10809   \ref setInteractions) to possibly change selection states accordingly. Further, specialized mouse
10810   click signals are emitted (e.g. \ref plottableClick, \ref axisClick, etc.)
10811
10812   If a layout element has mouse capture focus (a \ref mousePressEvent happened on top of the layout
10813   element before), the \ref mouseReleaseEvent is forwarded to that element.
10814
10815   \see mousePressEvent, mouseMoveEvent
10816 */
10817 void QCustomPlot::mouseReleaseEvent(QMouseEvent *event)
10818 {
10819   emit mouseRelease(event);
10820   bool doReplot = false;
10821
10822   if ((mMousePressPos-event->pos()).manhattanLength() < 5) // determine whether it was a click operation
10823   {
10824     if (event->button() == Qt::LeftButton)
10825     {
10826       // handle selection mechanism:
10827       QVariant details;
10828       QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);
10829       bool selectionStateChanged = false;
10830       bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier);
10831       // deselect all other layerables if not additive selection:
10832       if (!additive)
10833       {
10834         foreach (QCPLayer *layer, mLayers)
10835         {
10836           foreach (QCPLayerable *layerable, layer->children())
10837           {
10838             if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory()))
10839             {
10840               bool selChanged = false;
10841               layerable->deselectEvent(&selChanged);
10842               selectionStateChanged |= selChanged;
10843             }
10844           }
10845         }
10846       }
10847       if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory()))
10848       {
10849         // a layerable was actually clicked, call its selectEvent:
10850         bool selChanged = false;
10851         clickedLayerable->selectEvent(event, additive, details, &selChanged);
10852         selectionStateChanged |= selChanged;
10853       }
10854       doReplot = true;
10855       if (selectionStateChanged)
10856         emit selectionChangedByUser();
10857     }
10858
10859     // emit specialized object click signals:
10860     QVariant details;
10861     QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); // for these signals, selectability is ignored, that's why we call this again with onlySelectable set to false
10862     if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(clickedLayerable))
10863       emit plottableClick(ap, event);
10864     else if (QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10865       emit axisClick(ax, details.value<QCPAxis::SelectablePart>(), event);
10866     else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10867       emit itemClick(ai, event);
10868     else if (QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10869       emit legendClick(lg, 0, event);
10870     else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(clickedLayerable))
10871       emit legendClick(li->parentLegend(), li, event);
10872     else if (QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10873       emit titleClick(event, pt);
10874   }
10875
10876   // call event of affected layout element:
10877   if (mMouseEventElement)
10878   {
10879     mMouseEventElement->mouseReleaseEvent(event);
10880     mMouseEventElement = 0;
10881   }
10882
10883   if (doReplot || noAntialiasingOnDrag())
10884     replot();
10885
10886   QWidget::mouseReleaseEvent(event);
10887 }
10888
10889 /*! \internal
10890
10891   Event handler for mouse wheel events. First, the \ref mouseWheel signal is emitted. Then
10892   determines the affected layout element and forwards the event to it.
10893
10894 */
10895 void QCustomPlot::wheelEvent(QWheelEvent *event)
10896 {
10897   emit mouseWheel(event);
10898
10899   // call event of affected layout element:
10900   if (QCPLayoutElement *el = layoutElementAt(event->pos()))
10901     el->wheelEvent(event);
10902
10903   QWidget::wheelEvent(event);
10904 }
10905
10906 /*! \internal
10907
10908   This is the main draw function. It draws the entire plot, including background pixmap, with the
10909   specified \a painter. Note that it does not fill the background with the background brush (as the
10910   user may specify with \ref setBackground(const QBrush &brush)), this is up to the respective
10911   functions calling this method (e.g. \ref replot, \ref toPixmap and \ref toPainter).
10912 */
10913 void QCustomPlot::draw(QCPPainter *painter)
10914 {
10915   // run through layout phases:
10916   mPlotLayout->update(QCPLayoutElement::upPreparation);
10917   mPlotLayout->update(QCPLayoutElement::upMargins);
10918   mPlotLayout->update(QCPLayoutElement::upLayout);
10919
10920   // draw viewport background pixmap:
10921   drawBackground(painter);
10922
10923   // draw all layered objects (grid, axes, plottables, items, legend,...):
10924   foreach (QCPLayer *layer, mLayers)
10925   {
10926     foreach (QCPLayerable *child, layer->children())
10927     {
10928       if (child->realVisibility())
10929       {
10930         painter->save();
10931         painter->setClipRect(child->clipRect().translated(0, -1));
10932         child->applyDefaultAntialiasingHint(painter);
10933         child->draw(painter);
10934         painter->restore();
10935       }
10936     }
10937   }
10938
10939   /* Debug code to draw all layout element rects
10940   foreach (QCPLayoutElement* el, findChildren<QCPLayoutElement*>())
10941   {
10942     painter->setBrush(Qt::NoBrush);
10943     painter->setPen(QPen(QColor(0, 0, 0, 100), 0, Qt::DashLine));
10944     painter->drawRect(el->rect());
10945     painter->setPen(QPen(QColor(255, 0, 0, 100), 0, Qt::DashLine));
10946     painter->drawRect(el->outerRect());
10947   }
10948   */
10949 }
10950
10951 /*! \internal
10952
10953   Draws the viewport background pixmap of the plot.
10954
10955   If a pixmap was provided via \ref setBackground, this function buffers the scaled version
10956   depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside
10957   the viewport with the provided \a painter. The scaled version is buffered in
10958   mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when
10959   the axis rect has changed in a way that requires a rescale of the background pixmap (this is
10960   dependent on the \ref setBackgroundScaledMode), or when a differend axis background pixmap was
10961   set.
10962
10963   Note that this function does not draw a fill with the background brush (\ref setBackground(const
10964   QBrush &brush)) beneath the pixmap.
10965
10966   \see setBackground, setBackgroundScaled, setBackgroundScaledMode
10967 */
10968 void QCustomPlot::drawBackground(QCPPainter *painter)
10969 {
10970   // Note: background color is handled in individual replot/save functions
10971
10972   // draw background pixmap (on top of fill, if brush specified):
10973   if (!mBackgroundPixmap.isNull())
10974   {
10975     if (mBackgroundScaled)
10976     {
10977       // check whether mScaledBackground needs to be updated:
10978       QSize scaledSize(mBackgroundPixmap.size());
10979       scaledSize.scale(mViewport.size(), mBackgroundScaledMode);
10980       if (mScaledBackgroundPixmap.size() != scaledSize)
10981         mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
10982       painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect());
10983     } else
10984     {
10985       painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()));
10986     }
10987   }
10988 }
10989
10990
10991 /*! \internal
10992
10993   This method is used by \ref QCPAxisRect::removeAxis to report removed axes to the QCustomPlot
10994   so it may clear its QCustomPlot::xAxis, yAxis, xAxis2 and yAxis2 members accordingly.
10995 */
10996 void QCustomPlot::axisRemoved(QCPAxis *axis)
10997 {
10998   if (xAxis == axis)
10999     xAxis = 0;
11000   if (xAxis2 == axis)
11001     xAxis2 = 0;
11002   if (yAxis == axis)
11003     yAxis = 0;
11004   if (yAxis2 == axis)
11005     yAxis2 = 0;
11006
11007   // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers
11008 }
11009
11010 /*! \internal
11011
11012   This method is used by the QCPLegend destructor to report legend removal to the QCustomPlot so
11013   it may clear its QCustomPlot::legend member accordingly.
11014 */
11015 void QCustomPlot::legendRemoved(QCPLegend *legend)
11016 {
11017   if (this->legend == legend)
11018     this->legend = 0;
11019 }
11020
11021 /*! \internal
11022
11023   Assigns all layers their index (QCPLayer::mIndex) in the mLayers list. This method is thus called
11024   after every operation that changes the layer indices, like layer removal, layer creation, layer
11025   moving.
11026 */
11027 void QCustomPlot::updateLayerIndices() const
11028 {
11029   for (int i=0; i<mLayers.size(); ++i)
11030     mLayers.at(i)->mIndex = i;
11031 }
11032
11033 /*! \internal
11034
11035   Returns the layerable at pixel position \a pos. If \a onlySelectable is set to true, only those
11036   layerables that are selectable will be considered. (Layerable subclasses communicate their
11037   selectability via the QCPLayerable::selectTest method, by returning -1.)
11038
11039   \a selectionDetails is an output parameter that contains selection specifics of the affected
11040   layerable. This is useful if the respective layerable shall be given a subsequent
11041   QCPLayerable::selectEvent (like in \ref mouseReleaseEvent). \a selectionDetails usually contains
11042   information about which part of the layerable was hit, in multi-part layerables (e.g.
11043   QCPAxis::SelectablePart).
11044 */
11045 QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const
11046 {
11047   for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex)
11048   {
11049     const QList<QCPLayerable*> layerables = mLayers.at(layerIndex)->children();
11050     double minimumDistance = selectionTolerance()*1.1;
11051     QCPLayerable *minimumDistanceLayerable = 0;
11052     for (int i=layerables.size()-1; i>=0; --i)
11053     {
11054       if (!layerables.at(i)->realVisibility())
11055         continue;
11056       QVariant details;
11057       double dist = layerables.at(i)->selectTest(pos, onlySelectable, &details);
11058       if (dist >= 0 && dist < minimumDistance)
11059       {
11060         minimumDistance = dist;
11061         minimumDistanceLayerable = layerables.at(i);
11062         if (selectionDetails) *selectionDetails = details;
11063       }
11064     }
11065     if (minimumDistance < selectionTolerance())
11066       return minimumDistanceLayerable;
11067   }
11068   return 0;
11069 }
11070
11071 /*!
11072   Saves the plot to a rastered image file \a fileName in the image format \a format. The plot is
11073   sized to \a width and \a height in pixels and scaled with \a scale. (width 100 and scale 2.0 lead
11074   to a full resolution file with width 200.) If the \a format supports compression, \a quality may
11075   be between 0 and 100 to control it.
11076
11077   Returns true on success. If this function fails, most likely the given \a format isn't supported
11078   by the system, see Qt docs about QImageWriter::supportedImageFormats().
11079
11080   \see saveBmp, saveJpg, savePng, savePdf
11081 */
11082 bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality)
11083 {
11084   QPixmap buffer = toPixmap(width, height, scale);
11085   if (!buffer.isNull())
11086     return buffer.save(fileName, format, quality);
11087   else
11088     return false;
11089 }
11090
11091 /*!
11092   Renders the plot to a pixmap and returns it.
11093
11094   The plot is sized to \a width and \a height in pixels and scaled with \a scale. (width 100 and
11095   scale 2.0 lead to a full resolution pixmap with width 200.)
11096
11097   \see toPainter, saveRastered, saveBmp, savePng, saveJpg, savePdf
11098 */
11099 QPixmap QCustomPlot::toPixmap(int width, int height, double scale)
11100 {
11101   // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too.
11102   int newWidth, newHeight;
11103   if (width == 0 || height == 0)
11104   {
11105     newWidth = this->width();
11106     newHeight = this->height();
11107   } else
11108   {
11109     newWidth = width;
11110     newHeight = height;
11111   }
11112   int scaledWidth = qRound(scale*newWidth);
11113   int scaledHeight = qRound(scale*newHeight);
11114
11115   QPixmap result(scaledWidth, scaledHeight);
11116   result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later
11117   QCPPainter painter;
11118   painter.begin(&result);
11119   if (painter.isActive())
11120   {
11121     QRect oldViewport = viewport();
11122     setViewport(QRect(0, 0, newWidth, newHeight));
11123     painter.setMode(QCPPainter::pmNoCaching);
11124     if (!qFuzzyCompare(scale, 1.0))
11125     {
11126       if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales
11127         painter.setMode(QCPPainter::pmNonCosmetic);
11128       painter.scale(scale, scale);
11129     }
11130     if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush)
11131       painter.fillRect(mViewport, mBackgroundBrush);
11132     draw(&painter);
11133     setViewport(oldViewport);
11134     painter.end();
11135   } else // might happen if pixmap has width or height zero
11136   {
11137     qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap";
11138     return QPixmap();
11139   }
11140   return result;
11141 }
11142
11143 /*!
11144   Renders the plot using the passed \a painter.
11145
11146   The plot is sized to \a width and \a height in pixels. If the \a painter's scale is not 1.0, the resulting plot will
11147   appear scaled accordingly.
11148
11149   \note If you are restricted to using a QPainter (instead of QCPPainter), create a temporary QPicture and open a QCPPainter
11150   on it. Then call \ref toPainter with this QCPPainter. After ending the paint operation on the picture, draw it with
11151   the QPainter. This will reproduce the painter actions the QCPPainter took, with a QPainter.
11152
11153   \see toPixmap
11154 */
11155 void QCustomPlot::toPainter(QCPPainter *painter, int width, int height)
11156 {
11157   // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too.
11158   int newWidth, newHeight;
11159   if (width == 0 || height == 0)
11160   {
11161     newWidth = this->width();
11162     newHeight = this->height();
11163   } else
11164   {
11165     newWidth = width;
11166     newHeight = height;
11167   }
11168
11169   if (painter->isActive())
11170   {
11171     QRect oldViewport = viewport();
11172     setViewport(QRect(0, 0, newWidth, newHeight));
11173     painter->setMode(QCPPainter::pmNoCaching);
11174     // warning: the following is different in toPixmap, because a solid background color is applied there via QPixmap::fill
11175     // here, we need to do this via QPainter::fillRect.
11176     if (mBackgroundBrush.style() != Qt::NoBrush)
11177       painter->fillRect(mViewport, mBackgroundBrush);
11178     draw(painter);
11179     setViewport(oldViewport);
11180   } else
11181     qDebug() << Q_FUNC_INFO << "Passed painter is not active";
11182 }
11183
11184
11185 ////////////////////////////////////////////////////////////////////////////////////////////////////
11186 //////////////////// QCPColorGradient
11187 ////////////////////////////////////////////////////////////////////////////////////////////////////
11188
11189 /*! \class QCPColorGradient
11190   \brief Defines a color gradient for use with e.g. \ref QCPColorMap
11191
11192   This class describes a color gradient which can be used to encode data with color. For example,
11193   QCPColorMap and QCPColorScale have \ref QCPColorMap::setGradient "setGradient" methods which
11194   take an instance of this class. Colors are set with \ref setColorStopAt(double position, const QColor &color)
11195   with a \a position from 0 to 1. In between these defined color positions, the
11196   color will be interpolated linearly either in RGB or HSV space, see \ref setColorInterpolation.
11197
11198   Alternatively, load one of the preset color gradients shown in the image below, with \ref
11199   loadPreset, or by directly specifying the preset in the constructor.
11200
11201   \image html QCPColorGradient.png
11202
11203   The fact that the \ref QCPColorGradient(GradientPreset preset) constructor allows directly
11204   converting a \ref GradientPreset to a QCPColorGradient, you can also directly pass \ref
11205   GradientPreset to all the \a setGradient methods, e.g.:
11206   \code
11207   colorMap->setGradient(QCPColorGradient::gpHot);
11208   \endcode
11209
11210   The total number of levels used in the gradient can be set with \ref setLevelCount. Whether the
11211   color gradient shall be applied periodically (wrapping around) to data values that lie outside
11212   the data range specified on the plottable instance can be controlled with \ref setPeriodic.
11213 */
11214
11215 /*!
11216   Constructs a new QCPColorGradient initialized with the colors and color interpolation according
11217   to \a preset.
11218
11219   The color level count is initialized to 350.
11220 */
11221 QCPColorGradient::QCPColorGradient(GradientPreset preset) :
11222   mLevelCount(350),
11223   mColorInterpolation(ciRGB),
11224   mPeriodic(false),
11225   mColorBufferInvalidated(true)
11226 {
11227   mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount);
11228   loadPreset(preset);
11229 }
11230
11231 /* undocumented operator */
11232 bool QCPColorGradient::operator==(const QCPColorGradient &other) const
11233 {
11234   return ((other.mLevelCount == this->mLevelCount) &&
11235           (other.mColorInterpolation == this->mColorInterpolation) &&
11236           (other.mPeriodic == this->mPeriodic) &&
11237           (other.mColorStops == this->mColorStops));
11238 }
11239
11240 /*!
11241   Sets the number of discretization levels of the color gradient to \a n. The default is 350 which
11242   is typically enough to create a smooth appearance.
11243
11244   \image html QCPColorGradient-levelcount.png
11245 */
11246 void QCPColorGradient::setLevelCount(int n)
11247 {
11248   if (n < 2)
11249   {
11250     qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n;
11251     n = 2;
11252   }
11253   if (n != mLevelCount)
11254   {
11255     mLevelCount = n;
11256     mColorBufferInvalidated = true;
11257   }
11258 }
11259
11260 /*!
11261   Sets at which positions from 0 to 1 which color shall occur. The positions are the keys, the
11262   colors are the values of the passed QMap \a colorStops. In between these color stops, the color
11263   is interpolated according to \ref setColorInterpolation.
11264
11265   A more convenient way to create a custom gradient may be to clear all color stops with \ref
11266   clearColorStops and then adding them one by one with \ref setColorStopAt.
11267
11268   \see clearColorStops
11269 */
11270 void QCPColorGradient::setColorStops(const QMap<double, QColor> &colorStops)
11271 {
11272   mColorStops = colorStops;
11273   mColorBufferInvalidated = true;
11274 }
11275
11276 /*!
11277   Sets the \a color the gradient will have at the specified \a position (from 0 to 1). In between
11278   these color stops, the color is interpolated according to \ref setColorInterpolation.
11279
11280   \see setColorStops, clearColorStops
11281 */
11282 void QCPColorGradient::setColorStopAt(double position, const QColor &color)
11283 {
11284   mColorStops.insert(position, color);
11285   mColorBufferInvalidated = true;
11286 }
11287
11288 /*!
11289   Sets whether the colors in between the configured color stops (see \ref setColorStopAt) shall be
11290   interpolated linearly in RGB or in HSV color space.
11291
11292   For example, a sweep in RGB space from red to green will have a muddy brown intermediate color,
11293   whereas in HSV space the intermediate color is yellow.
11294 */
11295 void QCPColorGradient::setColorInterpolation(QCPColorGradient::ColorInterpolation interpolation)
11296 {
11297   if (interpolation != mColorInterpolation)
11298   {
11299     mColorInterpolation = interpolation;
11300     mColorBufferInvalidated = true;
11301   }
11302 }
11303
11304 /*!
11305   Sets whether data points that are outside the configured data range (e.g. \ref
11306   QCPColorMap::setDataRange) are colored by periodically repeating the color gradient or whether
11307   they all have the same color, corresponding to the respective gradient boundary color.
11308
11309   \image html QCPColorGradient-periodic.png
11310
11311   As shown in the image above, gradients that have the same start and end color are especially
11312   suitable for a periodic gradient mapping, since they produce smooth color transitions throughout
11313   the color map. A preset that has this property is \ref gpHues.
11314
11315   In practice, using periodic color gradients makes sense when the data corresponds to a periodic
11316   dimension, such as an angle or a phase. If this is not the case, the color encoding might become
11317   ambiguous, because multiple different data values are shown as the same color.
11318 */
11319 void QCPColorGradient::setPeriodic(bool enabled)
11320 {
11321   mPeriodic = enabled;
11322 }
11323
11324 /*!
11325   This method is used to quickly convert a \a data array to colors. The colors will be output in
11326   the array \a scanLine. Both \a data and \a scanLine must have the length \a n when passed to this
11327   function. The data range that shall be used for mapping the data value to the gradient is passed
11328   in \a range. \a logarithmic indicates whether the data values shall be mapped to colors
11329   logarithmically.
11330
11331   if \a data actually contains 2D-data linearized via <tt>[row*columnCount + column]</tt>, you can
11332   set \a dataIndexFactor to <tt>columnCount</tt> to convert a column instead of a row of the data
11333   array, in \a scanLine. \a scanLine will remain a regular (1D) array. This works because \a data
11334   is addressed <tt>data[i*dataIndexFactor]</tt>.
11335 */
11336 void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic)
11337 {
11338   // If you change something here, make sure to also adapt ::color()
11339   if (!data)
11340   {
11341     qDebug() << Q_FUNC_INFO << "null pointer given as data";
11342     return;
11343   }
11344   if (!scanLine)
11345   {
11346     qDebug() << Q_FUNC_INFO << "null pointer given as scanLine";
11347     return;
11348   }
11349   if (mColorBufferInvalidated)
11350     updateColorBuffer();
11351
11352   if (!logarithmic)
11353   {
11354     const double posToIndexFactor = (mLevelCount-1)/range.size();
11355     if (mPeriodic)
11356     {
11357       for (int i=0; i<n; ++i)
11358       {
11359         int index = (int)((data[dataIndexFactor*i]-range.lower)*posToIndexFactor) % mLevelCount;
11360         if (index < 0)
11361           index += mLevelCount;
11362         scanLine[i] = mColorBuffer.at(index);
11363       }
11364     } else
11365     {
11366       for (int i=0; i<n; ++i)
11367       {
11368         int index = (data[dataIndexFactor*i]-range.lower)*posToIndexFactor;
11369         if (index < 0)
11370           index = 0;
11371         else if (index >= mLevelCount)
11372           index = mLevelCount-1;
11373         scanLine[i] = mColorBuffer.at(index);
11374       }
11375     }
11376   } else // logarithmic == true
11377   {
11378     if (mPeriodic)
11379     {
11380       for (int i=0; i<n; ++i)
11381       {
11382         int index = (int)(qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1)) % mLevelCount;
11383         if (index < 0)
11384           index += mLevelCount;
11385         scanLine[i] = mColorBuffer.at(index);
11386       }
11387     } else
11388     {
11389       for (int i=0; i<n; ++i)
11390       {
11391         int index = qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1);
11392         if (index < 0)
11393           index = 0;
11394         else if (index >= mLevelCount)
11395           index = mLevelCount-1;
11396         scanLine[i] = mColorBuffer.at(index);
11397       }
11398     }
11399   }
11400 }
11401
11402 /*! \internal
11403
11404   This method is used to colorize a single data value given in \a position, to colors. The data
11405   range that shall be used for mapping the data value to the gradient is passed in \a range. \a
11406   logarithmic indicates whether the data value shall be mapped to a color logarithmically.
11407
11408   If an entire array of data values shall be converted, rather use \ref colorize, for better
11409   performance.
11410 */
11411 QRgb QCPColorGradient::color(double position, const QCPRange &range, bool logarithmic)
11412 {
11413   // If you change something here, make sure to also adapt ::colorize()
11414   if (mColorBufferInvalidated)
11415     updateColorBuffer();
11416   int index = 0;
11417   if (!logarithmic)
11418     index = (position-range.lower)*(mLevelCount-1)/range.size();
11419   else
11420     index = qLn(position/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1);
11421   if (mPeriodic)
11422   {
11423     index = index % mLevelCount;
11424     if (index < 0)
11425       index += mLevelCount;
11426   } else
11427   {
11428     if (index < 0)
11429       index = 0;
11430     else if (index >= mLevelCount)
11431       index = mLevelCount-1;
11432   }
11433   return mColorBuffer.at(index);
11434 }
11435
11436 /*!
11437   Clears the current color stops and loads the specified \a preset. A preset consists of predefined
11438   color stops and the corresponding color interpolation method.
11439
11440   The available presets are:
11441   \image html QCPColorGradient.png
11442 */
11443 void QCPColorGradient::loadPreset(GradientPreset preset)
11444 {
11445   clearColorStops();
11446   switch (preset)
11447   {
11448     case gpGrayscale:
11449       setColorInterpolation(ciRGB);
11450       setColorStopAt(0, Qt::black);
11451       setColorStopAt(1, Qt::white);
11452       break;
11453     case gpHot:
11454       setColorInterpolation(ciRGB);
11455       setColorStopAt(0, QColor(50, 0, 0));
11456       setColorStopAt(0.2, QColor(180, 10, 0));
11457       setColorStopAt(0.4, QColor(245, 50, 0));
11458       setColorStopAt(0.6, QColor(255, 150, 10));
11459       setColorStopAt(0.8, QColor(255, 255, 50));
11460       setColorStopAt(1, QColor(255, 255, 255));
11461       break;
11462     case gpCold:
11463       setColorInterpolation(ciRGB);
11464       setColorStopAt(0, QColor(0, 0, 50));
11465       setColorStopAt(0.2, QColor(0, 10, 180));
11466       setColorStopAt(0.4, QColor(0, 50, 245));
11467       setColorStopAt(0.6, QColor(10, 150, 255));
11468       setColorStopAt(0.8, QColor(50, 255, 255));
11469       setColorStopAt(1, QColor(255, 255, 255));
11470       break;
11471     case gpNight:
11472       setColorInterpolation(ciHSV);
11473       setColorStopAt(0, QColor(10, 20, 30));
11474       setColorStopAt(1, QColor(250, 255, 250));
11475       break;
11476     case gpCandy:
11477       setColorInterpolation(ciHSV);
11478       setColorStopAt(0, QColor(0, 0, 255));
11479       setColorStopAt(1, QColor(255, 250, 250));
11480       break;
11481     case gpGeography:
11482       setColorInterpolation(ciRGB);
11483       setColorStopAt(0, QColor(70, 170, 210));
11484       setColorStopAt(0.20, QColor(90, 160, 180));
11485       setColorStopAt(0.25, QColor(45, 130, 175));
11486       setColorStopAt(0.30, QColor(100, 140, 125));
11487       setColorStopAt(0.5, QColor(100, 140, 100));
11488       setColorStopAt(0.6, QColor(130, 145, 120));
11489       setColorStopAt(0.7, QColor(140, 130, 120));
11490       setColorStopAt(0.9, QColor(180, 190, 190));
11491       setColorStopAt(1, QColor(210, 210, 230));
11492       break;
11493     case gpIon:
11494       setColorInterpolation(ciHSV);
11495       setColorStopAt(0, QColor(50, 10, 10));
11496       setColorStopAt(0.45, QColor(0, 0, 255));
11497       setColorStopAt(0.8, QColor(0, 255, 255));
11498       setColorStopAt(1, QColor(0, 255, 0));
11499       break;
11500     case gpThermal:
11501       setColorInterpolation(ciRGB);
11502       setColorStopAt(0, QColor(0, 0, 50));
11503       setColorStopAt(0.15, QColor(20, 0, 120));
11504       setColorStopAt(0.33, QColor(200, 30, 140));
11505       setColorStopAt(0.6, QColor(255, 100, 0));
11506       setColorStopAt(0.85, QColor(255, 255, 40));
11507       setColorStopAt(1, QColor(255, 255, 255));
11508       break;
11509     case gpPolar:
11510       setColorInterpolation(ciRGB);
11511       setColorStopAt(0, QColor(50, 255, 255));
11512       setColorStopAt(0.18, QColor(10, 70, 255));
11513       setColorStopAt(0.28, QColor(10, 10, 190));
11514       setColorStopAt(0.5, QColor(0, 0, 0));
11515       setColorStopAt(0.72, QColor(190, 10, 10));
11516       setColorStopAt(0.82, QColor(255, 70, 10));
11517       setColorStopAt(1, QColor(255, 255, 50));
11518       break;
11519     case gpSpectrum:
11520       setColorInterpolation(ciHSV);
11521       setColorStopAt(0, QColor(50, 0, 50));
11522       setColorStopAt(0.15, QColor(0, 0, 255));
11523       setColorStopAt(0.35, QColor(0, 255, 255));
11524       setColorStopAt(0.6, QColor(255, 255, 0));
11525       setColorStopAt(0.75, QColor(255, 30, 0));
11526       setColorStopAt(1, QColor(50, 0, 0));
11527       break;
11528     case gpJet:
11529       setColorInterpolation(ciRGB);
11530       setColorStopAt(0, QColor(0, 0, 100));
11531       setColorStopAt(0.15, QColor(0, 50, 255));
11532       setColorStopAt(0.35, QColor(0, 255, 255));
11533       setColorStopAt(0.65, QColor(255, 255, 0));
11534       setColorStopAt(0.85, QColor(255, 30, 0));
11535       setColorStopAt(1, QColor(100, 0, 0));
11536       break;
11537     case gpHues:
11538       setColorInterpolation(ciHSV);
11539       setColorStopAt(0, QColor(255, 0, 0));
11540       setColorStopAt(1.0/3.0, QColor(0, 0, 255));
11541       setColorStopAt(2.0/3.0, QColor(0, 255, 0));
11542       setColorStopAt(1, QColor(255, 0, 0));
11543       break;
11544   }
11545 }
11546
11547 /*!
11548   Clears all color stops.
11549
11550   \see setColorStops, setColorStopAt
11551 */
11552 void QCPColorGradient::clearColorStops()
11553 {
11554   mColorStops.clear();
11555   mColorBufferInvalidated = true;
11556 }
11557
11558 /*!
11559   Returns an inverted gradient. The inverted gradient has all properties as this \ref
11560   QCPColorGradient, but the order of the color stops is inverted.
11561
11562   \see setColorStops, setColorStopAt
11563 */
11564 QCPColorGradient QCPColorGradient::inverted() const
11565 {
11566   QCPColorGradient result(*this);
11567   result.clearColorStops();
11568   for (QMap<double, QColor>::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it)
11569     result.setColorStopAt(1.0-it.key(), it.value());
11570   return result;
11571 }
11572
11573 /*! \internal
11574
11575   Updates the internal color buffer which will be used by \ref colorize and \ref color, to quickly
11576   convert positions to colors. This is where the interpolation between color stops is calculated.
11577 */
11578 void QCPColorGradient::updateColorBuffer()
11579 {
11580   if (mColorBuffer.size() != mLevelCount)
11581     mColorBuffer.resize(mLevelCount);
11582   if (mColorStops.size() > 1)
11583   {
11584     double indexToPosFactor = 1.0/(double)(mLevelCount-1);
11585     for (int i=0; i<mLevelCount; ++i)
11586     {
11587       double position = i*indexToPosFactor;
11588       QMap<double, QColor>::const_iterator it = mColorStops.lowerBound(position);
11589       if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop
11590       {
11591         mColorBuffer[i] = (it-1).value().rgb();
11592       } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop
11593       {
11594         mColorBuffer[i] = it.value().rgb();
11595       } else // position is in between stops (or on an intermediate stop), interpolate color
11596       {
11597         QMap<double, QColor>::const_iterator high = it;
11598         QMap<double, QColor>::const_iterator low = it-1;
11599         double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1
11600         switch (mColorInterpolation)
11601         {
11602           case ciRGB:
11603           {
11604             mColorBuffer[i] = qRgb((1-t)*low.value().red() + t*high.value().red(),
11605                                    (1-t)*low.value().green() + t*high.value().green(),
11606                                    (1-t)*low.value().blue() + t*high.value().blue());
11607             break;
11608           }
11609           case ciHSV:
11610           {
11611             QColor lowHsv = low.value().toHsv();
11612             QColor highHsv = high.value().toHsv();
11613             double hue = 0;
11614             double hueDiff = highHsv.hueF()-lowHsv.hueF();
11615             if (hueDiff > 0.5)
11616               hue = lowHsv.hueF() - t*(1.0-hueDiff);
11617             else if (hueDiff < -0.5)
11618               hue = lowHsv.hueF() + t*(1.0+hueDiff);
11619             else
11620               hue = lowHsv.hueF() + t*hueDiff;
11621             if (hue < 0) hue += 1.0;
11622             else if (hue >= 1.0) hue -= 1.0;
11623             mColorBuffer[i] = QColor::fromHsvF(hue, (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
11624             break;
11625           }
11626         }
11627       }
11628     }
11629   } else if (mColorStops.size() == 1)
11630   {
11631     mColorBuffer.fill(mColorStops.constBegin().value().rgb());
11632   } else // mColorStops is empty, fill color buffer with black
11633   {
11634     mColorBuffer.fill(qRgb(0, 0, 0));
11635   }
11636   mColorBufferInvalidated = false;
11637 }
11638
11639
11640 ////////////////////////////////////////////////////////////////////////////////////////////////////
11641 //////////////////// QCPAxisRect
11642 ////////////////////////////////////////////////////////////////////////////////////////////////////
11643
11644 /*! \class QCPAxisRect
11645   \brief Holds multiple axes and arranges them in a rectangular shape.
11646
11647   This class represents an axis rect, a rectangular area that is bounded on all sides with an
11648   arbitrary number of axes.
11649
11650   Initially QCustomPlot has one axis rect, accessible via QCustomPlot::axisRect(). However, the
11651   layout system allows to have multiple axis rects, e.g. arranged in a grid layout
11652   (QCustomPlot::plotLayout).
11653
11654   By default, QCPAxisRect comes with four axes, at bottom, top, left and right. They can be
11655   accessed via \ref axis by providing the respective axis type (\ref QCPAxis::AxisType) and index.
11656   If you need all axes in the axis rect, use \ref axes. The top and right axes are set to be
11657   invisible initially (QCPAxis::setVisible). To add more axes to a side, use \ref addAxis or \ref
11658   addAxes. To remove an axis, use \ref removeAxis.
11659
11660   The axis rect layerable itself only draws a background pixmap or color, if specified (\ref
11661   setBackground). It is placed on the "background" layer initially (see \ref QCPLayer for an
11662   explanation of the QCustomPlot layer system). The axes that are held by the axis rect can be
11663   placed on other layers, independently of the axis rect.
11664
11665   Every axis rect has a child layout of type \ref QCPLayoutInset. It is accessible via \ref
11666   insetLayout and can be used to have other layout elements (or even other layouts with multiple
11667   elements) hovering inside the axis rect.
11668
11669   If an axis rect is clicked and dragged, it processes this by moving certain axis ranges. The
11670   behaviour can be controlled with \ref setRangeDrag and \ref setRangeDragAxes. If the mouse wheel
11671   is scrolled while the cursor is on the axis rect, certain axes are scaled. This is controllable
11672   via \ref setRangeZoom, \ref setRangeZoomAxes and \ref setRangeZoomFactor. These interactions are
11673   only enabled if \ref QCustomPlot::setInteractions contains \ref QCP::iRangeDrag and \ref
11674   QCP::iRangeZoom.
11675
11676   \image html AxisRectSpacingOverview.png
11677   <center>Overview of the spacings and paddings that define the geometry of an axis. The dashed
11678   line on the far left indicates the viewport/widget border.</center>
11679 */
11680
11681 /* start documentation of inline functions */
11682
11683 /*! \fn QCPLayoutInset *QCPAxisRect::insetLayout() const
11684
11685   Returns the inset layout of this axis rect. It can be used to place other layout elements (or
11686   even layouts with multiple other elements) inside/on top of an axis rect.
11687
11688   \see QCPLayoutInset
11689 */
11690
11691 /*! \fn int QCPAxisRect::left() const
11692
11693   Returns the pixel position of the left border of this axis rect. Margins are not taken into
11694   account here, so the returned value is with respect to the inner \ref rect.
11695 */
11696
11697 /*! \fn int QCPAxisRect::right() const
11698
11699   Returns the pixel position of the right border of this axis rect. Margins are not taken into
11700   account here, so the returned value is with respect to the inner \ref rect.
11701 */
11702
11703 /*! \fn int QCPAxisRect::top() const
11704
11705   Returns the pixel position of the top border of this axis rect. Margins are not taken into
11706   account here, so the returned value is with respect to the inner \ref rect.
11707 */
11708
11709 /*! \fn int QCPAxisRect::bottom() const
11710
11711   Returns the pixel position of the bottom border of this axis rect. Margins are not taken into
11712   account here, so the returned value is with respect to the inner \ref rect.
11713 */
11714
11715 /*! \fn int QCPAxisRect::width() const
11716
11717   Returns the pixel width of this axis rect. Margins are not taken into account here, so the
11718   returned value is with respect to the inner \ref rect.
11719 */
11720
11721 /*! \fn int QCPAxisRect::height() const
11722
11723   Returns the pixel height of this axis rect. Margins are not taken into account here, so the
11724   returned value is with respect to the inner \ref rect.
11725 */
11726
11727 /*! \fn QSize QCPAxisRect::size() const
11728
11729   Returns the pixel size of this axis rect. Margins are not taken into account here, so the
11730   returned value is with respect to the inner \ref rect.
11731 */
11732
11733 /*! \fn QPoint QCPAxisRect::topLeft() const
11734
11735   Returns the top left corner of this axis rect in pixels. Margins are not taken into account here,
11736   so the returned value is with respect to the inner \ref rect.
11737 */
11738
11739 /*! \fn QPoint QCPAxisRect::topRight() const
11740
11741   Returns the top right corner of this axis rect in pixels. Margins are not taken into account
11742   here, so the returned value is with respect to the inner \ref rect.
11743 */
11744
11745 /*! \fn QPoint QCPAxisRect::bottomLeft() const
11746
11747   Returns the bottom left corner of this axis rect in pixels. Margins are not taken into account
11748   here, so the returned value is with respect to the inner \ref rect.
11749 */
11750
11751 /*! \fn QPoint QCPAxisRect::bottomRight() const
11752
11753   Returns the bottom right corner of this axis rect in pixels. Margins are not taken into account
11754   here, so the returned value is with respect to the inner \ref rect.
11755 */
11756
11757 /*! \fn QPoint QCPAxisRect::center() const
11758
11759   Returns the center of this axis rect in pixels. Margins are not taken into account here, so the
11760   returned value is with respect to the inner \ref rect.
11761 */
11762
11763 /* end documentation of inline functions */
11764
11765 /*!
11766   Creates a QCPAxisRect instance and sets default values. An axis is added for each of the four
11767   sides, the top and right axes are set invisible initially.
11768 */
11769 QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) :
11770   QCPLayoutElement(parentPlot),
11771   mBackgroundBrush(Qt::NoBrush),
11772   mBackgroundScaled(true),
11773   mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
11774   mInsetLayout(new QCPLayoutInset),
11775   mRangeDrag(Qt::Horizontal|Qt::Vertical),
11776   mRangeZoom(Qt::Horizontal|Qt::Vertical),
11777   mRangeZoomFactorHorz(0.85),
11778   mRangeZoomFactorVert(0.85),
11779   mDragging(false)
11780 {
11781   mInsetLayout->initializeParentPlot(mParentPlot);
11782   mInsetLayout->setParentLayerable(this);
11783   mInsetLayout->setParent(this);
11784
11785   setMinimumSize(50, 50);
11786   setMinimumMargins(QMargins(15, 15, 15, 15));
11787   mAxes.insert(QCPAxis::atLeft, QList<QCPAxis*>());
11788   mAxes.insert(QCPAxis::atRight, QList<QCPAxis*>());
11789   mAxes.insert(QCPAxis::atTop, QList<QCPAxis*>());
11790   mAxes.insert(QCPAxis::atBottom, QList<QCPAxis*>());
11791
11792   if (setupDefaultAxes)
11793   {
11794     QCPAxis *xAxis = addAxis(QCPAxis::atBottom);
11795     QCPAxis *yAxis = addAxis(QCPAxis::atLeft);
11796     QCPAxis *xAxis2 = addAxis(QCPAxis::atTop);
11797     QCPAxis *yAxis2 = addAxis(QCPAxis::atRight);
11798     setRangeDragAxes(xAxis, yAxis);
11799     setRangeZoomAxes(xAxis, yAxis);
11800     xAxis2->setVisible(false);
11801     yAxis2->setVisible(false);
11802     xAxis->grid()->setVisible(true);
11803     yAxis->grid()->setVisible(true);
11804     xAxis2->grid()->setVisible(false);
11805     yAxis2->grid()->setVisible(false);
11806     xAxis2->grid()->setZeroLinePen(Qt::NoPen);
11807     yAxis2->grid()->setZeroLinePen(Qt::NoPen);
11808     xAxis2->grid()->setVisible(false);
11809     yAxis2->grid()->setVisible(false);
11810   }
11811 }
11812
11813 QCPAxisRect::~QCPAxisRect()
11814 {
11815   delete mInsetLayout;
11816   mInsetLayout = 0;
11817
11818   QList<QCPAxis*> axesList = axes();
11819   for (int i=0; i<axesList.size(); ++i)
11820     removeAxis(axesList.at(i));
11821 }
11822
11823 /*!
11824   Returns the number of axes on the axis rect side specified with \a type.
11825
11826   \see axis
11827 */
11828 int QCPAxisRect::axisCount(QCPAxis::AxisType type) const
11829 {
11830   return mAxes.value(type).size();
11831 }
11832
11833 /*!
11834   Returns the axis with the given \a index on the axis rect side specified with \a type.
11835
11836   \see axisCount, axes
11837 */
11838 QCPAxis *QCPAxisRect::axis(QCPAxis::AxisType type, int index) const
11839 {
11840   QList<QCPAxis*> ax(mAxes.value(type));
11841   if (index >= 0 && index < ax.size())
11842   {
11843     return ax.at(index);
11844   } else
11845   {
11846     qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index;
11847     return 0;
11848   }
11849 }
11850
11851 /*!
11852   Returns all axes on the axis rect sides specified with \a types.
11853
11854   \a types may be a single \ref QCPAxis::AxisType or an <tt>or</tt>-combination, to get the axes of
11855   multiple sides.
11856
11857   \see axis
11858 */
11859 QList<QCPAxis*> QCPAxisRect::axes(QCPAxis::AxisTypes types) const
11860 {
11861   QList<QCPAxis*> result;
11862   if (types.testFlag(QCPAxis::atLeft))
11863     result << mAxes.value(QCPAxis::atLeft);
11864   if (types.testFlag(QCPAxis::atRight))
11865     result << mAxes.value(QCPAxis::atRight);
11866   if (types.testFlag(QCPAxis::atTop))
11867     result << mAxes.value(QCPAxis::atTop);
11868   if (types.testFlag(QCPAxis::atBottom))
11869     result << mAxes.value(QCPAxis::atBottom);
11870   return result;
11871 }
11872
11873 /*! \overload
11874
11875   Returns all axes of this axis rect.
11876 */
11877 QList<QCPAxis*> QCPAxisRect::axes() const
11878 {
11879   QList<QCPAxis*> result;
11880   QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
11881   while (it.hasNext())
11882   {
11883     it.next();
11884     result << it.value();
11885   }
11886   return result;
11887 }
11888
11889 /*!
11890   Adds a new axis to the axis rect side specified with \a type, and returns it. If \a axis is 0, a
11891   new QCPAxis instance is created internally.
11892
11893   You may inject QCPAxis instances (or sublasses of QCPAxis) by setting \a axis to an axis that was
11894   previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership
11895   of the axis, so you may not delete it afterwards. Further, the \a axis must have been created
11896   with this axis rect as parent and with the same axis type as specified in \a type. If this is not
11897   the case, a debug output is generated, the axis is not added, and the method returns 0.
11898
11899   This method can not be used to move \a axis between axis rects. The same \a axis instance must
11900   not be added multiple times to the same or different axis rects.
11901
11902   If an axis rect side already contains one or more axes, the lower and upper endings of the new
11903   axis (\ref QCPAxis::setLowerEnding, \ref QCPAxis::setUpperEnding) are set to \ref
11904   QCPLineEnding::esHalfBar.
11905
11906   \see addAxes, setupFullAxesBox
11907 */
11908 QCPAxis *QCPAxisRect::addAxis(QCPAxis::AxisType type, QCPAxis *axis)
11909 {
11910   QCPAxis *newAxis = axis;
11911   if (!newAxis)
11912   {
11913     newAxis = new QCPAxis(this, type);
11914   } else // user provided existing axis instance, do some sanity checks
11915   {
11916     if (newAxis->axisType() != type)
11917     {
11918       qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter";
11919       return 0;
11920     }
11921     if (newAxis->axisRect() != this)
11922     {
11923       qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect";
11924       return 0;
11925     }
11926     if (axes().contains(newAxis))
11927     {
11928       qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect";
11929       return 0;
11930     }
11931   }
11932   if (mAxes[type].size() > 0) // multiple axes on one side, add half-bar axis ending to additional axes with offset
11933   {
11934     bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom);
11935     newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert));
11936     newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert));
11937   }
11938   mAxes[type].append(newAxis);
11939   return newAxis;
11940 }
11941
11942 /*!
11943   Adds a new axis with \ref addAxis to each axis rect side specified in \a types. This may be an
11944   <tt>or</tt>-combination of QCPAxis::AxisType, so axes can be added to multiple sides at once.
11945
11946   Returns a list of the added axes.
11947
11948   \see addAxis, setupFullAxesBox
11949 */
11950 QList<QCPAxis*> QCPAxisRect::addAxes(QCPAxis::AxisTypes types)
11951 {
11952   QList<QCPAxis*> result;
11953   if (types.testFlag(QCPAxis::atLeft))
11954     result << addAxis(QCPAxis::atLeft);
11955   if (types.testFlag(QCPAxis::atRight))
11956     result << addAxis(QCPAxis::atRight);
11957   if (types.testFlag(QCPAxis::atTop))
11958     result << addAxis(QCPAxis::atTop);
11959   if (types.testFlag(QCPAxis::atBottom))
11960     result << addAxis(QCPAxis::atBottom);
11961   return result;
11962 }
11963
11964 /*!
11965   Removes the specified \a axis from the axis rect and deletes it.
11966
11967   Returns true on success, i.e. if \a axis was a valid axis in this axis rect.
11968
11969   \see addAxis
11970 */
11971 bool QCPAxisRect::removeAxis(QCPAxis *axis)
11972 {
11973   // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers:
11974   QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
11975   while (it.hasNext())
11976   {
11977     it.next();
11978     if (it.value().contains(axis))
11979     {
11980       mAxes[it.key()].removeOne(axis);
11981       if (qobject_cast<QCustomPlot*>(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot)
11982         parentPlot()->axisRemoved(axis);
11983       delete axis;
11984       return true;
11985     }
11986   }
11987   qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast<quintptr>(axis);
11988   return false;
11989 }
11990
11991 /*!
11992   Convenience function to create an axis on each side that doesn't have any axes yet and set their
11993   visibility to true. Further, the top/right axes are assigned the following properties of the
11994   bottom/left axes:
11995
11996   \li range (\ref QCPAxis::setRange)
11997   \li range reversed (\ref QCPAxis::setRangeReversed)
11998   \li scale type (\ref QCPAxis::setScaleType)
11999   \li scale log base  (\ref QCPAxis::setScaleLogBase)
12000   \li ticks (\ref QCPAxis::setTicks)
12001   \li auto (major) tick count (\ref QCPAxis::setAutoTickCount)
12002   \li sub tick count (\ref QCPAxis::setSubTickCount)
12003   \li auto sub ticks (\ref QCPAxis::setAutoSubTicks)
12004   \li tick step (\ref QCPAxis::setTickStep)
12005   \li auto tick step (\ref QCPAxis::setAutoTickStep)
12006   \li number format (\ref QCPAxis::setNumberFormat)
12007   \li number precision (\ref QCPAxis::setNumberPrecision)
12008   \li tick label type (\ref QCPAxis::setTickLabelType)
12009   \li date time format (\ref QCPAxis::setDateTimeFormat)
12010   \li date time spec (\ref QCPAxis::setDateTimeSpec)
12011
12012   Tick labels (\ref QCPAxis::setTickLabels) of the right and top axes are set to false.
12013
12014   If \a connectRanges is true, the \ref QCPAxis::rangeChanged "rangeChanged" signals of the bottom
12015   and left axes are connected to the \ref QCPAxis::setRange slots of the top and right axes.
12016 */
12017 void QCPAxisRect::setupFullAxesBox(bool connectRanges)
12018 {
12019   QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
12020   if (axisCount(QCPAxis::atBottom) == 0)
12021     xAxis = addAxis(QCPAxis::atBottom);
12022   else
12023     xAxis = axis(QCPAxis::atBottom);
12024
12025   if (axisCount(QCPAxis::atLeft) == 0)
12026     yAxis = addAxis(QCPAxis::atLeft);
12027   else
12028     yAxis = axis(QCPAxis::atLeft);
12029
12030   if (axisCount(QCPAxis::atTop) == 0)
12031     xAxis2 = addAxis(QCPAxis::atTop);
12032   else
12033     xAxis2 = axis(QCPAxis::atTop);
12034
12035   if (axisCount(QCPAxis::atRight) == 0)
12036     yAxis2 = addAxis(QCPAxis::atRight);
12037   else
12038     yAxis2 = axis(QCPAxis::atRight);
12039
12040   xAxis->setVisible(true);
12041   yAxis->setVisible(true);
12042   xAxis2->setVisible(true);
12043   yAxis2->setVisible(true);
12044   xAxis2->setTickLabels(false);
12045   yAxis2->setTickLabels(false);
12046
12047   xAxis2->setRange(xAxis->range());
12048   xAxis2->setRangeReversed(xAxis->rangeReversed());
12049   xAxis2->setScaleType(xAxis->scaleType());
12050   xAxis2->setScaleLogBase(xAxis->scaleLogBase());
12051   xAxis2->setTicks(xAxis->ticks());
12052   xAxis2->setAutoTickCount(xAxis->autoTickCount());
12053   xAxis2->setSubTickCount(xAxis->subTickCount());
12054   xAxis2->setAutoSubTicks(xAxis->autoSubTicks());
12055   xAxis2->setTickStep(xAxis->tickStep());
12056   xAxis2->setAutoTickStep(xAxis->autoTickStep());
12057   xAxis2->setNumberFormat(xAxis->numberFormat());
12058   xAxis2->setNumberPrecision(xAxis->numberPrecision());
12059   xAxis2->setTickLabelType(xAxis->tickLabelType());
12060   xAxis2->setDateTimeFormat(xAxis->dateTimeFormat());
12061   xAxis2->setDateTimeSpec(xAxis->dateTimeSpec());
12062
12063   yAxis2->setRange(yAxis->range());
12064   yAxis2->setRangeReversed(yAxis->rangeReversed());
12065   yAxis2->setScaleType(yAxis->scaleType());
12066   yAxis2->setScaleLogBase(yAxis->scaleLogBase());
12067   yAxis2->setTicks(yAxis->ticks());
12068   yAxis2->setAutoTickCount(yAxis->autoTickCount());
12069   yAxis2->setSubTickCount(yAxis->subTickCount());
12070   yAxis2->setAutoSubTicks(yAxis->autoSubTicks());
12071   yAxis2->setTickStep(yAxis->tickStep());
12072   yAxis2->setAutoTickStep(yAxis->autoTickStep());
12073   yAxis2->setNumberFormat(yAxis->numberFormat());
12074   yAxis2->setNumberPrecision(yAxis->numberPrecision());
12075   yAxis2->setTickLabelType(yAxis->tickLabelType());
12076   yAxis2->setDateTimeFormat(yAxis->dateTimeFormat());
12077   yAxis2->setDateTimeSpec(yAxis->dateTimeSpec());
12078
12079   if (connectRanges)
12080   {
12081     connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange)));
12082     connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange)));
12083   }
12084 }
12085
12086 /*!
12087   Returns a list of all the plottables that are associated with this axis rect.
12088
12089   A plottable is considered associated with an axis rect if its key or value axis (or both) is in
12090   this axis rect.
12091
12092   \see graphs, items
12093 */
12094 QList<QCPAbstractPlottable*> QCPAxisRect::plottables() const
12095 {
12096   // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries
12097   QList<QCPAbstractPlottable*> result;
12098   for (int i=0; i<mParentPlot->mPlottables.size(); ++i)
12099   {
12100     if (mParentPlot->mPlottables.at(i)->keyAxis()->axisRect() == this ||mParentPlot->mPlottables.at(i)->valueAxis()->axisRect() == this)
12101       result.append(mParentPlot->mPlottables.at(i));
12102   }
12103   return result;
12104 }
12105
12106 /*!
12107   Returns a list of all the graphs that are associated with this axis rect.
12108
12109   A graph is considered associated with an axis rect if its key or value axis (or both) is in
12110   this axis rect.
12111
12112   \see plottables, items
12113 */
12114 QList<QCPGraph*> QCPAxisRect::graphs() const
12115 {
12116   // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries
12117   QList<QCPGraph*> result;
12118   for (int i=0; i<mParentPlot->mGraphs.size(); ++i)
12119   {
12120     if (mParentPlot->mGraphs.at(i)->keyAxis()->axisRect() == this || mParentPlot->mGraphs.at(i)->valueAxis()->axisRect() == this)
12121       result.append(mParentPlot->mGraphs.at(i));
12122   }
12123   return result;
12124 }
12125
12126 /*!
12127   Returns a list of all the items that are associated with this axis rect.
12128
12129   An item is considered associated with an axis rect if any of its positions has key or value axis
12130   set to an axis that is in this axis rect, or if any of its positions has \ref
12131   QCPItemPosition::setAxisRect set to the axis rect, or if the clip axis rect (\ref
12132   QCPAbstractItem::setClipAxisRect) is set to this axis rect.
12133
12134   \see plottables, graphs
12135 */
12136 QList<QCPAbstractItem *> QCPAxisRect::items() const
12137 {
12138   // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries
12139   //       and miss those items that have this axis rect as clipAxisRect.
12140   QList<QCPAbstractItem*> result;
12141   for (int itemId=0; itemId<mParentPlot->mItems.size(); ++itemId)
12142   {
12143     if (mParentPlot->mItems.at(itemId)->clipAxisRect() == this)
12144     {
12145       result.append(mParentPlot->mItems.at(itemId));
12146       continue;
12147     }
12148     QList<QCPItemPosition*> positions = mParentPlot->mItems.at(itemId)->positions();
12149     for (int posId=0; posId<positions.size(); ++posId)
12150     {
12151       if (positions.at(posId)->axisRect() == this ||
12152           positions.at(posId)->keyAxis()->axisRect() == this ||
12153           positions.at(posId)->valueAxis()->axisRect() == this)
12154       {
12155         result.append(mParentPlot->mItems.at(itemId));
12156         break;
12157       }
12158     }
12159   }
12160   return result;
12161 }
12162
12163 /*!
12164   This method is called automatically upon replot and doesn't need to be called by users of
12165   QCPAxisRect.
12166
12167   Calls the base class implementation to update the margins (see \ref QCPLayoutElement::update),
12168   and finally passes the \ref rect to the inset layout (\ref insetLayout) and calls its
12169   QCPInsetLayout::update function.
12170 */
12171 void QCPAxisRect::update(UpdatePhase phase)
12172 {
12173   QCPLayoutElement::update(phase);
12174
12175   switch (phase)
12176   {
12177     case upPreparation:
12178     {
12179       QList<QCPAxis*> allAxes = axes();
12180       for (int i=0; i<allAxes.size(); ++i)
12181         allAxes.at(i)->setupTickVectors();
12182       break;
12183     }
12184     case upLayout:
12185     {
12186       mInsetLayout->setOuterRect(rect());
12187       break;
12188     }
12189     default: break;
12190   }
12191
12192   // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout):
12193   mInsetLayout->update(phase);
12194 }
12195
12196 /* inherits documentation from base class */
12197 QList<QCPLayoutElement*> QCPAxisRect::elements(bool recursive) const
12198 {
12199   QList<QCPLayoutElement*> result;
12200   if (mInsetLayout)
12201   {
12202     result << mInsetLayout;
12203     if (recursive)
12204       result << mInsetLayout->elements(recursive);
12205   }
12206   return result;
12207 }
12208
12209 /* inherits documentation from base class */
12210 void QCPAxisRect::applyDefaultAntialiasingHint(QCPPainter *painter) const
12211 {
12212   painter->setAntialiasing(false);
12213 }
12214
12215 /* inherits documentation from base class */
12216 void QCPAxisRect::draw(QCPPainter *painter)
12217 {
12218   drawBackground(painter);
12219 }
12220
12221 /*!
12222   Sets \a pm as the axis background pixmap. The axis background pixmap will be drawn inside the
12223   axis rect. Since axis rects place themselves on the "background" layer by default, the axis rect
12224   backgrounds are usually drawn below everything else.
12225
12226   For cases where the provided pixmap doesn't have the same size as the axis rect, scaling can be
12227   enabled with \ref setBackgroundScaled and the scaling mode (i.e. whether and how the aspect ratio
12228   is preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call,
12229   consider using the overloaded version of this function.
12230
12231   Below the pixmap, the axis rect may be optionally filled with a brush, if specified with \ref
12232   setBackground(const QBrush &brush).
12233
12234   \see setBackgroundScaled, setBackgroundScaledMode, setBackground(const QBrush &brush)
12235 */
12236 void QCPAxisRect::setBackground(const QPixmap &pm)
12237 {
12238   mBackgroundPixmap = pm;
12239   mScaledBackgroundPixmap = QPixmap();
12240 }
12241
12242 /*! \overload
12243
12244   Sets \a brush as the background brush. The axis rect background will be filled with this brush.
12245   Since axis rects place themselves on the "background" layer by default, the axis rect backgrounds
12246   are usually drawn below everything else.
12247
12248   The brush will be drawn before (under) any background pixmap, which may be specified with \ref
12249   setBackground(const QPixmap &pm).
12250
12251   To disable drawing of a background brush, set \a brush to Qt::NoBrush.
12252
12253   \see setBackground(const QPixmap &pm)
12254 */
12255 void QCPAxisRect::setBackground(const QBrush &brush)
12256 {
12257   mBackgroundBrush = brush;
12258 }
12259
12260 /*! \overload
12261
12262   Allows setting the background pixmap of the axis rect, whether it shall be scaled and how it
12263   shall be scaled in one call.
12264
12265   \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode
12266 */
12267 void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
12268 {
12269   mBackgroundPixmap = pm;
12270   mScaledBackgroundPixmap = QPixmap();
12271   mBackgroundScaled = scaled;
12272   mBackgroundScaledMode = mode;
12273 }
12274
12275 /*!
12276   Sets whether the axis background pixmap shall be scaled to fit the axis rect or not. If \a scaled
12277   is set to true, you may control whether and how the aspect ratio of the original pixmap is
12278   preserved with \ref setBackgroundScaledMode.
12279
12280   Note that the scaled version of the original pixmap is buffered, so there is no performance
12281   penalty on replots. (Except when the axis rect dimensions are changed continuously.)
12282
12283   \see setBackground, setBackgroundScaledMode
12284 */
12285 void QCPAxisRect::setBackgroundScaled(bool scaled)
12286 {
12287   mBackgroundScaled = scaled;
12288 }
12289
12290 /*!
12291   If scaling of the axis background pixmap is enabled (\ref setBackgroundScaled), use this function to
12292   define whether and how the aspect ratio of the original pixmap passed to \ref setBackground is preserved.
12293   \see setBackground, setBackgroundScaled
12294 */
12295 void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode)
12296 {
12297   mBackgroundScaledMode = mode;
12298 }
12299
12300 /*!
12301   Returns the range drag axis of the \a orientation provided.
12302
12303   \see setRangeDragAxes
12304 */
12305 QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation)
12306 {
12307   return (orientation == Qt::Horizontal ? mRangeDragHorzAxis.data() : mRangeDragVertAxis.data());
12308 }
12309
12310 /*!
12311   Returns the range zoom axis of the \a orientation provided.
12312
12313   \see setRangeZoomAxes
12314 */
12315 QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation)
12316 {
12317   return (orientation == Qt::Horizontal ? mRangeZoomHorzAxis.data() : mRangeZoomVertAxis.data());
12318 }
12319
12320 /*!
12321   Returns the range zoom factor of the \a orientation provided.
12322
12323   \see setRangeZoomFactor
12324 */
12325 double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation)
12326 {
12327   return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert);
12328 }
12329
12330 /*!
12331   Sets which axis orientation may be range dragged by the user with mouse interaction.
12332   What orientation corresponds to which specific axis can be set with
12333   \ref setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical). By
12334   default, the horizontal axis is the bottom axis (xAxis) and the vertical axis
12335   is the left axis (yAxis).
12336
12337   To disable range dragging entirely, pass 0 as \a orientations or remove \ref QCP::iRangeDrag from \ref
12338   QCustomPlot::setInteractions. To enable range dragging for both directions, pass <tt>Qt::Horizontal |
12339   Qt::Vertical</tt> as \a orientations.
12340
12341   In addition to setting \a orientations to a non-zero value, make sure \ref QCustomPlot::setInteractions
12342   contains \ref QCP::iRangeDrag to enable the range dragging interaction.
12343
12344   \see setRangeZoom, setRangeDragAxes, setNoAntialiasingOnDrag
12345 */
12346 void QCPAxisRect::setRangeDrag(Qt::Orientations orientations)
12347 {
12348   mRangeDrag = orientations;
12349 }
12350
12351 /*!
12352   Sets which axis orientation may be zoomed by the user with the mouse wheel. What orientation
12353   corresponds to which specific axis can be set with \ref setRangeZoomAxes(QCPAxis *horizontal,
12354   QCPAxis *vertical). By default, the horizontal axis is the bottom axis (xAxis) and the vertical
12355   axis is the left axis (yAxis).
12356
12357   To disable range zooming entirely, pass 0 as \a orientations or remove \ref QCP::iRangeZoom from \ref
12358   QCustomPlot::setInteractions. To enable range zooming for both directions, pass <tt>Qt::Horizontal |
12359   Qt::Vertical</tt> as \a orientations.
12360
12361   In addition to setting \a orientations to a non-zero value, make sure \ref QCustomPlot::setInteractions
12362   contains \ref QCP::iRangeZoom to enable the range zooming interaction.
12363
12364   \see setRangeZoomFactor, setRangeZoomAxes, setRangeDrag
12365 */
12366 void QCPAxisRect::setRangeZoom(Qt::Orientations orientations)
12367 {
12368   mRangeZoom = orientations;
12369 }
12370
12371 /*!
12372   Sets the axes whose range will be dragged when \ref setRangeDrag enables mouse range dragging
12373   on the QCustomPlot widget.
12374
12375   \see setRangeZoomAxes
12376 */
12377 void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical)
12378 {
12379   mRangeDragHorzAxis = horizontal;
12380   mRangeDragVertAxis = vertical;
12381 }
12382
12383 /*!
12384   Sets the axes whose range will be zoomed when \ref setRangeZoom enables mouse wheel zooming on the
12385   QCustomPlot widget. The two axes can be zoomed with different strengths, when different factors
12386   are passed to \ref setRangeZoomFactor(double horizontalFactor, double verticalFactor).
12387
12388   \see setRangeDragAxes
12389 */
12390 void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical)
12391 {
12392   mRangeZoomHorzAxis = horizontal;
12393   mRangeZoomVertAxis = vertical;
12394 }
12395
12396 /*!
12397   Sets how strong one rotation step of the mouse wheel zooms, when range zoom was activated with
12398   \ref setRangeZoom. The two parameters \a horizontalFactor and \a verticalFactor provide a way to
12399   let the horizontal axis zoom at different rates than the vertical axis. Which axis is horizontal
12400   and which is vertical, can be set with \ref setRangeZoomAxes.
12401
12402   When the zoom factor is greater than one, scrolling the mouse wheel backwards (towards the user)
12403   will zoom in (make the currently visible range smaller). For zoom factors smaller than one, the
12404   same scrolling direction will zoom out.
12405 */
12406 void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor)
12407 {
12408   mRangeZoomFactorHorz = horizontalFactor;
12409   mRangeZoomFactorVert = verticalFactor;
12410 }
12411
12412 /*! \overload
12413
12414   Sets both the horizontal and vertical zoom \a factor.
12415 */
12416 void QCPAxisRect::setRangeZoomFactor(double factor)
12417 {
12418   mRangeZoomFactorHorz = factor;
12419   mRangeZoomFactorVert = factor;
12420 }
12421
12422 /*! \internal
12423
12424   Draws the background of this axis rect. It may consist of a background fill (a QBrush) and a
12425   pixmap.
12426
12427   If a brush was given via \ref setBackground(const QBrush &brush), this function first draws an
12428   according filling inside the axis rect with the provided \a painter.
12429
12430   Then, if a pixmap was provided via \ref setBackground, this function buffers the scaled version
12431   depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside
12432   the axis rect with the provided \a painter. The scaled version is buffered in
12433   mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when
12434   the axis rect has changed in a way that requires a rescale of the background pixmap (this is
12435   dependent on the \ref setBackgroundScaledMode), or when a differend axis backgroud pixmap was
12436   set.
12437
12438   \see setBackground, setBackgroundScaled, setBackgroundScaledMode
12439 */
12440 void QCPAxisRect::drawBackground(QCPPainter *painter)
12441 {
12442   // draw background fill:
12443   if (mBackgroundBrush != Qt::NoBrush)
12444     painter->fillRect(mRect, mBackgroundBrush);
12445
12446   // draw background pixmap (on top of fill, if brush specified):
12447   if (!mBackgroundPixmap.isNull())
12448   {
12449     if (mBackgroundScaled)
12450     {
12451       // check whether mScaledBackground needs to be updated:
12452       QSize scaledSize(mBackgroundPixmap.size());
12453       scaledSize.scale(mRect.size(), mBackgroundScaledMode);
12454       if (mScaledBackgroundPixmap.size() != scaledSize)
12455         mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
12456       painter->drawPixmap(mRect.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect());
12457     } else
12458     {
12459       painter->drawPixmap(mRect.topLeft(), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()));
12460     }
12461   }
12462 }
12463
12464 /*! \internal
12465
12466   This function makes sure multiple axes on the side specified with \a type don't collide, but are
12467   distributed according to their respective space requirement (QCPAxis::calculateMargin).
12468
12469   It does this by setting an appropriate offset (\ref QCPAxis::setOffset) on all axes except the
12470   one with index zero.
12471
12472   This function is called by \ref calculateAutoMargin.
12473 */
12474 void QCPAxisRect::updateAxesOffset(QCPAxis::AxisType type)
12475 {
12476   const QList<QCPAxis*> axesList = mAxes.value(type);
12477   if (axesList.isEmpty())
12478     return;
12479
12480   bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false
12481   for (int i=1; i<axesList.size(); ++i)
12482   {
12483     int offset = axesList.at(i-1)->offset() + axesList.at(i-1)->calculateMargin();
12484     if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible)
12485     {
12486       if (!isFirstVisible)
12487         offset += axesList.at(i)->tickLengthIn();
12488       isFirstVisible = false;
12489     }
12490     axesList.at(i)->setOffset(offset);
12491   }
12492 }
12493
12494 /* inherits documentation from base class */
12495 int QCPAxisRect::calculateAutoMargin(QCP::MarginSide side)
12496 {
12497   if (!mAutoMargins.testFlag(side))
12498     qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin";
12499
12500   updateAxesOffset(QCPAxis::marginSideToAxisType(side));
12501
12502   // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call
12503   const QList<QCPAxis*> axesList = mAxes.value(QCPAxis::marginSideToAxisType(side));
12504   if (axesList.size() > 0)
12505     return axesList.last()->offset() + axesList.last()->calculateMargin();
12506   else
12507     return 0;
12508 }
12509
12510 /*! \internal
12511
12512   Event handler for when a mouse button is pressed on the axis rect. If the left mouse button is
12513   pressed, the range dragging interaction is initialized (the actual range manipulation happens in
12514   the \ref mouseMoveEvent).
12515
12516   The mDragging flag is set to true and some anchor points are set that are needed to determine the
12517   distance the mouse was dragged in the mouse move/release events later.
12518
12519   \see mouseMoveEvent, mouseReleaseEvent
12520 */
12521 void QCPAxisRect::mousePressEvent(QMouseEvent *event)
12522 {
12523   mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in releaseEvent whether it was a full click (no position change between press and release)
12524   if (event->buttons() & Qt::LeftButton)
12525   {
12526     mDragging = true;
12527     // initialize antialiasing backup in case we start dragging:
12528     if (mParentPlot->noAntialiasingOnDrag())
12529     {
12530       mAADragBackup = mParentPlot->antialiasedElements();
12531       mNotAADragBackup = mParentPlot->notAntialiasedElements();
12532     }
12533     // Mouse range dragging interaction:
12534     if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
12535     {
12536       if (mRangeDragHorzAxis)
12537         mDragStartHorzRange = mRangeDragHorzAxis.data()->range();
12538       if (mRangeDragVertAxis)
12539         mDragStartVertRange = mRangeDragVertAxis.data()->range();
12540     }
12541   }
12542 }
12543
12544 /*! \internal
12545
12546   Event handler for when the mouse is moved on the axis rect. If range dragging was activated in a
12547   preceding \ref mousePressEvent, the range is moved accordingly.
12548
12549   \see mousePressEvent, mouseReleaseEvent
12550 */
12551 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event)
12552 {
12553   // Mouse range dragging interaction:
12554   if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag))
12555   {
12556     if (mRangeDrag.testFlag(Qt::Horizontal))
12557     {
12558       if (QCPAxis *rangeDragHorzAxis = mRangeDragHorzAxis.data())
12559       {
12560         if (rangeDragHorzAxis->mScaleType == QCPAxis::stLinear)
12561         {
12562           double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x());
12563           rangeDragHorzAxis->setRange(mDragStartHorzRange.lower+diff, mDragStartHorzRange.upper+diff);
12564         } else if (rangeDragHorzAxis->mScaleType == QCPAxis::stLogarithmic)
12565         {
12566           double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x());
12567           rangeDragHorzAxis->setRange(mDragStartHorzRange.lower*diff, mDragStartHorzRange.upper*diff);
12568         }
12569       }
12570     }
12571     if (mRangeDrag.testFlag(Qt::Vertical))
12572     {
12573       if (QCPAxis *rangeDragVertAxis = mRangeDragVertAxis.data())
12574       {
12575         if (rangeDragVertAxis->mScaleType == QCPAxis::stLinear)
12576         {
12577           double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y());
12578           rangeDragVertAxis->setRange(mDragStartVertRange.lower+diff, mDragStartVertRange.upper+diff);
12579         } else if (rangeDragVertAxis->mScaleType == QCPAxis::stLogarithmic)
12580         {
12581           double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y());
12582           rangeDragVertAxis->setRange(mDragStartVertRange.lower*diff, mDragStartVertRange.upper*diff);
12583         }
12584       }
12585     }
12586     if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot
12587     {
12588       if (mParentPlot->noAntialiasingOnDrag())
12589         mParentPlot->setNotAntialiasedElements(QCP::aeAll);
12590       mParentPlot->replot();
12591     }
12592   }
12593 }
12594
12595 /* inherits documentation from base class */
12596 void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event)
12597 {
12598   Q_UNUSED(event)
12599   mDragging = false;
12600   if (mParentPlot->noAntialiasingOnDrag())
12601   {
12602     mParentPlot->setAntialiasedElements(mAADragBackup);
12603     mParentPlot->setNotAntialiasedElements(mNotAADragBackup);
12604   }
12605 }
12606
12607 /*! \internal
12608
12609   Event handler for mouse wheel events. If rangeZoom is Qt::Horizontal, Qt::Vertical or both, the
12610   ranges of the axes defined as rangeZoomHorzAxis and rangeZoomVertAxis are scaled. The center of
12611   the scaling operation is the current cursor position inside the axis rect. The scaling factor is
12612   dependent on the mouse wheel delta (which direction the wheel was rotated) to provide a natural
12613   zooming feel. The Strength of the zoom can be controlled via \ref setRangeZoomFactor.
12614
12615   Note, that event->delta() is usually +/-120 for single rotation steps. However, if the mouse
12616   wheel is turned rapidly, many steps may bunch up to one event, so the event->delta() may then be
12617   multiples of 120. This is taken into account here, by calculating \a wheelSteps and using it as
12618   exponent of the range zoom factor. This takes care of the wheel direction automatically, by
12619   inverting the factor, when the wheel step is negative (f^-1 = 1/f).
12620 */
12621 void QCPAxisRect::wheelEvent(QWheelEvent *event)
12622 {
12623   // Mouse range zooming interaction:
12624   if (mParentPlot->interactions().testFlag(QCP::iRangeZoom))
12625   {
12626     if (mRangeZoom != 0)
12627     {
12628       double factor;
12629       double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually
12630       if (mRangeZoom.testFlag(Qt::Horizontal))
12631       {
12632         factor = qPow(mRangeZoomFactorHorz, wheelSteps);
12633         if (mRangeZoomHorzAxis.data())
12634           mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x()));
12635       }
12636       if (mRangeZoom.testFlag(Qt::Vertical))
12637       {
12638         factor = qPow(mRangeZoomFactorVert, wheelSteps);
12639         if (mRangeZoomVertAxis.data())
12640           mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y()));
12641       }
12642       mParentPlot->replot();
12643     }
12644   }
12645 }
12646
12647
12648 ////////////////////////////////////////////////////////////////////////////////////////////////////
12649 //////////////////// QCPAbstractLegendItem
12650 ////////////////////////////////////////////////////////////////////////////////////////////////////
12651
12652 /*! \class QCPAbstractLegendItem
12653   \brief The abstract base class for all entries in a QCPLegend.
12654
12655   It defines a very basic interface for entries in a QCPLegend. For representing plottables in the
12656   legend, the subclass \ref QCPPlottableLegendItem is more suitable.
12657
12658   Only derive directly from this class when you need absolute freedom (e.g. a custom legend entry
12659   that's not even associated with a plottable).
12660
12661   You must implement the following pure virtual functions:
12662   \li \ref draw (from QCPLayerable)
12663
12664   You inherit the following members you may use:
12665   <table>
12666     <tr>
12667       <td>QCPLegend *\b mParentLegend</td>
12668       <td>A pointer to the parent QCPLegend.</td>
12669     </tr><tr>
12670       <td>QFont \b mFont</td>
12671       <td>The generic font of the item. You should use this font for all or at least the most prominent text of the item.</td>
12672     </tr>
12673   </table>
12674 */
12675
12676 /* start of documentation of signals */
12677
12678 /*! \fn void QCPAbstractLegendItem::selectionChanged(bool selected)
12679
12680   This signal is emitted when the selection state of this legend item has changed, either by user
12681   interaction or by a direct call to \ref setSelected.
12682 */
12683
12684 /* end of documentation of signals */
12685
12686 /*!
12687   Constructs a QCPAbstractLegendItem and associates it with the QCPLegend \a parent. This does not
12688   cause the item to be added to \a parent, so \ref QCPLegend::addItem must be called separately.
12689 */
12690 QCPAbstractLegendItem::QCPAbstractLegendItem(QCPLegend *parent) :
12691   QCPLayoutElement(parent->parentPlot()),
12692   mParentLegend(parent),
12693   mFont(parent->font()),
12694   mTextColor(parent->textColor()),
12695   mSelectedFont(parent->selectedFont()),
12696   mSelectedTextColor(parent->selectedTextColor()),
12697   mSelectable(true),
12698   mSelected(false)
12699 {
12700   setLayer(QLatin1String("legend"));
12701   setMargins(QMargins(8, 2, 8, 2));
12702 }
12703
12704 /*!
12705   Sets the default font of this specific legend item to \a font.
12706
12707   \see setTextColor, QCPLegend::setFont
12708 */
12709 void QCPAbstractLegendItem::setFont(const QFont &font)
12710 {
12711   mFont = font;
12712 }
12713
12714 /*!
12715   Sets the default text color of this specific legend item to \a color.
12716
12717   \see setFont, QCPLegend::setTextColor
12718 */
12719 void QCPAbstractLegendItem::setTextColor(const QColor &color)
12720 {
12721   mTextColor = color;
12722 }
12723
12724 /*!
12725   When this legend item is selected, \a font is used to draw generic text, instead of the normal
12726   font set with \ref setFont.
12727
12728   \see setFont, QCPLegend::setSelectedFont
12729 */
12730 void QCPAbstractLegendItem::setSelectedFont(const QFont &font)
12731 {
12732   mSelectedFont = font;
12733 }
12734
12735 /*!
12736   When this legend item is selected, \a color is used to draw generic text, instead of the normal
12737   color set with \ref setTextColor.
12738
12739   \see setTextColor, QCPLegend::setSelectedTextColor
12740 */
12741 void QCPAbstractLegendItem::setSelectedTextColor(const QColor &color)
12742 {
12743   mSelectedTextColor = color;
12744 }
12745
12746 /*!
12747   Sets whether this specific legend item is selectable.
12748
12749   \see setSelectedParts, QCustomPlot::setInteractions
12750 */
12751 void QCPAbstractLegendItem::setSelectable(bool selectable)
12752 {
12753   if (mSelectable != selectable)
12754   {
12755     mSelectable = selectable;
12756     emit selectableChanged(mSelectable);
12757   }
12758 }
12759
12760 /*!
12761   Sets whether this specific legend item is selected.
12762
12763   It is possible to set the selection state of this item by calling this function directly, even if
12764   setSelectable is set to false.
12765
12766   \see setSelectableParts, QCustomPlot::setInteractions
12767 */
12768 void QCPAbstractLegendItem::setSelected(bool selected)
12769 {
12770   if (mSelected != selected)
12771   {
12772     mSelected = selected;
12773     emit selectionChanged(mSelected);
12774   }
12775 }
12776
12777 /* inherits documentation from base class */
12778 double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
12779 {
12780   Q_UNUSED(details)
12781   if (!mParentPlot) return -1;
12782   if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems)))
12783     return -1;
12784
12785   if (mRect.contains(pos.toPoint()))
12786     return mParentPlot->selectionTolerance()*0.99;
12787   else
12788     return -1;
12789 }
12790
12791 /* inherits documentation from base class */
12792 void QCPAbstractLegendItem::applyDefaultAntialiasingHint(QCPPainter *painter) const
12793 {
12794   applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems);
12795 }
12796
12797 /* inherits documentation from base class */
12798 QRect QCPAbstractLegendItem::clipRect() const
12799 {
12800   return mOuterRect;
12801 }
12802
12803 /* inherits documentation from base class */
12804 void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
12805 {
12806   Q_UNUSED(event)
12807   Q_UNUSED(details)
12808   if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems))
12809   {
12810     bool selBefore = mSelected;
12811     setSelected(additive ? !mSelected : true);
12812     if (selectionStateChanged)
12813       *selectionStateChanged = mSelected != selBefore;
12814   }
12815 }
12816
12817 /* inherits documentation from base class */
12818 void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged)
12819 {
12820   if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems))
12821   {
12822     bool selBefore = mSelected;
12823     setSelected(false);
12824     if (selectionStateChanged)
12825       *selectionStateChanged = mSelected != selBefore;
12826   }
12827 }
12828
12829 ////////////////////////////////////////////////////////////////////////////////////////////////////
12830 //////////////////// QCPPlottableLegendItem
12831 ////////////////////////////////////////////////////////////////////////////////////////////////////
12832
12833 /*! \class QCPPlottableLegendItem
12834   \brief A legend item representing a plottable with an icon and the plottable name.
12835
12836   This is the standard legend item for plottables. It displays an icon of the plottable next to the
12837   plottable name. The icon is drawn by the respective plottable itself (\ref
12838   QCPAbstractPlottable::drawLegendIcon), and tries to give an intuitive symbol for the plottable.
12839   For example, the QCPGraph draws a centered horizontal line and/or a single scatter point in the
12840   middle.
12841
12842   Legend items of this type are always associated with one plottable (retrievable via the
12843   plottable() function and settable with the constructor). You may change the font of the plottable
12844   name with \ref setFont. Icon padding and border pen is taken from the parent QCPLegend, see \ref
12845   QCPLegend::setIconBorderPen and \ref QCPLegend::setIconTextPadding.
12846
12847   The function \ref QCPAbstractPlottable::addToLegend/\ref QCPAbstractPlottable::removeFromLegend
12848   creates/removes legend items of this type in the default implementation. However, these functions
12849   may be reimplemented such that a different kind of legend item (e.g a direct subclass of
12850   QCPAbstractLegendItem) is used for that plottable.
12851
12852   Since QCPLegend is based on QCPLayoutGrid, a legend item itself is just a subclass of
12853   QCPLayoutElement. While it could be added to a legend (or any other layout) via the normal layout
12854   interface, QCPLegend has specialized functions for handling legend items conveniently, see the
12855   documentation of \ref QCPLegend.
12856 */
12857
12858 /*!
12859   Creates a new legend item associated with \a plottable.
12860
12861   Once it's created, it can be added to the legend via \ref QCPLegend::addItem.
12862
12863   A more convenient way of adding/removing a plottable to/from the legend is via the functions \ref
12864   QCPAbstractPlottable::addToLegend and \ref QCPAbstractPlottable::removeFromLegend.
12865 */
12866 QCPPlottableLegendItem::QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable) :
12867   QCPAbstractLegendItem(parent),
12868   mPlottable(plottable)
12869 {
12870 }
12871
12872 /*! \internal
12873
12874   Returns the pen that shall be used to draw the icon border, taking into account the selection
12875   state of this item.
12876 */
12877 QPen QCPPlottableLegendItem::getIconBorderPen() const
12878 {
12879   return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen();
12880 }
12881
12882 /*! \internal
12883
12884   Returns the text color that shall be used to draw text, taking into account the selection state
12885   of this item.
12886 */
12887 QColor QCPPlottableLegendItem::getTextColor() const
12888 {
12889   return mSelected ? mSelectedTextColor : mTextColor;
12890 }
12891
12892 /*! \internal
12893
12894   Returns the font that shall be used to draw text, taking into account the selection state of this
12895   item.
12896 */
12897 QFont QCPPlottableLegendItem::getFont() const
12898 {
12899   return mSelected ? mSelectedFont : mFont;
12900 }
12901
12902 /*! \internal
12903
12904   Draws the item with \a painter. The size and position of the drawn legend item is defined by the
12905   parent layout (typically a \ref QCPLegend) and the \ref minimumSizeHint and \ref maximumSizeHint
12906   of this legend item.
12907 */
12908 void QCPPlottableLegendItem::draw(QCPPainter *painter)
12909 {
12910   if (!mPlottable) return;
12911   painter->setFont(getFont());
12912   painter->setPen(QPen(getTextColor()));
12913   QSizeF iconSize = mParentLegend->iconSize();
12914   QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
12915   QRectF iconRect(mRect.topLeft(), iconSize);
12916   int textHeight = qMax(textRect.height(), iconSize.height());  // if text has smaller height than icon, center text vertically in icon height, else align tops
12917   painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name());
12918   // draw icon:
12919   painter->save();
12920   painter->setClipRect(iconRect, Qt::IntersectClip);
12921   mPlottable->drawLegendIcon(painter, iconRect);
12922   painter->restore();
12923   // draw icon border:
12924   if (getIconBorderPen().style() != Qt::NoPen)
12925   {
12926     painter->setPen(getIconBorderPen());
12927     painter->setBrush(Qt::NoBrush);
12928     painter->drawRect(iconRect);
12929   }
12930 }
12931
12932 /*! \internal
12933
12934   Calculates and returns the size of this item. This includes the icon, the text and the padding in
12935   between.
12936 */
12937 QSize QCPPlottableLegendItem::minimumSizeHint() const
12938 {
12939   if (!mPlottable) return QSize();
12940   QSize result(0, 0);
12941   QRect textRect;
12942   QFontMetrics fontMetrics(getFont());
12943   QSize iconSize = mParentLegend->iconSize();
12944   textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
12945   result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() + mMargins.left() + mMargins.right());
12946   result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() + mMargins.bottom());
12947   return result;
12948 }
12949
12950
12951 ////////////////////////////////////////////////////////////////////////////////////////////////////
12952 //////////////////// QCPLegend
12953 ////////////////////////////////////////////////////////////////////////////////////////////////////
12954
12955 /*! \class QCPLegend
12956   \brief Manages a legend inside a QCustomPlot.
12957
12958   A legend is a small box somewhere in the plot which lists plottables with their name and icon.
12959
12960   Normally, the legend is populated by calling \ref QCPAbstractPlottable::addToLegend. The
12961   respective legend item can be removed with \ref QCPAbstractPlottable::removeFromLegend. However,
12962   QCPLegend also offers an interface to add and manipulate legend items directly: \ref item, \ref
12963   itemWithPlottable, \ref itemCount, \ref addItem, \ref removeItem, etc.
12964
12965   The QCPLegend derives from QCPLayoutGrid and as such can be placed in any position a
12966   QCPLayoutElement may be positioned. The legend items are themselves QCPLayoutElements which are
12967   placed in the grid layout of the legend. QCPLegend only adds an interface specialized for
12968   handling child elements of type QCPAbstractLegendItem, as mentioned above. In principle, any
12969   other layout elements may also be added to a legend via the normal \ref QCPLayoutGrid interface.
12970   However, the QCPAbstractLegendItem-Interface will ignore those elements (e.g. \ref itemCount will
12971   only return the number of items with QCPAbstractLegendItems type).
12972
12973   By default, every QCustomPlot has one legend (QCustomPlot::legend) which is placed in the inset
12974   layout of the main axis rect (\ref QCPAxisRect::insetLayout). To move the legend to another
12975   position inside the axis rect, use the methods of the \ref QCPLayoutInset. To move the legend
12976   outside of the axis rect, place it anywhere else with the QCPLayout/QCPLayoutElement interface.
12977 */
12978
12979 /* start of documentation of signals */
12980
12981 /*! \fn void QCPLegend::selectionChanged(QCPLegend::SelectableParts selection);
12982
12983   This signal is emitted when the selection state of this legend has changed.
12984
12985   \see setSelectedParts, setSelectableParts
12986 */
12987
12988 /* end of documentation of signals */
12989
12990 /*!
12991   Constructs a new QCPLegend instance with \a parentPlot as the containing plot and default values.
12992
12993   Note that by default, QCustomPlot already contains a legend ready to be used as
12994   QCustomPlot::legend
12995 */
12996 QCPLegend::QCPLegend()
12997 {
12998   setRowSpacing(0);
12999   setColumnSpacing(10);
13000   setMargins(QMargins(2, 3, 2, 2));
13001   setAntialiased(false);
13002   setIconSize(32, 18);
13003
13004   setIconTextPadding(7);
13005
13006   setSelectableParts(spLegendBox | spItems);
13007   setSelectedParts(spNone);
13008
13009   setBorderPen(QPen(Qt::black));
13010   setSelectedBorderPen(QPen(Qt::blue, 2));
13011   setIconBorderPen(Qt::NoPen);
13012   setSelectedIconBorderPen(QPen(Qt::blue, 2));
13013   setBrush(Qt::white);
13014   setSelectedBrush(Qt::white);
13015   setTextColor(Qt::black);
13016   setSelectedTextColor(Qt::blue);
13017 }
13018
13019 QCPLegend::~QCPLegend()
13020 {
13021   clearItems();
13022   if (qobject_cast<QCustomPlot*>(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot)
13023     mParentPlot->legendRemoved(this);
13024 }
13025
13026 /* no doc for getter, see setSelectedParts */
13027 QCPLegend::SelectableParts QCPLegend::selectedParts() const
13028 {
13029   // check whether any legend elements selected, if yes, add spItems to return value
13030   bool hasSelectedItems = false;
13031   for (int i=0; i<itemCount(); ++i)
13032   {
13033     if (item(i) && item(i)->selected())
13034     {
13035       hasSelectedItems = true;
13036       break;
13037     }
13038   }
13039   if (hasSelectedItems)
13040     return mSelectedParts | spItems;
13041   else
13042     return mSelectedParts & ~spItems;
13043 }
13044
13045 /*!
13046   Sets the pen, the border of the entire legend is drawn with.
13047 */
13048 void QCPLegend::setBorderPen(const QPen &pen)
13049 {
13050   mBorderPen = pen;
13051 }
13052
13053 /*!
13054   Sets the brush of the legend background.
13055 */
13056 void QCPLegend::setBrush(const QBrush &brush)
13057 {
13058   mBrush = brush;
13059 }
13060
13061 /*!
13062   Sets the default font of legend text. Legend items that draw text (e.g. the name of a graph) will
13063   use this font by default. However, a different font can be specified on a per-item-basis by
13064   accessing the specific legend item.
13065
13066   This function will also set \a font on all already existing legend items.
13067
13068   \see QCPAbstractLegendItem::setFont
13069 */
13070 void QCPLegend::setFont(const QFont &font)
13071 {
13072   mFont = font;
13073   for (int i=0; i<itemCount(); ++i)
13074   {
13075     if (item(i))
13076       item(i)->setFont(mFont);
13077   }
13078 }
13079
13080 /*!
13081   Sets the default color of legend text. Legend items that draw text (e.g. the name of a graph)
13082   will use this color by default. However, a different colors can be specified on a per-item-basis
13083   by accessing the specific legend item.
13084
13085   This function will also set \a color on all already existing legend items.
13086
13087   \see QCPAbstractLegendItem::setTextColor
13088 */
13089 void QCPLegend::setTextColor(const QColor &color)
13090 {
13091   mTextColor = color;
13092   for (int i=0; i<itemCount(); ++i)
13093   {
13094     if (item(i))
13095       item(i)->setTextColor(color);
13096   }
13097 }
13098
13099 /*!
13100   Sets the size of legend icons. Legend items that draw an icon (e.g. a visual
13101   representation of the graph) will use this size by default.
13102 */
13103 void QCPLegend::setIconSize(const QSize &size)
13104 {
13105   mIconSize = size;
13106 }
13107
13108 /*! \overload
13109 */
13110 void QCPLegend::setIconSize(int width, int height)
13111 {
13112   mIconSize.setWidth(width);
13113   mIconSize.setHeight(height);
13114 }
13115
13116 /*!
13117   Sets the horizontal space in pixels between the legend icon and the text next to it.
13118   Legend items that draw an icon (e.g. a visual representation of the graph) and text (e.g. the
13119   name of the graph) will use this space by default.
13120 */
13121 void QCPLegend::setIconTextPadding(int padding)
13122 {
13123   mIconTextPadding = padding;
13124 }
13125
13126 /*!
13127   Sets the pen used to draw a border around each legend icon. Legend items that draw an
13128   icon (e.g. a visual representation of the graph) will use this pen by default.
13129
13130   If no border is wanted, set this to \a Qt::NoPen.
13131 */
13132 void QCPLegend::setIconBorderPen(const QPen &pen)
13133 {
13134   mIconBorderPen = pen;
13135 }
13136
13137 /*!
13138   Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface.
13139   (When \ref QCustomPlot::setInteractions contains \ref QCP::iSelectLegend.)
13140
13141   However, even when \a selectable is set to a value not allowing the selection of a specific part,
13142   it is still possible to set the selection of this part manually, by calling \ref setSelectedParts
13143   directly.
13144
13145   \see SelectablePart, setSelectedParts
13146 */
13147 void QCPLegend::setSelectableParts(const SelectableParts &selectable)
13148 {
13149   if (mSelectableParts != selectable)
13150   {
13151     mSelectableParts = selectable;
13152     emit selectableChanged(mSelectableParts);
13153   }
13154 }
13155
13156 /*!
13157   Sets the selected state of the respective legend parts described by \ref SelectablePart. When a part
13158   is selected, it uses a different pen/font and brush. If some legend items are selected and \a selected
13159   doesn't contain \ref spItems, those items become deselected.
13160
13161   The entire selection mechanism is handled automatically when \ref QCustomPlot::setInteractions
13162   contains iSelectLegend. You only need to call this function when you wish to change the selection
13163   state manually.
13164
13165   This function can change the selection state of a part even when \ref setSelectableParts was set to a
13166   value that actually excludes the part.
13167
13168   emits the \ref selectionChanged signal when \a selected is different from the previous selection state.
13169
13170   Note that it doesn't make sense to set the selected state \ref spItems here when it wasn't set
13171   before, because there's no way to specify which exact items to newly select. Do this by calling
13172   \ref QCPAbstractLegendItem::setSelected directly on the legend item you wish to select.
13173
13174   \see SelectablePart, setSelectableParts, selectTest, setSelectedBorderPen, setSelectedIconBorderPen, setSelectedBrush,
13175   setSelectedFont
13176 */
13177 void QCPLegend::setSelectedParts(const SelectableParts &selected)
13178 {
13179   SelectableParts newSelected = selected;
13180   mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed
13181
13182   if (mSelectedParts != newSelected)
13183   {
13184     if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that)
13185     {
13186       qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function";
13187       newSelected &= ~spItems;
13188     }
13189     if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection
13190     {
13191       for (int i=0; i<itemCount(); ++i)
13192       {
13193         if (item(i))
13194           item(i)->setSelected(false);
13195       }
13196     }
13197     mSelectedParts = newSelected;
13198     emit selectionChanged(mSelectedParts);
13199   }
13200 }
13201
13202 /*!
13203   When the legend box is selected, this pen is used to draw the border instead of the normal pen
13204   set via \ref setBorderPen.
13205
13206   \see setSelectedParts, setSelectableParts, setSelectedBrush
13207 */
13208 void QCPLegend::setSelectedBorderPen(const QPen &pen)
13209 {
13210   mSelectedBorderPen = pen;
13211 }
13212
13213 /*!
13214   Sets the pen legend items will use to draw their icon borders, when they are selected.
13215
13216   \see setSelectedParts, setSelectableParts, setSelectedFont
13217 */
13218 void QCPLegend::setSelectedIconBorderPen(const QPen &pen)
13219 {
13220   mSelectedIconBorderPen = pen;
13221 }
13222
13223 /*!
13224   When the legend box is selected, this brush is used to draw the legend background instead of the normal brush
13225   set via \ref setBrush.
13226
13227   \see setSelectedParts, setSelectableParts, setSelectedBorderPen
13228 */
13229 void QCPLegend::setSelectedBrush(const QBrush &brush)
13230 {
13231   mSelectedBrush = brush;
13232 }
13233
13234 /*!
13235   Sets the default font that is used by legend items when they are selected.
13236
13237   This function will also set \a font on all already existing legend items.
13238
13239   \see setFont, QCPAbstractLegendItem::setSelectedFont
13240 */
13241 void QCPLegend::setSelectedFont(const QFont &font)
13242 {
13243   mSelectedFont = font;
13244   for (int i=0; i<itemCount(); ++i)
13245   {
13246     if (item(i))
13247       item(i)->setSelectedFont(font);
13248   }
13249 }
13250
13251 /*!
13252   Sets the default text color that is used by legend items when they are selected.
13253
13254   This function will also set \a color on all already existing legend items.
13255
13256   \see setTextColor, QCPAbstractLegendItem::setSelectedTextColor
13257 */
13258 void QCPLegend::setSelectedTextColor(const QColor &color)
13259 {
13260   mSelectedTextColor = color;
13261   for (int i=0; i<itemCount(); ++i)
13262   {
13263     if (item(i))
13264       item(i)->setSelectedTextColor(color);
13265   }
13266 }
13267
13268 /*!
13269   Returns the item with index \a i.
13270
13271   \see itemCount
13272 */
13273 QCPAbstractLegendItem *QCPLegend::item(int index) const
13274 {
13275   return qobject_cast<QCPAbstractLegendItem*>(elementAt(index));
13276 }
13277
13278 /*!
13279   Returns the QCPPlottableLegendItem which is associated with \a plottable (e.g. a \ref QCPGraph*).
13280   If such an item isn't in the legend, returns 0.
13281
13282   \see hasItemWithPlottable
13283 */
13284 QCPPlottableLegendItem *QCPLegend::itemWithPlottable(const QCPAbstractPlottable *plottable) const
13285 {
13286   for (int i=0; i<itemCount(); ++i)
13287   {
13288     if (QCPPlottableLegendItem *pli = qobject_cast<QCPPlottableLegendItem*>(item(i)))
13289     {
13290       if (pli->plottable() == plottable)
13291         return pli;
13292     }
13293   }
13294   return 0;
13295 }
13296
13297 /*!
13298   Returns the number of items currently in the legend.
13299   \see item
13300 */
13301 int QCPLegend::itemCount() const
13302 {
13303   return elementCount();
13304 }
13305
13306 /*!
13307   Returns whether the legend contains \a itm.
13308 */
13309 bool QCPLegend::hasItem(QCPAbstractLegendItem *item) const
13310 {
13311   for (int i=0; i<itemCount(); ++i)
13312   {
13313     if (item == this->item(i))
13314         return true;
13315   }
13316   return false;
13317 }
13318
13319 /*!
13320   Returns whether the legend contains a QCPPlottableLegendItem which is associated with \a plottable (e.g. a \ref QCPGraph*).
13321   If such an item isn't in the legend, returns false.
13322
13323   \see itemWithPlottable
13324 */
13325 bool QCPLegend::hasItemWithPlottable(const QCPAbstractPlottable *plottable) const
13326 {
13327   return itemWithPlottable(plottable);
13328 }
13329
13330 /*!
13331   Adds \a item to the legend, if it's not present already.
13332
13333   Returns true on success, i.e. if the item wasn't in the list already and has been successfuly added.
13334
13335   The legend takes ownership of the item.
13336 */
13337 bool QCPLegend::addItem(QCPAbstractLegendItem *item)
13338 {
13339   if (!hasItem(item))
13340   {
13341     return addElement(rowCount(), 0, item);
13342   } else
13343     return false;
13344 }
13345
13346 /*!
13347   Removes the item with index \a index from the legend.
13348
13349   Returns true, if successful.
13350
13351   \see itemCount, clearItems
13352 */
13353 bool QCPLegend::removeItem(int index)
13354 {
13355   if (QCPAbstractLegendItem *ali = item(index))
13356   {
13357     bool success = remove(ali);
13358     simplify();
13359     return success;
13360   } else
13361     return false;
13362 }
13363
13364 /*! \overload
13365
13366   Removes \a item from the legend.
13367
13368   Returns true, if successful.
13369
13370   \see clearItems
13371 */
13372 bool QCPLegend::removeItem(QCPAbstractLegendItem *item)
13373 {
13374   bool success = remove(item);
13375   simplify();
13376   return success;
13377 }
13378
13379 /*!
13380   Removes all items from the legend.
13381 */
13382 void QCPLegend::clearItems()
13383 {
13384   for (int i=itemCount()-1; i>=0; --i)
13385     removeItem(i);
13386 }
13387
13388 /*!
13389   Returns the legend items that are currently selected. If no items are selected,
13390   the list is empty.
13391
13392   \see QCPAbstractLegendItem::setSelected, setSelectable
13393 */
13394 QList<QCPAbstractLegendItem *> QCPLegend::selectedItems() const
13395 {
13396   QList<QCPAbstractLegendItem*> result;
13397   for (int i=0; i<itemCount(); ++i)
13398   {
13399     if (QCPAbstractLegendItem *ali = item(i))
13400     {
13401       if (ali->selected())
13402         result.append(ali);
13403     }
13404   }
13405   return result;
13406 }
13407
13408 /*! \internal
13409
13410   A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter
13411   before drawing main legend elements.
13412
13413   This is the antialiasing state the painter passed to the \ref draw method is in by default.
13414
13415   This function takes into account the local setting of the antialiasing flag as well as the
13416   overrides set with \ref QCustomPlot::setAntialiasedElements and \ref
13417   QCustomPlot::setNotAntialiasedElements.
13418
13419   \see setAntialiased
13420 */
13421 void QCPLegend::applyDefaultAntialiasingHint(QCPPainter *painter) const
13422 {
13423   applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend);
13424 }
13425
13426 /*! \internal
13427
13428   Returns the pen used to paint the border of the legend, taking into account the selection state
13429   of the legend box.
13430 */
13431 QPen QCPLegend::getBorderPen() const
13432 {
13433   return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen;
13434 }
13435
13436 /*! \internal
13437
13438   Returns the brush used to paint the background of the legend, taking into account the selection
13439   state of the legend box.
13440 */
13441 QBrush QCPLegend::getBrush() const
13442 {
13443   return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush;
13444 }
13445
13446 /*! \internal
13447
13448   Draws the legend box with the provided \a painter. The individual legend items are layerables
13449   themselves, thus are drawn independently.
13450 */
13451 void QCPLegend::draw(QCPPainter *painter)
13452 {
13453   // draw background rect:
13454   painter->setBrush(getBrush());
13455   painter->setPen(getBorderPen());
13456   painter->drawRect(mOuterRect);
13457 }
13458
13459 /* inherits documentation from base class */
13460 double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
13461 {
13462   if (!mParentPlot) return -1;
13463   if (onlySelectable && !mSelectableParts.testFlag(spLegendBox))
13464     return -1;
13465
13466   if (mOuterRect.contains(pos.toPoint()))
13467   {
13468     if (details) details->setValue(spLegendBox);
13469     return mParentPlot->selectionTolerance()*0.99;
13470   }
13471   return -1;
13472 }
13473
13474 /* inherits documentation from base class */
13475 void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13476 {
13477   Q_UNUSED(event)
13478   mSelectedParts = selectedParts(); // in case item selection has changed
13479   if (details.value<SelectablePart>() == spLegendBox && mSelectableParts.testFlag(spLegendBox))
13480   {
13481     SelectableParts selBefore = mSelectedParts;
13482     setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent)
13483     if (selectionStateChanged)
13484       *selectionStateChanged = mSelectedParts != selBefore;
13485   }
13486 }
13487
13488 /* inherits documentation from base class */
13489 void QCPLegend::deselectEvent(bool *selectionStateChanged)
13490 {
13491   mSelectedParts = selectedParts(); // in case item selection has changed
13492   if (mSelectableParts.testFlag(spLegendBox))
13493   {
13494     SelectableParts selBefore = mSelectedParts;
13495     setSelectedParts(selectedParts() & ~spLegendBox);
13496     if (selectionStateChanged)
13497       *selectionStateChanged = mSelectedParts != selBefore;
13498   }
13499 }
13500
13501 /* inherits documentation from base class */
13502 QCP::Interaction QCPLegend::selectionCategory() const
13503 {
13504   return QCP::iSelectLegend;
13505 }
13506
13507 /* inherits documentation from base class */
13508 QCP::Interaction QCPAbstractLegendItem::selectionCategory() const
13509 {
13510   return QCP::iSelectLegend;
13511 }
13512
13513 /* inherits documentation from base class */
13514 void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot)
13515 {
13516   Q_UNUSED(parentPlot)
13517 }
13518
13519
13520 ////////////////////////////////////////////////////////////////////////////////////////////////////
13521 //////////////////// QCPPlotTitle
13522 ////////////////////////////////////////////////////////////////////////////////////////////////////
13523
13524 /*! \class QCPPlotTitle
13525   \brief A layout element displaying a plot title text
13526
13527   The text may be specified with \ref setText, theformatting can be controlled with \ref setFont
13528   and \ref setTextColor.
13529
13530   A plot title can be added as follows:
13531   \code
13532   customPlot->plotLayout()->insertRow(0); // inserts an empty row above the default axis rect
13533   customPlot->plotLayout()->addElement(0, 0, new QCPPlotTitle(customPlot, "Your Plot Title"));
13534   \endcode
13535
13536   Since a plot title is a common requirement, QCustomPlot offers specialized selection signals for
13537   easy interaction with QCPPlotTitle. If a layout element of type QCPPlotTitle is clicked, the
13538   signal \ref QCustomPlot::titleClick is emitted. A double click emits the \ref
13539   QCustomPlot::titleDoubleClick signal.
13540 */
13541
13542 /* start documentation of signals */
13543
13544 /*! \fn void QCPPlotTitle::selectionChanged(bool selected)
13545
13546   This signal is emitted when the selection state has changed to \a selected, either by user
13547   interaction or by a direct call to \ref setSelected.
13548
13549   \see setSelected, setSelectable
13550 */
13551
13552 /* end documentation of signals */
13553
13554 /*!
13555   Creates a new QCPPlotTitle instance and sets default values. The initial text is empty (\ref setText).
13556
13557   To set the title text in the constructor, rather use \ref QCPPlotTitle(QCustomPlot *parentPlot, const QString &text).
13558 */
13559 QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot) :
13560   QCPLayoutElement(parentPlot),
13561   mFont(QFont(QLatin1String("sans serif"), 13*1.5, QFont::Bold)),
13562   mTextColor(Qt::black),
13563   mSelectedFont(QFont(QLatin1String("sans serif"), 13*1.6, QFont::Bold)),
13564   mSelectedTextColor(Qt::blue),
13565   mSelectable(false),
13566   mSelected(false)
13567 {
13568   if (parentPlot)
13569   {
13570     setLayer(parentPlot->currentLayer());
13571     mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold);
13572     mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold);
13573   }
13574   setMargins(QMargins(5, 5, 5, 0));
13575 }
13576
13577 /*! \overload
13578
13579   Creates a new QCPPlotTitle instance and sets default values. The initial text is set to \a text.
13580 */
13581 QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot, const QString &text) :
13582   QCPLayoutElement(parentPlot),
13583   mText(text),
13584   mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)),
13585   mTextColor(Qt::black),
13586   mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)),
13587   mSelectedTextColor(Qt::blue),
13588   mSelectable(false),
13589   mSelected(false)
13590 {
13591   setLayer(QLatin1String("axes"));
13592   setMargins(QMargins(5, 5, 5, 0));
13593 }
13594
13595 /*!
13596   Sets the text that will be displayed to \a text. Multiple lines can be created by insertion of "\n".
13597
13598   \see setFont, setTextColor
13599 */
13600 void QCPPlotTitle::setText(const QString &text)
13601 {
13602   mText = text;
13603 }
13604
13605 /*!
13606   Sets the \a font of the title text.
13607
13608   \see setTextColor, setSelectedFont
13609 */
13610 void QCPPlotTitle::setFont(const QFont &font)
13611 {
13612   mFont = font;
13613 }
13614
13615 /*!
13616   Sets the \a color of the title text.
13617
13618   \see setFont, setSelectedTextColor
13619 */
13620 void QCPPlotTitle::setTextColor(const QColor &color)
13621 {
13622   mTextColor = color;
13623 }
13624
13625 /*!
13626   Sets the \a font of the title text that will be used if the plot title is selected (\ref setSelected).
13627
13628   \see setFont
13629 */
13630 void QCPPlotTitle::setSelectedFont(const QFont &font)
13631 {
13632   mSelectedFont = font;
13633 }
13634
13635 /*!
13636   Sets the \a color of the title text that will be used if the plot title is selected (\ref setSelected).
13637
13638   \see setTextColor
13639 */
13640 void QCPPlotTitle::setSelectedTextColor(const QColor &color)
13641 {
13642   mSelectedTextColor = color;
13643 }
13644
13645 /*!
13646   Sets whether the user may select this plot title to \a selectable.
13647
13648   Note that even when \a selectable is set to <tt>false</tt>, the selection state may be changed
13649   programmatically via \ref setSelected.
13650 */
13651 void QCPPlotTitle::setSelectable(bool selectable)
13652 {
13653   if (mSelectable != selectable)
13654   {
13655     mSelectable = selectable;
13656     emit selectableChanged(mSelectable);
13657   }
13658 }
13659
13660 /*!
13661   Sets the selection state of this plot title to \a selected. If the selection has changed, \ref
13662   selectionChanged is emitted.
13663
13664   Note that this function can change the selection state independently of the current \ref
13665   setSelectable state.
13666 */
13667 void QCPPlotTitle::setSelected(bool selected)
13668 {
13669   if (mSelected != selected)
13670   {
13671     mSelected = selected;
13672     emit selectionChanged(mSelected);
13673   }
13674 }
13675
13676 /* inherits documentation from base class */
13677 void QCPPlotTitle::applyDefaultAntialiasingHint(QCPPainter *painter) const
13678 {
13679   applyAntialiasingHint(painter, mAntialiased, QCP::aeNone);
13680 }
13681
13682 /* inherits documentation from base class */
13683 void QCPPlotTitle::draw(QCPPainter *painter)
13684 {
13685   painter->setFont(mainFont());
13686   painter->setPen(QPen(mainTextColor()));
13687   painter->drawText(mRect, Qt::AlignCenter, mText, &mTextBoundingRect);
13688 }
13689
13690 /* inherits documentation from base class */
13691 QSize QCPPlotTitle::minimumSizeHint() const
13692 {
13693   QFontMetrics metrics(mFont);
13694   QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size();
13695   result.rwidth() += mMargins.left() + mMargins.right();
13696   result.rheight() += mMargins.top() + mMargins.bottom();
13697   return result;
13698 }
13699
13700 /* inherits documentation from base class */
13701 QSize QCPPlotTitle::maximumSizeHint() const
13702 {
13703   QFontMetrics metrics(mFont);
13704   QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size();
13705   result.rheight() += mMargins.top() + mMargins.bottom();
13706   result.setWidth(QWIDGETSIZE_MAX);
13707   return result;
13708 }
13709
13710 /* inherits documentation from base class */
13711 void QCPPlotTitle::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13712 {
13713   Q_UNUSED(event)
13714   Q_UNUSED(details)
13715   if (mSelectable)
13716   {
13717     bool selBefore = mSelected;
13718     setSelected(additive ? !mSelected : true);
13719     if (selectionStateChanged)
13720       *selectionStateChanged = mSelected != selBefore;
13721   }
13722 }
13723
13724 /* inherits documentation from base class */
13725 void QCPPlotTitle::deselectEvent(bool *selectionStateChanged)
13726 {
13727   if (mSelectable)
13728   {
13729     bool selBefore = mSelected;
13730     setSelected(false);
13731     if (selectionStateChanged)
13732       *selectionStateChanged = mSelected != selBefore;
13733   }
13734 }
13735
13736 /* inherits documentation from base class */
13737 double QCPPlotTitle::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
13738 {
13739   Q_UNUSED(details)
13740   if (onlySelectable && !mSelectable)
13741     return -1;
13742
13743   if (mTextBoundingRect.contains(pos.toPoint()))
13744     return mParentPlot->selectionTolerance()*0.99;
13745   else
13746     return -1;
13747 }
13748
13749 /*! \internal
13750
13751   Returns the main font to be used. This is mSelectedFont if \ref setSelected is set to
13752   <tt>true</tt>, else mFont is returned.
13753 */
13754 QFont QCPPlotTitle::mainFont() const
13755 {
13756   return mSelected ? mSelectedFont : mFont;
13757 }
13758
13759 /*! \internal
13760
13761   Returns the main color to be used. This is mSelectedTextColor if \ref setSelected is set to
13762   <tt>true</tt>, else mTextColor is returned.
13763 */
13764 QColor QCPPlotTitle::mainTextColor() const
13765 {
13766   return mSelected ? mSelectedTextColor : mTextColor;
13767 }
13768
13769
13770 ////////////////////////////////////////////////////////////////////////////////////////////////////
13771 //////////////////// QCPColorScale
13772 ////////////////////////////////////////////////////////////////////////////////////////////////////
13773
13774 /*! \class QCPColorScale
13775   \brief A color scale for use with color coding data such as QCPColorMap
13776
13777   This layout element can be placed on the plot to correlate a color gradient with data values. It
13778   is usually used in combination with one or multiple \ref QCPColorMap "QCPColorMaps".
13779
13780   \image html QCPColorScale.png
13781
13782   The color scale can be either horizontal or vertical, as shown in the image above. The
13783   orientation and the side where the numbers appear is controlled with \ref setType.
13784
13785   Use \ref QCPColorMap::setColorScale to connect a color map with a color scale. Once they are
13786   connected, they share their gradient, data range and data scale type (\ref setGradient, \ref
13787   setDataRange, \ref setDataScaleType). Multiple color maps may be associated with a single color
13788   scale, to make them all synchronize these properties.
13789
13790   To have finer control over the number display and axis behaviour, you can directly access the
13791   \ref axis. See the documentation of QCPAxis for details about configuring axes. For example, if
13792   you want to change the number of automatically generated ticks, call
13793   \code
13794   colorScale->axis()->setAutoTickCount(3);
13795   \endcode
13796
13797   Placing a color scale next to the main axis rect works like with any other layout element:
13798   \code
13799   QCPColorScale *colorScale = new QCPColorScale(customPlot);
13800   customPlot->plotLayout()->addElement(0, 1, colorScale);
13801   colorScale->setLabel("Some Label Text");
13802   \endcode
13803   In this case we have placed it to the right of the default axis rect, so it wasn't necessary to
13804   call \ref setType, since \ref QCPAxis::atRight is already the default. The text next to the color
13805   scale can be set with \ref setLabel.
13806
13807   For optimum appearance (like in the image above), it may be desirable to line up the axis rect and
13808   the borders of the color scale. Use a \ref QCPMarginGroup to achieve this:
13809   \code
13810   QCPMarginGroup *group = new QCPMarginGroup(customPlot);
13811   colorScale->setMarginGroup(QCP::msTop|QCP::msBottom, group);
13812   customPlot->axisRect()->setMarginGroup(QCP::msTop|QCP::msBottom, group);
13813   \endcode
13814
13815   Color scales are initialized with a non-zero minimum top and bottom margin (\ref
13816   setMinimumMargins), because vertical color scales are most common and the minimum top/bottom
13817   margin makes sure it keeps some distance to the top/bottom widget border. So if you change to a
13818   horizontal color scale by setting \ref setType to \ref QCPAxis::atBottom or \ref QCPAxis::atTop, you
13819   might want to also change the minimum margins accordingly, e.g. <tt>setMinimumMargins(QMargins(6, 0, 6, 0))</tt>.
13820 */
13821
13822 /* start documentation of inline functions */
13823
13824 /*! \fn QCPAxis *QCPColorScale::axis() const
13825
13826   Returns the internal \ref QCPAxis instance of this color scale. You can access it to alter the
13827   appearance and behaviour of the axis. \ref QCPColorScale duplicates some properties in its
13828   interface for convenience. Those are \ref setDataRange (\ref QCPAxis::setRange), \ref
13829   setDataScaleType (\ref QCPAxis::setScaleType), and the method \ref setLabel (\ref
13830   QCPAxis::setLabel). As they each are connected, it does not matter whether you use the method on
13831   the QCPColorScale or on its QCPAxis.
13832
13833   If the type of the color scale is changed with \ref setType, the axis returned by this method
13834   will change, too, to either the left, right, bottom or top axis, depending on which type was set.
13835 */
13836
13837 /* end documentation of signals */
13838 /* start documentation of signals */
13839
13840 /*! \fn void QCPColorScale::dataRangeChanged(QCPRange newRange);
13841
13842   This signal is emitted when the data range changes.
13843
13844   \see setDataRange
13845 */
13846
13847 /*! \fn void QCPColorScale::dataScaleTypeChanged(QCPAxis::ScaleType scaleType);
13848
13849   This signal is emitted when the data scale type changes.
13850
13851   \see setDataScaleType
13852 */
13853
13854 /*! \fn void QCPColorScale::gradientChanged(QCPColorGradient newGradient);
13855
13856   This signal is emitted when the gradient changes.
13857
13858   \see setGradient
13859 */
13860
13861 /* end documentation of signals */
13862
13863 /*!
13864   Constructs a new QCPColorScale.
13865 */
13866 QCPColorScale::QCPColorScale(QCustomPlot *parentPlot) :
13867   QCPLayoutElement(parentPlot),
13868   mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight
13869   mDataScaleType(QCPAxis::stLinear),
13870   mBarWidth(20),
13871   mAxisRect(new QCPColorScaleAxisRectPrivate(this))
13872 {
13873   setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used)
13874   setType(QCPAxis::atRight);
13875   setDataRange(QCPRange(0, 6));
13876 }
13877
13878 QCPColorScale::~QCPColorScale()
13879 {
13880   delete mAxisRect;
13881 }
13882
13883 /* undocumented getter */
13884 QString QCPColorScale::label() const
13885 {
13886   if (!mColorAxis)
13887   {
13888     qDebug() << Q_FUNC_INFO << "internal color axis undefined";
13889     return QString();
13890   }
13891
13892   return mColorAxis.data()->label();
13893 }
13894
13895 /* undocumented getter */
13896 bool QCPColorScale::rangeDrag() const
13897 {
13898   if (!mAxisRect)
13899   {
13900     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13901     return false;
13902   }
13903
13904   return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) &&
13905       mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) &&
13906       mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
13907 }
13908
13909 /* undocumented getter */
13910 bool QCPColorScale::rangeZoom() const
13911 {
13912   if (!mAxisRect)
13913   {
13914     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13915     return false;
13916   }
13917
13918   return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) &&
13919       mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) &&
13920       mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
13921 }
13922
13923 /*!
13924   Sets at which side of the color scale the axis is placed, and thus also its orientation.
13925
13926   Note that after setting \a type to a different value, the axis returned by \ref axis() will
13927   be a different one. The new axis will adopt the following properties from the previous axis: The
13928   range, scale type, log base and label.
13929 */
13930 void QCPColorScale::setType(QCPAxis::AxisType type)
13931 {
13932   if (!mAxisRect)
13933   {
13934     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13935     return;
13936   }
13937   if (mType != type)
13938   {
13939     mType = type;
13940     QCPRange rangeTransfer(0, 6);
13941     double logBaseTransfer = 10;
13942     QString labelTransfer;
13943     // revert some settings on old axis:
13944     if (mColorAxis)
13945     {
13946       rangeTransfer = mColorAxis.data()->range();
13947       labelTransfer = mColorAxis.data()->label();
13948       logBaseTransfer = mColorAxis.data()->scaleLogBase();
13949       mColorAxis.data()->setLabel(QString());
13950       disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
13951       disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
13952     }
13953     foreach (QCPAxis::AxisType atype, QList<QCPAxis::AxisType>() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop)
13954     {
13955       mAxisRect.data()->axis(atype)->setTicks(atype == mType);
13956       mAxisRect.data()->axis(atype)->setTickLabels(atype== mType);
13957     }
13958     // set new mColorAxis pointer:
13959     mColorAxis = mAxisRect.data()->axis(mType);
13960     // transfer settings to new axis:
13961     mColorAxis.data()->setRange(rangeTransfer); // transfer range of old axis to new one (necessary if axis changes from vertical to horizontal or vice versa)
13962     mColorAxis.data()->setLabel(labelTransfer);
13963     mColorAxis.data()->setScaleLogBase(logBaseTransfer); // scaleType is synchronized among axes in realtime via signals (connected in QCPColorScale ctor), so we only need to take care of log base here
13964     connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
13965     connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
13966     mAxisRect.data()->setRangeDragAxes(QCPAxis::orientation(mType) == Qt::Horizontal ? mColorAxis.data() : 0,
13967                                        QCPAxis::orientation(mType) == Qt::Vertical ? mColorAxis.data() : 0);
13968   }
13969 }
13970
13971 /*!
13972   Sets the range spanned by the color gradient and that is shown by the axis in the color scale.
13973
13974   It is equivalent to calling QCPColorMap::setDataRange on any of the connected color maps. It is
13975   also equivalent to directly accessing the \ref axis and setting its range with \ref
13976   QCPAxis::setRange.
13977
13978   \see setDataScaleType, setGradient, rescaleDataRange
13979 */
13980 void QCPColorScale::setDataRange(const QCPRange &dataRange)
13981 {
13982   if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper)
13983   {
13984     mDataRange = dataRange;
13985     if (mColorAxis)
13986       mColorAxis.data()->setRange(mDataRange);
13987     emit dataRangeChanged(mDataRange);
13988   }
13989 }
13990
13991 /*!
13992   Sets the scale type of the color scale, i.e. whether values are linearly associated with colors
13993   or logarithmically.
13994
13995   It is equivalent to calling QCPColorMap::setDataScaleType on any of the connected color maps. It is
13996   also equivalent to directly accessing the \ref axis and setting its scale type with \ref
13997   QCPAxis::setScaleType.
13998
13999   \see setDataRange, setGradient
14000 */
14001 void QCPColorScale::setDataScaleType(QCPAxis::ScaleType scaleType)
14002 {
14003   if (mDataScaleType != scaleType)
14004   {
14005     mDataScaleType = scaleType;
14006     if (mColorAxis)
14007       mColorAxis.data()->setScaleType(mDataScaleType);
14008     if (mDataScaleType == QCPAxis::stLogarithmic)
14009       setDataRange(mDataRange.sanitizedForLogScale());
14010     emit dataScaleTypeChanged(mDataScaleType);
14011   }
14012 }
14013
14014 /*!
14015   Sets the color gradient that will be used to represent data values.
14016
14017   It is equivalent to calling QCPColorMap::setGradient on any of the connected color maps.
14018
14019   \see setDataRange, setDataScaleType
14020 */
14021 void QCPColorScale::setGradient(const QCPColorGradient &gradient)
14022 {
14023   if (mGradient != gradient)
14024   {
14025     mGradient = gradient;
14026     if (mAxisRect)
14027       mAxisRect.data()->mGradientImageInvalidated = true;
14028     emit gradientChanged(mGradient);
14029   }
14030 }
14031
14032 /*!
14033   Sets the axis label of the color scale. This is equivalent to calling \ref QCPAxis::setLabel on
14034   the internal \ref axis.
14035 */
14036 void QCPColorScale::setLabel(const QString &str)
14037 {
14038   if (!mColorAxis)
14039   {
14040     qDebug() << Q_FUNC_INFO << "internal color axis undefined";
14041     return;
14042   }
14043
14044   mColorAxis.data()->setLabel(str);
14045 }
14046
14047 /*!
14048   Sets the width (or height, for horizontal color scales) the bar where the gradient is displayed
14049   will have.
14050 */
14051 void QCPColorScale::setBarWidth(int width)
14052 {
14053   mBarWidth = width;
14054 }
14055
14056 /*!
14057   Sets whether the user can drag the data range (\ref setDataRange).
14058
14059   Note that \ref QCP::iRangeDrag must be in the QCustomPlot's interactions (\ref
14060   QCustomPlot::setInteractions) to allow range dragging.
14061 */
14062 void QCPColorScale::setRangeDrag(bool enabled)
14063 {
14064   if (!mAxisRect)
14065   {
14066     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14067     return;
14068   }
14069
14070   if (enabled)
14071     mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType));
14072   else
14073     mAxisRect.data()->setRangeDrag(0);
14074 }
14075
14076 /*!
14077   Sets whether the user can zoom the data range (\ref setDataRange) by scrolling the mouse wheel.
14078
14079   Note that \ref QCP::iRangeZoom must be in the QCustomPlot's interactions (\ref
14080   QCustomPlot::setInteractions) to allow range dragging.
14081 */
14082 void QCPColorScale::setRangeZoom(bool enabled)
14083 {
14084   if (!mAxisRect)
14085   {
14086     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14087     return;
14088   }
14089
14090   if (enabled)
14091     mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType));
14092   else
14093     mAxisRect.data()->setRangeZoom(0);
14094 }
14095
14096 /*!
14097   Returns a list of all the color maps associated with this color scale.
14098 */
14099 QList<QCPColorMap*> QCPColorScale::colorMaps() const
14100 {
14101   QList<QCPColorMap*> result;
14102   for (int i=0; i<mParentPlot->plottableCount(); ++i)
14103   {
14104     if (QCPColorMap *cm = qobject_cast<QCPColorMap*>(mParentPlot->plottable(i)))
14105       if (cm->colorScale() == this)
14106         result.append(cm);
14107   }
14108   return result;
14109 }
14110
14111 /*!
14112   Changes the data range such that all color maps associated with this color scale are fully mapped
14113   to the gradient in the data dimension.
14114
14115   \see setDataRange
14116 */
14117 void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps)
14118 {
14119   QList<QCPColorMap*> maps = colorMaps();
14120   QCPRange newRange;
14121   bool haveRange = false;
14122   int sign = 0; // TODO: should change this to QCPAbstractPlottable::SignDomain later (currently is protected, maybe move to QCP namespace)
14123   if (mDataScaleType == QCPAxis::stLogarithmic)
14124     sign = (mDataRange.upper < 0 ? -1 : 1);
14125   for (int i=0; i<maps.size(); ++i)
14126   {
14127     if (!maps.at(i)->realVisibility() && onlyVisibleMaps)
14128       continue;
14129     QCPRange mapRange;
14130     if (maps.at(i)->colorScale() == this)
14131     {
14132       bool currentFoundRange = true;
14133       mapRange = maps.at(i)->data()->dataBounds();
14134       if (sign == 1)
14135       {
14136         if (mapRange.lower <= 0 && mapRange.upper > 0)
14137           mapRange.lower = mapRange.upper*1e-3;
14138         else if (mapRange.lower <= 0 && mapRange.upper <= 0)
14139           currentFoundRange = false;
14140       } else if (sign == -1)
14141       {
14142         if (mapRange.upper >= 0 && mapRange.lower < 0)
14143           mapRange.upper = mapRange.lower*1e-3;
14144         else if (mapRange.upper >= 0 && mapRange.lower >= 0)
14145           currentFoundRange = false;
14146       }
14147       if (currentFoundRange)
14148       {
14149         if (!haveRange)
14150           newRange = mapRange;
14151         else
14152           newRange.expand(mapRange);
14153         haveRange = true;
14154       }
14155     }
14156   }
14157   if (haveRange)
14158   {
14159     if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data
14160     {
14161       double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
14162       if (mDataScaleType == QCPAxis::stLinear)
14163       {
14164         newRange.lower = center-mDataRange.size()/2.0;
14165         newRange.upper = center+mDataRange.size()/2.0;
14166       } else // mScaleType == stLogarithmic
14167       {
14168         newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower);
14169         newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower);
14170       }
14171     }
14172     setDataRange(newRange);
14173   }
14174 }
14175
14176 /* inherits documentation from base class */
14177 void QCPColorScale::update(UpdatePhase phase)
14178 {
14179   QCPLayoutElement::update(phase);
14180   if (!mAxisRect)
14181   {
14182     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14183     return;
14184   }
14185
14186   mAxisRect.data()->update(phase);
14187
14188   switch (phase)
14189   {
14190     case upMargins:
14191     {
14192       if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop)
14193       {
14194         setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom());
14195         setMinimumSize(0,               mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom());
14196       } else
14197       {
14198         setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), QWIDGETSIZE_MAX);
14199         setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), 0);
14200       }
14201       break;
14202     }
14203     case upLayout:
14204     {
14205       mAxisRect.data()->setOuterRect(rect());
14206       break;
14207     }
14208     default: break;
14209   }
14210 }
14211
14212 /* inherits documentation from base class */
14213 void QCPColorScale::applyDefaultAntialiasingHint(QCPPainter *painter) const
14214 {
14215   painter->setAntialiasing(false);
14216 }
14217
14218 /* inherits documentation from base class */
14219 void QCPColorScale::mousePressEvent(QMouseEvent *event)
14220 {
14221   if (!mAxisRect)
14222   {
14223     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14224     return;
14225   }
14226   mAxisRect.data()->mousePressEvent(event);
14227 }
14228
14229 /* inherits documentation from base class */
14230 void QCPColorScale::mouseMoveEvent(QMouseEvent *event)
14231 {
14232   if (!mAxisRect)
14233   {
14234     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14235     return;
14236   }
14237   mAxisRect.data()->mouseMoveEvent(event);
14238 }
14239
14240 /* inherits documentation from base class */
14241 void QCPColorScale::mouseReleaseEvent(QMouseEvent *event)
14242 {
14243   if (!mAxisRect)
14244   {
14245     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14246     return;
14247   }
14248   mAxisRect.data()->mouseReleaseEvent(event);
14249 }
14250
14251 /* inherits documentation from base class */
14252 void QCPColorScale::wheelEvent(QWheelEvent *event)
14253 {
14254   if (!mAxisRect)
14255   {
14256     qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14257     return;
14258   }
14259   mAxisRect.data()->wheelEvent(event);
14260 }
14261
14262 ////////////////////////////////////////////////////////////////////////////////////////////////////
14263 //////////////////// QCPColorScaleAxisRectPrivate
14264 ////////////////////////////////////////////////////////////////////////////////////////////////////
14265
14266 /*! \class QCPColorScaleAxisRectPrivate
14267
14268   \internal
14269   \brief An axis rect subclass for use in a QCPColorScale
14270
14271   This is a private class and not part of the public QCustomPlot interface.
14272
14273   It provides the axis rect functionality for the QCPColorScale class.
14274 */
14275
14276
14277 /*!
14278   Creates a new instance, as a child of \a parentColorScale.
14279 */
14280 QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale) :
14281   QCPAxisRect(parentColorScale->parentPlot(), true),
14282   mParentColorScale(parentColorScale),
14283   mGradientImageInvalidated(true)
14284 {
14285   setParentLayerable(parentColorScale);
14286   setMinimumMargins(QMargins(0, 0, 0, 0));
14287   foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14288   {
14289     axis(type)->setVisible(true);
14290     axis(type)->grid()->setVisible(false);
14291     axis(type)->setPadding(0);
14292     connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts)));
14293     connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts)));
14294   }
14295
14296   connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange)));
14297   connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange)));
14298   connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange)));
14299   connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
14300   connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType)));
14301   connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType)));
14302   connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType)));
14303   connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType)));
14304
14305   // make layer transfers of color scale transfer to axis rect and axes
14306   // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect:
14307   connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*)));
14308   foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14309     connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*)));
14310 }
14311
14312 /*! \internal
14313   Updates the color gradient image if necessary, by calling \ref updateGradientImage, then draws
14314   it. Then the axes are drawn by calling the \ref QCPAxisRect::draw base class implementation.
14315 */
14316 void QCPColorScaleAxisRectPrivate::draw(QCPPainter *painter)
14317 {
14318   if (mGradientImageInvalidated)
14319     updateGradientImage();
14320
14321   bool mirrorHorz = false;
14322   bool mirrorVert = false;
14323   if (mParentColorScale->mColorAxis)
14324   {
14325     mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop);
14326     mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight);
14327   }
14328
14329   painter->drawImage(rect(), mGradientImage.mirrored(mirrorHorz, mirrorVert));
14330   QCPAxisRect::draw(painter);
14331 }
14332
14333 /*! \internal
14334
14335   Uses the current gradient of the parent \ref QCPColorScale (specified in the constructor) to
14336   generate a gradient image. This gradient image will be used in the \ref draw method.
14337 */
14338 void QCPColorScaleAxisRectPrivate::updateGradientImage()
14339 {
14340   if (rect().isEmpty())
14341     return;
14342
14343   int n = mParentColorScale->mGradient.levelCount();
14344   int w, h;
14345   QVector<double> data(n);
14346   for (int i=0; i<n; ++i)
14347     data[i] = i;
14348   if (mParentColorScale->mType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop)
14349   {
14350     w = n;
14351     h = rect().height();
14352     mGradientImage = QImage(w, h, QImage::Format_RGB32);
14353     QVector<QRgb*> pixels;
14354     for (int y=0; y<h; ++y)
14355       pixels.append(reinterpret_cast<QRgb*>(mGradientImage.scanLine(y)));
14356     mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n);
14357     for (int y=1; y<h; ++y)
14358       memcpy(pixels.at(y), pixels.first(), n*sizeof(QRgb));
14359   } else
14360   {
14361     w = rect().width();
14362     h = n;
14363     mGradientImage = QImage(w, h, QImage::Format_RGB32);
14364     for (int y=0; y<h; ++y)
14365     {
14366       QRgb *pixels = reinterpret_cast<QRgb*>(mGradientImage.scanLine(y));
14367       const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1));
14368       for (int x=0; x<w; ++x)
14369         pixels[x] = lineColor;
14370     }
14371   }
14372   mGradientImageInvalidated = false;
14373 }
14374
14375 /*! \internal
14376
14377   This slot is connected to the selectionChanged signals of the four axes in the constructor. It
14378   synchronizes the selection state of the axes.
14379 */
14380 void QCPColorScaleAxisRectPrivate::axisSelectionChanged(QCPAxis::SelectableParts selectedParts)
14381 {
14382   // axis bases of four axes shall always (de-)selected synchronously:
14383   foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14384   {
14385     if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14386       if (senderAxis->axisType() == type)
14387         continue;
14388
14389     if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
14390     {
14391       if (selectedParts.testFlag(QCPAxis::spAxis))
14392         axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis);
14393       else
14394         axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis);
14395     }
14396   }
14397 }
14398
14399 /*! \internal
14400
14401   This slot is connected to the selectableChanged signals of the four axes in the constructor. It
14402   synchronizes the selectability of the axes.
14403 */
14404 void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts)
14405 {
14406   // synchronize axis base selectability:
14407   foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14408   {
14409     if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14410       if (senderAxis->axisType() == type)
14411         continue;
14412
14413     if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
14414     {
14415       if (selectableParts.testFlag(QCPAxis::spAxis))
14416         axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis);
14417       else
14418         axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis);
14419     }
14420   }
14421 }
14422
14423
14424 ////////////////////////////////////////////////////////////////////////////////////////////////////
14425 //////////////////// QCPData
14426 ////////////////////////////////////////////////////////////////////////////////////////////////////
14427
14428 /*! \class QCPData
14429   \brief Holds the data of one single data point for QCPGraph.
14430
14431   The container for storing multiple data points is \ref QCPDataMap.
14432
14433   The stored data is:
14434   \li \a key: coordinate on the key axis of this data point
14435   \li \a value: coordinate on the value axis of this data point
14436   \li \a keyErrorMinus: negative error in the key dimension (for error bars)
14437   \li \a keyErrorPlus: positive error in the key dimension (for error bars)
14438   \li \a valueErrorMinus: negative error in the value dimension (for error bars)
14439   \li \a valueErrorPlus: positive error in the value dimension (for error bars)
14440
14441   \see QCPDataMap
14442 */
14443
14444 /*!
14445   Constructs a data point with key, value and all errors set to zero.
14446 */
14447 QCPData::QCPData() :
14448   key(0),
14449   value(0),
14450   keyErrorPlus(0),
14451   keyErrorMinus(0),
14452   valueErrorPlus(0),
14453   valueErrorMinus(0)
14454 {
14455 }
14456
14457 /*!
14458   Constructs a data point with the specified \a key and \a value. All errors are set to zero.
14459 */
14460 QCPData::QCPData(double key, double value) :
14461   key(key),
14462   value(value),
14463   keyErrorPlus(0),
14464   keyErrorMinus(0),
14465   valueErrorPlus(0),
14466   valueErrorMinus(0)
14467 {
14468 }
14469
14470
14471 ////////////////////////////////////////////////////////////////////////////////////////////////////
14472 //////////////////// QCPGraph
14473 ////////////////////////////////////////////////////////////////////////////////////////////////////
14474
14475 /*! \class QCPGraph
14476   \brief A plottable representing a graph in a plot.
14477
14478   \image html QCPGraph.png
14479
14480   Usually QCustomPlot creates graphs internally via QCustomPlot::addGraph and the resulting
14481   instance is accessed via QCustomPlot::graph.
14482
14483   To plot data, assign it with the \ref setData or \ref addData functions. Alternatively, you can
14484   also access and modify the graph's data via the \ref data method, which returns a pointer to the
14485   internal \ref QCPDataMap.
14486
14487   Graphs are used to display single-valued data. Single-valued means that there should only be one
14488   data point per unique key coordinate. In other words, the graph can't have \a loops. If you do
14489   want to plot non-single-valued curves, rather use the QCPCurve plottable.
14490
14491   \section appearance Changing the appearance
14492
14493   The appearance of the graph is mainly determined by the line style, scatter style, brush and pen
14494   of the graph (\ref setLineStyle, \ref setScatterStyle, \ref setBrush, \ref setPen).
14495
14496   \subsection filling Filling under or between graphs
14497
14498   QCPGraph knows two types of fills: Normal graph fills towards the zero-value-line parallel to
14499   the key axis of the graph, and fills between two graphs, called channel fills. To enable a fill,
14500   just set a brush with \ref setBrush which is neither Qt::NoBrush nor fully transparent.
14501
14502   By default, a normal fill towards the zero-value-line will be drawn. To set up a channel fill
14503   between this graph and another one, call \ref setChannelFillGraph with the other graph as
14504   parameter.
14505
14506   \see QCustomPlot::addGraph, QCustomPlot::graph, QCPLegend::addGraph
14507 */
14508
14509 /* start of documentation of inline functions */
14510
14511 /*! \fn QCPDataMap *QCPGraph::data() const
14512
14513   Returns a pointer to the internal data storage of type \ref QCPDataMap. You may use it to
14514   directly manipulate the data, which may be more convenient and faster than using the regular \ref
14515   setData or \ref addData methods, in certain situations.
14516 */
14517
14518 /* end of documentation of inline functions */
14519
14520 /*!
14521   Constructs a graph which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value
14522   axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have
14523   the same orientation. If either of these restrictions is violated, a corresponding message is
14524   printed to the debug output (qDebug), the construction is not aborted, though.
14525
14526   The constructed QCPGraph can be added to the plot with QCustomPlot::addPlottable, QCustomPlot
14527   then takes ownership of the graph.
14528
14529   To directly create a graph inside a plot, you can also use the simpler QCustomPlot::addGraph function.
14530 */
14531 QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) :
14532   QCPAbstractPlottable(keyAxis, valueAxis)
14533 {
14534   mData = new QCPDataMap;
14535
14536   setPen(QPen(Qt::blue, 0));
14537   setErrorPen(QPen(Qt::black));
14538   setBrush(Qt::NoBrush);
14539   setSelectedPen(QPen(QColor(80, 80, 255), 2.5));
14540   setSelectedBrush(Qt::NoBrush);
14541
14542   setLineStyle(lsLine);
14543   setErrorType(etNone);
14544   setErrorBarSize(6);
14545   setErrorBarSkipSymbol(true);
14546   setChannelFillGraph(0);
14547   setAdaptiveSampling(true);
14548 }
14549
14550 QCPGraph::~QCPGraph()
14551 {
14552   delete mData;
14553 }
14554
14555 /*!
14556   Replaces the current data with the provided \a data.
14557
14558   If \a copy is set to true, data points in \a data will only be copied. if false, the graph
14559   takes ownership of the passed data and replaces the internal data pointer with it. This is
14560   significantly faster than copying for large datasets.
14561
14562   Alternatively, you can also access and modify the graph's data via the \ref data method, which
14563   returns a pointer to the internal \ref QCPDataMap.
14564 */
14565 void QCPGraph::setData(QCPDataMap *data, bool copy)
14566 {
14567   if (mData == data)
14568   {
14569     qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
14570     return;
14571   }
14572   if (copy)
14573   {
14574     *mData = *data;
14575   } else
14576   {
14577     delete mData;
14578     mData = data;
14579   }
14580 }
14581
14582 /*! \overload
14583
14584   Replaces the current data with the provided points in \a key and \a value pairs. The provided
14585   vectors should have equal length. Else, the number of added points will be the size of the
14586   smallest vector.
14587 */
14588 void QCPGraph::setData(const QVector<double> &key, const QVector<double> &value)
14589 {
14590   mData->clear();
14591   int n = key.size();
14592   n = qMin(n, value.size());
14593   QCPData newData;
14594   for (int i=0; i<n; ++i)
14595   {
14596     newData.key = key[i];
14597     newData.value = value[i];
14598     mData->insertMulti(newData.key, newData);
14599   }
14600 }
14601
14602 /*!
14603   Replaces the current data with the provided points in \a key and \a value pairs. Additionally the
14604   symmetrical value error of the data points are set to the values in \a valueError.
14605   For error bars to show appropriately, see \ref setErrorType.
14606   The provided vectors should have equal length. Else, the number of added points will be the size of the
14607   smallest vector.
14608
14609   For asymmetrical errors (plus different from minus), see the overloaded version of this function.
14610 */
14611 void QCPGraph::setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueError)
14612 {
14613   mData->clear();
14614   int n = key.size();
14615   n = qMin(n, value.size());
14616   n = qMin(n, valueError.size());
14617   QCPData newData;
14618   for (int i=0; i<n; ++i)
14619   {
14620     newData.key = key[i];
14621     newData.value = value[i];
14622     newData.valueErrorMinus = valueError[i];
14623     newData.valueErrorPlus = valueError[i];
14624     mData->insertMulti(key[i], newData);
14625   }
14626 }
14627
14628 /*!
14629   \overload
14630   Replaces the current data with the provided points in \a key and \a value pairs. Additionally the
14631   negative value error of the data points are set to the values in \a valueErrorMinus, the positive
14632   value error to \a valueErrorPlus.
14633   For error bars to show appropriately, see \ref setErrorType.
14634   The provided vectors should have equal length. Else, the number of added points will be the size of the
14635   smallest vector.
14636 */
14637 void QCPGraph::setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus)
14638 {
14639   mData->clear();
14640   int n = key.size();
14641   n = qMin(n, value.size());
14642   n = qMin(n, valueErrorMinus.size());
14643   n = qMin(n, valueErrorPlus.size());
14644   QCPData newData;
14645   for (int i=0; i<n; ++i)
14646   {
14647     newData.key = key[i];
14648     newData.value = value[i];
14649     newData.valueErrorMinus = valueErrorMinus[i];
14650     newData.valueErrorPlus = valueErrorPlus[i];
14651     mData->insertMulti(key[i], newData);
14652   }
14653 }
14654
14655 /*!
14656   Replaces the current data with the provided points in \a key and \a value pairs. Additionally the
14657   symmetrical key error of the data points are set to the values in \a keyError.
14658   For error bars to show appropriately, see \ref setErrorType.
14659   The provided vectors should have equal length. Else, the number of added points will be the size of the
14660   smallest vector.
14661
14662   For asymmetrical errors (plus different from minus), see the overloaded version of this function.
14663 */
14664 void QCPGraph::setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError)
14665 {
14666   mData->clear();
14667   int n = key.size();
14668   n = qMin(n, value.size());
14669   n = qMin(n, keyError.size());
14670   QCPData newData;
14671   for (int i=0; i<n; ++i)
14672   {
14673     newData.key = key[i];
14674     newData.value = value[i];
14675     newData.keyErrorMinus = keyError[i];
14676     newData.keyErrorPlus = keyError[i];
14677     mData->insertMulti(key[i], newData);
14678   }
14679 }
14680
14681 /*!
14682   \overload
14683   Replaces the current data with the provided points in \a key and \a value pairs. Additionally the
14684   negative key error of the data points are set to the values in \a keyErrorMinus, the positive
14685   key error to \a keyErrorPlus.
14686   For error bars to show appropriately, see \ref setErrorType.
14687   The provided vectors should have equal length. Else, the number of added points will be the size of the
14688   smallest vector.
14689 */
14690 void QCPGraph::setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus)
14691 {
14692   mData->clear();
14693   int n = key.size();
14694   n = qMin(n, value.size());
14695   n = qMin(n, keyErrorMinus.size());
14696   n = qMin(n, keyErrorPlus.size());
14697   QCPData newData;
14698   for (int i=0; i<n; ++i)
14699   {
14700     newData.key = key[i];
14701     newData.value = value[i];
14702     newData.keyErrorMinus = keyErrorMinus[i];
14703     newData.keyErrorPlus = keyErrorPlus[i];
14704     mData->insertMulti(key[i], newData);
14705   }
14706 }
14707
14708 /*!
14709   Replaces the current data with the provided points in \a key and \a value pairs. Additionally the
14710   symmetrical key and value errors of the data points are set to the values in \a keyError and \a valueError.
14711   For error bars to show appropriately, see \ref setErrorType.
14712   The provided vectors should have equal length. Else, the number of added points will be the size of the
14713   smallest vector.
14714
14715   For asymmetrical errors (plus different from minus), see the overloaded version of this function.
14716 */
14717 void QCPGraph::setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError, const QVector<double> &valueError)
14718 {
14719   mData->clear();
14720   int n = key.size();
14721   n = qMin(n, value.size());
14722   n = qMin(n, valueError.size());
14723   n = qMin(n, keyError.size());
14724   QCPData newData;
14725   for (int i=0; i<n; ++i)
14726   {
14727     newData.key = key[i];
14728     newData.value = value[i];
14729     newData.keyErrorMinus = keyError[i];
14730     newData.keyErrorPlus = keyError[i];
14731     newData.valueErrorMinus = valueError[i];
14732     newData.valueErrorPlus = valueError[i];
14733     mData->insertMulti(key[i], newData);
14734   }
14735 }
14736
14737 /*!
14738   \overload
14739   Replaces the current data with the provided points in \a key and \a value pairs. Additionally the
14740   negative key and value errors of the data points are set to the values in \a keyErrorMinus and \a valueErrorMinus. The positive
14741   key and value errors are set to the values in \a keyErrorPlus \a valueErrorPlus.
14742   For error bars to show appropriately, see \ref setErrorType.
14743   The provided vectors should have equal length. Else, the number of added points will be the size of the
14744   smallest vector.
14745 */
14746 void QCPGraph::setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus)
14747 {
14748   mData->clear();
14749   int n = key.size();
14750   n = qMin(n, value.size());
14751   n = qMin(n, valueErrorMinus.size());
14752   n = qMin(n, valueErrorPlus.size());
14753   n = qMin(n, keyErrorMinus.size());
14754   n = qMin(n, keyErrorPlus.size());
14755   QCPData newData;
14756   for (int i=0; i<n; ++i)
14757   {
14758     newData.key = key[i];
14759     newData.value = value[i];
14760     newData.keyErrorMinus = keyErrorMinus[i];
14761     newData.keyErrorPlus = keyErrorPlus[i];
14762     newData.valueErrorMinus = valueErrorMinus[i];
14763     newData.valueErrorPlus = valueErrorPlus[i];
14764     mData->insertMulti(key[i], newData);
14765   }
14766 }
14767
14768
14769 /*!
14770   Sets how the single data points are connected in the plot. For scatter-only plots, set \a ls to
14771   \ref lsNone and \ref setScatterStyle to the desired scatter style.
14772
14773   \see setScatterStyle
14774 */
14775 void QCPGraph::setLineStyle(LineStyle ls)
14776 {
14777   mLineStyle = ls;
14778 }
14779
14780 /*!
14781   Sets the visual appearance of single data points in the plot. If set to \ref QCPScatterStyle::ssNone, no scatter points
14782   are drawn (e.g. for line-only-plots with appropriate line style).
14783
14784   \see QCPScatterStyle, setLineStyle
14785 */
14786 void QCPGraph::setScatterStyle(const QCPScatterStyle &style)
14787 {
14788   mScatterStyle = style;
14789 }
14790
14791 /*!
14792   Sets which kind of error bars (Key Error, Value Error or both) should be drawn on each data
14793   point. If you set \a errorType to something other than \ref etNone, make sure to actually pass
14794   error data via the specific setData functions along with the data points (e.g. \ref
14795   setDataValueError, \ref setDataKeyError, \ref setDataBothError).
14796
14797   \see ErrorType
14798 */
14799 void QCPGraph::setErrorType(ErrorType errorType)
14800 {
14801   mErrorType = errorType;
14802 }
14803
14804 /*!
14805   Sets the pen with which the error bars will be drawn.
14806   \see setErrorBarSize, setErrorType
14807 */
14808 void QCPGraph::setErrorPen(const QPen &pen)
14809 {
14810   mErrorPen = pen;
14811 }
14812
14813 /*!
14814   Sets the width of the handles at both ends of an error bar in pixels.
14815 */
14816 void QCPGraph::setErrorBarSize(double size)
14817 {
14818   mErrorBarSize = size;
14819 }
14820
14821 /*!
14822   If \a enabled is set to true, the error bar will not be drawn as a solid line under the scatter symbol but
14823   leave some free space around the symbol.
14824
14825   This feature uses the current scatter size (\ref QCPScatterStyle::setSize) to determine the size
14826   of the area to leave blank. So when drawing Pixmaps as scatter points (\ref
14827   QCPScatterStyle::ssPixmap), the scatter size must be set manually to a value corresponding to the
14828   size of the Pixmap, if the error bars should leave gaps to its boundaries.
14829
14830   \ref setErrorType, setErrorBarSize, setScatterStyle
14831 */
14832 void QCPGraph::setErrorBarSkipSymbol(bool enabled)
14833 {
14834   mErrorBarSkipSymbol = enabled;
14835 }
14836
14837 /*!
14838   Sets the target graph for filling the area between this graph and \a targetGraph with the current
14839   brush (\ref setBrush).
14840
14841   When \a targetGraph is set to 0, a normal graph fill to the zero-value-line will be shown. To
14842   disable any filling, set the brush to Qt::NoBrush.
14843
14844   \see setBrush
14845 */
14846 void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph)
14847 {
14848   // prevent setting channel target to this graph itself:
14849   if (targetGraph == this)
14850   {
14851     qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself";
14852     mChannelFillGraph = 0;
14853     return;
14854   }
14855   // prevent setting channel target to a graph not in the plot:
14856   if (targetGraph && targetGraph->mParentPlot != mParentPlot)
14857   {
14858     qDebug() << Q_FUNC_INFO << "targetGraph not in same plot";
14859     mChannelFillGraph = 0;
14860     return;
14861   }
14862
14863   mChannelFillGraph = targetGraph;
14864 }
14865
14866 /*!
14867   Sets whether adaptive sampling shall be used when plotting this graph. QCustomPlot's adaptive
14868   sampling technique can drastically improve the replot performance for graphs with a larger number
14869   of points (e.g. above 10,000), without notably changing the appearance of the graph.
14870
14871   By default, adaptive sampling is enabled. Even if enabled, QCustomPlot decides whether adaptive
14872   sampling shall actually be used on a per-graph basis. So leaving adaptive sampling enabled has no
14873   disadvantage in almost all cases.
14874
14875   \image html adaptive-sampling-line.png "A line plot of 500,000 points without and with adaptive sampling"
14876
14877   As can be seen, line plots experience no visual degradation from adaptive sampling. Outliers are
14878   reproduced reliably, as well as the overall shape of the data set. The replot time reduces
14879   dramatically though. This allows QCustomPlot to display large amounts of data in realtime.
14880
14881   \image html adaptive-sampling-scatter.png "A scatter plot of 100,000 points without and with adaptive sampling"
14882
14883   Care must be taken when using high-density scatter plots in combination with adaptive sampling.
14884   The adaptive sampling algorithm treats scatter plots more carefully than line plots which still
14885   gives a significant reduction of replot times, but not quite as much as for line plots. This is
14886   because scatter plots inherently need more data points to be preserved in order to still resemble
14887   the original, non-adaptive-sampling plot. As shown above, the results still aren't quite
14888   identical, as banding occurs for the outer data points. This is in fact intentional, such that
14889   the boundaries of the data cloud stay visible to the viewer. How strong the banding appears,
14890   depends on the point density, i.e. the number of points in the plot.
14891
14892   For some situations with scatter plots it might thus be desirable to manually turn adaptive
14893   sampling off. For example, when saving the plot to disk. This can be achieved by setting \a
14894   enabled to false before issuing a command like \ref QCustomPlot::savePng, and setting \a enabled
14895   back to true afterwards.
14896 */
14897 void QCPGraph::setAdaptiveSampling(bool enabled)
14898 {
14899   mAdaptiveSampling = enabled;
14900 }
14901
14902 /*!
14903   Adds the provided data points in \a dataMap to the current data.
14904
14905   Alternatively, you can also access and modify the graph's data via the \ref data method, which
14906   returns a pointer to the internal \ref QCPDataMap.
14907
14908   \see removeData
14909 */
14910 void QCPGraph::addData(const QCPDataMap &dataMap)
14911 {
14912   mData->unite(dataMap);
14913 }
14914
14915 /*! \overload
14916   Adds the provided single data point in \a data to the current data.
14917
14918   Alternatively, you can also access and modify the graph's data via the \ref data method, which
14919   returns a pointer to the internal \ref QCPDataMap.
14920
14921   \see removeData
14922 */
14923 void QCPGraph::addData(const QCPData &data)
14924 {
14925   mData->insertMulti(data.key, data);
14926 }
14927
14928 /*! \overload
14929   Adds the provided single data point as \a key and \a value pair to the current data.
14930
14931   Alternatively, you can also access and modify the graph's data via the \ref data method, which
14932   returns a pointer to the internal \ref QCPDataMap.
14933
14934   \see removeData
14935 */
14936 void QCPGraph::addData(double key, double value)
14937 {
14938   QCPData newData;
14939   newData.key = key;
14940   newData.value = value;
14941   mData->insertMulti(newData.key, newData);
14942 }
14943
14944 /*! \overload
14945   Adds the provided data points as \a key and \a value pairs to the current data.
14946
14947   Alternatively, you can also access and modify the graph's data via the \ref data method, which
14948   returns a pointer to the internal \ref QCPDataMap.
14949
14950   \see removeData
14951 */
14952 void QCPGraph::addData(const QVector<double> &keys, const QVector<double> &values)
14953 {
14954   int n = qMin(keys.size(), values.size());
14955   QCPData newData;
14956   for (int i=0; i<n; ++i)
14957   {
14958     newData.key = keys[i];
14959     newData.value = values[i];
14960     mData->insertMulti(newData.key, newData);
14961   }
14962 }
14963
14964 /*!
14965   Removes all data points with keys smaller than \a key.
14966   \see addData, clearData
14967 */
14968 void QCPGraph::removeDataBefore(double key)
14969 {
14970   QCPDataMap::iterator it = mData->begin();
14971   while (it != mData->end() && it.key() < key)
14972     it = mData->erase(it);
14973 }
14974
14975 /*!
14976   Removes all data points with keys greater than \a key.
14977   \see addData, clearData
14978 */
14979 void QCPGraph::removeDataAfter(double key)
14980 {
14981   if (mData->isEmpty()) return;
14982   QCPDataMap::iterator it = mData->upperBound(key);
14983   while (it != mData->end())
14984     it = mData->erase(it);
14985 }
14986
14987 /*!
14988   Removes all data points with keys between \a fromKey and \a toKey.
14989   if \a fromKey is greater or equal to \a toKey, the function does nothing. To remove
14990   a single data point with known key, use \ref removeData(double key).
14991
14992   \see addData, clearData
14993 */
14994 void QCPGraph::removeData(double fromKey, double toKey)
14995 {
14996   if (fromKey >= toKey || mData->isEmpty()) return;
14997   QCPDataMap::iterator it = mData->upperBound(fromKey);
14998   QCPDataMap::iterator itEnd = mData->upperBound(toKey);
14999   while (it != itEnd)
15000     it = mData->erase(it);
15001 }
15002
15003 /*! \overload
15004
15005   Removes a single data point at \a key. If the position is not known with absolute precision,
15006   consider using \ref removeData(double fromKey, double toKey) with a small fuzziness interval around
15007   the suspected position, depeding on the precision with which the key is known.
15008
15009   \see addData, clearData
15010 */
15011 void QCPGraph::removeData(double key)
15012 {
15013   mData->remove(key);
15014 }
15015
15016 /*!
15017   Removes all data points.
15018   \see removeData, removeDataAfter, removeDataBefore
15019 */
15020 void QCPGraph::clearData()
15021 {
15022   mData->clear();
15023 }
15024
15025 /* inherits documentation from base class */
15026 double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
15027 {
15028   Q_UNUSED(details)
15029   if ((onlySelectable && !mSelectable) || mData->isEmpty())
15030     return -1;
15031   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
15032
15033   if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
15034     return pointDistance(pos);
15035   else
15036     return -1;
15037 }
15038
15039 /*! \overload
15040
15041   Allows to define whether error bars are taken into consideration when determining the new axis
15042   range.
15043
15044   \see rescaleKeyAxis, rescaleValueAxis, QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes
15045 */
15046 void QCPGraph::rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const
15047 {
15048   rescaleKeyAxis(onlyEnlarge, includeErrorBars);
15049   rescaleValueAxis(onlyEnlarge, includeErrorBars);
15050 }
15051
15052 /*! \overload
15053
15054   Allows to define whether error bars (of kind \ref QCPGraph::etKey) are taken into consideration
15055   when determining the new axis range.
15056
15057   \see rescaleAxes, QCPAbstractPlottable::rescaleKeyAxis
15058 */
15059 void QCPGraph::rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const
15060 {
15061   // this code is a copy of QCPAbstractPlottable::rescaleKeyAxis with the only change
15062   // that getKeyRange is passed the includeErrorBars value.
15063   if (mData->isEmpty()) return;
15064
15065   QCPAxis *keyAxis = mKeyAxis.data();
15066   if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
15067
15068   SignDomain signDomain = sdBoth;
15069   if (keyAxis->scaleType() == QCPAxis::stLogarithmic)
15070     signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive);
15071
15072   bool foundRange;
15073   QCPRange newRange = getKeyRange(foundRange, signDomain, includeErrorBars);
15074
15075   if (foundRange)
15076   {
15077     if (onlyEnlarge)
15078     {
15079       if (keyAxis->range().lower < newRange.lower)
15080         newRange.lower = keyAxis->range().lower;
15081       if (keyAxis->range().upper > newRange.upper)
15082         newRange.upper = keyAxis->range().upper;
15083     }
15084     keyAxis->setRange(newRange);
15085   }
15086 }
15087
15088 /*! \overload
15089
15090   Allows to define whether error bars (of kind \ref QCPGraph::etValue) are taken into consideration
15091   when determining the new axis range.
15092
15093   \see rescaleAxes, QCPAbstractPlottable::rescaleValueAxis
15094 */
15095 void QCPGraph::rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const
15096 {
15097   // this code is a copy of QCPAbstractPlottable::rescaleValueAxis with the only change
15098   // is that getValueRange is passed the includeErrorBars value.
15099   if (mData->isEmpty()) return;
15100
15101   QCPAxis *valueAxis = mValueAxis.data();
15102   if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; }
15103
15104   SignDomain signDomain = sdBoth;
15105   if (valueAxis->scaleType() == QCPAxis::stLogarithmic)
15106     signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive);
15107
15108   bool foundRange;
15109   QCPRange newRange = getValueRange(foundRange, signDomain, includeErrorBars);
15110
15111   if (foundRange)
15112   {
15113     if (onlyEnlarge)
15114     {
15115       if (valueAxis->range().lower < newRange.lower)
15116         newRange.lower = valueAxis->range().lower;
15117       if (valueAxis->range().upper > newRange.upper)
15118         newRange.upper = valueAxis->range().upper;
15119     }
15120     valueAxis->setRange(newRange);
15121   }
15122 }
15123
15124 /* inherits documentation from base class */
15125 void QCPGraph::draw(QCPPainter *painter)
15126 {
15127   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15128   if (mKeyAxis.data()->range().size() <= 0 || mData->isEmpty()) return;
15129   if (mLineStyle == lsNone && mScatterStyle.isNone()) return;
15130
15131   // allocate line and (if necessary) point vectors:
15132   QVector<QPointF> *lineData = new QVector<QPointF>;
15133   QVector<QCPData> *scatterData = 0;
15134   if (!mScatterStyle.isNone())
15135     scatterData = new QVector<QCPData>;
15136
15137   // fill vectors with data appropriate to plot style:
15138   getPlotData(lineData, scatterData);
15139
15140   // check data validity if flag set:
15141 #ifdef QCUSTOMPLOT_CHECK_DATA
15142   QCPDataMap::const_iterator it;
15143   for (it = mData->constBegin(); it != mData->constEnd(); ++it)
15144   {
15145     if (QCP::isInvalidData(it.value().key, it.value().value) ||
15146         QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) ||
15147         QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus))
15148       qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
15149   }
15150 #endif
15151
15152   // draw fill of graph:
15153   drawFill(painter, lineData);
15154
15155   // draw line:
15156   if (mLineStyle == lsImpulse)
15157     drawImpulsePlot(painter, lineData);
15158   else if (mLineStyle != lsNone)
15159     drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot
15160
15161   // draw scatters:
15162   if (scatterData)
15163     drawScatterPlot(painter, scatterData);
15164
15165   // free allocated line and point vectors:
15166   delete lineData;
15167   if (scatterData)
15168     delete scatterData;
15169 }
15170
15171 /* inherits documentation from base class */
15172 void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
15173 {
15174   // draw fill:
15175   if (mBrush.style() != Qt::NoBrush)
15176   {
15177     applyFillAntialiasingHint(painter);
15178     painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
15179   }
15180   // draw line vertically centered:
15181   if (mLineStyle != lsNone)
15182   {
15183     applyDefaultAntialiasingHint(painter);
15184     painter->setPen(mPen);
15185     painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
15186   }
15187   // draw scatter symbol:
15188   if (!mScatterStyle.isNone())
15189   {
15190     applyScattersAntialiasingHint(painter);
15191     // scale scatter pixmap if it's too large to fit in legend icon rect:
15192     if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
15193     {
15194       QCPScatterStyle scaledStyle(mScatterStyle);
15195       scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
15196       scaledStyle.applyTo(painter, mPen);
15197       scaledStyle.drawShape(painter, QRectF(rect).center());
15198     } else
15199     {
15200       mScatterStyle.applyTo(painter, mPen);
15201       mScatterStyle.drawShape(painter, QRectF(rect).center());
15202     }
15203   }
15204 }
15205
15206 /*! \internal
15207
15208   This function branches out to the line style specific "get(...)PlotData" functions, according to
15209   the line style of the graph.
15210
15211   \a lineData will be filled with raw points that will be drawn with the according draw functions,
15212   e.g. \ref drawLinePlot and \ref drawImpulsePlot. These aren't necessarily the original data
15213   points, since for step plots for example, additional points are needed for drawing lines that
15214   make up steps. If the line style of the graph is \ref lsNone, the \a lineData vector will be left
15215   untouched.
15216
15217   \a scatterData will be filled with the original data points so \ref drawScatterPlot can draw the
15218   scatter symbols accordingly. If no scatters need to be drawn, i.e. the scatter style's shape is
15219   \ref QCPScatterStyle::ssNone, pass 0 as \a scatterData, and this step will be skipped.
15220
15221   \see getScatterPlotData, getLinePlotData, getStepLeftPlotData, getStepRightPlotData,
15222   getStepCenterPlotData, getImpulsePlotData
15223 */
15224 void QCPGraph::getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const
15225 {
15226   switch(mLineStyle)
15227   {
15228     case lsNone: getScatterPlotData(scatterData); break;
15229     case lsLine: getLinePlotData(lineData, scatterData); break;
15230     case lsStepLeft: getStepLeftPlotData(lineData, scatterData); break;
15231     case lsStepRight: getStepRightPlotData(lineData, scatterData); break;
15232     case lsStepCenter: getStepCenterPlotData(lineData, scatterData); break;
15233     case lsImpulse: getImpulsePlotData(lineData, scatterData); break;
15234   }
15235 }
15236
15237 /*! \internal
15238
15239   If line style is \ref lsNone and the scatter style's shape is not \ref QCPScatterStyle::ssNone,
15240   this function serves at providing the visible data points in \a scatterData, so the \ref
15241   drawScatterPlot function can draw the scatter points accordingly.
15242
15243   If line style is not \ref lsNone, this function is not called and the data for the scatter points
15244   are (if needed) calculated inside the corresponding other "get(...)PlotData" functions.
15245
15246   \see drawScatterPlot
15247 */
15248 void QCPGraph::getScatterPlotData(QVector<QCPData> *scatterData) const
15249 {
15250   getPreparedData(0, scatterData);
15251 }
15252
15253 /*! \internal
15254
15255   Places the raw data points needed for a normal linearly connected graph in \a linePixelData.
15256
15257   As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter)
15258   points that are visible for drawing scatter points, if necessary. If drawing scatter points is
15259   disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a
15260   scatterData, and the function will skip filling the vector.
15261
15262   \see drawLinePlot
15263 */
15264 void QCPGraph::getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15265 {
15266   QCPAxis *keyAxis = mKeyAxis.data();
15267   QCPAxis *valueAxis = mValueAxis.data();
15268   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15269   if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
15270
15271   QVector<QCPData> lineData;
15272   getPreparedData(&lineData, scatterData);
15273   linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15274   linePixelData->resize(lineData.size());
15275
15276   // transform lineData points to pixels:
15277   if (keyAxis->orientation() == Qt::Vertical)
15278   {
15279     for (int i=0; i<lineData.size(); ++i)
15280     {
15281       (*linePixelData)[i].setX(valueAxis->coordToPixel(lineData.at(i).value));
15282       (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key));
15283     }
15284   } else // key axis is horizontal
15285   {
15286     for (int i=0; i<lineData.size(); ++i)
15287     {
15288       (*linePixelData)[i].setX(keyAxis->coordToPixel(lineData.at(i).key));
15289       (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value));
15290     }
15291   }
15292 }
15293
15294 /*!
15295   \internal
15296   Places the raw data points needed for a step plot with left oriented steps in \a lineData.
15297
15298   As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter)
15299   points that are visible for drawing scatter points, if necessary. If drawing scatter points is
15300   disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a
15301   scatterData, and the function will skip filling the vector.
15302
15303   \see drawLinePlot
15304 */
15305 void QCPGraph::getStepLeftPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15306 {
15307   QCPAxis *keyAxis = mKeyAxis.data();
15308   QCPAxis *valueAxis = mValueAxis.data();
15309   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15310   if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15311
15312   QVector<QCPData> lineData;
15313   getPreparedData(&lineData, scatterData);
15314   linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15315   linePixelData->resize(lineData.size()*2);
15316
15317   // calculate steps from lineData and transform to pixel coordinates:
15318   if (keyAxis->orientation() == Qt::Vertical)
15319   {
15320     double lastValue = valueAxis->coordToPixel(lineData.first().value);
15321     double key;
15322     for (int i=0; i<lineData.size(); ++i)
15323     {
15324       key = keyAxis->coordToPixel(lineData.at(i).key);
15325       (*linePixelData)[i*2+0].setX(lastValue);
15326       (*linePixelData)[i*2+0].setY(key);
15327       lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15328       (*linePixelData)[i*2+1].setX(lastValue);
15329       (*linePixelData)[i*2+1].setY(key);
15330     }
15331   } else // key axis is horizontal
15332   {
15333     double lastValue = valueAxis->coordToPixel(lineData.first().value);
15334     double key;
15335     for (int i=0; i<lineData.size(); ++i)
15336     {
15337       key = keyAxis->coordToPixel(lineData.at(i).key);
15338       (*linePixelData)[i*2+0].setX(key);
15339       (*linePixelData)[i*2+0].setY(lastValue);
15340       lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15341       (*linePixelData)[i*2+1].setX(key);
15342       (*linePixelData)[i*2+1].setY(lastValue);
15343     }
15344   }
15345 }
15346
15347 /*!
15348   \internal
15349   Places the raw data points needed for a step plot with right oriented steps in \a lineData.
15350
15351   As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter)
15352   points that are visible for drawing scatter points, if necessary. If drawing scatter points is
15353   disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a
15354   scatterData, and the function will skip filling the vector.
15355
15356   \see drawLinePlot
15357 */
15358 void QCPGraph::getStepRightPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15359 {
15360   QCPAxis *keyAxis = mKeyAxis.data();
15361   QCPAxis *valueAxis = mValueAxis.data();
15362   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15363   if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15364
15365   QVector<QCPData> lineData;
15366   getPreparedData(&lineData, scatterData);
15367   linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15368   linePixelData->resize(lineData.size()*2);
15369
15370   // calculate steps from lineData and transform to pixel coordinates:
15371   if (keyAxis->orientation() == Qt::Vertical)
15372   {
15373     double lastKey = keyAxis->coordToPixel(lineData.first().key);
15374     double value;
15375     for (int i=0; i<lineData.size(); ++i)
15376     {
15377       value = valueAxis->coordToPixel(lineData.at(i).value);
15378       (*linePixelData)[i*2+0].setX(value);
15379       (*linePixelData)[i*2+0].setY(lastKey);
15380       lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15381       (*linePixelData)[i*2+1].setX(value);
15382       (*linePixelData)[i*2+1].setY(lastKey);
15383     }
15384   } else // key axis is horizontal
15385   {
15386     double lastKey = keyAxis->coordToPixel(lineData.first().key);
15387     double value;
15388     for (int i=0; i<lineData.size(); ++i)
15389     {
15390       value = valueAxis->coordToPixel(lineData.at(i).value);
15391       (*linePixelData)[i*2+0].setX(lastKey);
15392       (*linePixelData)[i*2+0].setY(value);
15393       lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15394       (*linePixelData)[i*2+1].setX(lastKey);
15395       (*linePixelData)[i*2+1].setY(value);
15396     }
15397   }
15398 }
15399
15400 /*!
15401   \internal
15402   Places the raw data points needed for a step plot with centered steps in \a lineData.
15403
15404   As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter)
15405   points that are visible for drawing scatter points, if necessary. If drawing scatter points is
15406   disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a
15407   scatterData, and the function will skip filling the vector.
15408
15409   \see drawLinePlot
15410 */
15411 void QCPGraph::getStepCenterPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15412 {
15413   QCPAxis *keyAxis = mKeyAxis.data();
15414   QCPAxis *valueAxis = mValueAxis.data();
15415   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15416   if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15417
15418   QVector<QCPData> lineData;
15419   getPreparedData(&lineData, scatterData);
15420   linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15421   linePixelData->resize(lineData.size()*2);
15422   // calculate steps from lineData and transform to pixel coordinates:
15423   if (keyAxis->orientation() == Qt::Vertical)
15424   {
15425     double lastKey = keyAxis->coordToPixel(lineData.first().key);
15426     double lastValue = valueAxis->coordToPixel(lineData.first().value);
15427     double key;
15428     (*linePixelData)[0].setX(lastValue);
15429     (*linePixelData)[0].setY(lastKey);
15430     for (int i=1; i<lineData.size(); ++i)
15431     {
15432       key = (keyAxis->coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15433       (*linePixelData)[i*2-1].setX(lastValue);
15434       (*linePixelData)[i*2-1].setY(key);
15435       lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15436       lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15437       (*linePixelData)[i*2+0].setX(lastValue);
15438       (*linePixelData)[i*2+0].setY(key);
15439     }
15440     (*linePixelData)[lineData.size()*2-1].setX(lastValue);
15441     (*linePixelData)[lineData.size()*2-1].setY(lastKey);
15442   } else // key axis is horizontal
15443   {
15444     double lastKey = keyAxis->coordToPixel(lineData.first().key);
15445     double lastValue = valueAxis->coordToPixel(lineData.first().value);
15446     double key;
15447     (*linePixelData)[0].setX(lastKey);
15448     (*linePixelData)[0].setY(lastValue);
15449     for (int i=1; i<lineData.size(); ++i)
15450     {
15451       key = (keyAxis->coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15452       (*linePixelData)[i*2-1].setX(key);
15453       (*linePixelData)[i*2-1].setY(lastValue);
15454       lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15455       lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15456       (*linePixelData)[i*2+0].setX(key);
15457       (*linePixelData)[i*2+0].setY(lastValue);
15458     }
15459     (*linePixelData)[lineData.size()*2-1].setX(lastKey);
15460     (*linePixelData)[lineData.size()*2-1].setY(lastValue);
15461   }
15462
15463 }
15464
15465 /*!
15466   \internal
15467   Places the raw data points needed for an impulse plot in \a lineData.
15468
15469   As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter)
15470   points that are visible for drawing scatter points, if necessary. If drawing scatter points is
15471   disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a
15472   scatterData, and the function will skip filling the vector.
15473
15474   \see drawImpulsePlot
15475 */
15476 void QCPGraph::getImpulsePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15477 {
15478   QCPAxis *keyAxis = mKeyAxis.data();
15479   QCPAxis *valueAxis = mValueAxis.data();
15480   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15481   if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
15482
15483   QVector<QCPData> lineData;
15484   getPreparedData(&lineData, scatterData);
15485   linePixelData->resize(lineData.size()*2); // no need to reserve 2 extra points because impulse plot has no fill
15486
15487   // transform lineData points to pixels:
15488   if (keyAxis->orientation() == Qt::Vertical)
15489   {
15490     double zeroPointX = valueAxis->coordToPixel(0);
15491     double key;
15492     for (int i=0; i<lineData.size(); ++i)
15493     {
15494       key = keyAxis->coordToPixel(lineData.at(i).key);
15495       (*linePixelData)[i*2+0].setX(zeroPointX);
15496       (*linePixelData)[i*2+0].setY(key);
15497       (*linePixelData)[i*2+1].setX(valueAxis->coordToPixel(lineData.at(i).value));
15498       (*linePixelData)[i*2+1].setY(key);
15499     }
15500   } else // key axis is horizontal
15501   {
15502     double zeroPointY = valueAxis->coordToPixel(0);
15503     double key;
15504     for (int i=0; i<lineData.size(); ++i)
15505     {
15506       key = keyAxis->coordToPixel(lineData.at(i).key);
15507       (*linePixelData)[i*2+0].setX(key);
15508       (*linePixelData)[i*2+0].setY(zeroPointY);
15509       (*linePixelData)[i*2+1].setX(key);
15510       (*linePixelData)[i*2+1].setY(valueAxis->coordToPixel(lineData.at(i).value));
15511     }
15512   }
15513 }
15514
15515 /*! \internal
15516
15517   Draws the fill of the graph with the specified brush.
15518
15519   If the fill is a normal fill towards the zero-value-line, only the \a lineData is required (and
15520   two extra points at the zero-value-line, which are added by \ref addFillBasePoints and removed by
15521   \ref removeFillBasePoints after the fill drawing is done).
15522
15523   If the fill is a channel fill between this QCPGraph and another QCPGraph (mChannelFillGraph), the
15524   more complex polygon is calculated with the \ref getChannelFillPolygon function.
15525
15526   \see drawLinePlot
15527 */
15528 void QCPGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lineData) const
15529 {
15530   if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot
15531   if (mainBrush().style() == Qt::NoBrush || mainBrush().color().alpha() == 0) return;
15532
15533   applyFillAntialiasingHint(painter);
15534   if (!mChannelFillGraph)
15535   {
15536     // draw base fill under graph, fill goes all the way to the zero-value-line:
15537     addFillBasePoints(lineData);
15538     painter->setPen(Qt::NoPen);
15539     painter->setBrush(mainBrush());
15540     painter->drawPolygon(QPolygonF(*lineData));
15541     removeFillBasePoints(lineData);
15542   } else
15543   {
15544     // draw channel fill between this graph and mChannelFillGraph:
15545     painter->setPen(Qt::NoPen);
15546     painter->setBrush(mainBrush());
15547     painter->drawPolygon(getChannelFillPolygon(lineData));
15548   }
15549 }
15550
15551 /*! \internal
15552
15553   Draws scatter symbols at every data point passed in \a scatterData. scatter symbols are independent
15554   of the line style and are always drawn if the scatter style's shape is not \ref
15555   QCPScatterStyle::ssNone. Hence, the \a scatterData vector is outputted by all "get(...)PlotData"
15556   functions, together with the (line style dependent) line data.
15557
15558   \see drawLinePlot, drawImpulsePlot
15559 */
15560 void QCPGraph::drawScatterPlot(QCPPainter *painter, QVector<QCPData> *scatterData) const
15561 {
15562   QCPAxis *keyAxis = mKeyAxis.data();
15563   QCPAxis *valueAxis = mValueAxis.data();
15564   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15565
15566   // draw error bars:
15567   if (mErrorType != etNone)
15568   {
15569     applyErrorBarsAntialiasingHint(painter);
15570     painter->setPen(mErrorPen);
15571     if (keyAxis->orientation() == Qt::Vertical)
15572     {
15573       for (int i=0; i<scatterData->size(); ++i)
15574         drawError(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key), scatterData->at(i));
15575     } else
15576     {
15577       for (int i=0; i<scatterData->size(); ++i)
15578         drawError(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value), scatterData->at(i));
15579     }
15580   }
15581
15582   // draw scatter point symbols:
15583   applyScattersAntialiasingHint(painter);
15584   mScatterStyle.applyTo(painter, mPen);
15585   if (keyAxis->orientation() == Qt::Vertical)
15586   {
15587     for (int i=0; i<scatterData->size(); ++i)
15588       if (!qIsNaN(scatterData->at(i).value))
15589         mScatterStyle.drawShape(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key));
15590   } else
15591   {
15592     for (int i=0; i<scatterData->size(); ++i)
15593       if (!qIsNaN(scatterData->at(i).value))
15594         mScatterStyle.drawShape(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value));
15595   }
15596 }
15597
15598 /*!  \internal
15599
15600   Draws line graphs from the provided data. It connects all points in \a lineData, which was
15601   created by one of the "get(...)PlotData" functions for line styles that require simple line
15602   connections between the point vector they create. These are for example \ref getLinePlotData,
15603   \ref getStepLeftPlotData, \ref getStepRightPlotData and \ref getStepCenterPlotData.
15604
15605   \see drawScatterPlot, drawImpulsePlot
15606 */
15607 void QCPGraph::drawLinePlot(QCPPainter *painter, QVector<QPointF> *lineData) const
15608 {
15609   // draw line of graph:
15610   if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
15611   {
15612     applyDefaultAntialiasingHint(painter);
15613     painter->setPen(mainPen());
15614     painter->setBrush(Qt::NoBrush);
15615
15616     /* Draws polyline in batches, currently not used:
15617     int p = 0;
15618     while (p < lineData->size())
15619     {
15620       int batch = qMin(25, lineData->size()-p);
15621       if (p != 0)
15622       {
15623         ++batch;
15624         --p; // to draw the connection lines between two batches
15625       }
15626       painter->drawPolyline(lineData->constData()+p, batch);
15627       p += batch;
15628     }
15629     */
15630
15631     // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
15632     if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
15633         painter->pen().style() == Qt::SolidLine &&
15634         !painter->modes().testFlag(QCPPainter::pmVectorized)&&
15635         !painter->modes().testFlag(QCPPainter::pmNoCaching))
15636     {
15637       int i = 1;
15638       int lineDataSize = lineData->size();
15639       while (i < lineDataSize)
15640       {
15641         if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
15642           painter->drawLine(lineData->at(i-1), lineData->at(i));
15643         else
15644           ++i;
15645         ++i;
15646       }
15647     } else
15648     {
15649       int segmentStart = 0;
15650       int i = 0;
15651       int lineDataSize = lineData->size();
15652       while (i < lineDataSize)
15653       {
15654         if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
15655         {
15656           painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
15657           segmentStart = i+1;
15658         }
15659         ++i;
15660       }
15661       // draw last segment:
15662       painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point
15663     }
15664   }
15665 }
15666
15667 /*! \internal
15668
15669   Draws impulses from the provided data, i.e. it connects all line pairs in \a lineData, which was
15670   created by \ref getImpulsePlotData.
15671
15672   \see drawScatterPlot, drawLinePlot
15673 */
15674 void QCPGraph::drawImpulsePlot(QCPPainter *painter, QVector<QPointF> *lineData) const
15675 {
15676   // draw impulses:
15677   if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
15678   {
15679     applyDefaultAntialiasingHint(painter);
15680     QPen pen = mainPen();
15681     pen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line
15682     painter->setPen(pen);
15683     painter->setBrush(Qt::NoBrush);
15684     painter->drawLines(*lineData);
15685   }
15686 }
15687
15688 /*! \internal
15689
15690   Returns the \a lineData and \a scatterData that need to be plotted for this graph taking into
15691   consideration the current axis ranges and, if \ref setAdaptiveSampling is enabled, local point
15692   densities.
15693
15694   0 may be passed as \a lineData or \a scatterData to indicate that the respective dataset isn't
15695   needed. For example, if the scatter style (\ref setScatterStyle) is \ref QCPScatterStyle::ssNone, \a
15696   scatterData should be 0 to prevent unnecessary calculations.
15697
15698   This method is used by the various "get(...)PlotData" methods to get the basic working set of data.
15699 */
15700 void QCPGraph::getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const
15701 {
15702   QCPAxis *keyAxis = mKeyAxis.data();
15703   QCPAxis *valueAxis = mValueAxis.data();
15704   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15705   // get visible data range:
15706   QCPDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
15707   getVisibleDataBounds(lower, upper);
15708   if (lower == mData->constEnd() || upper == mData->constEnd())
15709     return;
15710
15711   // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling:
15712   int maxCount = std::numeric_limits<int>::max();
15713   if (mAdaptiveSampling)
15714   {
15715     int keyPixelSpan = qAbs(keyAxis->coordToPixel(lower.key())-keyAxis->coordToPixel(upper.key()));
15716     maxCount = 2*keyPixelSpan+2;
15717   }
15718   int dataCount = countDataInBounds(lower, upper, maxCount);
15719
15720   if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
15721   {
15722     if (lineData)
15723     {
15724       QCPDataMap::const_iterator it = lower;
15725       QCPDataMap::const_iterator upperEnd = upper+1;
15726       double minValue = it.value().value;
15727       double maxValue = it.value().value;
15728       QCPDataMap::const_iterator currentIntervalFirstPoint = it;
15729       int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15730       int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15731       double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound));
15732       double lastIntervalEndKey = currentIntervalStartKey;
15733       double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15734       bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15735       int intervalDataCount = 1;
15736       ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15737       while (it != upperEnd)
15738       {
15739         if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary
15740         {
15741           if (it.value().value < minValue)
15742             minValue = it.value().value;
15743           else if (it.value().value > maxValue)
15744             maxValue = it.value().value;
15745           ++intervalDataCount;
15746         } else // new pixel interval started
15747         {
15748           if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15749           {
15750             if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point
15751               lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15752             lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15753             lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15754             if (it.key() > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point
15755               lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value));
15756           } else
15757             lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15758           lastIntervalEndKey = (it-1).value().key;
15759           minValue = it.value().value;
15760           maxValue = it.value().value;
15761           currentIntervalFirstPoint = it;
15762           currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound));
15763           if (keyEpsilonVariable)
15764             keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15765           intervalDataCount = 1;
15766         }
15767         ++it;
15768       }
15769       // handle last interval:
15770       if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15771       {
15772         if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point
15773           lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15774         lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15775         lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15776       } else
15777         lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15778     }
15779
15780     if (scatterData)
15781     {
15782       double valueMaxRange = valueAxis->range().upper;
15783       double valueMinRange = valueAxis->range().lower;
15784       QCPDataMap::const_iterator it = lower;
15785       QCPDataMap::const_iterator upperEnd = upper+1;
15786       double minValue = it.value().value;
15787       double maxValue = it.value().value;
15788       QCPDataMap::const_iterator minValueIt = it;
15789       QCPDataMap::const_iterator maxValueIt = it;
15790       QCPDataMap::const_iterator currentIntervalStart = it;
15791       int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15792       int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15793       double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound));
15794       double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15795       bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15796       int intervalDataCount = 1;
15797       ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15798       while (it != upperEnd)
15799       {
15800         if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary
15801         {
15802           if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15803           {
15804             minValue = it.value().value;
15805             minValueIt = it;
15806           } else if (it.value().value > maxValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15807           {
15808             maxValue = it.value().value;
15809             maxValueIt = it;
15810           }
15811           ++intervalDataCount;
15812         } else // new pixel started
15813         {
15814           if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15815           {
15816             // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15817             double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15818             int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
15819             QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15820             int c = 0;
15821             while (intervalIt != it)
15822             {
15823               if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15824                 scatterData->append(intervalIt.value());
15825               ++c;
15826               ++intervalIt;
15827             }
15828           } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15829             scatterData->append(currentIntervalStart.value());
15830           minValue = it.value().value;
15831           maxValue = it.value().value;
15832           currentIntervalStart = it;
15833           currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound));
15834           if (keyEpsilonVariable)
15835             keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15836           intervalDataCount = 1;
15837         }
15838         ++it;
15839       }
15840       // handle last interval:
15841       if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15842       {
15843         // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15844         double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15845         int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
15846         QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15847         int c = 0;
15848         while (intervalIt != it)
15849         {
15850           if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15851             scatterData->append(intervalIt.value());
15852           ++c;
15853           ++intervalIt;
15854         }
15855       } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15856         scatterData->append(currentIntervalStart.value());
15857     }
15858   } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters
15859   {
15860     QVector<QCPData> *dataVector = 0;
15861     if (lineData)
15862       dataVector = lineData;
15863     else if (scatterData)
15864       dataVector = scatterData;
15865     if (dataVector)
15866     {
15867       QCPDataMap::const_iterator it = lower;
15868       QCPDataMap::const_iterator upperEnd = upper+1;
15869       dataVector->reserve(dataCount+2); // +2 for possible fill end points
15870       while (it != upperEnd)
15871       {
15872         dataVector->append(it.value());
15873         ++it;
15874       }
15875     }
15876     if (lineData && scatterData)
15877       *scatterData = *dataVector;
15878   }
15879 }
15880
15881 /*!  \internal
15882
15883   called by the scatter drawing function (\ref drawScatterPlot) to draw the error bars on one data
15884   point. \a x and \a y pixel positions of the data point are passed since they are already known in
15885   pixel coordinates in the drawing function, so we save some extra coordToPixel transforms here. \a
15886   data is therefore only used for the errors, not key and value.
15887 */
15888 void QCPGraph::drawError(QCPPainter *painter, double x, double y, const QCPData &data) const
15889 {
15890   if (qIsNaN(data.value))
15891     return;
15892   QCPAxis *keyAxis = mKeyAxis.data();
15893   QCPAxis *valueAxis = mValueAxis.data();
15894   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15895
15896   double a, b; // positions of error bar bounds in pixels
15897   double barWidthHalf = mErrorBarSize*0.5;
15898   double skipSymbolMargin = mScatterStyle.size(); // pixels left blank per side, when mErrorBarSkipSymbol is true
15899
15900   if (keyAxis->orientation() == Qt::Vertical)
15901   {
15902     // draw key error vertically and value error horizontally
15903     if (mErrorType == etKey || mErrorType == etBoth)
15904     {
15905       a = keyAxis->coordToPixel(data.key-data.keyErrorMinus);
15906       b = keyAxis->coordToPixel(data.key+data.keyErrorPlus);
15907       if (keyAxis->rangeReversed())
15908         qSwap(a,b);
15909       // draw spine:
15910       if (mErrorBarSkipSymbol)
15911       {
15912         if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15913           painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin));
15914         if (y-b > skipSymbolMargin)
15915           painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b));
15916       } else
15917         painter->drawLine(QLineF(x, a, x, b));
15918       // draw handles:
15919       painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
15920       painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
15921     }
15922     if (mErrorType == etValue || mErrorType == etBoth)
15923     {
15924       a = valueAxis->coordToPixel(data.value-data.valueErrorMinus);
15925       b = valueAxis->coordToPixel(data.value+data.valueErrorPlus);
15926       if (valueAxis->rangeReversed())
15927         qSwap(a,b);
15928       // draw spine:
15929       if (mErrorBarSkipSymbol)
15930       {
15931         if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15932           painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y));
15933         if (b-x > skipSymbolMargin)
15934           painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y));
15935       } else
15936         painter->drawLine(QLineF(a, y, b, y));
15937       // draw handles:
15938       painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
15939       painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
15940     }
15941   } else // mKeyAxis->orientation() is Qt::Horizontal
15942   {
15943     // draw value error vertically and key error horizontally
15944     if (mErrorType == etKey || mErrorType == etBoth)
15945     {
15946       a = keyAxis->coordToPixel(data.key-data.keyErrorMinus);
15947       b = keyAxis->coordToPixel(data.key+data.keyErrorPlus);
15948       if (keyAxis->rangeReversed())
15949         qSwap(a,b);
15950       // draw spine:
15951       if (mErrorBarSkipSymbol)
15952       {
15953         if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15954           painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y));
15955         if (b-x > skipSymbolMargin)
15956           painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y));
15957       } else
15958         painter->drawLine(QLineF(a, y, b, y));
15959       // draw handles:
15960       painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
15961       painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
15962     }
15963     if (mErrorType == etValue || mErrorType == etBoth)
15964     {
15965       a = valueAxis->coordToPixel(data.value-data.valueErrorMinus);
15966       b = valueAxis->coordToPixel(data.value+data.valueErrorPlus);
15967       if (valueAxis->rangeReversed())
15968         qSwap(a,b);
15969       // draw spine:
15970       if (mErrorBarSkipSymbol)
15971       {
15972         if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15973           painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin));
15974         if (y-b > skipSymbolMargin)
15975           painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b));
15976       } else
15977         painter->drawLine(QLineF(x, a, x, b));
15978       // draw handles:
15979       painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
15980       painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
15981     }
15982   }
15983 }
15984
15985 /*!  \internal
15986
15987   called by \ref getPreparedData to determine which data (key) range is visible at the current key
15988   axis range setting, so only that needs to be processed.
15989
15990   \a lower returns an iterator to the lowest data point that needs to be taken into account when
15991   plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a
15992   lower may still be just outside the visible range.
15993
15994   \a upper returns an iterator to the highest data point. Same as before, \a upper may also lie
15995   just outside of the visible range.
15996
15997   if the graph contains no data, both \a lower and \a upper point to constEnd.
15998 */
15999 void QCPGraph::getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const
16000 {
16001   if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
16002   if (mData->isEmpty())
16003   {
16004     lower = mData->constEnd();
16005     upper = mData->constEnd();
16006     return;
16007   }
16008
16009   // get visible data range as QMap iterators
16010   QCPDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower);
16011   QCPDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper);
16012   bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
16013   bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
16014
16015   lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
16016   upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
16017 }
16018
16019 /*!  \internal
16020
16021   Counts the number of data points between \a lower and \a upper (including them), up to a maximum
16022   of \a maxCount.
16023
16024   This function is used by \ref getPreparedData to determine whether adaptive sampling shall be
16025   used (if enabled via \ref setAdaptiveSampling) or not. This is also why counting of data points
16026   only needs to be done until \a maxCount is reached, which should be set to the number of data
16027   points at which adaptive sampling sets in.
16028 */
16029 int QCPGraph::countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const
16030 {
16031   if (upper == mData->constEnd() && lower == mData->constEnd())
16032     return 0;
16033   QCPDataMap::const_iterator it = lower;
16034   int count = 1;
16035   while (it != upper && count < maxCount)
16036   {
16037     ++it;
16038     ++count;
16039   }
16040   return count;
16041 }
16042
16043 /*! \internal
16044
16045   The line data vector generated by e.g. getLinePlotData contains only the line that connects the
16046   data points. If the graph needs to be filled, two additional points need to be added at the
16047   value-zero-line in the lower and upper key positions of the graph. This function calculates these
16048   points and adds them to the end of \a lineData. Since the fill is typically drawn before the line
16049   stroke, these added points need to be removed again after the fill is done, with the
16050   removeFillBasePoints function.
16051
16052   The expanding of \a lineData by two points will not cause unnecessary memory reallocations,
16053   because the data vector generation functions (getLinePlotData etc.) reserve two extra points when
16054   they allocate memory for \a lineData.
16055
16056   \see removeFillBasePoints, lowerFillBasePoint, upperFillBasePoint
16057 */
16058 void QCPGraph::addFillBasePoints(QVector<QPointF> *lineData) const
16059 {
16060   if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
16061
16062   // append points that close the polygon fill at the key axis:
16063   if (mKeyAxis.data()->orientation() == Qt::Vertical)
16064   {
16065     *lineData << upperFillBasePoint(lineData->last().y());
16066     *lineData << lowerFillBasePoint(lineData->first().y());
16067   } else
16068   {
16069     *lineData << upperFillBasePoint(lineData->last().x());
16070     *lineData << lowerFillBasePoint(lineData->first().x());
16071   }
16072 }
16073
16074 /*! \internal
16075
16076   removes the two points from \a lineData that were added by \ref addFillBasePoints.
16077
16078   \see addFillBasePoints, lowerFillBasePoint, upperFillBasePoint
16079 */
16080 void QCPGraph::removeFillBasePoints(QVector<QPointF> *lineData) const
16081 {
16082   lineData->remove(lineData->size()-2, 2);
16083 }
16084
16085 /*! \internal
16086
16087   called by \ref addFillBasePoints to conveniently assign the point which closes the fill polygon
16088   on the lower side of the zero-value-line parallel to the key axis. The logarithmic axis scale
16089   case is a bit special, since the zero-value-line in pixel coordinates is in positive or negative
16090   infinity. So this case is handled separately by just closing the fill polygon on the axis which
16091   lies in the direction towards the zero value.
16092
16093   \a lowerKey will be the the key (in pixels) of the returned point. Depending on whether the key
16094   axis is horizontal or vertical, \a lowerKey will end up as the x or y value of the returned
16095   point, respectively.
16096
16097   \see upperFillBasePoint, addFillBasePoints
16098 */
16099 QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const
16100 {
16101   QCPAxis *keyAxis = mKeyAxis.data();
16102   QCPAxis *valueAxis = mValueAxis.data();
16103   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
16104
16105   QPointF point;
16106   if (valueAxis->scaleType() == QCPAxis::stLinear)
16107   {
16108     if (keyAxis->axisType() == QCPAxis::atLeft)
16109     {
16110       point.setX(valueAxis->coordToPixel(0));
16111       point.setY(lowerKey);
16112     } else if (keyAxis->axisType() == QCPAxis::atRight)
16113     {
16114       point.setX(valueAxis->coordToPixel(0));
16115       point.setY(lowerKey);
16116     } else if (keyAxis->axisType() == QCPAxis::atTop)
16117     {
16118       point.setX(lowerKey);
16119       point.setY(valueAxis->coordToPixel(0));
16120     } else if (keyAxis->axisType() == QCPAxis::atBottom)
16121     {
16122       point.setX(lowerKey);
16123       point.setY(valueAxis->coordToPixel(0));
16124     }
16125   } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
16126   {
16127     // In logarithmic scaling we can't just draw to value zero so we just fill all the way
16128     // to the axis which is in the direction towards zero
16129     if (keyAxis->orientation() == Qt::Vertical)
16130     {
16131       if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16132           (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16133         point.setX(keyAxis->axisRect()->right());
16134       else
16135         point.setX(keyAxis->axisRect()->left());
16136       point.setY(lowerKey);
16137     } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom)
16138     {
16139       point.setX(lowerKey);
16140       if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16141           (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16142         point.setY(keyAxis->axisRect()->top());
16143       else
16144         point.setY(keyAxis->axisRect()->bottom());
16145     }
16146   }
16147   return point;
16148 }
16149
16150 /*! \internal
16151
16152   called by \ref addFillBasePoints to conveniently assign the point which closes the fill
16153   polygon on the upper side of the zero-value-line parallel to the key axis. The logarithmic axis
16154   scale case is a bit special, since the zero-value-line in pixel coordinates is in positive or
16155   negative infinity. So this case is handled separately by just closing the fill polygon on the
16156   axis which lies in the direction towards the zero value.
16157
16158   \a upperKey will be the the key (in pixels) of the returned point. Depending on whether the key
16159   axis is horizontal or vertical, \a upperKey will end up as the x or y value of the returned
16160   point, respectively.
16161
16162   \see lowerFillBasePoint, addFillBasePoints
16163 */
16164 QPointF QCPGraph::upperFillBasePoint(double upperKey) const
16165 {
16166   QCPAxis *keyAxis = mKeyAxis.data();
16167   QCPAxis *valueAxis = mValueAxis.data();
16168   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
16169
16170   QPointF point;
16171   if (valueAxis->scaleType() == QCPAxis::stLinear)
16172   {
16173     if (keyAxis->axisType() == QCPAxis::atLeft)
16174     {
16175       point.setX(valueAxis->coordToPixel(0));
16176       point.setY(upperKey);
16177     } else if (keyAxis->axisType() == QCPAxis::atRight)
16178     {
16179       point.setX(valueAxis->coordToPixel(0));
16180       point.setY(upperKey);
16181     } else if (keyAxis->axisType() == QCPAxis::atTop)
16182     {
16183       point.setX(upperKey);
16184       point.setY(valueAxis->coordToPixel(0));
16185     } else if (keyAxis->axisType() == QCPAxis::atBottom)
16186     {
16187       point.setX(upperKey);
16188       point.setY(valueAxis->coordToPixel(0));
16189     }
16190   } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
16191   {
16192     // In logarithmic scaling we can't just draw to value 0 so we just fill all the way
16193     // to the axis which is in the direction towards 0
16194     if (keyAxis->orientation() == Qt::Vertical)
16195     {
16196       if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16197           (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16198         point.setX(keyAxis->axisRect()->right());
16199       else
16200         point.setX(keyAxis->axisRect()->left());
16201       point.setY(upperKey);
16202     } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom)
16203     {
16204       point.setX(upperKey);
16205       if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16206           (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16207         point.setY(keyAxis->axisRect()->top());
16208       else
16209         point.setY(keyAxis->axisRect()->bottom());
16210     }
16211   }
16212   return point;
16213 }
16214
16215 /*! \internal
16216
16217   Generates the polygon needed for drawing channel fills between this graph (data passed via \a
16218   lineData) and the graph specified by mChannelFillGraph (data generated by calling its \ref
16219   getPlotData function). May return an empty polygon if the key ranges have no overlap or fill
16220   target graph and this graph don't have same orientation (i.e. both key axes horizontal or both
16221   key axes vertical). For increased performance (due to implicit sharing), keep the returned
16222   QPolygonF const.
16223 */
16224 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lineData) const
16225 {
16226   if (!mChannelFillGraph)
16227     return QPolygonF();
16228
16229   QCPAxis *keyAxis = mKeyAxis.data();
16230   QCPAxis *valueAxis = mValueAxis.data();
16231   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
16232   if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); }
16233
16234   if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation())
16235     return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis)
16236
16237   if (lineData->isEmpty()) return QPolygonF();
16238   QVector<QPointF> otherData;
16239   mChannelFillGraph.data()->getPlotData(&otherData, 0);
16240   if (otherData.isEmpty()) return QPolygonF();
16241   QVector<QPointF> thisData;
16242   thisData.reserve(lineData->size()+otherData.size()); // because we will join both vectors at end of this function
16243   for (int i=0; i<lineData->size(); ++i) // don't use the vector<<(vector),  it squeezes internally, which ruins the performance tuning with reserve()
16244     thisData << lineData->at(i);
16245
16246   // pointers to be able to swap them, depending which data range needs cropping:
16247   QVector<QPointF> *staticData = &thisData;
16248   QVector<QPointF> *croppedData = &otherData;
16249
16250   // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType):
16251   if (keyAxis->orientation() == Qt::Horizontal)
16252   {
16253     // x is key
16254     // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys:
16255     if (staticData->first().x() > staticData->last().x())
16256     {
16257       int size = staticData->size();
16258       for (int i=0; i<size/2; ++i)
16259         qSwap((*staticData)[i], (*staticData)[size-1-i]);
16260     }
16261     if (croppedData->first().x() > croppedData->last().x())
16262     {
16263       int size = croppedData->size();
16264       for (int i=0; i<size/2; ++i)
16265         qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16266     }
16267     // crop lower bound:
16268     if (staticData->first().x() < croppedData->first().x()) // other one must be cropped
16269       qSwap(staticData, croppedData);
16270     int lowBound = findIndexBelowX(croppedData, staticData->first().x());
16271     if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
16272     croppedData->remove(0, lowBound);
16273     // set lowest point of cropped data to fit exactly key position of first static data
16274     // point via linear interpolation:
16275     if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16276     double slope;
16277     if (croppedData->at(1).x()-croppedData->at(0).x() != 0)
16278       slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x());
16279     else
16280       slope = 0;
16281     (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x()));
16282     (*croppedData)[0].setX(staticData->first().x());
16283
16284     // crop upper bound:
16285     if (staticData->last().x() > croppedData->last().x()) // other one must be cropped
16286       qSwap(staticData, croppedData);
16287     int highBound = findIndexAboveX(croppedData, staticData->last().x());
16288     if (highBound == -1) return QPolygonF(); // key ranges have no overlap
16289     croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16290     // set highest point of cropped data to fit exactly key position of last static data
16291     // point via linear interpolation:
16292     if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16293     int li = croppedData->size()-1; // last index
16294     if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0)
16295       slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x());
16296     else
16297       slope = 0;
16298     (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x()));
16299     (*croppedData)[li].setX(staticData->last().x());
16300   } else // mKeyAxis->orientation() == Qt::Vertical
16301   {
16302     // y is key
16303     // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared to x,
16304     // because in pixel coordinates, y increases from top to bottom, not bottom to top like data coordinate.
16305     // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys:
16306     if (staticData->first().y() < staticData->last().y())
16307     {
16308       int size = staticData->size();
16309       for (int i=0; i<size/2; ++i)
16310         qSwap((*staticData)[i], (*staticData)[size-1-i]);
16311     }
16312     if (croppedData->first().y() < croppedData->last().y())
16313     {
16314       int size = croppedData->size();
16315       for (int i=0; i<size/2; ++i)
16316         qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16317     }
16318     // crop lower bound:
16319     if (staticData->first().y() > croppedData->first().y()) // other one must be cropped
16320       qSwap(staticData, croppedData);
16321     int lowBound = findIndexAboveY(croppedData, staticData->first().y());
16322     if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
16323     croppedData->remove(0, lowBound);
16324     // set lowest point of cropped data to fit exactly key position of first static data
16325     // point via linear interpolation:
16326     if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16327     double slope;
16328     if (croppedData->at(1).y()-croppedData->at(0).y() != 0) // avoid division by zero in step plots
16329       slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y());
16330     else
16331       slope = 0;
16332     (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y()));
16333     (*croppedData)[0].setY(staticData->first().y());
16334
16335     // crop upper bound:
16336     if (staticData->last().y() < croppedData->last().y()) // other one must be cropped
16337       qSwap(staticData, croppedData);
16338     int highBound = findIndexBelowY(croppedData, staticData->last().y());
16339     if (highBound == -1) return QPolygonF(); // key ranges have no overlap
16340     croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16341     // set highest point of cropped data to fit exactly key position of last static data
16342     // point via linear interpolation:
16343     if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16344     int li = croppedData->size()-1; // last index
16345     if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0) // avoid division by zero in step plots
16346       slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y());
16347     else
16348       slope = 0;
16349     (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y()));
16350     (*croppedData)[li].setY(staticData->last().y());
16351   }
16352
16353   // return joined:
16354   for (int i=otherData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted
16355     thisData << otherData.at(i);
16356   return QPolygonF(thisData);
16357 }
16358
16359 /*! \internal
16360
16361   Finds the smallest index of \a data, whose points x value is just above \a x. Assumes x values in
16362   \a data points are ordered ascending, as is the case when plotting with horizontal key axis.
16363
16364   Used to calculate the channel fill polygon, see \ref getChannelFillPolygon.
16365 */
16366 int QCPGraph::findIndexAboveX(const QVector<QPointF> *data, double x) const
16367 {
16368   for (int i=data->size()-1; i>=0; --i)
16369   {
16370     if (data->at(i).x() < x)
16371     {
16372       if (i<data->size()-1)
16373         return i+1;
16374       else
16375         return data->size()-1;
16376     }
16377   }
16378   return -1;
16379 }
16380
16381 /*! \internal
16382
16383   Finds the highest index of \a data, whose points x value is just below \a x. Assumes x values in
16384   \a data points are ordered ascending, as is the case when plotting with horizontal key axis.
16385
16386   Used to calculate the channel fill polygon, see \ref getChannelFillPolygon.
16387 */
16388 int QCPGraph::findIndexBelowX(const QVector<QPointF> *data, double x) const
16389 {
16390   for (int i=0; i<data->size(); ++i)
16391   {
16392     if (data->at(i).x() > x)
16393     {
16394       if (i>0)
16395         return i-1;
16396       else
16397         return 0;
16398     }
16399   }
16400   return -1;
16401 }
16402
16403 /*! \internal
16404
16405   Finds the smallest index of \a data, whose points y value is just above \a y. Assumes y values in
16406   \a data points are ordered descending, as is the case when plotting with vertical key axis.
16407
16408   Used to calculate the channel fill polygon, see \ref getChannelFillPolygon.
16409 */
16410 int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const
16411 {
16412   for (int i=0; i<data->size(); ++i)
16413   {
16414     if (data->at(i).y() < y)
16415     {
16416       if (i>0)
16417         return i-1;
16418       else
16419         return 0;
16420     }
16421   }
16422   return -1;
16423 }
16424
16425 /*! \internal
16426
16427   Calculates the (minimum) distance (in pixels) the graph's representation has from the given \a
16428   pixelPoint in pixels. This is used to determine whether the graph was clicked or not, e.g. in
16429   \ref selectTest.
16430
16431   If either the graph has no data or if the line style is \ref lsNone and the scatter style's shape
16432   is \ref QCPScatterStyle::ssNone (i.e. there is no visual representation of the graph), returns
16433   500.
16434 */
16435 double QCPGraph::pointDistance(const QPointF &pixelPoint) const
16436 {
16437   if (mData->isEmpty())
16438   {
16439     qDebug() << Q_FUNC_INFO << "requested point distance on graph" << mName << "without data";
16440     return 500;
16441   }
16442   if (mData->size() == 1)
16443   {
16444     QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value);
16445     return QVector2D(dataPoint-pixelPoint).length();
16446   }
16447
16448   if (mLineStyle == lsNone && mScatterStyle.isNone())
16449     return 500;
16450
16451   // calculate minimum distances to graph representation:
16452   if (mLineStyle == lsNone)
16453   {
16454     // no line displayed, only calculate distance to scatter points:
16455     QVector<QCPData> *scatterData = new QVector<QCPData>;
16456     getScatterPlotData(scatterData);
16457     double minDistSqr = std::numeric_limits<double>::max();
16458     QPointF ptA;
16459     QPointF ptB = coordsToPixels(scatterData->at(0).key, scatterData->at(0).value); // getScatterPlotData returns in plot coordinates, so transform to pixels
16460     for (int i=1; i<scatterData->size(); ++i)
16461     {
16462       ptA = ptB;
16463       ptB = coordsToPixels(scatterData->at(i).key, scatterData->at(i).value);
16464       double currentDistSqr = distSqrToLine(ptA, ptB, pixelPoint);
16465       if (currentDistSqr < minDistSqr)
16466         minDistSqr = currentDistSqr;
16467     }
16468     delete scatterData;
16469     return qSqrt(minDistSqr);
16470   } else
16471   {
16472     // line displayed calculate distance to line segments:
16473     QVector<QPointF> *lineData = new QVector<QPointF>;
16474     getPlotData(lineData, 0); // unlike with getScatterPlotData we get pixel coordinates here
16475     double minDistSqr = std::numeric_limits<double>::max();
16476     if (mLineStyle == lsImpulse)
16477     {
16478       // impulse plot differs from other line styles in that the lineData points are only pairwise connected:
16479       for (int i=0; i<lineData->size()-1; i+=2) // iterate pairs
16480       {
16481         double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
16482         if (currentDistSqr < minDistSqr)
16483           minDistSqr = currentDistSqr;
16484       }
16485     } else
16486     {
16487       // all other line plots (line and step) connect points directly:
16488       for (int i=0; i<lineData->size()-1; ++i)
16489       {
16490         double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
16491         if (currentDistSqr < minDistSqr)
16492           minDistSqr = currentDistSqr;
16493       }
16494     }
16495     delete lineData;
16496     return qSqrt(minDistSqr);
16497   }
16498 }
16499
16500 /*! \internal
16501
16502   Finds the highest index of \a data, whose points y value is just below \a y. Assumes y values in
16503   \a data points are ordered descending, as is the case when plotting with vertical key axis (since
16504   keys are ordered ascending).
16505
16506   Used to calculate the channel fill polygon, see \ref getChannelFillPolygon.
16507 */
16508 int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const
16509 {
16510   for (int i=data->size()-1; i>=0; --i)
16511   {
16512     if (data->at(i).y() > y)
16513     {
16514       if (i<data->size()-1)
16515         return i+1;
16516       else
16517         return data->size()-1;
16518     }
16519   }
16520   return -1;
16521 }
16522
16523 /* inherits documentation from base class */
16524 QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
16525 {
16526   // just call the specialized version which takes an additional argument whether error bars
16527   // should also be taken into consideration for range calculation. We set this to true here.
16528   return getKeyRange(foundRange, inSignDomain, true);
16529 }
16530
16531 /* inherits documentation from base class */
16532 QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain) const
16533 {
16534   // just call the specialized version which takes an additional argument whether error bars
16535   // should also be taken into consideration for range calculation. We set this to true here.
16536   return getValueRange(foundRange, inSignDomain, true);
16537 }
16538
16539 /*! \overload
16540
16541   Allows to specify whether the error bars should be included in the range calculation.
16542
16543   \see getKeyRange(bool &foundRange, SignDomain inSignDomain)
16544 */
16545 QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
16546 {
16547   QCPRange range;
16548   bool haveLower = false;
16549   bool haveUpper = false;
16550
16551   double current, currentErrorMinus, currentErrorPlus;
16552
16553   if (inSignDomain == sdBoth) // range may be anywhere
16554   {
16555     QCPDataMap::const_iterator it = mData->constBegin();
16556     while (it != mData->constEnd())
16557     {
16558       current = it.value().key;
16559       currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16560       currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16561       if (current-currentErrorMinus < range.lower || !haveLower)
16562       {
16563         range.lower = current-currentErrorMinus;
16564         haveLower = true;
16565       }
16566       if (current+currentErrorPlus > range.upper || !haveUpper)
16567       {
16568         range.upper = current+currentErrorPlus;
16569         haveUpper = true;
16570       }
16571       ++it;
16572     }
16573   } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
16574   {
16575     QCPDataMap::const_iterator it = mData->constBegin();
16576     while (it != mData->constEnd())
16577     {
16578       current = it.value().key;
16579       currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16580       currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16581       if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
16582       {
16583         range.lower = current-currentErrorMinus;
16584         haveLower = true;
16585       }
16586       if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
16587       {
16588         range.upper = current+currentErrorPlus;
16589         haveUpper = true;
16590       }
16591       if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
16592       {
16593         if ((current < range.lower || !haveLower) && current < 0)
16594         {
16595           range.lower = current;
16596           haveLower = true;
16597         }
16598         if ((current > range.upper || !haveUpper) && current < 0)
16599         {
16600           range.upper = current;
16601           haveUpper = true;
16602         }
16603       }
16604       ++it;
16605     }
16606   } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16607   {
16608     QCPDataMap::const_iterator it = mData->constBegin();
16609     while (it != mData->constEnd())
16610     {
16611       current = it.value().key;
16612       currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16613       currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16614       if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
16615       {
16616         range.lower = current-currentErrorMinus;
16617         haveLower = true;
16618       }
16619       if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
16620       {
16621         range.upper = current+currentErrorPlus;
16622         haveUpper = true;
16623       }
16624       if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
16625       {
16626         if ((current < range.lower || !haveLower) && current > 0)
16627         {
16628           range.lower = current;
16629           haveLower = true;
16630         }
16631         if ((current > range.upper || !haveUpper) && current > 0)
16632         {
16633           range.upper = current;
16634           haveUpper = true;
16635         }
16636       }
16637       ++it;
16638     }
16639   }
16640
16641   foundRange = haveLower && haveUpper;
16642   return range;
16643 }
16644
16645 /*! \overload
16646
16647   Allows to specify whether the error bars should be included in the range calculation.
16648
16649   \see getValueRange(bool &foundRange, SignDomain inSignDomain)
16650 */
16651 QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
16652 {
16653   QCPRange range;
16654   bool haveLower = false;
16655   bool haveUpper = false;
16656
16657   double current, currentErrorMinus, currentErrorPlus;
16658
16659   if (inSignDomain == sdBoth) // range may be anywhere
16660   {
16661     QCPDataMap::const_iterator it = mData->constBegin();
16662     while (it != mData->constEnd())
16663     {
16664       current = it.value().value;
16665       currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16666       currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16667       if (current-currentErrorMinus < range.lower || !haveLower)
16668       {
16669         range.lower = current-currentErrorMinus;
16670         haveLower = true;
16671       }
16672       if (current+currentErrorPlus > range.upper || !haveUpper)
16673       {
16674         range.upper = current+currentErrorPlus;
16675         haveUpper = true;
16676       }
16677       ++it;
16678     }
16679   } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
16680   {
16681     QCPDataMap::const_iterator it = mData->constBegin();
16682     while (it != mData->constEnd())
16683     {
16684       current = it.value().value;
16685       currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16686       currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16687       if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
16688       {
16689         range.lower = current-currentErrorMinus;
16690         haveLower = true;
16691       }
16692       if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
16693       {
16694         range.upper = current+currentErrorPlus;
16695         haveUpper = true;
16696       }
16697       if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
16698       {
16699         if ((current < range.lower || !haveLower) && current < 0)
16700         {
16701           range.lower = current;
16702           haveLower = true;
16703         }
16704         if ((current > range.upper || !haveUpper) && current < 0)
16705         {
16706           range.upper = current;
16707           haveUpper = true;
16708         }
16709       }
16710       ++it;
16711     }
16712   } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16713   {
16714     QCPDataMap::const_iterator it = mData->constBegin();
16715     while (it != mData->constEnd())
16716     {
16717       current = it.value().value;
16718       currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16719       currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16720       if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
16721       {
16722         range.lower = current-currentErrorMinus;
16723         haveLower = true;
16724       }
16725       if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
16726       {
16727         range.upper = current+currentErrorPlus;
16728         haveUpper = true;
16729       }
16730       if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
16731       {
16732         if ((current < range.lower || !haveLower) && current > 0)
16733         {
16734           range.lower = current;
16735           haveLower = true;
16736         }
16737         if ((current > range.upper || !haveUpper) && current > 0)
16738         {
16739           range.upper = current;
16740           haveUpper = true;
16741         }
16742       }
16743       ++it;
16744     }
16745   }
16746
16747   foundRange = haveLower && haveUpper;
16748   return range;
16749 }
16750
16751
16752 ////////////////////////////////////////////////////////////////////////////////////////////////////
16753 //////////////////// QCPCurveData
16754 ////////////////////////////////////////////////////////////////////////////////////////////////////
16755
16756 /*! \class QCPCurveData
16757   \brief Holds the data of one single data point for QCPCurve.
16758
16759   The container for storing multiple data points is \ref QCPCurveDataMap.
16760
16761   The stored data is:
16762   \li \a t: the free parameter of the curve at this curve point (cp. the mathematical vector <em>(x(t), y(t))</em>)
16763   \li \a key: coordinate on the key axis of this curve point
16764   \li \a value: coordinate on the value axis of this curve point
16765
16766   \see QCPCurveDataMap
16767 */
16768
16769 /*!
16770   Constructs a curve data point with t, key and value set to zero.
16771 */
16772 QCPCurveData::QCPCurveData() :
16773   t(0),
16774   key(0),
16775   value(0)
16776 {
16777 }
16778
16779 /*!
16780   Constructs a curve data point with the specified \a t, \a key and \a value.
16781 */
16782 QCPCurveData::QCPCurveData(double t, double key, double value) :
16783   t(t),
16784   key(key),
16785   value(value)
16786 {
16787 }
16788
16789
16790 ////////////////////////////////////////////////////////////////////////////////////////////////////
16791 //////////////////// QCPCurve
16792 ////////////////////////////////////////////////////////////////////////////////////////////////////
16793
16794 /*! \class QCPCurve
16795   \brief A plottable representing a parametric curve in a plot.
16796
16797   \image html QCPCurve.png
16798
16799   Unlike QCPGraph, plottables of this type may have multiple points with the same key coordinate,
16800   so their visual representation can have \a loops. This is realized by introducing a third
16801   coordinate \a t, which defines the order of the points described by the other two coordinates \a
16802   x and \a y.
16803
16804   To plot data, assign it with the \ref setData or \ref addData functions.
16805
16806   \section appearance Changing the appearance
16807
16808   The appearance of the curve is determined by the pen and the brush (\ref setPen, \ref setBrush).
16809   \section usage Usage
16810
16811   Like all data representing objects in QCustomPlot, the QCPCurve is a plottable (QCPAbstractPlottable). So
16812   the plottable-interface of QCustomPlot applies (QCustomPlot::plottable, QCustomPlot::addPlottable, QCustomPlot::removePlottable, etc.)
16813
16814   Usually, you first create an instance:
16815   \code
16816   QCPCurve *newCurve = new QCPCurve(customPlot->xAxis, customPlot->yAxis);\endcode
16817   add it to the customPlot with QCustomPlot::addPlottable:
16818   \code
16819   customPlot->addPlottable(newCurve);\endcode
16820   and then modify the properties of the newly created plottable, e.g.:
16821   \code
16822   newCurve->setName("Fermat's Spiral");
16823   newCurve->setData(tData, xData, yData);\endcode
16824 */
16825
16826 /*!
16827   Constructs a curve which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value
16828   axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have
16829   the same orientation. If either of these restrictions is violated, a corresponding message is
16830   printed to the debug output (qDebug), the construction is not aborted, though.
16831
16832   The constructed QCPCurve can be added to the plot with QCustomPlot::addPlottable, QCustomPlot
16833   then takes ownership of the graph.
16834 */
16835 QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) :
16836   QCPAbstractPlottable(keyAxis, valueAxis)
16837 {
16838   mData = new QCPCurveDataMap;
16839   mPen.setColor(Qt::blue);
16840   mPen.setStyle(Qt::SolidLine);
16841   mBrush.setColor(Qt::blue);
16842   mBrush.setStyle(Qt::NoBrush);
16843   mSelectedPen = mPen;
16844   mSelectedPen.setWidthF(2.5);
16845   mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen
16846   mSelectedBrush = mBrush;
16847
16848   setScatterStyle(QCPScatterStyle());
16849   setLineStyle(lsLine);
16850 }
16851
16852 QCPCurve::~QCPCurve()
16853 {
16854   delete mData;
16855 }
16856
16857 /*!
16858   Replaces the current data with the provided \a data.
16859
16860   If \a copy is set to true, data points in \a data will only be copied. if false, the plottable
16861   takes ownership of the passed data and replaces the internal data pointer with it. This is
16862   significantly faster than copying for large datasets.
16863 */
16864 void QCPCurve::setData(QCPCurveDataMap *data, bool copy)
16865 {
16866   if (mData == data)
16867   {
16868     qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
16869     return;
16870   }
16871   if (copy)
16872   {
16873     *mData = *data;
16874   } else
16875   {
16876     delete mData;
16877     mData = data;
16878   }
16879 }
16880
16881 /*! \overload
16882
16883   Replaces the current data with the provided points in \a t, \a key and \a value tuples. The
16884   provided vectors should have equal length. Else, the number of added points will be the size of
16885   the smallest vector.
16886 */
16887 void QCPCurve::setData(const QVector<double> &t, const QVector<double> &key, const QVector<double> &value)
16888 {
16889   mData->clear();
16890   int n = t.size();
16891   n = qMin(n, key.size());
16892   n = qMin(n, value.size());
16893   QCPCurveData newData;
16894   for (int i=0; i<n; ++i)
16895   {
16896     newData.t = t[i];
16897     newData.key = key[i];
16898     newData.value = value[i];
16899     mData->insertMulti(newData.t, newData);
16900   }
16901 }
16902
16903 /*! \overload
16904
16905   Replaces the current data with the provided \a key and \a value pairs. The t parameter
16906   of each data point will be set to the integer index of the respective key/value pair.
16907 */
16908 void QCPCurve::setData(const QVector<double> &key, const QVector<double> &value)
16909 {
16910   mData->clear();
16911   int n = key.size();
16912   n = qMin(n, value.size());
16913   QCPCurveData newData;
16914   for (int i=0; i<n; ++i)
16915   {
16916     newData.t = i; // no t vector given, so we assign t the index of the key/value pair
16917     newData.key = key[i];
16918     newData.value = value[i];
16919     mData->insertMulti(newData.t, newData);
16920   }
16921 }
16922
16923 /*!
16924   Sets the visual appearance of single data points in the plot. If set to \ref
16925   QCPScatterStyle::ssNone, no scatter points are drawn (e.g. for line-only plots with appropriate
16926   line style).
16927
16928   \see QCPScatterStyle, setLineStyle
16929 */
16930 void QCPCurve::setScatterStyle(const QCPScatterStyle &style)
16931 {
16932   mScatterStyle = style;
16933 }
16934
16935 /*!
16936   Sets how the single data points are connected in the plot or how they are represented visually
16937   apart from the scatter symbol. For scatter-only plots, set \a style to \ref lsNone and \ref
16938   setScatterStyle to the desired scatter style.
16939
16940   \see setScatterStyle
16941 */
16942 void QCPCurve::setLineStyle(QCPCurve::LineStyle style)
16943 {
16944   mLineStyle = style;
16945 }
16946
16947 /*!
16948   Adds the provided data points in \a dataMap to the current data.
16949   \see removeData
16950 */
16951 void QCPCurve::addData(const QCPCurveDataMap &dataMap)
16952 {
16953   mData->unite(dataMap);
16954 }
16955
16956 /*! \overload
16957   Adds the provided single data point in \a data to the current data.
16958   \see removeData
16959 */
16960 void QCPCurve::addData(const QCPCurveData &data)
16961 {
16962   mData->insertMulti(data.t, data);
16963 }
16964
16965 /*! \overload
16966   Adds the provided single data point as \a t, \a key and \a value tuple to the current data
16967   \see removeData
16968 */
16969 void QCPCurve::addData(double t, double key, double value)
16970 {
16971   QCPCurveData newData;
16972   newData.t = t;
16973   newData.key = key;
16974   newData.value = value;
16975   mData->insertMulti(newData.t, newData);
16976 }
16977
16978 /*! \overload
16979
16980   Adds the provided single data point as \a key and \a value pair to the current data The t
16981   parameter of the data point is set to the t of the last data point plus 1. If there is no last
16982   data point, t will be set to 0.
16983
16984   \see removeData
16985 */
16986 void QCPCurve::addData(double key, double value)
16987 {
16988   QCPCurveData newData;
16989   if (!mData->isEmpty())
16990     newData.t = (mData->constEnd()-1).key()+1;
16991   else
16992     newData.t = 0;
16993   newData.key = key;
16994   newData.value = value;
16995   mData->insertMulti(newData.t, newData);
16996 }
16997
16998 /*! \overload
16999   Adds the provided data points as \a t, \a key and \a value tuples to the current data.
17000   \see removeData
17001 */
17002 void QCPCurve::addData(const QVector<double> &ts, const QVector<double> &keys, const QVector<double> &values)
17003 {
17004   int n = ts.size();
17005   n = qMin(n, keys.size());
17006   n = qMin(n, values.size());
17007   QCPCurveData newData;
17008   for (int i=0; i<n; ++i)
17009   {
17010     newData.t = ts[i];
17011     newData.key = keys[i];
17012     newData.value = values[i];
17013     mData->insertMulti(newData.t, newData);
17014   }
17015 }
17016
17017 /*!
17018   Removes all data points with curve parameter t smaller than \a t.
17019   \see addData, clearData
17020 */
17021 void QCPCurve::removeDataBefore(double t)
17022 {
17023   QCPCurveDataMap::iterator it = mData->begin();
17024   while (it != mData->end() && it.key() < t)
17025     it = mData->erase(it);
17026 }
17027
17028 /*!
17029   Removes all data points with curve parameter t greater than \a t.
17030   \see addData, clearData
17031 */
17032 void QCPCurve::removeDataAfter(double t)
17033 {
17034   if (mData->isEmpty()) return;
17035   QCPCurveDataMap::iterator it = mData->upperBound(t);
17036   while (it != mData->end())
17037     it = mData->erase(it);
17038 }
17039
17040 /*!
17041   Removes all data points with curve parameter t between \a fromt and \a tot. if \a fromt is
17042   greater or equal to \a tot, the function does nothing. To remove a single data point with known
17043   t, use \ref removeData(double t).
17044
17045   \see addData, clearData
17046 */
17047 void QCPCurve::removeData(double fromt, double tot)
17048 {
17049   if (fromt >= tot || mData->isEmpty()) return;
17050   QCPCurveDataMap::iterator it = mData->upperBound(fromt);
17051   QCPCurveDataMap::iterator itEnd = mData->upperBound(tot);
17052   while (it != itEnd)
17053     it = mData->erase(it);
17054 }
17055
17056 /*! \overload
17057
17058   Removes a single data point at curve parameter \a t. If the position is not known with absolute
17059   precision, consider using \ref removeData(double fromt, double tot) with a small fuzziness
17060   interval around the suspected position, depeding on the precision with which the curve parameter
17061   is known.
17062
17063   \see addData, clearData
17064 */
17065 void QCPCurve::removeData(double t)
17066 {
17067   mData->remove(t);
17068 }
17069
17070 /*!
17071   Removes all data points.
17072   \see removeData, removeDataAfter, removeDataBefore
17073 */
17074 void QCPCurve::clearData()
17075 {
17076   mData->clear();
17077 }
17078
17079 /* inherits documentation from base class */
17080 double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
17081 {
17082   Q_UNUSED(details)
17083   if ((onlySelectable && !mSelectable) || mData->isEmpty())
17084     return -1;
17085   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
17086
17087   if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
17088     return pointDistance(pos);
17089   else
17090     return -1;
17091 }
17092
17093 /* inherits documentation from base class */
17094 void QCPCurve::draw(QCPPainter *painter)
17095 {
17096   if (mData->isEmpty()) return;
17097
17098   // allocate line vector:
17099   QVector<QPointF> *lineData = new QVector<QPointF>;
17100
17101   // fill with curve data:
17102   getCurveData(lineData);
17103
17104   // check data validity if flag set:
17105 #ifdef QCUSTOMPLOT_CHECK_DATA
17106   QCPCurveDataMap::const_iterator it;
17107   for (it = mData->constBegin(); it != mData->constEnd(); ++it)
17108   {
17109     if (QCP::isInvalidData(it.value().t) ||
17110         QCP::isInvalidData(it.value().key, it.value().value))
17111       qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
17112   }
17113 #endif
17114
17115   // draw curve fill:
17116   if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0)
17117   {
17118     applyFillAntialiasingHint(painter);
17119     painter->setPen(Qt::NoPen);
17120     painter->setBrush(mainBrush());
17121     painter->drawPolygon(QPolygonF(*lineData));
17122   }
17123
17124   // draw curve line:
17125   if (mLineStyle != lsNone && mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
17126   {
17127     applyDefaultAntialiasingHint(painter);
17128     painter->setPen(mainPen());
17129     painter->setBrush(Qt::NoBrush);
17130     // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
17131     if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
17132         painter->pen().style() == Qt::SolidLine &&
17133         !painter->modes().testFlag(QCPPainter::pmVectorized) &&
17134         !painter->modes().testFlag(QCPPainter::pmNoCaching))
17135     {
17136       int i = 1;
17137       int lineDataSize = lineData->size();
17138       while (i < lineDataSize)
17139       {
17140         if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
17141           painter->drawLine(lineData->at(i-1), lineData->at(i));
17142         else
17143           ++i;
17144         ++i;
17145       }
17146     } else
17147     {
17148       int segmentStart = 0;
17149       int i = 0;
17150       int lineDataSize = lineData->size();
17151       while (i < lineDataSize)
17152       {
17153         if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
17154         {
17155           painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
17156           segmentStart = i+1;
17157         }
17158         ++i;
17159       }
17160       // draw last segment:
17161       painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point
17162     }
17163   }
17164
17165   // draw scatters:
17166   if (!mScatterStyle.isNone())
17167     drawScatterPlot(painter, lineData);
17168
17169   // free allocated line data:
17170   delete lineData;
17171 }
17172
17173 /* inherits documentation from base class */
17174 void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
17175 {
17176   // draw fill:
17177   if (mBrush.style() != Qt::NoBrush)
17178   {
17179     applyFillAntialiasingHint(painter);
17180     painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
17181   }
17182   // draw line vertically centered:
17183   if (mLineStyle != lsNone)
17184   {
17185     applyDefaultAntialiasingHint(painter);
17186     painter->setPen(mPen);
17187     painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
17188   }
17189   // draw scatter symbol:
17190   if (!mScatterStyle.isNone())
17191   {
17192     applyScattersAntialiasingHint(painter);
17193     // scale scatter pixmap if it's too large to fit in legend icon rect:
17194     if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
17195     {
17196       QCPScatterStyle scaledStyle(mScatterStyle);
17197       scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
17198       scaledStyle.applyTo(painter, mPen);
17199       scaledStyle.drawShape(painter, QRectF(rect).center());
17200     } else
17201     {
17202       mScatterStyle.applyTo(painter, mPen);
17203       mScatterStyle.drawShape(painter, QRectF(rect).center());
17204     }
17205   }
17206 }
17207
17208 /*! \internal
17209
17210   Draws scatter symbols at every data point passed in \a pointData. scatter symbols are independent of
17211   the line style and are always drawn if scatter shape is not \ref QCPScatterStyle::ssNone.
17212 */
17213 void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector<QPointF> *pointData) const
17214 {
17215   // draw scatter point symbols:
17216   applyScattersAntialiasingHint(painter);
17217   mScatterStyle.applyTo(painter, mPen);
17218   for (int i=0; i<pointData->size(); ++i)
17219     if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y()))
17220       mScatterStyle.drawShape(painter,  pointData->at(i));
17221 }
17222
17223 /*! \internal
17224
17225   called by QCPCurve::draw to generate a point vector (in pixel coordinates) which represents the
17226   line of the curve.
17227
17228   Line segments that aren't visible in the current axis rect are handled in an optimized way. They
17229   are projected onto a rectangle slightly larger than the visible axis rect and simplified
17230   regarding point count. The algorithm makes sure to preserve appearance of lines and fills inside
17231   the visible axis rect by generating new temporary points on the outer rect if necessary.
17232
17233   Methods that are also involved in the algorithm are: \ref getRegion, \ref getOptimizedPoint, \ref
17234   getOptimizedCornerPoints \ref mayTraverse, \ref getTraverse, \ref getTraverseCornerPoints.
17235 */
17236 void QCPCurve::getCurveData(QVector<QPointF> *lineData) const
17237 {
17238   QCPAxis *keyAxis = mKeyAxis.data();
17239   QCPAxis *valueAxis = mValueAxis.data();
17240   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
17241
17242   // add margins to rect to compensate for stroke width
17243   double strokeMargin = qMax(qreal(1.0), qreal(mainPen().widthF()*0.75)); // stroke radius + 50% safety
17244   if (!mScatterStyle.isNone())
17245     strokeMargin = qMax(strokeMargin, mScatterStyle.size());
17246   double rectLeft = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1));
17247   double rectRight = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1));
17248   double rectBottom = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)+strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1));
17249   double rectTop = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)-strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1));
17250   int currentRegion;
17251   QCPCurveDataMap::const_iterator it = mData->constBegin();
17252   QCPCurveDataMap::const_iterator prevIt = mData->constEnd()-1;
17253   int prevRegion = getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom);
17254   QVector<QPointF> trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right)
17255   while (it != mData->constEnd())
17256   {
17257     currentRegion = getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17258     if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R
17259     {
17260       if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal
17261       {
17262         QPointF crossA, crossB;
17263         if (prevRegion == 5) // we're coming from R, so add this point optimized
17264         {
17265           lineData->append(getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom));
17266           // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point
17267           *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17268         } else if (mayTraverse(prevRegion, currentRegion) &&
17269                    getTraverse(prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom, crossA, crossB))
17270         {
17271           // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point:
17272           QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints;
17273           getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints);
17274           if (it != mData->constBegin())
17275           {
17276             *lineData << beforeTraverseCornerPoints;
17277             lineData->append(crossA);
17278             lineData->append(crossB);
17279             *lineData << afterTraverseCornerPoints;
17280           } else
17281           {
17282             lineData->append(crossB);
17283             *lineData << afterTraverseCornerPoints;
17284             trailingPoints << beforeTraverseCornerPoints << crossA ;
17285           }
17286         } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s)
17287         {
17288           *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17289         }
17290       } else // segment does end in R, so we add previous point optimized and this point at original position
17291       {
17292         if (it == mData->constBegin()) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end
17293           trailingPoints << getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17294         else
17295           lineData->append(getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom));
17296         lineData->append(coordsToPixels(it.value().key, it.value().value));
17297       }
17298     } else // region didn't change
17299     {
17300       if (currentRegion == 5) // still in R, keep adding original points
17301       {
17302         lineData->append(coordsToPixels(it.value().key, it.value().value));
17303       } else // still outside R, no need to add anything
17304       {
17305         // see how this is not doing anything? That's the main optimization...
17306       }
17307     }
17308     prevIt = it;
17309     prevRegion = currentRegion;
17310     ++it;
17311   }
17312   *lineData << trailingPoints;
17313 }
17314
17315 /*! \internal
17316
17317   This function is part of the curve optimization algorithm of \ref getCurveData.
17318
17319   It returns the region of the given point (\a x, \a y) with respect to a rectangle defined by \a
17320   rectLeft, \a rectTop, \a rectRight, and \a rectBottom.
17321
17322   The regions are enumerated from top to bottom and left to right:
17323
17324   <table style="width:10em; text-align:center">
17325     <tr><td>1</td><td>4</td><td>7</td></tr>
17326     <tr><td>2</td><td style="border:1px solid black">5</td><td>8</td></tr>
17327     <tr><td>3</td><td>6</td><td>9</td></tr>
17328   </table>
17329
17330   With the rectangle being region 5, and the outer regions extending infinitely outwards. In the
17331   curve optimization algorithm, region 5 is considered to be the visible portion of the plot.
17332 */
17333 int QCPCurve::getRegion(double x, double y, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17334 {
17335   if (x < rectLeft) // region 123
17336   {
17337     if (y > rectTop)
17338       return 1;
17339     else if (y < rectBottom)
17340       return 3;
17341     else
17342       return 2;
17343   } else if (x > rectRight) // region 789
17344   {
17345     if (y > rectTop)
17346       return 7;
17347     else if (y < rectBottom)
17348       return 9;
17349     else
17350       return 8;
17351   } else // region 456
17352   {
17353     if (y > rectTop)
17354       return 4;
17355     else if (y < rectBottom)
17356       return 6;
17357     else
17358       return 5;
17359   }
17360 }
17361
17362 /*! \internal
17363
17364   This function is part of the curve optimization algorithm of \ref getCurveData.
17365
17366   This method is used in case the current segment passes from inside the visible rect (region 5,
17367   see \ref getRegion) to any of the outer regions (\a otherRegion). The current segment is given by
17368   the line connecting (\a key, \a value) with (\a otherKey, \a otherValue).
17369
17370   It returns the intersection point of the segment with the border of region 5.
17371
17372   For this function it doesn't matter whether (\a key, \a value) is the point inside region 5 or
17373   whether it's (\a otherKey, \a otherValue), i.e. whether the segment is coming from region 5 or
17374   leaving it. It is important though that \a otherRegion correctly identifies the other region not
17375   equal to 5.
17376 */
17377 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17378 {
17379   double intersectKey = rectLeft; // initial value is just fail-safe
17380   double intersectValue = rectTop; // initial value is just fail-safe
17381   switch (otherRegion)
17382   {
17383     case 1: // top and left edge
17384     {
17385       intersectValue = rectTop;
17386       intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17387       if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17388       {
17389         intersectKey = rectLeft;
17390         intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17391       }
17392       break;
17393     }
17394     case 2: // left edge
17395     {
17396       intersectKey = rectLeft;
17397       intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17398       break;
17399     }
17400     case 3: // bottom and left edge
17401     {
17402       intersectValue = rectBottom;
17403       intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17404       if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17405       {
17406         intersectKey = rectLeft;
17407         intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17408       }
17409       break;
17410     }
17411     case 4: // top edge
17412     {
17413       intersectValue = rectTop;
17414       intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17415       break;
17416     }
17417     case 5:
17418     {
17419       break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table
17420     }
17421     case 6: // bottom edge
17422     {
17423       intersectValue = rectBottom;
17424       intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17425       break;
17426     }
17427     case 7: // top and right edge
17428     {
17429       intersectValue = rectTop;
17430       intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17431       if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17432       {
17433         intersectKey = rectRight;
17434         intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17435       }
17436       break;
17437     }
17438     case 8: // right edge
17439     {
17440       intersectKey = rectRight;
17441       intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17442       break;
17443     }
17444     case 9: // bottom and right edge
17445     {
17446       intersectValue = rectBottom;
17447       intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17448       if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17449       {
17450         intersectKey = rectRight;
17451         intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17452       }
17453       break;
17454     }
17455   }
17456   return coordsToPixels(intersectKey, intersectValue);
17457 }
17458
17459 /*! \internal
17460
17461   This function is part of the curve optimization algorithm of \ref getCurveData.
17462
17463   In situations where a single segment skips over multiple regions it might become necessary to add
17464   extra points at the corners of region 5 (see \ref getRegion) such that the optimized segment
17465   doesn't unintentionally cut through the visible area of the axis rect and create plot artifacts.
17466   This method provides these points that must be added, assuming the original segment doesn't
17467   start, end, or traverse region 5. (Corner points where region 5 is traversed are calculated by
17468   \ref getTraverseCornerPoints.)
17469
17470   For example, consider a segment which directly goes from region 4 to 2 but originally is far out
17471   to the top left such that it doesn't cross region 5. Naively optimizing these points by
17472   projecting them on the top and left borders of region 5 will create a segment that surely crosses
17473   5, creating a visual artifact in the plot. This method prevents this by providing extra points at
17474   the top left corner, making the optimized curve correctly pass from region 4 to 1 to 2 without
17475   traversing 5.
17476 */
17477 QVector<QPointF> QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17478 {
17479   QVector<QPointF> result;
17480   switch (prevRegion)
17481   {
17482     case 1:
17483     {
17484       switch (currentRegion)
17485       {
17486         case 2: { result << coordsToPixels(rectLeft, rectTop); break; }
17487         case 4: { result << coordsToPixels(rectLeft, rectTop); break; }
17488         case 3: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); break; }
17489         case 7: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); break; }
17490         case 6: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17491         case 8: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17492         case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17493           if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R
17494           { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); }
17495           else
17496           { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); }
17497           break;
17498         }
17499       }
17500       break;
17501     }
17502     case 2:
17503     {
17504       switch (currentRegion)
17505       {
17506         case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17507         case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17508         case 4: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17509         case 6: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17510         case 7: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; }
17511         case 9: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; }
17512       }
17513       break;
17514     }
17515     case 3:
17516     {
17517       switch (currentRegion)
17518       {
17519         case 2: { result << coordsToPixels(rectLeft, rectBottom); break; }
17520         case 6: { result << coordsToPixels(rectLeft, rectBottom); break; }
17521         case 1: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); break; }
17522         case 9: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); break; }
17523         case 4: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17524         case 8: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17525         case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17526           if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R
17527           { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); }
17528           else
17529           { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); }
17530           break;
17531         }
17532       }
17533       break;
17534     }
17535     case 4:
17536     {
17537       switch (currentRegion)
17538       {
17539         case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17540         case 7: { result << coordsToPixels(rectRight, rectTop); break; }
17541         case 2: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17542         case 8: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17543         case 3: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; }
17544         case 9: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; }
17545       }
17546       break;
17547     }
17548     case 5:
17549     {
17550       switch (currentRegion)
17551       {
17552         case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17553         case 7: { result << coordsToPixels(rectRight, rectTop); break; }
17554         case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
17555         case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17556       }
17557       break;
17558     }
17559     case 6:
17560     {
17561       switch (currentRegion)
17562       {
17563         case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17564         case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
17565         case 2: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17566         case 8: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17567         case 1: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; }
17568         case 7: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; }
17569       }
17570       break;
17571     }
17572     case 7:
17573     {
17574       switch (currentRegion)
17575       {
17576         case 4: { result << coordsToPixels(rectRight, rectTop); break; }
17577         case 8: { result << coordsToPixels(rectRight, rectTop); break; }
17578         case 1: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); break; }
17579         case 9: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); break; }
17580         case 2: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17581         case 6: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17582         case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17583           if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R
17584           { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); }
17585           else
17586           { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); }
17587           break;
17588         }
17589       }
17590       break;
17591     }
17592     case 8:
17593     {
17594       switch (currentRegion)
17595       {
17596         case 7: { result << coordsToPixels(rectRight, rectTop); break; }
17597         case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
17598         case 4: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17599         case 6: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17600         case 1: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; }
17601         case 3: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; }
17602       }
17603       break;
17604     }
17605     case 9:
17606     {
17607       switch (currentRegion)
17608       {
17609         case 6: { result << coordsToPixels(rectRight, rectBottom); break; }
17610         case 8: { result << coordsToPixels(rectRight, rectBottom); break; }
17611         case 3: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); break; }
17612         case 7: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); break; }
17613         case 2: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17614         case 4: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17615         case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17616           if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R
17617           { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); }
17618           else
17619           { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); }
17620           break;
17621         }
17622       }
17623       break;
17624     }
17625   }
17626   return result;
17627 }
17628
17629 /*! \internal
17630
17631   This function is part of the curve optimization algorithm of \ref getCurveData.
17632
17633   This method returns whether a segment going from \a prevRegion to \a currentRegion (see \ref
17634   getRegion) may traverse the visible region 5. This function assumes that neither \a prevRegion
17635   nor \a currentRegion is 5 itself.
17636
17637   If this method returns false, the segment for sure doesn't pass region 5. If it returns true, the
17638   segment may or may not pass region 5 and a more fine-grained calculation must be used (\ref
17639   getTraverse).
17640 */
17641 bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const
17642 {
17643   switch (prevRegion)
17644   {
17645     case 1:
17646     {
17647       switch (currentRegion)
17648       {
17649         case 4:
17650         case 7:
17651         case 2:
17652         case 3: return false;
17653         default: return true;
17654       }
17655     }
17656     case 2:
17657     {
17658       switch (currentRegion)
17659       {
17660         case 1:
17661         case 3: return false;
17662         default: return true;
17663       }
17664     }
17665     case 3:
17666     {
17667       switch (currentRegion)
17668       {
17669         case 1:
17670         case 2:
17671         case 6:
17672         case 9: return false;
17673         default: return true;
17674       }
17675     }
17676     case 4:
17677     {
17678       switch (currentRegion)
17679       {
17680         case 1:
17681         case 7: return false;
17682         default: return true;
17683       }
17684     }
17685     case 5: return false; // should never occur
17686     case 6:
17687     {
17688       switch (currentRegion)
17689       {
17690         case 3:
17691         case 9: return false;
17692         default: return true;
17693       }
17694     }
17695     case 7:
17696     {
17697       switch (currentRegion)
17698       {
17699         case 1:
17700         case 4:
17701         case 8:
17702         case 9: return false;
17703         default: return true;
17704       }
17705     }
17706     case 8:
17707     {
17708       switch (currentRegion)
17709       {
17710         case 7:
17711         case 9: return false;
17712         default: return true;
17713       }
17714     }
17715     case 9:
17716     {
17717       switch (currentRegion)
17718       {
17719         case 3:
17720         case 6:
17721         case 8:
17722         case 7: return false;
17723         default: return true;
17724       }
17725     }
17726     default: return true;
17727   }
17728 }
17729
17730
17731 /*! \internal
17732
17733   This function is part of the curve optimization algorithm of \ref getCurveData.
17734
17735   This method assumes that the \ref mayTraverse test has returned true, so there is a chance the
17736   segment defined by (\a prevKey, \a prevValue) and (\a key, \a value) goes through the visible
17737   region 5.
17738
17739   The return value of this method indicates whether the segment actually traverses region 5 or not.
17740
17741   If the segment traverses 5, the output parameters \a crossA and \a crossB indicate the entry and
17742   exit points of region 5. They will become the optimized points for that segment.
17743 */
17744 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const
17745 {
17746   QList<QPointF> intersections; // x of QPointF corresponds to key and y to value
17747   if (qFuzzyIsNull(key-prevKey)) // line is parallel to value axis
17748   {
17749     // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here
17750     intersections.append(QPointF(key, rectBottom)); // direction will be taken care of at end of method
17751     intersections.append(QPointF(key, rectTop));
17752   } else if (qFuzzyIsNull(value-prevValue)) // line is parallel to key axis
17753   {
17754     // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here
17755     intersections.append(QPointF(rectLeft, value)); // direction will be taken care of at end of method
17756     intersections.append(QPointF(rectRight, value));
17757   } else // line is skewed
17758   {
17759     double gamma;
17760     double keyPerValue = (key-prevKey)/(value-prevValue);
17761     // check top of rect:
17762     gamma = prevKey + (rectTop-prevValue)*keyPerValue;
17763     if (gamma >= rectLeft && gamma <= rectRight)
17764       intersections.append(QPointF(gamma, rectTop));
17765     // check bottom of rect:
17766     gamma = prevKey + (rectBottom-prevValue)*keyPerValue;
17767     if (gamma >= rectLeft && gamma <= rectRight)
17768       intersections.append(QPointF(gamma, rectBottom));
17769     double valuePerKey = 1.0/keyPerValue;
17770     // check left of rect:
17771     gamma = prevValue + (rectLeft-prevKey)*valuePerKey;
17772     if (gamma >= rectBottom && gamma <= rectTop)
17773       intersections.append(QPointF(rectLeft, gamma));
17774     // check right of rect:
17775     gamma = prevValue + (rectRight-prevKey)*valuePerKey;
17776     if (gamma >= rectBottom && gamma <= rectTop)
17777       intersections.append(QPointF(rectRight, gamma));
17778   }
17779
17780   // handle cases where found points isn't exactly 2:
17781   if (intersections.size() > 2)
17782   {
17783     // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between:
17784     double distSqrMax = 0;
17785     QPointF pv1, pv2;
17786     for (int i=0; i<intersections.size()-1; ++i)
17787     {
17788       for (int k=i+1; k<intersections.size(); ++k)
17789       {
17790         QPointF distPoint = intersections.at(i)-intersections.at(k);
17791         double distSqr = distPoint.x()*distPoint.x()+distPoint.y()+distPoint.y();
17792         if (distSqr > distSqrMax)
17793         {
17794           pv1 = intersections.at(i);
17795           pv2 = intersections.at(k);
17796           distSqrMax = distSqr;
17797         }
17798       }
17799     }
17800     intersections = QList<QPointF>() << pv1 << pv2;
17801   } else if (intersections.size() != 2)
17802   {
17803     // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment
17804     return false;
17805   }
17806
17807   // possibly re-sort points so optimized point segment has same direction as original segment:
17808   if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction
17809     intersections.move(0, 1);
17810   crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y());
17811   crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y());
17812   return true;
17813 }
17814
17815 /*! \internal
17816
17817   This function is part of the curve optimization algorithm of \ref getCurveData.
17818
17819   This method assumes that the \ref getTraverse test has returned true, so the segment definitely
17820   traverses the visible region 5 when going from \a prevRegion to \a currentRegion.
17821
17822   In certain situations it is not sufficient to merely generate the entry and exit points of the
17823   segment into/out of region 5, as \ref getTraverse provides. It may happen that a single segment, in
17824   addition to traversing region 5, skips another region outside of region 5, which makes it
17825   necessary to add an optimized corner point there (very similar to the job \ref
17826   getOptimizedCornerPoints does for segments that are completely in outside regions and don't
17827   traverse 5).
17828
17829   As an example, consider a segment going from region 1 to region 6, traversing the lower left
17830   corner of region 5. In this configuration, the segment additionally crosses the border between
17831   region 1 and 2 before entering region 5. This makes it necessary to add an additional point in
17832   the top left corner, before adding the optimized traverse points. So in this case, the output
17833   parameter \a beforeTraverse will contain the top left corner point, and \a afterTraverse will be
17834   empty.
17835
17836   In some cases, such as when going from region 1 to 9, it may even be necessary to add additional
17837   corner points before and after the traverse. Then both \a beforeTraverse and \a afterTraverse
17838   return the respective corner points.
17839 */
17840 void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector<QPointF> &beforeTraverse, QVector<QPointF> &afterTraverse) const
17841 {
17842   switch (prevRegion)
17843   {
17844     case 1:
17845     {
17846       switch (currentRegion)
17847       {
17848         case 6: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; }
17849         case 9: { beforeTraverse << coordsToPixels(rectLeft, rectTop); afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
17850         case 8: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; }
17851       }
17852       break;
17853     }
17854     case 2:
17855     {
17856       switch (currentRegion)
17857       {
17858         case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; }
17859         case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
17860       }
17861       break;
17862     }
17863     case 3:
17864     {
17865       switch (currentRegion)
17866       {
17867         case 4: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17868         case 7: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); afterTraverse << coordsToPixels(rectRight, rectTop); break; }
17869         case 8: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17870       }
17871       break;
17872     }
17873     case 4:
17874     {
17875       switch (currentRegion)
17876       {
17877         case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17878         case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
17879       }
17880       break;
17881     }
17882     case 5: { break; } // shouldn't happen because this method only handles full traverses
17883     case 6:
17884     {
17885       switch (currentRegion)
17886       {
17887         case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
17888         case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; }
17889       }
17890       break;
17891     }
17892     case 7:
17893     {
17894       switch (currentRegion)
17895       {
17896         case 2: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; }
17897         case 3: { beforeTraverse << coordsToPixels(rectRight, rectTop); afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17898         case 6: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; }
17899       }
17900       break;
17901     }
17902     case 8:
17903     {
17904       switch (currentRegion)
17905       {
17906         case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
17907         case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17908       }
17909       break;
17910     }
17911     case 9:
17912     {
17913       switch (currentRegion)
17914       {
17915         case 2: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; }
17916         case 1: { beforeTraverse << coordsToPixels(rectRight, rectBottom); afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
17917         case 4: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; }
17918       }
17919       break;
17920     }
17921   }
17922 }
17923
17924 /*! \internal
17925
17926   Calculates the (minimum) distance (in pixels) the curve's representation has from the given \a
17927   pixelPoint in pixels. This is used to determine whether the curve was clicked or not, e.g. in
17928   \ref selectTest.
17929 */
17930 double QCPCurve::pointDistance(const QPointF &pixelPoint) const
17931 {
17932   if (mData->isEmpty())
17933   {
17934     qDebug() << Q_FUNC_INFO << "requested point distance on curve" << mName << "without data";
17935     return 500;
17936   }
17937   if (mData->size() == 1)
17938   {
17939     QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value);
17940     return QVector2D(dataPoint-pixelPoint).length();
17941   }
17942
17943   // calculate minimum distance to line segments:
17944   QVector<QPointF> *lineData = new QVector<QPointF>;
17945   getCurveData(lineData);
17946   double minDistSqr = std::numeric_limits<double>::max();
17947   for (int i=0; i<lineData->size()-1; ++i)
17948   {
17949     double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
17950     if (currentDistSqr < minDistSqr)
17951       minDistSqr = currentDistSqr;
17952   }
17953   delete lineData;
17954   return qSqrt(minDistSqr);
17955 }
17956
17957 /* inherits documentation from base class */
17958 QCPRange QCPCurve::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
17959 {
17960   QCPRange range;
17961   bool haveLower = false;
17962   bool haveUpper = false;
17963
17964   double current;
17965
17966   QCPCurveDataMap::const_iterator it = mData->constBegin();
17967   while (it != mData->constEnd())
17968   {
17969     current = it.value().key;
17970     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
17971     {
17972       if (current < range.lower || !haveLower)
17973       {
17974         range.lower = current;
17975         haveLower = true;
17976       }
17977       if (current > range.upper || !haveUpper)
17978       {
17979         range.upper = current;
17980         haveUpper = true;
17981       }
17982     }
17983     ++it;
17984   }
17985
17986   foundRange = haveLower && haveUpper;
17987   return range;
17988 }
17989
17990 /* inherits documentation from base class */
17991 QCPRange QCPCurve::getValueRange(bool &foundRange, SignDomain inSignDomain) const
17992 {
17993   QCPRange range;
17994   bool haveLower = false;
17995   bool haveUpper = false;
17996
17997   double current;
17998
17999   QCPCurveDataMap::const_iterator it = mData->constBegin();
18000   while (it != mData->constEnd())
18001   {
18002     current = it.value().value;
18003     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
18004     {
18005       if (current < range.lower || !haveLower)
18006       {
18007         range.lower = current;
18008         haveLower = true;
18009       }
18010       if (current > range.upper || !haveUpper)
18011       {
18012         range.upper = current;
18013         haveUpper = true;
18014       }
18015     }
18016     ++it;
18017   }
18018
18019   foundRange = haveLower && haveUpper;
18020   return range;
18021 }
18022
18023
18024 ////////////////////////////////////////////////////////////////////////////////////////////////////
18025 //////////////////// QCPBarsGroup
18026 ////////////////////////////////////////////////////////////////////////////////////////////////////
18027
18028 /*! \class QCPBarsGroup
18029   \brief Groups multiple QCPBars together so they appear side by side
18030
18031   \image html QCPBarsGroup.png
18032
18033   When showing multiple QCPBars in one plot which have bars at identical keys, it may be desirable
18034   to have them appearing next to each other at each key. This is what adding the respective QCPBars
18035   plottables to a QCPBarsGroup achieves. (An alternative approach is to stack them on top of each
18036   other, see \ref QCPBars::moveAbove.)
18037
18038   \section qcpbarsgroup-usage Usage
18039
18040   To add a QCPBars plottable to the group, create a new group and then add the respective bars
18041   intances:
18042   \code
18043     QCPBarsGroup *group = new QCPBarsGroup(customPlot);
18044     group->append(bars1);
18045     group->append(bars2);
18046   \endcode
18047   Alternatively to appending to the group like shown above, you can also set the group on the
18048   QCPBars plottable via \ref QCPBars::setBarsGroup.
18049
18050   The spacing between the bars can be configured via \ref setSpacingType and \ref setSpacing. The
18051   bars in this group appear in the plot in the order they were appended. To insert a bars plottable
18052   at a certain index position, or to reposition a bars plottable which is already in the group, use
18053   \ref insert.
18054
18055   To remove specific bars from the group, use either \ref remove or call \ref
18056   QCPBars::setBarsGroup "QCPBars::setBarsGroup(0)" on the respective bars plottable.
18057
18058   To clear the entire group, call \ref clear, or simply delete the group.
18059 */
18060
18061 /* start of documentation of inline functions */
18062
18063 /*! \fn QList<QCPBars*> QCPBarsGroup::bars() const
18064
18065   Returns all bars currently in this group.
18066
18067   \see bars(int index)
18068 */
18069
18070 /*! \fn int QCPBarsGroup::size() const
18071
18072   Returns the number of QCPBars plottables that are part of this group.
18073
18074 */
18075
18076 /*! \fn bool QCPBarsGroup::isEmpty() const
18077
18078   Returns whether this bars group is empty.
18079
18080   \see size
18081 */
18082
18083 /*! \fn bool QCPBarsGroup::contains(QCPBars *bars)
18084
18085   Returns whether the specified \a bars plottable is part of this group.
18086
18087 */
18088
18089 /* end of documentation of inline functions */
18090
18091 /*!
18092   Constructs a new bars group for the specified QCustomPlot instance.
18093 */
18094 QCPBarsGroup::QCPBarsGroup(QCustomPlot *parentPlot) :
18095   QObject(parentPlot),
18096   mParentPlot(parentPlot),
18097   mSpacingType(stAbsolute),
18098   mSpacing(4)
18099 {
18100 }
18101
18102 QCPBarsGroup::~QCPBarsGroup()
18103 {
18104   clear();
18105 }
18106
18107 /*!
18108   Sets how the spacing between adjacent bars is interpreted. See \ref SpacingType.
18109
18110   The actual spacing can then be specified with \ref setSpacing.
18111
18112   \see setSpacing
18113 */
18114 void QCPBarsGroup::setSpacingType(SpacingType spacingType)
18115 {
18116   mSpacingType = spacingType;
18117 }
18118
18119 /*!
18120   Sets the spacing between adjacent bars. What the number passed as \a spacing actually means, is
18121   defined by the current \ref SpacingType, which can be set with \ref setSpacingType.
18122
18123   \see setSpacingType
18124 */
18125 void QCPBarsGroup::setSpacing(double spacing)
18126 {
18127   mSpacing = spacing;
18128 }
18129
18130 /*!
18131   Returns the QCPBars instance with the specified \a index in this group. If no such QCPBars
18132   exists, returns 0.
18133
18134   \see bars(), size
18135 */
18136 QCPBars *QCPBarsGroup::bars(int index) const
18137 {
18138   if (index >= 0 && index < mBars.size())
18139   {
18140     return mBars.at(index);
18141   } else
18142   {
18143     qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
18144     return 0;
18145   }
18146 }
18147
18148 /*!
18149   Removes all QCPBars plottables from this group.
18150
18151   \see isEmpty
18152 */
18153 void QCPBarsGroup::clear()
18154 {
18155   foreach (QCPBars *bars, mBars) // since foreach takes a copy, removing bars in the loop is okay
18156     bars->setBarsGroup(0); // removes itself via removeBars
18157 }
18158
18159 /*!
18160   Adds the specified \a bars plottable to this group. Alternatively, you can also use \ref
18161   QCPBars::setBarsGroup on the \a bars instance.
18162
18163   \see insert, remove
18164 */
18165 void QCPBarsGroup::append(QCPBars *bars)
18166 {
18167   if (!bars)
18168   {
18169     qDebug() << Q_FUNC_INFO << "bars is 0";
18170     return;
18171   }
18172
18173   if (!mBars.contains(bars))
18174     bars->setBarsGroup(this);
18175   else
18176     qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast<quintptr>(bars);
18177 }
18178
18179 /*!
18180   Inserts the specified \a bars plottable into this group at the specified index position \a i.
18181   This gives you full control over the ordering of the bars.
18182
18183   \a bars may already be part of this group. In that case, \a bars is just moved to the new index
18184   position.
18185
18186   \see append, remove
18187 */
18188 void QCPBarsGroup::insert(int i, QCPBars *bars)
18189 {
18190   if (!bars)
18191   {
18192     qDebug() << Q_FUNC_INFO << "bars is 0";
18193     return;
18194   }
18195
18196   // first append to bars list normally:
18197   if (!mBars.contains(bars))
18198     bars->setBarsGroup(this);
18199   // then move to according position:
18200   mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1));
18201 }
18202
18203 /*!
18204   Removes the specified \a bars plottable from this group.
18205
18206   \see contains, clear
18207 */
18208 void QCPBarsGroup::remove(QCPBars *bars)
18209 {
18210   if (!bars)
18211   {
18212     qDebug() << Q_FUNC_INFO << "bars is 0";
18213     return;
18214   }
18215
18216   if (mBars.contains(bars))
18217     bars->setBarsGroup(0);
18218   else
18219     qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast<quintptr>(bars);
18220 }
18221
18222 /*! \internal
18223
18224   Adds the specified \a bars to the internal mBars list of bars. This method does not change the
18225   barsGroup property on \a bars.
18226
18227   \see unregisterBars
18228 */
18229 void QCPBarsGroup::registerBars(QCPBars *bars)
18230 {
18231   if (!mBars.contains(bars))
18232     mBars.append(bars);
18233 }
18234
18235 /*! \internal
18236
18237   Removes the specified \a bars from the internal mBars list of bars. This method does not change
18238   the barsGroup property on \a bars.
18239
18240   \see registerBars
18241 */
18242 void QCPBarsGroup::unregisterBars(QCPBars *bars)
18243 {
18244   mBars.removeOne(bars);
18245 }
18246
18247 /*! \internal
18248
18249   Returns the pixel offset in the key dimension the specified \a bars plottable should have at the
18250   given key coordinate \a keyCoord. The offset is relative to the pixel position of the key
18251   coordinate \a keyCoord.
18252 */
18253 double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord)
18254 {
18255   // find list of all base bars in case some mBars are stacked:
18256   QList<const QCPBars*> baseBars;
18257   foreach (const QCPBars *b, mBars)
18258   {
18259     while (b->barBelow())
18260       b = b->barBelow();
18261     if (!baseBars.contains(b))
18262       baseBars.append(b);
18263   }
18264   // find base bar this "bars" is stacked on:
18265   const QCPBars *thisBase = bars;
18266   while (thisBase->barBelow())
18267     thisBase = thisBase->barBelow();
18268
18269   // determine key pixel offset of this base bars considering all other base bars in this barsgroup:
18270   double result = 0;
18271   int index = baseBars.indexOf(thisBase);
18272   if (index >= 0)
18273   {
18274     int startIndex;
18275     double lowerPixelWidth, upperPixelWidth;
18276     if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose)
18277     {
18278       return result;
18279     } else if (index < (baseBars.size()-1)/2.0) // bar is to the left of center
18280     {
18281       if (baseBars.size() % 2 == 0) // even number of bars
18282       {
18283         startIndex = baseBars.size()/2-1;
18284         result -= getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
18285       } else // uneven number of bars
18286       {
18287         startIndex = (baseBars.size()-1)/2-1;
18288         baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18289         result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
18290         result -= getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
18291       }
18292       for (int i=startIndex; i>index; --i) // add widths and spacings of bars in between center and our bars
18293       {
18294         baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18295         result -= qAbs(upperPixelWidth-lowerPixelWidth);
18296         result -= getPixelSpacing(baseBars.at(i), keyCoord);
18297       }
18298       // finally half of our bars width:
18299       baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18300       result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18301     } else // bar is to the right of center
18302     {
18303       if (baseBars.size() % 2 == 0) // even number of bars
18304       {
18305         startIndex = baseBars.size()/2;
18306         result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
18307       } else // uneven number of bars
18308       {
18309         startIndex = (baseBars.size()-1)/2+1;
18310         baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18311         result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
18312         result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
18313       }
18314       for (int i=startIndex; i<index; ++i) // add widths and spacings of bars in between center and our bars
18315       {
18316         baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18317         result += qAbs(upperPixelWidth-lowerPixelWidth);
18318         result += getPixelSpacing(baseBars.at(i), keyCoord);
18319       }
18320       // finally half of our bars width:
18321       baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18322       result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18323     }
18324   }
18325   return result;
18326 }
18327
18328 /*! \internal
18329
18330   Returns the spacing in pixels which is between this \a bars and the following one, both at the
18331   key coordinate \a keyCoord.
18332
18333   \note Typically the returned value doesn't depend on \a bars or \a keyCoord. \a bars is only
18334   needed to get acces to the key axis transformation and axis rect for the modes \ref
18335   stAxisRectRatio and \ref stPlotCoords. The \a keyCoord is only relevant for spacings given in
18336   \ref stPlotCoords on a logarithmic axis.
18337 */
18338 double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord)
18339 {
18340   switch (mSpacingType)
18341   {
18342     case stAbsolute:
18343     {
18344       return mSpacing;
18345     }
18346     case stAxisRectRatio:
18347     {
18348       if (bars->keyAxis()->orientation() == Qt::Horizontal)
18349         return bars->keyAxis()->axisRect()->width()*mSpacing;
18350       else
18351         return bars->keyAxis()->axisRect()->height()*mSpacing;
18352     }
18353     case stPlotCoords:
18354     {
18355       double keyPixel = bars->keyAxis()->coordToPixel(keyCoord);
18356       return bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel;
18357     }
18358   }
18359   return 0;
18360 }
18361
18362
18363 ////////////////////////////////////////////////////////////////////////////////////////////////////
18364 //////////////////// QCPBarData
18365 ////////////////////////////////////////////////////////////////////////////////////////////////////
18366
18367 /*! \class QCPBarData
18368   \brief Holds the data of one single data point (one bar) for QCPBars.
18369
18370   The container for storing multiple data points is \ref QCPBarDataMap.
18371
18372   The stored data is:
18373   \li \a key: coordinate on the key axis of this bar
18374   \li \a value: height coordinate on the value axis of this bar
18375
18376   \see QCPBarDataaMap
18377 */
18378
18379 /*!
18380   Constructs a bar data point with key and value set to zero.
18381 */
18382 QCPBarData::QCPBarData() :
18383   key(0),
18384   value(0)
18385 {
18386 }
18387
18388 /*!
18389   Constructs a bar data point with the specified \a key and \a value.
18390 */
18391 QCPBarData::QCPBarData(double key, double value) :
18392   key(key),
18393   value(value)
18394 {
18395 }
18396
18397
18398 ////////////////////////////////////////////////////////////////////////////////////////////////////
18399 //////////////////// QCPBars
18400 ////////////////////////////////////////////////////////////////////////////////////////////////////
18401
18402 /*! \class QCPBars
18403   \brief A plottable representing a bar chart in a plot.
18404
18405   \image html QCPBars.png
18406
18407   To plot data, assign it with the \ref setData or \ref addData functions.
18408
18409   \section appearance Changing the appearance
18410
18411   The appearance of the bars is determined by the pen and the brush (\ref setPen, \ref setBrush).
18412   The width of the individual bars can be controlled with \ref setWidthType and \ref setWidth.
18413
18414   Bar charts are stackable. This means, two QCPBars plottables can be placed on top of each other
18415   (see \ref QCPBars::moveAbove). So when two bars are at the same key position, they will appear
18416   stacked.
18417
18418   If you would like to group multiple QCPBars plottables together so they appear side by side as
18419   shown below, use QCPBarsGroup.
18420
18421   \image html QCPBarsGroup.png
18422
18423   \section usage Usage
18424
18425   Like all data representing objects in QCustomPlot, the QCPBars is a plottable
18426   (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies
18427   (QCustomPlot::plottable, QCustomPlot::addPlottable, QCustomPlot::removePlottable, etc.)
18428
18429   Usually, you first create an instance:
18430   \code
18431   QCPBars *newBars = new QCPBars(customPlot->xAxis, customPlot->yAxis);\endcode
18432   add it to the customPlot with QCustomPlot::addPlottable:
18433   \code
18434   customPlot->addPlottable(newBars);\endcode
18435   and then modify the properties of the newly created plottable, e.g.:
18436   \code
18437   newBars->setName("Country population");
18438   newBars->setData(xData, yData);\endcode
18439 */
18440
18441 /* start of documentation of inline functions */
18442
18443 /*! \fn QCPBars *QCPBars::barBelow() const
18444   Returns the bars plottable that is directly below this bars plottable.
18445   If there is no such plottable, returns 0.
18446
18447   \see barAbove, moveBelow, moveAbove
18448 */
18449
18450 /*! \fn QCPBars *QCPBars::barAbove() const
18451   Returns the bars plottable that is directly above this bars plottable.
18452   If there is no such plottable, returns 0.
18453
18454   \see barBelow, moveBelow, moveAbove
18455 */
18456
18457 /* end of documentation of inline functions */
18458
18459 /*!
18460   Constructs a bar chart which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value
18461   axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have
18462   the same orientation. If either of these restrictions is violated, a corresponding message is
18463   printed to the debug output (qDebug), the construction is not aborted, though.
18464
18465   The constructed QCPBars can be added to the plot with QCustomPlot::addPlottable, QCustomPlot
18466   then takes ownership of the bar chart.
18467 */
18468 QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) :
18469   QCPAbstractPlottable(keyAxis, valueAxis),
18470   mData(new QCPBarDataMap),
18471   mWidth(0.75),
18472   mWidthType(wtPlotCoords),
18473   mBarsGroup(0),
18474   mBaseValue(0)
18475 {
18476   // modify inherited properties from abstract plottable:
18477   mPen.setColor(Qt::blue);
18478   mPen.setStyle(Qt::SolidLine);
18479   mBrush.setColor(QColor(40, 50, 255, 30));
18480   mBrush.setStyle(Qt::SolidPattern);
18481   mSelectedPen = mPen;
18482   mSelectedPen.setWidthF(2.5);
18483   mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen
18484   mSelectedBrush = mBrush;
18485 }
18486
18487 QCPBars::~QCPBars()
18488 {
18489   setBarsGroup(0);
18490   if (mBarBelow || mBarAbove)
18491     connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking
18492   delete mData;
18493 }
18494
18495 /*!
18496   Sets the width of the bars.
18497
18498   How the number passed as \a width is interpreted (e.g. screen pixels, plot coordinates,...),
18499   depends on the currently set width type, see \ref setWidthType and \ref WidthType.
18500 */
18501 void QCPBars::setWidth(double width)
18502 {
18503   mWidth = width;
18504 }
18505
18506 /*!
18507   Sets how the width of the bars is defined. See the documentation of \ref WidthType for an
18508   explanation of the possible values for \a widthType.
18509
18510   The default value is \ref wtPlotCoords.
18511
18512   \see setWidth
18513 */
18514 void QCPBars::setWidthType(QCPBars::WidthType widthType)
18515 {
18516   mWidthType = widthType;
18517 }
18518
18519 /*!
18520   Sets to which QCPBarsGroup this QCPBars instance belongs to. Alternatively, you can also use \ref
18521   QCPBarsGroup::append.
18522
18523   To remove this QCPBars from any group, set \a barsGroup to 0.
18524 */
18525 void QCPBars::setBarsGroup(QCPBarsGroup *barsGroup)
18526 {
18527   // deregister at old group:
18528   if (mBarsGroup)
18529     mBarsGroup->unregisterBars(this);
18530   mBarsGroup = barsGroup;
18531   // register at new group:
18532   if (mBarsGroup)
18533     mBarsGroup->registerBars(this);
18534 }
18535
18536 /*!
18537   Sets the base value of this bars plottable.
18538
18539   The base value defines where on the value coordinate the bars start. How far the bars extend from
18540   the base value is given by their individual value data. For example, if the base value is set to
18541   1, a bar with data value 2 will have its lowest point at value coordinate 1 and highest point at
18542   3.
18543
18544   For stacked bars, only the base value of the bottom-most QCPBars has meaning.
18545
18546   The default base value is 0.
18547 */
18548 void QCPBars::setBaseValue(double baseValue)
18549 {
18550   mBaseValue = baseValue;
18551 }
18552
18553 /*!
18554   Replaces the current data with the provided \a data.
18555
18556   If \a copy is set to true, data points in \a data will only be copied. if false, the plottable
18557   takes ownership of the passed data and replaces the internal data pointer with it. This is
18558   significantly faster than copying for large datasets.
18559 */
18560 void QCPBars::setData(QCPBarDataMap *data, bool copy)
18561 {
18562   if (mData == data)
18563   {
18564     qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
18565     return;
18566   }
18567   if (copy)
18568   {
18569     *mData = *data;
18570   } else
18571   {
18572     delete mData;
18573     mData = data;
18574   }
18575 }
18576
18577 /*! \overload
18578
18579   Replaces the current data with the provided points in \a key and \a value tuples. The
18580   provided vectors should have equal length. Else, the number of added points will be the size of
18581   the smallest vector.
18582 */
18583 void QCPBars::setData(const QVector<double> &key, const QVector<double> &value)
18584 {
18585   mData->clear();
18586   int n = key.size();
18587   n = qMin(n, value.size());
18588   QCPBarData newData;
18589   for (int i=0; i<n; ++i)
18590   {
18591     newData.key = key[i];
18592     newData.value = value[i];
18593     mData->insertMulti(newData.key, newData);
18594   }
18595 }
18596
18597 /*!
18598   Moves this bars plottable below \a bars. In other words, the bars of this plottable will appear
18599   below the bars of \a bars. The move target \a bars must use the same key and value axis as this
18600   plottable.
18601
18602   Inserting into and removing from existing bar stacking is handled gracefully. If \a bars already
18603   has a bars object below itself, this bars object is inserted between the two. If this bars object
18604   is already between two other bars, the two other bars will be stacked on top of each other after
18605   the operation.
18606
18607   To remove this bars plottable from any stacking, set \a bars to 0.
18608
18609   \see moveBelow, barAbove, barBelow
18610 */
18611 void QCPBars::moveBelow(QCPBars *bars)
18612 {
18613   if (bars == this) return;
18614   if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
18615   {
18616     qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
18617     return;
18618   }
18619   // remove from stacking:
18620   connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
18621   // if new bar given, insert this bar below it:
18622   if (bars)
18623   {
18624     if (bars->mBarBelow)
18625       connectBars(bars->mBarBelow.data(), this);
18626     connectBars(this, bars);
18627   }
18628 }
18629
18630 /*!
18631   Moves this bars plottable above \a bars. In other words, the bars of this plottable will appear
18632   above the bars of \a bars. The move target \a bars must use the same key and value axis as this
18633   plottable.
18634
18635   Inserting into and removing from existing bar stacking is handled gracefully. If \a bars already
18636   has a bars object below itself, this bars object is inserted between the two. If this bars object
18637   is already between two other bars, the two other bars will be stacked on top of each other after
18638   the operation.
18639
18640   To remove this bars plottable from any stacking, set \a bars to 0.
18641
18642   \see moveBelow, barBelow, barAbove
18643 */
18644 void QCPBars::moveAbove(QCPBars *bars)
18645 {
18646   if (bars == this) return;
18647   if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
18648   {
18649     qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
18650     return;
18651   }
18652   // remove from stacking:
18653   connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
18654   // if new bar given, insert this bar above it:
18655   if (bars)
18656   {
18657     if (bars->mBarAbove)
18658       connectBars(this, bars->mBarAbove.data());
18659     connectBars(bars, this);
18660   }
18661 }
18662
18663 /*!
18664   Adds the provided data points in \a dataMap to the current data.
18665   \see removeData
18666 */
18667 void QCPBars::addData(const QCPBarDataMap &dataMap)
18668 {
18669   mData->unite(dataMap);
18670 }
18671
18672 /*! \overload
18673   Adds the provided single data point in \a data to the current data.
18674   \see removeData
18675 */
18676 void QCPBars::addData(const QCPBarData &data)
18677 {
18678   mData->insertMulti(data.key, data);
18679 }
18680
18681 /*! \overload
18682   Adds the provided single data point as \a key and \a value tuple to the current data
18683   \see removeData
18684 */
18685 void QCPBars::addData(double key, double value)
18686 {
18687   QCPBarData newData;
18688   newData.key = key;
18689   newData.value = value;
18690   mData->insertMulti(newData.key, newData);
18691 }
18692
18693 /*! \overload
18694   Adds the provided data points as \a key and \a value tuples to the current data.
18695   \see removeData
18696 */
18697 void QCPBars::addData(const QVector<double> &keys, const QVector<double> &values)
18698 {
18699   int n = keys.size();
18700   n = qMin(n, values.size());
18701   QCPBarData newData;
18702   for (int i=0; i<n; ++i)
18703   {
18704     newData.key = keys[i];
18705     newData.value = values[i];
18706     mData->insertMulti(newData.key, newData);
18707   }
18708 }
18709
18710 /*!
18711   Removes all data points with key smaller than \a key.
18712   \see addData, clearData
18713 */
18714 void QCPBars::removeDataBefore(double key)
18715 {
18716   QCPBarDataMap::iterator it = mData->begin();
18717   while (it != mData->end() && it.key() < key)
18718     it = mData->erase(it);
18719 }
18720
18721 /*!
18722   Removes all data points with key greater than \a key.
18723   \see addData, clearData
18724 */
18725 void QCPBars::removeDataAfter(double key)
18726 {
18727   if (mData->isEmpty()) return;
18728   QCPBarDataMap::iterator it = mData->upperBound(key);
18729   while (it != mData->end())
18730     it = mData->erase(it);
18731 }
18732
18733 /*!
18734   Removes all data points with key between \a fromKey and \a toKey. if \a fromKey is
18735   greater or equal to \a toKey, the function does nothing. To remove a single data point with known
18736   key, use \ref removeData(double key).
18737
18738   \see addData, clearData
18739 */
18740 void QCPBars::removeData(double fromKey, double toKey)
18741 {
18742   if (fromKey >= toKey || mData->isEmpty()) return;
18743   QCPBarDataMap::iterator it = mData->upperBound(fromKey);
18744   QCPBarDataMap::iterator itEnd = mData->upperBound(toKey);
18745   while (it != itEnd)
18746     it = mData->erase(it);
18747 }
18748
18749 /*! \overload
18750
18751   Removes a single data point at \a key. If the position is not known with absolute precision,
18752   consider using \ref removeData(double fromKey, double toKey) with a small fuzziness interval
18753   around the suspected position, depeding on the precision with which the key is known.
18754
18755   \see addData, clearData
18756 */
18757 void QCPBars::removeData(double key)
18758 {
18759   mData->remove(key);
18760 }
18761
18762 /*!
18763   Removes all data points.
18764   \see removeData, removeDataAfter, removeDataBefore
18765 */
18766 void QCPBars::clearData()
18767 {
18768   mData->clear();
18769 }
18770
18771 /* inherits documentation from base class */
18772 double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
18773 {
18774   Q_UNUSED(details)
18775   if (onlySelectable && !mSelectable)
18776     return -1;
18777   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
18778
18779   if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
18780   {
18781     QCPBarDataMap::ConstIterator it;
18782     for (it = mData->constBegin(); it != mData->constEnd(); ++it)
18783     {
18784       if (getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos))
18785         return mParentPlot->selectionTolerance()*0.99;
18786     }
18787   }
18788   return -1;
18789 }
18790
18791 /* inherits documentation from base class */
18792 void QCPBars::draw(QCPPainter *painter)
18793 {
18794   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
18795   if (mData->isEmpty()) return;
18796
18797   QCPBarDataMap::const_iterator it, lower, upperEnd;
18798   getVisibleDataBounds(lower, upperEnd);
18799   for (it = lower; it != upperEnd; ++it)
18800   {
18801     // check data validity if flag set:
18802 #ifdef QCUSTOMPLOT_CHECK_DATA
18803     if (QCP::isInvalidData(it.value().key, it.value().value))
18804       qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "of drawn range invalid." << "Plottable name:" << name();
18805 #endif
18806     QPolygonF barPolygon = getBarPolygon(it.key(), it.value().value);
18807     // draw bar fill:
18808     if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0)
18809     {
18810       applyFillAntialiasingHint(painter);
18811       painter->setPen(Qt::NoPen);
18812       painter->setBrush(mainBrush());
18813       painter->drawPolygon(barPolygon);
18814     }
18815     // draw bar line:
18816     if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
18817     {
18818       applyDefaultAntialiasingHint(painter);
18819       painter->setPen(mainPen());
18820       painter->setBrush(Qt::NoBrush);
18821       painter->drawPolyline(barPolygon);
18822     }
18823   }
18824 }
18825
18826 /* inherits documentation from base class */
18827 void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
18828 {
18829   // draw filled rect:
18830   applyDefaultAntialiasingHint(painter);
18831   painter->setBrush(mBrush);
18832   painter->setPen(mPen);
18833   QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
18834   r.moveCenter(rect.center());
18835   painter->drawRect(r);
18836 }
18837
18838 /*!  \internal
18839
18840   called by \ref draw to determine which data (key) range is visible at the current key axis range
18841   setting, so only that needs to be processed. It also takes into account the bar width.
18842
18843   \a lower returns an iterator to the lowest data point that needs to be taken into account when
18844   plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a
18845   lower may still be just outside the visible range.
18846
18847   \a upperEnd returns an iterator one higher than the highest visible data point. Same as before, \a
18848   upperEnd may also lie just outside of the visible range.
18849
18850   if the bars plottable contains no data, both \a lower and \a upperEnd point to constEnd.
18851 */
18852 void QCPBars::getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const
18853 {
18854   if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
18855   if (mData->isEmpty())
18856   {
18857     lower = mData->constEnd();
18858     upperEnd = mData->constEnd();
18859     return;
18860   }
18861
18862   // get visible data range as QMap iterators
18863   lower = mData->lowerBound(mKeyAxis.data()->range().lower);
18864   upperEnd = mData->upperBound(mKeyAxis.data()->range().upper);
18865   double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower);
18866   double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper);
18867   bool isVisible = false;
18868   // walk left from lbound to find lower bar that actually is completely outside visible pixel range:
18869   QCPBarDataMap::const_iterator it = lower;
18870   while (it != mData->constBegin())
18871   {
18872     --it;
18873     QRectF barBounds = getBarPolygon(it.value().key, it.value().value).boundingRect();
18874     if (mKeyAxis.data()->orientation() == Qt::Horizontal)
18875       isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound));
18876     else // keyaxis is vertical
18877       isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound));
18878     if (isVisible)
18879       lower = it;
18880     else
18881       break;
18882   }
18883   // walk right from ubound to find upper bar that actually is completely outside visible pixel range:
18884   it = upperEnd;
18885   while (it != mData->constEnd())
18886   {
18887     QRectF barBounds = getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect();
18888     if (mKeyAxis.data()->orientation() == Qt::Horizontal)
18889       isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound));
18890     else // keyaxis is vertical
18891       isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound));
18892     if (isVisible)
18893       upperEnd = it+1;
18894     else
18895       break;
18896     ++it;
18897   }
18898 }
18899
18900 /*! \internal
18901
18902   Returns the polygon of a single bar with \a key and \a value. The Polygon is open at the bottom
18903   and shifted according to the bar stacking (see \ref moveAbove) and base value (see \ref
18904   setBaseValue).
18905 */
18906 QPolygonF QCPBars::getBarPolygon(double key, double value) const
18907 {
18908   QCPAxis *keyAxis = mKeyAxis.data();
18909   QCPAxis *valueAxis = mValueAxis.data();
18910   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
18911
18912   QPolygonF result;
18913   double lowerPixelWidth, upperPixelWidth;
18914   getPixelWidth(key, lowerPixelWidth, upperPixelWidth);
18915   double base = getStackedBaseValue(key, value >= 0);
18916   double basePixel = valueAxis->coordToPixel(base);
18917   double valuePixel = valueAxis->coordToPixel(base+value);
18918   double keyPixel = keyAxis->coordToPixel(key);
18919   if (mBarsGroup)
18920     keyPixel += mBarsGroup->keyPixelOffset(this, key);
18921   if (keyAxis->orientation() == Qt::Horizontal)
18922   {
18923     result << QPointF(keyPixel+lowerPixelWidth, basePixel);
18924     result << QPointF(keyPixel+lowerPixelWidth, valuePixel);
18925     result << QPointF(keyPixel+upperPixelWidth, valuePixel);
18926     result << QPointF(keyPixel+upperPixelWidth, basePixel);
18927   } else
18928   {
18929     result << QPointF(basePixel, keyPixel+lowerPixelWidth);
18930     result << QPointF(valuePixel, keyPixel+lowerPixelWidth);
18931     result << QPointF(valuePixel, keyPixel+upperPixelWidth);
18932     result << QPointF(basePixel, keyPixel+upperPixelWidth);
18933   }
18934   return result;
18935 }
18936
18937 /*! \internal
18938
18939   This function is used to determine the width of the bar at coordinate \a key, according to the
18940   specified width (\ref setWidth) and width type (\ref setWidthType).
18941
18942   The output parameters \a lower and \a upper return the number of pixels the bar extends to lower
18943   and higher keys, relative to the \a key coordinate (so with a non-reversed horizontal axis, \a
18944   lower is negative and \a upper positive).
18945 */
18946 void QCPBars::getPixelWidth(double key, double &lower, double &upper) const
18947 {
18948   switch (mWidthType)
18949   {
18950     case wtAbsolute:
18951     {
18952       upper = mWidth*0.5;
18953       lower = -upper;
18954       if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical)))
18955         qSwap(lower, upper);
18956       break;
18957     }
18958     case wtAxisRectRatio:
18959     {
18960       if (mKeyAxis && mKeyAxis.data()->axisRect())
18961       {
18962         if (mKeyAxis.data()->orientation() == Qt::Horizontal)
18963           upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5;
18964         else
18965           upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5;
18966         lower = -upper;
18967         if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical)))
18968           qSwap(lower, upper);
18969       } else
18970         qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined";
18971       break;
18972     }
18973     case wtPlotCoords:
18974     {
18975       if (mKeyAxis)
18976       {
18977         double keyPixel = mKeyAxis.data()->coordToPixel(key);
18978         upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel;
18979         lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel;
18980         // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by
18981         // coordinate transform which includes range direction
18982       } else
18983         qDebug() << Q_FUNC_INFO << "No key axis defined";
18984       break;
18985     }
18986   }
18987 }
18988
18989 /*! \internal
18990
18991   This function is called to find at which value to start drawing the base of a bar at \a key, when
18992   it is stacked on top of another QCPBars (e.g. with \ref moveAbove).
18993
18994   positive and negative bars are separated per stack (positive are stacked above baseValue upwards,
18995   negative are stacked below baseValue downwards). This can be indicated with \a positive. So if the
18996   bar for which we need the base value is negative, set \a positive to false.
18997 */
18998 double QCPBars::getStackedBaseValue(double key, bool positive) const
18999 {
19000   if (mBarBelow)
19001   {
19002     double max = 0; // don't use mBaseValue here because only base value of bottom-most bar has meaning in a bar stack
19003     // find bars of mBarBelow that are approximately at key and find largest one:
19004     double epsilon = qAbs(key)*1e-6; // should be safe even when changed to use float at some point
19005     if (key == 0)
19006       epsilon = 1e-6;
19007     QCPBarDataMap::const_iterator it = mBarBelow.data()->mData->lowerBound(key-epsilon);
19008     QCPBarDataMap::const_iterator itEnd = mBarBelow.data()->mData->upperBound(key+epsilon);
19009     while (it != itEnd)
19010     {
19011       if ((positive && it.value().value > max) ||
19012           (!positive && it.value().value < max))
19013         max = it.value().value;
19014       ++it;
19015     }
19016     // recurse down the bar-stack to find the total height:
19017     return max + mBarBelow.data()->getStackedBaseValue(key, positive);
19018   } else
19019     return mBaseValue;
19020 }
19021
19022 /*! \internal
19023
19024   Connects \a below and \a above to each other via their mBarAbove/mBarBelow properties. The bar(s)
19025   currently above lower and below upper will become disconnected to lower/upper.
19026
19027   If lower is zero, upper will be disconnected at the bottom.
19028   If upper is zero, lower will be disconnected at the top.
19029 */
19030 void QCPBars::connectBars(QCPBars *lower, QCPBars *upper)
19031 {
19032   if (!lower && !upper) return;
19033
19034   if (!lower) // disconnect upper at bottom
19035   {
19036     // disconnect old bar below upper:
19037     if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
19038       upper->mBarBelow.data()->mBarAbove = 0;
19039     upper->mBarBelow = 0;
19040   } else if (!upper) // disconnect lower at top
19041   {
19042     // disconnect old bar above lower:
19043     if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
19044       lower->mBarAbove.data()->mBarBelow = 0;
19045     lower->mBarAbove = 0;
19046   } else // connect lower and upper
19047   {
19048     // disconnect old bar above lower:
19049     if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
19050       lower->mBarAbove.data()->mBarBelow = 0;
19051     // disconnect old bar below upper:
19052     if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
19053       upper->mBarBelow.data()->mBarAbove = 0;
19054     lower->mBarAbove = upper;
19055     upper->mBarBelow = lower;
19056   }
19057 }
19058
19059 /* inherits documentation from base class */
19060 QCPRange QCPBars::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
19061 {
19062   QCPRange range;
19063   bool haveLower = false;
19064   bool haveUpper = false;
19065
19066   double current;
19067   QCPBarDataMap::const_iterator it = mData->constBegin();
19068   while (it != mData->constEnd())
19069   {
19070     current = it.value().key;
19071     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
19072     {
19073       if (current < range.lower || !haveLower)
19074       {
19075         range.lower = current;
19076         haveLower = true;
19077       }
19078       if (current > range.upper || !haveUpper)
19079       {
19080         range.upper = current;
19081         haveUpper = true;
19082       }
19083     }
19084     ++it;
19085   }
19086   // determine exact range of bars by including bar width and barsgroup offset:
19087   if (haveLower && mKeyAxis)
19088   {
19089     double lowerPixelWidth, upperPixelWidth, keyPixel;
19090     getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth);
19091     keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth;
19092     if (mBarsGroup)
19093       keyPixel += mBarsGroup->keyPixelOffset(this, range.lower);
19094     range.lower = mKeyAxis.data()->pixelToCoord(keyPixel);
19095   }
19096   if (haveUpper && mKeyAxis)
19097   {
19098     double lowerPixelWidth, upperPixelWidth, keyPixel;
19099     getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth);
19100     keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth;
19101     if (mBarsGroup)
19102       keyPixel += mBarsGroup->keyPixelOffset(this, range.upper);
19103     range.upper = mKeyAxis.data()->pixelToCoord(keyPixel);
19104   }
19105   foundRange = haveLower && haveUpper;
19106   return range;
19107 }
19108
19109 /* inherits documentation from base class */
19110 QCPRange QCPBars::getValueRange(bool &foundRange, SignDomain inSignDomain) const
19111 {
19112   QCPRange range;
19113   range.lower = mBaseValue;
19114   range.upper = mBaseValue;
19115   bool haveLower = true; // set to true, because baseValue should always be visible in bar charts
19116   bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts
19117   double current;
19118
19119   QCPBarDataMap::const_iterator it = mData->constBegin();
19120   while (it != mData->constEnd())
19121   {
19122     current = it.value().value + getStackedBaseValue(it.value().key, it.value().value >= 0);
19123     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
19124     {
19125       if (current < range.lower || !haveLower)
19126       {
19127         range.lower = current;
19128         haveLower = true;
19129       }
19130       if (current > range.upper || !haveUpper)
19131       {
19132         range.upper = current;
19133         haveUpper = true;
19134       }
19135     }
19136     ++it;
19137   }
19138
19139   foundRange = true; // return true because bar charts always have the 0-line visible
19140   return range;
19141 }
19142
19143
19144 ////////////////////////////////////////////////////////////////////////////////////////////////////
19145 //////////////////// QCPStatisticalBox
19146 ////////////////////////////////////////////////////////////////////////////////////////////////////
19147
19148 /*! \class QCPStatisticalBox
19149   \brief A plottable representing a single statistical box in a plot.
19150
19151   \image html QCPStatisticalBox.png
19152
19153   To plot data, assign it with the individual parameter functions or use \ref setData to set all
19154   parameters at once. The individual functions are:
19155   \li \ref setMinimum
19156   \li \ref setLowerQuartile
19157   \li \ref setMedian
19158   \li \ref setUpperQuartile
19159   \li \ref setMaximum
19160
19161   Additionally you can define a list of outliers, drawn as scatter datapoints:
19162   \li \ref setOutliers
19163
19164   \section appearance Changing the appearance
19165
19166   The appearance of the box itself is controlled via \ref setPen and \ref setBrush. You may change
19167   the width of the box with \ref setWidth in plot coordinates (not pixels).
19168
19169   Analog functions exist for the minimum/maximum-whiskers: \ref setWhiskerPen, \ref
19170   setWhiskerBarPen, \ref setWhiskerWidth. The whisker width is the width of the bar at the top
19171   (maximum) and bottom (minimum).
19172
19173   The median indicator line has its own pen, \ref setMedianPen.
19174
19175   If the whisker backbone pen is changed, make sure to set the capStyle to Qt::FlatCap. Else, the
19176   backbone line might exceed the whisker bars by a few pixels due to the pen cap being not
19177   perfectly flat.
19178
19179   The Outlier data points are drawn as normal scatter points. Their look can be controlled with
19180   \ref setOutlierStyle
19181
19182   \section usage Usage
19183
19184   Like all data representing objects in QCustomPlot, the QCPStatisticalBox is a plottable
19185   (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies
19186   (QCustomPlot::plottable, QCustomPlot::addPlottable, QCustomPlot::removePlottable, etc.)
19187
19188   Usually, you first create an instance:
19189   \code
19190   QCPStatisticalBox *newBox = new QCPStatisticalBox(customPlot->xAxis, customPlot->yAxis);\endcode
19191   add it to the customPlot with QCustomPlot::addPlottable:
19192   \code
19193   customPlot->addPlottable(newBox);\endcode
19194   and then modify the properties of the newly created plottable, e.g.:
19195   \code
19196   newBox->setName("Measurement Series 1");
19197   newBox->setData(1, 3, 4, 5, 7);
19198   newBox->setOutliers(QVector<double>() << 0.5 << 0.64 << 7.2 << 7.42);\endcode
19199 */
19200
19201 /*!
19202   Constructs a statistical box which uses \a keyAxis as its key axis ("x") and \a valueAxis as its
19203   value axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and
19204   not have the same orientation. If either of these restrictions is violated, a corresponding
19205   message is printed to the debug output (qDebug), the construction is not aborted, though.
19206
19207   The constructed statistical box can be added to the plot with QCustomPlot::addPlottable,
19208   QCustomPlot then takes ownership of the statistical box.
19209 */
19210 QCPStatisticalBox::QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis) :
19211   QCPAbstractPlottable(keyAxis, valueAxis),
19212   mKey(0),
19213   mMinimum(0),
19214   mLowerQuartile(0),
19215   mMedian(0),
19216   mUpperQuartile(0),
19217   mMaximum(0)
19218 {
19219   setOutlierStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, 6));
19220   setWhiskerWidth(0.2);
19221   setWidth(0.5);
19222
19223   setPen(QPen(Qt::black));
19224   setSelectedPen(QPen(Qt::blue, 2.5));
19225   setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap));
19226   setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap));
19227   setWhiskerBarPen(QPen(Qt::black));
19228   setBrush(Qt::NoBrush);
19229   setSelectedBrush(Qt::NoBrush);
19230 }
19231
19232 /*!
19233   Sets the key coordinate of the statistical box.
19234 */
19235 void QCPStatisticalBox::setKey(double key)
19236 {
19237   mKey = key;
19238 }
19239
19240 /*!
19241   Sets the parameter "minimum" of the statistical box plot. This is the position of the lower
19242   whisker, typically the minimum measurement of the sample that's not considered an outlier.
19243
19244   \see setMaximum, setWhiskerPen, setWhiskerBarPen, setWhiskerWidth
19245 */
19246 void QCPStatisticalBox::setMinimum(double value)
19247 {
19248   mMinimum = value;
19249 }
19250
19251 /*!
19252   Sets the parameter "lower Quartile" of the statistical box plot. This is the lower end of the
19253   box. The lower and the upper quartiles are the two statistical quartiles around the median of the
19254   sample, they contain 50% of the sample data.
19255
19256   \see setUpperQuartile, setPen, setBrush, setWidth
19257 */
19258 void QCPStatisticalBox::setLowerQuartile(double value)
19259 {
19260   mLowerQuartile = value;
19261 }
19262
19263 /*!
19264   Sets the parameter "median" of the statistical box plot. This is the value of the median mark
19265   inside the quartile box. The median separates the sample data in half (50% of the sample data is
19266   below/above the median).
19267
19268   \see setMedianPen
19269 */
19270 void QCPStatisticalBox::setMedian(double value)
19271 {
19272   mMedian = value;
19273 }
19274
19275 /*!
19276   Sets the parameter "upper Quartile" of the statistical box plot. This is the upper end of the
19277   box. The lower and the upper quartiles are the two statistical quartiles around the median of the
19278   sample, they contain 50% of the sample data.
19279
19280   \see setLowerQuartile, setPen, setBrush, setWidth
19281 */
19282 void QCPStatisticalBox::setUpperQuartile(double value)
19283 {
19284   mUpperQuartile = value;
19285 }
19286
19287 /*!
19288   Sets the parameter "maximum" of the statistical box plot. This is the position of the upper
19289   whisker, typically the maximum measurement of the sample that's not considered an outlier.
19290
19291   \see setMinimum, setWhiskerPen, setWhiskerBarPen, setWhiskerWidth
19292 */
19293 void QCPStatisticalBox::setMaximum(double value)
19294 {
19295   mMaximum = value;
19296 }
19297
19298 /*!
19299   Sets a vector of outlier values that will be drawn as scatters. Any data points in the sample
19300   that are not within the whiskers (\ref setMinimum, \ref setMaximum) should be considered outliers
19301   and displayed as such.
19302
19303   \see setOutlierStyle
19304 */
19305 void QCPStatisticalBox::setOutliers(const QVector<double> &values)
19306 {
19307   mOutliers = values;
19308 }
19309
19310 /*!
19311   Sets all parameters of the statistical box plot at once.
19312
19313   \see setKey, setMinimum, setLowerQuartile, setMedian, setUpperQuartile, setMaximum
19314 */
19315 void QCPStatisticalBox::setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum)
19316 {
19317   setKey(key);
19318   setMinimum(minimum);
19319   setLowerQuartile(lowerQuartile);
19320   setMedian(median);
19321   setUpperQuartile(upperQuartile);
19322   setMaximum(maximum);
19323 }
19324
19325 /*!
19326   Sets the width of the box in key coordinates.
19327
19328   \see setWhiskerWidth
19329 */
19330 void QCPStatisticalBox::setWidth(double width)
19331 {
19332   mWidth = width;
19333 }
19334
19335 /*!
19336   Sets the width of the whiskers (\ref setMinimum, \ref setMaximum) in key coordinates.
19337
19338   \see setWidth
19339 */
19340 void QCPStatisticalBox::setWhiskerWidth(double width)
19341 {
19342   mWhiskerWidth = width;
19343 }
19344
19345 /*!
19346   Sets the pen used for drawing the whisker backbone (That's the line parallel to the value axis).
19347
19348   Make sure to set the \a pen capStyle to Qt::FlatCap to prevent the whisker backbone from reaching
19349   a few pixels past the whisker bars, when using a non-zero pen width.
19350
19351   \see setWhiskerBarPen
19352 */
19353 void QCPStatisticalBox::setWhiskerPen(const QPen &pen)
19354 {
19355   mWhiskerPen = pen;
19356 }
19357
19358 /*!
19359   Sets the pen used for drawing the whisker bars (Those are the lines parallel to the key axis at
19360   each end of the whisker backbone).
19361
19362   \see setWhiskerPen
19363 */
19364 void QCPStatisticalBox::setWhiskerBarPen(const QPen &pen)
19365 {
19366   mWhiskerBarPen = pen;
19367 }
19368
19369 /*!
19370   Sets the pen used for drawing the median indicator line inside the statistical box.
19371 */
19372 void QCPStatisticalBox::setMedianPen(const QPen &pen)
19373 {
19374   mMedianPen = pen;
19375 }
19376
19377 /*!
19378   Sets the appearance of the outlier data points.
19379
19380   \see setOutliers
19381 */
19382 void QCPStatisticalBox::setOutlierStyle(const QCPScatterStyle &style)
19383 {
19384   mOutlierStyle = style;
19385 }
19386
19387 /* inherits documentation from base class */
19388 void QCPStatisticalBox::clearData()
19389 {
19390   setOutliers(QVector<double>());
19391   setKey(0);
19392   setMinimum(0);
19393   setLowerQuartile(0);
19394   setMedian(0);
19395   setUpperQuartile(0);
19396   setMaximum(0);
19397 }
19398
19399 /* inherits documentation from base class */
19400 double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
19401 {
19402   Q_UNUSED(details)
19403   if (onlySelectable && !mSelectable)
19404     return -1;
19405   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
19406
19407   if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
19408   {
19409     double posKey, posValue;
19410     pixelsToCoords(pos, posKey, posValue);
19411     // quartile box:
19412     QCPRange keyRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19413     QCPRange valueRange(mLowerQuartile, mUpperQuartile);
19414     if (keyRange.contains(posKey) && valueRange.contains(posValue))
19415       return mParentPlot->selectionTolerance()*0.99;
19416
19417     // min/max whiskers:
19418     if (QCPRange(mMinimum, mMaximum).contains(posValue))
19419       return qAbs(mKeyAxis.data()->coordToPixel(mKey)-mKeyAxis.data()->coordToPixel(posKey));
19420   }
19421   return -1;
19422 }
19423
19424 /* inherits documentation from base class */
19425 void QCPStatisticalBox::draw(QCPPainter *painter)
19426 {
19427   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
19428
19429   // check data validity if flag set:
19430 #ifdef QCUSTOMPLOT_CHECK_DATA
19431   if (QCP::isInvalidData(mKey, mMedian) ||
19432       QCP::isInvalidData(mLowerQuartile, mUpperQuartile) ||
19433       QCP::isInvalidData(mMinimum, mMaximum))
19434     qDebug() << Q_FUNC_INFO << "Data point at" << mKey << "of drawn range has invalid data." << "Plottable name:" << name();
19435   for (int i=0; i<mOutliers.size(); ++i)
19436     if (QCP::isInvalidData(mOutliers.at(i)))
19437       qDebug() << Q_FUNC_INFO << "Data point outlier at" << mKey << "of drawn range invalid." << "Plottable name:" << name();
19438 #endif
19439
19440   QRectF quartileBox;
19441   drawQuartileBox(painter, &quartileBox);
19442
19443   painter->save();
19444   painter->setClipRect(quartileBox, Qt::IntersectClip);
19445   drawMedian(painter);
19446   painter->restore();
19447
19448   drawWhiskers(painter);
19449   drawOutliers(painter);
19450 }
19451
19452 /* inherits documentation from base class */
19453 void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
19454 {
19455   // draw filled rect:
19456   applyDefaultAntialiasingHint(painter);
19457   painter->setPen(mPen);
19458   painter->setBrush(mBrush);
19459   QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
19460   r.moveCenter(rect.center());
19461   painter->drawRect(r);
19462 }
19463
19464 /*! \internal
19465
19466   Draws the quartile box. \a box is an output parameter that returns the quartile box (in pixel
19467   coordinates) which is used to set the clip rect of the painter before calling \ref drawMedian (so
19468   the median doesn't draw outside the quartile box).
19469 */
19470 void QCPStatisticalBox::drawQuartileBox(QCPPainter *painter, QRectF *quartileBox) const
19471 {
19472   QRectF box;
19473   box.setTopLeft(coordsToPixels(mKey-mWidth*0.5, mUpperQuartile));
19474   box.setBottomRight(coordsToPixels(mKey+mWidth*0.5, mLowerQuartile));
19475   applyDefaultAntialiasingHint(painter);
19476   painter->setPen(mainPen());
19477   painter->setBrush(mainBrush());
19478   painter->drawRect(box);
19479   if (quartileBox)
19480     *quartileBox = box;
19481 }
19482
19483 /*! \internal
19484
19485   Draws the median line inside the quartile box.
19486 */
19487 void QCPStatisticalBox::drawMedian(QCPPainter *painter) const
19488 {
19489   QLineF medianLine;
19490   medianLine.setP1(coordsToPixels(mKey-mWidth*0.5, mMedian));
19491   medianLine.setP2(coordsToPixels(mKey+mWidth*0.5, mMedian));
19492   applyDefaultAntialiasingHint(painter);
19493   painter->setPen(mMedianPen);
19494   painter->drawLine(medianLine);
19495 }
19496
19497 /*! \internal
19498
19499   Draws both whisker backbones and bars.
19500 */
19501 void QCPStatisticalBox::drawWhiskers(QCPPainter *painter) const
19502 {
19503   QLineF backboneMin, backboneMax, barMin, barMax;
19504   backboneMax.setPoints(coordsToPixels(mKey, mUpperQuartile), coordsToPixels(mKey, mMaximum));
19505   backboneMin.setPoints(coordsToPixels(mKey, mLowerQuartile), coordsToPixels(mKey, mMinimum));
19506   barMax.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMaximum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMaximum));
19507   barMin.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMinimum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMinimum));
19508   applyErrorBarsAntialiasingHint(painter);
19509   painter->setPen(mWhiskerPen);
19510   painter->drawLine(backboneMin);
19511   painter->drawLine(backboneMax);
19512   painter->setPen(mWhiskerBarPen);
19513   painter->drawLine(barMin);
19514   painter->drawLine(barMax);
19515 }
19516
19517 /*! \internal
19518
19519   Draws the outlier scatter points.
19520 */
19521 void QCPStatisticalBox::drawOutliers(QCPPainter *painter) const
19522 {
19523   applyScattersAntialiasingHint(painter);
19524   mOutlierStyle.applyTo(painter, mPen);
19525   for (int i=0; i<mOutliers.size(); ++i)
19526     mOutlierStyle.drawShape(painter, coordsToPixels(mKey, mOutliers.at(i)));
19527 }
19528
19529 /* inherits documentation from base class */
19530 QCPRange QCPStatisticalBox::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
19531 {
19532   foundRange = true;
19533   if (inSignDomain == sdBoth)
19534   {
19535     return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19536   } else if (inSignDomain == sdNegative)
19537   {
19538     if (mKey+mWidth*0.5 < 0)
19539       return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19540     else if (mKey < 0)
19541       return QCPRange(mKey-mWidth*0.5, mKey);
19542     else
19543     {
19544       foundRange = false;
19545       return QCPRange();
19546     }
19547   } else if (inSignDomain == sdPositive)
19548   {
19549     if (mKey-mWidth*0.5 > 0)
19550       return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19551     else if (mKey > 0)
19552       return QCPRange(mKey, mKey+mWidth*0.5);
19553     else
19554     {
19555       foundRange = false;
19556       return QCPRange();
19557     }
19558   }
19559   foundRange = false;
19560   return QCPRange();
19561 }
19562
19563 /* inherits documentation from base class */
19564 QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, SignDomain inSignDomain) const
19565 {
19566   QVector<double> values; // values that must be considered (i.e. all outliers and the five box-parameters)
19567   values.reserve(mOutliers.size() + 5);
19568   values << mMaximum << mUpperQuartile << mMedian << mLowerQuartile << mMinimum;
19569   values << mOutliers;
19570   // go through values and find the ones in legal range:
19571   bool haveUpper = false;
19572   bool haveLower = false;
19573   double upper = 0;
19574   double lower = 0;
19575   for (int i=0; i<values.size(); ++i)
19576   {
19577     if ((inSignDomain == sdNegative && values.at(i) < 0) ||
19578         (inSignDomain == sdPositive && values.at(i) > 0) ||
19579         (inSignDomain == sdBoth))
19580     {
19581       if (values.at(i) > upper || !haveUpper)
19582       {
19583         upper = values.at(i);
19584         haveUpper = true;
19585       }
19586       if (values.at(i) < lower || !haveLower)
19587       {
19588         lower = values.at(i);
19589         haveLower = true;
19590       }
19591     }
19592   }
19593   // return the bounds if we found some sensible values:
19594   if (haveLower && haveUpper)
19595   {
19596     foundRange = true;
19597     return QCPRange(lower, upper);
19598   } else // might happen if all values are in other sign domain
19599   {
19600     foundRange = false;
19601     return QCPRange();
19602   }
19603 }
19604
19605
19606 ////////////////////////////////////////////////////////////////////////////////////////////////////
19607 //////////////////// QCPColorMapData
19608 ////////////////////////////////////////////////////////////////////////////////////////////////////
19609
19610 /*! \class QCPColorMapData
19611   \brief Holds the two-dimensional data of a QCPColorMap plottable.
19612
19613   This class is a data storage for \ref QCPColorMap. It holds a two-dimensional array, which \ref
19614   QCPColorMap then displays as a 2D image in the plot, where the array values are represented by a
19615   color, depending on the value.
19616
19617   The size of the array can be controlled via \ref setSize (or \ref setKeySize, \ref setValueSize).
19618   Which plot coordinates these cells correspond to can be configured with \ref setRange (or \ref
19619   setKeyRange, \ref setValueRange).
19620
19621   The data cells can be accessed in two ways: They can be directly addressed by an integer index
19622   with \ref setCell. This is the fastest method. Alternatively, they can be addressed by their plot
19623   coordinate with \ref setData. plot coordinate to cell index transformations and vice versa are
19624   provided by the functions \ref coordToCell and \ref cellToCoord.
19625
19626   This class also buffers the minimum and maximum values that are in the data set, to provide
19627   QCPColorMap::rescaleDataRange with the necessary information quickly. Setting a cell to a value
19628   that is greater than the current maximum increases this maximum to the new value. However,
19629   setting the cell that currently holds the maximum value to a smaller value doesn't decrease the
19630   maximum again, because finding the true new maximum would require going through the entire data
19631   array, which might be time consuming. The same holds for the data minimum. This functionality is
19632   given by \ref recalculateDataBounds, such that you can decide when it is sensible to find the
19633   true current minimum and maximum. The method QCPColorMap::rescaleDataRange offers a convenience
19634   parameter \a recalculateDataBounds which may be set to true to automatically call \ref
19635   recalculateDataBounds internally.
19636 */
19637
19638 /* start of documentation of inline functions */
19639
19640 /*! \fn bool QCPColorMapData::isEmpty() const
19641
19642   Returns whether this instance carries no data. This is equivalent to having a size where at least
19643   one of the dimensions is 0 (see \ref setSize).
19644 */
19645
19646 /* end of documentation of inline functions */
19647
19648 /*!
19649   Constructs a new QCPColorMapData instance. The instance has \a keySize cells in the key direction
19650   and \a valueSize cells in the value direction. These cells will be displayed by the \ref QCPColorMap
19651   at the coordinates \a keyRange and \a valueRange.
19652
19653   \see setSize, setKeySize, setValueSize, setRange, setKeyRange, setValueRange
19654 */
19655 QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) :
19656   mKeySize(0),
19657   mValueSize(0),
19658   mKeyRange(keyRange),
19659   mValueRange(valueRange),
19660   mIsEmpty(true),
19661   mData(0),
19662   mDataModified(true)
19663 {
19664   setSize(keySize, valueSize);
19665   fill(0);
19666 }
19667
19668 QCPColorMapData::~QCPColorMapData()
19669 {
19670   if (mData)
19671     delete[] mData;
19672 }
19673
19674 /*!
19675   Constructs a new QCPColorMapData instance copying the data and range of \a other.
19676 */
19677 QCPColorMapData::QCPColorMapData(const QCPColorMapData &other) :
19678   mKeySize(0),
19679   mValueSize(0),
19680   mIsEmpty(true),
19681   mData(0),
19682   mDataModified(true)
19683 {
19684   *this = other;
19685 }
19686
19687 /*!
19688   Overwrites this color map data instance with the data stored in \a other.
19689 */
19690 QCPColorMapData &QCPColorMapData::operator=(const QCPColorMapData &other)
19691 {
19692   if (&other != this)
19693   {
19694     const int keySize = other.keySize();
19695     const int valueSize = other.valueSize();
19696     setSize(keySize, valueSize);
19697     setRange(other.keyRange(), other.valueRange());
19698     if (!mIsEmpty)
19699       memcpy(mData, other.mData, sizeof(mData[0])*keySize*valueSize);
19700     mDataBounds = other.mDataBounds;
19701     mDataModified = true;
19702   }
19703   return *this;
19704 }
19705
19706 /* undocumented getter */
19707 double QCPColorMapData::data(double key, double value)
19708 {
19709   int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
19710   int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
19711   if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
19712     return mData[valueCell*mKeySize + keyCell];
19713   else
19714     return 0;
19715 }
19716
19717 /* undocumented getter */
19718 double QCPColorMapData::cell(int keyIndex, int valueIndex)
19719 {
19720   if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
19721     return mData[valueIndex*mKeySize + keyIndex];
19722   else
19723     return 0;
19724 }
19725
19726 /*!
19727   Resizes the data array to have \a keySize cells in the key dimension and \a valueSize cells in
19728   the value dimension.
19729
19730   The current data is discarded and the map cells are set to 0, unless the map had already the
19731   requested size.
19732
19733   Setting at least one of \a keySize or \a valueSize to zero frees the internal data array and \ref
19734   isEmpty returns true.
19735
19736   \see setRange, setKeySize, setValueSize
19737 */
19738 void QCPColorMapData::setSize(int keySize, int valueSize)
19739 {
19740   if (keySize != mKeySize || valueSize != mValueSize)
19741   {
19742     mKeySize = keySize;
19743     mValueSize = valueSize;
19744     if (mData)
19745       delete[] mData;
19746     mIsEmpty = mKeySize == 0 || mValueSize == 0;
19747     if (!mIsEmpty)
19748     {
19749 #ifdef __EXCEPTIONS
19750       try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message
19751 #endif
19752       mData = new double[mKeySize*mValueSize];
19753 #ifdef __EXCEPTIONS
19754       } catch (...) { mData = 0; }
19755 #endif
19756       if (mData)
19757         fill(0);
19758       else
19759         qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize;
19760     } else
19761       mData = 0;
19762     mDataModified = true;
19763   }
19764 }
19765
19766 /*!
19767   Resizes the data array to have \a keySize cells in the key dimension.
19768
19769   The current data is discarded and the map cells are set to 0, unless the map had already the
19770   requested size.
19771
19772   Setting \a keySize to zero frees the internal data array and \ref isEmpty returns true.
19773
19774   \see setKeyRange, setSize, setValueSize
19775 */
19776 void QCPColorMapData::setKeySize(int keySize)
19777 {
19778   setSize(keySize, mValueSize);
19779 }
19780
19781 /*!
19782   Resizes the data array to have \a valueSize cells in the value dimension.
19783
19784   The current data is discarded and the map cells are set to 0, unless the map had already the
19785   requested size.
19786
19787   Setting \a valueSize to zero frees the internal data array and \ref isEmpty returns true.
19788
19789   \see setValueRange, setSize, setKeySize
19790 */
19791 void QCPColorMapData::setValueSize(int valueSize)
19792 {
19793   setSize(mKeySize, valueSize);
19794 }
19795
19796 /*!
19797   Sets the coordinate ranges the data shall be distributed over. This defines the rectangular area
19798   covered by the color map in plot coordinates.
19799
19800   The outer cells will be centered on the range boundaries given to this function. For example, if
19801   the key size (\ref setKeySize) is 3 and \a keyRange is set to <tt>QCPRange(2, 3)</tt> there will
19802   be cells centered on the key coordinates 2, 2.5 and 3.
19803
19804   \see setSize
19805 */
19806 void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange)
19807 {
19808   setKeyRange(keyRange);
19809   setValueRange(valueRange);
19810 }
19811
19812 /*!
19813   Sets the coordinate range the data shall be distributed over in the key dimension. Together with
19814   the value range, This defines the rectangular area covered by the color map in plot coordinates.
19815
19816   The outer cells will be centered on the range boundaries given to this function. For example, if
19817   the key size (\ref setKeySize) is 3 and \a keyRange is set to <tt>QCPRange(2, 3)</tt> there will
19818   be cells centered on the key coordinates 2, 2.5 and 3.
19819
19820   \see setRange, setValueRange, setSize
19821 */
19822 void QCPColorMapData::setKeyRange(const QCPRange &keyRange)
19823 {
19824   mKeyRange = keyRange;
19825 }
19826
19827 /*!
19828   Sets the coordinate range the data shall be distributed over in the value dimension. Together with
19829   the key range, This defines the rectangular area covered by the color map in plot coordinates.
19830
19831   The outer cells will be centered on the range boundaries given to this function. For example, if
19832   the value size (\ref setValueSize) is 3 and \a valueRange is set to <tt>QCPRange(2, 3)</tt> there
19833   will be cells centered on the value coordinates 2, 2.5 and 3.
19834
19835   \see setRange, setKeyRange, setSize
19836 */
19837 void QCPColorMapData::setValueRange(const QCPRange &valueRange)
19838 {
19839   mValueRange = valueRange;
19840 }
19841
19842 /*!
19843   Sets the data of the cell, which lies at the plot coordinates given by \a key and \a value, to \a
19844   z.
19845
19846   \see setCell, setRange
19847 */
19848 void QCPColorMapData::setData(double key, double value, double z)
19849 {
19850   int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
19851   int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
19852   if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
19853   {
19854     mData[valueCell*mKeySize + keyCell] = z;
19855     if (z < mDataBounds.lower)
19856       mDataBounds.lower = z;
19857     if (z > mDataBounds.upper)
19858       mDataBounds.upper = z;
19859      mDataModified = true;
19860   }
19861 }
19862
19863 /*!
19864   Sets the data of the cell with indices \a keyIndex and \a valueIndex to \a z. The indices
19865   enumerate the cells starting from zero, up to the map's size-1 in the respective dimension (see
19866   \ref setSize).
19867
19868   In the standard plot configuration (horizontal key axis and vertical value axis, both not
19869   range-reversed), the cell with indices (0, 0) is in the bottom left corner and the cell with
19870   indices (keySize-1, valueSize-1) is in the top right corner of the color map.
19871
19872   \see setData, setSize
19873 */
19874 void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z)
19875 {
19876   if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
19877   {
19878     mData[valueIndex*mKeySize + keyIndex] = z;
19879     if (z < mDataBounds.lower)
19880       mDataBounds.lower = z;
19881     if (z > mDataBounds.upper)
19882       mDataBounds.upper = z;
19883      mDataModified = true;
19884   }
19885 }
19886
19887 /*!
19888   Goes through the data and updates the buffered minimum and maximum data values.
19889
19890   Calling this method is only advised if you are about to call \ref QCPColorMap::rescaleDataRange
19891   and can not guarantee that the cells holding the maximum or minimum data haven't been overwritten
19892   with a smaller or larger value respectively, since the buffered maximum/minimum values have been
19893   updated the last time. Why this is the case is explained in the class description (\ref
19894   QCPColorMapData).
19895
19896   Note that the method \ref QCPColorMap::rescaleDataRange provides a parameter \a
19897   recalculateDataBounds for convenience. Setting this to true will call this method for you, before
19898   doing the rescale.
19899 */
19900 void QCPColorMapData::recalculateDataBounds()
19901 {
19902   if (mKeySize > 0 && mValueSize > 0)
19903   {
19904     double minHeight = mData[0];
19905     double maxHeight = mData[0];
19906     const int dataCount = mValueSize*mKeySize;
19907     for (int i=0; i<dataCount; ++i)
19908     {
19909       if (mData[i] > maxHeight)
19910         maxHeight = mData[i];
19911       if (mData[i] < minHeight)
19912         minHeight = mData[i];
19913     }
19914     mDataBounds.lower = minHeight;
19915     mDataBounds.upper = maxHeight;
19916   }
19917 }
19918
19919 /*!
19920   Frees the internal data memory.
19921
19922   This is equivalent to calling \ref setSize "setSize(0, 0)".
19923 */
19924 void QCPColorMapData::clear()
19925 {
19926   setSize(0, 0);
19927 }
19928
19929 /*!
19930   Sets all cells to the value \a z.
19931 */
19932 void QCPColorMapData::fill(double z)
19933 {
19934   const int dataCount = mValueSize*mKeySize;
19935   for (int i=0; i<dataCount; ++i)
19936     mData[i] = z;
19937   mDataBounds = QCPRange(z, z);
19938 }
19939
19940 /*!
19941   Transforms plot coordinates given by \a key and \a value to cell indices of this QCPColorMapData
19942   instance. The resulting cell indices are returned via the output parameters \a keyIndex and \a
19943   valueIndex.
19944
19945   The retrieved key/value cell indices can then be used for example with \ref setCell.
19946
19947   If you are only interested in a key or value index, you may pass 0 as \a valueIndex or \a
19948   keyIndex.
19949
19950   \see cellToCoord, QCPAxis::coordToPixel
19951 */
19952 void QCPColorMapData::coordToCell(double key, double value, int *keyIndex, int *valueIndex) const
19953 {
19954   if (keyIndex)
19955     *keyIndex = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
19956   if (valueIndex)
19957     *valueIndex = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
19958 }
19959
19960 /*!
19961   Transforms cell indices given by \a keyIndex and \a valueIndex to cell indices of this QCPColorMapData
19962   instance. The resulting coordinates are returned via the output parameters \a key and \a
19963   value.
19964
19965   If you are only interested in a key or value coordinate, you may pass 0 as \a key or \a
19966   value.
19967
19968   \see coordToCell, QCPAxis::pixelToCoord
19969 */
19970 void QCPColorMapData::cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const
19971 {
19972   if (key)
19973     *key = keyIndex/(double)(mKeySize-1)*(mKeyRange.upper-mKeyRange.lower)+mKeyRange.lower;
19974   if (value)
19975     *value = valueIndex/(double)(mValueSize-1)*(mValueRange.upper-mValueRange.lower)+mValueRange.lower;
19976 }
19977
19978
19979 ////////////////////////////////////////////////////////////////////////////////////////////////////
19980 //////////////////// QCPColorMap
19981 ////////////////////////////////////////////////////////////////////////////////////////////////////
19982
19983 /*! \class QCPColorMap
19984   \brief A plottable representing a two-dimensional color map in a plot.
19985
19986   \image html QCPColorMap.png
19987
19988   The data is stored in the class \ref QCPColorMapData, which can be accessed via the data()
19989   method.
19990
19991   A color map has three dimensions to represent a data point: The \a key dimension, the \a value
19992   dimension and the \a data dimension. As with other plottables such as graphs, \a key and \a value
19993   correspond to two orthogonal axes on the QCustomPlot surface that you specify in the QColorMap
19994   constructor. The \a data dimension however is encoded as the color of the point at (\a key, \a
19995   value).
19996
19997   Set the number of points (or \a cells) in the key/value dimension via \ref
19998   QCPColorMapData::setSize. The plot coordinate range over which these points will be displayed is
19999   specified via \ref QCPColorMapData::setRange. The first cell will be centered on the lower range
20000   boundary and the last cell will be centered on the upper range boundary. The data can be set by
20001   either accessing the cells directly with QCPColorMapData::setCell or by addressing the cells via
20002   their plot coordinates with \ref QCPColorMapData::setData. If possible, you should prefer
20003   setCell, since it doesn't need to do any coordinate transformation and thus performs a bit
20004   better.
20005
20006   The cell with index (0, 0) is at the bottom left, if the color map uses normal (i.e. not reversed)
20007   key and value axes.
20008
20009   To show the user which colors correspond to which \a data values, a \ref QCPColorScale is
20010   typically placed to the right of the axis rect. See the documentation there for details on how to
20011   add and use a color scale.
20012
20013   \section appearance Changing the appearance
20014
20015   The central part of the appearance is the color gradient, which can be specified via \ref
20016   setGradient. See the documentation of \ref QCPColorGradient for details on configuring a color
20017   gradient.
20018
20019   The \a data range that is mapped to the colors of the gradient can be specified with \ref
20020   setDataRange. To make the data range encompass the whole data set minimum to maximum, call \ref
20021   rescaleDataRange.
20022
20023   \section usage Usage
20024
20025   Like all data representing objects in QCustomPlot, the QCPColorMap is a plottable
20026   (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies
20027   (QCustomPlot::plottable, QCustomPlot::addPlottable, QCustomPlot::removePlottable, etc.)
20028
20029   Usually, you first create an instance:
20030   \code
20031   QCPColorMap *colorMap = new QCPColorMap(customPlot->xAxis, customPlot->yAxis);\endcode
20032   add it to the customPlot with QCustomPlot::addPlottable:
20033   \code
20034   customPlot->addPlottable(colorMap);\endcode
20035   and then modify the properties of the newly created color map, e.g.:
20036   \code
20037   colorMap->data()->setSize(50, 50);
20038   colorMap->data()->setRange(QCPRange(0, 2), QCPRange(0, 2));
20039   for (int x=0; x<50; ++x)
20040     for (int y=0; y<50; ++y)
20041       colorMap->data()->setCell(x, y, qCos(x/10.0)+qSin(y/10.0));
20042   colorMap->setGradient(QCPColorGradient::gpPolar);
20043   colorMap->rescaleDataRange(true);
20044   customPlot->rescaleAxes();
20045   customPlot->replot();
20046   \endcode
20047
20048   \note The QCPColorMap always displays the data at equal key/value intervals, even if the key or
20049   value axis is set to a logarithmic scaling. If you want to use QCPColorMap with logarithmic axes,
20050   you shouldn't use the \ref QCPColorMapData::setData method as it uses a linear transformation to
20051   determine the cell index. Rather directly access the cell index with \ref
20052   QCPColorMapData::setCell.
20053 */
20054
20055 /* start documentation of inline functions */
20056
20057 /*! \fn QCPColorMapData *QCPColorMap::data() const
20058
20059   Returns a pointer to the internal data storage of type \ref QCPColorMapData. Access this to
20060   modify data points (cells) and the color map key/value range.
20061
20062   \see setData
20063 */
20064
20065 /* end documentation of inline functions */
20066
20067 /* start documentation of signals */
20068
20069 /*! \fn void QCPColorMap::dataRangeChanged(QCPRange newRange);
20070
20071   This signal is emitted when the data range changes.
20072
20073   \see setDataRange
20074 */
20075
20076 /*! \fn void QCPColorMap::dataScaleTypeChanged(QCPAxis::ScaleType scaleType);
20077
20078   This signal is emitted when the data scale type changes.
20079
20080   \see setDataScaleType
20081 */
20082
20083 /*! \fn void QCPColorMap::gradientChanged(QCPColorGradient newGradient);
20084
20085   This signal is emitted when the gradient changes.
20086
20087   \see setGradient
20088 */
20089
20090 /* end documentation of signals */
20091
20092 /*!
20093   Constructs a color map with the specified \a keyAxis and \a valueAxis.
20094
20095   The constructed QCPColorMap can be added to the plot with QCustomPlot::addPlottable, QCustomPlot
20096   then takes ownership of the color map.
20097 */
20098 QCPColorMap::QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis) :
20099   QCPAbstractPlottable(keyAxis, valueAxis),
20100   mDataScaleType(QCPAxis::stLinear),
20101   mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))),
20102   mInterpolate(true),
20103   mTightBoundary(false),
20104   mMapImageInvalidated(true)
20105 {
20106 }
20107
20108 QCPColorMap::~QCPColorMap()
20109 {
20110   delete mMapData;
20111 }
20112
20113 /*!
20114   Replaces the current \ref data with the provided \a data.
20115
20116   If \a copy is set to true, the \a data object will only be copied. if false, the color map
20117   takes ownership of the passed data and replaces the internal data pointer with it. This is
20118   significantly faster than copying for large datasets.
20119 */
20120 void QCPColorMap::setData(QCPColorMapData *data, bool copy)
20121 {
20122   if (mMapData == data)
20123   {
20124     qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
20125     return;
20126   }
20127   if (copy)
20128   {
20129     *mMapData = *data;
20130   } else
20131   {
20132     delete mMapData;
20133     mMapData = data;
20134   }
20135   mMapImageInvalidated = true;
20136 }
20137
20138 /*!
20139   Sets the data range of this color map to \a dataRange. The data range defines which data values
20140   are mapped to the color gradient.
20141
20142   To make the data range span the full range of the data set, use \ref rescaleDataRange.
20143
20144   \see QCPColorScale::setDataRange
20145 */
20146 void QCPColorMap::setDataRange(const QCPRange &dataRange)
20147 {
20148   if (!QCPRange::validRange(dataRange)) return;
20149   if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper)
20150   {
20151     if (mDataScaleType == QCPAxis::stLogarithmic)
20152       mDataRange = dataRange.sanitizedForLogScale();
20153     else
20154       mDataRange = dataRange.sanitizedForLinScale();
20155     mMapImageInvalidated = true;
20156     emit dataRangeChanged(mDataRange);
20157   }
20158 }
20159
20160 /*!
20161   Sets whether the data is correlated with the color gradient linearly or logarithmically.
20162
20163   \see QCPColorScale::setDataScaleType
20164 */
20165 void QCPColorMap::setDataScaleType(QCPAxis::ScaleType scaleType)
20166 {
20167   if (mDataScaleType != scaleType)
20168   {
20169     mDataScaleType = scaleType;
20170     mMapImageInvalidated = true;
20171     emit dataScaleTypeChanged(mDataScaleType);
20172     if (mDataScaleType == QCPAxis::stLogarithmic)
20173       setDataRange(mDataRange.sanitizedForLogScale());
20174   }
20175 }
20176
20177 /*!
20178   Sets the color gradient that is used to represent the data. For more details on how to create an
20179   own gradient or use one of the preset gradients, see \ref QCPColorGradient.
20180
20181   The colors defined by the gradient will be used to represent data values in the currently set
20182   data range, see \ref setDataRange. Data points that are outside this data range will either be
20183   colored uniformly with the respective gradient boundary color, or the gradient will repeat,
20184   depending on \ref QCPColorGradient::setPeriodic.
20185
20186   \see QCPColorScale::setGradient
20187 */
20188 void QCPColorMap::setGradient(const QCPColorGradient &gradient)
20189 {
20190   if (mGradient != gradient)
20191   {
20192     mGradient = gradient;
20193     mMapImageInvalidated = true;
20194     emit gradientChanged(mGradient);
20195   }
20196 }
20197
20198 /*!
20199   Sets whether the color map image shall use bicubic interpolation when displaying the color map
20200   shrinked or expanded, and not at a 1:1 pixel-to-data scale.
20201
20202   \image html QCPColorMap-interpolate.png "A 10*10 color map, with interpolation and without interpolation enabled"
20203 */
20204 void QCPColorMap::setInterpolate(bool enabled)
20205 {
20206   mInterpolate = enabled;
20207 }
20208
20209 /*!
20210   Sets whether the outer most data rows and columns are clipped to the specified key and value
20211   range (see \ref QCPColorMapData::setKeyRange, \ref QCPColorMapData::setValueRange).
20212
20213   if \a enabled is set to false, the data points at the border of the color map are drawn with the
20214   same width and height as all other data points. Since the data points are represented by
20215   rectangles of one color centered on the data coordinate, this means that the shown color map
20216   extends by half a data point over the specified key/value range in each direction.
20217
20218   \image html QCPColorMap-tightboundary.png "A color map, with tight boundary enabled and disabled"
20219 */
20220 void QCPColorMap::setTightBoundary(bool enabled)
20221 {
20222   mTightBoundary = enabled;
20223 }
20224
20225 /*!
20226   Associates the color scale \a colorScale with this color map.
20227
20228   This means that both the color scale and the color map synchronize their gradient, data range and
20229   data scale type (\ref setGradient, \ref setDataRange, \ref setDataScaleType). Multiple color maps
20230   can be associated with one single color scale. This causes the color maps to also synchronize
20231   those properties, via the mutual color scale.
20232
20233   This function causes the color map to adopt the current color gradient, data range and data scale
20234   type of \a colorScale. After this call, you may change these properties at either the color map
20235   or the color scale, and the setting will be applied to both.
20236
20237   Pass 0 as \a colorScale to disconnect the color scale from this color map again.
20238 */
20239 void QCPColorMap::setColorScale(QCPColorScale *colorScale)
20240 {
20241   if (mColorScale) // unconnect signals from old color scale
20242   {
20243     disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
20244     disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
20245     disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
20246     disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20247     disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
20248     disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20249   }
20250   mColorScale = colorScale;
20251   if (mColorScale) // connect signals to new color scale
20252   {
20253     setGradient(mColorScale.data()->gradient());
20254     setDataRange(mColorScale.data()->dataRange());
20255     setDataScaleType(mColorScale.data()->dataScaleType());
20256     connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
20257     connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
20258     connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
20259     connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20260     connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
20261     connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20262   }
20263 }
20264
20265 /*!
20266   Sets the data range (\ref setDataRange) to span the minimum and maximum values that occur in the
20267   current data set. This corresponds to the \ref rescaleKeyAxis or \ref rescaleValueAxis methods,
20268   only for the third data dimension of the color map.
20269
20270   The minimum and maximum values of the data set are buffered in the internal QCPColorMapData
20271   instance (\ref data). As data is updated via its \ref QCPColorMapData::setCell or \ref
20272   QCPColorMapData::setData, the buffered minimum and maximum values are updated, too. For
20273   performance reasons, however, they are only updated in an expanding fashion. So the buffered
20274   maximum can only increase and the buffered minimum can only decrease. In consequence, changes to
20275   the data that actually lower the maximum of the data set (by overwriting the cell holding the
20276   current maximum with a smaller value), aren't recognized and the buffered maximum overestimates
20277   the true maximum of the data set. The same happens for the buffered minimum. To recalculate the
20278   true minimum and maximum by explicitly looking at each cell, the method
20279   QCPColorMapData::recalculateDataBounds can be used. For convenience, setting the parameter \a
20280   recalculateDataBounds calls this method before setting the data range to the buffered minimum and
20281   maximum.
20282
20283   \see setDataRange
20284 */
20285 void QCPColorMap::rescaleDataRange(bool recalculateDataBounds)
20286 {
20287   if (recalculateDataBounds)
20288     mMapData->recalculateDataBounds();
20289   setDataRange(mMapData->dataBounds());
20290 }
20291
20292 /*!
20293   Takes the current appearance of the color map and updates the legend icon, which is used to
20294   represent this color map in the legend (see \ref QCPLegend).
20295
20296   The \a transformMode specifies whether the rescaling is done by a faster, low quality image
20297   scaling algorithm (Qt::FastTransformation) or by a slower, higher quality algorithm
20298   (Qt::SmoothTransformation).
20299
20300   The current color map appearance is scaled down to \a thumbSize. Ideally, this should be equal to
20301   the size of the legend icon (see \ref QCPLegend::setIconSize). If it isn't exactly the configured
20302   legend icon size, the thumb will be rescaled during drawing of the legend item.
20303
20304   \see setDataRange
20305 */
20306 void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize)
20307 {
20308   if (mMapImage.isNull() && !data()->isEmpty())
20309     updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet)
20310
20311   if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again
20312   {
20313     bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
20314     bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
20315     mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode);
20316   }
20317 }
20318
20319 /*!
20320   Clears the colormap data by calling \ref QCPColorMapData::clear() on the internal data. This also
20321   resizes the map to 0x0 cells.
20322 */
20323 void QCPColorMap::clearData()
20324 {
20325   mMapData->clear();
20326 }
20327
20328 /* inherits documentation from base class */
20329 double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
20330 {
20331   Q_UNUSED(details)
20332   if (onlySelectable && !mSelectable)
20333     return -1;
20334   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
20335
20336   if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20337   {
20338     double posKey, posValue;
20339     pixelsToCoords(pos, posKey, posValue);
20340     if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue))
20341       return mParentPlot->selectionTolerance()*0.99;
20342   }
20343   return -1;
20344 }
20345
20346 /*! \internal
20347
20348   Updates the internal map image buffer by going through the internal \ref QCPColorMapData and
20349   turning the data values into color pixels with \ref QCPColorGradient::colorize.
20350
20351   This method is called by \ref QCPColorMap::draw if either the data has been modified or the map image
20352   has been invalidated for a different reason (e.g. a change of the data range with \ref
20353   setDataRange).
20354 */
20355 void QCPColorMap::updateMapImage()
20356 {
20357   QCPAxis *keyAxis = mKeyAxis.data();
20358   if (!keyAxis) return;
20359
20360   // resize mMapImage to correct dimensions, according to key/value axes orientation:
20361   if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.size().width() != mMapData->keySize() || mMapImage.size().height() != mMapData->valueSize()))
20362     mMapImage = QImage(QSize(mMapData->keySize(), mMapData->valueSize()), QImage::Format_RGB32);
20363   else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.size().width() != mMapData->valueSize() || mMapImage.size().height() != mMapData->keySize()))
20364     mMapImage = QImage(QSize(mMapData->valueSize(), mMapData->keySize()), QImage::Format_RGB32);
20365
20366   const int keySize = mMapData->keySize();
20367   const int valueSize = mMapData->valueSize();
20368   const double *rawData = mMapData->mData;
20369
20370   if (keyAxis->orientation() == Qt::Horizontal)
20371   {
20372     const int lineCount = valueSize;
20373     const int rowCount = keySize;
20374     for (int line=0; line<lineCount; ++line)
20375     {
20376       QRgb* pixels = reinterpret_cast<QRgb*>(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
20377       mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic);
20378     }
20379   } else // keyAxis->orientation() == Qt::Vertical
20380   {
20381     const int lineCount = keySize;
20382     const int rowCount = valueSize;
20383     for (int line=0; line<lineCount; ++line)
20384     {
20385       QRgb* pixels = reinterpret_cast<QRgb*>(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
20386       mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic);
20387     }
20388   }
20389
20390   mMapData->mDataModified = false;
20391   mMapImageInvalidated = false;
20392 }
20393
20394 /* inherits documentation from base class */
20395 void QCPColorMap::draw(QCPPainter *painter)
20396 {
20397   if (mMapData->isEmpty()) return;
20398   if (!mKeyAxis || !mValueAxis) return;
20399   applyDefaultAntialiasingHint(painter);
20400
20401   if (mMapData->mDataModified || mMapImageInvalidated)
20402     updateMapImage();
20403
20404   double halfSampleKey = 0;
20405   double halfSampleValue = 0;
20406   if (mMapData->keySize() > 1)
20407     halfSampleKey = 0.5*mMapData->keyRange().size()/(double)(mMapData->keySize()-1);
20408   if (mMapData->valueSize() > 1)
20409     halfSampleValue = 0.5*mMapData->valueRange().size()/(double)(mMapData->valueSize()-1);
20410   QRectF imageRect(coordsToPixels(mMapData->keyRange().lower-halfSampleKey, mMapData->valueRange().lower-halfSampleValue),
20411                    coordsToPixels(mMapData->keyRange().upper+halfSampleKey, mMapData->valueRange().upper+halfSampleValue));
20412   imageRect = imageRect.normalized();
20413   bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
20414   bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
20415   bool smoothBackup = painter->renderHints().testFlag(QPainter::SmoothPixmapTransform);
20416   painter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate);
20417   QRegion clipBackup;
20418   if (mTightBoundary)
20419   {
20420     clipBackup = painter->clipRegion();
20421     painter->setClipRect(QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower),
20422                                 coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(), Qt::IntersectClip);
20423   }
20424   painter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY));
20425   if (mTightBoundary)
20426     painter->setClipRegion(clipBackup);
20427   painter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup);
20428 }
20429
20430 /* inherits documentation from base class */
20431 void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
20432 {
20433   applyDefaultAntialiasingHint(painter);
20434   // draw map thumbnail:
20435   if (!mLegendIcon.isNull())
20436   {
20437     QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
20438     QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height());
20439     iconRect.moveCenter(rect.center());
20440     painter->drawPixmap(iconRect.topLeft(), scaledIcon);
20441   }
20442   /*
20443   // draw frame:
20444   painter->setBrush(Qt::NoBrush);
20445   painter->setPen(Qt::black);
20446   painter->drawRect(rect.adjusted(1, 1, 0, 0));
20447   */
20448 }
20449
20450 /* inherits documentation from base class */
20451 QCPRange QCPColorMap::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
20452 {
20453   foundRange = true;
20454   QCPRange result = mMapData->keyRange();
20455   result.normalize();
20456   if (inSignDomain == QCPAbstractPlottable::sdPositive)
20457   {
20458     if (result.lower <= 0 && result.upper > 0)
20459       result.lower = result.upper*1e-3;
20460     else if (result.lower <= 0 && result.upper <= 0)
20461       foundRange = false;
20462   } else if (inSignDomain == QCPAbstractPlottable::sdNegative)
20463   {
20464     if (result.upper >= 0 && result.lower < 0)
20465       result.upper = result.lower*1e-3;
20466     else if (result.upper >= 0 && result.lower >= 0)
20467       foundRange = false;
20468   }
20469   return result;
20470 }
20471
20472 /* inherits documentation from base class */
20473 QCPRange QCPColorMap::getValueRange(bool &foundRange, SignDomain inSignDomain) const
20474 {
20475   foundRange = true;
20476   QCPRange result = mMapData->valueRange();
20477   result.normalize();
20478   if (inSignDomain == QCPAbstractPlottable::sdPositive)
20479   {
20480     if (result.lower <= 0 && result.upper > 0)
20481       result.lower = result.upper*1e-3;
20482     else if (result.lower <= 0 && result.upper <= 0)
20483       foundRange = false;
20484   } else if (inSignDomain == QCPAbstractPlottable::sdNegative)
20485   {
20486     if (result.upper >= 0 && result.lower < 0)
20487       result.upper = result.lower*1e-3;
20488     else if (result.upper >= 0 && result.lower >= 0)
20489       foundRange = false;
20490   }
20491   return result;
20492 }
20493
20494
20495 ////////////////////////////////////////////////////////////////////////////////////////////////////
20496 //////////////////// QCPFinancialData
20497 ////////////////////////////////////////////////////////////////////////////////////////////////////
20498
20499 /*! \class QCPFinancialData
20500   \brief Holds the data of one single data point for QCPFinancial.
20501
20502   The container for storing multiple data points is \ref QCPFinancialDataMap.
20503
20504   The stored data is:
20505   \li \a key: coordinate on the key axis of this data point
20506   \li \a open: The opening value at the data point
20507   \li \a high: The high/maximum value at the data point
20508   \li \a low: The low/minimum value at the data point
20509   \li \a close: The closing value at the data point
20510
20511   \see QCPFinancialDataMap
20512 */
20513
20514 /*!
20515   Constructs a data point with key and all values set to zero.
20516 */
20517 QCPFinancialData::QCPFinancialData() :
20518   key(0),
20519   open(0),
20520   high(0),
20521   low(0),
20522   close(0)
20523 {
20524 }
20525
20526 /*!
20527   Constructs a data point with the specified \a key and OHLC values.
20528 */
20529 QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) :
20530   key(key),
20531   open(open),
20532   high(high),
20533   low(low),
20534   close(close)
20535 {
20536 }
20537
20538
20539 ////////////////////////////////////////////////////////////////////////////////////////////////////
20540 //////////////////// QCPFinancial
20541 ////////////////////////////////////////////////////////////////////////////////////////////////////
20542
20543 /*! \class QCPFinancial
20544   \brief A plottable representing a financial stock chart
20545
20546   \image html QCPFinancial.png
20547
20548   This plottable represents time series data binned to certain intervals, mainly used for stock
20549   charts. The two common representations OHLC (Open-High-Low-Close) bars and Candlesticks can be
20550   set via \ref setChartStyle.
20551
20552   The data is passed via \ref setData as a set of open/high/low/close values at certain keys
20553   (typically times). This means the data must be already binned appropriately. If data is only
20554   available as a series of values (e.g. \a price against \a time), you can use the static
20555   convenience function \ref timeSeriesToOhlc to generate binned OHLC-data which can then be passed
20556   to \ref setData.
20557
20558   The width of the OHLC bars/candlesticks can be controlled with \ref setWidth and is given in plot
20559   key coordinates. A typical choice is to set it to (or slightly less than) one bin interval width.
20560
20561   \section appearance Changing the appearance
20562
20563   Charts can be either single- or two-colored (\ref setTwoColored). If set to be single-colored,
20564   lines are drawn with the plottable's pen (\ref setPen) and fills with the brush (\ref setBrush).
20565
20566   If set to two-colored, positive changes of the value during an interval (\a close >= \a open) are
20567   represented with a different pen and brush than negative changes (\a close < \a open). These can
20568   be configured with \ref setPenPositive, \ref setPenNegative, \ref setBrushPositive, and \ref
20569   setBrushNegative. In two-colored mode, the normal plottable pen/brush is ignored. Upon selection
20570   however, the normal selected pen/brush (\ref setSelectedPen, \ref setSelectedBrush) is used,
20571   irrespective of whether the chart is single- or two-colored.
20572
20573 */
20574
20575 /* start of documentation of inline functions */
20576
20577 /*! \fn QCPFinancialDataMap *QCPFinancial::data() const
20578
20579   Returns a pointer to the internal data storage of type \ref QCPFinancialDataMap. You may use it to
20580   directly manipulate the data, which may be more convenient and faster than using the regular \ref
20581   setData or \ref addData methods, in certain situations.
20582 */
20583
20584 /* end of documentation of inline functions */
20585
20586 /*!
20587   Constructs a financial chart which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value
20588   axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have
20589   the same orientation. If either of these restrictions is violated, a corresponding message is
20590   printed to the debug output (qDebug), the construction is not aborted, though.
20591
20592   The constructed QCPFinancial can be added to the plot with QCustomPlot::addPlottable, QCustomPlot
20593   then takes ownership of the financial chart.
20594 */
20595 QCPFinancial::QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis) :
20596   QCPAbstractPlottable(keyAxis, valueAxis),
20597   mData(0),
20598   mChartStyle(csOhlc),
20599   mWidth(0.5),
20600   mTwoColored(false),
20601   mBrushPositive(QBrush(QColor(210, 210, 255))),
20602   mBrushNegative(QBrush(QColor(255, 210, 210))),
20603   mPenPositive(QPen(QColor(10, 40, 180))),
20604   mPenNegative(QPen(QColor(180, 40, 10)))
20605 {
20606   mData = new QCPFinancialDataMap;
20607
20608   setSelectedPen(QPen(QColor(80, 80, 255), 2.5));
20609   setSelectedBrush(QBrush(QColor(80, 80, 255)));
20610 }
20611
20612 QCPFinancial::~QCPFinancial()
20613 {
20614   delete mData;
20615 }
20616
20617 /*!
20618   Replaces the current data with the provided \a data.
20619
20620   If \a copy is set to true, data points in \a data will only be copied. if false, the plottable
20621   takes ownership of the passed data and replaces the internal data pointer with it. This is
20622   significantly faster than copying for large datasets.
20623
20624   Alternatively, you can also access and modify the plottable's data via the \ref data method, which
20625   returns a pointer to the internal \ref QCPFinancialDataMap.
20626
20627   \see timeSeriesToOhlc
20628 */
20629 void QCPFinancial::setData(QCPFinancialDataMap *data, bool copy)
20630 {
20631   if (mData == data)
20632   {
20633     qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
20634     return;
20635   }
20636   if (copy)
20637   {
20638     *mData = *data;
20639   } else
20640   {
20641     delete mData;
20642     mData = data;
20643   }
20644 }
20645
20646 /*! \overload
20647
20648   Replaces the current data with the provided open/high/low/close data. The provided vectors should
20649   have equal length. Else, the number of added points will be the size of the smallest vector.
20650
20651   \see timeSeriesToOhlc
20652 */
20653 void QCPFinancial::setData(const QVector<double> &key, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close)
20654 {
20655   mData->clear();
20656   int n = key.size();
20657   n = qMin(n, open.size());
20658   n = qMin(n, high.size());
20659   n = qMin(n, low.size());
20660   n = qMin(n, close.size());
20661   for (int i=0; i<n; ++i)
20662   {
20663     mData->insertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i]));
20664   }
20665 }
20666
20667 /*!
20668   Sets which representation style shall be used to display the OHLC data.
20669 */
20670 void QCPFinancial::setChartStyle(QCPFinancial::ChartStyle style)
20671 {
20672   mChartStyle = style;
20673 }
20674
20675 /*!
20676   Sets the width of the individual bars/candlesticks to \a width in plot key coordinates.
20677
20678   A typical choice is to set it to (or slightly less than) one bin interval width.
20679 */
20680 void QCPFinancial::setWidth(double width)
20681 {
20682   mWidth = width;
20683 }
20684
20685 /*!
20686   Sets whether this chart shall contrast positive from negative trends per data point by using two
20687   separate colors to draw the respective bars/candlesticks.
20688
20689   If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref
20690   setBrush).
20691
20692   \see setPenPositive, setPenNegative, setBrushPositive, setBrushNegative
20693 */
20694 void QCPFinancial::setTwoColored(bool twoColored)
20695 {
20696   mTwoColored = twoColored;
20697 }
20698
20699 /*!
20700   If \ref setTwoColored is set to true, this function controls the brush that is used to draw fills
20701   of data points with a positive trend (i.e. bars/candlesticks with close >= open).
20702
20703   If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref
20704   setBrush).
20705
20706   \see setBrushNegative, setPenPositive, setPenNegative
20707 */
20708 void QCPFinancial::setBrushPositive(const QBrush &brush)
20709 {
20710   mBrushPositive = brush;
20711 }
20712
20713 /*!
20714   If \ref setTwoColored is set to true, this function controls the brush that is used to draw fills
20715   of data points with a negative trend (i.e. bars/candlesticks with close < open).
20716
20717   If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref
20718   setBrush).
20719
20720   \see setBrushPositive, setPenNegative, setPenPositive
20721 */
20722 void QCPFinancial::setBrushNegative(const QBrush &brush)
20723 {
20724   mBrushNegative = brush;
20725 }
20726
20727 /*!
20728   If \ref setTwoColored is set to true, this function controls the pen that is used to draw
20729   outlines of data points with a positive trend (i.e. bars/candlesticks with close >= open).
20730
20731   If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref
20732   setBrush).
20733
20734   \see setPenNegative, setBrushPositive, setBrushNegative
20735 */
20736 void QCPFinancial::setPenPositive(const QPen &pen)
20737 {
20738   mPenPositive = pen;
20739 }
20740
20741 /*!
20742   If \ref setTwoColored is set to true, this function controls the pen that is used to draw
20743   outlines of data points with a negative trend (i.e. bars/candlesticks with close < open).
20744
20745   If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref
20746   setBrush).
20747
20748   \see setPenPositive, setBrushNegative, setBrushPositive
20749 */
20750 void QCPFinancial::setPenNegative(const QPen &pen)
20751 {
20752   mPenNegative = pen;
20753 }
20754
20755 /*!
20756   Adds the provided data points in \a dataMap to the current data.
20757
20758   Alternatively, you can also access and modify the data via the \ref data method, which returns a
20759   pointer to the internal \ref QCPFinancialDataMap.
20760
20761   \see removeData
20762 */
20763 void QCPFinancial::addData(const QCPFinancialDataMap &dataMap)
20764 {
20765   mData->unite(dataMap);
20766 }
20767
20768 /*! \overload
20769
20770   Adds the provided single data point in \a data to the current data.
20771
20772   Alternatively, you can also access and modify the data via the \ref data method, which returns a
20773   pointer to the internal \ref QCPFinancialData.
20774
20775   \see removeData
20776 */
20777 void QCPFinancial::addData(const QCPFinancialData &data)
20778 {
20779   mData->insertMulti(data.key, data);
20780 }
20781
20782 /*! \overload
20783
20784   Adds the provided single data point given by \a key, \a open, \a high, \a low, and \a close to
20785   the current data.
20786
20787   Alternatively, you can also access and modify the data via the \ref data method, which returns a
20788   pointer to the internal \ref QCPFinancialData.
20789
20790   \see removeData
20791 */
20792 void QCPFinancial::addData(double key, double open, double high, double low, double close)
20793 {
20794   mData->insertMulti(key, QCPFinancialData(key, open, high, low, close));
20795 }
20796
20797 /*! \overload
20798
20799   Adds the provided open/high/low/close data to the current data.
20800
20801   Alternatively, you can also access and modify the data via the \ref data method, which returns a
20802   pointer to the internal \ref QCPFinancialData.
20803
20804   \see removeData
20805 */
20806 void QCPFinancial::addData(const QVector<double> &key, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close)
20807 {
20808   int n = key.size();
20809   n = qMin(n, open.size());
20810   n = qMin(n, high.size());
20811   n = qMin(n, low.size());
20812   n = qMin(n, close.size());
20813   for (int i=0; i<n; ++i)
20814   {
20815     mData->insertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i]));
20816   }
20817 }
20818
20819 /*!
20820   Removes all data points with keys smaller than \a key.
20821
20822   \see addData, clearData
20823 */
20824 void QCPFinancial::removeDataBefore(double key)
20825 {
20826   QCPFinancialDataMap::iterator it = mData->begin();
20827   while (it != mData->end() && it.key() < key)
20828     it = mData->erase(it);
20829 }
20830
20831 /*!
20832   Removes all data points with keys greater than \a key.
20833
20834   \see addData, clearData
20835 */
20836 void QCPFinancial::removeDataAfter(double key)
20837 {
20838   if (mData->isEmpty()) return;
20839   QCPFinancialDataMap::iterator it = mData->upperBound(key);
20840   while (it != mData->end())
20841     it = mData->erase(it);
20842 }
20843
20844 /*!
20845   Removes all data points with keys between \a fromKey and \a toKey. if \a fromKey is greater or
20846   equal to \a toKey, the function does nothing. To remove a single data point with known key, use
20847   \ref removeData(double key).
20848
20849   \see addData, clearData
20850 */
20851 void QCPFinancial::removeData(double fromKey, double toKey)
20852 {
20853   if (fromKey >= toKey || mData->isEmpty()) return;
20854   QCPFinancialDataMap::iterator it = mData->upperBound(fromKey);
20855   QCPFinancialDataMap::iterator itEnd = mData->upperBound(toKey);
20856   while (it != itEnd)
20857     it = mData->erase(it);
20858 }
20859
20860 /*! \overload
20861
20862   Removes a single data point at \a key. If the position is not known with absolute precision,
20863   consider using \ref removeData(double fromKey, double toKey) with a small fuzziness interval
20864   around the suspected position, depeding on the precision with which the key is known.
20865
20866   \see addData, clearData
20867 */
20868 void QCPFinancial::removeData(double key)
20869 {
20870   mData->remove(key);
20871 }
20872
20873 /*!
20874   Removes all data points.
20875
20876   \see removeData, removeDataAfter, removeDataBefore
20877 */
20878 void QCPFinancial::clearData()
20879 {
20880   mData->clear();
20881 }
20882
20883 /* inherits documentation from base class */
20884 double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
20885 {
20886   Q_UNUSED(details)
20887   if (onlySelectable && !mSelectable)
20888     return -1;
20889   if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
20890
20891   if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20892   {
20893     // get visible data range:
20894     QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
20895     getVisibleDataBounds(lower, upper);
20896     if (lower == mData->constEnd() || upper == mData->constEnd())
20897       return -1;
20898     // perform select test according to configured style:
20899     switch (mChartStyle)
20900     {
20901       case QCPFinancial::csOhlc:
20902         return ohlcSelectTest(pos, lower, upper+1); break;
20903       case QCPFinancial::csCandlestick:
20904         return candlestickSelectTest(pos, lower, upper+1); break;
20905     }
20906   }
20907   return -1;
20908 }
20909
20910 /*!
20911   A convenience function that converts time series data (\a value against \a time) to OHLC binned
20912   data points. The return value can then be passed on to \ref setData.
20913
20914   The size of the bins can be controlled with \a timeBinSize in the same units as \a time is given.
20915   For example, if the unit of \a time is seconds and single OHLC/Candlesticks should span an hour
20916   each, set \a timeBinSize to 3600.
20917
20918   \a timeBinOffset allows to control precisely at what \a time coordinate a bin should start. The
20919   value passed as \a timeBinOffset doesn't need to be in the range encompassed by the \a time keys.
20920   It merely defines the mathematical offset/phase of the bins that will be used to process the
20921   data.
20922 */
20923 QCPFinancialDataMap QCPFinancial::timeSeriesToOhlc(const QVector<double> &time, const QVector<double> &value, double timeBinSize, double timeBinOffset)
20924 {
20925   QCPFinancialDataMap map;
20926   int count = qMin(time.size(), value.size());
20927   if (count == 0)
20928     return QCPFinancialDataMap();
20929
20930   QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first());
20931   int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5);
20932   for (int i=0; i<count; ++i)
20933   {
20934     int index = qFloor((time.at(i)-timeBinOffset)/timeBinSize+0.5);
20935     if (currentBinIndex == index) // data point still in current bin, extend high/low:
20936     {
20937       if (value.at(i) < currentBinData.low) currentBinData.low = value.at(i);
20938       if (value.at(i) > currentBinData.high) currentBinData.high = value.at(i);
20939       if (i == count-1) // last data point is in current bin, finalize bin:
20940       {
20941         currentBinData.close = value.at(i);
20942         currentBinData.key = timeBinOffset+(index)*timeBinSize;
20943         map.insert(currentBinData.key, currentBinData);
20944       }
20945     } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map:
20946     {
20947       // finalize current bin:
20948       currentBinData.close = value.at(i-1);
20949       currentBinData.key = timeBinOffset+(index-1)*timeBinSize;
20950       map.insert(currentBinData.key, currentBinData);
20951       // start next bin:
20952       currentBinIndex = index;
20953       currentBinData.open = value.at(i);
20954       currentBinData.high = value.at(i);
20955       currentBinData.low = value.at(i);
20956     }
20957   }
20958
20959   return map;
20960 }
20961
20962 /* inherits documentation from base class */
20963 void QCPFinancial::draw(QCPPainter *painter)
20964 {
20965   // get visible data range:
20966   QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
20967   getVisibleDataBounds(lower, upper);
20968   if (lower == mData->constEnd() || upper == mData->constEnd())
20969     return;
20970
20971   // draw visible data range according to configured style:
20972   switch (mChartStyle)
20973   {
20974     case QCPFinancial::csOhlc:
20975       drawOhlcPlot(painter, lower, upper+1); break;
20976     case QCPFinancial::csCandlestick:
20977       drawCandlestickPlot(painter, lower, upper+1); break;
20978   }
20979 }
20980
20981 /* inherits documentation from base class */
20982 void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
20983 {
20984   painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing
20985   if (mChartStyle == csOhlc)
20986   {
20987     if (mTwoColored)
20988     {
20989       // draw upper left half icon with positive color:
20990       painter->setBrush(mBrushPositive);
20991       painter->setPen(mPenPositive);
20992       painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
20993       painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
20994       painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
20995       painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
20996       // draw bottom right hald icon with negative color:
20997       painter->setBrush(mBrushNegative);
20998       painter->setPen(mPenNegative);
20999       painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
21000       painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21001       painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21002       painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21003     } else
21004     {
21005       painter->setBrush(mBrush);
21006       painter->setPen(mPen);
21007       painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21008       painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21009       painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21010     }
21011   } else if (mChartStyle == csCandlestick)
21012   {
21013     if (mTwoColored)
21014     {
21015       // draw upper left half icon with positive color:
21016       painter->setBrush(mBrushPositive);
21017       painter->setPen(mPenPositive);
21018       painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
21019       painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21020       painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21021       painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21022       // draw bottom right hald icon with negative color:
21023       painter->setBrush(mBrushNegative);
21024       painter->setPen(mPenNegative);
21025       painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
21026       painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21027       painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21028       painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21029     } else
21030     {
21031       painter->setBrush(mBrush);
21032       painter->setPen(mPen);
21033       painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21034       painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21035       painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21036     }
21037   }
21038 }
21039
21040 /* inherits documentation from base class */
21041 QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const
21042 {
21043   QCPRange range;
21044   bool haveLower = false;
21045   bool haveUpper = false;
21046
21047   double current;
21048   QCPFinancialDataMap::const_iterator it = mData->constBegin();
21049   while (it != mData->constEnd())
21050   {
21051     current = it.value().key;
21052     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
21053     {
21054       if (current < range.lower || !haveLower)
21055       {
21056         range.lower = current;
21057         haveLower = true;
21058       }
21059       if (current > range.upper || !haveUpper)
21060       {
21061         range.upper = current;
21062         haveUpper = true;
21063       }
21064     }
21065     ++it;
21066   }
21067   // determine exact range by including width of bars/flags:
21068   if (haveLower && mKeyAxis)
21069     range.lower = range.lower-mWidth*0.5;
21070   if (haveUpper && mKeyAxis)
21071     range.upper = range.upper+mWidth*0.5;
21072   foundRange = haveLower && haveUpper;
21073   return range;
21074 }
21075
21076 /* inherits documentation from base class */
21077 QCPRange QCPFinancial::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const
21078 {
21079   QCPRange range;
21080   bool haveLower = false;
21081   bool haveUpper = false;
21082
21083   QCPFinancialDataMap::const_iterator it = mData->constBegin();
21084   while (it != mData->constEnd())
21085   {
21086     // high:
21087     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().high < 0) || (inSignDomain == sdPositive && it.value().high > 0))
21088     {
21089       if (it.value().high < range.lower || !haveLower)
21090       {
21091         range.lower = it.value().high;
21092         haveLower = true;
21093       }
21094       if (it.value().high > range.upper || !haveUpper)
21095       {
21096         range.upper = it.value().high;
21097         haveUpper = true;
21098       }
21099     }
21100     // low:
21101     if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().low < 0) || (inSignDomain == sdPositive && it.value().low > 0))
21102     {
21103       if (it.value().low < range.lower || !haveLower)
21104       {
21105         range.lower = it.value().low;
21106         haveLower = true;
21107       }
21108       if (it.value().low > range.upper || !haveUpper)
21109       {
21110         range.upper = it.value().low;
21111         haveUpper = true;
21112       }
21113     }
21114     ++it;
21115   }
21116
21117   foundRange = haveLower && haveUpper;
21118   return range;
21119 }
21120
21121 /*! \internal
21122
21123   Draws the data from \a begin to \a end as OHLC bars with the provided \a painter.
21124
21125   This method is a helper function for \ref draw. It is used when the chart style is \ref csOhlc.
21126 */
21127 void QCPFinancial::drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
21128 {
21129   QCPAxis *keyAxis = mKeyAxis.data();
21130   QCPAxis *valueAxis = mValueAxis.data();
21131   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21132
21133   QPen linePen;
21134
21135   if (keyAxis->orientation() == Qt::Horizontal)
21136   {
21137     for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21138     {
21139       if (mSelected)
21140         linePen = mSelectedPen;
21141       else if (mTwoColored)
21142         linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative;
21143       else
21144         linePen = mPen;
21145       painter->setPen(linePen);
21146       double keyPixel = keyAxis->coordToPixel(it.value().key);
21147       double openPixel = valueAxis->coordToPixel(it.value().open);
21148       double closePixel = valueAxis->coordToPixel(it.value().close);
21149       // draw backbone:
21150       painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)));
21151       // draw open:
21152       double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides
21153       painter->drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel));
21154       // draw close:
21155       painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel));
21156     }
21157   } else
21158   {
21159     for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21160     {
21161       if (mSelected)
21162         linePen = mSelectedPen;
21163       else if (mTwoColored)
21164         linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative;
21165       else
21166         linePen = mPen;
21167       painter->setPen(linePen);
21168       double keyPixel = keyAxis->coordToPixel(it.value().key);
21169       double openPixel = valueAxis->coordToPixel(it.value().open);
21170       double closePixel = valueAxis->coordToPixel(it.value().close);
21171       // draw backbone:
21172       painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel));
21173       // draw open:
21174       double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides
21175       painter->drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel));
21176       // draw close:
21177       painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels));
21178     }
21179   }
21180 }
21181
21182 /*! \internal
21183
21184   Draws the data from \a begin to \a end as Candlesticks with the provided \a painter.
21185
21186   This method is a helper function for \ref draw. It is used when the chart style is \ref csCandlestick.
21187 */
21188 void QCPFinancial::drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
21189 {
21190   QCPAxis *keyAxis = mKeyAxis.data();
21191   QCPAxis *valueAxis = mValueAxis.data();
21192   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21193
21194   QPen linePen;
21195   QBrush boxBrush;
21196
21197   if (keyAxis->orientation() == Qt::Horizontal)
21198   {
21199     for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21200     {
21201       if (mSelected)
21202       {
21203         linePen = mSelectedPen;
21204         boxBrush = mSelectedBrush;
21205       } else if (mTwoColored)
21206       {
21207         if (it.value().close >= it.value().open)
21208         {
21209           linePen = mPenPositive;
21210           boxBrush = mBrushPositive;
21211         } else
21212         {
21213           linePen = mPenNegative;
21214           boxBrush = mBrushNegative;
21215         }
21216       } else
21217       {
21218         linePen = mPen;
21219         boxBrush = mBrush;
21220       }
21221       painter->setPen(linePen);
21222       painter->setBrush(boxBrush);
21223       double keyPixel = keyAxis->coordToPixel(it.value().key);
21224       double openPixel = valueAxis->coordToPixel(it.value().open);
21225       double closePixel = valueAxis->coordToPixel(it.value().close);
21226       // draw high:
21227       painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))));
21228       // draw low:
21229       painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))));
21230       // draw open-close box:
21231       double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5);
21232       painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel)));
21233     }
21234   } else // keyAxis->orientation() == Qt::Vertical
21235   {
21236     for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21237     {
21238       if (mSelected)
21239       {
21240         linePen = mSelectedPen;
21241         boxBrush = mSelectedBrush;
21242       } else if (mTwoColored)
21243       {
21244         if (it.value().close >= it.value().open)
21245         {
21246           linePen = mPenPositive;
21247           boxBrush = mBrushPositive;
21248         } else
21249         {
21250           linePen = mPenNegative;
21251           boxBrush = mBrushNegative;
21252         }
21253       } else
21254       {
21255         linePen = mPen;
21256         boxBrush = mBrush;
21257       }
21258       painter->setPen(linePen);
21259       painter->setBrush(boxBrush);
21260       double keyPixel = keyAxis->coordToPixel(it.value().key);
21261       double openPixel = valueAxis->coordToPixel(it.value().open);
21262       double closePixel = valueAxis->coordToPixel(it.value().close);
21263       // draw high:
21264       painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel));
21265       // draw low:
21266       painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel));
21267       // draw open-close box:
21268       double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5);
21269       painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels)));
21270     }
21271   }
21272 }
21273
21274 /*! \internal
21275
21276   This method is a helper function for \ref selectTest. It is used to test for selection when the
21277   chart style is \ref csOhlc. It only tests against the data points between \a begin and \a end.
21278 */
21279 double QCPFinancial::ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
21280 {
21281   QCPAxis *keyAxis = mKeyAxis.data();
21282   QCPAxis *valueAxis = mValueAxis.data();
21283   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21284
21285   double minDistSqr = std::numeric_limits<double>::max();
21286   QCPFinancialDataMap::const_iterator it;
21287   if (keyAxis->orientation() == Qt::Horizontal)
21288   {
21289     for (it = begin; it != end; ++it)
21290     {
21291       double keyPixel = keyAxis->coordToPixel(it.value().key);
21292       // calculate distance to backbone:
21293       double currentDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), pos);
21294       if (currentDistSqr < minDistSqr)
21295         minDistSqr = currentDistSqr;
21296     }
21297   } else // keyAxis->orientation() == Qt::Vertical
21298   {
21299     for (it = begin; it != end; ++it)
21300     {
21301       double keyPixel = keyAxis->coordToPixel(it.value().key);
21302       // calculate distance to backbone:
21303       double currentDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), pos);
21304       if (currentDistSqr < minDistSqr)
21305         minDistSqr = currentDistSqr;
21306     }
21307   }
21308   return qSqrt(minDistSqr);
21309 }
21310
21311 /*! \internal
21312
21313   This method is a helper function for \ref selectTest. It is used to test for selection when the
21314   chart style is \ref csCandlestick. It only tests against the data points between \a begin and \a
21315   end.
21316 */
21317 double QCPFinancial::candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
21318 {
21319   QCPAxis *keyAxis = mKeyAxis.data();
21320   QCPAxis *valueAxis = mValueAxis.data();
21321   if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21322
21323   double minDistSqr = std::numeric_limits<double>::max();
21324   QCPFinancialDataMap::const_iterator it;
21325   if (keyAxis->orientation() == Qt::Horizontal)
21326   {
21327     for (it = begin; it != end; ++it)
21328     {
21329       double currentDistSqr;
21330       // determine whether pos is in open-close-box:
21331       QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5);
21332       QCPRange boxValueRange(it.value().close, it.value().open);
21333       double posKey, posValue;
21334       pixelsToCoords(pos, posKey, posValue);
21335       if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
21336       {
21337         currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
21338       } else
21339       {
21340         // calculate distance to high/low lines:
21341         double keyPixel = keyAxis->coordToPixel(it.value().key);
21342         double highLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))), pos);
21343         double lowLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))), pos);
21344         currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21345       }
21346       if (currentDistSqr < minDistSqr)
21347         minDistSqr = currentDistSqr;
21348     }
21349   } else // keyAxis->orientation() == Qt::Vertical
21350   {
21351     for (it = begin; it != end; ++it)
21352     {
21353       double currentDistSqr;
21354       // determine whether pos is in open-close-box:
21355       QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5);
21356       QCPRange boxValueRange(it.value().close, it.value().open);
21357       double posKey, posValue;
21358       pixelsToCoords(pos, posKey, posValue);
21359       if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
21360       {
21361         currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
21362       } else
21363       {
21364         // calculate distance to high/low lines:
21365         double keyPixel = keyAxis->coordToPixel(it.value().key);
21366         double highLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos);
21367         double lowLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos);
21368         currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21369       }
21370       if (currentDistSqr < minDistSqr)
21371         minDistSqr = currentDistSqr;
21372     }
21373   }
21374   return qSqrt(minDistSqr);
21375 }
21376
21377 /*!  \internal
21378
21379   called by the drawing methods to determine which data (key) range is visible at the current key
21380   axis range setting, so only that needs to be processed.
21381
21382   \a lower returns an iterator to the lowest data point that needs to be taken into account when
21383   plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a
21384   lower may still be just outside the visible range.
21385
21386   \a upper returns an iterator to the highest data point. Same as before, \a upper may also lie
21387   just outside of the visible range.
21388
21389   if the plottable contains no data, both \a lower and \a upper point to constEnd.
21390
21391   \see QCPGraph::getVisibleDataBounds
21392 */
21393 void QCPFinancial::getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const
21394 {
21395   if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
21396   if (mData->isEmpty())
21397   {
21398     lower = mData->constEnd();
21399     upper = mData->constEnd();
21400     return;
21401   }
21402
21403   // get visible data range as QMap iterators
21404   QCPFinancialDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower);
21405   QCPFinancialDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper);
21406   bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
21407   bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
21408
21409   lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
21410   upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
21411 }
21412
21413
21414 ////////////////////////////////////////////////////////////////////////////////////////////////////
21415 //////////////////// QCPItemStraightLine
21416 ////////////////////////////////////////////////////////////////////////////////////////////////////
21417
21418 /*! \class QCPItemStraightLine
21419   \brief A straight line that spans infinitely in both directions
21420
21421   \image html QCPItemStraightLine.png "Straight line example. Blue dotted circles are anchors, solid blue discs are positions."
21422
21423   It has two positions, \a point1 and \a point2, which define the straight line.
21424 */
21425
21426 /*!
21427   Creates a straight line item and sets default values.
21428
21429   The constructed item can be added to the plot with QCustomPlot::addItem.
21430 */
21431 QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) :
21432   QCPAbstractItem(parentPlot),
21433   point1(createPosition(QLatin1String("point1"))),
21434   point2(createPosition(QLatin1String("point2")))
21435 {
21436   point1->setCoords(0, 0);
21437   point2->setCoords(1, 1);
21438
21439   setPen(QPen(Qt::black));
21440   setSelectedPen(QPen(Qt::blue,2));
21441 }
21442
21443 QCPItemStraightLine::~QCPItemStraightLine()
21444 {
21445 }
21446
21447 /*!
21448   Sets the pen that will be used to draw the line
21449
21450   \see setSelectedPen
21451 */
21452 void QCPItemStraightLine::setPen(const QPen &pen)
21453 {
21454   mPen = pen;
21455 }
21456
21457 /*!
21458   Sets the pen that will be used to draw the line when selected
21459
21460   \see setPen, setSelected
21461 */
21462 void QCPItemStraightLine::setSelectedPen(const QPen &pen)
21463 {
21464   mSelectedPen = pen;
21465 }
21466
21467 /* inherits documentation from base class */
21468 double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21469 {
21470   Q_UNUSED(details)
21471   if (onlySelectable && !mSelectable)
21472     return -1;
21473
21474   return distToStraightLine(QVector2D(point1->pixelPoint()), QVector2D(point2->pixelPoint()-point1->pixelPoint()), QVector2D(pos));
21475 }
21476
21477 /* inherits documentation from base class */
21478 void QCPItemStraightLine::draw(QCPPainter *painter)
21479 {
21480   QVector2D start(point1->pixelPoint());
21481   QVector2D end(point2->pixelPoint());
21482   // get visible segment of straight line inside clipRect:
21483   double clipPad = mainPen().widthF();
21484   QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
21485   // paint visible segment, if existent:
21486   if (!line.isNull())
21487   {
21488     painter->setPen(mainPen());
21489     painter->drawLine(line);
21490   }
21491 }
21492
21493 /*! \internal
21494
21495   finds the shortest distance of \a point to the straight line defined by the base point \a
21496   base and the direction vector \a vec.
21497
21498   This is a helper function for \ref selectTest.
21499 */
21500 double QCPItemStraightLine::distToStraightLine(const QVector2D &base, const QVector2D &vec, const QVector2D &point) const
21501 {
21502   return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length();
21503 }
21504
21505 /*! \internal
21506
21507   Returns the section of the straight line defined by \a base and direction vector \a
21508   vec, that is visible in the specified \a rect.
21509
21510   This is a helper function for \ref draw.
21511 */
21512 QLineF QCPItemStraightLine::getRectClippedStraightLine(const QVector2D &base, const QVector2D &vec, const QRect &rect) const
21513 {
21514   double bx, by;
21515   double gamma;
21516   QLineF result;
21517   if (vec.x() == 0 && vec.y() == 0)
21518     return result;
21519   if (qFuzzyIsNull(vec.x())) // line is vertical
21520   {
21521     // check top of rect:
21522     bx = rect.left();
21523     by = rect.top();
21524     gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21525     if (gamma >= 0 && gamma <= rect.width())
21526       result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical
21527   } else if (qFuzzyIsNull(vec.y())) // line is horizontal
21528   {
21529     // check left of rect:
21530     bx = rect.left();
21531     by = rect.top();
21532     gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21533     if (gamma >= 0 && gamma <= rect.height())
21534       result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal
21535   } else // line is skewed
21536   {
21537     QList<QVector2D> pointVectors;
21538     // check top of rect:
21539     bx = rect.left();
21540     by = rect.top();
21541     gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21542     if (gamma >= 0 && gamma <= rect.width())
21543       pointVectors.append(QVector2D(bx+gamma, by));
21544     // check bottom of rect:
21545     bx = rect.left();
21546     by = rect.bottom();
21547     gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21548     if (gamma >= 0 && gamma <= rect.width())
21549       pointVectors.append(QVector2D(bx+gamma, by));
21550     // check left of rect:
21551     bx = rect.left();
21552     by = rect.top();
21553     gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21554     if (gamma >= 0 && gamma <= rect.height())
21555       pointVectors.append(QVector2D(bx, by+gamma));
21556     // check right of rect:
21557     bx = rect.right();
21558     by = rect.top();
21559     gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21560     if (gamma >= 0 && gamma <= rect.height())
21561       pointVectors.append(QVector2D(bx, by+gamma));
21562
21563     // evaluate points:
21564     if (pointVectors.size() == 2)
21565     {
21566       result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
21567     } else if (pointVectors.size() > 2)
21568     {
21569       // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
21570       double distSqrMax = 0;
21571       QVector2D pv1, pv2;
21572       for (int i=0; i<pointVectors.size()-1; ++i)
21573       {
21574         for (int k=i+1; k<pointVectors.size(); ++k)
21575         {
21576           double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
21577           if (distSqr > distSqrMax)
21578           {
21579             pv1 = pointVectors.at(i);
21580             pv2 = pointVectors.at(k);
21581             distSqrMax = distSqr;
21582           }
21583         }
21584       }
21585       result.setPoints(pv1.toPointF(), pv2.toPointF());
21586     }
21587   }
21588   return result;
21589 }
21590
21591 /*! \internal
21592
21593   Returns the pen that should be used for drawing lines. Returns mPen when the
21594   item is not selected and mSelectedPen when it is.
21595 */
21596 QPen QCPItemStraightLine::mainPen() const
21597 {
21598   return mSelected ? mSelectedPen : mPen;
21599 }
21600
21601
21602 ////////////////////////////////////////////////////////////////////////////////////////////////////
21603 //////////////////// QCPItemLine
21604 ////////////////////////////////////////////////////////////////////////////////////////////////////
21605
21606 /*! \class QCPItemLine
21607   \brief A line from one point to another
21608
21609   \image html QCPItemLine.png "Line example. Blue dotted circles are anchors, solid blue discs are positions."
21610
21611   It has two positions, \a start and \a end, which define the end points of the line.
21612
21613   With \ref setHead and \ref setTail you may set different line ending styles, e.g. to create an arrow.
21614 */
21615
21616 /*!
21617   Creates a line item and sets default values.
21618
21619   The constructed item can be added to the plot with QCustomPlot::addItem.
21620 */
21621 QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) :
21622   QCPAbstractItem(parentPlot),
21623   start(createPosition(QLatin1String("start"))),
21624   end(createPosition(QLatin1String("end")))
21625 {
21626   start->setCoords(0, 0);
21627   end->setCoords(1, 1);
21628
21629   setPen(QPen(Qt::black));
21630   setSelectedPen(QPen(Qt::blue,2));
21631 }
21632
21633 QCPItemLine::~QCPItemLine()
21634 {
21635 }
21636
21637 /*!
21638   Sets the pen that will be used to draw the line
21639
21640   \see setSelectedPen
21641 */
21642 void QCPItemLine::setPen(const QPen &pen)
21643 {
21644   mPen = pen;
21645 }
21646
21647 /*!
21648   Sets the pen that will be used to draw the line when selected
21649
21650   \see setPen, setSelected
21651 */
21652 void QCPItemLine::setSelectedPen(const QPen &pen)
21653 {
21654   mSelectedPen = pen;
21655 }
21656
21657 /*!
21658   Sets the line ending style of the head. The head corresponds to the \a end position.
21659
21660   Note that due to the overloaded QCPLineEnding constructor, you may directly specify
21661   a QCPLineEnding::EndingStyle here, e.g. \code setHead(QCPLineEnding::esSpikeArrow) \endcode
21662
21663   \see setTail
21664 */
21665 void QCPItemLine::setHead(const QCPLineEnding &head)
21666 {
21667   mHead = head;
21668 }
21669
21670 /*!
21671   Sets the line ending style of the tail. The tail corresponds to the \a start position.
21672
21673   Note that due to the overloaded QCPLineEnding constructor, you may directly specify
21674   a QCPLineEnding::EndingStyle here, e.g. \code setTail(QCPLineEnding::esSpikeArrow) \endcode
21675
21676   \see setHead
21677 */
21678 void QCPItemLine::setTail(const QCPLineEnding &tail)
21679 {
21680   mTail = tail;
21681 }
21682
21683 /* inherits documentation from base class */
21684 double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21685 {
21686   Q_UNUSED(details)
21687   if (onlySelectable && !mSelectable)
21688     return -1;
21689
21690   return qSqrt(distSqrToLine(start->pixelPoint(), end->pixelPoint(), pos));
21691 }
21692
21693 /* inherits documentation from base class */
21694 void QCPItemLine::draw(QCPPainter *painter)
21695 {
21696   QVector2D startVec(start->pixelPoint());
21697   QVector2D endVec(end->pixelPoint());
21698   if (startVec.toPoint() == endVec.toPoint())
21699     return;
21700   // get visible segment of straight line inside clipRect:
21701   double clipPad = qMax(mHead.boundingDistance(), mTail.boundingDistance());
21702   clipPad = qMax(clipPad, (double)mainPen().widthF());
21703   QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
21704   // paint visible segment, if existent:
21705   if (!line.isNull())
21706   {
21707     painter->setPen(mainPen());
21708     painter->drawLine(line);
21709     painter->setBrush(Qt::SolidPattern);
21710     if (mTail.style() != QCPLineEnding::esNone)
21711       mTail.draw(painter, startVec, startVec-endVec);
21712     if (mHead.style() != QCPLineEnding::esNone)
21713       mHead.draw(painter, endVec, endVec-startVec);
21714   }
21715 }
21716
21717 /*! \internal
21718
21719   Returns the section of the line defined by \a start and \a end, that is visible in the specified
21720   \a rect.
21721
21722   This is a helper function for \ref draw.
21723 */
21724 QLineF QCPItemLine::getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const
21725 {
21726   bool containsStart = rect.contains(start.x(), start.y());
21727   bool containsEnd = rect.contains(end.x(), end.y());
21728   if (containsStart && containsEnd)
21729     return QLineF(start.toPointF(), end.toPointF());
21730
21731   QVector2D base = start;
21732   QVector2D vec = end-start;
21733   double bx, by;
21734   double gamma, mu;
21735   QLineF result;
21736   QList<QVector2D> pointVectors;
21737
21738   if (!qFuzzyIsNull(vec.y())) // line is not horizontal
21739   {
21740     // check top of rect:
21741     bx = rect.left();
21742     by = rect.top();
21743     mu = (by-base.y())/vec.y();
21744     if (mu >= 0 && mu <= 1)
21745     {
21746       gamma = base.x()-bx + mu*vec.x();
21747       if (gamma >= 0 && gamma <= rect.width())
21748         pointVectors.append(QVector2D(bx+gamma, by));
21749     }
21750     // check bottom of rect:
21751     bx = rect.left();
21752     by = rect.bottom();
21753     mu = (by-base.y())/vec.y();
21754     if (mu >= 0 && mu <= 1)
21755     {
21756       gamma = base.x()-bx + mu*vec.x();
21757       if (gamma >= 0 && gamma <= rect.width())
21758         pointVectors.append(QVector2D(bx+gamma, by));
21759     }
21760   }
21761   if (!qFuzzyIsNull(vec.x())) // line is not vertical
21762   {
21763     // check left of rect:
21764     bx = rect.left();
21765     by = rect.top();
21766     mu = (bx-base.x())/vec.x();
21767     if (mu >= 0 && mu <= 1)
21768     {
21769       gamma = base.y()-by + mu*vec.y();
21770       if (gamma >= 0 && gamma <= rect.height())
21771         pointVectors.append(QVector2D(bx, by+gamma));
21772     }
21773     // check right of rect:
21774     bx = rect.right();
21775     by = rect.top();
21776     mu = (bx-base.x())/vec.x();
21777     if (mu >= 0 && mu <= 1)
21778     {
21779       gamma = base.y()-by + mu*vec.y();
21780       if (gamma >= 0 && gamma <= rect.height())
21781         pointVectors.append(QVector2D(bx, by+gamma));
21782     }
21783   }
21784
21785   if (containsStart)
21786     pointVectors.append(start);
21787   if (containsEnd)
21788     pointVectors.append(end);
21789
21790   // evaluate points:
21791   if (pointVectors.size() == 2)
21792   {
21793     result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
21794   } else if (pointVectors.size() > 2)
21795   {
21796     // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
21797     double distSqrMax = 0;
21798     QVector2D pv1, pv2;
21799     for (int i=0; i<pointVectors.size()-1; ++i)
21800     {
21801       for (int k=i+1; k<pointVectors.size(); ++k)
21802       {
21803         double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
21804         if (distSqr > distSqrMax)
21805         {
21806           pv1 = pointVectors.at(i);
21807           pv2 = pointVectors.at(k);
21808           distSqrMax = distSqr;
21809         }
21810       }
21811     }
21812     result.setPoints(pv1.toPointF(), pv2.toPointF());
21813   }
21814   return result;
21815 }
21816
21817 /*! \internal
21818
21819   Returns the pen that should be used for drawing lines. Returns mPen when the
21820   item is not selected and mSelectedPen when it is.
21821 */
21822 QPen QCPItemLine::mainPen() const
21823 {
21824   return mSelected ? mSelectedPen : mPen;
21825 }
21826
21827
21828 ////////////////////////////////////////////////////////////////////////////////////////////////////
21829 //////////////////// QCPItemCurve
21830 ////////////////////////////////////////////////////////////////////////////////////////////////////
21831
21832 /*! \class QCPItemCurve
21833   \brief A curved line from one point to another
21834
21835   \image html QCPItemCurve.png "Curve example. Blue dotted circles are anchors, solid blue discs are positions."
21836
21837   It has four positions, \a start and \a end, which define the end points of the line, and two
21838   control points which define the direction the line exits from the start and the direction from
21839   which it approaches the end: \a startDir and \a endDir.
21840
21841   With \ref setHead and \ref setTail you may set different line ending styles, e.g. to create an
21842   arrow.
21843
21844   Often it is desirable for the control points to stay at fixed relative positions to the start/end
21845   point. This can be achieved by setting the parent anchor e.g. of \a startDir simply to \a start,
21846   and then specify the desired pixel offset with QCPItemPosition::setCoords on \a startDir.
21847 */
21848
21849 /*!
21850   Creates a curve item and sets default values.
21851
21852   The constructed item can be added to the plot with QCustomPlot::addItem.
21853 */
21854 QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) :
21855   QCPAbstractItem(parentPlot),
21856   start(createPosition(QLatin1String("start"))),
21857   startDir(createPosition(QLatin1String("startDir"))),
21858   endDir(createPosition(QLatin1String("endDir"))),
21859   end(createPosition(QLatin1String("end")))
21860 {
21861   start->setCoords(0, 0);
21862   startDir->setCoords(0.5, 0);
21863   endDir->setCoords(0, 0.5);
21864   end->setCoords(1, 1);
21865
21866   setPen(QPen(Qt::black));
21867   setSelectedPen(QPen(Qt::blue,2));
21868 }
21869
21870 QCPItemCurve::~QCPItemCurve()
21871 {
21872 }
21873
21874 /*!
21875   Sets the pen that will be used to draw the line
21876
21877   \see setSelectedPen
21878 */
21879 void QCPItemCurve::setPen(const QPen &pen)
21880 {
21881   mPen = pen;
21882 }
21883
21884 /*!
21885   Sets the pen that will be used to draw the line when selected
21886
21887   \see setPen, setSelected
21888 */
21889 void QCPItemCurve::setSelectedPen(const QPen &pen)
21890 {
21891   mSelectedPen = pen;
21892 }
21893
21894 /*!
21895   Sets the line ending style of the head. The head corresponds to the \a end position.
21896
21897   Note that due to the overloaded QCPLineEnding constructor, you may directly specify
21898   a QCPLineEnding::EndingStyle here, e.g. \code setHead(QCPLineEnding::esSpikeArrow) \endcode
21899
21900   \see setTail
21901 */
21902 void QCPItemCurve::setHead(const QCPLineEnding &head)
21903 {
21904   mHead = head;
21905 }
21906
21907 /*!
21908   Sets the line ending style of the tail. The tail corresponds to the \a start position.
21909
21910   Note that due to the overloaded QCPLineEnding constructor, you may directly specify
21911   a QCPLineEnding::EndingStyle here, e.g. \code setTail(QCPLineEnding::esSpikeArrow) \endcode
21912
21913   \see setHead
21914 */
21915 void QCPItemCurve::setTail(const QCPLineEnding &tail)
21916 {
21917   mTail = tail;
21918 }
21919
21920 /* inherits documentation from base class */
21921 double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21922 {
21923   Q_UNUSED(details)
21924   if (onlySelectable && !mSelectable)
21925     return -1;
21926
21927   QPointF startVec(start->pixelPoint());
21928   QPointF startDirVec(startDir->pixelPoint());
21929   QPointF endDirVec(endDir->pixelPoint());
21930   QPointF endVec(end->pixelPoint());
21931
21932   QPainterPath cubicPath(startVec);
21933   cubicPath.cubicTo(startDirVec, endDirVec, endVec);
21934
21935   QPolygonF polygon = cubicPath.toSubpathPolygons().first();
21936   double minDistSqr = std::numeric_limits<double>::max();
21937   for (int i=1; i<polygon.size(); ++i)
21938   {
21939     double distSqr = distSqrToLine(polygon.at(i-1), polygon.at(i), pos);
21940     if (distSqr < minDistSqr)
21941       minDistSqr = distSqr;
21942   }
21943   return qSqrt(minDistSqr);
21944 }
21945
21946 /* inherits documentation from base class */
21947 void QCPItemCurve::draw(QCPPainter *painter)
21948 {
21949   QPointF startVec(start->pixelPoint());
21950   QPointF startDirVec(startDir->pixelPoint());
21951   QPointF endDirVec(endDir->pixelPoint());
21952   QPointF endVec(end->pixelPoint());
21953   if (QVector2D(endVec-startVec).length() > 1e10f) // too large curves cause crash
21954     return;
21955
21956   QPainterPath cubicPath(startVec);
21957   cubicPath.cubicTo(startDirVec, endDirVec, endVec);
21958
21959   // paint visible segment, if existent:
21960   QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
21961   QRect cubicRect = cubicPath.controlPointRect().toRect();
21962   if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position
21963     cubicRect.adjust(0, 0, 1, 1);
21964   if (clip.intersects(cubicRect))
21965   {
21966     painter->setPen(mainPen());
21967     painter->drawPath(cubicPath);
21968     painter->setBrush(Qt::SolidPattern);
21969     if (mTail.style() != QCPLineEnding::esNone)
21970       mTail.draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI);
21971     if (mHead.style() != QCPLineEnding::esNone)
21972       mHead.draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI);
21973   }
21974 }
21975
21976 /*! \internal
21977
21978   Returns the pen that should be used for drawing lines. Returns mPen when the
21979   item is not selected and mSelectedPen when it is.
21980 */
21981 QPen QCPItemCurve::mainPen() const
21982 {
21983   return mSelected ? mSelectedPen : mPen;
21984 }
21985
21986
21987 ////////////////////////////////////////////////////////////////////////////////////////////////////
21988 //////////////////// QCPItemRect
21989 ////////////////////////////////////////////////////////////////////////////////////////////////////
21990
21991 /*! \class QCPItemRect
21992   \brief A rectangle
21993
21994   \image html QCPItemRect.png "Rectangle example. Blue dotted circles are anchors, solid blue discs are positions."
21995
21996   It has two positions, \a topLeft and \a bottomRight, which define the rectangle.
21997 */
21998
21999 /*!
22000   Creates a rectangle item and sets default values.
22001
22002   The constructed item can be added to the plot with QCustomPlot::addItem.
22003 */
22004 QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) :
22005   QCPAbstractItem(parentPlot),
22006   topLeft(createPosition(QLatin1String("topLeft"))),
22007   bottomRight(createPosition(QLatin1String("bottomRight"))),
22008   top(createAnchor(QLatin1String("top"), aiTop)),
22009   topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22010   right(createAnchor(QLatin1String("right"), aiRight)),
22011   bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22012   bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22013   left(createAnchor(QLatin1String("left"), aiLeft))
22014 {
22015   topLeft->setCoords(0, 1);
22016   bottomRight->setCoords(1, 0);
22017
22018   setPen(QPen(Qt::black));
22019   setSelectedPen(QPen(Qt::blue,2));
22020   setBrush(Qt::NoBrush);
22021   setSelectedBrush(Qt::NoBrush);
22022 }
22023
22024 QCPItemRect::~QCPItemRect()
22025 {
22026 }
22027
22028 /*!
22029   Sets the pen that will be used to draw the line of the rectangle
22030
22031   \see setSelectedPen, setBrush
22032 */
22033 void QCPItemRect::setPen(const QPen &pen)
22034 {
22035   mPen = pen;
22036 }
22037
22038 /*!
22039   Sets the pen that will be used to draw the line of the rectangle when selected
22040
22041   \see setPen, setSelected
22042 */
22043 void QCPItemRect::setSelectedPen(const QPen &pen)
22044 {
22045   mSelectedPen = pen;
22046 }
22047
22048 /*!
22049   Sets the brush that will be used to fill the rectangle. To disable filling, set \a brush to
22050   Qt::NoBrush.
22051
22052   \see setSelectedBrush, setPen
22053 */
22054 void QCPItemRect::setBrush(const QBrush &brush)
22055 {
22056   mBrush = brush;
22057 }
22058
22059 /*!
22060   Sets the brush that will be used to fill the rectangle when selected. To disable filling, set \a
22061   brush to Qt::NoBrush.
22062
22063   \see setBrush
22064 */
22065 void QCPItemRect::setSelectedBrush(const QBrush &brush)
22066 {
22067   mSelectedBrush = brush;
22068 }
22069
22070 /* inherits documentation from base class */
22071 double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22072 {
22073   Q_UNUSED(details)
22074   if (onlySelectable && !mSelectable)
22075     return -1;
22076
22077   QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()).normalized();
22078   bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
22079   return rectSelectTest(rect, pos, filledRect);
22080 }
22081
22082 /* inherits documentation from base class */
22083 void QCPItemRect::draw(QCPPainter *painter)
22084 {
22085   QPointF p1 = topLeft->pixelPoint();
22086   QPointF p2 = bottomRight->pixelPoint();
22087   if (p1.toPoint() == p2.toPoint())
22088     return;
22089   QRectF rect = QRectF(p1, p2).normalized();
22090   double clipPad = mainPen().widthF();
22091   QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22092   if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect
22093   {
22094     painter->setPen(mainPen());
22095     painter->setBrush(mainBrush());
22096     painter->drawRect(rect);
22097   }
22098 }
22099
22100 /* inherits documentation from base class */
22101 QPointF QCPItemRect::anchorPixelPoint(int anchorId) const
22102 {
22103   QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint());
22104   switch (anchorId)
22105   {
22106     case aiTop:         return (rect.topLeft()+rect.topRight())*0.5;
22107     case aiTopRight:    return rect.topRight();
22108     case aiRight:       return (rect.topRight()+rect.bottomRight())*0.5;
22109     case aiBottom:      return (rect.bottomLeft()+rect.bottomRight())*0.5;
22110     case aiBottomLeft:  return rect.bottomLeft();
22111     case aiLeft:        return (rect.topLeft()+rect.bottomLeft())*0.5;
22112   }
22113
22114   qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22115   return QPointF();
22116 }
22117
22118 /*! \internal
22119
22120   Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected
22121   and mSelectedPen when it is.
22122 */
22123 QPen QCPItemRect::mainPen() const
22124 {
22125   return mSelected ? mSelectedPen : mPen;
22126 }
22127
22128 /*! \internal
22129
22130   Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item
22131   is not selected and mSelectedBrush when it is.
22132 */
22133 QBrush QCPItemRect::mainBrush() const
22134 {
22135   return mSelected ? mSelectedBrush : mBrush;
22136 }
22137
22138
22139 ////////////////////////////////////////////////////////////////////////////////////////////////////
22140 //////////////////// QCPItemText
22141 ////////////////////////////////////////////////////////////////////////////////////////////////////
22142
22143 /*! \class QCPItemText
22144   \brief A text label
22145
22146   \image html QCPItemText.png "Text example. Blue dotted circles are anchors, solid blue discs are positions."
22147
22148   Its position is defined by the member \a position and the setting of \ref setPositionAlignment.
22149   The latter controls which part of the text rect shall be aligned with \a position.
22150
22151   The text alignment itself (i.e. left, center, right) can be controlled with \ref
22152   setTextAlignment.
22153
22154   The text may be rotated around the \a position point with \ref setRotation.
22155 */
22156
22157 /*!
22158   Creates a text item and sets default values.
22159
22160   The constructed item can be added to the plot with QCustomPlot::addItem.
22161 */
22162 QCPItemText::QCPItemText(QCustomPlot *parentPlot) :
22163   QCPAbstractItem(parentPlot),
22164   position(createPosition(QLatin1String("position"))),
22165   topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)),
22166   top(createAnchor(QLatin1String("top"), aiTop)),
22167   topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22168   right(createAnchor(QLatin1String("right"), aiRight)),
22169   bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)),
22170   bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22171   bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22172   left(createAnchor(QLatin1String("left"), aiLeft))
22173 {
22174   position->setCoords(0, 0);
22175
22176   setRotation(0);
22177   setTextAlignment(Qt::AlignTop|Qt::AlignHCenter);
22178   setPositionAlignment(Qt::AlignCenter);
22179   setText(QLatin1String("text"));
22180
22181   setPen(Qt::NoPen);
22182   setSelectedPen(Qt::NoPen);
22183   setBrush(Qt::NoBrush);
22184   setSelectedBrush(Qt::NoBrush);
22185   setColor(Qt::black);
22186   setSelectedColor(Qt::blue);
22187 }
22188
22189 QCPItemText::~QCPItemText()
22190 {
22191 }
22192
22193 /*!
22194   Sets the color of the text.
22195 */
22196 void QCPItemText::setColor(const QColor &color)
22197 {
22198   mColor = color;
22199 }
22200
22201 /*!
22202   Sets the color of the text that will be used when the item is selected.
22203 */
22204 void QCPItemText::setSelectedColor(const QColor &color)
22205 {
22206   mSelectedColor = color;
22207 }
22208
22209 /*!
22210   Sets the pen that will be used do draw a rectangular border around the text. To disable the
22211   border, set \a pen to Qt::NoPen.
22212
22213   \see setSelectedPen, setBrush, setPadding
22214 */
22215 void QCPItemText::setPen(const QPen &pen)
22216 {
22217   mPen = pen;
22218 }
22219
22220 /*!
22221   Sets the pen that will be used do draw a rectangular border around the text, when the item is
22222   selected. To disable the border, set \a pen to Qt::NoPen.
22223
22224   \see setPen
22225 */
22226 void QCPItemText::setSelectedPen(const QPen &pen)
22227 {
22228   mSelectedPen = pen;
22229 }
22230
22231 /*!
22232   Sets the brush that will be used do fill the background of the text. To disable the
22233   background, set \a brush to Qt::NoBrush.
22234
22235   \see setSelectedBrush, setPen, setPadding
22236 */
22237 void QCPItemText::setBrush(const QBrush &brush)
22238 {
22239   mBrush = brush;
22240 }
22241
22242 /*!
22243   Sets the brush that will be used do fill the background of the text, when the item is selected. To disable the
22244   background, set \a brush to Qt::NoBrush.
22245
22246   \see setBrush
22247 */
22248 void QCPItemText::setSelectedBrush(const QBrush &brush)
22249 {
22250   mSelectedBrush = brush;
22251 }
22252
22253 /*!
22254   Sets the font of the text.
22255
22256   \see setSelectedFont, setColor
22257 */
22258 void QCPItemText::setFont(const QFont &font)
22259 {
22260   mFont = font;
22261 }
22262
22263 /*!
22264   Sets the font of the text that will be used when the item is selected.
22265
22266   \see setFont
22267 */
22268 void QCPItemText::setSelectedFont(const QFont &font)
22269 {
22270   mSelectedFont = font;
22271 }
22272
22273 /*!
22274   Sets the text that will be displayed. Multi-line texts are supported by inserting a line break
22275   character, e.g. '\n'.
22276
22277   \see setFont, setColor, setTextAlignment
22278 */
22279 void QCPItemText::setText(const QString &text)
22280 {
22281   mText = text;
22282 }
22283
22284 /*!
22285   Sets which point of the text rect shall be aligned with \a position.
22286
22287   Examples:
22288   \li If \a alignment is <tt>Qt::AlignHCenter | Qt::AlignTop</tt>, the text will be positioned such
22289   that the top of the text rect will be horizontally centered on \a position.
22290   \li If \a alignment is <tt>Qt::AlignLeft | Qt::AlignBottom</tt>, \a position will indicate the
22291   bottom left corner of the text rect.
22292
22293   If you want to control the alignment of (multi-lined) text within the text rect, use \ref
22294   setTextAlignment.
22295 */
22296 void QCPItemText::setPositionAlignment(Qt::Alignment alignment)
22297 {
22298   mPositionAlignment = alignment;
22299 }
22300
22301 /*!
22302   Controls how (multi-lined) text is aligned inside the text rect (typically Qt::AlignLeft, Qt::AlignCenter or Qt::AlignRight).
22303 */
22304 void QCPItemText::setTextAlignment(Qt::Alignment alignment)
22305 {
22306   mTextAlignment = alignment;
22307 }
22308
22309 /*!
22310   Sets the angle in degrees by which the text (and the text rectangle, if visible) will be rotated
22311   around \a position.
22312 */
22313 void QCPItemText::setRotation(double degrees)
22314 {
22315   mRotation = degrees;
22316 }
22317
22318 /*!
22319   Sets the distance between the border of the text rectangle and the text. The appearance (and
22320   visibility) of the text rectangle can be controlled with \ref setPen and \ref setBrush.
22321 */
22322 void QCPItemText::setPadding(const QMargins &padding)
22323 {
22324   mPadding = padding;
22325 }
22326
22327 /* inherits documentation from base class */
22328 double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22329 {
22330   Q_UNUSED(details)
22331   if (onlySelectable && !mSelectable)
22332     return -1;
22333
22334   // The rect may be rotated, so we transform the actual clicked pos to the rotated
22335   // coordinate system, so we can use the normal rectSelectTest function for non-rotated rects:
22336   QPointF positionPixels(position->pixelPoint());
22337   QTransform inputTransform;
22338   inputTransform.translate(positionPixels.x(), positionPixels.y());
22339   inputTransform.rotate(-mRotation);
22340   inputTransform.translate(-positionPixels.x(), -positionPixels.y());
22341   QPointF rotatedPos = inputTransform.map(pos);
22342   QFontMetrics fontMetrics(mFont);
22343   QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22344   QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22345   QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment);
22346   textBoxRect.moveTopLeft(textPos.toPoint());
22347
22348   return rectSelectTest(textBoxRect, rotatedPos, true);
22349 }
22350
22351 /* inherits documentation from base class */
22352 void QCPItemText::draw(QCPPainter *painter)
22353 {
22354   QPointF pos(position->pixelPoint());
22355   QTransform transform = painter->transform();
22356   transform.translate(pos.x(), pos.y());
22357   if (!qFuzzyIsNull(mRotation))
22358     transform.rotate(mRotation);
22359   painter->setFont(mainFont());
22360   QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22361   QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22362   QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
22363   textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top()));
22364   textBoxRect.moveTopLeft(textPos.toPoint());
22365   double clipPad = mainPen().widthF();
22366   QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22367   if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect())))
22368   {
22369     painter->setTransform(transform);
22370     if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) ||
22371         (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0))
22372     {
22373       painter->setPen(mainPen());
22374       painter->setBrush(mainBrush());
22375       painter->drawRect(textBoxRect);
22376     }
22377     painter->setBrush(Qt::NoBrush);
22378     painter->setPen(QPen(mainColor()));
22379     painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText);
22380   }
22381 }
22382
22383 /* inherits documentation from base class */
22384 QPointF QCPItemText::anchorPixelPoint(int anchorId) const
22385 {
22386   // get actual rect points (pretty much copied from draw function):
22387   QPointF pos(position->pixelPoint());
22388   QTransform transform;
22389   transform.translate(pos.x(), pos.y());
22390   if (!qFuzzyIsNull(mRotation))
22391     transform.rotate(mRotation);
22392   QFontMetrics fontMetrics(mainFont());
22393   QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22394   QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22395   QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
22396   textBoxRect.moveTopLeft(textPos.toPoint());
22397   QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect));
22398
22399   switch (anchorId)
22400   {
22401     case aiTopLeft:     return rectPoly.at(0);
22402     case aiTop:         return (rectPoly.at(0)+rectPoly.at(1))*0.5;
22403     case aiTopRight:    return rectPoly.at(1);
22404     case aiRight:       return (rectPoly.at(1)+rectPoly.at(2))*0.5;
22405     case aiBottomRight: return rectPoly.at(2);
22406     case aiBottom:      return (rectPoly.at(2)+rectPoly.at(3))*0.5;
22407     case aiBottomLeft:  return rectPoly.at(3);
22408     case aiLeft:        return (rectPoly.at(3)+rectPoly.at(0))*0.5;
22409   }
22410
22411   qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22412   return QPointF();
22413 }
22414
22415 /*! \internal
22416
22417   Returns the point that must be given to the QPainter::drawText function (which expects the top
22418   left point of the text rect), according to the position \a pos, the text bounding box \a rect and
22419   the requested \a positionAlignment.
22420
22421   For example, if \a positionAlignment is <tt>Qt::AlignLeft | Qt::AlignBottom</tt> the returned point
22422   will be shifted upward by the height of \a rect, starting from \a pos. So if the text is finally
22423   drawn at that point, the lower left corner of the resulting text rect is at \a pos.
22424 */
22425 QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const
22426 {
22427   if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop))
22428     return pos;
22429
22430   QPointF result = pos; // start at top left
22431   if (positionAlignment.testFlag(Qt::AlignHCenter))
22432     result.rx() -= rect.width()/2.0;
22433   else if (positionAlignment.testFlag(Qt::AlignRight))
22434     result.rx() -= rect.width();
22435   if (positionAlignment.testFlag(Qt::AlignVCenter))
22436     result.ry() -= rect.height()/2.0;
22437   else if (positionAlignment.testFlag(Qt::AlignBottom))
22438     result.ry() -= rect.height();
22439   return result;
22440 }
22441
22442 /*! \internal
22443
22444   Returns the font that should be used for drawing text. Returns mFont when the item is not selected
22445   and mSelectedFont when it is.
22446 */
22447 QFont QCPItemText::mainFont() const
22448 {
22449   return mSelected ? mSelectedFont : mFont;
22450 }
22451
22452 /*! \internal
22453
22454   Returns the color that should be used for drawing text. Returns mColor when the item is not
22455   selected and mSelectedColor when it is.
22456 */
22457 QColor QCPItemText::mainColor() const
22458 {
22459   return mSelected ? mSelectedColor : mColor;
22460 }
22461
22462 /*! \internal
22463
22464   Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected
22465   and mSelectedPen when it is.
22466 */
22467 QPen QCPItemText::mainPen() const
22468 {
22469   return mSelected ? mSelectedPen : mPen;
22470 }
22471
22472 /*! \internal
22473
22474   Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item
22475   is not selected and mSelectedBrush when it is.
22476 */
22477 QBrush QCPItemText::mainBrush() const
22478 {
22479   return mSelected ? mSelectedBrush : mBrush;
22480 }
22481
22482
22483 ////////////////////////////////////////////////////////////////////////////////////////////////////
22484 //////////////////// QCPItemEllipse
22485 ////////////////////////////////////////////////////////////////////////////////////////////////////
22486
22487 /*! \class QCPItemEllipse
22488   \brief An ellipse
22489
22490   \image html QCPItemEllipse.png "Ellipse example. Blue dotted circles are anchors, solid blue discs are positions."
22491
22492   It has two positions, \a topLeft and \a bottomRight, which define the rect the ellipse will be drawn in.
22493 */
22494
22495 /*!
22496   Creates an ellipse item and sets default values.
22497
22498   The constructed item can be added to the plot with QCustomPlot::addItem.
22499 */
22500 QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) :
22501   QCPAbstractItem(parentPlot),
22502   topLeft(createPosition(QLatin1String("topLeft"))),
22503   bottomRight(createPosition(QLatin1String("bottomRight"))),
22504   topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)),
22505   top(createAnchor(QLatin1String("top"), aiTop)),
22506   topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)),
22507   right(createAnchor(QLatin1String("right"), aiRight)),
22508   bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)),
22509   bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22510   bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)),
22511   left(createAnchor(QLatin1String("left"), aiLeft)),
22512   center(createAnchor(QLatin1String("center"), aiCenter))
22513 {
22514   topLeft->setCoords(0, 1);
22515   bottomRight->setCoords(1, 0);
22516
22517   setPen(QPen(Qt::black));
22518   setSelectedPen(QPen(Qt::blue, 2));
22519   setBrush(Qt::NoBrush);
22520   setSelectedBrush(Qt::NoBrush);
22521 }
22522
22523 QCPItemEllipse::~QCPItemEllipse()
22524 {
22525 }
22526
22527 /*!
22528   Sets the pen that will be used to draw the line of the ellipse
22529
22530   \see setSelectedPen, setBrush
22531 */
22532 void QCPItemEllipse::setPen(const QPen &pen)
22533 {
22534   mPen = pen;
22535 }
22536
22537 /*!
22538   Sets the pen that will be used to draw the line of the ellipse when selected
22539
22540   \see setPen, setSelected
22541 */
22542 void QCPItemEllipse::setSelectedPen(const QPen &pen)
22543 {
22544   mSelectedPen = pen;
22545 }
22546
22547 /*!
22548   Sets the brush that will be used to fill the ellipse. To disable filling, set \a brush to
22549   Qt::NoBrush.
22550
22551   \see setSelectedBrush, setPen
22552 */
22553 void QCPItemEllipse::setBrush(const QBrush &brush)
22554 {
22555   mBrush = brush;
22556 }
22557
22558 /*!
22559   Sets the brush that will be used to fill the ellipse when selected. To disable filling, set \a
22560   brush to Qt::NoBrush.
22561
22562   \see setBrush
22563 */
22564 void QCPItemEllipse::setSelectedBrush(const QBrush &brush)
22565 {
22566   mSelectedBrush = brush;
22567 }
22568
22569 /* inherits documentation from base class */
22570 double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22571 {
22572   Q_UNUSED(details)
22573   if (onlySelectable && !mSelectable)
22574     return -1;
22575
22576   double result = -1;
22577   QPointF p1 = topLeft->pixelPoint();
22578   QPointF p2 = bottomRight->pixelPoint();
22579   QPointF center((p1+p2)/2.0);
22580   double a = qAbs(p1.x()-p2.x())/2.0;
22581   double b = qAbs(p1.y()-p2.y())/2.0;
22582   double x = pos.x()-center.x();
22583   double y = pos.y()-center.y();
22584
22585   // distance to border:
22586   double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b));
22587   result = qAbs(c-1)*qSqrt(x*x+y*y);
22588   // filled ellipse, allow click inside to count as hit:
22589   if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
22590   {
22591     if (x*x/(a*a) + y*y/(b*b) <= 1)
22592       result = mParentPlot->selectionTolerance()*0.99;
22593   }
22594   return result;
22595 }
22596
22597 /* inherits documentation from base class */
22598 void QCPItemEllipse::draw(QCPPainter *painter)
22599 {
22600   QPointF p1 = topLeft->pixelPoint();
22601   QPointF p2 = bottomRight->pixelPoint();
22602   if (p1.toPoint() == p2.toPoint())
22603     return;
22604   QRectF ellipseRect = QRectF(p1, p2).normalized();
22605   QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
22606   if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect
22607   {
22608     painter->setPen(mainPen());
22609     painter->setBrush(mainBrush());
22610 #ifdef __EXCEPTIONS
22611     try // drawEllipse sometimes throws exceptions if ellipse is too big
22612     {
22613 #endif
22614       painter->drawEllipse(ellipseRect);
22615 #ifdef __EXCEPTIONS
22616     } catch (...)
22617     {
22618       qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible";
22619       setVisible(false);
22620     }
22621 #endif
22622   }
22623 }
22624
22625 /* inherits documentation from base class */
22626 QPointF QCPItemEllipse::anchorPixelPoint(int anchorId) const
22627 {
22628   QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint());
22629   switch (anchorId)
22630   {
22631     case aiTopLeftRim:     return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2);
22632     case aiTop:            return (rect.topLeft()+rect.topRight())*0.5;
22633     case aiTopRightRim:    return rect.center()+(rect.topRight()-rect.center())*1/qSqrt(2);
22634     case aiRight:          return (rect.topRight()+rect.bottomRight())*0.5;
22635     case aiBottomRightRim: return rect.center()+(rect.bottomRight()-rect.center())*1/qSqrt(2);
22636     case aiBottom:         return (rect.bottomLeft()+rect.bottomRight())*0.5;
22637     case aiBottomLeftRim:  return rect.center()+(rect.bottomLeft()-rect.center())*1/qSqrt(2);
22638     case aiLeft:           return (rect.topLeft()+rect.bottomLeft())*0.5;
22639     case aiCenter:         return (rect.topLeft()+rect.bottomRight())*0.5;
22640   }
22641
22642   qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22643   return QPointF();
22644 }
22645
22646 /*! \internal
22647
22648   Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected
22649   and mSelectedPen when it is.
22650 */
22651 QPen QCPItemEllipse::mainPen() const
22652 {
22653   return mSelected ? mSelectedPen : mPen;
22654 }
22655
22656 /*! \internal
22657
22658   Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item
22659   is not selected and mSelectedBrush when it is.
22660 */
22661 QBrush QCPItemEllipse::mainBrush() const
22662 {
22663   return mSelected ? mSelectedBrush : mBrush;
22664 }
22665
22666
22667 ////////////////////////////////////////////////////////////////////////////////////////////////////
22668 //////////////////// QCPItemPixmap
22669 ////////////////////////////////////////////////////////////////////////////////////////////////////
22670
22671 /*! \class QCPItemPixmap
22672   \brief An arbitrary pixmap
22673
22674   \image html QCPItemPixmap.png "Pixmap example. Blue dotted circles are anchors, solid blue discs are positions."
22675
22676   It has two positions, \a topLeft and \a bottomRight, which define the rectangle the pixmap will
22677   be drawn in. Depending on the scale setting (\ref setScaled), the pixmap will be either scaled to
22678   fit the rectangle or be drawn aligned to the topLeft position.
22679
22680   If scaling is enabled and \a topLeft is further to the bottom/right than \a bottomRight (as shown
22681   on the right side of the example image), the pixmap will be flipped in the respective
22682   orientations.
22683 */
22684
22685 /*!
22686   Creates a rectangle item and sets default values.
22687
22688   The constructed item can be added to the plot with QCustomPlot::addItem.
22689 */
22690 QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) :
22691   QCPAbstractItem(parentPlot),
22692   topLeft(createPosition(QLatin1String("topLeft"))),
22693   bottomRight(createPosition(QLatin1String("bottomRight"))),
22694   top(createAnchor(QLatin1String("top"), aiTop)),
22695   topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22696   right(createAnchor(QLatin1String("right"), aiRight)),
22697   bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22698   bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22699   left(createAnchor(QLatin1String("left"), aiLeft))
22700 {
22701   topLeft->setCoords(0, 1);
22702   bottomRight->setCoords(1, 0);
22703
22704   setPen(Qt::NoPen);
22705   setSelectedPen(QPen(Qt::blue));
22706   setScaled(false, Qt::KeepAspectRatio, Qt::SmoothTransformation);
22707 }
22708
22709 QCPItemPixmap::~QCPItemPixmap()
22710 {
22711 }
22712
22713 /*!
22714   Sets the pixmap that will be displayed.
22715 */
22716 void QCPItemPixmap::setPixmap(const QPixmap &pixmap)
22717 {
22718   mPixmap = pixmap;
22719   if (mPixmap.isNull())
22720     qDebug() << Q_FUNC_INFO << "pixmap is null";
22721 }
22722
22723 /*!
22724   Sets whether the pixmap will be scaled to fit the rectangle defined by the \a topLeft and \a
22725   bottomRight positions.
22726 */
22727 void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode)
22728 {
22729   mScaled = scaled;
22730   mAspectRatioMode = aspectRatioMode;
22731   mTransformationMode = transformationMode;
22732   updateScaledPixmap();
22733 }
22734
22735 /*!
22736   Sets the pen that will be used to draw a border around the pixmap.
22737
22738   \see setSelectedPen, setBrush
22739 */
22740 void QCPItemPixmap::setPen(const QPen &pen)
22741 {
22742   mPen = pen;
22743 }
22744
22745 /*!
22746   Sets the pen that will be used to draw a border around the pixmap when selected
22747
22748   \see setPen, setSelected
22749 */
22750 void QCPItemPixmap::setSelectedPen(const QPen &pen)
22751 {
22752   mSelectedPen = pen;
22753 }
22754
22755 /* inherits documentation from base class */
22756 double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22757 {
22758   Q_UNUSED(details)
22759   if (onlySelectable && !mSelectable)
22760     return -1;
22761
22762   return rectSelectTest(getFinalRect(), pos, true);
22763 }
22764
22765 /* inherits documentation from base class */
22766 void QCPItemPixmap::draw(QCPPainter *painter)
22767 {
22768   bool flipHorz = false;
22769   bool flipVert = false;
22770   QRect rect = getFinalRect(&flipHorz, &flipVert);
22771   double clipPad = mainPen().style() == Qt::NoPen ? 0 : mainPen().widthF();
22772   QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22773   if (boundingRect.intersects(clipRect()))
22774   {
22775     updateScaledPixmap(rect, flipHorz, flipVert);
22776     painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap);
22777     QPen pen = mainPen();
22778     if (pen.style() != Qt::NoPen)
22779     {
22780       painter->setPen(pen);
22781       painter->setBrush(Qt::NoBrush);
22782       painter->drawRect(rect);
22783     }
22784   }
22785 }
22786
22787 /* inherits documentation from base class */
22788 QPointF QCPItemPixmap::anchorPixelPoint(int anchorId) const
22789 {
22790   bool flipHorz;
22791   bool flipVert;
22792   QRect rect = getFinalRect(&flipHorz, &flipVert);
22793   // we actually want denormal rects (negative width/height) here, so restore
22794   // the flipped state:
22795   if (flipHorz)
22796     rect.adjust(rect.width(), 0, -rect.width(), 0);
22797   if (flipVert)
22798     rect.adjust(0, rect.height(), 0, -rect.height());
22799
22800   switch (anchorId)
22801   {
22802     case aiTop:         return (rect.topLeft()+rect.topRight())*0.5;
22803     case aiTopRight:    return rect.topRight();
22804     case aiRight:       return (rect.topRight()+rect.bottomRight())*0.5;
22805     case aiBottom:      return (rect.bottomLeft()+rect.bottomRight())*0.5;
22806     case aiBottomLeft:  return rect.bottomLeft();
22807     case aiLeft:        return (rect.topLeft()+rect.bottomLeft())*0.5;;
22808   }
22809
22810   qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22811   return QPointF();
22812 }
22813
22814 /*! \internal
22815
22816   Creates the buffered scaled image (\a mScaledPixmap) to fit the specified \a finalRect. The
22817   parameters \a flipHorz and \a flipVert control whether the resulting image shall be flipped
22818   horizontally or vertically. (This is used when \a topLeft is further to the bottom/right than \a
22819   bottomRight.)
22820
22821   This function only creates the scaled pixmap when the buffered pixmap has a different size than
22822   the expected result, so calling this function repeatedly, e.g. in the \ref draw function, does
22823   not cause expensive rescaling every time.
22824
22825   If scaling is disabled, sets mScaledPixmap to a null QPixmap.
22826 */
22827 void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert)
22828 {
22829   if (mPixmap.isNull())
22830     return;
22831
22832   if (mScaled)
22833   {
22834     if (finalRect.isNull())
22835       finalRect = getFinalRect(&flipHorz, &flipVert);
22836     if (finalRect.size() != mScaledPixmap.size())
22837     {
22838       mScaledPixmap = mPixmap.scaled(finalRect.size(), mAspectRatioMode, mTransformationMode);
22839       if (flipHorz || flipVert)
22840         mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert));
22841     }
22842   } else if (!mScaledPixmap.isNull())
22843     mScaledPixmap = QPixmap();
22844 }
22845
22846 /*! \internal
22847
22848   Returns the final (tight) rect the pixmap is drawn in, depending on the current item positions
22849   and scaling settings.
22850
22851   The output parameters \a flippedHorz and \a flippedVert return whether the pixmap should be drawn
22852   flipped horizontally or vertically in the returned rect. (The returned rect itself is always
22853   normalized, i.e. the top left corner of the rect is actually further to the top/left than the
22854   bottom right corner). This is the case when the item position \a topLeft is further to the
22855   bottom/right than \a bottomRight.
22856
22857   If scaling is disabled, returns a rect with size of the original pixmap and the top left corner
22858   aligned with the item position \a topLeft. The position \a bottomRight is ignored.
22859 */
22860 QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const
22861 {
22862   QRect result;
22863   bool flipHorz = false;
22864   bool flipVert = false;
22865   QPoint p1 = topLeft->pixelPoint().toPoint();
22866   QPoint p2 = bottomRight->pixelPoint().toPoint();
22867   if (p1 == p2)
22868     return QRect(p1, QSize(0, 0));
22869   if (mScaled)
22870   {
22871     QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y());
22872     QPoint topLeft = p1;
22873     if (newSize.width() < 0)
22874     {
22875       flipHorz = true;
22876       newSize.rwidth() *= -1;
22877       topLeft.setX(p2.x());
22878     }
22879     if (newSize.height() < 0)
22880     {
22881       flipVert = true;
22882       newSize.rheight() *= -1;
22883       topLeft.setY(p2.y());
22884     }
22885     QSize scaledSize = mPixmap.size();
22886     scaledSize.scale(newSize, mAspectRatioMode);
22887     result = QRect(topLeft, scaledSize);
22888   } else
22889   {
22890     result = QRect(p1, mPixmap.size());
22891   }
22892   if (flippedHorz)
22893     *flippedHorz = flipHorz;
22894   if (flippedVert)
22895     *flippedVert = flipVert;
22896   return result;
22897 }
22898
22899 /*! \internal
22900
22901   Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected
22902   and mSelectedPen when it is.
22903 */
22904 QPen QCPItemPixmap::mainPen() const
22905 {
22906   return mSelected ? mSelectedPen : mPen;
22907 }
22908
22909
22910 ////////////////////////////////////////////////////////////////////////////////////////////////////
22911 //////////////////// QCPItemTracer
22912 ////////////////////////////////////////////////////////////////////////////////////////////////////
22913
22914 /*! \class QCPItemTracer
22915   \brief Item that sticks to QCPGraph data points
22916
22917   \image html QCPItemTracer.png "Tracer example. Blue dotted circles are anchors, solid blue discs are positions."
22918
22919   The tracer can be connected with a QCPGraph via \ref setGraph. Then it will automatically adopt
22920   the coordinate axes of the graph and update its \a position to be on the graph's data. This means
22921   the key stays controllable via \ref setGraphKey, but the value will follow the graph data. If a
22922   QCPGraph is connected, note that setting the coordinates of the tracer item directly via \a
22923   position will have no effect because they will be overriden in the next redraw (this is when the
22924   coordinate update happens).
22925
22926   If the specified key in \ref setGraphKey is outside the key bounds of the graph, the tracer will
22927   stay at the corresponding end of the graph.
22928
22929   With \ref setInterpolating you may specify whether the tracer may only stay exactly on data
22930   points or whether it interpolates data points linearly, if given a key that lies between two data
22931   points of the graph.
22932
22933   The tracer has different visual styles, see \ref setStyle. It is also possible to make the tracer
22934   have no own visual appearance (set the style to \ref tsNone), and just connect other item
22935   positions to the tracer \a position (used as an anchor) via \ref
22936   QCPItemPosition::setParentAnchor.
22937
22938   \note The tracer position is only automatically updated upon redraws. So when the data of the
22939   graph changes and immediately afterwards (without a redraw) the a position coordinates of the
22940   tracer are retrieved, they will not reflect the updated data of the graph. In this case \ref
22941   updatePosition must be called manually, prior to reading the tracer coordinates.
22942 */
22943
22944 /*!
22945   Creates a tracer item and sets default values.
22946
22947   The constructed item can be added to the plot with QCustomPlot::addItem.
22948 */
22949 QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) :
22950   QCPAbstractItem(parentPlot),
22951   position(createPosition(QLatin1String("position"))),
22952   mGraph(0)
22953 {
22954   position->setCoords(0, 0);
22955
22956   setBrush(Qt::NoBrush);
22957   setSelectedBrush(Qt::NoBrush);
22958   setPen(QPen(Qt::black));
22959   setSelectedPen(QPen(Qt::blue, 2));
22960   setStyle(tsCrosshair);
22961   setSize(6);
22962   setInterpolating(false);
22963   setGraphKey(0);
22964 }
22965
22966 QCPItemTracer::~QCPItemTracer()
22967 {
22968 }
22969
22970 /*!
22971   Sets the pen that will be used to draw the line of the tracer
22972
22973   \see setSelectedPen, setBrush
22974 */
22975 void QCPItemTracer::setPen(const QPen &pen)
22976 {
22977   mPen = pen;
22978 }
22979
22980 /*!
22981   Sets the pen that will be used to draw the line of the tracer when selected
22982
22983   \see setPen, setSelected
22984 */
22985 void QCPItemTracer::setSelectedPen(const QPen &pen)
22986 {
22987   mSelectedPen = pen;
22988 }
22989
22990 /*!
22991   Sets the brush that will be used to draw any fills of the tracer
22992
22993   \see setSelectedBrush, setPen
22994 */
22995 void QCPItemTracer::setBrush(const QBrush &brush)
22996 {
22997   mBrush = brush;
22998 }
22999
23000 /*!
23001   Sets the brush that will be used to draw any fills of the tracer, when selected.
23002
23003   \see setBrush, setSelected
23004 */
23005 void QCPItemTracer::setSelectedBrush(const QBrush &brush)
23006 {
23007   mSelectedBrush = brush;
23008 }
23009
23010 /*!
23011   Sets the size of the tracer in pixels, if the style supports setting a size (e.g. \ref tsSquare
23012   does, \ref tsCrosshair does not).
23013 */
23014 void QCPItemTracer::setSize(double size)
23015 {
23016   mSize = size;
23017 }
23018
23019 /*!
23020   Sets the style/visual appearance of the tracer.
23021
23022   If you only want to use the tracer \a position as an anchor for other items, set \a style to
23023   \ref tsNone.
23024 */
23025 void QCPItemTracer::setStyle(QCPItemTracer::TracerStyle style)
23026 {
23027   mStyle = style;
23028 }
23029
23030 /*!
23031   Sets the QCPGraph this tracer sticks to. The tracer \a position will be set to type
23032   QCPItemPosition::ptPlotCoords and the axes will be set to the axes of \a graph.
23033
23034   To free the tracer from any graph, set \a graph to 0. The tracer \a position can then be placed
23035   freely like any other item position. This is the state the tracer will assume when its graph gets
23036   deleted while still attached to it.
23037
23038   \see setGraphKey
23039 */
23040 void QCPItemTracer::setGraph(QCPGraph *graph)
23041 {
23042   if (graph)
23043   {
23044     if (graph->parentPlot() == mParentPlot)
23045     {
23046       position->setType(QCPItemPosition::ptPlotCoords);
23047       position->setAxes(graph->keyAxis(), graph->valueAxis());
23048       mGraph = graph;
23049       updatePosition();
23050     } else
23051       qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item";
23052   } else
23053   {
23054     mGraph = 0;
23055   }
23056 }
23057
23058 /*!
23059   Sets the key of the graph's data point the tracer will be positioned at. This is the only free
23060   coordinate of a tracer when attached to a graph.
23061
23062   Depending on \ref setInterpolating, the tracer will be either positioned on the data point
23063   closest to \a key, or will stay exactly at \a key and interpolate the value linearly.
23064
23065   \see setGraph, setInterpolating
23066 */
23067 void QCPItemTracer::setGraphKey(double key)
23068 {
23069   mGraphKey = key;
23070 }
23071
23072 /*!
23073   Sets whether the value of the graph's data points shall be interpolated, when positioning the
23074   tracer.
23075
23076   If \a enabled is set to false and a key is given with \ref setGraphKey, the tracer is placed on
23077   the data point of the graph which is closest to the key, but which is not necessarily exactly
23078   there. If \a enabled is true, the tracer will be positioned exactly at the specified key, and
23079   the appropriate value will be interpolated from the graph's data points linearly.
23080
23081   \see setGraph, setGraphKey
23082 */
23083 void QCPItemTracer::setInterpolating(bool enabled)
23084 {
23085   mInterpolating = enabled;
23086 }
23087
23088 /* inherits documentation from base class */
23089 double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23090 {
23091   Q_UNUSED(details)
23092   if (onlySelectable && !mSelectable)
23093     return -1;
23094
23095   QPointF center(position->pixelPoint());
23096   double w = mSize/2.0;
23097   QRect clip = clipRect();
23098   switch (mStyle)
23099   {
23100     case tsNone: return -1;
23101     case tsPlus:
23102     {
23103       if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23104         return qSqrt(qMin(distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos),
23105                           distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos)));
23106       break;
23107     }
23108     case tsCrosshair:
23109     {
23110       return qSqrt(qMin(distSqrToLine(QPointF(clip.left(), center.y()), QPointF(clip.right(), center.y()), pos),
23111                         distSqrToLine(QPointF(center.x(), clip.top()), QPointF(center.x(), clip.bottom()), pos)));
23112     }
23113     case tsCircle:
23114     {
23115       if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23116       {
23117         // distance to border:
23118         double centerDist = QVector2D(center-pos).length();
23119         double circleLine = w;
23120         double result = qAbs(centerDist-circleLine);
23121         // filled ellipse, allow click inside to count as hit:
23122         if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
23123         {
23124           if (centerDist <= circleLine)
23125             result = mParentPlot->selectionTolerance()*0.99;
23126         }
23127         return result;
23128       }
23129       break;
23130     }
23131     case tsSquare:
23132     {
23133       if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23134       {
23135         QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w));
23136         bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
23137         return rectSelectTest(rect, pos, filledRect);
23138       }
23139       break;
23140     }
23141   }
23142   return -1;
23143 }
23144
23145 /* inherits documentation from base class */
23146 void QCPItemTracer::draw(QCPPainter *painter)
23147 {
23148   updatePosition();
23149   if (mStyle == tsNone)
23150     return;
23151
23152   painter->setPen(mainPen());
23153   painter->setBrush(mainBrush());
23154   QPointF center(position->pixelPoint());
23155   double w = mSize/2.0;
23156   QRect clip = clipRect();
23157   switch (mStyle)
23158   {
23159     case tsNone: return;
23160     case tsPlus:
23161     {
23162       if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23163       {
23164         painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0)));
23165         painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w)));
23166       }
23167       break;
23168     }
23169     case tsCrosshair:
23170     {
23171       if (center.y() > clip.top() && center.y() < clip.bottom())
23172         painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y()));
23173       if (center.x() > clip.left() && center.x() < clip.right())
23174         painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom()));
23175       break;
23176     }
23177     case tsCircle:
23178     {
23179       if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23180         painter->drawEllipse(center, w, w);
23181       break;
23182     }
23183     case tsSquare:
23184     {
23185       if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23186         painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w)));
23187       break;
23188     }
23189   }
23190 }
23191
23192 /*!
23193   If the tracer is connected with a graph (\ref setGraph), this function updates the tracer's \a
23194   position to reside on the graph data, depending on the configured key (\ref setGraphKey).
23195
23196   It is called automatically on every redraw and normally doesn't need to be called manually. One
23197   exception is when you want to read the tracer coordinates via \a position and are not sure that
23198   the graph's data (or the tracer key with \ref setGraphKey) hasn't changed since the last redraw.
23199   In that situation, call this function before accessing \a position, to make sure you don't get
23200   out-of-date coordinates.
23201
23202   If there is no graph set on this tracer, this function does nothing.
23203 */
23204 void QCPItemTracer::updatePosition()
23205 {
23206   if (mGraph)
23207   {
23208     if (mParentPlot->hasPlottable(mGraph))
23209     {
23210       if (mGraph->data()->size() > 1)
23211       {
23212         QCPDataMap::const_iterator first = mGraph->data()->constBegin();
23213         QCPDataMap::const_iterator last = mGraph->data()->constEnd()-1;
23214         if (mGraphKey < first.key())
23215           position->setCoords(first.key(), first.value().value);
23216         else if (mGraphKey > last.key())
23217           position->setCoords(last.key(), last.value().value);
23218         else
23219         {
23220           QCPDataMap::const_iterator it = mGraph->data()->lowerBound(mGraphKey);
23221           if (it != first) // mGraphKey is somewhere between iterators
23222           {
23223             QCPDataMap::const_iterator prevIt = it-1;
23224             if (mInterpolating)
23225             {
23226               // interpolate between iterators around mGraphKey:
23227               double slope = 0;
23228               if (!qFuzzyCompare((double)it.key(), (double)prevIt.key()))
23229                 slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key());
23230               position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value);
23231             } else
23232             {
23233               // find iterator with key closest to mGraphKey:
23234               if (mGraphKey < (prevIt.key()+it.key())*0.5)
23235                 it = prevIt;
23236               position->setCoords(it.key(), it.value().value);
23237             }
23238           } else // mGraphKey is exactly on first iterator
23239             position->setCoords(it.key(), it.value().value);
23240         }
23241       } else if (mGraph->data()->size() == 1)
23242       {
23243         QCPDataMap::const_iterator it = mGraph->data()->constBegin();
23244         position->setCoords(it.key(), it.value().value);
23245       } else
23246         qDebug() << Q_FUNC_INFO << "graph has no data";
23247     } else
23248       qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)";
23249   }
23250 }
23251
23252 /*! \internal
23253
23254   Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected
23255   and mSelectedPen when it is.
23256 */
23257 QPen QCPItemTracer::mainPen() const
23258 {
23259   return mSelected ? mSelectedPen : mPen;
23260 }
23261
23262 /*! \internal
23263
23264   Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item
23265   is not selected and mSelectedBrush when it is.
23266 */
23267 QBrush QCPItemTracer::mainBrush() const
23268 {
23269   return mSelected ? mSelectedBrush : mBrush;
23270 }
23271
23272
23273 ////////////////////////////////////////////////////////////////////////////////////////////////////
23274 //////////////////// QCPItemBracket
23275 ////////////////////////////////////////////////////////////////////////////////////////////////////
23276
23277 /*! \class QCPItemBracket
23278   \brief A bracket for referencing/highlighting certain parts in the plot.
23279
23280   \image html QCPItemBracket.png "Bracket example. Blue dotted circles are anchors, solid blue discs are positions."
23281
23282   It has two positions, \a left and \a right, which define the span of the bracket. If \a left is
23283   actually farther to the left than \a right, the bracket is opened to the bottom, as shown in the
23284   example image.
23285
23286   The bracket supports multiple styles via \ref setStyle. The length, i.e. how far the bracket
23287   stretches away from the embraced span, can be controlled with \ref setLength.
23288
23289   \image html QCPItemBracket-length.png
23290   <center>Demonstrating the effect of different values for \ref setLength, for styles \ref
23291   bsCalligraphic and \ref bsSquare. Anchors and positions are displayed for reference.</center>
23292
23293   It provides an anchor \a center, to allow connection of other items, e.g. an arrow (QCPItemLine
23294   or QCPItemCurve) or a text label (QCPItemText), to the bracket.
23295 */
23296
23297 /*!
23298   Creates a bracket item and sets default values.
23299
23300   The constructed item can be added to the plot with QCustomPlot::addItem.
23301 */
23302 QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) :
23303   QCPAbstractItem(parentPlot),
23304   left(createPosition(QLatin1String("left"))),
23305   right(createPosition(QLatin1String("right"))),
23306   center(createAnchor(QLatin1String("center"), aiCenter))
23307 {
23308   left->setCoords(0, 0);
23309   right->setCoords(1, 1);
23310
23311   setPen(QPen(Qt::black));
23312   setSelectedPen(QPen(Qt::blue, 2));
23313   setLength(8);
23314   setStyle(bsCalligraphic);
23315 }
23316
23317 QCPItemBracket::~QCPItemBracket()
23318 {
23319 }
23320
23321 /*!
23322   Sets the pen that will be used to draw the bracket.
23323
23324   Note that when the style is \ref bsCalligraphic, only the color will be taken from the pen, the
23325   stroke and width are ignored. To change the apparent stroke width of a calligraphic bracket, use
23326   \ref setLength, which has a similar effect.
23327
23328   \see setSelectedPen
23329 */
23330 void QCPItemBracket::setPen(const QPen &pen)
23331 {
23332   mPen = pen;
23333 }
23334
23335 /*!
23336   Sets the pen that will be used to draw the bracket when selected
23337
23338   \see setPen, setSelected
23339 */
23340 void QCPItemBracket::setSelectedPen(const QPen &pen)
23341 {
23342   mSelectedPen = pen;
23343 }
23344
23345 /*!
23346   Sets the \a length in pixels how far the bracket extends in the direction towards the embraced
23347   span of the bracket (i.e. perpendicular to the <i>left</i>-<i>right</i>-direction)
23348
23349   \image html QCPItemBracket-length.png
23350   <center>Demonstrating the effect of different values for \ref setLength, for styles \ref
23351   bsCalligraphic and \ref bsSquare. Anchors and positions are displayed for reference.</center>
23352 */
23353 void QCPItemBracket::setLength(double length)
23354 {
23355   mLength = length;
23356 }
23357
23358 /*!
23359   Sets the style of the bracket, i.e. the shape/visual appearance.
23360
23361   \see setPen
23362 */
23363 void QCPItemBracket::setStyle(QCPItemBracket::BracketStyle style)
23364 {
23365   mStyle = style;
23366 }
23367
23368 /* inherits documentation from base class */
23369 double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23370 {
23371   Q_UNUSED(details)
23372   if (onlySelectable && !mSelectable)
23373     return -1;
23374
23375   QVector2D leftVec(left->pixelPoint());
23376   QVector2D rightVec(right->pixelPoint());
23377   if (leftVec.toPoint() == rightVec.toPoint())
23378     return -1;
23379
23380   QVector2D widthVec = (rightVec-leftVec)*0.5f;
23381   QVector2D lengthVec(-widthVec.y(), widthVec.x());
23382   lengthVec = lengthVec.normalized()*mLength;
23383   QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23384
23385   return qSqrt(distSqrToLine((centerVec-widthVec).toPointF(), (centerVec+widthVec).toPointF(), pos));
23386 }
23387
23388 /* inherits documentation from base class */
23389 void QCPItemBracket::draw(QCPPainter *painter)
23390 {
23391   QVector2D leftVec(left->pixelPoint());
23392   QVector2D rightVec(right->pixelPoint());
23393   if (leftVec.toPoint() == rightVec.toPoint())
23394     return;
23395
23396   QVector2D widthVec = (rightVec-leftVec)*0.5f;
23397   QVector2D lengthVec(-widthVec.y(), widthVec.x());
23398   lengthVec = lengthVec.normalized()*mLength;
23399   QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23400
23401   QPolygon boundingPoly;
23402   boundingPoly << leftVec.toPoint() << rightVec.toPoint()
23403                << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint();
23404   QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
23405   if (clip.intersects(boundingPoly.boundingRect()))
23406   {
23407     painter->setPen(mainPen());
23408     switch (mStyle)
23409     {
23410       case bsSquare:
23411       {
23412         painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF());
23413         painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
23414         painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23415         break;
23416       }
23417       case bsRound:
23418       {
23419         painter->setBrush(Qt::NoBrush);
23420         QPainterPath path;
23421         path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23422         path.cubicTo((centerVec+widthVec).toPointF(), (centerVec+widthVec).toPointF(), centerVec.toPointF());
23423         path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23424         painter->drawPath(path);
23425         break;
23426       }
23427       case bsCurly:
23428       {
23429         painter->setBrush(Qt::NoBrush);
23430         QPainterPath path;
23431         path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23432         path.cubicTo((centerVec+widthVec-lengthVec*0.8f).toPointF(), (centerVec+0.4f*widthVec+lengthVec).toPointF(), centerVec.toPointF());
23433         path.cubicTo((centerVec-0.4f*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23434         painter->drawPath(path);
23435         break;
23436       }
23437       case bsCalligraphic:
23438       {
23439         painter->setPen(Qt::NoPen);
23440         painter->setBrush(QBrush(mainPen().color()));
23441         QPainterPath path;
23442         path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23443
23444         path.cubicTo((centerVec+widthVec-lengthVec*0.8f).toPointF(), (centerVec+0.4f*widthVec+0.8f*lengthVec).toPointF(), centerVec.toPointF());
23445         path.cubicTo((centerVec-0.4f*widthVec+0.8f*lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23446
23447         path.cubicTo((centerVec-widthVec-lengthVec*0.5f).toPointF(), (centerVec-0.2f*widthVec+1.2f*lengthVec).toPointF(), (centerVec+lengthVec*0.2f).toPointF());
23448         path.cubicTo((centerVec+0.2f*widthVec+1.2f*lengthVec).toPointF(), (centerVec+widthVec-lengthVec*0.5f).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
23449
23450         painter->drawPath(path);
23451         break;
23452       }
23453     }
23454   }
23455 }
23456
23457 /* inherits documentation from base class */
23458 QPointF QCPItemBracket::anchorPixelPoint(int anchorId) const
23459 {
23460   QVector2D leftVec(left->pixelPoint());
23461   QVector2D rightVec(right->pixelPoint());
23462   if (leftVec.toPoint() == rightVec.toPoint())
23463     return leftVec.toPointF();
23464
23465   QVector2D widthVec = (rightVec-leftVec)*0.5f;
23466   QVector2D lengthVec(-widthVec.y(), widthVec.x());
23467   lengthVec = lengthVec.normalized()*mLength;
23468   QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23469
23470   switch (anchorId)
23471   {
23472     case aiCenter:
23473       return centerVec.toPointF();
23474   }
23475   qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
23476   return QPointF();
23477 }
23478
23479 /*! \internal
23480
23481   Returns the pen that should be used for drawing lines. Returns mPen when the
23482   item is not selected and mSelectedPen when it is.
23483 */
23484 QPen QCPItemBracket::mainPen() const
23485 {
23486     return mSelected ? mSelectedPen : mPen;
23487 }
23488