|
1 /* |
|
2 * Copyright (c) 2008-2009 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: Base class for AppMngr2 list view containers |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "appmngr2listcontainer.h" // CAppMngr2ListContainer |
|
20 #include "appmngr2appui.h" // CAppMngr2AppUi |
|
21 #include "appmngr2model.h" // CAppMngr2Model |
|
22 #include "appmngr2listview.h" // CAppMngr2ListView |
|
23 #include "appmngr2.hrh" // Icon IDs |
|
24 #include <appmngr2runtime.h> // CAppMngr2Runtime |
|
25 #include <appmngr2infobase.h> // CAppMngr2InfoBase |
|
26 #include <appmngr2debugutils.h> // FLOG macros |
|
27 #include <aknlists.h> // CAknDoubleLargeStyleListBox |
|
28 #include <eiktxlbm.h> // CTextListBoxModel |
|
29 #include <AknIconArray.h> // CAknIconArray |
|
30 #include <StringLoader.h> // StringLoader |
|
31 #include <gulicon.h> // CGulIcon |
|
32 |
|
33 const TInt KGranularity = 8; |
|
34 const TInt KSpaceForTabsAndIconIndexes = 9; // 3 tabs + 2 * 3 digits |
|
35 _LIT( KItemFormatFull, "%d\t%S\t%S\t%d" ); |
|
36 _LIT( KItemFormatNoInd, "%d\t%S\t%S" ); |
|
37 |
|
38 |
|
39 // ======== MEMBER FUNCTIONS ======== |
|
40 |
|
41 // --------------------------------------------------------------------------- |
|
42 // CAppMngr2ListContainer::CAppMngr2ListContainer() |
|
43 // --------------------------------------------------------------------------- |
|
44 // |
|
45 CAppMngr2ListContainer::CAppMngr2ListContainer( CAppMngr2ListView& aView ) |
|
46 : iView( aView ) |
|
47 { |
|
48 } |
|
49 |
|
50 // --------------------------------------------------------------------------- |
|
51 // CAppMngr2ListContainer::~CAppMngr2ListContainer() |
|
52 // --------------------------------------------------------------------------- |
|
53 // |
|
54 CAppMngr2ListContainer::~CAppMngr2ListContainer() |
|
55 { |
|
56 delete iListBox; |
|
57 delete iItemArray; |
|
58 } |
|
59 |
|
60 // --------------------------------------------------------------------------- |
|
61 // CAppMngr2ListContainer::OfferKeyEventL() |
|
62 // --------------------------------------------------------------------------- |
|
63 // |
|
64 TKeyResponse CAppMngr2ListContainer::OfferKeyEventL( |
|
65 const TKeyEvent& aKeyEvent, TEventCode aType ) |
|
66 { |
|
67 TKeyResponse response = iListBox->OfferKeyEventL( aKeyEvent, aType ); |
|
68 if( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow ) |
|
69 { |
|
70 iView.UpdateMiddleSoftkeyCommandL(); |
|
71 iView.CurrentItemSelectedByUser( ETrue ); |
|
72 } |
|
73 return response; |
|
74 } |
|
75 |
|
76 // --------------------------------------------------------------------------- |
|
77 // CAppMngr2ListContainer::HandleResourceChange() |
|
78 // --------------------------------------------------------------------------- |
|
79 // |
|
80 void CAppMngr2ListContainer::HandleResourceChange( TInt aType ) |
|
81 { |
|
82 CCoeControl::HandleResourceChange( aType ); |
|
83 |
|
84 if( aType == KAknsMessageSkinChange ) |
|
85 { |
|
86 TRAP_IGNORE( LoadIconsL() ); |
|
87 } |
|
88 |
|
89 if( aType == KEikDynamicLayoutVariantSwitch ) |
|
90 { |
|
91 TRect mainPaneRect; |
|
92 if( AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, |
|
93 mainPaneRect ) ) |
|
94 { |
|
95 SetRect( mainPaneRect ); |
|
96 } |
|
97 DrawDeferred(); |
|
98 } |
|
99 } |
|
100 |
|
101 // --------------------------------------------------------------------------- |
|
102 // CAppMngr2ListContainer::SizeChanged() |
|
103 // --------------------------------------------------------------------------- |
|
104 // |
|
105 void CAppMngr2ListContainer::SizeChanged() |
|
106 { |
|
107 if( iListBox ) |
|
108 { |
|
109 iListBox->SetRect( Rect() ); |
|
110 } |
|
111 } |
|
112 |
|
113 // --------------------------------------------------------------------------- |
|
114 // CAppMngr2ListContainer::CountComponentControls() |
|
115 // --------------------------------------------------------------------------- |
|
116 // |
|
117 TInt CAppMngr2ListContainer::CountComponentControls() const |
|
118 { |
|
119 return 1; // always only iListBox |
|
120 } |
|
121 |
|
122 // --------------------------------------------------------------------------- |
|
123 // CAppMngr2ListContainer::ComponentControl() |
|
124 // --------------------------------------------------------------------------- |
|
125 // |
|
126 CCoeControl* CAppMngr2ListContainer::ComponentControl( TInt /*aIndex*/ ) const |
|
127 { |
|
128 return iListBox; |
|
129 } |
|
130 |
|
131 // --------------------------------------------------------------------------- |
|
132 // CAppMngr2ListContainer::HandleListBoxEventL() |
|
133 // --------------------------------------------------------------------------- |
|
134 // |
|
135 void CAppMngr2ListContainer::HandleListBoxEventL( CEikListBox* /*aListBox*/, |
|
136 TListBoxEvent aEventType ) |
|
137 { |
|
138 if( aEventType == EEventItemClicked || aEventType == EEventItemSingleClicked ) |
|
139 { |
|
140 iView.UpdateMiddleSoftkeyCommandL(); |
|
141 iView.CurrentItemSelectedByUser( ETrue ); |
|
142 } |
|
143 } |
|
144 |
|
145 // --------------------------------------------------------------------------- |
|
146 // CAppMngr2ListContainer::IsListEmpty() |
|
147 // --------------------------------------------------------------------------- |
|
148 // |
|
149 TBool CAppMngr2ListContainer::IsListEmpty() const |
|
150 { |
|
151 if( iItemArray ) |
|
152 { |
|
153 return ( iItemArray->Count() == 0 ); |
|
154 } |
|
155 return ETrue; |
|
156 } |
|
157 |
|
158 // --------------------------------------------------------------------------- |
|
159 // CAppMngr2ListContainer::HandleGenericCommandL() |
|
160 // --------------------------------------------------------------------------- |
|
161 // |
|
162 void CAppMngr2ListContainer::HandleGenericCommandL( TInt aCommand ) |
|
163 { |
|
164 if( !IsListEmpty() ) |
|
165 { |
|
166 CAppMngr2InfoBase& currentItem = CurrentItem(); |
|
167 if( currentItem.SupportsGenericCommand( aCommand ) ) |
|
168 { |
|
169 Model().HandleCommandL( currentItem, aCommand ); |
|
170 } |
|
171 } |
|
172 } |
|
173 |
|
174 // --------------------------------------------------------------------------- |
|
175 // CAppMngr2ListContainer::RefreshL() |
|
176 // --------------------------------------------------------------------------- |
|
177 // |
|
178 void CAppMngr2ListContainer::RefreshL( TBool aPreserveSelectedItem, |
|
179 TBool& aSelectedItemChanged, TInt aMoreRefreshesExpected ) |
|
180 { |
|
181 FLOG( "CAppMngr2ListContainer::RefreshL( %d )", aPreserveSelectedItem ); |
|
182 |
|
183 // Record the item text of the current item if selection must be preserved in |
|
184 // the current item. The item text is used to identify the item later, so that |
|
185 // it can be selected again. |
|
186 HBufC* itemText = NULL; |
|
187 TInt currentItemIndex = iListBox->CurrentItemIndex(); |
|
188 if( aPreserveSelectedItem && currentItemIndex >= 0 ) |
|
189 { |
|
190 itemText = (*iItemArray)[ currentItemIndex ].AllocL(); |
|
191 CleanupStack::PushL( itemText ); |
|
192 } |
|
193 |
|
194 SetEmptyTextL( aMoreRefreshesExpected ); // defines empty text in first refresh |
|
195 CreateItemArrayL(); // resets the item array |
|
196 PopulateItemArrayL(); // fills in new items |
|
197 iListBox->HandleItemAdditionL(); // re-calculates size and scrollbar |
|
198 |
|
199 // If selection must be preserved, search the item in new item array |
|
200 // and select it again. Make sure to delete itemText if it was allocated. |
|
201 TBool currentItemSet = EFalse; |
|
202 TInt itemCount = iItemArray->Count(); |
|
203 if( itemText ) |
|
204 { |
|
205 for( TInt index = 0; index < itemCount && !currentItemSet; index++ ) |
|
206 { |
|
207 if( itemText->Compare( (*iItemArray)[ index ] ) == 0 ) |
|
208 { |
|
209 iListBox->SetCurrentItemIndex( index ); |
|
210 currentItemSet = ETrue; |
|
211 } |
|
212 } |
|
213 CleanupStack::PopAndDestroy( itemText ); |
|
214 } |
|
215 |
|
216 // If item is not found (it may have been deleted), then tell to the |
|
217 // caller that the selected item was changed and select another item |
|
218 // from the same row number than the previously selected item. |
|
219 aSelectedItemChanged = !currentItemSet; |
|
220 if( aSelectedItemChanged ) |
|
221 { |
|
222 if( currentItemIndex >= itemCount ) |
|
223 { |
|
224 currentItemIndex = itemCount - 1; |
|
225 } |
|
226 if( currentItemIndex < 0 ) |
|
227 { |
|
228 currentItemIndex = 0; |
|
229 } |
|
230 if( currentItemIndex != iListBox->CurrentItemIndex() ) |
|
231 { |
|
232 iListBox->SetCurrentItemIndex( currentItemIndex ); |
|
233 } |
|
234 } |
|
235 } |
|
236 |
|
237 // --------------------------------------------------------------------------- |
|
238 // CAppMngr2ListContainer::ConstructL() |
|
239 // --------------------------------------------------------------------------- |
|
240 // |
|
241 void CAppMngr2ListContainer::ConstructL( const TRect& aRect ) |
|
242 { |
|
243 CreateWindowL(); |
|
244 SetRect( aRect ); |
|
245 iListBox = new (ELeave) CAknDoubleLargeStyleListBox; |
|
246 iListBox->SetContainerWindowL( *this ); |
|
247 iListBox->ConstructL( this, EAknListBoxSelectionList ); |
|
248 iListBox->SetListBoxObserver( this ); |
|
249 |
|
250 // Dont display default "(no data)" empty text |
|
251 iListBox->View()->SetListEmptyTextL( KNullDesC ); |
|
252 |
|
253 LoadIconsL(); |
|
254 CreateItemArrayL(); |
|
255 PopulateItemArrayL(); |
|
256 |
|
257 iListBox->CreateScrollBarFrameL(); |
|
258 iListBox->ScrollBarFrame()->SetScrollBarVisibilityL( |
|
259 CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto ); |
|
260 iListBox->SetRect( aRect.Size() ); |
|
261 |
|
262 // Enable marquee effect |
|
263 iListBox->ItemDrawer()->ColumnData()->EnableMarqueeL( ETrue ); |
|
264 } |
|
265 |
|
266 // --------------------------------------------------------------------------- |
|
267 // CAppMngr2ListContainer::Model() |
|
268 // --------------------------------------------------------------------------- |
|
269 // |
|
270 CAppMngr2Model& CAppMngr2ListContainer::Model() const |
|
271 { |
|
272 return reinterpret_cast<CAppMngr2AppUi*>( iEikonEnv->EikAppUi() )->Model(); |
|
273 } |
|
274 |
|
275 // --------------------------------------------------------------------------- |
|
276 // CAppMngr2ListContainer::LoadIconsL() |
|
277 // --------------------------------------------------------------------------- |
|
278 // |
|
279 void CAppMngr2ListContainer::LoadIconsL() |
|
280 { |
|
281 CAknIconArray* iconArray = new ( ELeave ) CAknIconArray( KGranularity ); |
|
282 CleanupStack::PushL( iconArray ); |
|
283 Model().LoadIconsL( *iconArray ); |
|
284 delete iListBox->ItemDrawer()->ColumnData()->IconArray(); |
|
285 iListBox->ItemDrawer()->ColumnData()->SetIconArray( iconArray ); |
|
286 CleanupStack::Pop( iconArray ); |
|
287 iItemSpecificIcons = 0; |
|
288 } |
|
289 |
|
290 // --------------------------------------------------------------------------- |
|
291 // CAppMngr2ListContainer::CreateItemArrayL() |
|
292 // --------------------------------------------------------------------------- |
|
293 // |
|
294 void CAppMngr2ListContainer::CreateItemArrayL() |
|
295 { |
|
296 if( iItemArray ) |
|
297 { |
|
298 iListBox->Model()->SetItemTextArray( NULL ); |
|
299 delete iItemArray; |
|
300 iItemArray = NULL; |
|
301 } |
|
302 iItemArray = new ( ELeave ) CDesCArrayFlat( KGranularity ); |
|
303 iListBox->Model()->SetItemTextArray( iItemArray ); |
|
304 iListBox->Model()->SetOwnershipType( ELbmDoesNotOwnItemArray ); |
|
305 } |
|
306 |
|
307 // --------------------------------------------------------------------------- |
|
308 // CAppMngr2ListContainer::PopulateItemArrayL() |
|
309 // --------------------------------------------------------------------------- |
|
310 // |
|
311 void CAppMngr2ListContainer::PopulateItemArrayL() |
|
312 { |
|
313 FLOG( "CAppMngr2ListContainer::PopulateItemArrayL()" ); |
|
314 |
|
315 CArrayPtr<CGulIcon>* iconArray = iListBox->ItemDrawer()->ColumnData()->IconArray(); |
|
316 DeleteItemSpecificIcons( *iconArray ); |
|
317 |
|
318 TInt count = ItemCount(); |
|
319 for( TInt index = 0; index < count; index++ ) |
|
320 { |
|
321 const CAppMngr2InfoBase& appInfo = ItemInfo( index ); |
|
322 |
|
323 // Get name and details |
|
324 TPtrC name = appInfo.Name(); |
|
325 TPtrC size = appInfo.Details(); |
|
326 |
|
327 // Get icon indexes that plugin loaded in LoadIconsL() |
|
328 TInt iconIndexBase; |
|
329 TInt iconIndexMax; |
|
330 Model().GetIconIndexesL( appInfo.Runtime().RuntimeUid(), |
|
331 iconIndexBase, iconIndexMax ); |
|
332 |
|
333 // Get list icon index from plugin |
|
334 TInt iconIndex = appInfo.IconIndex(); |
|
335 |
|
336 // Convert index into the range of 0 .. (icons - 1) |
|
337 if( iconIndex == EAppMngr2UseSpecificIcon ) |
|
338 { |
|
339 CGulIcon* icon = NULL; |
|
340 TRAP_IGNORE( icon = appInfo.SpecificIconL() ); |
|
341 if( icon ) |
|
342 { |
|
343 CleanupStack::PushL( icon ); |
|
344 iconIndex = iconArray->Count(); |
|
345 iconArray->AppendL( icon ); |
|
346 CleanupStack::Pop( icon ); |
|
347 iItemSpecificIcons++; |
|
348 } |
|
349 else |
|
350 { |
|
351 iconIndex = EAppMngr2IconIndex_QgnPropUnknown; |
|
352 } |
|
353 } |
|
354 else |
|
355 { |
|
356 // There are no default list icons that plugins could use, so |
|
357 // this must be list icon that plugin has loaded in LoadIconsL(). |
|
358 // Icons (of this plugin) are indexed from iconIndexBase. |
|
359 iconIndex += iconIndexBase; |
|
360 |
|
361 // Plugin should use only those icons it has provided. Use |
|
362 // default unknown icon if plugin tries to use icons that |
|
363 // another plugin has loaded. |
|
364 if( iconIndex < iconIndexBase || iconIndex >= iconIndexMax ) |
|
365 { |
|
366 iconIndex = EAppMngr2IconIndex_QgnPropUnknown; |
|
367 } |
|
368 } |
|
369 // Sanity check - index must be in range, otherwise list panics |
|
370 if( iconIndex < 0 || iconIndex >= iconArray->Count() ) |
|
371 { |
|
372 iconIndex = EAppMngr2IconIndex_QgnPropUnknown; |
|
373 } |
|
374 |
|
375 // Get indicator icon index from plugin |
|
376 TInt indIconIndex = appInfo.IndicatorIconIndex(); |
|
377 |
|
378 // Convert indicator icon index into the range of 0 .. (icons-1) or |
|
379 // leave special value EAppMngr2NoIndicatorIcon in it |
|
380 if( indIconIndex == EAppMngr2UseSpecificIcon ) |
|
381 { |
|
382 CGulIcon* icon = NULL; |
|
383 TRAP_IGNORE( icon = appInfo.SpecificIndicatorIconL() ); |
|
384 if( icon ) |
|
385 { |
|
386 CleanupStack::PushL( icon ); |
|
387 indIconIndex = iconArray->Count(); |
|
388 iconArray->AppendL( icon ); |
|
389 CleanupStack::Pop( icon ); |
|
390 iItemSpecificIcons++; |
|
391 } |
|
392 else |
|
393 { |
|
394 indIconIndex = EAppMngr2NoIndicatorIcon; |
|
395 } |
|
396 } |
|
397 else |
|
398 { |
|
399 // EAppMngr2NoIndicatorIcon is special value that is handled later |
|
400 if( indIconIndex != EAppMngr2NoIndicatorIcon ) |
|
401 { |
|
402 // Default icon indexes (starting from EAppMngr2NoIndicatorIcon) are |
|
403 // all above the icon index range reserved for plugins |
|
404 if( indIconIndex > EAppMngr2NoIndicatorIcon ) |
|
405 { |
|
406 // Use default icons, indexes start from zero |
|
407 indIconIndex -= ( EAppMngr2NoIndicatorIcon + 1 ); |
|
408 } |
|
409 else |
|
410 { |
|
411 // Use item specific icons, indexes start from iconIndexBase |
|
412 indIconIndex += iconIndexBase; |
|
413 } |
|
414 } |
|
415 } |
|
416 // Sanity check - icon index must be in range, otherwise list panics |
|
417 if( ( indIconIndex != EAppMngr2NoIndicatorIcon ) && |
|
418 ( indIconIndex < 0 || indIconIndex >= iconArray->Count() ) ) |
|
419 { |
|
420 indIconIndex = EAppMngr2NoIndicatorIcon; |
|
421 } |
|
422 |
|
423 // Construct line to be displayed |
|
424 HBufC* temp = HBufC::NewLC( name.Length() + size.Length() + KSpaceForTabsAndIconIndexes ); |
|
425 TPtr line = temp->Des(); |
|
426 if( indIconIndex == EAppMngr2NoIndicatorIcon ) |
|
427 { |
|
428 line.AppendFormat( KItemFormatNoInd, iconIndex, &name, &size ); |
|
429 } |
|
430 else |
|
431 { |
|
432 line.AppendFormat( KItemFormatFull, iconIndex, &name, &size, indIconIndex ); |
|
433 } |
|
434 iItemArray->AppendL( line ); |
|
435 FLOG( "CAppMngr2ListContainer::PopulateItemArrayL(): %S", temp ); |
|
436 CleanupStack::PopAndDestroy( temp ); |
|
437 } |
|
438 } |
|
439 |
|
440 // --------------------------------------------------------------------------- |
|
441 // CAppMngr2ListContainer::DeleteItemSpecificIcons() |
|
442 // --------------------------------------------------------------------------- |
|
443 // |
|
444 void CAppMngr2ListContainer::DeleteItemSpecificIcons( CArrayPtr<CGulIcon>& aIconArray ) |
|
445 { |
|
446 if( iItemSpecificIcons ) |
|
447 { |
|
448 TInt iconArrayCount = aIconArray.Count(); |
|
449 TInt firstItemSpecificIcon = iconArrayCount - iItemSpecificIcons; |
|
450 for( TInt index = firstItemSpecificIcon; index < iconArrayCount; index++ ) |
|
451 { |
|
452 delete aIconArray[ index ]; |
|
453 } |
|
454 aIconArray.Delete( firstItemSpecificIcon, iItemSpecificIcons ); |
|
455 iItemSpecificIcons = 0; |
|
456 } |
|
457 } |
|
458 |
|
459 // --------------------------------------------------------------------------- |
|
460 // CAppMngr2ListContainer::SetEmptyTextL() |
|
461 // --------------------------------------------------------------------------- |
|
462 // |
|
463 void CAppMngr2ListContainer::SetEmptyTextL( TInt aMoreRefreshesExpected ) |
|
464 { |
|
465 // Set empty text if it is not already set |
|
466 CListBoxView* view = iListBox->View(); |
|
467 if( view ) |
|
468 { |
|
469 const TDesC* text = view->EmptyListText(); |
|
470 if( text == NULL || text->Length() == 0 ) |
|
471 { |
|
472 // The first refresh may happen too soon. If there are no items |
|
473 // to be displayed, and more refreshes are still expected, then |
|
474 // do not set the empty text yet -- it would be displayed. |
|
475 if( ItemCount() > 0 || !aMoreRefreshesExpected ) |
|
476 { |
|
477 HBufC* emptyText = StringLoader::LoadLC( ListEmptyTextResourceId() ); |
|
478 view->SetListEmptyTextL( *emptyText ); |
|
479 CleanupStack::PopAndDestroy( emptyText ); |
|
480 } |
|
481 } |
|
482 } |
|
483 } |
|
484 |