1 /*
2  * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB.  All rights reserved.
3  *
4  * This file is part of the KD Chart library.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "KChartRelativePosition.h"
21 
22 #include "KChartEnums.h"
23 #include "KChartMeasure.h"
24 #include "KChartPosition.h"
25 #include "KChartAbstractArea.h"
26 #include "KChartMath_p.h"
27 
28 #include <QWidget>
29 #include <QLayout>
30 
31 using namespace KChart;
32 
33 class Q_DECL_HIDDEN RelativePosition::Private {
34     friend class ::KChart::RelativePosition;
35 public:
36     Private();
37     ~Private();
38 
39 private:
40     QObject* area;
41     PositionPoints points;
42     Position position;
43     Qt::Alignment alignment;
44     Measure horizontalPadding;
45     Measure verticalPadding;
46     qreal rotation;
47 };
48 
49 
Private()50 RelativePosition::Private::Private()
51     : area( nullptr ),
52       alignment( Qt::AlignCenter ),
53       rotation( 0 )
54 {
55 
56 }
57 
~Private()58 RelativePosition::Private::~Private()
59 {}
60 
61 
62 
RelativePosition()63 RelativePosition::RelativePosition()
64     : _d( new Private )
65 {
66 
67 }
68 
RelativePosition(const RelativePosition & r)69 RelativePosition::RelativePosition( const RelativePosition& r )
70     : _d( new Private( *r._d ) )
71 {
72 
73 }
74 
operator =(const RelativePosition & other)75 RelativePosition & RelativePosition::operator=( const RelativePosition & other ) {
76     RelativePosition copy( other );
77     copy.swap( *this );
78     return *this;
79 }
80 
~RelativePosition()81 RelativePosition::~RelativePosition()
82 {
83     delete _d;
84 }
85 
86 #define d d_func()
87 
setReferenceArea(QObject * area)88 void RelativePosition::setReferenceArea( QObject * area ) {
89     d->area = area;
90     if ( area )
91         setReferencePoints( PositionPoints() );
92 }
93 
referenceArea() const94 QObject * RelativePosition::referenceArea() const {
95     return d->area;
96 }
97 
setReferencePoints(const PositionPoints & points)98 void RelativePosition::setReferencePoints( const PositionPoints& points ) {
99     d->points = points;
100     if ( !points.isNull() )
101         setReferenceArea( nullptr );
102 }
referencePoints() const103 const PositionPoints RelativePosition::referencePoints() const{
104     return d->points;
105 }
106 
setReferencePosition(Position pos)107 void RelativePosition::setReferencePosition( Position pos ) {
108     d->position = pos;
109 }
110 
resetReferencePosition()111 void RelativePosition::resetReferencePosition() {
112     d->position = Position::Unknown;
113 }
114 
referencePosition() const115 Position RelativePosition::referencePosition() const {
116     return d->position;
117 }
118 
setAlignment(Qt::Alignment align)119 void RelativePosition::setAlignment( Qt::Alignment align ) {
120     d->alignment = align;
121 }
122 
alignment() const123 Qt::Alignment RelativePosition::alignment() const {
124     return d->alignment;
125 }
126 
setHorizontalPadding(const Measure & pad)127 void RelativePosition::setHorizontalPadding( const Measure & pad ) {
128     d->horizontalPadding = pad;
129 }
130 
horizontalPadding() const131 Measure RelativePosition::horizontalPadding() const {
132     return d->horizontalPadding;
133 }
134 
setVerticalPadding(const Measure & pad)135 void RelativePosition::setVerticalPadding( const Measure & pad ) {
136     d->verticalPadding = pad;
137 }
138 
verticalPadding() const139 Measure RelativePosition::verticalPadding() const {
140     return d->verticalPadding;
141 }
142 
setRotation(qreal rot)143 void RelativePosition::setRotation( qreal rot ) {
144     d->rotation = rot;
145 }
146 
rotation() const147 qreal RelativePosition::rotation() const {
148     return d->rotation;
149 }
150 
151 
referencePoint(qreal * polarDegrees) const152 const QPointF RelativePosition::referencePoint( qreal* polarDegrees ) const
153 {
154     bool useRect = ( d->area != nullptr );
155     QRect rect;
156     if ( useRect ) {
157         if ( const QWidget* widget = qobject_cast< const QWidget* >( d->area ) ) {
158             const QLayout* layout = widget->layout();
159             rect = layout ? layout->geometry() : widget->geometry();
160         } else if ( const AbstractArea* kdcArea = qobject_cast< const AbstractArea* >( d->area ) ) {
161             rect = kdcArea->geometry();
162         } else {
163             useRect = false;
164         }
165     }
166 
167     QPointF pt;
168     qreal angle = 0.0;
169     if ( useRect ) {
170         pt = PositionPoints( rect ).point( d->position );
171     } else {
172         pt = d->points.point( d->position );
173         angle = d->points.degrees( d->position.value() );
174     }
175 
176     if ( polarDegrees ) {
177         *polarDegrees = angle;
178     }
179    return pt;
180 }
181 
182 
calculatedPoint(const QSizeF & autoSize) const183 const QPointF RelativePosition::calculatedPoint( const QSizeF& autoSize ) const
184 {
185     const qreal dx = horizontalPadding().calculatedValue( autoSize, KChartEnums::MeasureOrientationHorizontal );
186     const qreal dy = verticalPadding().calculatedValue( autoSize, KChartEnums::MeasureOrientationVertical );
187 
188     qreal polarDegrees;
189     QPointF pt( referencePoint( &polarDegrees ) );
190     if ( polarDegrees == 0.0 ) {
191         pt += QPointF( dx, dy );
192     } else {
193         const qreal rad = DEGTORAD( polarDegrees);
194         const qreal sinDeg = sin(rad);
195         const qreal cosDeg = cos(rad);
196         pt.setX( pt.x() + dx * cosDeg + dy * sinDeg );
197         pt.setY( pt.y() - dx * sinDeg + dy * cosDeg );
198     }
199     return pt;
200 }
201 
202 
operator ==(const RelativePosition & r) const203 bool RelativePosition::operator==( const RelativePosition& r ) const
204 {
205     return  d->area              == r.referenceArea() &&
206             d->position          == r.referencePosition() &&
207             d->alignment         == r.alignment() &&
208             d->horizontalPadding == r.horizontalPadding() &&
209             d->verticalPadding   == r.verticalPadding() &&
210             d->rotation          == r.rotation() ;
211 }
212 
213 #undef d
214 
215 
216 #if !defined(QT_NO_DEBUG_STREAM)
operator <<(QDebug dbg,const KChart::RelativePosition & rp)217 QDebug operator<<(QDebug dbg, const KChart::RelativePosition& rp)
218 {
219     dbg << "KChart::RelativePosition("
220 	<< "referencearea="<<rp.referenceArea()
221 	<< "referenceposition="<<rp.referencePosition()
222 	<< "alignment="<<rp.alignment()
223 	<< "horizontalpadding="<<rp.horizontalPadding()
224 	<< "verticalpadding="<<rp.verticalPadding()
225 	<< "rotation="<<rp.rotation()
226 	<< ")";
227     return dbg;
228 }
229 #endif /* QT_NO_DEBUG_STREAM */
230