##// END OF EJS Templates
Values and Intervals axes ranges are now initialized only if they haven't been preset earlier
Values and Intervals axes ranges are now initialized only if they haven't been preset earlier

File last commit:

r1538:8f0be28e5215
r1703:d83729eb88d8
Show More
legendlayout.cpp
380 lines | 12.7 KiB | text/x-c | CppLexer
Michal Klocek
Adds missing license headers
r1535 /****************************************************************************
**
** Copyright (C) 2012 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 Commercial Charts Add-on.
**
** $QT_BEGIN_LICENSE$
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial 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$
**
****************************************************************************/
Michal Klocek
Refactors layout managment...
r1534 #include "legendlayout_p.h"
#include "chartpresenter_p.h"
#include "legendmarker_p.h"
#include "qlegend_p.h"
Michal Klocek
Fixes blinking and minimal false size for legend
r1538 #include <QDebug>
Michal Klocek
Adds missing license headers
r1535
Michal Klocek
Refactors layout managment...
r1534 QTCOMMERCIALCHART_BEGIN_NAMESPACE
LegendLayout::LegendLayout(QLegend* legend):
m_legend(legend)
{
}
LegendLayout::~LegendLayout()
{
}
void LegendLayout::setOffset(qreal x, qreal y)
{
bool scrollHorizontal = true;
switch(m_legend->alignment()) {
case Qt::AlignTop:
case Qt::AlignBottom: {
scrollHorizontal = true;
break;
}
case Qt::AlignLeft:
case Qt::AlignRight: {
scrollHorizontal = false;
break;
}
}
// If detached, the scrolling direction is vertical instead of horizontal and vice versa.
if (!m_legend->isAttachedToChart()) {
scrollHorizontal = !scrollHorizontal;
}
QRectF boundingRect = geometry();
// Limit offset between m_minOffset and m_maxOffset
if (scrollHorizontal) {
if(m_width<=boundingRect.width()) return;
if (x != m_offsetX) {
m_offsetX = qBound(m_minOffsetX, x, m_maxOffsetX);
m_legend->d_ptr->items()->setPos(-m_offsetX,boundingRect.top());
}
}
else {
if(m_height<=boundingRect.height()) return;
if (y != m_offsetY) {
m_offsetY = qBound(m_minOffsetY, y, m_maxOffsetY);
m_legend->d_ptr->items()->setPos(boundingRect.left(),-m_offsetY);
}
}
}
QPointF LegendLayout::offset() const
{
return QPointF(m_offsetX,m_offsetY);
}
void LegendLayout::setGeometry(const QRectF& rect)
{
QGraphicsLayout::setGeometry(rect);
if(m_legend->isAttachedToChart()) {
setAttachedGeometry(rect);
}
else {
setDettachedGeometry(rect);
}
}
void LegendLayout::setAttachedGeometry(const QRectF& rect)
{
Michal Klocek
Fixes blinking and minimal false size for legend
r1538 if (!rect.isValid()) return;
Michal Klocek
Refactors layout managment...
r1534
m_offsetX=0;
m_offsetY=0;
QSizeF size(0,0);
if( m_legend->d_ptr->markers().isEmpty()) return;
m_width=0;
m_height=0;
switch(m_legend->alignment()) {
case Qt::AlignTop:
case Qt::AlignBottom: {
QPointF point(0,0);
foreach (LegendMarker* marker, m_legend->d_ptr->markers()) {
if (marker->isVisible()) {
marker->setGeometry(QRectF(QPoint(0,0),marker->effectiveSizeHint(Qt::PreferredSize)));
marker->setPos(point.x(),rect.height()/2 - marker->boundingRect().height()/2);
const QRectF& rect = marker->boundingRect();
size = size.expandedTo(rect.size());
qreal w = rect.width();
m_width+=w;
point.setX(point.x() + w);
}
}
if(m_width<rect.width()) {
m_legend->d_ptr->items()->setPos(rect.width()/2-m_width/2,rect.top());
}
else {
m_legend->d_ptr->items()->setPos(rect.topLeft());
}
m_height=size.height();
}
break;
case Qt::AlignLeft:
case Qt::AlignRight: {
QPointF point(0,0);
foreach (LegendMarker* marker, m_legend->d_ptr->markers()) {
if (marker->isVisible()) {
marker->setGeometry(QRectF(QPoint(0,0),marker->effectiveSizeHint(Qt::PreferredSize)));
marker->setPos(point);
const QRectF& rect = marker->boundingRect();
qreal h = rect.height();
size = size.expandedTo(rect.size());
m_height+=h;
point.setY(point.y() + h);
}
}
if(m_height<rect.height()) {
m_legend->d_ptr->items()->setPos(rect.left(),rect.height()/2-m_height/2);
}
else {
m_legend->d_ptr->items()->setPos(rect.topLeft());
}
m_width=size.width();
}
break;
}
m_minOffsetX = 0;
m_minOffsetY = 0;
m_maxOffsetX = m_width - rect.width();
m_maxOffsetY = m_height - rect.height();
}
void LegendLayout::setDettachedGeometry(const QRectF& rect)
{
Michal Klocek
Fixes blinking and minimal false size for legend
r1538 if (!rect.isValid()) return;
Michal Klocek
Refactors layout managment...
r1534 // Detached layout is different.
// In detached mode legend may have multiple rows and columns, so layout calculations
// differ a log from attached mode.
// Also the scrolling logic is bit different.
m_offsetX=0;
m_offsetY=0;
QSizeF size(0,0);
Michal Klocek
Fixes detach legend layout logic
r1536 QList<LegendMarker *> markers = m_legend->d_ptr->markers();
Michal Klocek
Refactors layout managment...
r1534
Michal Klocek
Fixes detach legend layout logic
r1536 if(markers.isEmpty()) return;
Michal Klocek
Refactors layout managment...
r1534
switch (m_legend->alignment()) {
case Qt::AlignTop: {
QPointF point = rect.topLeft();
m_width = 0;
m_height = 0;
Michal Klocek
Fixes detach legend layout logic
r1536 for (int i=0; i<markers.count(); i++) {
LegendMarker *marker = markers.at(i);
if (marker->isVisible()) {
marker->setGeometry(QRectF(QPoint(0,0),marker->effectiveSizeHint(Qt::PreferredSize)));
marker->setPos(point.x(),point.y());
const QRectF& boundingRect = marker->boundingRect();
Michal Klocek
Refactors layout managment...
r1534 qreal w = boundingRect.width();
qreal h = boundingRect.height();
m_width = qMax(m_width,w);
m_height = qMax(m_height,h);
point.setX(point.x() + w);
if (point.x() + w > rect.topLeft().x() + rect.width()) {
// Next item would go off rect.
point.setX(rect.topLeft().x());
point.setY(point.y() + h);
Michal Klocek
Fixes detach legend layout logic
r1536 if (i+1 < markers.count()) {
Michal Klocek
Refactors layout managment...
r1534 m_height += h;
}
}
}
}
m_legend->d_ptr->items()->setPos(rect.topLeft());
m_minOffsetX = 0;
m_minOffsetY = 0;
m_maxOffsetX = m_width - rect.width();
m_maxOffsetY = m_height - rect.height();
}
break;
case Qt::AlignBottom: {
QPointF point = rect.bottomLeft();
m_width = 0;
m_height = 0;
Michal Klocek
Fixes detach legend layout logic
r1536 for (int i=0; i<markers.count(); i++) {
LegendMarker *marker = markers.at(i);
if (marker->isVisible()) {
marker->setGeometry(QRectF(QPoint(0,0),marker->effectiveSizeHint(Qt::PreferredSize)));
const QRectF& boundingRect = marker->boundingRect();
Michal Klocek
Refactors layout managment...
r1534 qreal w = boundingRect.width();
qreal h = boundingRect.height();
m_width = qMax(m_width,w);
m_height = qMax(m_height,h);
Michal Klocek
Fixes detach legend layout logic
r1536 marker->setPos(point.x(),point.y() - h);
Michal Klocek
Refactors layout managment...
r1534 point.setX(point.x() + w);
if (point.x() + w > rect.bottomLeft().x() + rect.width()) {
// Next item would go off rect.
point.setX(rect.bottomLeft().x());
point.setY(point.y() - h);
Michal Klocek
Fixes detach legend layout logic
r1536 if (i+1 < markers.count()) {
Michal Klocek
Refactors layout managment...
r1534 m_height += h;
}
}
}
}
m_legend->d_ptr->items()->setPos(rect.topLeft());
m_minOffsetX = 0;
m_minOffsetY = qMin(rect.topLeft().y(), rect.topLeft().y() - m_height + rect.height());
m_maxOffsetX = m_width - rect.width();
m_maxOffsetY = 0;
}
break;
case Qt::AlignLeft: {
QPointF point = rect.topLeft();
m_width = 0;
m_height = 0;
qreal maxWidth = 0;
Michal Klocek
Fixes detach legend layout logic
r1536 for (int i=0; i<markers.count(); i++) {
LegendMarker *marker = markers.at(i);
if (marker->isVisible()) {
marker->setGeometry(QRectF(QPoint(0,0),marker->effectiveSizeHint(Qt::PreferredSize)));
const QRectF& boundingRect = marker->boundingRect();
Michal Klocek
Refactors layout managment...
r1534 qreal w = boundingRect.width();
qreal h = boundingRect.height();
m_height = qMax(m_height,h);
maxWidth = qMax(maxWidth,w);
Michal Klocek
Fixes detach legend layout logic
r1536 marker->setPos(point.x(),point.y());
Michal Klocek
Refactors layout managment...
r1534 point.setY(point.y() + h);
if (point.y() + h > rect.topLeft().y() + rect.height()) {
// Next item would go off rect.
point.setX(point.x() + maxWidth);
point.setY(rect.topLeft().y());
Michal Klocek
Fixes detach legend layout logic
r1536 if (i+1 < markers.count()) {
Michal Klocek
Refactors layout managment...
r1534 m_width += maxWidth;
maxWidth = 0;
}
}
}
}
m_width += maxWidth;
m_legend->d_ptr->items()->setPos(rect.topLeft());
m_minOffsetX = 0;
m_minOffsetY = 0;
m_maxOffsetX = m_width - rect.width();
m_maxOffsetY = m_height - rect.height();
}
break;
case Qt::AlignRight: {
QPointF point = rect.topRight();
m_width = 0;
m_height = 0;
qreal maxWidth = 0;
Michal Klocek
Fixes detach legend layout logic
r1536 for (int i=0; i<markers.count(); i++) {
LegendMarker *marker = markers.at(i);
if (marker->isVisible()) {
marker->setGeometry(QRectF(QPoint(0,0),marker->effectiveSizeHint(Qt::PreferredSize)));
const QRectF& boundingRect = marker->boundingRect();
Michal Klocek
Refactors layout managment...
r1534 qreal w = boundingRect.width();
qreal h = boundingRect.height();
m_height = qMax(m_height,h);
maxWidth = qMax(maxWidth,w);
Michal Klocek
Fixes detach legend layout logic
r1536 marker->setPos(point.x() - w,point.y());
Michal Klocek
Refactors layout managment...
r1534 point.setY(point.y() + h);
if (point.y() + h > rect.topLeft().y() + rect.height()) {
// Next item would go off rect.
point.setX(point.x() - maxWidth);
point.setY(rect.topLeft().y());
Michal Klocek
Fixes detach legend layout logic
r1536 if (i+1 < markers.count()) {
Michal Klocek
Refactors layout managment...
r1534 m_width += maxWidth;
maxWidth = 0;
}
}
}
}
m_width += maxWidth;
m_legend->d_ptr->items()->setPos(rect.topLeft());
m_minOffsetX = qMin(rect.topLeft().x(), rect.topLeft().x() - m_width + rect.width());
m_minOffsetY = 0;
m_maxOffsetX = 0;
m_maxOffsetY = m_height - rect.height();
}
break;
default:
break;
}
}
QSizeF LegendLayout::sizeHint ( Qt::SizeHint which, const QSizeF & constraint) const
{
QSizeF size(0, 0);
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
Michal Klocek
Fixes blinking and minimal false size for legend
r1538 if(which!=Qt::PreferredSize) return QSizeF(-1,-1);
Michal Klocek
Refactors layout managment...
r1534 if(constraint.isValid()) {
foreach(LegendMarker* marker, m_legend->d_ptr->markers()) {
size = size.expandedTo(marker->effectiveSizeHint(which));
}
size = size.boundedTo(constraint);
}
else if (constraint.width() >= 0) {
qreal width = 0;
qreal height = 0;
foreach(LegendMarker* marker, m_legend->d_ptr->markers()) {
width+=marker->effectiveSizeHint(which).width();
height=qMax(height,marker->effectiveSizeHint(which).height());
}
size = QSizeF(qMin(constraint.width(),width), height);
}
else if (constraint.height() >= 0) {
qreal width = 0;
qreal height = 0;
foreach(LegendMarker* marker, m_legend->d_ptr->markers()) {
width=qMax(width,marker->effectiveSizeHint(which).width());
height+=height,marker->effectiveSizeHint(which).height();
}
size = QSizeF(width,qMin(constraint.height(),height));
}
else {
foreach(LegendMarker* marker, m_legend->d_ptr->markers()) {
size = size.expandedTo(marker->effectiveSizeHint(which));
}
}
size += QSize(left + right, top + bottom);
Michal Klocek
Fixes blinking and minimal false size for legend
r1538
Michal Klocek
Refactors layout managment...
r1534 return size;
Michal Klocek
Fixes blinking and minimal false size for legend
r1538
Michal Klocek
Refactors layout managment...
r1534 }
QTCOMMERCIALCHART_END_NAMESPACE