|
1 /* |
|
2 * Copyright (c) 2010 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 * Description: Easy dialing list box. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 |
|
21 #include "easydialinglistbox.h" |
|
22 #include "easydialinglistboxview.h" |
|
23 #include "easydialinglistboxitemdrawer.h" |
|
24 #include "easydialinglistboxdata.h" |
|
25 #include "easydialingpanics.h" |
|
26 #include "easydialingcontactdatamanager.h" |
|
27 #include "easydialingcrkeys.h" |
|
28 |
|
29 #include <easydialingpluginresources.rsg> |
|
30 |
|
31 #include <phoneappcommands.hrh> |
|
32 #include <phonebook2.mbg> |
|
33 #include <phonebook2ece.mbg> |
|
34 |
|
35 #include <ccappcommlauncherpluginrsc.rsg> |
|
36 |
|
37 // AvKON and drawing header files |
|
38 |
|
39 #include <aknpointereventsuppressor.h> |
|
40 #include <aknlongtapdetector.h> // Required for touch |
|
41 #include <AknsFrameBackgroundControlContext.h> |
|
42 #include <AknInfoPopupNoteController.h> // tooltips |
|
43 |
|
44 #include <aknlayoutscalable_apps.cdl.h> |
|
45 #include <layoutmetadata.cdl.h> |
|
46 #include <gulicon.h> |
|
47 #include <centralrepository.h> |
|
48 #include <bautils.h> // for BaflUtils |
|
49 |
|
50 #include <aknlistloadertfx.h> |
|
51 #include <aknlistboxtfxinternal.h> |
|
52 #include <aknlistboxtfx.h> |
|
53 |
|
54 // EXTERNAL DATA STRUCTURES |
|
55 |
|
56 // EXTERNAL FUNCTION PROTOTYPES |
|
57 |
|
58 extern TRect ContactImageBoundingBox( const TRect& aItemRect ); |
|
59 extern TRect ActionMenuIconBoundingBox(const TRect& aItemRect); |
|
60 |
|
61 // CONSTANTS |
|
62 static const TInt KListBoxMarginWidth = 2; |
|
63 static const TInt KMaxVisibleItemsPortrait = 3; |
|
64 static const TInt KMaxVisibleItemsLandscape = 2; |
|
65 |
|
66 // MACROS |
|
67 |
|
68 // LOCAL CONSTANTS AND MACROS |
|
69 |
|
70 // MODULE DATA STRUCTURES |
|
71 |
|
72 // LOCAL FUNCTION PROTOTYPES |
|
73 |
|
74 // FORWARD DECLARATIONS |
|
75 |
|
76 |
|
77 /* |
|
78 * ============================================================================== |
|
79 * |
|
80 * |
|
81 * class CEasyDialingListBox |
|
82 * |
|
83 * |
|
84 * ============================================================================== |
|
85 */ |
|
86 |
|
87 |
|
88 // ----------------------------------------------------------------------------- |
|
89 // CEasyDialingListBox |
|
90 // |
|
91 // ----------------------------------------------------------------------------- |
|
92 // |
|
93 CEasyDialingListBox::CEasyDialingListBox() : |
|
94 CEikFormattedCellListBox() |
|
95 { |
|
96 } |
|
97 |
|
98 // ----------------------------------------------------------------------------- |
|
99 // ~CEasyDialingListBox |
|
100 // |
|
101 // ----------------------------------------------------------------------------- |
|
102 // |
|
103 CEasyDialingListBox::~CEasyDialingListBox() |
|
104 { |
|
105 delete iBGContext; |
|
106 delete iLongTapDetector; |
|
107 } |
|
108 |
|
109 // ----------------------------------------------------------------------------- |
|
110 // ConstructL |
|
111 // |
|
112 // ----------------------------------------------------------------------------- |
|
113 // |
|
114 void CEasyDialingListBox::ConstructL( TInt aFlags, |
|
115 CEasyDialingContactDataManager* aContactDataManager ) |
|
116 { |
|
117 CEikFormattedCellListBox::ConstructL( NULL, aFlags ); |
|
118 |
|
119 iLongTapDetector = CAknLongTapDetector::NewL( this ); |
|
120 |
|
121 CEasyDialingListBoxItemDrawer* drawer = static_cast<CEasyDialingListBoxItemDrawer*> (iItemDrawer); |
|
122 CEasyDialingListBoxData* data = drawer->EasyDialingCellData(); |
|
123 data->SetContactDataManager(aContactDataManager); |
|
124 data->SetEDLBXControl(this); |
|
125 |
|
126 iBGContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrPopupSub, |
|
127 Rect(), Rect(), EFalse ); |
|
128 |
|
129 // ContactDataManager is accessed from SizeChanged. If list item size |
|
130 // changes -> thumbnail size changes |
|
131 iContactDataManager = aContactDataManager; |
|
132 |
|
133 drawer->SetColors(); |
|
134 |
|
135 CreateScrollBarFrameL( ETrue ); |
|
136 ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto ); |
|
137 } |
|
138 |
|
139 |
|
140 // ----------------------------------------------------------------------------- |
|
141 // MakeViewClassInstanceL |
|
142 // |
|
143 // ----------------------------------------------------------------------------- |
|
144 // |
|
145 CListBoxView* CEasyDialingListBox::MakeViewClassInstanceL() |
|
146 { |
|
147 return (new ( ELeave ) CEasyDialingListBoxView); |
|
148 } |
|
149 |
|
150 |
|
151 // ----------------------------------------------------------------------------- |
|
152 // ItemDrawer |
|
153 // |
|
154 // ----------------------------------------------------------------------------- |
|
155 // |
|
156 CEasyDialingListBoxItemDrawer* CEasyDialingListBox::ItemDrawer() const |
|
157 { |
|
158 return (CEasyDialingListBoxItemDrawer*) iItemDrawer; |
|
159 } |
|
160 |
|
161 |
|
162 // ----------------------------------------------------------------------------- |
|
163 // FocusChanged |
|
164 // |
|
165 // ----------------------------------------------------------------------------- |
|
166 // |
|
167 void CEasyDialingListBox::FocusChanged( TDrawNow aDrawNow ) |
|
168 { |
|
169 if ( !IsFocused() ) |
|
170 { |
|
171 CEasyDialingListBoxView* view = static_cast<CEasyDialingListBoxView*>( iView ); |
|
172 view->SetCurrentItemIndexToNone(); |
|
173 |
|
174 // Invalidate window area. |
|
175 // This fixes the drawing problem that the top |
|
176 // of listbox is not always redrawn on the area that overlaps |
|
177 // the status pane area. |
|
178 // TODO: This overlapping no longer happens in 9.2 so this may |
|
179 // now be unnecessary. |
|
180 Window().Invalidate(); |
|
181 } |
|
182 CEikFormattedCellListBox::FocusChanged( aDrawNow ); |
|
183 } |
|
184 |
|
185 |
|
186 // ----------------------------------------------------------------------------- |
|
187 // CreateItemDrawerL |
|
188 // |
|
189 // ----------------------------------------------------------------------------- |
|
190 // |
|
191 void CEasyDialingListBox::CreateItemDrawerL() |
|
192 { |
|
193 CEasyDialingListBoxData* celldata = CEasyDialingListBoxData::NewL(); |
|
194 CleanupStack::PushL( celldata ); |
|
195 iItemDrawer = new(ELeave) CEasyDialingListBoxItemDrawer(Model(), iEikonEnv->NormalFont(), celldata); |
|
196 CleanupStack::Pop( celldata ); |
|
197 } |
|
198 |
|
199 |
|
200 // ----------------------------------------------------------------------------- |
|
201 // Draw |
|
202 // |
|
203 // ----------------------------------------------------------------------------- |
|
204 // |
|
205 void CEasyDialingListBox::Draw(const TRect& aRect) const |
|
206 { |
|
207 MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( iItemDrawer->Gc() ); |
|
208 if ( transApi ) |
|
209 { |
|
210 transApi->SetListType( MAknListBoxTfxInternal::EListBoxTypeMainPane ); |
|
211 transApi->BeginRedraw( MAknListBoxTfxInternal::EListView, this->Rect() ); |
|
212 } |
|
213 |
|
214 if (!iView->RedrawDisabled() ) |
|
215 { |
|
216 TRect clientRect( Rect() ); |
|
217 TRect viewRect = iView->ViewRect(); |
|
218 |
|
219 if ( transApi ) |
|
220 { |
|
221 transApi->StartDrawing( MAknListBoxTfxInternal::EListView ); |
|
222 } |
|
223 |
|
224 AknsDrawUtils::BackgroundBetweenRects( |
|
225 AknsUtils::SkinInstance(), |
|
226 iBGContext, |
|
227 this, |
|
228 *iItemDrawer->Gc(), |
|
229 clientRect, |
|
230 viewRect ); |
|
231 |
|
232 if ( transApi ) |
|
233 { |
|
234 transApi->StopDrawing(); |
|
235 } |
|
236 } |
|
237 |
|
238 if ( iModel->NumberOfItems() ) |
|
239 { |
|
240 // Draw the actual list |
|
241 iView->Draw(&aRect); |
|
242 } |
|
243 if ( transApi ) |
|
244 { |
|
245 transApi->EndViewRedraw( aRect ); |
|
246 } |
|
247 } |
|
248 |
|
249 |
|
250 // ----------------------------------------------------------------------------- |
|
251 // HandleResourceChange |
|
252 // |
|
253 // ----------------------------------------------------------------------------- |
|
254 // |
|
255 void CEasyDialingListBox::HandleResourceChange(TInt aType) |
|
256 { |
|
257 CEikFormattedCellListBox::HandleResourceChange( aType ); |
|
258 iSBFrame->VerticalScrollBar()->HandleResourceChange( aType ); |
|
259 iSBFrame->DrawScrollBarsNow(); |
|
260 ItemDrawer()->SetColors(); |
|
261 |
|
262 // Base call to HandleResourceChange justifies the list to even items |
|
263 // on the top. This causes problems when listbox height is not a multiple of |
|
264 // listitem heights. Fix scrolling manually for these cases. |
|
265 TRAP_IGNORE( HandleItemAdditionL() ); // needed to prevent drawing problems |
|
266 TInt scrollIndex = ( IsFocused() ? CurrentItemIndex() : iNumberOfNames - 1 ); |
|
267 ScrollToMakeItemVisible( scrollIndex ); |
|
268 |
|
269 DrawDeferred(); |
|
270 } |
|
271 |
|
272 |
|
273 // ----------------------------------------------------------------------------- |
|
274 // SizeChanged |
|
275 // |
|
276 // ----------------------------------------------------------------------------- |
|
277 // |
|
278 void CEasyDialingListBox::SizeChanged() |
|
279 { |
|
280 CEikFormattedCellListBox::SizeChanged(); |
|
281 |
|
282 // Set the listbox colors. |
|
283 // For some reason, calling this in HandleResourceChange is not enough, it does |
|
284 // not get called in situation it should. |
|
285 ItemDrawer()->SetColors(); |
|
286 |
|
287 // resize scroll bar |
|
288 if ( iSBFrame ) |
|
289 { |
|
290 TAknLayoutRect rect; |
|
291 TInt variety = ( Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0 ); |
|
292 |
|
293 TAknWindowComponentLayout viewLayout( AknLayoutScalable_Apps::dia3_list_pane( variety ) ); |
|
294 rect.LayoutRect( Rect(), viewLayout ); |
|
295 TRect viewRect( rect.Rect() ); |
|
296 // Add a bit of margin around the view as layout doesn't define any |
|
297 viewRect.Shrink( KListBoxMarginWidth, KListBoxMarginWidth ); |
|
298 |
|
299 TAknWindowComponentLayout scrollBarLayout( AknLayoutScalable_Apps::scroll_pane_cp12() ); |
|
300 rect.LayoutRect( Rect(), scrollBarLayout ); |
|
301 TRect scrollBarRect( rect.Rect() ); |
|
302 |
|
303 iView->SetViewRect( viewRect ); |
|
304 |
|
305 CAknDoubleSpanScrollBar* scrollbar = static_cast <CAknDoubleSpanScrollBar*>( iSBFrame->VerticalScrollBar() ); |
|
306 |
|
307 scrollbar->SetFixedLayoutRect( scrollBarRect ); |
|
308 scrollbar->SetRect( scrollBarRect ); |
|
309 |
|
310 TRect viewAndScrollBarRect( viewRect ); |
|
311 |
|
312 if ( AknLayoutUtils::LayoutMirrored() ) |
|
313 { |
|
314 viewAndScrollBarRect.iTl = scrollBarRect.iTl; |
|
315 } |
|
316 else |
|
317 { |
|
318 viewAndScrollBarRect.iBr = scrollBarRect.iBr; |
|
319 } |
|
320 iBGContext->SetFrameRects( Rect(), viewAndScrollBarRect ); |
|
321 } |
|
322 } |
|
323 |
|
324 |
|
325 // ----------------------------------------------------------------------------- |
|
326 // MopSupplyObject |
|
327 // |
|
328 // ----------------------------------------------------------------------------- |
|
329 // |
|
330 TTypeUid::Ptr CEasyDialingListBox::MopSupplyObject( TTypeUid aId ) |
|
331 { |
|
332 if ( aId.iUid == MAknsControlContext::ETypeId && iBGContext ) |
|
333 { |
|
334 return MAknsControlContext::SupplyMopObject( aId, iBGContext ); |
|
335 } |
|
336 return CEikFormattedCellListBox::MopSupplyObject( aId ); |
|
337 } |
|
338 |
|
339 // ----------------------------------------------------------------------------- |
|
340 // MakeVisible |
|
341 // |
|
342 // ----------------------------------------------------------------------------- |
|
343 // |
|
344 void CEasyDialingListBox::MakeVisible( TBool aVisible ) |
|
345 { |
|
346 if ( aVisible != IsVisible() ) |
|
347 { |
|
348 CEikFormattedCellListBox::MakeVisible( aVisible ); |
|
349 if ( iSBFrame ) |
|
350 { |
|
351 CEikScrollBar* sb = iSBFrame->GetScrollBarHandle( CEikScrollBar::EVertical ); |
|
352 if ( sb ) |
|
353 { |
|
354 sb->MakeVisible( aVisible ); |
|
355 if ( aVisible ) |
|
356 { |
|
357 UpdateScrollBarThumbs(); |
|
358 } |
|
359 } |
|
360 } |
|
361 } |
|
362 } |
|
363 |
|
364 // ----------------------------------------------------------------------------- |
|
365 // SetMaxRect |
|
366 // |
|
367 // ----------------------------------------------------------------------------- |
|
368 // |
|
369 void CEasyDialingListBox::SetMaxRect( TRect aMaxRect ) |
|
370 { |
|
371 iMaxRect = aMaxRect; |
|
372 |
|
373 // Update the list item size according the maximum view rect size |
|
374 TInt variety = ( Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0 ); |
|
375 TAknLayoutRect maxViewLayout; |
|
376 maxViewLayout.LayoutRect( aMaxRect, AknLayoutScalable_Apps::dia3_list_pane( variety ) ); |
|
377 TRect maxViewRect( maxViewLayout.Rect() ); |
|
378 maxViewRect.Shrink( KListBoxMarginWidth, KListBoxMarginWidth ); // layout data doens't include any margins but we have added some |
|
379 |
|
380 TInt maxItemsShown = ( variety ? KMaxVisibleItemsLandscape : KMaxVisibleItemsPortrait ); |
|
381 TInt itemHeight = maxViewRect.Height() / maxItemsShown; |
|
382 TRAP_IGNORE( SetItemHeightL( itemHeight ) ); |
|
383 |
|
384 // Calculate new thumbnail rect from item size |
|
385 TSize itemSize( maxViewRect.Width(), itemHeight ); |
|
386 TRect thumbnailRect = ContactImageBoundingBox( itemSize ); |
|
387 iContactDataManager->SetThumbnailSize( thumbnailRect.Size() ); // reloads thumbnails if the new size is different from old one |
|
388 |
|
389 // Inform listbox data class about changed list item size |
|
390 ItemDrawer()->EasyDialingCellData()->HandleItemSizeChange(); |
|
391 } |
|
392 |
|
393 // ----------------------------------------------------------------------------- |
|
394 // SetRectToNumberOfItems |
|
395 // ----------------------------------------------------------------------------- |
|
396 // |
|
397 void CEasyDialingListBox::SetRectToNumberOfItems( TInt aNumberOfNames ) |
|
398 { |
|
399 iNumberOfNames = aNumberOfNames; |
|
400 |
|
401 TRect listboxRect( iMaxRect ); |
|
402 |
|
403 // Make listbox smaller if maximum size is not needed to show |
|
404 // all list items. |
|
405 TInt requiredHeight = GetHeightBasedOnNumberOfItems( iNumberOfNames ); |
|
406 if ( requiredHeight < listboxRect.Height() ) |
|
407 { |
|
408 // Shrink rect height so that bottom of the rect doesn't move |
|
409 listboxRect.iTl.iY += ( listboxRect.Height() - requiredHeight ); |
|
410 } |
|
411 |
|
412 SetRect( listboxRect ); |
|
413 } |
|
414 |
|
415 |
|
416 |
|
417 // ----------------------------------------------------------------------------- |
|
418 // SetFocusedWithKeyEventL |
|
419 // ----------------------------------------------------------------------------- |
|
420 // |
|
421 TKeyResponse CEasyDialingListBox::SetFocusedWithKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType ) |
|
422 { |
|
423 TKeyResponse keyResponse = EKeyWasNotConsumed; |
|
424 TInt keyCode = aKeyEvent.iCode; |
|
425 |
|
426 // Disable redrawing temporarily. |
|
427 // This is because OfferKeyEventL puts the focus to the wrong item, |
|
428 // and we don't want to show it flashing there. |
|
429 // Make sure that no leave happens before redraw is enabled again. |
|
430 iView->SetDisableRedraw( ETrue ); |
|
431 |
|
432 TRAP_IGNORE( keyResponse = OfferKeyEventL( aKeyEvent, aType ) ); |
|
433 |
|
434 TInt itemToFocus = ( keyCode == EKeyUpArrow ? iNumberOfNames - 1 : 0 ); |
|
435 ScrollToMakeItemVisible( itemToFocus ); |
|
436 SetCurrentItemIndex( itemToFocus ); |
|
437 |
|
438 iView->SetDisableRedraw( EFalse ); |
|
439 |
|
440 DrawDeferred(); |
|
441 |
|
442 return keyResponse; |
|
443 } |
|
444 |
|
445 |
|
446 // ----------------------------------------------------------------------------- |
|
447 // GetHeightBasedOnNumberOfItems |
|
448 // |
|
449 // ----------------------------------------------------------------------------- |
|
450 // |
|
451 TInt CEasyDialingListBox::GetHeightBasedOnNumberOfItems( TInt aNum ) const |
|
452 { |
|
453 return ( ItemHeight()*aNum + KListBoxMarginWidth*2 ); |
|
454 } |
|
455 |
|
456 |
|
457 // ----------------------------------------------------------------------------- |
|
458 // CurrentContactDataIndex |
|
459 // |
|
460 // ----------------------------------------------------------------------------- |
|
461 // |
|
462 TInt CEasyDialingListBox::CurrentContactDataIndex() |
|
463 { |
|
464 if ( CurrentItemIndex() >= 0 ) |
|
465 { |
|
466 TPtrC itemText = Model()->ItemText( CurrentItemIndex() ); |
|
467 TPtrC indexText; |
|
468 |
|
469 TInt error = TextUtils::ColumnText( indexText , 0, &itemText ); |
|
470 __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) ); |
|
471 |
|
472 TUint id( 0 ); |
|
473 TLex lex( indexText ); |
|
474 error = lex.Val( id, EHex ); |
|
475 __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) ); |
|
476 |
|
477 return id; |
|
478 } |
|
479 else |
|
480 { |
|
481 return KErrNotFound; |
|
482 } |
|
483 } |
|
484 |
|
485 // ----------------------------------------------------------------------------- |
|
486 // CurrentContactLinkLC |
|
487 // |
|
488 // ----------------------------------------------------------------------------- |
|
489 // |
|
490 HBufC8* CEasyDialingListBox::CurrentContactLinkLC() |
|
491 { |
|
492 TInt index = CurrentContactDataIndex(); |
|
493 return iContactDataManager->ContactLinkLC( index ); |
|
494 } |
|
495 |
|
496 |
|
497 // ----------------------------------------------------------------------------- |
|
498 // HandleLongTapEventL |
|
499 // Callback from CAknLongTapDetector. |
|
500 // ----------------------------------------------------------------------------- |
|
501 // |
|
502 void CEasyDialingListBox::HandleLongTapEventL( const TPoint& /*aPenEventLocation*/, |
|
503 const TPoint& /*aPenEventScreenLocation*/ ) |
|
504 { |
|
505 ReportListBoxEventL( static_cast<MEikListBoxObserver::TListBoxEvent> |
|
506 ( KEasyDialingContactLongTapped ) ); |
|
507 iPointerLongPressHandled = ETrue; |
|
508 } |
|
509 |
|
510 |
|
511 // ----------------------------------------------------------------------------- |
|
512 // HandlePointerEventL |
|
513 // Pointer event handling within the EasyDialingListBox. |
|
514 // ----------------------------------------------------------------------------- |
|
515 // |
|
516 void CEasyDialingListBox::HandlePointerEventL(const TPointerEvent& aPointerEvent) |
|
517 { |
|
518 // Button down event starts new pointer press. Reset flags at this point. |
|
519 if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) |
|
520 { |
|
521 iPointerLongPressHandled = EFalse; |
|
522 } |
|
523 |
|
524 iLongTapDetector->PointerEventL(aPointerEvent); |
|
525 if ( iPointerLongPressHandled ) |
|
526 { |
|
527 // No further handling is made after long tap on list item |
|
528 // has been detected. |
|
529 return; |
|
530 } |
|
531 |
|
532 CEikFormattedCellListBox::HandlePointerEventL( aPointerEvent ); |
|
533 } |
|
534 |
|
535 |
|
536 // end of file |
|
537 |