KissCount/lib/libkdchart/src/KDChartAbstractCoordinatePlane.h

438 lines
16 KiB
C++

/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTABSTRACTCOORDINATEPLANE_H
#define KDCHARTABSTRACTCOORDINATEPLANE_H
#include <QObject>
#include <QList>
#include "KDChartAbstractArea.h"
#include "KDChartAbstractDiagram.h"
#include "KDChartEnums.h"
namespace KDChart {
class Chart;
class GridAttributes;
class DataDimension;
typedef QList<DataDimension> DataDimensionsList;
/**
* @brief Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane, TernaryCoordinatePlane
*/
class KDCHART_EXPORT AbstractCoordinatePlane : public AbstractArea
{
Q_OBJECT
Q_DISABLE_COPY( AbstractCoordinatePlane )
KDCHART_DECLARE_PRIVATE_DERIVED_PARENT( AbstractCoordinatePlane, Chart* )
friend class AbstractGrid;
public:
enum AxesCalcMode { Linear, Logarithmic };
protected:
explicit AbstractCoordinatePlane ( Chart* parent = 0 );
public:
virtual ~AbstractCoordinatePlane();
/**
* Adds a diagram to this coordinate plane.
* @param diagram The diagram to add.
*
* \sa replaceDiagram, takeDiagram
*/
virtual void addDiagram ( AbstractDiagram* diagram );
/**
* Replaces the old diagram, or appends the
* diagram, it there is none yet.
*
* @param diagram The diagram to be used instead of the old diagram.
* This parameter must not be zero, or the method will do nothing.
*
* @param oldDiagram The diagram to be removed by the new diagram. This
* diagram will be deleted automatically. If the parameter is omitted,
* the very first diagram will be replaced. In case, there was no
* diagram yet, the new diagram will just be added.
*
* \note If you want to re-use the old diagram, call takeDiagram and
* addDiagram, instead of using replaceDiagram.
*
* \sa addDiagram, takeDiagram
*/
virtual void replaceDiagram ( AbstractDiagram* diagram, AbstractDiagram* oldDiagram = 0 );
/**
* Removes the diagram from the plane, without deleting it.
*
* The plane no longer owns the diagram, so it is
* the caller's responsibility to delete the diagram.
*
* \sa addDiagram, replaceDiagram
*/
virtual void takeDiagram( AbstractDiagram* diagram );
/**
* @return The first diagram associated with this coordinate plane.
*/
AbstractDiagram* diagram();
/**
* @return The list of diagrams associated with this coordinate plane.
*/
AbstractDiagramList diagrams();
/**
* @return The list of diagrams associated with this coordinate plane.
*/
ConstAbstractDiagramList diagrams() const;
/**
* Distribute the available space among the diagrams and axes.
*/
virtual void layoutDiagrams() = 0;
/**
* Translate the given point in value space coordinates to a position
* in pixel space.
* @param diagramPoint The point in value coordinates.
* @returns The translated point.
*/
virtual const QPointF translate ( const QPointF& diagramPoint ) const = 0;
/** \reimpl */
virtual QSize minimumSizeHint() const;
/** \reimpl */
virtual QSizePolicy sizePolicy() const;
/**
* @return Whether zooming with a rubber band using the mouse is enabled.
*/
bool isRubberBandZoomingEnabled() const;
/**
* Enables or disables zooming with a rubber band using the mouse.
*/
void setRubberBandZoomingEnabled( bool enable );
/**
* @return The zoom factor in horizontal direction, that is applied
* to all coordinate transformations.
*/
virtual double zoomFactorX() const { return 1.0; }
/**
* @return The zoom factor in vertical direction, that is applied
* to all coordinate transformations.
*/
virtual double zoomFactorY() const { return 1.0; }
/**
* Sets both zoom factors in one go.
* \sa setZoomFactorX,setZoomFactorY
*/
virtual void setZoomFactors( double factorX, double factorY ) { Q_UNUSED( factorX ); Q_UNUSED( factorY ); }
/**
* Sets the zoom factor in horizontal direction, that is applied
* to all coordinate transformations.
* @param factor The new zoom factor
*/
virtual void setZoomFactorX( double factor ) { Q_UNUSED( factor ); }
/**
* Sets the zoom factor in vertical direction, that is applied
* to all coordinate transformations.
* @param factor The new zoom factor
*/
virtual void setZoomFactorY( double factor ) { Q_UNUSED( factor ); }
/**
* @return The center point (in value coordinates) of the
* coordinate plane, that is used for zoom operations.
*/
virtual QPointF zoomCenter() const { return QPointF(0.0, 0.0); }
/**
* Set the point (in value coordinates) to be used as the
* center point in zoom operations.
* @param center The point to use.
*/
virtual void setZoomCenter( const QPointF& center ) { Q_UNUSED( center ); }
/**
* Set the grid attributes to be used by this coordinate plane.
* To disable grid painting, for example, your code should like this:
* \code
* GridAttributes ga = plane->globalGridAttributes();
* ga.setGlobalGridVisible( false );
* plane->setGlobalGridAttributes( ga );
* \endcode
* \sa globalGridAttributes
* \sa CartesianCoordinatePlane::setGridAttributes
*/
void setGlobalGridAttributes( const GridAttributes & );
/**
* @return The grid attributes used by this coordinate plane.
* \sa setGlobalGridAttributes
* \sa CartesianCoordinatePlane::gridAttributes
*/
GridAttributes globalGridAttributes() const;
/**
* Returns the dimensions used for drawing the grid lines.
*
* Returned data is the result of (cached) grid calculations,
* so - if you need that information for your own tasks - make sure to
* call again this function after every data modification that has changed
* the data range, since grid calculation is based upon the data range,
* thus the grid start/end might have changed if the data was changed.
*
* @note Returned list will contain different numbers of DataDimension,
* depending on the kind of coordinate plane used.
* For CartesianCoordinatePlane two DataDimension are returned: the first
* representing grid lines in X direction (matching the Abscissa axes)
* and the second indicating vertical grid lines (or Ordinate axes, resp.).
*
* @return The dimensions used for drawing the grid lines.
* @sa DataDimension
*/
DataDimensionsList gridDimensionsList();
/**
* Set another coordinate plane to be used as the reference plane
* for this one.
* @param plane The coordinate plane to be used the reference plane
* for this one.
* @see referenceCoordinatePlane
*/
void setReferenceCoordinatePlane( AbstractCoordinatePlane * plane );
/**
* There are two ways, in which planes can be caused to interact, in
* where they are put layouting wise: The first is the reference plane. If
* such a reference plane is set, on a plane, it will use the same cell in the
* layout as that one. In addition to this, planes can share an axis. In that case
* they will be laid out in relation to each other as suggested by the position
* of the axis. If, for example Plane1 and Plane2 share an axis at position Left,
* that will result in the layout: Axis Plane1 Plane 2, vertically. If Plane1
* also happens to be Plane2's reference plane, both planes are drawn over each
* other. The reference plane concept allows two planes to share the same space
* even if neither has any axis, and in case there are shared axis, it is used
* to decided, whether the planes should be painted on top of each other or
* laid out vertically or horizontally next to each other.
* @return The reference coordinate plane associated with this one.
*/
AbstractCoordinatePlane * referenceCoordinatePlane() const;
virtual AbstractCoordinatePlane* sharedAxisMasterPlane( QPainter* p = 0 );
/** pure virtual in QLayoutItem */
virtual bool isEmpty() const;
/** pure virtual in QLayoutItem */
virtual Qt::Orientations expandingDirections() const;
/** pure virtual in QLayoutItem */
virtual QSize maximumSize() const;
/** pure virtual in QLayoutItem */
virtual QSize minimumSize() const;
/** pure virtual in QLayoutItem */
virtual QSize sizeHint() const;
/** pure virtual in QLayoutItem
*
* \note Do not call this function directly, unless you know
* exactly what you are doing. Geometry management is done
* by KD Chart's internal layouting measures.
*/
virtual void setGeometry( const QRect& r );
/** pure virtual in QLayoutItem */
virtual QRect geometry() const;
virtual void mousePressEvent( QMouseEvent* event );
virtual void mouseDoubleClickEvent( QMouseEvent* event );
virtual void mouseMoveEvent( QMouseEvent* event );
virtual void mouseReleaseEvent( QMouseEvent* event );
/**
* Called internally by KDChart::Chart
*/
void setParent( Chart* parent );
Chart* parent();
const Chart* parent() const;
/**
* Tests, if a point is visible on the coordinate plane.
*
* \note Before calling this function the point must have been translated into coordinate plane space.
*/
#if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
const bool isVisiblePoint( const QPointF& point ) const;
#else
bool isVisiblePoint( const QPointF& point ) const;
#endif
public Q_SLOTS:
/**
* Calling update() on the plane triggers the global KDChart::Chart::update()
*/
void update();
/**
* Calling relayout() on the plane triggers the global KDChart::Chart::slotRelayout()
*/
void relayout();
/**
* Calling layoutPlanes() on the plane triggers the global KDChart::Chart::slotLayoutPlanes()
*/
void layoutPlanes();
/**
* Used by the chart to clear the cached grid data.
*/
void setGridNeedsRecalculate();
Q_SIGNALS:
/** Emitted when this coordinate plane is destroyed. */
void destroyedCoordinatePlane( AbstractCoordinatePlane* );
/** Emitted when plane needs to update its drawings. */
void needUpdate();
/** Emitted when plane needs to trigger the Chart's layouting. */
void needRelayout();
/** Emitted when plane needs to trigger the Chart's layouting of the coord. planes. */
void needLayoutPlanes();
/** Emitted upon change of a property of the Coordinate Plane or any of its components. */
void propertiesChanged();
/** Emitted after the geometry of the Coordinate Plane has been changed.
* and control has returned to the event loop.
*
* Parameters are the the old geometry, the new geometry.
*/
void geometryChanged( QRect, QRect );
private:
Q_SIGNALS:
// Emitted from inside the setGeometry()
// This is connected via QueuedConnection to the geometryChanged() Signal
// that users can connect to safely then.
void internal_geometryChanged( QRect, QRect );
protected:
virtual DataDimensionsList getDataDimensionsList() const = 0;
//KDCHART_DECLARE_PRIVATE_DERIVED( AbstractCoordinatePlane )
};
/**
* \brief Helper class for one dimension of data, e.g. for the rows in a data model,
* or for the labels of an axis, or for the vertical lines in a grid.
*
* isCalculated specifies whether this dimension's values are calculated or counted.
* (counted == "Item 1", "Item 2", "Item 3" ...)
*
* sequence is the GranularitySequence, as specified at for the respective
* coordinate plane.
*
* Step width is an optional parameter, to be omitted (or set to Zero, resp.)
* if the step width is unknown.
*
* The default c'tor just gets you counted values from 1..10, using step width 1,
* used by the CartesianGrid, when showing an empty plane without any diagrams.
*/
class DataDimension{
public:
DataDimension()
: start( 1.0 )
, end( 10.0 )
, isCalculated( false )
, calcMode( AbstractCoordinatePlane::Linear )
, sequence( KDChartEnums::GranularitySequence_10_20 )
, stepWidth( 1.0 )
, subStepWidth( 0.0 )
{}
DataDimension( qreal start_,
qreal end_,
bool isCalculated_,
AbstractCoordinatePlane::AxesCalcMode calcMode_,
KDChartEnums::GranularitySequence sequence_,
qreal stepWidth_=0.0,
qreal subStepWidth_=0.0 )
: start( start_ )
, end( end_ )
, isCalculated( isCalculated_ )
, calcMode( calcMode_ )
, sequence( sequence_ )
, stepWidth( stepWidth_ )
, subStepWidth( subStepWidth_ )
{}
/**
* Returns the size of the distance,
* equivalent to the width() (or height(), resp.) of a QRectF.
*
* Note that this value can be negative, e.g. indicating axis labels
* going in reversed direction.
*/
qreal distance() const
{
return end-start;
}
bool operator==( const DataDimension& r ) const
{
return
(start == r.start) &&
(end == r.end) &&
(sequence == r.sequence) &&
(isCalculated == r.isCalculated) &&
(calcMode == r.calcMode) &&
(stepWidth == r.stepWidth) &&
(subStepWidth == r.subStepWidth);
}
bool operator!=( const DataDimension& other ) const
{ return !operator==( other ); }
qreal start;
qreal end;
bool isCalculated;
AbstractCoordinatePlane::AxesCalcMode calcMode;
KDChartEnums::GranularitySequence sequence;
qreal stepWidth;
qreal subStepWidth;
};
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<( QDebug stream, const DataDimension& r );
#endif
}
#endif