diff options
Diffstat (limited to 'src/axis/polarchartaxisangular.cpp')
-rw-r--r-- | src/axis/polarchartaxisangular.cpp | 432 |
1 files changed, 0 insertions, 432 deletions
diff --git a/src/axis/polarchartaxisangular.cpp b/src/axis/polarchartaxisangular.cpp deleted file mode 100644 index 91d396ac..00000000 --- a/src/axis/polarchartaxisangular.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt Enterprise Charts Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "polarchartaxisangular_p.h" -#include "chartpresenter_p.h" -#include "abstractchartlayout_p.h" -#include "qabstractaxis.h" -#include "qabstractaxis_p.h" -#include <QDebug> -#include <qmath.h> -#include <QTextDocument> - -QTCOMMERCIALCHART_BEGIN_NAMESPACE - -PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis) - : PolarChartAxis(axis, item, intervalAxis) -{ -} - -PolarChartAxisAngular::~PolarChartAxisAngular() -{ -} - -void PolarChartAxisAngular::updateGeometry() -{ - QGraphicsLayoutItem::updateGeometry(); - - const QVector<qreal> &layout = this->layout(); - if (layout.isEmpty()) - return; - - createAxisLabels(layout); - QStringList labelList = labels(); - QPointF center = axisGeometry().center(); - QList<QGraphicsItem *> arrowItemList = arrowItems(); - QList<QGraphicsItem *> gridItemList = gridItems(); - QList<QGraphicsItem *> labelItemList = labelItems(); - QList<QGraphicsItem *> shadeItemList = shadeItems(); - QGraphicsTextItem *title = titleItem(); - - QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0)); - axisLine->setRect(axisGeometry()); - - qreal radius = axisGeometry().height() / 2.0; - - QRectF previousLabelRect; - QRectF firstLabelRect; - - qreal labelHeight = 0; - - bool firstShade = true; - bool nextTickVisible = false; - if (layout.size()) - nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0); - - for (int i = 0; i < layout.size(); ++i) { - qreal angularCoordinate = layout.at(i); - - QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i)); - QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1)); - QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i)); - QGraphicsPathItem *shadeItem = 0; - if (i == 0) - shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0)); - else if (i % 2) - shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1)); - - // Ignore ticks outside valid range - bool currentTickVisible = nextTickVisible; - if ((i == layout.size() - 1) - || layout.at(i + 1) < 0.0 - || layout.at(i + 1) > 360.0) { - nextTickVisible = false; - } else { - nextTickVisible = true; - } - - qreal labelCoordinate = angularCoordinate; - qreal labelVisible = currentTickVisible; - if (intervalAxis()) { - qreal farEdge; - if (i == (layout.size() - 1)) - farEdge = 360.0; - else - farEdge = qMin(qreal(360.0), layout.at(i + 1)); - - // Adjust the labelCoordinate to show it if next tick is visible - if (nextTickVisible) - labelCoordinate = qMax(qreal(0.0), labelCoordinate); - - labelCoordinate = (labelCoordinate + farEdge) / 2.0; - // Don't display label once the category gets too small near the axis - if (labelCoordinate < 5.0 || labelCoordinate > 355.0) - labelVisible = false; - else - labelVisible = true; - } - - // Need this also in label calculations, so determine it first - QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(), - QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2()); - tickLine.translate(center); - - // Angular axis label - if (axis()->labelsVisible() && labelVisible) { - QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), - labelList.at(i), - axis()->labelsAngle()); - labelItem->setTextWidth(boundingRect.width()); - labelItem->setHtml(labelList.at(i)); - const QRectF &rect = labelItem->boundingRect(); - QPointF labelCenter = rect.center(); - labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y()); - boundingRect.moveCenter(labelCenter); - QPointF positionDiff(rect.topLeft() - boundingRect.topLeft()); - - QPointF labelPoint; - if (intervalAxis()) { - QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate); - labelLine.translate(center); - labelPoint = labelLine.p2(); - } else { - labelPoint = tickLine.p2(); - } - - QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect); - labelItem->setPos(labelRect.topLeft() + positionDiff); - - // Store height for title calculations - qreal labelClearance = axisGeometry().top() - labelRect.top(); - labelHeight = qMax(labelHeight, labelClearance); - - // Label overlap detection - if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) { - labelVisible = false; - } else { - // Store labelRect for future comparison. Some area is deducted to make things look - // little nicer, as usually intersection happens at label corner with angular labels. - labelRect.adjust(-2.0, -4.0, -2.0, -4.0); - if (firstLabelRect.isEmpty()) - firstLabelRect = labelRect; - - previousLabelRect = labelRect; - labelVisible = true; - } - } - - labelItem->setVisible(labelVisible); - if (!currentTickVisible) { - gridLineItem->setVisible(false); - tickItem->setVisible(false); - if (shadeItem) - shadeItem->setVisible(false); - continue; - } - - // Angular grid line - QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate); - gridLine.translate(center); - gridLineItem->setLine(gridLine); - gridLineItem->setVisible(true); - - // Tick - tickItem->setLine(tickLine); - tickItem->setVisible(true); - - // Shades - if (i % 2 || (i == 0 && !nextTickVisible)) { - QPainterPath path; - path.moveTo(center); - if (i == 0) { - // If first tick is also the last, we need to custom fill the first partial arc - // or it won't get filled. - path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0)); - path.closeSubpath(); - } else { - qreal nextCoordinate; - if (!nextTickVisible) // Last visible tick - nextCoordinate = 360.0; - else - nextCoordinate = layout.at(i + 1); - qreal arcSpan = angularCoordinate - nextCoordinate; - path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan); - path.closeSubpath(); - - // Add additional arc for first shade item if there is a partial arc to be filled - if (firstShade) { - QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0)); - if (layout.at(i - 1) > 0.0) { - QPainterPath specialPath; - specialPath.moveTo(center); - specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1)); - specialPath.closeSubpath(); - specialShadeItem->setPath(specialPath); - specialShadeItem->setVisible(true); - } else { - specialShadeItem->setVisible(false); - } - } - } - shadeItem->setPath(path); - shadeItem->setVisible(true); - firstShade = false; - } - } - - // Title, centered above the chart - QString titleText = axis()->titleText(); - if (!titleText.isEmpty() && axis()->isTitleVisible()) { - QRectF truncatedRect; - 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, - truncatedRect)); - title->setTextWidth(truncatedRect.width()); - - QRectF titleBoundingRect = title->boundingRect(); - QPointF titleCenter = center - titleBoundingRect.center(); - title->setPos(titleCenter.x(), axisGeometry().top() - titlePadding() * 2.0 - titleBoundingRect.height() - labelHeight); - } -} - -Qt::Orientation PolarChartAxisAngular::orientation() const -{ - return Qt::Horizontal; -} - -void PolarChartAxisAngular::createItems(int count) -{ - if (arrowItems().count() == 0) { - // angular axis line - QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem()); - arrow->setPen(axis()->linePen()); - arrowGroup()->addToGroup(arrow); - } - - QGraphicsTextItem *title = titleItem(); - title->setFont(axis()->titleFont()); - title->setDefaultTextColor(axis()->titleBrush().color()); - title->setHtml(axis()->titleText()); - - for (int i = 0; i < count; ++i) { - QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem()); - QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem()); - QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem()); - label->document()->setDocumentMargin(ChartPresenter::textMargin()); - arrow->setPen(axis()->linePen()); - grid->setPen(axis()->gridLinePen()); - label->setFont(axis()->labelsFont()); - label->setDefaultTextColor(axis()->labelsBrush().color()); - label->setRotation(axis()->labelsAngle()); - arrowGroup()->addToGroup(arrow); - gridGroup()->addToGroup(grid); - labelGroup()->addToGroup(label); - if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) { - QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem()); - shade->setPen(axis()->shadesPen()); - shade->setBrush(axis()->shadesBrush()); - shadeGroup()->addToGroup(shade); - } - } -} - -void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen) -{ - bool first = true; - foreach (QGraphicsItem *item, arrowItems()) { - if (first) { - first = false; - // First arrow item is the outer circle of axis - static_cast<QGraphicsEllipseItem *>(item)->setPen(pen); - } else { - static_cast<QGraphicsLineItem *>(item)->setPen(pen); - } - } -} - -void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen) -{ - foreach (QGraphicsItem *item, gridItems()) - static_cast<QGraphicsLineItem *>(item)->setPen(pen); -} - -QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_UNUSED(which); - Q_UNUSED(constraint); - return QSizeF(-1, -1); -} - -qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize) -{ - qreal radius = maxSize.height() / 2.0; - if (maxSize.width() < maxSize.height()) - radius = maxSize.width() / 2.0; - - if (axis()->labelsVisible()) { - QVector<qreal> layout = calculateLayout(); - if (layout.isEmpty()) - return radius; - - createAxisLabels(layout); - QStringList labelList = labels(); - QFont font = axis()->labelsFont(); - - QRectF maxRect; - maxRect.setSize(maxSize); - maxRect.moveCenter(QPointF(0.0, 0.0)); - - // This is a horrible way to find out the maximum radius for angular axis and its labels. - // It just increments the radius down until everyhing fits the constraint size. - // Proper way would be to actually calculate it but this seems to work reasonably fast as it is. - bool nextTickVisible = false; - for (int i = 0; i < layout.size(); ) { - if ((i == layout.size() - 1) - || layout.at(i + 1) < 0.0 - || layout.at(i + 1) > 360.0) { - nextTickVisible = false; - } else { - nextTickVisible = true; - } - - qreal labelCoordinate = layout.at(i); - qreal labelVisible; - - if (intervalAxis()) { - qreal farEdge; - if (i == (layout.size() - 1)) - farEdge = 360.0; - else - farEdge = qMin(qreal(360.0), layout.at(i + 1)); - - // Adjust the labelCoordinate to show it if next tick is visible - if (nextTickVisible) - labelCoordinate = qMax(qreal(0.0), labelCoordinate); - - labelCoordinate = (labelCoordinate + farEdge) / 2.0; - } - - if (labelCoordinate < 0.0 || labelCoordinate > 360.0) - labelVisible = false; - else - labelVisible = true; - - if (!labelVisible) { - i++; - continue; - } - - QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle()); - QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2(); - - boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect); - QRectF intersectRect = maxRect.intersected(boundingRect); - if (boundingRect.isEmpty() || intersectRect == boundingRect) { - i++; - } else { - qreal reduction(0.0); - // If there is no intersection, reduce by smallest dimension of label rect to be on the safe side - if (intersectRect.isEmpty()) { - reduction = qMin(boundingRect.height(), boundingRect.width()); - } else { - // Approximate needed radius reduction is the amount label rect exceeds max rect in either dimension. - // Could be further optimized by figuring out the proper math how to calculate exact needed reduction. - reduction = qMax(boundingRect.height() - intersectRect.height(), - boundingRect.width() - intersectRect.width()); - } - // Typically the approximated reduction is little low, so add one - radius -= (reduction + 1.0); - - if (radius < 1.0) // safeguard - return 1.0; - } - } - } - - if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) { - QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText()); - - radius -= titlePadding() + (titleRect.height() / 2.0); - if (radius < 1.0) // safeguard - return 1.0; - } - - return radius; -} - -QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const -{ - if (angularCoordinate == 0.0) - labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0)); - else if (angularCoordinate < 90.0) - labelRect.moveBottomLeft(labelPoint); - else if (angularCoordinate == 90.0) - labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis - else if (angularCoordinate < 180.0) - labelRect.moveTopLeft(labelPoint); - else if (angularCoordinate == 180.0) - labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0)); - else if (angularCoordinate < 270.0) - labelRect.moveTopRight(labelPoint); - else if (angularCoordinate == 270.0) - labelRect.moveCenter(labelPoint + QPointF(-labelRect.width() / 2.0 - 2.0, 0)); // -2 so that it does not hit the radial axis - else if (angularCoordinate < 360.0) - labelRect.moveBottomRight(labelPoint); - else - labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0)); - return labelRect; -} - -#include "moc_polarchartaxisangular_p.cpp" - -QTCOMMERCIALCHART_END_NAMESPACE |