|
1 /* |
|
2 ============================================================================ |
|
3 Name : NPRStationListBox.cpp |
|
4 Author : Symsource |
|
5 |
|
6 Copyright (c) 2009 Symbian Foundation Ltd |
|
7 This component and the accompanying materials are made available |
|
8 under the terms of the License "Eclipse Public License v1.0" |
|
9 which accompanies this distribution, and is available |
|
10 at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
11 |
|
12 Initial Contributors: |
|
13 - Symsource |
|
14 |
|
15 Contributors: |
|
16 - Symsource |
|
17 |
|
18 Description : Container for Series60 double style list box to show the NPR's station list |
|
19 ============================================================================ |
|
20 */ |
|
21 |
|
22 #include <barsread.h> |
|
23 #include <aknlists.h> |
|
24 #include <NPR_0xEEB0E481.rsg> |
|
25 |
|
26 #include "NPRStationListBox.h" |
|
27 #include "NPRStationListBoxView.h" |
|
28 #include "NPR.hrh" |
|
29 #include "NPRStation.h" |
|
30 #include "NPRAppUi.h" |
|
31 #include "NPRAppEngine.h" |
|
32 |
|
33 const TInt KFrequencyTab = 20; |
|
34 /** |
|
35 * First phase of Symbian two-phase construction. Should not |
|
36 * contain any code that could leave. |
|
37 */ |
|
38 CNPRStationListBox::CNPRStationListBox() |
|
39 { |
|
40 iListBox = NULL; |
|
41 iStationArray = static_cast<CNPRAppUi*>(CEikonEnv::Static()->EikAppUi())->Engine().Stations(); |
|
42 } |
|
43 /** |
|
44 * Destroy child controls. |
|
45 */ |
|
46 CNPRStationListBox::~CNPRStationListBox() |
|
47 { |
|
48 delete iListBox; |
|
49 iListBox = NULL; |
|
50 } |
|
51 |
|
52 /** |
|
53 * Construct the control (first phase). |
|
54 * Creates an instance and initializes it. |
|
55 * Instance is not left on cleanup stack. |
|
56 * @param aRect bounding rectangle |
|
57 * @param aParent owning parent, or NULL |
|
58 * @param aCommandObserver command observer |
|
59 * @return initialized instance of CNPRStationListBox |
|
60 */ |
|
61 CNPRStationListBox* CNPRStationListBox::NewL( |
|
62 const TRect& aRect, |
|
63 const CCoeControl* aParent, |
|
64 MEikCommandObserver* aCommandObserver ) |
|
65 { |
|
66 CNPRStationListBox* self = CNPRStationListBox::NewLC( |
|
67 aRect, |
|
68 aParent, |
|
69 aCommandObserver ); |
|
70 CleanupStack::Pop( self ); |
|
71 return self; |
|
72 } |
|
73 |
|
74 /** |
|
75 * Construct the control (first phase). |
|
76 * Creates an instance and initializes it. |
|
77 * Instance is left on cleanup stack. |
|
78 * @param aRect The rectangle for this window |
|
79 * @param aParent owning parent, or NULL |
|
80 * @param aCommandObserver command observer |
|
81 * @return new instance of CNPRStationListBox |
|
82 */ |
|
83 CNPRStationListBox* CNPRStationListBox::NewLC( |
|
84 const TRect& aRect, |
|
85 const CCoeControl* aParent, |
|
86 MEikCommandObserver* aCommandObserver ) |
|
87 { |
|
88 CNPRStationListBox* self = new ( ELeave ) CNPRStationListBox(); |
|
89 CleanupStack::PushL( self ); |
|
90 self->ConstructL( aRect, aParent, aCommandObserver ); |
|
91 return self; |
|
92 } |
|
93 |
|
94 /** |
|
95 * Construct the control (second phase). |
|
96 * Creates a window to contain the controls and activates it. |
|
97 * @param aRect bounding rectangle |
|
98 * @param aCommandObserver command observer |
|
99 * @param aParent owning parent, or NULL |
|
100 */ |
|
101 void CNPRStationListBox::ConstructL( |
|
102 const TRect& aRect, |
|
103 const CCoeControl* aParent, |
|
104 MEikCommandObserver* aCommandObserver ) |
|
105 { |
|
106 if ( aParent == NULL ) |
|
107 { |
|
108 CreateWindowL(); |
|
109 } |
|
110 else |
|
111 { |
|
112 SetContainerWindowL( *aParent ); |
|
113 } |
|
114 iFocusControl = NULL; |
|
115 iCommandObserver = aCommandObserver; |
|
116 InitializeControlsL(); |
|
117 SetRect( aRect ); |
|
118 ActivateL(); |
|
119 } |
|
120 |
|
121 /** |
|
122 * Return the number of controls in the container (override) |
|
123 * @return count |
|
124 */ |
|
125 TInt CNPRStationListBox::CountComponentControls() const |
|
126 { |
|
127 return ( int ) ELastControl; |
|
128 } |
|
129 |
|
130 /** |
|
131 * Get the control with the given index (override) |
|
132 * @param aIndex Control index [0...n) (limited by #CountComponentControls) |
|
133 * @return Pointer to control |
|
134 */ |
|
135 CCoeControl* CNPRStationListBox::ComponentControl( TInt aIndex ) const |
|
136 { |
|
137 switch ( aIndex ) |
|
138 { |
|
139 case EListBox: |
|
140 return iListBox; |
|
141 } |
|
142 return NULL; |
|
143 } |
|
144 |
|
145 /** |
|
146 * Handle resizing of the container. This implementation will lay out |
|
147 * full-sized controls like list boxes for any screen size, and will layout |
|
148 * labels, editors, etc. to the size they were given in the UI designer. |
|
149 * This code will need to be modified to adjust arbitrary controls to |
|
150 * any screen size. |
|
151 */ |
|
152 void CNPRStationListBox::SizeChanged() |
|
153 { |
|
154 CCoeControl::SizeChanged(); |
|
155 LayoutControls(); |
|
156 } |
|
157 |
|
158 /** |
|
159 * Layout components as specified in the UI Designer |
|
160 */ |
|
161 void CNPRStationListBox::LayoutControls() |
|
162 { |
|
163 iListBox->SetExtent( TPoint( 0, 0 ), iListBox->MinimumSize() ); |
|
164 } |
|
165 |
|
166 void CNPRStationListBox::Listen() |
|
167 { |
|
168 static_cast<CNPRAppUi*>(CEikonEnv::Static()->EikAppUi())->Engine().SendNPRCommandL(EPlayStationStream, KNullDesC()); |
|
169 } |
|
170 |
|
171 /** |
|
172 * Handle key events. |
|
173 */ |
|
174 TKeyResponse CNPRStationListBox::OfferKeyEventL( |
|
175 const TKeyEvent& aKeyEvent, |
|
176 TEventCode aType ) |
|
177 { |
|
178 if ( aKeyEvent.iCode == EKeyLeftArrow |
|
179 || aKeyEvent.iCode == EKeyRightArrow ) |
|
180 { |
|
181 // Listbox takes all events even if it doesn't use them |
|
182 return EKeyWasNotConsumed; |
|
183 } |
|
184 |
|
185 if ( iFocusControl != NULL |
|
186 && iFocusControl->OfferKeyEventL( aKeyEvent, aType ) == EKeyWasConsumed ) |
|
187 { |
|
188 return EKeyWasConsumed; |
|
189 } |
|
190 return CCoeControl::OfferKeyEventL( aKeyEvent, aType ); |
|
191 } |
|
192 |
|
193 /** |
|
194 * Initialize each control upon creation. |
|
195 */ |
|
196 void CNPRStationListBox::InitializeControlsL() |
|
197 { |
|
198 iListBox = new ( ELeave ) CAknDoubleStyle2ListBox; |
|
199 iListBox->SetContainerWindowL( *this ); |
|
200 TResourceReader reader; |
|
201 iEikonEnv->CreateResourceReaderLC( reader, R_NPRSTATION_LIST_BOX_LIST_BOX); |
|
202 iListBox->ConstructFromResourceL( reader ); |
|
203 CleanupStack::PopAndDestroy(); // reader internal state |
|
204 // the listbox owns the items in the list and will free them |
|
205 iListBox->Model()->SetOwnershipType( ELbmOwnsItemArray ); |
|
206 iListBox->CreateScrollBarFrameL(ETrue); |
|
207 iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOn, CEikScrollBarFrame::EAuto); |
|
208 |
|
209 // setup the icon array so graphics-style boxes work |
|
210 SetupListBoxIconsL(); |
|
211 |
|
212 // add list items |
|
213 for(TInt i=0; i<iStationArray->Count(); i++) |
|
214 { |
|
215 TInt nameLength = (*iStationArray)[i]->Name().Length(); |
|
216 TBuf<64> namePlusFrequency((*iStationArray)[i]->Name()); |
|
217 if((*iStationArray)[i]->Frequency().Length()!=0) |
|
218 { |
|
219 for(TInt j=0; j<KFrequencyTab-nameLength;j++) |
|
220 { |
|
221 namePlusFrequency.Append(_L(" ")); |
|
222 } |
|
223 namePlusFrequency.Append((*iStationArray)[i]->Frequency()); |
|
224 } |
|
225 TBuf<128> listString; |
|
226 CreateListBoxItemL(listString, namePlusFrequency, (*iStationArray)[i]->MarketCity()); |
|
227 AddListBoxItemL(iListBox, listString); |
|
228 } |
|
229 |
|
230 iListBox->SetFocus( ETrue ); |
|
231 iFocusControl = iListBox; |
|
232 } |
|
233 |
|
234 /** |
|
235 * Handle global resource changes, such as scalable UI or skin events (override) |
|
236 */ |
|
237 void CNPRStationListBox::HandleResourceChange( TInt aType ) |
|
238 { |
|
239 CCoeControl::HandleResourceChange( aType ); |
|
240 SetRect( iAvkonViewAppUi->View( TUid::Uid( ENPRStationListBoxViewId ) )->ClientRect() ); |
|
241 } |
|
242 |
|
243 /** |
|
244 * Draw container contents. |
|
245 */ |
|
246 void CNPRStationListBox::Draw( const TRect& aRect ) const |
|
247 { |
|
248 CWindowGc& gc = SystemGc(); |
|
249 gc.Clear( aRect ); |
|
250 } |
|
251 |
|
252 /** |
|
253 * Add a list box item to a list. |
|
254 */ |
|
255 void CNPRStationListBox::AddListBoxItemL( |
|
256 CEikTextListBox* aListBox, |
|
257 const TDesC& aString ) |
|
258 { |
|
259 CTextListBoxModel* model = aListBox->Model(); |
|
260 CDesCArray* itemArray = static_cast< CDesCArray* > ( model->ItemTextArray() ); |
|
261 itemArray->AppendL( aString ); |
|
262 aListBox->HandleItemAdditionL(); |
|
263 } |
|
264 |
|
265 /** |
|
266 * Get the array of selected item indices, with respect to the list model. |
|
267 * The array is sorted in ascending order. |
|
268 * The array should be destroyed with two calls to CleanupStack::PopAndDestroy(), |
|
269 * the first with no argument (referring to the internal resource) and the |
|
270 * second with the array pointer. |
|
271 * @return newly allocated array, which is left on the cleanup stack; |
|
272 * or NULL for empty list. |
|
273 */ |
|
274 RArray< TInt >* CNPRStationListBox::GetSelectedListBoxItemsLC( CEikTextListBox* aListBox ) |
|
275 { |
|
276 CAknFilteredTextListBoxModel* model = |
|
277 static_cast< CAknFilteredTextListBoxModel *> ( aListBox->Model() ); |
|
278 if ( model->NumberOfItems() == 0 ) |
|
279 return NULL; |
|
280 |
|
281 // get currently selected indices |
|
282 const CListBoxView::CSelectionIndexArray* selectionIndexes = |
|
283 aListBox->SelectionIndexes(); |
|
284 TInt selectedIndexesCount = selectionIndexes->Count(); |
|
285 if ( selectedIndexesCount == 0 ) |
|
286 return NULL; |
|
287 |
|
288 // copy the indices and sort numerically |
|
289 RArray<TInt>* orderedSelectedIndices = |
|
290 new (ELeave) RArray< TInt >( selectedIndexesCount ); |
|
291 |
|
292 // push the allocated array |
|
293 CleanupStack::PushL( orderedSelectedIndices ); |
|
294 |
|
295 // dispose the array resource |
|
296 CleanupClosePushL( *orderedSelectedIndices ); |
|
297 |
|
298 // see if the search field is enabled |
|
299 CAknListBoxFilterItems* filter = model->Filter(); |
|
300 if ( filter != NULL ) |
|
301 { |
|
302 // when filtering enabled, translate indices back to underlying model |
|
303 for ( TInt idx = 0; idx < selectedIndexesCount; idx++ ) |
|
304 { |
|
305 TInt filteredItem = ( *selectionIndexes ) [ idx ]; |
|
306 TInt actualItem = filter->FilteredItemIndex ( filteredItem ); |
|
307 orderedSelectedIndices->InsertInOrder( actualItem ); |
|
308 } |
|
309 } |
|
310 else |
|
311 { |
|
312 // the selection indices refer directly to the model |
|
313 for ( TInt idx = 0; idx < selectedIndexesCount; idx++ ) |
|
314 orderedSelectedIndices->InsertInOrder( ( *selectionIndexes ) [ idx ] ); |
|
315 } |
|
316 |
|
317 return orderedSelectedIndices; |
|
318 } |
|
319 |
|
320 /** |
|
321 * Delete the selected item or items from the list box. |
|
322 */ |
|
323 void CNPRStationListBox::DeleteSelectedListBoxItemsL( CEikTextListBox* aListBox ) |
|
324 { |
|
325 CAknFilteredTextListBoxModel* model = |
|
326 static_cast< CAknFilteredTextListBoxModel *> ( aListBox->Model() ); |
|
327 if ( model->NumberOfItems() == 0 ) |
|
328 return; |
|
329 |
|
330 RArray< TInt >* orderedSelectedIndices = GetSelectedListBoxItemsLC( aListBox ); |
|
331 if ( !orderedSelectedIndices ) |
|
332 return; |
|
333 |
|
334 // Delete selected items from bottom up so indices don't change on us |
|
335 CDesCArray* itemArray = static_cast< CDesCArray* > ( model->ItemTextArray() ); |
|
336 TInt currentItem = 0; |
|
337 |
|
338 for ( TInt idx = orderedSelectedIndices->Count(); idx-- > 0; ) |
|
339 { |
|
340 currentItem = ( *orderedSelectedIndices )[ idx ]; |
|
341 itemArray->Delete ( currentItem ); |
|
342 } |
|
343 |
|
344 // dispose the array resources |
|
345 CleanupStack::PopAndDestroy(); |
|
346 |
|
347 // dispose the array pointer |
|
348 CleanupStack::PopAndDestroy( orderedSelectedIndices ); |
|
349 |
|
350 // refresh listbox's cursor now that items are deleted |
|
351 AknListBoxUtils::HandleItemRemovalAndPositionHighlightL( |
|
352 aListBox, currentItem, ETrue ); |
|
353 } |
|
354 |
|
355 /** |
|
356 * Get the listbox. |
|
357 */ |
|
358 CAknDoubleStyle2ListBox* CNPRStationListBox::ListBox() |
|
359 { |
|
360 return iListBox; |
|
361 } |
|
362 |
|
363 /** |
|
364 * Create a list box item with the given column values. |
|
365 */ |
|
366 void CNPRStationListBox::CreateListBoxItemL( TDes& aBuffer, |
|
367 const TDesC& aMainText, |
|
368 const TDesC& aSecondaryText ) |
|
369 { |
|
370 _LIT ( KStringHeader, "\t%S\t%S" ); |
|
371 |
|
372 aBuffer.Format( KStringHeader(), &aMainText, &aSecondaryText ); |
|
373 } |
|
374 |
|
375 /** |
|
376 * Add an item to the list by reading the text items from the array resource |
|
377 * and setting a single image property (if available) from an index |
|
378 * in the list box's icon array. |
|
379 * @param aResourceId id of an ARRAY resource containing the textual |
|
380 * items in the columns |
|
381 * |
|
382 */ |
|
383 void CNPRStationListBox::AddListBoxResourceArrayItemL( TInt aResourceId ) |
|
384 { |
|
385 CDesCArray* array = iCoeEnv->ReadDesCArrayResourceL( aResourceId ); |
|
386 CleanupStack::PushL( array ); |
|
387 // This is intended to be large enough, but if you get |
|
388 // a USER 11 panic, consider reducing string sizes. |
|
389 TBuf<512> listString; |
|
390 CreateListBoxItemL( listString, ( *array ) [ 0 ], ( *array ) [ 1 ] ); |
|
391 AddListBoxItemL( iListBox, listString ); |
|
392 CleanupStack::PopAndDestroy( array ); |
|
393 } |
|
394 |
|
395 /** |
|
396 * Set up the list's icon array. |
|
397 */ |
|
398 void CNPRStationListBox::SetupListBoxIconsL() |
|
399 { |
|
400 CArrayPtr< CGulIcon >* icons = NULL; |
|
401 |
|
402 if(icons != NULL) |
|
403 { |
|
404 iListBox->ItemDrawer()->ColumnData()->SetIconArray(icons); |
|
405 } |
|
406 } |
|
407 |
|
408 /** |
|
409 * Handle commands relating to markable lists. |
|
410 */ |
|
411 TBool CNPRStationListBox::HandleMarkableListCommandL(TInt /*aCommand*/) |
|
412 { |
|
413 TBool result = EFalse; |
|
414 return result; |
|
415 } |