diff --git a/src/axis/horizontalaxis.cpp b/src/axis/horizontalaxis.cpp index ac8ccc8..4aef626 100644 --- a/src/axis/horizontalaxis.cpp +++ b/src/axis/horizontalaxis.cpp @@ -73,23 +73,10 @@ void HorizontalAxis::updateGeometry() if (!titleText.isEmpty() && titleItem()->isVisible()) { availableSpace -= titlePadding() * 2.0; qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height(); - QString truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), - gridRect.width(), Qt::Horizontal, titleBoundingRect); qreal titleSpace = availableSpace - minimumLabelHeight; - if (titleSpace < titleBoundingRect.height()) { - // Need to also truncate title vertically (multiline title) - bool skip = false; - if (truncatedTitle.endsWith("...")) { - if (truncatedTitle.size() == 3) - skip = true; // Already truncated to minimum - else - truncatedTitle.chop(3); - } - if (!skip) - truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), truncatedTitle, qreal(0.0), - titleSpace, Qt::Vertical, titleBoundingRect); - } - title->setHtml(truncatedTitle); + title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), + gridRect.width(), titleSpace, + titleBoundingRect)); titleBoundingRect = title->boundingRect(); @@ -114,8 +101,15 @@ void HorizontalAxis::updateGeometry() //label text wrapping QString text = labelList.at(i); QRectF boundingRect; - labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(), - availableSpace, Qt::Vertical, boundingRect)); + // don't truncate empty labels + if (text.isEmpty()) { + labelItem->setHtml(text); + } else { + qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding()); + labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, + axis()->labelsAngle(), labelWidth, + availableSpace, boundingRect)); + } //label transformation origin point const QRectF& rect = labelItem->boundingRect(); @@ -141,16 +135,18 @@ void HorizontalAxis::updateGeometry() const qreal delta = rightBound - leftBound; // Hide label in case visible part of the category at the grid edge is too narrow if (delta < boundingRect.width() - && (leftBound == gridRect.left() || rightBound == gridRect.right())) { + && (leftBound == gridRect.left() || rightBound == gridRect.right()) + && !intervalAxis()) { forceHide = true; } else { labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y()); } } //label overlap detection - compensate one pixel for rounding errors - if (labelItem->pos().x() < width || forceHide || + if ((labelItem->pos().x() < width || forceHide || (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) || - (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()){ + (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()) + && !intervalAxis()) { labelItem->setVisible(false); } else { labelItem->setVisible(true); diff --git a/src/axis/polarchartaxisangular.cpp b/src/axis/polarchartaxisangular.cpp index f82b3f2..69af03c 100644 --- a/src/axis/polarchartaxisangular.cpp +++ b/src/axis/polarchartaxisangular.cpp @@ -222,7 +222,12 @@ void PolarChartAxisAngular::updateGeometry() QString titleText = axis()->titleText(); if (!titleText.isEmpty() && axis()->isTitleVisible()) { QRectF dummyRect; - title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), axisGeometry().width(), Qt::Horizontal, dummyRect)); + qreal availableTitleHeight = axisGeometry().height() - labelPadding() - titlePadding() * 2.0; + qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height(); + availableTitleHeight -= minimumLabelHeight; + title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), + axisGeometry().width(), availableTitleHeight, + dummyRect)); QRectF titleBoundingRect = title->boundingRect(); QPointF titleCenter = center - titleBoundingRect.center(); diff --git a/src/axis/polarchartaxisradial.cpp b/src/axis/polarchartaxisradial.cpp index bfb2732..2587b91 100644 --- a/src/axis/polarchartaxisradial.cpp +++ b/src/axis/polarchartaxisradial.cpp @@ -205,7 +205,8 @@ void PolarChartAxisRadial::updateGeometry() QString titleText = axis()->titleText(); if (!titleText.isEmpty() && axis()->isTitleVisible()) { QRectF dummyRect; - title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), radius, Qt::Horizontal, dummyRect)); + title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), + radius, radius, dummyRect)); QRectF titleBoundingRect = title->boundingRect(); QPointF titleCenter = titleBoundingRect.center(); diff --git a/src/axis/verticalaxis.cpp b/src/axis/verticalaxis.cpp index e0d3451..2986b51 100644 --- a/src/axis/verticalaxis.cpp +++ b/src/axis/verticalaxis.cpp @@ -74,23 +74,10 @@ void VerticalAxis::updateGeometry() if (!titleText.isEmpty() && titleItem()->isVisible()) { availableSpace -= titlePadding() * 2.0; qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").width(); - QString truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), - gridRect.height(), Qt::Horizontal, titleBoundingRect); qreal titleSpace = availableSpace - minimumLabelWidth; - if (titleSpace < titleBoundingRect.height()) { - // Need to also truncate title vertically (multiline title) - bool skip = false; - if (truncatedTitle.endsWith("...")) { - if (truncatedTitle.size() == 3) - skip = true; // Already truncated to minimum - else - truncatedTitle.chop(3); - } - if (!skip) - truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), truncatedTitle, qreal(0.0), - titleSpace, Qt::Vertical, titleBoundingRect); - } - title->setHtml(truncatedTitle); + title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0), + titleSpace, gridRect.height(), + titleBoundingRect)); titleBoundingRect = title->boundingRect(); @@ -118,8 +105,15 @@ void VerticalAxis::updateGeometry() //label text wrapping QString text = labelList.at(i); QRectF boundingRect; - labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(), - availableSpace, Qt::Horizontal, boundingRect)); + // don't truncate empty labels + if (text.isEmpty()) { + labelItem->setHtml(text); + } else { + qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding()); + labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, + axis()->labelsAngle(), availableSpace, + labelHeight, boundingRect)); + } //label transformation origin point const QRectF &rect = labelItem->boundingRect(); @@ -145,7 +139,8 @@ void VerticalAxis::updateGeometry() const qreal delta = lowerBound - upperBound; // Hide label in case visible part of the category at the grid edge is too narrow if (delta < boundingRect.height() - && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) { + && (lowerBound == gridRect.bottom() || upperBound == gridRect.top()) + && !intervalAxis()) { forceHide = true; } else { labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y()); @@ -153,9 +148,10 @@ void VerticalAxis::updateGeometry() } //label overlap detection - compensate one pixel for rounding errors - if (labelItem->pos().y() + boundingRect.height() > height || forceHide || + if ((labelItem->pos().y() + boundingRect.height() > height || forceHide || (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() || - labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) { + labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) + && !intervalAxis()) { labelItem->setVisible(false); } else { diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp index 765a228..9bf9d2a 100644 --- a/src/chartpresenter.cpp +++ b/src/chartpresenter.cpp @@ -410,14 +410,11 @@ QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, // boundingRect parameter returns the rotated bounding rect of the text QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle, - qreal maxSize, Qt::Orientation constraintOrientation, - QRectF &boundingRect) + qreal maxWidth, qreal maxHeight, QRectF &boundingRect) { QString truncatedString(text); boundingRect = textBoundingRect(font, truncatedString, angle); - qreal checkDimension = ((constraintOrientation == Qt::Horizontal) - ? boundingRect.width() : boundingRect.height()); - if (checkDimension > maxSize) { + if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) { // It can be assumed that almost any amount of string manipulation is faster // than calculating one bounding rectangle, so first prepare a list of truncated strings // to try. @@ -452,12 +449,11 @@ QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qr int maxIndex(count - 1); int bestIndex(count); QRectF checkRect; + while (maxIndex >= minIndex) { int mid = (maxIndex + minIndex) / 2; checkRect = textBoundingRect(font, testStrings.at(mid), angle); - checkDimension = ((constraintOrientation == Qt::Horizontal) - ? checkRect.width() : checkRect.height()); - if (checkDimension > maxSize) { + if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) { // Checked index too large, all under this are also too large minIndex = mid + 1; } else { diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h index 93a616f..116aa6a 100644 --- a/src/chartpresenter_p.h +++ b/src/chartpresenter_p.h @@ -145,8 +145,8 @@ public: QChart *chart() { return m_chart; } static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0); - static QString truncatedText(const QFont &font, const QString &text, qreal angle, qreal maxSize, - Qt::Orientation constraintOrientation, QRectF &boundingRect); + static QString truncatedText(const QFont &font, const QString &text, qreal angle, + qreal maxWidth, qreal maxHeight, QRectF &boundingRect); inline static qreal textMargin() { return qreal(0.5); } private: void createBackgroundItem(); diff --git a/src/charttitle.cpp b/src/charttitle.cpp index d5306cf..d6fd0e0 100644 --- a/src/charttitle.cpp +++ b/src/charttitle.cpp @@ -51,7 +51,9 @@ QString ChartTitle::text() const void ChartTitle::setGeometry(const QRectF &rect) { QRectF dummyRect; - QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0), rect.width(), Qt::Horizontal, dummyRect)); + QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0), + rect.width(), rect.height(), + dummyRect)); setPos(rect.topLeft()); } diff --git a/src/legend/legendmarkeritem.cpp b/src/legend/legendmarkeritem.cpp index fbd809f..0fe48a9 100644 --- a/src/legend/legendmarkeritem.cpp +++ b/src/legend/legendmarkeritem.cpp @@ -116,7 +116,8 @@ void LegendMarkerItem::setGeometry(const QRectF &rect) qreal x = m_margin + m_markerRect.width() + m_space + m_margin; QRectF truncatedRect; - m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0), width - x, Qt::Horizontal, truncatedRect)); + m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0), + width - x, rect.height(), truncatedRect)); qreal y = qMax(m_markerRect.height() + 2 * m_margin, truncatedRect.height() + 2 * m_margin); diff --git a/src/piechart/piesliceitem.cpp b/src/piechart/piesliceitem.cpp index b0de3f7..aaca4a8 100644 --- a/src/piechart/piesliceitem.cpp +++ b/src/piechart/piesliceitem.cpp @@ -94,9 +94,11 @@ void PieSliceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o painter->setClipRect(parentItem()->boundingRect()); painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color()); if (fm.width(m_data.m_labelText) > m_labelTextRect.width()) { + // Only one line label text is supported currently. + // The height for the label is set one pixel over the font metrics. label = ChartPresenter::truncatedText(m_data.m_labelFont, m_data.m_labelText, qreal(0.0), m_labelTextRect.width(), - Qt::Horizontal, labelBoundingRect); + fm.height() + 1.0, labelBoundingRect); } painter->drawText(m_labelTextRect, Qt::AlignCenter, label); break;