1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Charts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <private/cartesianchartlayout_p.h>
31#include <private/chartpresenter_p.h>
32#include <private/chartaxiselement_p.h>
33#include <QtCore/QDebug>
34
35QT_CHARTS_BEGIN_NAMESPACE
36
37static const qreal maxAxisPortion = 0.4;
38
39CartesianChartLayout::CartesianChartLayout(ChartPresenter *presenter)
40 : AbstractChartLayout(presenter)
41{
42}
43
44CartesianChartLayout::~CartesianChartLayout()
45{
46}
47
48QRectF CartesianChartLayout::calculateAxisGeometry(const QRectF &geometry,
49 const QList<ChartAxisElement *> &axes,
50 bool update) const
51{
52 Q_UNUSED(update)
53 QSizeF left(0,0);
54 QSizeF minLeft(0,0);
55 QSizeF right(0,0);
56 QSizeF minRight(0,0);
57 QSizeF bottom(0,0);
58 QSizeF minBottom(0,0);
59 QSizeF top(0,0);
60 QSizeF minTop(0,0);
61 QSizeF labelExtents(0,0);
62 int leftCount = 0;
63 int rightCount = 0;
64 int topCount = 0;
65 int bottomCount = 0;
66
67 foreach (ChartAxisElement *axis , axes) {
68
69 if (!axis->isVisible())
70 continue;
71
72
73 QSizeF size = axis->effectiveSizeHint(which: Qt::PreferredSize);
74 //this is used to get single thick font size
75 QSizeF minSize = axis->effectiveSizeHint(which: Qt::MinimumSize);
76
77 switch (axis->axis()->alignment()) {
78 case Qt::AlignLeft:
79 left.setWidth(left.width()+size.width());
80 left.setHeight(qMax(a: left.height(),b: size.height()));
81 minLeft.setWidth(minLeft.width()+minSize.width());
82 minLeft.setHeight(qMax(a: minLeft.height(),b: minSize.height()));
83 labelExtents.setHeight(qMax(a: size.height(), b: labelExtents.height()));
84 leftCount++;
85 break;
86 case Qt::AlignRight:
87 right.setWidth(right.width()+size.width());
88 right.setHeight(qMax(a: right.height(),b: size.height()));
89 minRight.setWidth(minRight.width()+minSize.width());
90 minRight.setHeight(qMax(a: minRight.height(),b: minSize.height()));
91 labelExtents.setHeight(qMax(a: size.height(), b: labelExtents.height()));
92 rightCount++;
93 break;
94 case Qt::AlignTop:
95 top.setWidth(qMax(a: top.width(),b: size.width()));
96 top.setHeight(top.height()+size.height());
97 minTop.setWidth(qMax(a: minTop.width(),b: minSize.width()));
98 minTop.setHeight(minTop.height()+minSize.height());
99 labelExtents.setWidth(qMax(a: size.width(), b: labelExtents.width()));
100 topCount++;
101 break;
102 case Qt::AlignBottom:
103 bottom.setWidth(qMax(a: bottom.width(), b: size.width()));
104 bottom.setHeight(bottom.height() + size.height());
105 minBottom.setWidth(qMax(a: minBottom.width(),b: minSize.width()));
106 minBottom.setHeight(minBottom.height() + minSize.height());
107 labelExtents.setWidth(qMax(a: size.width(), b: labelExtents.width()));
108 bottomCount++;
109 break;
110 default:
111 qWarning()<<"Axis is without alignment !";
112 break;
113 }
114 }
115
116 qreal totalVerticalAxes = leftCount + rightCount;
117 qreal leftSqueezeRatio = 1.0;
118 qreal rightSqueezeRatio = 1.0;
119 qreal vratio = 0;
120
121 if (totalVerticalAxes > 0)
122 vratio = (maxAxisPortion * geometry.width()) / totalVerticalAxes;
123
124 if (leftCount > 0) {
125 int maxWidth = vratio * leftCount;
126 if (left.width() > maxWidth) {
127 leftSqueezeRatio = maxWidth / left.width();
128 left.setWidth(maxWidth);
129 }
130 }
131 if (rightCount > 0) {
132 int maxWidth = vratio * rightCount;
133 if (right.width() > maxWidth) {
134 rightSqueezeRatio = maxWidth / right.width();
135 right.setWidth(maxWidth);
136 }
137 }
138
139 qreal totalHorizontalAxes = topCount + bottomCount;
140 qreal topSqueezeRatio = 1.0;
141 qreal bottomSqueezeRatio = 1.0;
142 qreal hratio = 0;
143
144 if (totalHorizontalAxes > 0)
145 hratio = (maxAxisPortion * geometry.height()) / totalHorizontalAxes;
146
147 if (topCount > 0) {
148 int maxHeight = hratio * topCount;
149 if (top.height() > maxHeight) {
150 topSqueezeRatio = maxHeight / top.height();
151 top.setHeight(maxHeight);
152 }
153 }
154 if (bottomCount > 0) {
155 int maxHeight = hratio * bottomCount;
156 if (bottom.height() > maxHeight) {
157 bottomSqueezeRatio = maxHeight / bottom.height();
158 bottom.setHeight(maxHeight);
159 }
160 }
161
162 qreal minHeight = qMax(a: minLeft.height(),b: minRight.height()) + 1;
163 qreal minWidth = qMax(a: minTop.width(),b: minBottom.width()) + 1;
164
165 // Ensure that there is enough space for first and last tick labels.
166 left.setWidth(qMax(a: labelExtents.width(), b: left.width()));
167 right.setWidth(qMax(a: labelExtents.width(), b: right.width()));
168 top.setHeight(qMax(a: labelExtents.height(), b: top.height()));
169 bottom.setHeight(qMax(a: labelExtents.height(), b: bottom.height()));
170
171 QRectF chartRect = geometry.adjusted(xp1: qMax(a: left.width(),b: minWidth/2), yp1: qMax(a: top.height(), b: minHeight/2),xp2: -qMax(a: right.width(),b: minWidth/2),yp2: -qMax(a: bottom.height(),b: minHeight/2));
172
173 qreal leftOffset = 0;
174 qreal rightOffset = 0;
175 qreal topOffset = 0;
176 qreal bottomOffset = 0;
177
178 // The axes are positioned here for the first time, so we need to catch any possible resizing
179 // of the chart when in fixed geometry to prevent them being moved out of place.
180 if (m_presenter->isFixedGeometry())
181 chartRect = m_presenter->geometry();
182
183 foreach (ChartAxisElement *axis , axes) {
184
185 if (!axis->isVisible())
186 continue;
187
188 QSizeF size = axis->effectiveSizeHint(which: Qt::PreferredSize);
189
190 switch (axis->axis()->alignment()){
191 case Qt::AlignLeft:{
192 qreal width = size.width();
193 if (leftSqueezeRatio < 1.0)
194 width *= leftSqueezeRatio;
195 leftOffset+=width;
196 axis->setGeometry(axis: QRect(chartRect.left()-leftOffset, geometry.top(),width, geometry.bottom()),grid: chartRect);
197 break;
198 }
199 case Qt::AlignRight:{
200 qreal width = size.width();
201 if (rightSqueezeRatio < 1.0)
202 width *= rightSqueezeRatio;
203 axis->setGeometry(axis: QRect(chartRect.right()+rightOffset,geometry.top(),width,geometry.bottom()),grid: chartRect);
204 rightOffset+=width;
205 break;
206 }
207 case Qt::AlignTop: {
208 qreal height = size.height();
209 if (topSqueezeRatio < 1.0)
210 height *= topSqueezeRatio;
211 axis->setGeometry(axis: QRect(geometry.left(), chartRect.top() - topOffset - height, geometry.width(), height), grid: chartRect);
212 topOffset += height;
213 break;
214 }
215 case Qt::AlignBottom:
216 qreal height = size.height();
217 if (bottomSqueezeRatio < 1.0)
218 height *= bottomSqueezeRatio;
219 axis->setGeometry(axis: QRect(geometry.left(), chartRect.bottom() + bottomOffset, geometry.width(), height), grid: chartRect);
220 bottomOffset += height;
221 break;
222 }
223 }
224
225 return chartRect;
226}
227
228QRectF CartesianChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const
229{
230 QSizeF left;
231 QSizeF right;
232 QSizeF bottom;
233 QSizeF top;
234
235 foreach (ChartAxisElement *axis, axes) {
236 QSizeF size = axis->effectiveSizeHint(which: Qt::MinimumSize);
237
238 if (!axis->isVisible())
239 continue;
240
241 switch (axis->axis()->alignment()) {
242 case Qt::AlignLeft:
243 left.setWidth(left.width() + size.width());
244 left.setHeight(qMax(a: left.height(), b: size.height()));
245 break;
246 case Qt::AlignRight:
247 right.setWidth(right.width() + size.width());
248 right.setHeight(qMax(a: right.height(), b: size.height()));
249 break;
250 case Qt::AlignTop:
251 top.setWidth(qMax(a: top.width(), b: size.width()));
252 top.setHeight(top.height() + size.height());
253 break;
254 case Qt::AlignBottom:
255 bottom.setWidth(qMax(a: bottom.width(), b: size.width()));
256 bottom.setHeight(bottom.height() + size.height());
257 break;
258 }
259 }
260 return minimum.adjusted(xp1: 0, yp1: 0, xp2: left.width() + right.width() + qMax(a: top.width(), b: bottom.width()), yp2: top.height() + bottom.height() + qMax(a: left.height(), b: right.height()));
261}
262
263QT_CHARTS_END_NAMESPACE
264

source code of qtcharts/src/charts/layout/cartesianchartlayout.cpp