@@ -73,23 +73,10 void HorizontalAxis::updateGeometry() | |||||
73 | if (!titleText.isEmpty() && titleItem()->isVisible()) { |
|
73 | if (!titleText.isEmpty() && titleItem()->isVisible()) { | |
74 | availableSpace -= titlePadding() * 2.0; |
|
74 | availableSpace -= titlePadding() * 2.0; | |
75 | qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height(); |
|
75 | qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height(); | |
76 | QString truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), |
|
|||
77 | gridRect.width(), Qt::Horizontal, titleBoundingRect); |
|
|||
78 | qreal titleSpace = availableSpace - minimumLabelHeight; |
|
76 | qreal titleSpace = availableSpace - minimumLabelHeight; | |
79 | if (titleSpace < titleBoundingRect.height()) { |
|
77 | title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), | |
80 | // Need to also truncate title vertically (multiline title) |
|
78 | gridRect.width(), titleSpace, | |
81 | bool skip = false; |
|
79 | titleBoundingRect)); | |
82 | if (truncatedTitle.endsWith("...")) { |
|
|||
83 | if (truncatedTitle.size() == 3) |
|
|||
84 | skip = true; // Already truncated to minimum |
|
|||
85 | else |
|
|||
86 | truncatedTitle.chop(3); |
|
|||
87 | } |
|
|||
88 | if (!skip) |
|
|||
89 | truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), truncatedTitle, qreal(0.0), |
|
|||
90 | titleSpace, Qt::Vertical, titleBoundingRect); |
|
|||
91 | } |
|
|||
92 | title->setHtml(truncatedTitle); |
|
|||
93 |
|
80 | |||
94 | titleBoundingRect = title->boundingRect(); |
|
81 | titleBoundingRect = title->boundingRect(); | |
95 |
|
82 | |||
@@ -114,8 +101,15 void HorizontalAxis::updateGeometry() | |||||
114 | //label text wrapping |
|
101 | //label text wrapping | |
115 | QString text = labelList.at(i); |
|
102 | QString text = labelList.at(i); | |
116 | QRectF boundingRect; |
|
103 | QRectF boundingRect; | |
117 | labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(), |
|
104 | // don't truncate empty labels | |
118 | availableSpace, Qt::Vertical, boundingRect)); |
|
105 | if (text.isEmpty()) { | |
|
106 | labelItem->setHtml(text); | |||
|
107 | } else { | |||
|
108 | qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding()); | |||
|
109 | labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, | |||
|
110 | axis()->labelsAngle(), labelWidth, | |||
|
111 | availableSpace, boundingRect)); | |||
|
112 | } | |||
119 |
|
113 | |||
120 | //label transformation origin point |
|
114 | //label transformation origin point | |
121 | const QRectF& rect = labelItem->boundingRect(); |
|
115 | const QRectF& rect = labelItem->boundingRect(); | |
@@ -141,16 +135,18 void HorizontalAxis::updateGeometry() | |||||
141 | const qreal delta = rightBound - leftBound; |
|
135 | const qreal delta = rightBound - leftBound; | |
142 | // Hide label in case visible part of the category at the grid edge is too narrow |
|
136 | // Hide label in case visible part of the category at the grid edge is too narrow | |
143 | if (delta < boundingRect.width() |
|
137 | if (delta < boundingRect.width() | |
144 |
&& (leftBound == gridRect.left() || rightBound == gridRect.right()) |
|
138 | && (leftBound == gridRect.left() || rightBound == gridRect.right()) | |
|
139 | && !intervalAxis()) { | |||
145 | forceHide = true; |
|
140 | forceHide = true; | |
146 | } else { |
|
141 | } else { | |
147 | labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y()); |
|
142 | labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y()); | |
148 | } |
|
143 | } | |
149 | } |
|
144 | } | |
150 | //label overlap detection - compensate one pixel for rounding errors |
|
145 | //label overlap detection - compensate one pixel for rounding errors | |
151 | if (labelItem->pos().x() < width || forceHide || |
|
146 | if ((labelItem->pos().x() < width || forceHide || | |
152 | (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) || |
|
147 | (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) || | |
153 |
(labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()) |
|
148 | (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()) | |
|
149 | && !intervalAxis()) { | |||
154 | labelItem->setVisible(false); |
|
150 | labelItem->setVisible(false); | |
155 | } else { |
|
151 | } else { | |
156 | labelItem->setVisible(true); |
|
152 | labelItem->setVisible(true); |
@@ -222,7 +222,12 void PolarChartAxisAngular::updateGeometry() | |||||
222 | QString titleText = axis()->titleText(); |
|
222 | QString titleText = axis()->titleText(); | |
223 | if (!titleText.isEmpty() && axis()->isTitleVisible()) { |
|
223 | if (!titleText.isEmpty() && axis()->isTitleVisible()) { | |
224 | QRectF dummyRect; |
|
224 | QRectF dummyRect; | |
225 | title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), axisGeometry().width(), Qt::Horizontal, dummyRect)); |
|
225 | qreal availableTitleHeight = axisGeometry().height() - labelPadding() - titlePadding() * 2.0; | |
|
226 | qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height(); | |||
|
227 | availableTitleHeight -= minimumLabelHeight; | |||
|
228 | title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), | |||
|
229 | axisGeometry().width(), availableTitleHeight, | |||
|
230 | dummyRect)); | |||
226 |
|
231 | |||
227 | QRectF titleBoundingRect = title->boundingRect(); |
|
232 | QRectF titleBoundingRect = title->boundingRect(); | |
228 | QPointF titleCenter = center - titleBoundingRect.center(); |
|
233 | QPointF titleCenter = center - titleBoundingRect.center(); |
@@ -205,7 +205,8 void PolarChartAxisRadial::updateGeometry() | |||||
205 | QString titleText = axis()->titleText(); |
|
205 | QString titleText = axis()->titleText(); | |
206 | if (!titleText.isEmpty() && axis()->isTitleVisible()) { |
|
206 | if (!titleText.isEmpty() && axis()->isTitleVisible()) { | |
207 | QRectF dummyRect; |
|
207 | QRectF dummyRect; | |
208 |
title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), |
|
208 | title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), | |
|
209 | radius, radius, dummyRect)); | |||
209 |
|
210 | |||
210 | QRectF titleBoundingRect = title->boundingRect(); |
|
211 | QRectF titleBoundingRect = title->boundingRect(); | |
211 | QPointF titleCenter = titleBoundingRect.center(); |
|
212 | QPointF titleCenter = titleBoundingRect.center(); |
@@ -74,23 +74,10 void VerticalAxis::updateGeometry() | |||||
74 | if (!titleText.isEmpty() && titleItem()->isVisible()) { |
|
74 | if (!titleText.isEmpty() && titleItem()->isVisible()) { | |
75 | availableSpace -= titlePadding() * 2.0; |
|
75 | availableSpace -= titlePadding() * 2.0; | |
76 | qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").width(); |
|
76 | qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").width(); | |
77 | QString truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0), |
|
|||
78 | gridRect.height(), Qt::Horizontal, titleBoundingRect); |
|
|||
79 | qreal titleSpace = availableSpace - minimumLabelWidth; |
|
77 | qreal titleSpace = availableSpace - minimumLabelWidth; | |
80 | if (titleSpace < titleBoundingRect.height()) { |
|
78 | title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0), | |
81 | // Need to also truncate title vertically (multiline title) |
|
79 | titleSpace, gridRect.height(), | |
82 | bool skip = false; |
|
80 | titleBoundingRect)); | |
83 | if (truncatedTitle.endsWith("...")) { |
|
|||
84 | if (truncatedTitle.size() == 3) |
|
|||
85 | skip = true; // Already truncated to minimum |
|
|||
86 | else |
|
|||
87 | truncatedTitle.chop(3); |
|
|||
88 | } |
|
|||
89 | if (!skip) |
|
|||
90 | truncatedTitle = ChartPresenter::truncatedText(axis()->titleFont(), truncatedTitle, qreal(0.0), |
|
|||
91 | titleSpace, Qt::Vertical, titleBoundingRect); |
|
|||
92 | } |
|
|||
93 | title->setHtml(truncatedTitle); |
|
|||
94 |
|
81 | |||
95 | titleBoundingRect = title->boundingRect(); |
|
82 | titleBoundingRect = title->boundingRect(); | |
96 |
|
83 | |||
@@ -118,8 +105,15 void VerticalAxis::updateGeometry() | |||||
118 | //label text wrapping |
|
105 | //label text wrapping | |
119 | QString text = labelList.at(i); |
|
106 | QString text = labelList.at(i); | |
120 | QRectF boundingRect; |
|
107 | QRectF boundingRect; | |
121 | labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(), |
|
108 | // don't truncate empty labels | |
122 | availableSpace, Qt::Horizontal, boundingRect)); |
|
109 | if (text.isEmpty()) { | |
|
110 | labelItem->setHtml(text); | |||
|
111 | } else { | |||
|
112 | qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding()); | |||
|
113 | labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text, | |||
|
114 | axis()->labelsAngle(), availableSpace, | |||
|
115 | labelHeight, boundingRect)); | |||
|
116 | } | |||
123 |
|
117 | |||
124 | //label transformation origin point |
|
118 | //label transformation origin point | |
125 | const QRectF &rect = labelItem->boundingRect(); |
|
119 | const QRectF &rect = labelItem->boundingRect(); | |
@@ -145,7 +139,8 void VerticalAxis::updateGeometry() | |||||
145 | const qreal delta = lowerBound - upperBound; |
|
139 | const qreal delta = lowerBound - upperBound; | |
146 | // Hide label in case visible part of the category at the grid edge is too narrow |
|
140 | // Hide label in case visible part of the category at the grid edge is too narrow | |
147 | if (delta < boundingRect.height() |
|
141 | if (delta < boundingRect.height() | |
148 |
&& (lowerBound == gridRect.bottom() || upperBound == gridRect.top()) |
|
142 | && (lowerBound == gridRect.bottom() || upperBound == gridRect.top()) | |
|
143 | && !intervalAxis()) { | |||
149 | forceHide = true; |
|
144 | forceHide = true; | |
150 | } else { |
|
145 | } else { | |
151 | labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y()); |
|
146 | labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y()); | |
@@ -153,9 +148,10 void VerticalAxis::updateGeometry() | |||||
153 | } |
|
148 | } | |
154 |
|
149 | |||
155 | //label overlap detection - compensate one pixel for rounding errors |
|
150 | //label overlap detection - compensate one pixel for rounding errors | |
156 | if (labelItem->pos().y() + boundingRect.height() > height || forceHide || |
|
151 | if ((labelItem->pos().y() + boundingRect.height() > height || forceHide || | |
157 | (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() || |
|
152 | (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() || | |
158 |
labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) |
|
153 | labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) | |
|
154 | && !intervalAxis()) { | |||
159 | labelItem->setVisible(false); |
|
155 | labelItem->setVisible(false); | |
160 | } |
|
156 | } | |
161 | else { |
|
157 | else { |
@@ -410,14 +410,11 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, | |||||
410 |
|
410 | |||
411 | // boundingRect parameter returns the rotated bounding rect of the text |
|
411 | // boundingRect parameter returns the rotated bounding rect of the text | |
412 | QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle, |
|
412 | QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle, | |
413 |
qreal max |
|
413 | qreal maxWidth, qreal maxHeight, QRectF &boundingRect) | |
414 | QRectF &boundingRect) |
|
|||
415 | { |
|
414 | { | |
416 | QString truncatedString(text); |
|
415 | QString truncatedString(text); | |
417 | boundingRect = textBoundingRect(font, truncatedString, angle); |
|
416 | boundingRect = textBoundingRect(font, truncatedString, angle); | |
418 | qreal checkDimension = ((constraintOrientation == Qt::Horizontal) |
|
417 | if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) { | |
419 | ? boundingRect.width() : boundingRect.height()); |
|
|||
420 | if (checkDimension > maxSize) { |
|
|||
421 | // It can be assumed that almost any amount of string manipulation is faster |
|
418 | // It can be assumed that almost any amount of string manipulation is faster | |
422 | // than calculating one bounding rectangle, so first prepare a list of truncated strings |
|
419 | // than calculating one bounding rectangle, so first prepare a list of truncated strings | |
423 | // to try. |
|
420 | // to try. | |
@@ -452,12 +449,11 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qr | |||||
452 | int maxIndex(count - 1); |
|
449 | int maxIndex(count - 1); | |
453 | int bestIndex(count); |
|
450 | int bestIndex(count); | |
454 | QRectF checkRect; |
|
451 | QRectF checkRect; | |
|
452 | ||||
455 | while (maxIndex >= minIndex) { |
|
453 | while (maxIndex >= minIndex) { | |
456 | int mid = (maxIndex + minIndex) / 2; |
|
454 | int mid = (maxIndex + minIndex) / 2; | |
457 | checkRect = textBoundingRect(font, testStrings.at(mid), angle); |
|
455 | checkRect = textBoundingRect(font, testStrings.at(mid), angle); | |
458 | checkDimension = ((constraintOrientation == Qt::Horizontal) |
|
456 | if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) { | |
459 | ? checkRect.width() : checkRect.height()); |
|
|||
460 | if (checkDimension > maxSize) { |
|
|||
461 | // Checked index too large, all under this are also too large |
|
457 | // Checked index too large, all under this are also too large | |
462 | minIndex = mid + 1; |
|
458 | minIndex = mid + 1; | |
463 | } else { |
|
459 | } else { |
@@ -145,8 +145,8 public: | |||||
145 | QChart *chart() { return m_chart; } |
|
145 | QChart *chart() { return m_chart; } | |
146 |
|
146 | |||
147 | static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0); |
|
147 | static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0); | |
148 |
static QString truncatedText(const QFont &font, const QString &text, qreal angle, |
|
148 | static QString truncatedText(const QFont &font, const QString &text, qreal angle, | |
149 |
|
|
149 | qreal maxWidth, qreal maxHeight, QRectF &boundingRect); | |
150 | inline static qreal textMargin() { return qreal(0.5); } |
|
150 | inline static qreal textMargin() { return qreal(0.5); } | |
151 | private: |
|
151 | private: | |
152 | void createBackgroundItem(); |
|
152 | void createBackgroundItem(); |
@@ -51,7 +51,9 QString ChartTitle::text() const | |||||
51 | void ChartTitle::setGeometry(const QRectF &rect) |
|
51 | void ChartTitle::setGeometry(const QRectF &rect) | |
52 | { |
|
52 | { | |
53 | QRectF dummyRect; |
|
53 | QRectF dummyRect; | |
54 |
QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0), |
|
54 | QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0), | |
|
55 | rect.width(), rect.height(), | |||
|
56 | dummyRect)); | |||
55 | setPos(rect.topLeft()); |
|
57 | setPos(rect.topLeft()); | |
56 | } |
|
58 | } | |
57 |
|
59 |
@@ -116,7 +116,8 void LegendMarkerItem::setGeometry(const QRectF &rect) | |||||
116 | qreal x = m_margin + m_markerRect.width() + m_space + m_margin; |
|
116 | qreal x = m_margin + m_markerRect.width() + m_space + m_margin; | |
117 | QRectF truncatedRect; |
|
117 | QRectF truncatedRect; | |
118 |
|
118 | |||
119 |
m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0), |
|
119 | m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0), | |
|
120 | width - x, rect.height(), truncatedRect)); | |||
120 |
|
121 | |||
121 | qreal y = qMax(m_markerRect.height() + 2 * m_margin, truncatedRect.height() + 2 * m_margin); |
|
122 | qreal y = qMax(m_markerRect.height() + 2 * m_margin, truncatedRect.height() + 2 * m_margin); | |
122 |
|
123 |
@@ -94,9 +94,11 void PieSliceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o | |||||
94 | painter->setClipRect(parentItem()->boundingRect()); |
|
94 | painter->setClipRect(parentItem()->boundingRect()); | |
95 | painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color()); |
|
95 | painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color()); | |
96 | if (fm.width(m_data.m_labelText) > m_labelTextRect.width()) { |
|
96 | if (fm.width(m_data.m_labelText) > m_labelTextRect.width()) { | |
|
97 | // Only one line label text is supported currently. | |||
|
98 | // The height for the label is set one pixel over the font metrics. | |||
97 | label = ChartPresenter::truncatedText(m_data.m_labelFont, m_data.m_labelText, |
|
99 | label = ChartPresenter::truncatedText(m_data.m_labelFont, m_data.m_labelText, | |
98 | qreal(0.0), m_labelTextRect.width(), |
|
100 | qreal(0.0), m_labelTextRect.width(), | |
99 |
|
|
101 | fm.height() + 1.0, labelBoundingRect); | |
100 | } |
|
102 | } | |
101 | painter->drawText(m_labelTextRect, Qt::AlignCenter, label); |
|
103 | painter->drawText(m_labelTextRect, Qt::AlignCenter, label); | |
102 | break; |
|
104 | break; |
General Comments 0
You need to be logged in to leave comments.
Login now