##// END OF EJS Templates
PieSliceItem bounding rect fix
Jani Honkonen -
r718:7a2556deb83d
parent child
Show More
@@ -1,182 +1,185
1 1 #include "piesliceitem_p.h"
2 2 #include "piechartitem_p.h"
3 3 #include "qpieseries.h"
4 4 #include "qpieslice.h"
5 5 #include "chartpresenter_p.h"
6 6 #include <QPainter>
7 7 #include <QDebug>
8 8 #include <qmath.h>
9 9 #include <QGraphicsSceneEvent>
10 10 #include <QTime>
11 11
12 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 13
14 14 #define PI 3.14159265 // TODO: is this defined in some header?
15 15
16 16 QPointF offset(qreal angle, qreal length)
17 17 {
18 18 qreal dx = qSin(angle*(PI/180)) * length;
19 19 qreal dy = qCos(angle*(PI/180)) * length;
20 20 return QPointF(dx, -dy);
21 21 }
22 22
23 23 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
24 24 :QGraphicsObject(parent)
25 25 {
26 26 setAcceptHoverEvents(true);
27 27 setAcceptedMouseButtons(Qt::MouseButtonMask);
28 28 setZValue(ChartPresenter::PieSeriesZValue);
29 29 }
30 30
31 31 PieSliceItem::~PieSliceItem()
32 32 {
33 33
34 34 }
35 35
36 36 QRectF PieSliceItem::boundingRect() const
37 37 {
38 38 return m_boundingRect;
39 39 }
40 40
41 41 QPainterPath PieSliceItem::shape() const
42 42 {
43 43 // Don't include the label and label arm.
44 44 // This is used to detect a mouse clicks. We do not want clicks from label.
45 45 return m_slicePath;
46 46 }
47 47
48 48 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
49 49 {
50 50 painter->setClipRect(parentItem()->boundingRect());
51 51
52 52 painter->save();
53 53 painter->setPen(m_data.m_slicePen);
54 54 painter->setBrush(m_data.m_sliceBrush);
55 55 painter->drawPath(m_slicePath);
56 56 painter->restore();
57 57
58 58 if (m_data.m_isLabelVisible) {
59 59 painter->setPen(m_data.m_labelPen);
60 60 painter->drawPath(m_labelArmPath);
61 61 // the pen color will affect the font color as well
62 62 painter->setFont(m_data.m_labelFont);
63 63 painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText);
64 64 }
65 65 }
66 66
67 67 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
68 68 {
69 69 emit hoverEnter();
70 70 }
71 71
72 72 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
73 73 {
74 74 emit hoverLeave();
75 75 }
76 76
77 77 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
78 78 {
79 79 emit clicked(event->buttons());
80 80 }
81 81
82 82 void PieSliceItem::setSliceData(PieSliceData sliceData)
83 83 {
84 84 m_data = sliceData;
85 85 }
86 86
87 87 void PieSliceItem::updateGeometry()
88 88 {
89 89 if (m_data.m_radius <= 0)
90 90 return;
91 91
92 92 prepareGeometryChange();
93 93
94 94 // update slice path
95 95 qreal centerAngle;
96 96 QPointF armStart;
97 97 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
98 98
99 99 // update text rect
100 100 m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText);
101 101
102 102 // update label arm path
103 103 QPointF labelTextStart;
104 104 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
105 105
106 106 // update text position
107 107 m_labelTextRect.moveBottomLeft(labelTextStart);
108 108
109 109 // update bounding rect
110 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
110 if (m_data.m_isLabelVisible)
111 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
112 else
113 m_boundingRect = m_slicePath.boundingRect();
111 114 }
112 115
113 116 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
114 117 {
115 118 if (slice->isExploded()) {
116 119 qreal centerAngle = slice->startAngle() + ((slice->endAngle() - slice->startAngle())/2);
117 120 qreal len = radius * slice->explodeDistanceFactor();
118 121 qreal dx = qSin(centerAngle*(PI/180)) * len;
119 122 qreal dy = -qCos(centerAngle*(PI/180)) * len;
120 123 point += QPointF(dx, dy);
121 124 }
122 125 return point;
123 126 }
124 127
125 128 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
126 129 {
127 130 // calculate center angle
128 131 *centerAngle = startAngle + (angleSpan/2);
129 132
130 133 // calculate slice rectangle
131 134 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
132 135
133 136 // slice path
134 137 // TODO: draw the shape so that it might have a hole in the center
135 138 QPainterPath path;
136 139 path.moveTo(rect.center());
137 140 path.arcTo(rect, -startAngle + 90, -angleSpan);
138 141 path.closeSubpath();
139 142
140 143 // calculate label arm start point
141 144 *armStart = center;
142 145 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
143 146
144 147 return path;
145 148 }
146 149
147 150 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
148 151 {
149 152 qreal dx = qSin(angle*(PI/180)) * length;
150 153 qreal dy = -qCos(angle*(PI/180)) * length;
151 154 QPointF parm1 = start + QPointF(dx, dy);
152 155
153 156 QPointF parm2 = parm1;
154 157 if (angle < 180) { // arm swings the other way on the left side
155 158 parm2 += QPointF(textWidth, 0);
156 159 *textStart = parm1;
157 160 }
158 161 else {
159 162 parm2 += QPointF(-textWidth,0);
160 163 *textStart = parm2;
161 164 }
162 165
163 166 // elevate the text position a bit so that it does not hit the line
164 167 *textStart += QPointF(0, -5);
165 168
166 169 QPainterPath path;
167 170 path.moveTo(start);
168 171 path.lineTo(parm1);
169 172 path.lineTo(parm2);
170 173
171 174 return path;
172 175 }
173 176
174 177 QRectF PieSliceItem::labelTextRect(QFont font, QString text)
175 178 {
176 179 QFontMetricsF fm(font);
177 180 return fm.boundingRect(text);
178 181 }
179 182
180 183 #include "moc_piesliceitem_p.cpp"
181 184
182 185 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now