2023-12-19 05:24:59 +08:00
/*
Copyright ( c ) 2023 - 2023 Jan W . Krieger ( < jan @ jkrieger . de > )
This software is free software : you can redistribute it and / or modify
it under the terms of the GNU Lesser General Public License ( LGPL ) as published by
the Free Software Foundation , either version 2.1 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Lesser General Public License ( LGPL ) for more details .
You should have received a copy of the GNU Lesser General Public License ( LGPL )
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifndef JKQTPKEY_H
# define JKQTPKEY_H
# include <QString>
# include <QPainter>
# include "jkqtplotter/jkqtplotter_imexport.h"
# include "jkqtplotter/jkqtpkeystyle.h"
// forward declarations
class JKQTBasePlotter ;
class JKQTPPlotElement ;
class JKQTMathText ;
/*! \brief base class for drawing a key (or legend)
\ ingroup jkqtpbaseplotter_elements
2023-12-19 18:18:28 +08:00
The class JKQTPBaseKey implements the basic layouting and drawing of a key / legend . The basic style properties are defined in JKQTPKeyStyle .
The following image shows , which properties of the key may be altered with the style :
2023-12-19 05:24:59 +08:00
\ image html plot_key . png
2023-12-19 18:18:28 +08:00
\ section JKQTPBaseKey_Usage Usage
The functions in JKQTPBaseKey are mainly used for drawing the main key in a JKQTBasePlotter .
The instance representing that main key is accessible via JKQTPBaseKey : : getMainKey ( ) .
It is not a direct instance of JKQTPBaseKey , which is impossible , as it is pure virtual ,
but an instance of JKQTPMainKey , which extends JKQTPBaseKey with access to the titles assigned to
each JKQTPPlotElement ( see JKQTPPlotElement : : getTitle ( ) , JKQTPPlotElement : : setTitle ( ) ) and its key - marker ( JKQTPPlotElement : : drawKeyMarker ( ) ) .
Note however that it is also possible to draw additional keys into the graph ( e . g . to show the size / color classes in a parametrized scatter graph ) ,
if the corresponding JKQTPPlotElement implements this .
\ section JKQTPBaseKey_ImplementationDetails Implementation Details
2023-12-19 05:24:59 +08:00
It relies on these protected virtual functions to determine the contents of the legend items :
2023-12-19 18:18:28 +08:00
- JKQTPBaseKey : : getEntryCount ( )
- JKQTPBaseKey : : getEntryTextExtent ( )
- JKQTPBaseKey : : getEntryText ( )
- JKQTPBaseKey : : drawEntrySample ( )
2023-12-19 05:24:59 +08:00
.
So you can derive from JKQTPBaseKey and implement these to provide a new source of data .
There are additional customization points in this class . You can also override the
default implementations of these functions to change the way keys / legends are drawn :
2023-12-19 18:18:28 +08:00
- JKQTPBaseKey : : drawKey ( )
- JKQTPBaseKey : : getLayout ( )
- JKQTPBaseKey : : modifySize ( )
2023-12-19 05:24:59 +08:00
.
2023-12-19 18:18:28 +08:00
\ see JKQTPKeyStyle , JKQTPMainKey
2023-12-19 05:24:59 +08:00
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBaseKey : public QObject {
Q_OBJECT
protected :
struct KeyLayoutDescription ; // forward
public :
/** \brief class constructor */
explicit JKQTPBaseKey ( JKQTBasePlotter * parent ) ;
/** \brief class destructor */
virtual ~ JKQTPBaseKey ( ) ;
virtual void setParent ( JKQTBasePlotter * parent ) ;
/** \brief loads the plot properties from a QSettings object */
virtual void loadSettings ( const QSettings & settings , const QString & group = QString ( " plots/key/ " ) ) ;
/** \brief saves the plot properties into a QSettings object.
*
* This method only saves those properties that differ from their default value .
*/
virtual void saveSettings ( QSettings & settings , const QString & group = QString ( " plots/key/ " ) ) const ;
/** \brief describes a single key entry */
struct JKQTPLOTTER_LIB_EXPORT KeyItemData {
KeyItemData ( int _id = - 1 , const QString & _text = " " , const QSizeF _size = QSizeF ( ) ) ;
/** \brief id of the item, used to call drawEntrySample() etc. */
int id ;
/** \brief text/label text/markup in the enry */
QString text ;
/** \brief size of \a text in pixels */
QSizeF size ;
} ;
/** \brief struct, describing basic layout and size properties of a key/legend, mostly used as return value of getSize(). */
struct JKQTPLOTTER_LIB_EXPORT KeySizeDescription {
/** \brief type describing the position of the key */
enum KeyLocation {
keyInside , /*!< \brief somewhere inside the plot */
keyOutsideLeft , /*!< \brief on the left of the plot */
keyOutsideRight , /*!< \brief on the right of the plot */
keyOutsideTop , /*!< \brief above the plot */
keyOutsideBottom /*!< \brief below the plot */
} ;
KeySizeDescription ( QSize _requiredSize = QSize ( ) , KeyLocation _keyLocation = keyInside ) ;
KeySizeDescription ( const KeySizeDescription & other ) ;
KeySizeDescription & operator = ( const KeySizeDescription & other ) ;
/** \brief required spacefor the key/legend [pixels] */
QSizeF requiredSize ;
/** \brief where the size requiredSize has to be resevred for the key */
KeyLocation keyLocation ;
/** \brief private data \internal */
std : : unique_ptr < KeyLayoutDescription > d ;
} ;
/** \brief calculates the size required for the key
*
* This function internally calls getLayout ( ) , which is ( together with drawKey ( ) )
* a customization point for key layout .
*/
KeySizeDescription getSize ( JKQTPEnhancedPainter & painter ) ;
/** \brief econd stage of size calculation
*
* This functions allows to again modify the KeySizeDescription \ a currentSize in a second step ,
* when the preliminary size of the plot is known ( given as \ a preliminaryPlotSize ) .
*
* This is used to implement the JKQTPKeyLayout : : JKQTPKeyLayoutMultiColumn and JKQTPKeyLayout : : JKQTPKeyLayoutMultiRow ,
* where the distribution of entries over rows / columns is calculated here .
*
* \ note This function is declared virtual so it can be used as a customization point !
*/
virtual void modifySize ( JKQTPEnhancedPainter & painter , KeySizeDescription & currentSize , QSizeF preliminaryPlotSize ) ;
/** \brief draw the key
*
* \ param painter the painter to use for drawing
* \ param rect the rectangle to plot the key into , depending on JKQTPKeyStyle : : position this is either the plot rectangle itself , or
* a rectangle outside the plot that fits the key
* \ param layout output of getSize ( ) , possibly modified by modifySize ( )
*
* \ note It is expected that the owning JKQTBasePlotter first calls getSize ( ) and the determmines a QREct that fits the legend . The latter is the supplied as \ a rect to this function for subsequent drawing .
* It is also expected that the legends contents does not changed in the meantime !
*/
virtual void drawKey ( JKQTPEnhancedPainter & painter , const QRectF & rect , const KeySizeDescription & layout ) ;
/** \copydoc parent */
inline const JKQTBasePlotter * getParent ( ) const { return parent ; }
/** \copydoc parent */
inline JKQTBasePlotter * getParent ( ) { return parent ; }
/** \brief current style properties (JKQTPKeyStyle) for this JKQTPKey
*
* \ see JKQTPKeyStyle
*/
const JKQTPKeyStyle & getCurrentKeyStyle ( ) const ;
/** \brief replace the current style properties for this JKQTPKey
*
* \ see JKQTPSetSystemDefaultBaseStyle ( ) , JKQTPSetSystemDefaultBaseStyle ( ) , setCurrentAxisStyle ( ) , getCurrentAxisStyle ( ) , \ ref jkqtpplotter_styling
*/
void setCurrentKeyStyle ( const JKQTPKeyStyle & style ) ;
/** \copydoc JKQTPKeyStyle::frameVisible */
inline bool getFrameVisible ( ) const { return keyStyle ( ) . frameVisible ; }
/** \copydoc JKQTPKeyStyle::visible */
inline bool getVisible ( ) const { return keyStyle ( ) . visible ; }
/** \copydoc JKQTPKeyStyle::xMargin */
inline double getXMargin ( ) const { return keyStyle ( ) . xMargin ; }
/** \copydoc JKQTPKeyStyle::yMargin */
inline double getYMargin ( ) const { return keyStyle ( ) . yMargin ; }
/** \copydoc JKQTPKeyStyle::xOffset */
inline double getXOffset ( ) const { return keyStyle ( ) . xOffset ; }
/** \copydoc JKQTPKeyStyle::yOffset */
inline double getYOffset ( ) const { return keyStyle ( ) . yOffset ; }
/** \copydoc JKQTPKeyStyle::xSeparation */
inline double getXSeparation ( ) const { return keyStyle ( ) . xSeparation ; }
/** \copydoc JKQTPKeyStyle::ySeparation */
inline double getYSeparation ( ) const { return keyStyle ( ) . ySeparation ; }
/** \copydoc JKQTPKeyStyle::columnSeparation */
inline double getColumnSeparation ( ) const { return keyStyle ( ) . columnSeparation ; }
/** \copydoc JKQTPKeyStyle::position */
inline JKQTPKeyPosition getPosition ( ) const { return keyStyle ( ) . position ; }
/** \copydoc JKQTPKeyStyle::layout */
inline JKQTPKeyLayout getLayout ( ) const { return keyStyle ( ) . layout ; }
/** \copydoc JKQTPKeyStyle::frameColor */
inline QColor getFrameColor ( ) const { return keyStyle ( ) . frameColor ; }
/** \copydoc JKQTPKeyStyle::frameLineStyle */
inline Qt : : PenStyle getFrameLineStyle ( ) const { return keyStyle ( ) . frameLineStyle ; }
/** \copydoc JKQTPKeyStyle::textColor */
inline QColor getTextColor ( ) const { return keyStyle ( ) . textColor ; }
/** \copydoc JKQTPKeyStyle::backgroundColor */
inline QColor getBackgroundColor ( ) const { return keyStyle ( ) . backgroundBrush . color ( ) ; }
/** \copydoc JKQTPKeyStyle::backgroundBrush */
inline const QBrush & getBackgroundBrush ( ) const { return keyStyle ( ) . backgroundBrush ; }
/** \copydoc JKQTPKeyStyle::frameWidth */
inline double getFrameWidth ( ) const { return keyStyle ( ) . frameWidth ; }
/** \copydoc JKQTPKeyStyle::fontSize */
inline double getFontSize ( ) const { return keyStyle ( ) . fontSize ; }
/** \copydoc JKQTPKeyStyle::frameRounding */
inline double getFrameRounding ( ) const { return keyStyle ( ) . frameRounding ; }
/** \copydoc JKQTPKeyStyle::sampleLineLength */
inline double getSampleLineLength ( ) const { return keyStyle ( ) . sampleLineLength ; }
public Q_SLOTS :
/** \copydoc JKQTPKeyStyle::visible */
inline void setVisible ( bool __value ) { keyStyle ( ) . visible = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::frameVisible */
inline void setFrameVisible ( bool __value ) { keyStyle ( ) . frameVisible = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::frameWidth */
inline void setFrameWidth ( double __value ) { keyStyle ( ) . frameWidth = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::frameRounding */
inline void setFrameRounding ( double __value ) { keyStyle ( ) . frameRounding = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::fontSize */
inline void setFontSize ( double __value ) { keyStyle ( ) . fontSize = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::sampleLineLength */
inline void setSampleLineLength ( double __value ) { keyStyle ( ) . sampleLineLength = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::xMargin */
inline void setXMargin ( double __value ) { keyStyle ( ) . xMargin = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::yMargin */
inline void setYMargin ( double __value ) { keyStyle ( ) . yMargin = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::xOffset */
inline void setXOffset ( double __value ) { keyStyle ( ) . xOffset = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::yOffset */
inline void setYOffset ( double __value ) { keyStyle ( ) . yOffset = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::xSeparation */
inline void setXSeparation ( double __value ) { keyStyle ( ) . xSeparation = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::ySeparation */
inline void setYSeparation ( double __value ) { keyStyle ( ) . ySeparation = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::columnSeparation */
inline void setColumnSeparation ( double __value ) { keyStyle ( ) . columnSeparation = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::position */
inline void setPosition ( JKQTPKeyPosition __value ) { keyStyle ( ) . position = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::layout */
inline void setLayout ( JKQTPKeyLayout __value ) { keyStyle ( ) . layout = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::frameColor */
inline void setFrameColor ( QColor __value ) { keyStyle ( ) . frameColor = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::frameLineStyle */
inline void setFrameLineStyle ( Qt : : PenStyle __value ) { keyStyle ( ) . frameLineStyle = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::textColor */
inline void setTextColor ( QColor __value ) { keyStyle ( ) . textColor = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::backgroundColor */
inline void setBackgroundColor ( QColor __value ) { keyStyle ( ) . backgroundBrush = __value ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::backgroundColor */
inline void setBackgroundColor ( QColor __value , Qt : : BrushStyle __style ) { keyStyle ( ) . backgroundBrush = QBrush ( __value , __style ) ; redrawPlot ( ) ; }
/** \copydoc JKQTPKeyStyle::backgroundBrush */
inline void setBackgroundBrush ( const QBrush & __value ) { keyStyle ( ) . backgroundBrush = __value ; redrawPlot ( ) ; }
protected :
/** \brief returns the number of legend entries */
virtual int getEntryCount ( ) const = 0 ;
/** \brief returns the label text (my contain markup for a JKQTMathText) of legend entry \a item 's text part */
virtual QString getEntryText ( int item ) const = 0 ;
/** \brief returns the label color of legend entry \a item 's text part */
virtual QColor getEntryColor ( int item ) const = 0 ;
/** \brief draws the sample for legend entry \a item into the given \a rect, using the given \a painter */
virtual void drawEntrySample ( int item , JKQTPEnhancedPainter & painter , const QRectF & rect ) = 0 ;
/** \brief describes one column of items in the key */
struct JKQTPLOTTER_LIB_EXPORT KeyColumnDescription {
KeyColumnDescription ( ) ;
KeyColumnDescription ( const KeyItemData & item1 ) ;
/** \brief list of all items in this row of key items */
QList < KeyItemData > rows ;
/** \brief calculates the max. text width of the column in pixels */
double calcMaxLabelWidth ( ) const ;
/** \brief calculates the width of the column in pixels */
double calcColumnWidth ( double sampleLineLength , double xSeparation ) const ;
} ;
/** \brief struct, describing basic layout and size properties of a key/legend, mostly used as return value of getSize(). */
struct JKQTPLOTTER_LIB_EXPORT KeyLayoutDescription {
/** \brief list of all columns with items in the key */
QList < KeyColumnDescription > columns ;
/** \brief calculates the width over all columns */
double calcOverallWidth ( double sampleLineLength , double xSeparation , double columnSeparation ) const ;
/** \brief calculates the width over all columns */
double calcOverallHeight ( double ySeparation , double sampleHeight ) const ;
/** \brief calculate the hieght of the \a i -th column */
double calcRowHeight ( int i , double sampleHeight ) const ;
/** \brief calculates the number of rows */
int calcRowCount ( ) const ;
/** \brief calculate the number of items */
int countItems ( ) const ;
/** \brief put all items into one column */
void redistributeIntoOneColumn ( ) ;
/** \brief takes all elements in columns and redistributes them over the given number of rows, items are distributed as equally as possible (last row may have fewer items) */
void redistributeOverRows ( int rows ) ;
/** \brief takes all elements in columns and redistributes them over the given number of columns, items are distributed as equally as possible (last column may have fewer items) */
void redistributeOverColumns ( int cols ) ;
} ;
/** \brief calculates all layout properties of the key/legend,necessary to size and draw it
*
* This is internally called by getSize ( ) and drawKey ( ) .
*/
virtual KeyLayoutDescription getKeyLayout ( JKQTPEnhancedPainter & painter ) ;
/** \brief fill KeySizeDescription::requiredSize */
void calcLayoutSize ( JKQTPEnhancedPainter & painter , KeySizeDescription & layout ) const ;
/** \brief takes the size calculated by KeyLayoutDescription::calcOverallWidth() and KeyLayoutDescription::calcOverallHeight() and extends it with margins, line widths, ... optionally returns the one-sided offset*/
virtual QSizeF extendLayoutSize ( QSizeF rawLayoutSize , JKQTPEnhancedPainter & painter , QPointF * offset = nullptr ) const ;
/** \brief provides the keyStyle to use for sizing/drawing this object */
virtual const JKQTPKeyStyle & keyStyle ( ) const ;
/** \brief provides the keyStyle to use for sizing/drawing this object */
virtual JKQTPKeyStyle & keyStyle ( ) ;
/** \brief signals the parent JKQTBasePlotter to redraw */
void redrawPlot ( ) ;
/** \brief retun parents JKQTMathText* object */
JKQTMathText * getParentMathText ( ) ;
/** \brief retun parents JKQTMathText* object */
const JKQTMathText * getParentMathText ( ) const ;
/** \brief parent plotter class */
JKQTBasePlotter * parent ;
private :
/** \brief current style properties for this key/legend
*
* \ see JKQTPKeyStyle
*/
JKQTPKeyStyle localKeyStyle ;
} ;
/*! \brief concrete class for drawing the main plot key (or legend).
* This class reads the key entries fromm the graphs list of its parent JKQTBasePlotter .
\ ingroup jkqtpbaseplotter_elements
\ see JKQTPKeyStyle
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPMainKey : public JKQTPBaseKey {
Q_OBJECT
protected :
public :
/** \brief class constructor */
explicit JKQTPMainKey ( JKQTBasePlotter * parent ) ;
/** \brief class destructor */
virtual ~ JKQTPMainKey ( ) ;
protected :
/** \copydoc JKQTPBaseKey::getEntryCount() */
virtual int getEntryCount ( ) const override ;
/** \copydoc JKQTPBaseKey::getEntryText() */
virtual QString getEntryText ( int item ) const override ;
/** \copydoc JKQTPBaseKey::getEntryColor() */
virtual QColor getEntryColor ( int item ) const override ;
/** \copydoc JKQTPBaseKey::drawEntrySample() */
virtual void drawEntrySample ( int item , JKQTPEnhancedPainter & painter , const QRectF & rect ) override ;
/** \brief returns the graph class from parent JKQTBasePlotter for the given \a item in the key */
const JKQTPPlotElement * getPlotElement ( int item ) const ;
/** \brief returns the graph class from parent JKQTBasePlotter for the given \a item in the key */
JKQTPPlotElement * getPlotElement ( int item ) ;
/** \brief returns all graph classes from parent JKQTBasePlotter for the key */
QList < const JKQTPPlotElement * > getPlotElements ( ) const ;
/** \brief provides the keyStyle to use for sizing/drawing this object (extracted from the parent JKQTBasePlotters's */
virtual const JKQTPKeyStyle & keyStyle ( ) const ;
/** \brief provides the keyStyle to use for sizing/drawing this object */
virtual JKQTPKeyStyle & keyStyle ( ) ;
} ;
# endif // JKQTPKEY_H