##// END OF EJS Templates
Reimplement zoom/scroll hanling for barcategoryaxis Y
Michal Klocek -
r2145:2a67480b6cc7
parent child
Show More
@@ -1,27 +1,33
1 1 INCLUDEPATH += $$PWD
2 2 DEPENDPATH += $$PWD
3 3 SOURCES += \
4 4 font/font.cpp \
5 5 xyseries/linechart.cpp \
6 6 xyseries/scatterchart.cpp \
7 7 xyseries/splinechart.cpp \
8 8 xyseries/areachart.cpp \
9 9 barseries/verticalstackedbarchart.cpp \
10 10 barseries/horizontalstackedbarchart.cpp \
11 11 barseries/verticalbarchart.cpp \
12 12 barseries/horizontalbarchart.cpp \
13 13 barseries/horizontalpercentbarchart.cpp \
14 14 barseries/verticalpercentbarchart.cpp \
15 15 pieseries/piechart.cpp \
16 16 pieseries/donutchart.cpp \
17 17 axis/valueaxis.cpp \
18 18 axis/categoryaxis.cpp \
19 19 axis/barcategoryaxisx.cpp \
20 20 axis/barcategoryaxisy.cpp \
21 21 axis/datetimeaxisx.cpp \
22 22 axis/datetimeaxisy.cpp \
23 axis/valueaxis2.cpp \
24 axis/categoryaxis2.cpp \
25 axis/barcategoryaxisx2.cpp \
26 axis/barcategoryaxisy2.cpp \
27 axis/datetimeaxisx2.cpp \
28 axis/datetimeaxisy2.cpp \
23 29 multiaxis/multivalueaxis.cpp \
24 30 multiaxis/multivalueaxis2.cpp \
25 31 multiaxis/multivalueaxis3.cpp \
26 32 multiaxis/multivalueaxis4.cpp \
27 33 multiaxis/multivaluebaraxis.cpp No newline at end of file
@@ -1,148 +1,143
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartbarcategoryaxisx_p.h"
22 22 #include "chartpresenter_p.h"
23 23 #include "qbarcategoryaxis_p.h"
24 24 #include <QFontMetrics>
25 25 #include <QDebug>
26 26 #include <qmath.h>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 ChartBarCategoryAxisX::ChartBarCategoryAxisX(QBarCategoryAxis *axis, ChartPresenter *presenter)
31 31 : HorizontalAxis(axis, presenter, true),
32 32 m_categoriesAxis(axis)
33 33 {
34 34
35 35 }
36 36
37 37 ChartBarCategoryAxisX::~ChartBarCategoryAxisX()
38 38 {
39 39 }
40 40
41 41 QVector<qreal> ChartBarCategoryAxisX::calculateLayout() const
42 42 {
43 43 QVector<qreal> points;
44
45 44 const QRectF& gridRect = gridGeometry();
46 45 qreal range = max() - min();
47
48 46 const qreal delta = gridRect.width()/range;
49 47
50 48 if(delta<2) return points;
51 49
52 50 qreal offset =-min()-0.5;
53
54 51 offset = int(offset * delta)%int(delta);
55 52
56 53 int count = qFloor(range);
57
58 54 if(count < 1 ) return points;
59 55
60 56 points.resize(count+2);
61 57
62 58 for (int i = 0; i < count+2; ++i) {
63 qreal x = offset + i * delta + gridRect.left();
64 points[i] = x;
59 points[i] = offset + i * delta + gridRect.left();
65 60 }
66 61
67 62 return points;
68 63 }
69 64
70 65 QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& layout) const
71 66 {
72 67 QStringList result ;
73 68 const QRectF &gridRect = gridGeometry();
74
75 69 qreal d = (max() - min()) / gridRect.width();
70
76 71 for (int i = 0; i < layout.count() - 1; ++i) {
77 72 qreal x = qFloor((((layout[i] + layout[i + 1]) / 2 - gridRect.left()) * d + min() + 0.5));
78 73 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
79 74 result << m_categoriesAxis->categories().at(x);
80 75 } else {
81 76 // No label for x coordinate
82 77 result << "";
83 78 }
84 79 }
85 80 result << "";
86 81 return result;
87 82 }
88 83
89 84
90 85 void ChartBarCategoryAxisX::updateGeometry()
91 86 {
92 87 const QVector<qreal>& layout = ChartAxis::layout();
93 88 if (layout.isEmpty())
94 89 return;
95 90 setLabels(createCategoryLabels(layout));
96 91 HorizontalAxis::updateGeometry();
97 92 }
98 93
99 94 void ChartBarCategoryAxisX::handleAxisUpdated()
100 95 {
101 96 if (m_categoriesAxis->categories() != m_categories) {
102 97 m_categories = m_categoriesAxis->categories();
103 98 if (ChartAxis::layout().count() == m_categoriesAxis->d_ptr->count() + 2)
104 99 updateGeometry();
105 100 }
106 101 ChartAxis::handleAxisUpdated();
107 102 }
108 103
109 104 QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
110 105 {
111 106 Q_UNUSED(constraint)
112 107
113 108 QFontMetrics fn(font());
114 109 QSizeF sh;
115 110 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
116 111 QStringList ticksList = createCategoryLabels(ChartAxis::layout());
117 112
118 113 qreal width=0;
119 114 qreal height=0;
120 115
121 116 switch (which) {
122 117 case Qt::MinimumSize:
123 118 width = fn.boundingRect("...").width();
124 119 height = fn.height()+labelPadding();
125 120 width=qMax(width,base.width());
126 121 height += base.height();
127 122 sh = QSizeF(width,height);
128 123 break;
129 124 case Qt::PreferredSize:{
130 125
131 126 for (int i = 0; i < ticksList.size(); ++i)
132 127 {
133 128 QRectF rect = fn.boundingRect(ticksList.at(i));
134 129 width += rect.width();
135 130 }
136 131 height = fn.height()+labelPadding();
137 132 width = qMax(width,base.width());
138 133 height += base.height();
139 134 sh = QSizeF(width,height);
140 135 break;
141 136 }
142 137 default:
143 138 break;
144 139 }
145 140 return sh;
146 141 }
147 142
148 143 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,146 +1,142
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartbarcategoryaxisy_p.h"
22 22 #include "chartpresenter_p.h"
23 23 #include "qbarcategoryaxis_p.h"
24 24 #include <qmath.h>
25 25 #include <QFontMetrics>
26 26 #include <QDebug>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 ChartBarCategoryAxisY::ChartBarCategoryAxisY(QBarCategoryAxis *axis, ChartPresenter *presenter)
31 31 : VerticalAxis(axis, presenter, true),
32 32 m_categoriesAxis(axis)
33 33 {
34 34 }
35 35
36 36 ChartBarCategoryAxisY::~ChartBarCategoryAxisY()
37 37 {
38 38 }
39 39
40 40 QVector<qreal> ChartBarCategoryAxisY::calculateLayout() const
41 41 {
42 int count = m_categoriesAxis->d_ptr->count();
43
44 Q_ASSERT(count >= 1);
45
46 42 QVector<qreal> points;
47 points.resize(count + 2);
48
49 43 const QRectF &gridRect = gridGeometry();
44 qreal range = max() - min();
45 const qreal delta = gridRect.height()/range;
46
47 if(delta<2) return points;
50 48
51 const qreal delta = gridRect.height() / (count);
52 49 qreal offset = - min() - 0.5;
50 offset = int(offset * delta)%int(delta);
53 51
54 if (delta < 1)
55 return points;
52 int count = qFloor(range);
53 if(count < 1 ) return points;
56 54
57 if (offset < 0)
58 offset = int(offset * gridRect.height() / (max() - min())) % int(delta) + delta;
59 else
60 offset = int(offset * gridRect.height() / (max() - min())) % int(delta);
55 points.resize(count+2);
61 56
62 for (int i = -1; i < count + 1; ++i) {
63 int y = gridRect.bottom() - i * delta - offset;
64 points[i + 1] = y;
57 for (int i = 0; i < count+2; ++i) {
58 points[i] = gridRect.bottom() - i * delta -offset;
65 59 }
60
66 61 return points;
67 62 }
68 63
69 64 QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& layout) const
70 65 {
71 66 QStringList result;
72 67 const QRectF &gridRect = gridGeometry();
73 68 qreal d = (max() - min()) / gridRect.height();
69
74 70 for (int i = 0; i < layout.count() - 1; ++i) {
75 71 qreal x = qFloor(((gridRect.height() - (layout[i + 1] + layout[i]) / 2 + gridRect.top()) * d + min() + 0.5));
76 72 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
77 73 result << m_categoriesAxis->categories().at(x);
78 74 } else {
79 75 // No label for x coordinate
80 76 result << "";
81 77 }
82 78 }
83 79 result << "";
84 80 return result;
85 81 }
86 82
87 83 void ChartBarCategoryAxisY::updateGeometry()
88 84 {
89 85 const QVector<qreal>& layout = ChartAxis::layout();
90 86 if (layout.isEmpty())
91 87 return;
92 88 setLabels(createCategoryLabels(layout));
93 89 VerticalAxis::updateGeometry();
94 90 }
95 91
96 92 void ChartBarCategoryAxisY::handleAxisUpdated()
97 93 {
98 94
99 95 if (m_categoriesAxis->categories() != m_categories) {
100 96 m_categories = m_categoriesAxis->categories();
101 97 if (ChartAxis::layout().count() == m_categoriesAxis->d_ptr->count() + 2)
102 98 updateGeometry();
103 99 }
104 100 ChartAxis::handleAxisUpdated();
105 101 }
106 102
107 103 QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
108 104 {
109 105 Q_UNUSED(constraint)
110 106
111 107 QFontMetrics fn(font());
112 108 QSizeF sh;
113 109 QSizeF base = VerticalAxis::sizeHint(which, constraint);
114 110 QStringList ticksList = createCategoryLabels(ChartAxis::layout());
115 111
116 112 qreal width=0;
117 113 qreal height=0;
118 114
119 115 switch (which) {
120 116 case Qt::MinimumSize:
121 117 width = fn.boundingRect("...").width() + labelPadding();
122 118 height = fn.height();
123 119 width+=base.width();
124 120 height=qMax(height,base.height());
125 121 sh = QSizeF(width,height);
126 122 break;
127 123 case Qt::PreferredSize:{
128 124
129 125 for (int i = 0; i < ticksList.size(); ++i)
130 126 {
131 127 QRectF rect = fn.boundingRect(ticksList.at(i));
132 128 height+=rect.height();
133 129 width=qMax(rect.width()+labelPadding() + 1 ,width); //one pixel torelance
134 130 }
135 131 height=qMax(height,base.height());
136 132 width+=base.width();
137 133 sh = QSizeF(width,height);
138 134 break;
139 135 }
140 136 default:
141 137 break;
142 138 }
143 139 return sh;
144 140 }
145 141
146 142 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,212 +1,211
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "horizontalaxis_p.h"
22 22 #include "qabstractaxis.h"
23 23 #include <QFontMetrics>
24 24 #include <qmath.h>
25 25 #include <QDebug>
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, ChartPresenter *presenter, bool intervalAxis)
30 30 : ChartAxis(axis, presenter, intervalAxis)
31 31 {
32 32 }
33 33
34 34 HorizontalAxis::~HorizontalAxis()
35 35 {
36 36 }
37 37
38 38 void HorizontalAxis::updateGeometry()
39 39 {
40 40 const QVector<qreal>& layout = ChartAxis::layout();
41 41
42 42 if (layout.isEmpty())
43 43 return;
44 44
45 45 QStringList labelList = labels();
46 46
47 47 QList<QGraphicsItem *> lines = lineItems();
48 48 QList<QGraphicsItem *> labels = labelItems();
49 49 QList<QGraphicsItem *> shades = shadeItems();
50 50 QList<QGraphicsItem *> axis = arrowItems();
51 51 QGraphicsSimpleTextItem* title = titleItem();
52 52
53 53 Q_ASSERT(labels.size() == labelList.size());
54 54 Q_ASSERT(layout.size() == labelList.size());
55 55
56 56 const QRectF &axisRect = axisGeometry();
57 57 const QRectF &gridRect = gridGeometry();
58 58
59 59 //arrow
60 60 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(axis.at(0));
61 61
62 62 if (alignment() == Qt::AlignTop)
63 63 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
64 64 else if (alignment() == Qt::AlignBottom)
65 65 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
66 66
67 67 qreal width = 0;
68 68 QFontMetrics fn(font());
69 69
70 70 for (int i = 0; i < layout.size(); ++i) {
71 71
72 72 //items
73 73 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
74 74 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(axis.at(i + 1));
75 75 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
76 76
77 77 //grid line
78 78 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
79 79
80 80 //label text wrapping
81 81 if(intervalAxis()&& i+1!=layout.size()) {
82 82 //wrapping in case of interval axis
83 83 const qreal delta = layout[i+1] - layout[i];
84 84 QString text = labelList.at(i);
85 if (fn.boundingRect(text).width() > delta )
85 if (fn.boundingRect(text).width() + 1 > delta )
86 86 {
87 87 QString label = text + "...";
88 while (fn.boundingRect(label).width() > delta && label.length() > 3)
88 while (fn.boundingRect(label).width() >= delta && label.length() > 3)
89 89 label.remove(label.length() - 4, 1);
90 90 labelItem->setText(label);
91 91 }
92 92 else {
93 93 labelItem->setText(text);
94 94 }
95 95 }else{
96 96 labelItem->setText(labelList.at(i));
97 97 }
98 98
99 99 //label transformation origin point
100 100 const QRectF& rect = labelItem->boundingRect();
101 101 QPointF center = rect.center();
102 102 labelItem->setTransformOriginPoint(center.x(), center.y());
103 103
104 104 //ticks and label position
105 105 if (alignment() == Qt::AlignTop) {
106 106 labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() - labelPadding());
107 107 tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
108 108 } else if (alignment() == Qt::AlignBottom) {
109 109 labelItem->setPos(layout[i] - center.x(), axisRect.top() + labelPadding());
110 110 tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
111 111 }
112 112
113 113 //label in beetwen
114 114 if(intervalAxis()&& i+1!=layout.size()) {
115 115 const qreal delta = (layout[i+1] - layout[i])/2;
116 116 labelItem->setPos(layout[i] + delta - center.x(), labelItem->pos().y());
117 117 }
118 118
119 119 //label overlap detection
120 if(labelItem->pos().x() <= width ||
120 if(labelItem->pos().x() < width ||
121 121 labelItem->pos().x() < axisRect.left() ||
122 122 labelItem->pos().x() + rect.width() > axisRect.right()) {
123 123 labelItem->setVisible(false);
124 }
125 else {
124 } else {
126 125 labelItem->setVisible(true);
127 126 width=rect.width()+labelItem->pos().x();
128 127 }
129 128
130 129 //shades
131 130 if ((i + 1) % 2 && i > 1) {
132 131 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
133 132 rectItem->setRect(layout[i - 1], gridRect.top(), layout[i] - layout[i - 1], gridRect.height());
134 133 }
135 134
136 135 // check if the grid line and the axis tick should be shown
137 136 qreal x = gridItem->line().p1().x();
138 137 if (x < gridRect.left() || x > gridRect.right()) {
139 138 gridItem->setVisible(false);
140 139 tickItem->setVisible(false);
141 140 }else{
142 141 gridItem->setVisible(true);
143 142 tickItem->setVisible(true);
144 143 }
145 144
146 145 }
147 146
148 147 //begin/end grid line in case labels between
149 148 if (intervalAxis()) {
150 149 QGraphicsLineItem *gridLine;
151 150 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
152 151 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
153 152 gridLine->setVisible(true);
154 153 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
155 154 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
156 155 gridLine->setVisible(true);
157 156 }
158 157
159 158 //title
160 159
161 160 if (!titleText().isNull()) {
162 161 QFontMetrics fn(title->font());
163 162
164 163 int size(0);
165 164
166 165 size = gridRect.width();
167 166 QString titleText = this->titleText();
168 167
169 168 if (fn.boundingRect(titleText).width() > size) {
170 169 QString string = titleText + "...";
171 170 while (fn.boundingRect(string).width() > size && string.length() > 3)
172 171 string.remove(string.length() - 4, 1);
173 172 title->setText(string);
174 173 } else {
175 174 title->setText(titleText);
176 175 }
177 176
178 177 QPointF center = gridRect.center() - title->boundingRect().center();
179 178 if (alignment() == Qt::AlignTop) {
180 179 title->setPos(center.x(), axisRect.top());
181 180 } else if (alignment() == Qt::AlignBottom) {
182 181 title->setPos(center.x(), axisRect.bottom() - title->boundingRect().height());
183 182 }
184 183 }
185 184
186 185 }
187 186
188 187 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
189 188 {
190 189 Q_UNUSED(constraint);
191 190 QFontMetrics fn(titleFont());
192 191 QSizeF sh;
193 192
194 193 if (titleText().isNull())
195 194 return sh;
196 195
197 196 switch (which) {
198 197 case Qt::MinimumSize:
199 198 sh = QSizeF(fn.boundingRect("...").width(), fn.height());
200 199 break;
201 200 case Qt::MaximumSize:
202 201 case Qt::PreferredSize:
203 202 sh = QSizeF(fn.boundingRect(axis()->title()).width(), fn.height());
204 203 break;
205 204 default:
206 205 break;
207 206 }
208 207
209 208 return sh;
210 209 }
211 210
212 211 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now