|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 */ |
|
15 |
|
16 |
|
17 #include <e32base.h> |
|
18 #include <e32const.h> |
|
19 #include <coecntrl.h> |
|
20 #include <coemain.h> |
|
21 |
|
22 #include <AknUtils.h> |
|
23 |
|
24 #include "xnwidgetextensionadapter.h" |
|
25 #include "xncontroladapter.h" |
|
26 |
|
27 #include "xncomponentnodeimpl.h" |
|
28 #include "xncomponent.h" |
|
29 |
|
30 #include "xnuiengine.h" |
|
31 #include "xnhittest.h" |
|
32 |
|
33 #include "xnnode.h" |
|
34 #include "xnnodepluginif.h" |
|
35 #include "xnviewnodeimpl.h" |
|
36 #include "xnnodepluginif.h" |
|
37 #include "xndomdocument.h" |
|
38 #include "xnproperty.h" |
|
39 #include "xnodt.h" |
|
40 #include "xntype.h" |
|
41 #include "xndomnode.h" |
|
42 #include "xndomstringpool.h" |
|
43 |
|
44 #include "xnappuiadapter.h" |
|
45 #include "xnviewmanager.h" |
|
46 #include "xnviewdata.h" |
|
47 #include "xnplugindata.h" |
|
48 |
|
49 |
|
50 _LIT8( KPopUpText, "popup" ); |
|
51 _LIT8( KPositionHint, "_s60-position-hint" ); |
|
52 _LIT8( KWidgetNodeName, "widget" ); |
|
53 _LIT8( KParentIdName, "parentid" ); |
|
54 _LIT8( KDisplay, "display" ); |
|
55 _LIT8( KNone, "none" ); |
|
56 // ============================ MEMBER FUNCTIONS =============================== |
|
57 |
|
58 // ----------------------------------------------------------------------------- |
|
59 // CXnWidgetExtensionAdapter::NewL |
|
60 // Two-phased constructor. Can leave. |
|
61 // ----------------------------------------------------------------------------- |
|
62 // |
|
63 CXnWidgetExtensionAdapter* CXnWidgetExtensionAdapter::NewL( |
|
64 CXnNodePluginIf& aNode ) |
|
65 { |
|
66 CXnWidgetExtensionAdapter* self = |
|
67 new ( ELeave ) CXnWidgetExtensionAdapter( aNode ); |
|
68 CleanupStack::PushL( self ); |
|
69 self->ConstructL(); |
|
70 CleanupStack::Pop( self ); |
|
71 return self; |
|
72 } |
|
73 |
|
74 // ----------------------------------------------------------------------------- |
|
75 // CXnWidgetExtensionAdapter::~CXnWidgetExtensionAdapter |
|
76 // Destructor. |
|
77 // ----------------------------------------------------------------------------- |
|
78 // |
|
79 CXnWidgetExtensionAdapter::~CXnWidgetExtensionAdapter() |
|
80 { |
|
81 } |
|
82 |
|
83 // ----------------------------------------------------------------------------- |
|
84 // CXnWidgetExtensionAdapter::CXnWidgetExtensionAdapter |
|
85 // C++ default constructor. Must not leave. |
|
86 // ----------------------------------------------------------------------------- |
|
87 // |
|
88 CXnWidgetExtensionAdapter::CXnWidgetExtensionAdapter( CXnNodePluginIf& aNode ) |
|
89 : iNode( aNode ), iPositionHint( ENone ) |
|
90 { |
|
91 } |
|
92 |
|
93 // ----------------------------------------------------------------------------- |
|
94 // CXnWidgetExtensionAdapter::ConstructL |
|
95 // 2nd phase constructor. Can leave. |
|
96 // ----------------------------------------------------------------------------- |
|
97 // |
|
98 void CXnWidgetExtensionAdapter::ConstructL() |
|
99 { |
|
100 CreateWindowL(); |
|
101 Window().SetRequiredDisplayMode( EColor16MA ); |
|
102 |
|
103 // this adapter handles both widgetextension and popup nodes |
|
104 // we have to decide which one of them is the recent one |
|
105 |
|
106 CXnType* typeInfo = iNode.Node().Type(); |
|
107 const TDesC8& type = typeInfo->Type(); |
|
108 |
|
109 if ( type == KPopUpText ) |
|
110 { |
|
111 // popup element does not capture pointer events |
|
112 SetPointerCapture( ETrue ); |
|
113 } |
|
114 else |
|
115 { |
|
116 // widget extension node |
|
117 SetPointerCapture( ETrue ); |
|
118 if ( Window().SetTransparencyAlphaChannel() == KErrNone ) |
|
119 { |
|
120 Window().SetBackgroundColor( ~0 ); |
|
121 } |
|
122 } |
|
123 iUiEngine = iNode.Node().UiEngine(); |
|
124 CXnControlAdapter::ConstructL( iNode ); |
|
125 EnableDragEvents(); |
|
126 |
|
127 iAppUiAdapter = static_cast< CXnAppUiAdapter* >( iAvkonAppUi ); |
|
128 |
|
129 } |
|
130 |
|
131 // ----------------------------------------------------------------------------- |
|
132 // CXnWidgetExtensionAdapter::MakeVisible |
|
133 // |
|
134 // ----------------------------------------------------------------------------- |
|
135 // |
|
136 void CXnWidgetExtensionAdapter::MakeVisible( TBool aVisible ) |
|
137 { |
|
138 |
|
139 TBool visible( IsVisible() ? ETrue : EFalse ); |
|
140 if ( visible == aVisible ) |
|
141 { |
|
142 return; |
|
143 } |
|
144 |
|
145 CXnPluginData& plugin( |
|
146 iAppUiAdapter->ViewManager().ActiveViewData().Plugin( &iNode.Node() ) ); |
|
147 |
|
148 plugin.SetIsDisplayingPopup( aVisible, &iNode.Node() ); |
|
149 |
|
150 if ( aVisible ) |
|
151 { |
|
152 |
|
153 CXnType* typeInfo = iNode.Node().Type(); |
|
154 const TDesC8& type = typeInfo->Type(); |
|
155 |
|
156 if ( type == KPopUpText ) |
|
157 { |
|
158 // read position-hint property and set-up its variable |
|
159 CXnProperty* positionHintProp = NULL; |
|
160 TRAP_IGNORE( positionHintProp = iNode.Node().GetPropertyL( KPositionHint ) ); |
|
161 |
|
162 if ( positionHintProp ) |
|
163 { |
|
164 const TDesC8& displayHintVal = positionHintProp->StringValue(); |
|
165 |
|
166 if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KAboveLeft ) |
|
167 { |
|
168 iPositionHint = EAboveLeft; |
|
169 } |
|
170 else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KAboveRight ) |
|
171 { |
|
172 iPositionHint = EAboveRight; |
|
173 } |
|
174 else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KBelowLeft ) |
|
175 { |
|
176 iPositionHint = EBelowLeft; |
|
177 } |
|
178 else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KBelowRight ) |
|
179 { |
|
180 iPositionHint = EBelowRight; |
|
181 } |
|
182 else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KRight ) |
|
183 { |
|
184 iPositionHint = ERight; |
|
185 } |
|
186 else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KLeft ) |
|
187 { |
|
188 iPositionHint = ELeft; |
|
189 } |
|
190 else |
|
191 { |
|
192 // if the value if of unknown type, use default one |
|
193 if ( AknLayoutUtils::LayoutMirrored() ) |
|
194 { |
|
195 iPositionHint = EAboveRight; |
|
196 } |
|
197 else |
|
198 { |
|
199 iPositionHint = EAboveLeft; |
|
200 } |
|
201 } |
|
202 |
|
203 if ( iPositionHint != ENone ) |
|
204 { |
|
205 // the popup is going visible and position-hind is available |
|
206 // calculate its position |
|
207 CalculatePosition(); |
|
208 } |
|
209 } |
|
210 } |
|
211 DrawableWindow()->FadeBehind( ETrue ); |
|
212 } |
|
213 else |
|
214 { |
|
215 DrawableWindow()->FadeBehind( EFalse ); |
|
216 } |
|
217 CCoeControl::MakeVisible( aVisible ); |
|
218 } |
|
219 |
|
220 // ----------------------------------------------------------------------------- |
|
221 // CXnWidgetExtensionAdapter::HandlePointerEventL |
|
222 // |
|
223 // ----------------------------------------------------------------------------- |
|
224 // |
|
225 void CXnWidgetExtensionAdapter::HandlePointerEventL( |
|
226 const TPointerEvent& aPointerEvent ) |
|
227 { |
|
228 |
|
229 CXnType* typeInfo = iNode.Node().Type(); |
|
230 const TDesC8& type = typeInfo->Type(); |
|
231 |
|
232 // in case of popup, we have to make sure that |
|
233 // it will be closed after tapping outside of the |
|
234 // area of itself and its parent |
|
235 if ( type == KPopUpText ) |
|
236 { |
|
237 |
|
238 // check if the tap was inside of popup |
|
239 TRect popupRect = this->Rect(); |
|
240 popupRect.Move(this->Position() ); |
|
241 TBool isInPopupWindow = popupRect.Contains( |
|
242 aPointerEvent.iParentPosition ); |
|
243 |
|
244 if ( !isInPopupWindow ) |
|
245 { |
|
246 |
|
247 // if tap was outside of window, check if tap was |
|
248 // inside of the parrent |
|
249 CXnProperty* parentIdProp = iNode.Node().GetPropertyL( |
|
250 KParentIdName ); |
|
251 |
|
252 if ( parentIdProp ) |
|
253 { |
|
254 const TDesC8& parentIdVal = parentIdProp->StringValue(); |
|
255 CXnNode* parentN(iUiEngine->FindNodeByIdL( parentIdVal, |
|
256 iNode.Node().Namespace() ) ); |
|
257 |
|
258 TRect clientRect = |
|
259 static_cast<CEikAppUi&> ( *iAppUiAdapter ).ClientRect(); |
|
260 TRect parentRect = parentN->Rect(); |
|
261 parentRect.Move( clientRect.iTl ); |
|
262 |
|
263 if ( !parentRect.Contains( aPointerEvent.iParentPosition ) ) |
|
264 { |
|
265 // tap was neither in popup nor in its parent - |
|
266 // we can close it |
|
267 if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) |
|
268 { |
|
269 CXnDomStringPool& sp = |
|
270 iNode.Node().DomNode()->StringPool(); |
|
271 CXnProperty* prop = CXnProperty::NewL( KDisplay, KNone, |
|
272 CXnDomPropertyValue::EString, sp ); |
|
273 CleanupStack::PushL( prop ); |
|
274 iNode.Node().SetPropertyL( prop ); |
|
275 CleanupStack::Pop( prop ); |
|
276 return; |
|
277 } |
|
278 } |
|
279 else |
|
280 { |
|
281 // tap was made inside of popup parent |
|
282 // we pass the event to it after |
|
283 // recalculating the taping point |
|
284 TPointerEvent newPointerEvent; |
|
285 newPointerEvent.Copy( aPointerEvent ); |
|
286 newPointerEvent.iPosition = TPoint( |
|
287 aPointerEvent.iParentPosition - clientRect.iTl ); |
|
288 parentN->Control()->HandlePointerEventL( newPointerEvent ); |
|
289 return; |
|
290 } |
|
291 } |
|
292 } |
|
293 } |
|
294 |
|
295 CXnControlAdapter::HandlePointerEventL( aPointerEvent ); |
|
296 |
|
297 } |
|
298 |
|
299 // ----------------------------------------------------------------------------- |
|
300 // CXnWidgetExtensionAdapter::Draw |
|
301 // |
|
302 // ----------------------------------------------------------------------------- |
|
303 // |
|
304 void CXnWidgetExtensionAdapter::Draw( const TRect& aRect ) const |
|
305 { |
|
306 CXnControlAdapter::Draw( aRect ); |
|
307 } |
|
308 |
|
309 // ----------------------------------------------------------------------------- |
|
310 // CalculatePosition |
|
311 // This is used only for popup element with position hint |
|
312 // ----------------------------------------------------------------------------- |
|
313 void CXnWidgetExtensionAdapter::CalculatePosition() |
|
314 { |
|
315 |
|
316 // widget's rectangle |
|
317 TRect controlRect; |
|
318 |
|
319 // get popup's window size |
|
320 TRect popupRect = this->Rect(); |
|
321 |
|
322 TRect clientRect = static_cast<CEikAppUi&>( *iAppUiAdapter ).ClientRect(); |
|
323 |
|
324 // get entire screen except control pane |
|
325 TRect contentRect( 0, 0, clientRect.iBr.iX, clientRect.iBr.iY ); |
|
326 |
|
327 // resulting rectangle |
|
328 TRect rect; |
|
329 |
|
330 TPoint offset( clientRect.iTl ); |
|
331 |
|
332 // parent widget's rectangle ( first predecesscor which is "widget" ) |
|
333 CXnNode* parent = iNode.Node().Parent(); |
|
334 |
|
335 while ( parent ) |
|
336 { |
|
337 const TDesC8& type( parent->DomNode()->Name() ); |
|
338 if ( type == KWidgetNodeName ) |
|
339 { |
|
340 break; |
|
341 } |
|
342 parent = parent->Parent(); |
|
343 } |
|
344 |
|
345 // if predecesscor widget was not found, use parent's rectangle |
|
346 if ( parent == NULL ) |
|
347 { |
|
348 controlRect = iNode.Node().Parent()->Rect(); |
|
349 } |
|
350 else |
|
351 { |
|
352 controlRect = parent->BorderRect(); |
|
353 } |
|
354 |
|
355 // calculate available space for placing the popup |
|
356 TInt spaceAbove = controlRect.iTl.iY + offset.iY; |
|
357 TInt spaceBelow = contentRect.iBr.iY - controlRect.iBr.iY - offset.iY; |
|
358 TInt spaceLeft = controlRect.iTl.iX + offset.iX; |
|
359 TInt spaceRight = contentRect.iBr.iX - controlRect.iBr.iX - offset.iX; |
|
360 |
|
361 switch ( iPositionHint ) |
|
362 { |
|
363 |
|
364 case EAboveLeft: |
|
365 |
|
366 // if this position does not fit the screen, |
|
367 // and if below left is more suitable, use it |
|
368 if ( spaceAbove < popupRect.Height() && spaceBelow > spaceAbove ) |
|
369 { |
|
370 rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iBr.iY ), |
|
371 TPoint( controlRect.iTl.iX + popupRect.Width(), controlRect.iBr.iY + popupRect.Height() ) ); |
|
372 } |
|
373 else |
|
374 { |
|
375 // use the above-left position |
|
376 rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iTl.iY - popupRect.Height() ), |
|
377 TPoint( controlRect.iTl.iX + popupRect.Width(), controlRect.iTl.iY ) ); |
|
378 |
|
379 } |
|
380 break; |
|
381 |
|
382 case EAboveRight: |
|
383 |
|
384 // if this position does not fit the screen, |
|
385 // and if below right is more suitable, use it |
|
386 if ( spaceAbove < popupRect.Height() && spaceBelow > spaceAbove ) |
|
387 { |
|
388 rect = TRect( TPoint( controlRect.iBr.iX - popupRect.Width(), controlRect.iBr.iY ), |
|
389 TPoint( controlRect.iBr.iX, controlRect.iBr.iY + popupRect.Height() ) ); |
|
390 } |
|
391 else |
|
392 { |
|
393 // use the above-right position |
|
394 rect = TRect( TPoint( controlRect.iBr.iX - popupRect.Width(), controlRect.iTl.iY - popupRect.Height() ), |
|
395 TPoint( controlRect.iBr.iX, controlRect.iTl.iY ) ); |
|
396 } |
|
397 break; |
|
398 |
|
399 case EBelowLeft: |
|
400 |
|
401 // if this position does not fit the screen, |
|
402 // and if above left is more suitable, use it |
|
403 if ( spaceBelow < popupRect.Height() && spaceBelow < spaceAbove ) |
|
404 { |
|
405 rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iTl.iY - popupRect.Height() ), |
|
406 TPoint( controlRect.iTl.iX + popupRect.Width(), controlRect.iTl.iY ) ); |
|
407 } |
|
408 else |
|
409 { |
|
410 // use the below-left position |
|
411 rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iBr.iY ), |
|
412 TPoint( controlRect.iTl.iX + popupRect.Width(), controlRect.iBr.iY + popupRect.Height() ) ); |
|
413 } |
|
414 break; |
|
415 |
|
416 case EBelowRight: |
|
417 |
|
418 // if this position does not fit the screen, |
|
419 // and if above right is more suitable, use it |
|
420 if ( spaceBelow < popupRect.Height() && spaceBelow < spaceAbove ) |
|
421 { |
|
422 rect = TRect( TPoint( controlRect.iBr.iX - popupRect.Width(), controlRect.iTl.iY - popupRect.Height() ), |
|
423 TPoint( controlRect.iBr.iX, controlRect.iTl.iY ) ); |
|
424 } |
|
425 else |
|
426 { |
|
427 // use the below-right position |
|
428 rect = TRect( TPoint( controlRect.iBr.iX - popupRect.Width(), controlRect.iBr.iY ), |
|
429 TPoint( controlRect.iBr.iX, controlRect.iBr.iY + popupRect.Height() ) ); |
|
430 } |
|
431 break; |
|
432 |
|
433 case ERight: |
|
434 |
|
435 // if this position does not fit the screen, |
|
436 // and if left or above-left is more suitable, use it |
|
437 if ( spaceRight < popupRect.Width() ) |
|
438 { |
|
439 // use the left position if the space is big enough |
|
440 if ( spaceLeft >= popupRect.Width() ) |
|
441 { |
|
442 // use left position |
|
443 rect = TRect( TPoint( controlRect.iTl.iX - popupRect.Width(), controlRect.iTl.iY ), |
|
444 TPoint( controlRect.iTl.iX, controlRect.iTl.iY + popupRect.Height() ) ); |
|
445 } |
|
446 else if ( spaceAbove >= popupRect.Height() ) |
|
447 { |
|
448 // use the above-right position |
|
449 rect = TRect( TPoint( controlRect.iBr.iX - popupRect.Width(), controlRect.iTl.iY - popupRect.Height() ), |
|
450 TPoint( controlRect.iBr.iX, controlRect.iTl.iY ) ); |
|
451 } |
|
452 else |
|
453 { |
|
454 // use the below-right position |
|
455 rect = TRect( TPoint( controlRect.iBr.iX - popupRect.Width(), controlRect.iBr.iY ), |
|
456 TPoint( controlRect.iBr.iX, controlRect.iBr.iY + popupRect.Height() ) ); |
|
457 } |
|
458 } |
|
459 else |
|
460 { |
|
461 // use the right position |
|
462 rect = TRect( TPoint( controlRect.iBr.iX, controlRect.iTl.iY ), |
|
463 TPoint( controlRect.iBr.iX + popupRect.Width(), controlRect.iTl.iY + popupRect.Height() ) ); |
|
464 } |
|
465 |
|
466 break; |
|
467 |
|
468 case ELeft: |
|
469 |
|
470 // if this position does not fit the screen, |
|
471 // and if right is more suitable, use it |
|
472 if ( spaceLeft < popupRect.Width() ) |
|
473 { |
|
474 // use the right position, if it the space is big enough |
|
475 if ( spaceRight >= popupRect.Width() ) |
|
476 { |
|
477 rect = TRect( TPoint( controlRect.iBr.iX, controlRect.iTl.iY ), |
|
478 TPoint( controlRect.iBr.iX + popupRect.Width(), controlRect.iTl.iY + popupRect.Height() ) ); |
|
479 } |
|
480 else if ( spaceAbove >= popupRect.Height() ) |
|
481 { |
|
482 // use the above-left position |
|
483 rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iTl.iY - popupRect.Height() ), |
|
484 TPoint( controlRect.iTl.iX + popupRect.Width(), controlRect.iTl.iY ) ); |
|
485 } |
|
486 else |
|
487 { |
|
488 // use the below-left position |
|
489 rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iBr.iY ), |
|
490 TPoint( controlRect.iTl.iX + popupRect.Width(), controlRect.iBr.iY + popupRect.Height() ) ); |
|
491 } |
|
492 } |
|
493 else |
|
494 { |
|
495 // use the left position |
|
496 rect = TRect( TPoint( controlRect.iTl.iX - popupRect.Width(), controlRect.iTl.iY ), |
|
497 TPoint( controlRect.iTl.iX, controlRect.iTl.iY + popupRect.Height() ) ); |
|
498 } |
|
499 break; |
|
500 default: |
|
501 break; |
|
502 } |
|
503 |
|
504 rect.Move( offset ); |
|
505 |
|
506 // if the popup rectangle exceeds the borders of content rectangle, move it. |
|
507 if ( rect.iTl.iY < contentRect.iTl.iY ) |
|
508 { |
|
509 rect.Move( 0, contentRect.iTl.iY - rect.iTl.iY ); |
|
510 } |
|
511 if ( rect.iTl.iX < contentRect.iTl.iX ) |
|
512 { |
|
513 rect.Move( contentRect.iTl.iX - rect.iTl.iX, 0 ); |
|
514 } |
|
515 if ( rect.iBr.iY > contentRect.iBr.iY ) |
|
516 { |
|
517 rect.Move( 0, contentRect.iBr.iY - rect.iBr.iY ); |
|
518 } |
|
519 if ( rect.iBr.iX > contentRect.iBr.iX ) |
|
520 { |
|
521 rect.Move( contentRect.iBr.iX - rect.iBr.iX, 0 ); |
|
522 } |
|
523 this->SetRect( rect ); |
|
524 } |
|
525 |
|
526 // End of File |