##// END OF EJS Templates
Fix long labels visibility for QBarChart...
Titta Heikkala -
r2604:776457a845dd
parent child
Show More
@@ -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), radius, Qt::Horizontal, dummyRect));
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 maxSize, Qt::Orientation constraintOrientation,
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, qreal maxSize,
148 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
149 Qt::Orientation constraintOrientation, QRectF &boundingRect);
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), rect.width(), Qt::Horizontal, dummyRect));
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), width - x, Qt::Horizontal, truncatedRect));
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 Qt::Horizontal, labelBoundingRect);
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