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 #ifndef KCHARTPOSITION_H 21 #define KCHARTPOSITION_H 22 23 #include <QDebug> 24 #include <Qt> 25 #include <QMetaType> 26 #include <QCoreApplication> 27 #include "KChartGlobal.h" 28 #include "KChartEnums.h" 29 30 QT_BEGIN_NAMESPACE 31 class QStringList; 32 class QByteArray; 33 template <typename T> class QList; 34 QT_END_NAMESPACE 35 36 namespace KChart { 37 38 /** 39 * \class Position KChartPosition.h 40 * \brief Defines a position, using compass terminology. 41 * 42 * Using KChart::Position you can specify one of nine 43 * pre-defined, logical points (see the \c static \c const getter 44 * methods below), in a similar way, as you would use a 45 * compass to navigate on a map. 46 * 47 * For each piece (slice/bar, etc.) of a chart for example, you can specify the position of the value 48 * labels. Figure 1 illustrates which cardinal points refer to which points 49 * on a pie or bar chart, resp. In the graphic, "N" stands for North, "S" for South, etc. 50 * 51 * \image html position-alignments.png "Figure 1: Different interpretations of KChart::Position within KChart" 52 * 53 * \note Often you will declare a \c Position together with the 54 * RelativePosition class, to specify a logical point, 55 * which then will be used to layout your chart at runtime, 56 * e.g. for specifying the location of a floating Legend box. 57 * 58 * For comparing a Position's value with a switch () statement, 59 * you can use numeric values defined in KChartEnums, like this: 60 \verbatim 61 switch ( yourPosition().value() ) { 62 case KChartEnums::PositionNorthWest: 63 // your code ... 64 break; 65 case KChartEnums::PositionNorth: 66 // your code ... 67 break; 68 } 69 \endverbatim 70 * \sa RelativePosition, KChartEnums::PositionValue 71 */ 72 class KCHART_EXPORT Position 73 { 74 Q_DECLARE_TR_FUNCTIONS( Position ) 75 Position( int value ); 76 public: 77 Position(); 78 Position( KChartEnums::PositionValue value ); // intentionally non-explicit 79 80 KChartEnums::PositionValue value() const; 81 82 const char *name() const; 83 QString printableName() const; 84 85 bool isUnknown() const; 86 87 bool isWestSide() const; 88 bool isNorthSide() const; 89 bool isEastSide() const; 90 bool isSouthSide() const; 91 92 bool isCorner() const; 93 bool isPole() const; 94 95 bool isFloating() const; 96 97 static const Position& Unknown; 98 static const Position& Center; 99 static const Position& NorthWest; 100 static const Position& North; 101 static const Position& NorthEast; 102 static const Position& East; 103 static const Position& SouthEast; 104 static const Position& South; 105 static const Position& SouthWest; 106 static const Position& West; 107 108 static const Position& Floating; 109 110 // boolean flags: 1, 2, 4, 8, ... 111 enum Option { 112 IncludeCenter = 0x1, 113 IncludeFloating = 0x2 }; 114 Q_DECLARE_FLAGS( Options, Option ) 115 116 // Unfortunately the following typecast from int to Options is needed 117 // as the | operator is not defined yet, this will be done by 118 // the makro Q_DECLARE_OPERATORS_FOR_FLAGS( KChart::Position::Options ) 119 // at the bottom of this file. 120 static QList<QByteArray> names( Options options = Options(IncludeCenter | IncludeFloating) ); 121 static QStringList printableNames( Options options = Options(IncludeCenter | IncludeFloating) ); 122 123 static Position fromName(const char * name); 124 static Position fromName(const QByteArray & name); 125 126 bool operator==( const Position& ) const; 127 bool operator==( int ) const; 128 bool operator!=( const Position& ) const; 129 bool operator!=( int ) const; 130 131 private: 132 int m_value; 133 }; // End of class Position 134 135 inline bool Position::operator!=( const Position & other ) const { return !operator==( other ); } 136 inline bool Position::operator!=( int other ) const { return !operator==( other ); } 137 138 /** 139 * @brief Stores the absolute target points of a Position 140 * \internal 141 */ 142 class KCHART_EXPORT PositionPoints 143 { 144 public: PositionPoints()145 PositionPoints() {} // all points get initialized with the default automatically 146 PositionPoints(QPointF center,QPointF northWest,QPointF north,QPointF northEast,QPointF east,QPointF southEast,QPointF south,QPointF southWest,QPointF west)147 PositionPoints( 148 QPointF center, 149 QPointF northWest, 150 QPointF north, 151 QPointF northEast, 152 QPointF east, 153 QPointF southEast, 154 QPointF south, 155 QPointF southWest, 156 QPointF west ) 157 : mPositionCenter( center ) 158 , mPositionNorthWest( northWest ) 159 , mPositionNorth( north ) 160 , mPositionNorthEast( northEast ) 161 , mPositionEast( east ) 162 , mPositionSouthEast( southEast ) 163 , mPositionSouth( south ) 164 , mPositionSouthWest( southWest ) 165 , mPositionWest( west ) 166 {} PositionPoints(const QPointF & onePointForAllPositions)167 PositionPoints( 168 const QPointF& onePointForAllPositions ) 169 : mPositionCenter( onePointForAllPositions ) 170 , mPositionNorthWest( onePointForAllPositions ) 171 , mPositionNorth( onePointForAllPositions ) 172 , mPositionNorthEast( onePointForAllPositions ) 173 , mPositionEast( onePointForAllPositions ) 174 , mPositionSouthEast( onePointForAllPositions ) 175 , mPositionSouth( onePointForAllPositions ) 176 , mPositionSouthWest( onePointForAllPositions ) 177 , mPositionWest( onePointForAllPositions ) 178 {} PositionPoints(const QRectF & rect)179 PositionPoints( 180 const QRectF& rect ) 181 { 182 const QRectF r( rect.normalized() ); 183 mPositionCenter = r.center(); 184 mPositionNorthWest = r.topLeft(); 185 mPositionNorth = QPointF(r.center().x(), r.top()); 186 mPositionNorthEast = r.topRight(); 187 mPositionEast = QPointF(r.right(), r.center().y()); 188 mPositionSouthEast = r.bottomRight(); 189 mPositionSouth = QPointF(r.center().x(), r.bottom()); 190 mPositionSouthWest = r.bottomLeft(); 191 mPositionWest = QPointF(r.left(), r.center().y()); 192 } PositionPoints(QPointF northWest,QPointF northEast,QPointF southEast,QPointF southWest)193 PositionPoints( 194 QPointF northWest, 195 QPointF northEast, 196 QPointF southEast, 197 QPointF southWest ) 198 : mPositionCenter( (northWest + southEast) / 2.0 ) 199 , mPositionNorthWest( northWest ) 200 , mPositionNorth( (northWest + northEast) / 2.0 ) 201 , mPositionNorthEast( northEast ) 202 , mPositionEast( (northEast + southEast) / 2.0 ) 203 , mPositionSouthEast( southEast ) 204 , mPositionSouth( (southWest + southEast) / 2.0 ) 205 , mPositionSouthWest( southWest ) 206 , mPositionWest( (northWest + southWest) / 2.0 ) 207 {} 208 setDegrees(KChartEnums::PositionValue pos,qreal degrees)209 void setDegrees( KChartEnums::PositionValue pos, qreal degrees ) 210 { 211 mapOfDegrees[pos] = degrees; 212 } 213 214 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE) degrees(KChartEnums::PositionValue pos)215 const qreal degrees( KChartEnums::PositionValue pos ) const 216 #else 217 qreal degrees( KChartEnums::PositionValue pos ) const 218 #endif 219 { 220 if ( mapOfDegrees.contains(pos) ) 221 return mapOfDegrees[pos]; 222 return 0.0; 223 } 224 225 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE) point(Position position)226 const QPointF point( Position position ) const 227 #else 228 QPointF point( Position position ) const 229 #endif 230 { 231 //qDebug() << "point( " << position.name() << " )"; 232 if ( position == Position::Center) 233 return mPositionCenter; 234 if ( position == Position::NorthWest) 235 return mPositionNorthWest; 236 if ( position == Position::North) 237 return mPositionNorth; 238 if ( position == Position::NorthEast) 239 return mPositionNorthEast; 240 if ( position == Position::East) 241 return mPositionEast; 242 if ( position == Position::SouthEast) 243 return mPositionSouthEast; 244 if ( position == Position::South) 245 return mPositionSouth; 246 if ( position == Position::SouthWest) 247 return mPositionSouthWest; 248 if ( position == Position::West) 249 return mPositionWest; 250 return mPositionUnknown; 251 } 252 isNull()253 bool isNull() const 254 { 255 return 256 mPositionUnknown.isNull() && 257 mPositionCenter.isNull() && 258 mPositionNorthWest.isNull() && 259 mPositionNorth.isNull() && 260 mPositionNorthEast.isNull() && 261 mPositionEast.isNull() && 262 mPositionSouthEast.isNull() && 263 mPositionSouth.isNull() && 264 mPositionSouthWest.isNull() && 265 mPositionWest.isNull(); 266 } 267 268 QPointF mPositionUnknown; 269 QPointF mPositionCenter; 270 QPointF mPositionNorthWest; 271 QPointF mPositionNorth; 272 QPointF mPositionNorthEast; 273 QPointF mPositionEast; 274 QPointF mPositionSouthEast; 275 QPointF mPositionSouth; 276 QPointF mPositionSouthWest; 277 QPointF mPositionWest; 278 QMap<KChartEnums::PositionValue, qreal> mapOfDegrees; 279 280 }; // End of class PositionPoints 281 282 283 } 284 285 286 #if !defined(QT_NO_DEBUG_STREAM) 287 KCHART_EXPORT QDebug operator<<(QDebug, const KChart::Position& ); 288 #endif /* QT_NO_DEBUG_STREAM */ 289 290 QT_BEGIN_NAMESPACE 291 Q_DECLARE_TYPEINFO( KChart::Position, Q_MOVABLE_TYPE ); 292 Q_DECLARE_OPERATORS_FOR_FLAGS( KChart::Position::Options ) 293 QT_END_NAMESPACE 294 295 Q_DECLARE_METATYPE( KChart::Position ) 296 297 #endif // KCHARTPOSITION_H 298