|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbWidgets module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include "hbsliderhandle_p.h" |
|
27 #include "hbslidercontrol_p.h" |
|
28 #include "hbslidercontrol_p_p.h" |
|
29 #include <hbwidgetfeedback.h> |
|
30 #include <hbstyle.h> |
|
31 #include <hbstyleoptionslider.h> |
|
32 #include <QGraphicsSceneMouseEvent> |
|
33 #include <QGraphicsScene> |
|
34 |
|
35 #ifdef HB_EFFECTS |
|
36 #include "hbeffect.h" |
|
37 #include "hbeffectinternal_p.h" |
|
38 #define HB_SLIDERHANDLE_TYPE "HB_SLIDERHANDLE" |
|
39 #endif |
|
40 |
|
41 /*! |
|
42 This is internal class for HbSlider |
|
43 this created slider handle |
|
44 It also has event handling for handle press/move and release |
|
45 |
|
46 */ |
|
47 |
|
48 |
|
49 /*! |
|
50 Constructs a slider handle for \a slider. |
|
51 */ |
|
52 HbSliderHandle::HbSliderHandle(HbSliderControl *slider) |
|
53 : HbWidget(slider), |
|
54 sliderControl(slider), |
|
55 gItem(0) , |
|
56 handleDragPos(0), |
|
57 touchItem(0), |
|
58 mHandleItem(0) |
|
59 { |
|
60 // create handle icon item |
|
61 gItem = slider->style()->createPrimitive(HbStyle::P_Slider_thumb, this); |
|
62 HbStyle::setItemName(gItem , "icon"); |
|
63 |
|
64 // create touch area for handle |
|
65 touchItem = slider->style()->createPrimitive(HbStyle::P_SliderElement_touchhandle, this); |
|
66 HbStyle::setItemName(touchItem , "toucharea"); |
|
67 |
|
68 setZValue(slider->zValue() + 1); |
|
69 |
|
70 |
|
71 #ifdef HB_EFFECTS |
|
72 // horizontal thumb press |
|
73 // HbEffectInternal::add(HB_SLIDERHANDLE_TYPE,"sliderhandle_h_press", "h_thumbpress"); |
|
74 //horizonal thumb release |
|
75 //HbEffectInternal::add(HB_SLIDERHANDLE_TYPE,"sliderhandle_h_releasel", "h_thumbrelease"); |
|
76 // vertical thumb press |
|
77 //HbEffectInternal::add(HB_SLIDERHANDLE_TYPE,"sliderhandle_v_press", "v_thumbpress"); |
|
78 //vertical thumb release |
|
79 //HbEffectInternal::add(HB_SLIDERHANDLE_TYPE,"sliderhandle_v_release", "v_thumbrelease"); |
|
80 // horizontal out of bound |
|
81 //HbEffectInternal::add(HB_SLIDERHANDLE_TYPE,"sliderhandle_h_outofbound", "h_outofbound"); |
|
82 //vertical out of bound |
|
83 //HbEffectInternal::add(HB_SLIDERHANDLE_TYPE,"sliderhandle_v_outofbound", "v_outofbound"); |
|
84 #endif |
|
85 } |
|
86 |
|
87 /*! |
|
88 Destroys the slider handle. |
|
89 */ |
|
90 HbSliderHandle::~HbSliderHandle() |
|
91 { |
|
92 if(mHandleItem) { |
|
93 mHandleItem->removeSceneEventFilter(this); |
|
94 } |
|
95 } |
|
96 |
|
97 |
|
98 /*! |
|
99 reimp |
|
100 |
|
101 */ |
|
102 /*void HbSliderHandle::polish( HbStyleParameters& params ) |
|
103 { |
|
104 updatePrimitives(); |
|
105 HbWidget::polish(params); |
|
106 }*/ |
|
107 |
|
108 /*! |
|
109 This Api set handle position and update handle icon to press ot normal |
|
110 */ |
|
111 void HbSliderHandle::forceSetPos(const QPointF &pos) |
|
112 { |
|
113 setPos(pos); |
|
114 HbStyleOptionSlider opt; |
|
115 sliderControl->initStyleOption(&opt); |
|
116 if( scene()){ |
|
117 if (true == sliderControl->isSliderDown()){ |
|
118 opt.state |= QStyle::State_Sunken; |
|
119 sliderControl->style()->updatePrimitive( |
|
120 sliderControl->primitive(HbStyle::P_Slider_groove), HbStyle::P_Slider_groove, &opt); |
|
121 } else { |
|
122 opt.state &= ~QStyle::State_Sunken; |
|
123 } |
|
124 } else { |
|
125 opt.state &= ~QStyle::State_Sunken; |
|
126 } |
|
127 |
|
128 opt.boundingRect=boundingRect(); |
|
129 sliderControl->style()->updatePrimitive(gItem, HbStyle::P_Slider_thumb, &opt); |
|
130 } |
|
131 |
|
132 void HbSliderHandle::setHandleItem(QGraphicsItem *item) |
|
133 { |
|
134 if(!item) { |
|
135 return; |
|
136 } |
|
137 if(mHandleItem) { |
|
138 delete mHandleItem; |
|
139 mHandleItem =0; |
|
140 } |
|
141 |
|
142 setHandlesChildEvents(false); |
|
143 |
|
144 mHandleItem = item; |
|
145 mHandleItem->setParentItem(this); |
|
146 sliderControl->style()->setItemName(mHandleItem,"widget"); |
|
147 //((QGraphicsWidget*)mHandleItem)->setGeometry(gItem->geometry());//TODO:geometry from css |
|
148 |
|
149 if(scene()) { |
|
150 mHandleItem->removeSceneEventFilter(this); |
|
151 mHandleItem->installSceneEventFilter(this); |
|
152 } |
|
153 mHandleItem->setFlag(QGraphicsItem::ItemIsMovable,true);//required as the press has to be accepted to filter move events. |
|
154 |
|
155 } |
|
156 |
|
157 QGraphicsItem *HbSliderHandle::handleItem() const |
|
158 { |
|
159 return mHandleItem; |
|
160 } |
|
161 |
|
162 void HbSliderHandle::showEvent(QShowEvent *event) |
|
163 { |
|
164 Q_UNUSED(event); |
|
165 if(scene()) { |
|
166 if(gItem) { |
|
167 //gItem->removeSceneEventFilter(this); |
|
168 //gItem->installSceneEventFilter(this); |
|
169 } |
|
170 if(mHandleItem && scene()) { |
|
171 mHandleItem->removeSceneEventFilter(this); |
|
172 mHandleItem->installSceneEventFilter(this); |
|
173 } |
|
174 |
|
175 } |
|
176 } |
|
177 bool HbSliderHandle::sceneEventFilter(QGraphicsItem *obj,QEvent *event) |
|
178 { |
|
179 //TODO: touch area doesnt work with the current filtering mechanism. find better solution |
|
180 if( obj == mHandleItem) { |
|
181 if(event->type() == QEvent::GraphicsSceneMouseMove){ |
|
182 mouseMoveEvent ( (QGraphicsSceneMouseEvent *) event ) ; |
|
183 return true; |
|
184 } |
|
185 else if (event->type() == QEvent::GraphicsSceneMousePress){ |
|
186 mousePressEvent((QGraphicsSceneMouseEvent *) event); |
|
187 } |
|
188 else if (event->type() == QEvent::GraphicsSceneMouseRelease){ |
|
189 mouseReleaseEvent((QGraphicsSceneMouseEvent *) event); |
|
190 } |
|
191 } |
|
192 return false; |
|
193 } |
|
194 |
|
195 /*! |
|
196 reimp |
|
197 |
|
198 */ |
|
199 void HbSliderHandle::mousePressEvent(QGraphicsSceneMouseEvent *event) |
|
200 { |
|
201 qreal span = 0; |
|
202 HbWidget::mousePressEvent(event); |
|
203 QRectF sliderBounds=sliderControl->boundingRect(); |
|
204 QRectF handleBounds=boundingRect(); |
|
205 sliderControl->setSliderDown(true); |
|
206 HbWidgetFeedback::triggered(sliderControl, Hb::InstantPressed, Hb::ModifierSliderHandle); |
|
207 if (scene()){ |
|
208 HbStyleOptionSlider opt; |
|
209 sliderControl->initStyleOption(&opt); |
|
210 if (sliderControl->orientation() == Qt::Horizontal) { |
|
211 #ifdef HB_EFFECTS |
|
212 HbEffect::start(gItem, HB_SLIDERHANDLE_TYPE, "h_thumbpress"); |
|
213 #endif |
|
214 sliderBounds.adjust(0, 0, -handleBounds.width(), 0); |
|
215 span = sliderBounds.width(); |
|
216 handleInitialPos = static_cast<int>(mapToParent(event->pos()).rx()); |
|
217 } else { |
|
218 #ifdef HB_EFFECTS |
|
219 HbEffect::start(gItem, HB_SLIDERHANDLE_TYPE, "v_thumbpress"); |
|
220 #endif |
|
221 sliderBounds.adjust(0, 0, 0, -handleBounds.height()); |
|
222 span = sliderBounds.height(); |
|
223 handleInitialPos = static_cast<int>(mapToParent(event->pos()).ry()); |
|
224 } |
|
225 handleDragPos= QStyle::sliderPositionFromValue(opt.minimum, opt.maximum, |
|
226 sliderControl->sliderPosition(), static_cast<int>(span),opt.upsideDown); |
|
227 updatePrimitives(); |
|
228 } |
|
229 event->accept(); |
|
230 } |
|
231 |
|
232 /*! |
|
233 reimp |
|
234 |
|
235 */ |
|
236 void HbSliderHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) |
|
237 { |
|
238 HbWidget::mouseReleaseEvent(event); |
|
239 #ifdef HB_EFFECTS |
|
240 if( sliderControl->orientation() == Qt::Horizontal ) { |
|
241 HbEffect::start(gItem, HB_SLIDERHANDLE_TYPE, "h_thumbrelease"); |
|
242 } |
|
243 else { |
|
244 HbEffect::start(gItem, HB_SLIDERHANDLE_TYPE, "v_thumbrelease"); |
|
245 } |
|
246 #endif |
|
247 HbWidgetFeedback::triggered(sliderControl, Hb::InstantReleased, Hb::ModifierSliderHandle); |
|
248 sliderControl->setSliderDown(false); |
|
249 QRectF controlRect = sliderControl->sceneBoundingRect(); |
|
250 if(!controlRect.contains(event->scenePos().x() , event->scenePos().y()) ){ |
|
251 sliderControl->releasedOutside(true); |
|
252 } |
|
253 if(sliderControl->singleStep() != 0) { |
|
254 HbWidgetFeedback::continuousStopped(sliderControl, Hb::ContinuousDragged); |
|
255 } |
|
256 event->accept(); |
|
257 if( sliderControl->snappingMode()!= HbSliderControl::NoSnapping ){ |
|
258 sliderControl->updateSliderPosToTick(); |
|
259 } |
|
260 updatePrimitives(); |
|
261 } |
|
262 |
|
263 /*! |
|
264 reimp |
|
265 |
|
266 */ |
|
267 void HbSliderHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) |
|
268 { |
|
269 qreal span = 0; |
|
270 HbWidget::mouseMoveEvent(event); |
|
271 QRectF sliderBounds=sliderControl->boundingRect(); |
|
272 QRectF handleBounds=boundingRect(); |
|
273 HbStyleOptionSlider opt; |
|
274 sliderControl->initStyleOption(&opt); |
|
275 int sliderPos; |
|
276 if ( sliderControl->orientation() == Qt::Horizontal ) { |
|
277 #ifdef HB_EFFECTS |
|
278 if( sliderBounds.topLeft().x() > mapToParent(event->pos()).x() || |
|
279 sliderBounds.bottomRight().x() < mapToParent(event->pos()).x()) { |
|
280 HbEffect::start(gItem, HB_SLIDERHANDLE_TYPE, "h_outofbound"); |
|
281 } |
|
282 #endif |
|
283 sliderBounds.adjust(0, 0, -handleBounds.width(), 0); |
|
284 span = sliderBounds.width(); |
|
285 sliderPos = static_cast<int>( |
|
286 handleDragPos+(mapToParent(event->pos()).rx()-handleInitialPos)); |
|
287 } else { |
|
288 #ifdef HB_EFFECTS |
|
289 if( sliderBounds.topLeft().y() > mapToParent(event->pos()).y() || |
|
290 sliderBounds.bottomRight().y() < mapToParent(event->pos()).y()) { |
|
291 HbEffect::start(gItem, HB_SLIDERHANDLE_TYPE, "v_outofbound"); |
|
292 } |
|
293 #endif |
|
294 sliderBounds.adjust(0, 0, 0, -handleBounds.height()); |
|
295 span = sliderBounds.height(); |
|
296 sliderPos = static_cast<int>( |
|
297 handleDragPos+(mapToParent(event->pos()).ry()-handleInitialPos)); |
|
298 } |
|
299 int pressValue= QStyle::sliderValueFromPosition(opt.minimum, opt.maximum, |
|
300 sliderPos, static_cast<int>(span),opt.upsideDown); |
|
301 sliderControl->setSliderPosition(pressValue); |
|
302 sliderControl->showToolTip(); |
|
303 } |
|
304 |
|
305 /*! |
|
306 reimp |
|
307 |
|
308 */ |
|
309 void HbSliderHandle::updatePrimitives() |
|
310 { |
|
311 HbStyleOptionSlider opt; |
|
312 sliderControl->initStyleOption(&opt); |
|
313 if( scene()){ |
|
314 if (true == sliderControl->isSliderDown()){ |
|
315 opt.state |= QStyle::State_Sunken; |
|
316 sliderControl->style()->updatePrimitive( |
|
317 sliderControl->primitive(HbStyle::P_Slider_groove), HbStyle::P_Slider_groove, &opt); |
|
318 } else { |
|
319 opt.state &= ~QStyle::State_Sunken; |
|
320 } |
|
321 } else { |
|
322 opt.state &= ~QStyle::State_Sunken; |
|
323 } |
|
324 |
|
325 opt.boundingRect=boundingRect(); |
|
326 sliderControl->style()->updatePrimitive(gItem, HbStyle::P_Slider_thumb, &opt); |
|
327 sliderControl->style()->updatePrimitive(touchItem , HbStyle::P_SliderElement_touchhandle ,&opt); |
|
328 sliderControl->update(boundingRect()); |
|
329 } |
|
330 |
|
331 /*! |
|
332 reimp |
|
333 |
|
334 */ |
|
335 QGraphicsItem * HbSliderHandle::primitive(HbStyle::Primitive primitive) const |
|
336 { |
|
337 switch (primitive) { |
|
338 case HbStyle::P_Slider_thumb: |
|
339 return gItem; |
|
340 case HbStyle::P_SliderElement_touchhandle: |
|
341 return touchItem; |
|
342 default: |
|
343 return NULL; |
|
344 } |
|
345 } |