diff --git a/.gitignore b/.gitignore index b721d47578..4d08d5e4e5 100644 --- a/.gitignore +++ b/.gitignore @@ -187,3 +187,5 @@ Sicherungskopie_* /doc/images/JKQTPBarHorizontalAutoscaleShrinkOnly_small.png /doc/images/JKQTPBarVerticalAutoscaleMaxWidthOnly_small.png /doc/images/JKQTPBarVerticalAutoscaleShrinkOnly_small.png +/doc/images/JKQTPGLabelHalfwaysToXAxis_small.png +/doc/images/JKQTPGLabelHalfwaysToYAxis_small.png diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 79c66b1377..e32ae0e1e8 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -276,7 +276,7 @@ if(JKQtPlotter_BUILD_EXAMPLES) symbols_and_errors/JKQTPXYLineErrorGraph_JKQTPErrorBars,JKQTPXYLineErrorGraph_JKQTPErrorLines,JKQTPXYLineErrorGraph_JKQTPErrorPolygons/--iteratefunctorsteps--iteratefunctorsteps_suppressinitial--smallscreenshotplot boxplot/JKQTPBoxplotVerticalGraph,JKQTPBoxplotHorizontalGraph/--iteratefunctorsteps--iteratefunctorsteps_suppressinitial--smallscreenshotplot second_axis/JKQTBasePlotter_addSecondaryYAxis,JKQTBasePlotter_addSecondaryXAxis - graphlabels/JKQTPGLabelAwayFromXAxis,JKQTPGLabelAwayFromYAxis,JKQTPGLabelTowardsXAxis,JKQTPGLabelTowardsYAxis,JKQTPGLabelAboveData,JKQTPGLabelRightHandSide,JKQTPGLabelBelowData,JKQTPGLabelLeftHandSide,JKQTPGLabelCenteredOnData,JKQTPGLabelCenteredOnDataVertical,JKQTPGLSimpleBox,JKQTPGLSimpleBoxVertical,JKQTPGLSimpleBoxAndLine,JKQTPGLSimpleBoxAndLineVertical,JKQTPGLSimpleBoxAndLineONLYLABELS,JKQTPGLSimpleBoxAndLineONLYLABELSVertical/--iteratefunctorsteps--smallscreenshotplot + graphlabels/JKQTPGLabelAwayFromXAxis,JKQTPGLabelAwayFromYAxis,JKQTPGLabelTowardsXAxis,JKQTPGLabelTowardsYAxis,JKQTPGLabelAboveData,JKQTPGLabelRightHandSide,JKQTPGLabelBelowData,JKQTPGLabelLeftHandSide,JKQTPGLabelCenteredOnData,JKQTPGLabelCenteredOnDataVertical,JKQTPGLSimpleBox,JKQTPGLSimpleBoxVertical,JKQTPGLSimpleBoxAndLine,JKQTPGLSimpleBoxAndLineVertical,JKQTPGLSimpleBoxAndLineONLYLABELS,JKQTPGLSimpleBoxAndLineONLYLABELSVertical,JKQTPGLabelHalfwaysToXAxis,JKQTPGLabelHalfwaysToYAxis/--iteratefunctorsteps--smallscreenshotplot vectorfield/JKQTPVectorFieldGraph,JKQTPVectorFieldGraphAnchorBottom,JKQTPVectorFieldGraphAnchorMid,JKQTPVectorFieldGraphAnchorTip,JKQTPVectorFieldGraphAutoscaleLength,JKQTPVectorFieldGraphLengthFromData,JKQTPVectorFieldGraphIgnoreLength,JKQTPVectorFieldGraphIgnoreLengthAutoscaleLineWidthFromLength,JKQTPVectorFieldGraphAutoscaleLengthAutoscaleLineWidthFromLength/--iteratefunctorsteps paramvectorfield/JKQTPParametrizedVectorFieldGraph,JKQTPParametrizedVectorFieldGraphColorFromMagnitude,JKQTPParametrizedVectorFieldGraphColorFromAngle,JKQTPParametrizedVectorFieldGraphDefaultColor/--iteratefunctorsteps financialgraphs/JKQTPFinancialGraph,JKQTPFinancialGraphCandleStick,JKQTPFinancialGraphSetCandlestickTwoColor,JKQTPFinancialGraphSetCandlestickTwoColor2,JKQTPFinancialGraphSetCandlestickOneColor,JKQTPFinancialGraphOHLC,JKQTPFinancialGraphSetOHLCTwoColor,JKQTPFinancialGraphSidyBySide/--iteratefunctorsteps diff --git a/doc/images/JKQTPGLabelHalfwaysToXAxis.png b/doc/images/JKQTPGLabelHalfwaysToXAxis.png new file mode 100644 index 0000000000..9f33d20bb8 Binary files /dev/null and b/doc/images/JKQTPGLabelHalfwaysToXAxis.png differ diff --git a/doc/images/JKQTPGLabelHalfwaysToYAxis.png b/doc/images/JKQTPGLabelHalfwaysToYAxis.png new file mode 100644 index 0000000000..57b4cd2299 Binary files /dev/null and b/doc/images/JKQTPGLabelHalfwaysToYAxis.png differ diff --git a/examples/graphlabels/graphlabels.cpp b/examples/graphlabels/graphlabels.cpp index f052b427c3..fce85bd72f 100644 --- a/examples/graphlabels/graphlabels.cpp +++ b/examples/graphlabels/graphlabels.cpp @@ -151,6 +151,18 @@ int main(int argc, char* argv[]) plotV.redrawPlot(); plotH.redrawPlot(); }); + app.addExportStepFunctor([&](){ + gV.first->setVisible(true); + gH.first->setVisible(true); + gV.second->setLabelPosition(JKQTPGLabelHalfwaysToXAxis); + gV.second->setLabelBoxType(JKQTPGLSimpleBox); + gV.second->setDrawLabelBoxFrame(false); + gH.second->setLabelPosition(JKQTPGLabelHalfwaysToYAxis); + gH.second->setLabelBoxType(JKQTPGLSimpleBox); + gH.second->setDrawLabelBoxFrame(false); + plotV.redrawPlot(); + plotH.redrawPlot(); + }); return app.exec(); } diff --git a/lib/jkqtplotter/graphs/jkqtpgraphlabels.cpp b/lib/jkqtplotter/graphs/jkqtpgraphlabels.cpp index e6a4361964..85de279ed9 100644 --- a/lib/jkqtplotter/graphs/jkqtpgraphlabels.cpp +++ b/lib/jkqtplotter/graphs/jkqtpgraphlabels.cpp @@ -89,9 +89,11 @@ void JKQTPXYGraphLabels::draw(JKQTPEnhancedPainter& painter) { const double yv=datastore->get(static_cast(yColumn),static_cast(i)); const double x=transformX(xv); const double y=transformY(yv); + const double blXv=(0.0>=parent->getXMin() && 0.0<=parent->getXMax()) ? 0.0 : parent->getXMin(); + const double blYv=(0.0>=parent->getYMin() && 0.0<=parent->getYMax()) ? 0.0 : parent->getYMin(); if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) { const QString label=generateLabel(xv,yv,iii); - drawLabel(painter, QPointF(x,y), QPointF(xv,yv), label, parent); + drawLabel(painter, QPointF(x,y), QPointF(xv,yv), label, parent, blXv, blYv); } } diff --git a/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.cpp b/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.cpp index c6a97b2c8c..1547bc4883 100644 --- a/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.cpp +++ b/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.cpp @@ -36,6 +36,8 @@ QString JKQTPGraphLabelPosition2String(JKQTPGraphLabelPosition pos) case JKQTPGLabelTowardsXAxis: return "label_towards_xaxis"; case JKQTPGLabelTowardsYAxis: return "label_towards_xaxis"; case JKQTPGLabelCenteredOnData: return "label_centered"; + case JKQTPGLabelHalfwaysToXAxis: return "label_halfways_to_xaxis"; + case JKQTPGLabelHalfwaysToYAxis: return "label_halfways_to_yaxis"; } return "label_away_from_xaxis"; } @@ -49,8 +51,10 @@ JKQTPGraphLabelPosition String2JKQTPGraphLabelPosition(const QString &pos) if (m=="label_right_hand_side" || m=="right_hand_side" || m=="right_hand" || m=="right" || m=="rhs") return JKQTPGLabelRightHandSide; if (m=="label_away_from_xaxis" || m=="away_from_xaxis") return JKQTPGLabelAwayFromXAxis; if (m=="label_away_from_yaxis" || m=="away_from_yaxis") return JKQTPGLabelAwayFromYAxis; - if (m=="label_towars_xaxis" || m=="towars_xaxis") return JKQTPGLabelTowardsXAxis; - if (m=="label_towars_yaxis" || m=="towars_yaxis") return JKQTPGLabelTowardsYAxis; + if (m=="label_towards_xaxis" || m=="towardds_xaxis") return JKQTPGLabelTowardsXAxis; + if (m=="label_towards_yaxis" || m=="towars_yaxis") return JKQTPGLabelTowardsYAxis; + if (m=="label_halfways_to_xaxis" || m=="halfways_to_xaxis") return JKQTPGLabelHalfwaysToXAxis; + if (m=="label_halfways_to_yaxis" || m=="halfways_to_yaxis") return JKQTPGLabelHalfwaysToYAxis; if (m=="label_centered" || m=="centered" || m=="label_centered_on_data" || m=="centered_on_data") return JKQTPGLabelCenteredOnData; return JKQTPGraphLabelDefault; } @@ -188,6 +192,8 @@ bool JKQTPGraphValueLabelStyleMixin::isLabelPositioningGrowingInX() const case JKQTPGLabelTowardsXAxis: case JKQTPGLabelTowardsYAxis: case JKQTPGLabelCenteredOnData: + case JKQTPGLabelHalfwaysToXAxis: + case JKQTPGLabelHalfwaysToYAxis: return false; } return false; @@ -206,6 +212,8 @@ bool JKQTPGraphValueLabelStyleMixin::isLabelPositioningGrowingInY() const case JKQTPGLabelLeftHandSide: case JKQTPGLabelRightHandSide: case JKQTPGLabelCenteredOnData: + case JKQTPGLabelHalfwaysToXAxis: + case JKQTPGLabelHalfwaysToYAxis: return false; } return false; @@ -231,12 +239,12 @@ JKQTPGraphLabelBoxType JKQTPGraphValueLabelStyleMixin::getLabelBoxType() const return m_labelBoxType; } -void JKQTPGraphValueLabelStyleMixin::drawLabel(JKQTPEnhancedPainter &painter, const QPointF &xDataPixel, const QPointF &xData, const QString &contents, JKQTBasePlotter *parent) const +void JKQTPGraphValueLabelStyleMixin::drawLabel(JKQTPEnhancedPainter &painter, const QPointF &xDataPixel, const QPointF &xData, const QString &contents, JKQTBasePlotter *parent, double baselineX, double baselineY) const { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); // calculate geometry - const LabelGeometry g=calcLabelGeometry(painter, xDataPixel, xData, contents, parent); + const LabelGeometry g=calcLabelGeometry(painter, xDataPixel, xData, contents, parent, baselineX, baselineY); // draw Box if (m_drawLabelBoxFrame) painter.setPen(getLinePenForRects(painter, parent)); @@ -275,7 +283,7 @@ void JKQTPGraphValueLabelStyleMixin::drawLabel(JKQTPEnhancedPainter &painter, co parent->getMathText()->draw(painter, Qt::AlignVCenter|Qt::AlignHCenter, g.textRect, parent->getCurrentPlotterStyle().debugShowTextBoxes); } -JKQTPGraphValueLabelStyleMixin::LabelGeometry JKQTPGraphValueLabelStyleMixin::calcLabelGeometry(JKQTPEnhancedPainter &painter, const QPointF &xDataPixel, const QPointF &xData, const QString &contents, JKQTBasePlotter *parent) const +JKQTPGraphValueLabelStyleMixin::LabelGeometry JKQTPGraphValueLabelStyleMixin::calcLabelGeometry(JKQTPEnhancedPainter &painter, const QPointF &xDataPixel, const QPointF &xData, const QString &contents, JKQTBasePlotter *parent, double baselineX, double baselineY) const { LabelGeometry res; res.label=contents; @@ -304,6 +312,12 @@ JKQTPGraphValueLabelStyleMixin::LabelGeometry JKQTPGraphValueLabelStyleMixin::ca } else if (m_labelPosition==JKQTPGLabelCenteredOnData) { res.textRect=QRectF(xDataPixel.x()-res.textSize.width/2.0, xDataPixel.y()-res.textSize.overallHeight/2.0, res.textSize.width, res.textSize.overallHeight); res.boxpos=LabelGeometry::BoxCentered; + } else if (m_labelPosition==JKQTPGLabelHalfwaysToXAxis) { + res.textRect=QRectF(xDataPixel.x()-res.textSize.width/2.0, (xDataPixel.y()+parent->getYAxis()->x2p(baselineY))/2.0-res.textSize.overallHeight/2.0, res.textSize.width, res.textSize.overallHeight); + res.boxpos=LabelGeometry::BoxCentered; + } else if (m_labelPosition==JKQTPGLabelHalfwaysToYAxis) { + res.textRect=QRectF((xDataPixel.x()+parent->getXAxis()->x2p(baselineX))/2.0-res.textSize.width/2.0, xDataPixel.y()-res.textSize.overallHeight/2.0, res.textSize.width, res.textSize.overallHeight); + res.boxpos=LabelGeometry::BoxCentered; } res.boxRect=QRectF(res.textRect.x()-res.padX-res.lw/2.0, res.textRect.y()-res.padY-res.lw/2.0, res.textRect.width()+res.padX*2.0+res.lw, res.textRect.height()+res.padY*2.0+res.lw); diff --git a/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.h b/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.h index bd9c286fa1..12f5ea1800 100644 --- a/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.h +++ b/lib/jkqtplotter/graphs/jkqtpgraphlabelstylemixin.h @@ -53,6 +53,8 @@ enum JKQTPGraphLabelPosition { JKQTPGLabelTowardsYAxis, /*!< \brief all labels between the datapoint and the y-axis the datapoint \image html JKQTPGLabelTowardsYAxis.png */ JKQTPGLabelAwayFromYAxis, /*!< \brief all labels pointing away from the y-axis \image html JKQTPGLabelAwayFromYAxis.png */ JKQTPGLabelCenteredOnData, /*!< \brief graph label is drawn centered arond the data point \c (x,y) \image html JKQTPGLabelCenteredOnData.png */ + JKQTPGLabelHalfwaysToXAxis, /*!< \brief all labels half-ways between the datapoint and the x-axis the datapoint \image html JKQTPGLabelHalfwaysToXAxis.png */ + JKQTPGLabelHalfwaysToYAxis, /*!< \brief all labels half-ways between the datapoint and the y-axis the datapoint \image html JKQTPGLabelHalfwaysToYAxis.png */ JKQTPGraphLabelDefault=JKQTPGLabelAwayFromXAxis, @@ -182,9 +184,11 @@ public: * \brief xData x- and y-coordinate of the datapoint (needed for some JKQTPGraphLabelPosition) * \brief contents the text to be rendered * \brief parent the JKQTPBasePlotter in whos context we are drawing (e.g. needed to render \a contents ) + * \brief baselineX baseline (in graph coordinate system, not pixels) of the graph in x-direction (typically 0), needed for JKQTPGLabelHalfwaysToYAxis + * \brief baselineY baseline (in graph coordinate system, not pixels) of the graph in y-direction (typically 0), needed for JKQTPGLabelHalfwaysToXAxis * */ - void drawLabel(JKQTPEnhancedPainter& painter, const QPointF& xDataPixel, const QPointF& xData, const QString& contents, JKQTBasePlotter *parent) const; + void drawLabel(JKQTPEnhancedPainter& painter, const QPointF& xDataPixel, const QPointF& xData, const QString& contents, JKQTBasePlotter *parent, double baselineX, double baselineY) const; @@ -238,9 +242,11 @@ protected: * \brief xData x- and y-coordinate of the datapoint (needed for some JKQTPGraphLabelPosition) * \brief contents the text to be rendered * \brief parent the JKQTPBasePlotter in whos context we are drawing (e.g. needed to render \a contents ) + * \brief baselineX baseline (in graph coordinate system, not pixels) of the graph in x-direction (typically 0), needed for JKQTPGLabelHalfwaysToYAxis + * \brief baselineY baseline (in graph coordinate system, not pixels) of the graph in y-direction (typically 0), needed for JKQTPGLabelHalfwaysToXAxis * */ - LabelGeometry calcLabelGeometry(JKQTPEnhancedPainter& painter, const QPointF& xDataPixel, const QPointF& xData, const QString& contents, JKQTBasePlotter *parent) const; + LabelGeometry calcLabelGeometry(JKQTPEnhancedPainter& painter, const QPointF& xDataPixel, const QPointF& xData, const QString& contents, JKQTBasePlotter *parent, double baselineX, double baselineY) const; private: /** \brief offset of the box rectangle to the actual data point location [pt], this is used for simple boxes and is a rather close distance (e.g. JKQTPGLSimpleBox)