JKQtPlotter/lib/jkqtplotter/jkqtpkey.cpp

674 lines
24 KiB
C++

/*
Copyright (c) 2008-2022 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/>.
*/
#include "jkqtplotter/jkqtpkey.h"
#include "jkqtplotter/jkqtpbaseplotter.h"
#include "jkqtplotter/jkqtpgraphsbase.h"
#include "jkqtcommon/jkqtpdrawingtools.h"
#include <QDebug>
#include <QDateTime>
#include <cfloat>
#include "jkqtplotter/jkqtptools.h"
#include "jkqtmathtext/jkqtmathtext.h"
JKQTPBaseKey::JKQTPBaseKey(JKQTBasePlotter* _parent):
QObject(_parent),
parent(_parent),
localKeyStyle()
{
}
JKQTPBaseKey::~JKQTPBaseKey() {
}
void JKQTPBaseKey::setParent(JKQTBasePlotter* parent) {
this->parent=parent;
QObject::setParent(parent);
}
void JKQTPBaseKey::redrawPlot() {
if (parent) {
parent->updateSecondaryAxes();
parent->redrawPlot();
}
}
void JKQTPBaseKey::loadSettings(const QSettings& settings, const QString& group) {
keyStyle().loadSettings(settings, group);
}
void JKQTPBaseKey::saveSettings(QSettings& settings, const QString& group) const {
keyStyle().saveSettings(settings, group);
}
void JKQTPBaseKey::drawKey(JKQTPEnhancedPainter &painter, const QRectF &rect, const KeySizeDescription& layout)
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::drawKey()").arg(objectName()));
#endif
if (!keyStyle().visible) return;
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
const qreal FHeight=JKQTMathTextGetFontHeight(kf, painter.device());
// determine layouting info and size
QPointF internalOffset(0,0);
const QSizeF keySize=extendLayoutSize(QSizeF(layout.d->calcOverallWidth(keyStyle().sampleLineLength*Xwid, keyStyle().xSeparation*Xwid, keyStyle().columnSeparation*Xwid),
layout.d->calcOverallHeight(keyStyle().ySeparation*FHeight, keyStyle().sampleHeight*FHeight)), painter, &internalOffset);
if (keySize.isEmpty() || keySize.isNull() || !keySize.isValid()) return;
const double frameWidth=qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, getParent()->pt2px(painter, keyStyle().frameWidth*getParent()->getLineWidthMultiplier()));
const bool drawDebugRects=getParent()->isDebugShowRegionBoxesEnabled();
// calculate start position for drawing
QPointF x0(0,0);
if (keyStyle().position.testFlag(JKQTPKeyLeft)) {
x0.setX(rect.left()+keyStyle().xOffset*Xwid);
} else if (keyStyle().position.testFlag(JKQTPKeyHCenter)) {
x0.setX(rect.left()+(rect.width()-keySize.width())/2.0+keyStyle().xOffset*Xwid);
} else if (keyStyle().position.testFlag(JKQTPKeyRight)) {
x0.setX(rect.right()-keySize.width()-keyStyle().xOffset*Xwid);
}
if (keyStyle().position.testFlag(JKQTPKeyTop)) {
x0.setY(rect.top()+keyStyle().yOffset*Xwid);
} else if (keyStyle().position.testFlag(JKQTPKeyVCenter)) {
x0.setY(rect.top()+(rect.height()-keySize.height())/2.0+keyStyle().yOffset*Xwid);
} else if (keyStyle().position.testFlag(JKQTPKeyBottom)) {
x0.setY(rect.bottom()-keySize.height()-keyStyle().yOffset*Xwid);
}
const QRectF rectKey(x0, keySize);
// construct necessary pens ...
QPen pf;
if (keyStyle().frameVisible) {
pf.setColor(keyStyle().frameColor);
pf.setWidthF(frameWidth);
pf.setStyle(keyStyle().frameLineStyle);
} else {
pf=Qt::NoPen;
}
// start drawing
{
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
// draw background rectangle
{
painter.save(); auto __finalbackpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setBrush(keyStyle().backgroundBrush);
painter.setPen(pf);
if (keyStyle().frameRounding<=0) {
painter.drawRect(rectKey);
} else {
painter.drawRoundedRect(rectKey, getParent()->pt2px(painter, keyStyle().frameRounding), getParent()->pt2px(painter, keyStyle().frameRounding));
}
}
// draw key table/contents
x0=x0+internalOffset;
QPointF xi=x0;
int ic=0;
for (const auto& c: layout.d->columns) {
xi.setY(x0.y());
int ir=0;
for (const auto& r: c.rows) {
const QRectF sampleRect(xi, QSizeF(keyStyle().sampleLineLength*Xwid, keyStyle().sampleHeight*FHeight));
const double rowHeight=layout.d->calcRowHeight(ir, sampleRect.height());
const QRectF textRect(xi+QPointF((keyStyle().sampleLineLength+keyStyle().xSeparation)*Xwid, 0), QSize(r.size.width(), rowHeight));
drawEntrySample(r.id, painter, sampleRect);
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaatmt(QString("JKQTPBaseKey[%1]::drawKey()::drawEntryText(r=%2,c=%3)::parse").arg(objectName()).arg(ir).arg(ic));
#endif
getParentMathText()->setFontColor(keyStyle().textColor);
getParentMathText()->setFontPointSize(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
getParentMathText()->setFontSpecial(keyStyle().fontName);
getParentMathText()->parse(r.text);
}
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaatmt(QString("JKQTPBaseKey[%1]::drawKey()::drawEntryText(r=%2,c=%3)::parse").arg(objectName()).arg(ir).arg(ic));
#endif
getParentMathText()->draw(painter, Qt::AlignLeft|Qt::AlignVCenter, textRect, getParent()->isDebugShowTextBoxesEnabled());
}
if (drawDebugRects) {
painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();});
QPen p("orange");
QColor col=p.color(); col.setAlphaF(0.8f); p.setColor(col);
p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth/2.0);
p.setStyle(Qt::DashLine);
painter.setPen(p);
painter.setBrush(QBrush(QColor(Qt::transparent)));
painter.drawRect(textRect);
painter.drawRect(sampleRect);
}
xi.setY(xi.y()+rowHeight+keyStyle().ySeparation*FHeight);
ir++;
}
xi.setX(xi.x()+c.calcColumnWidth(keyStyle().sampleLineLength*Xwid, keyStyle().xSeparation*Xwid)+keyStyle().columnSeparation*Xwid);
ic++;
}
}
}
JKQTPBaseKey::KeySizeDescription JKQTPBaseKey::getSize(JKQTPEnhancedPainter &painter)
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::getSize()").arg(objectName()));
#endif
KeySizeDescription size;
if (!keyStyle().visible) return size;
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
// calculate layout of the "table" of samples and labels
const KeyLayoutDescription layout=getKeyLayout(painter);
size.d->operator=(layout);
// calculate size of full key
calcLayoutSize(painter, size);
return size;
}
void JKQTPBaseKey::calcLayoutSize(JKQTPEnhancedPainter &painter, KeySizeDescription &layout) const
{
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
const qreal FHeight=JKQTMathTextGetFontHeight(kf, painter.device());
layout.requiredSize=extendLayoutSize(QSizeF(layout.d->calcOverallWidth(keyStyle().sampleLineLength*Xwid, keyStyle().xSeparation*Xwid, keyStyle().columnSeparation*Xwid),
layout.d->calcOverallHeight(keyStyle().ySeparation*FHeight, keyStyle().sampleHeight*FHeight)), painter);
// determine location of key from keySTyle().positon
if (keyStyle().position.testFlag(JKQTPKeyInside)) layout.keyLocation=KeySizeDescription::keyInside;
else if (keyStyle().position.testFlag(JKQTPKeyOutsideTop)) { layout.keyLocation=KeySizeDescription::keyOutsideTop; layout.requiredSize+=QSizeF(0,keyStyle().yOffset*Xwid); }
else if (keyStyle().position.testFlag(JKQTPKeyOutsideBottom)) { layout.keyLocation=KeySizeDescription::keyOutsideBottom; layout.requiredSize+=QSizeF(0,keyStyle().yOffset*Xwid); }
else if (keyStyle().position.testFlag(JKQTPKeyOutsideLeft)) { layout.keyLocation=KeySizeDescription::keyOutsideLeft; layout.requiredSize+=QSizeF(0,keyStyle().xOffset*Xwid); }
else if (keyStyle().position.testFlag(JKQTPKeyOutsideRight)) { layout.keyLocation=KeySizeDescription::keyOutsideRight; layout.requiredSize+=QSizeF(0,keyStyle().xOffset*Xwid); }
}
void JKQTPBaseKey::modifySize(JKQTPEnhancedPainter &painter, KeySizeDescription &currentKeyLayout, QSizeF preliminaryPlotSize)
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::modifySize()").arg(objectName()));
#endif
// in odd cases (many plots), the initial key size may be larger than the actual plot. then we can have negative sizes.
// in these cases we correct them preliminary plot size to 80% of the widget size (=available size)!
const auto widgetSize=QSizeF(parent->getWidth(), parent->getHeight());
if (preliminaryPlotSize.width()<0) preliminaryPlotSize.setWidth(widgetSize.width()*0.8);
if (preliminaryPlotSize.height()<0) preliminaryPlotSize.setHeight(widgetSize.height()*0.8);
const auto lay=getLayout();
if (lay==JKQTPKeyLayoutMultiColumn || lay==JKQTPKeyLayoutMultiRow) {
std::function<bool(QSizeF, QSizeF)> fcmpSizeTooLarge=[](const QSizeF& requiredSize, const QSizeF& preliminaryPlotSize) { return true; };
bool increaseColumnCount=true;
bool fillMaxMode=false;
if (currentKeyLayout.keyLocation==KeySizeDescription::keyInside) {
fcmpSizeTooLarge=[](const QSizeF& requiredSize, const QSizeF& preliminaryPlotSize) {
return (requiredSize.width()>preliminaryPlotSize.width() || requiredSize.height()>preliminaryPlotSize.height());
};
} else if (currentKeyLayout.keyLocation==KeySizeDescription::keyOutsideTop || currentKeyLayout.keyLocation==KeySizeDescription::keyOutsideBottom) {
fcmpSizeTooLarge=[widgetSize](const QSizeF& requiredSize, const QSizeF& preliminaryPlotSize) {
return (requiredSize.width()>preliminaryPlotSize.width());
};
increaseColumnCount=true;
fillMaxMode=true;
} else if (currentKeyLayout.keyLocation==KeySizeDescription::keyOutsideLeft || currentKeyLayout.keyLocation==KeySizeDescription::keyOutsideRight) {
fcmpSizeTooLarge=[widgetSize](const QSizeF& requiredSize, const QSizeF& preliminaryPlotSize) {
return (requiredSize.height()>preliminaryPlotSize.height());
};
increaseColumnCount=false;
fillMaxMode=true;
}
const int itemCnt=currentKeyLayout.d->countItems();
const auto initialLayout=currentKeyLayout;
if (fillMaxMode) {
int newCount=itemCnt+1;
bool notSizeOK=true;
while (newCount>1 && notSizeOK) {
newCount--; // increase number of rows/columns
currentKeyLayout=initialLayout; // reset to initial layout, which should have one column only!
// this is required, so redistribute...() does not scramble the order
if (increaseColumnCount) {
currentKeyLayout.d->redistributeOverColumns(newCount, lay==JKQTPKeyLayoutMultiColumn);
} else {
currentKeyLayout.d->redistributeOverRows(newCount, lay==JKQTPKeyLayoutMultiRow);
}
calcLayoutSize(painter, currentKeyLayout);
notSizeOK=fcmpSizeTooLarge(currentKeyLayout.requiredSize, preliminaryPlotSize);
}
} else {
int newCount=1;
while (newCount<itemCnt && fcmpSizeTooLarge(currentKeyLayout.requiredSize, preliminaryPlotSize)) {
newCount++; // increase number of rows/columns
currentKeyLayout=initialLayout; // reset to initial layout, which should have one column only!
// this is required, so redistribute...() does not scramble the order
if (increaseColumnCount) {
currentKeyLayout.d->redistributeOverColumns(newCount, lay==JKQTPKeyLayoutMultiColumn);
} else {
currentKeyLayout.d->redistributeOverRows(newCount, lay==JKQTPKeyLayoutMultiRow);
}
calcLayoutSize(painter, currentKeyLayout);
}
}
}
}
JKQTMathText* JKQTPBaseKey::getParentMathText() {
if (!parent) return nullptr;
return parent->getMathText();
}
const JKQTMathText* JKQTPBaseKey::getParentMathText() const {
if (!parent) return nullptr;
return parent->getMathText();
}
const JKQTPKeyStyle &JKQTPBaseKey::getCurrentKeyStyle() const
{
return keyStyle();
}
void JKQTPBaseKey::setCurrentKeyStyle(const JKQTPKeyStyle &style)
{
keyStyle()=style;
redrawPlot();
}
JKQTPBaseKey::KeyLayoutDescription JKQTPBaseKey::getKeyLayout(JKQTPEnhancedPainter &painter)
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::getKeyLayout()").arg(objectName()));
#endif
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
//const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
const qreal Fheight=JKQTMathTextGetFontHeight(kf, painter.device());
//const double frameWidth=qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, getParent()->pt2px(painter, keyStyle().frameWidth*getParent()->getLineWidthMultiplier()));
JKQTPBaseKey::KeyLayoutDescription layout;
KeyColumnDescription allItems;
// first collect all items into one column
const int NItems=getEntryCount();
for (int i=0; i<NItems; i++) {
KeyItemData item;
item.id=i;
item.text=getEntryText(i);
item.size=getParent()->getTextSizeSize(keyStyle().fontName, keyStyle().fontSize, item.text, painter);
item.size.setHeight(qMax(item.size.height(), keyStyle().sampleHeight*Fheight));
allItems.rows.push_back(item);
}
// now redistrbute accordint to keyStyle().layout
if (keyStyle().layout==JKQTPKeyLayoutOneColumn || keyStyle().layout==JKQTPKeyLayoutMultiColumn) {
layout.columns.append(allItems);
} else if (keyStyle().layout==JKQTPKeyLayoutOneRow || keyStyle().layout==JKQTPKeyLayoutMultiRow) {
for (const auto& r: allItems.rows) {
layout.columns.push_back(KeyColumnDescription(r));
}
}
return layout;
}
QSizeF JKQTPBaseKey::extendLayoutSize(QSizeF rawLayoutSize, JKQTPEnhancedPainter& painter, QPointF *offset) const
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::extendLayoutSize()").arg(objectName()));
#endif
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
const double frameWidth=qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, getParent()->pt2px(painter, keyStyle().frameWidth*getParent()->getLineWidthMultiplier()));
if (rawLayoutSize.width()>0) rawLayoutSize.setWidth(rawLayoutSize.width()+2.0*keyStyle().xMargin*Xwid+2.0*frameWidth);
if (rawLayoutSize.height()>0) rawLayoutSize.setHeight(rawLayoutSize.height()+2.0*keyStyle().yMargin*Xwid+2.0*frameWidth);
if (offset) *offset=QPointF(keyStyle().xMargin*Xwid+frameWidth, keyStyle().yMargin*Xwid+frameWidth);
return rawLayoutSize;
}
const JKQTPKeyStyle &JKQTPBaseKey::keyStyle() const
{
return localKeyStyle;
}
JKQTPKeyStyle &JKQTPBaseKey::keyStyle()
{
return localKeyStyle;
}
JKQTPBaseKey::KeyItemData::KeyItemData(int _id, const QString &_text, const QSizeF _size):
id(_id),
text(_text),
size(_size)
{
}
JKQTPBaseKey::KeySizeDescription::KeySizeDescription(QSize _requiredSize, KeyLocation _keyLocation):
requiredSize(_requiredSize),
keyLocation(_keyLocation),
d(new JKQTPBaseKey::KeyLayoutDescription)
{
}
JKQTPBaseKey::KeySizeDescription::KeySizeDescription(const KeySizeDescription &other):
requiredSize(),
keyLocation(KeyLocation::keyInside),
d(new JKQTPBaseKey::KeyLayoutDescription)
{
operator=(other);
}
JKQTPBaseKey::KeySizeDescription &JKQTPBaseKey::KeySizeDescription::operator=(const KeySizeDescription &other)
{
requiredSize=other.requiredSize;
keyLocation=other.keyLocation;
d->operator=(*(other.d));
return *this;
}
JKQTPBaseKey::KeyColumnDescription::KeyColumnDescription():
rows()
{
}
JKQTPBaseKey::KeyColumnDescription::KeyColumnDescription(const KeyItemData &item1):
KeyColumnDescription()
{
rows.append(item1);
}
double JKQTPBaseKey::KeyColumnDescription::calcMaxLabelWidth() const
{
double w=0;
for (const auto& r: rows) {
w=qMax(w, r.size.width());
}
return w;
}
double JKQTPBaseKey::KeyColumnDescription::calcColumnWidth(double sampleLineLength, double xSeparation) const
{
return calcMaxLabelWidth()+sampleLineLength+xSeparation;
}
double JKQTPBaseKey::KeyLayoutDescription::calcOverallWidth(double sampleLineLength, double xSeparation, double columnSeparation) const
{
double w=0;
for (const auto& c: columns) {
if (w>0) w+=columnSeparation;
w+=sampleLineLength;
w+=xSeparation;
w+=c.calcMaxLabelWidth();
}
return w;
}
double JKQTPBaseKey::KeyLayoutDescription::calcOverallHeight(double ySeparation, double sampleHeight) const
{
double h=0;
const int N=calcRowCount();
for (int i=0; i<N; i++) {
h+=calcRowHeight(i, sampleHeight);
if (i>0) h+=ySeparation;
}
return h;
}
double JKQTPBaseKey::KeyLayoutDescription::calcRowHeight(int i, double sampleHeight) const
{
double h=0;
for (const auto& c: columns) {
if (i>=0 && i<c.rows.size()) h=qMax(h, c.rows[i].size.height());
}
if (h>0) h=qMax(sampleHeight, h);
return h;
}
int JKQTPBaseKey::KeyLayoutDescription::calcRowCount() const
{
int n=0;
for (const auto& c: columns) {
n=qMax(n, c.rows.size());
}
return n;
}
int JKQTPBaseKey::KeyLayoutDescription::countItems() const
{
int n=0;
for (const auto& c: columns) {
n+=c.rows.size();
}
return n;
}
void JKQTPBaseKey::KeyLayoutDescription::redistributeIntoOneColumn()
{
if (countItems()>1) {
for (int i=1; i<columns.size(); i++) {
columns[0].rows.append(columns[i].rows);
}
for (int i=columns.size()-1; i>=1; i--) {
columns.removeAt(i);
}
}
}
void JKQTPBaseKey::KeyLayoutDescription::redistributeOverRows(int rowCnt, bool rowMajor)
{
const int itemCnt=countItems();
if (itemCnt>1) {
const int colCnt=static_cast<int>(ceil(static_cast<float>(itemCnt)/static_cast<float>(rowCnt)));
if (true) {
redistributeIntoOneColumn();
const auto items=columns[0].rows;
columns.clear();
int i=0;
for (int c=0; c<colCnt; c++) {
columns.push_back(KeyColumnDescription());
}
if (rowMajor) {
for (int r=0; r<rowCnt; r++) {
for (int c=0; c<colCnt; c++) {
if (i<itemCnt) columns[c].rows.append(items[i]);
i++;
}
}
} else {
for (int c=0; c<colCnt; c++) {
for (int r=0; r<rowCnt; r++) {
if (i<itemCnt) columns[c].rows.append(items[i]);
i++;
}
}
}
}
}
}
void JKQTPBaseKey::KeyLayoutDescription::redistributeOverColumns(int colCnt, bool colMajor)
{
const int itemCnt=countItems();
if (itemCnt>1) {
const int rowCnt=static_cast<int>(ceil(static_cast<float>(itemCnt)/static_cast<float>(colCnt)));
if (colCnt>1) {
redistributeIntoOneColumn();
const auto items=columns[0].rows;
columns.clear();
int i=0;
for (int c=0; c<colCnt; c++) {
columns.push_back(KeyColumnDescription());
}
if (colMajor) {
for (int c=0; c<colCnt; c++) {
for (int r=0; r<rowCnt; r++) {
if (i<itemCnt) columns[c].rows.append(items[i]);
i++;
}
}
} else {
for (int r=0; r<rowCnt; r++) {
for (int c=0; c<colCnt; c++) {
if (i<itemCnt) columns[c].rows.append(items[i]);
i++;
}
}
}
}
}
}
JKQTPMainKey::JKQTPMainKey(JKQTBasePlotter *parent):
JKQTPBaseKey(parent)
{
}
JKQTPMainKey::~JKQTPMainKey()
{
}
int JKQTPMainKey::getEntryCount() const
{
return getPlotElements().size();
}
QString JKQTPMainKey::getEntryText(int item) const
{
QString s;
const auto g=getPlotElement(item);
if (g) s=g->getTitle();
return s;
}
QColor JKQTPMainKey::getEntryColor(int item) const
{
QColor s=keyStyle().textColor;
const auto g=getPlotElement(item);
if (g) s=g->getKeyLabelColor();
return s;
}
void JKQTPMainKey::drawEntrySample(int item, JKQTPEnhancedPainter &painter, const QRectF &rect)
{
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::drawEntrySammple(%2)").arg(objectName()).arg(item));
#endif
auto g=getPlotElement(item);
if (g) g->drawKeyMarker(painter, rect);
}
QList<const JKQTPPlotElement *> JKQTPMainKey::getPlotElements() const
{
const auto p=getParent();
QList<const JKQTPPlotElement *> l;
if (!p) return l;
l.reserve(p->getGraphCount());
for (size_t i=0; i<p->getGraphCount(); i++) {
const auto g=p->getGraph(i);
if (g && g->isVisible() && !g->getTitle().isEmpty()) {
l<<g;
}
}
return l;
}
const JKQTPKeyStyle &JKQTPMainKey::keyStyle() const
{
return getParent()->getMainKeyStyle();
}
JKQTPKeyStyle &JKQTPMainKey::keyStyle()
{
return getParent()->getMainKeyStyle();
}
const JKQTPPlotElement* JKQTPMainKey::getPlotElement(int item) const
{
const auto p=getParent();
if (!p) return nullptr;
int curitem=0;
for (size_t i=0; i<p->getGraphCount(); i++) {
const auto g=p->getGraph(i);
if (g && g->isVisible() && !g->getTitle().isEmpty()) {
if (curitem==item) return g;
curitem++;
}
}
return nullptr;
}
JKQTPPlotElement* JKQTPMainKey::getPlotElement(int item)
{
auto p=getParent();
if (!p) return nullptr;
int curitem=0;
for (size_t i=0; i<p->getGraphCount(); i++) {
auto g=p->getGraph(i);
if (g && g->isVisible() && !g->getTitle().isEmpty()) {
if (curitem==item) return g;
curitem++;
}
}
return nullptr;
}