--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/NPRStoryListBox.cpp Fri Jul 24 08:46:02 2009 +0100
@@ -0,0 +1,496 @@
+/*
+ ============================================================================
+ Name : NPRStoryListBox.cpp
+ Author : Symsource
+
+ Copyright (c) 2009 Symbian Foundation Ltd
+ This component and the accompanying materials are made available
+ under the terms of the License "Eclipse Public License v1.0"
+ which accompanies this distribution, and is available
+ at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+ Initial Contributors:
+ - Symsource
+
+ Contributors:
+ - Symsource
+
+ Description : Container for Series60 double style list box to show the NPR's story list
+ ============================================================================
+ */
+
+#include <barsread.h>
+#include <aknlists.h>
+#include <akniconarray.h>
+#include <NPR_0xEEB0E481.rsg>
+#include <list_icons.mbg>
+
+#include "NPRStoryListBox.h"
+#include "NPRStoryListBoxView.h"
+#include "NPR.hrh"
+#include "NPRAppUi.h"
+#include "NPRAppEngine.h"
+#include "NPRHtmlCreator.h"
+
+_LIT(KStringHeader, "%d\t%S\t%S" );
+_LIT(KTestUiFile, "\\resource\\apps\\list_icons.mbm");
+
+/**
+ * Construct the control (first phase).
+ * Creates an instance and initializes it.
+ * Instance is not left on cleanup stack.
+ * @param aRect bounding rectangle
+ * @param aParent owning parent, or NULL
+ * @param aCommandObserver command observer
+ * @return initialized instance of CNPRStoryListBox
+ */
+CNPRStoryListBox* CNPRStoryListBox::NewL(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver )
+ {
+ CNPRStoryListBox* self = CNPRStoryListBox::NewLC(
+ aRect,
+ aParent,
+ aCommandObserver );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+/**
+ * Construct the control (first phase).
+ * Creates an instance and initializes it.
+ * Instance is left on cleanup stack.
+ * @param aRect The rectangle for this window
+ * @param aParent owning parent, or NULL
+ * @param aCommandObserver command observer
+ * @return new instance of CNPRStoryListBox
+ */
+CNPRStoryListBox* CNPRStoryListBox::NewLC(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver )
+ {
+ CNPRStoryListBox* self = new ( ELeave ) CNPRStoryListBox();
+ CleanupStack::PushL( self );
+ self->ConstructL( aRect, aParent, aCommandObserver );
+ return self;
+ }
+
+/**
+ * First phase of Symbian two-phase construction. Should not
+ * contain any code that could leave.
+ */
+CNPRStoryListBox::CNPRStoryListBox()
+ {
+ iListBox = NULL;
+ iStoryArray = static_cast<CNPRAppUi*>(CEikonEnv::Static()->EikAppUi())->Engine().Stories();
+ }
+/**
+ * Destroy child controls.
+ */
+CNPRStoryListBox::~CNPRStoryListBox()
+ {
+ delete iHtmlCreator;
+ delete iListBox;
+ iListBox = NULL;
+ }
+
+/**
+ * Construct the control (second phase).
+ * Creates a window to contain the controls and activates it.
+ * @param aRect bounding rectangle
+ * @param aCommandObserver command observer
+ * @param aParent owning parent, or NULL
+ */
+void CNPRStoryListBox::ConstructL(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver )
+ {
+ if ( aParent == NULL )
+ {
+ CreateWindowL();
+ }
+ else
+ {
+ SetContainerWindowL( *aParent );
+ }
+ iFocusControl = NULL;
+ iCommandObserver = aCommandObserver;
+ iHtmlCreator = CNPRHtmlCreator::NewL();
+
+ InitializeControlsL();
+ SetRect( aRect );
+ ActivateL();
+ }
+
+/**
+* Return the number of controls in the container (override)
+* @return count
+*/
+TInt CNPRStoryListBox::CountComponentControls() const
+ {
+ return ( int ) ELastControl;
+ }
+
+/**
+* Get the control with the given index (override)
+* @param aIndex Control index [0...n) (limited by #CountComponentControls)
+* @return Pointer to control
+*/
+CCoeControl* CNPRStoryListBox::ComponentControl( TInt aIndex ) const
+ {
+ switch(aIndex)
+ {
+ case EListBox:
+ return iListBox;
+ }
+ return NULL;
+ }
+
+/**
+ * Handle resizing of the container. This implementation will lay out
+ * full-sized controls like list boxes for any screen size, and will layout
+ * labels, editors, etc. to the size they were given in the UI designer.
+ * This code will need to be modified to adjust arbitrary controls to
+ * any screen size.
+ */
+void CNPRStoryListBox::SizeChanged()
+ {
+ CCoeControl::SizeChanged();
+ LayoutControls();
+ }
+
+/**
+ * Layout components as specified in the UI Designer
+ */
+void CNPRStoryListBox::LayoutControls()
+ {
+ iListBox->SetExtent( TPoint( 0, 0 ), iListBox->MinimumSize() );
+ }
+
+/**
+ * Handle key events.
+ */
+TKeyResponse CNPRStoryListBox::OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ if ( aKeyEvent.iCode == EKeyLeftArrow
+ || aKeyEvent.iCode == EKeyRightArrow )
+ {
+ // Listbox takes all events even if it doesn't use them
+ return EKeyWasNotConsumed;
+ }
+
+ if ( iFocusControl != NULL && aKeyEvent.iCode == EKeyDevice3)
+ {
+ ShowSelectedStoryL();
+ return EKeyWasConsumed;
+ }
+
+ if ( iFocusControl != NULL
+ && iFocusControl->OfferKeyEventL( aKeyEvent, aType ) == EKeyWasConsumed )
+ {
+ return EKeyWasConsumed;
+ }
+ return CCoeControl::OfferKeyEventL( aKeyEvent, aType );
+ }
+
+/**
+ * Initialize each control upon creation.
+ */
+void CNPRStoryListBox::InitializeControlsL()
+ {
+ iListBox = new ( ELeave ) CAknDoubleLargeStyleListBox;
+ iListBox->SetContainerWindowL( *this );
+ {
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_NPRSTORY_LIST_BOX_LIST_BOX );
+ iListBox->ConstructFromResourceL( reader );
+ CleanupStack::PopAndDestroy(); // reader internal state
+ }
+ // the listbox owns the items in the list and will free them
+ iListBox->Model()->SetOwnershipType( ELbmOwnsItemArray );
+ iListBox->CreateScrollBarFrameL(ETrue);
+ iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOn, CEikScrollBarFrame::EAuto);
+
+ SetupListBoxIconsL();
+ // add list items
+ for(TInt i=0; i<iStoryArray->Count(); i++)
+ {
+ HBufC* story = HBufC::NewLC(KStringHeader().Length()
+ + (*iStoryArray)[i]->Title().Length()
+ + (*iStoryArray)[i]->Teaser().Length()
+ );
+ TPtr storyPtr = story->Des();
+ CreateListBoxItemL(storyPtr, TInt(0), (*iStoryArray)[i]->Title(), (*iStoryArray)[i]->Teaser());
+ AddListBoxItemL(iListBox, storyPtr);
+ CleanupStack::PopAndDestroy(story);
+ }
+
+ iListBox->SetFocus( ETrue );
+ iFocusControl = iListBox;
+ }
+
+/**
+ * Handle global resource changes, such as scalable UI or skin events (override)
+ */
+void CNPRStoryListBox::HandleResourceChange( TInt aType )
+ {
+ CCoeControl::HandleResourceChange( aType );
+ SetRect( iAvkonViewAppUi->View( TUid::Uid( ENPRStoryListBoxViewId ) )->ClientRect() );
+ }
+
+/**
+ * Draw container contents.
+ */
+void CNPRStoryListBox::Draw( const TRect& aRect ) const
+ {
+ CWindowGc& gc = SystemGc();
+ gc.Clear( aRect );
+ }
+
+/**
+ * Add a list box item to a list.
+ */
+void CNPRStoryListBox::AddListBoxItemL(
+ CEikTextListBox* aListBox,
+ const TDesC& aString )
+ {
+ CTextListBoxModel* model = aListBox->Model();
+ CDesCArray* itemArray = static_cast< CDesCArray* > ( model->ItemTextArray() );
+ itemArray->AppendL( aString );
+ aListBox->HandleItemAdditionL();
+ }
+
+/**
+ * Get the array of selected item indices, with respect to the list model.
+ * The array is sorted in ascending order.
+ * The array should be destroyed with two calls to CleanupStack::PopAndDestroy(),
+ * the first with no argument (referring to the internal resource) and the
+ * second with the array pointer.
+ * @return newly allocated array, which is left on the cleanup stack;
+ * or NULL for empty list.
+ */
+RArray< TInt >* CNPRStoryListBox::GetSelectedListBoxItemsLC( CEikTextListBox* aListBox )
+ {
+ CAknFilteredTextListBoxModel* model =
+ static_cast< CAknFilteredTextListBoxModel *> ( aListBox->Model() );
+ if ( model->NumberOfItems() == 0 )
+ return NULL;
+
+ // get currently selected indices
+ const CListBoxView::CSelectionIndexArray* selectionIndexes =
+ aListBox->SelectionIndexes();
+ TInt selectedIndexesCount = selectionIndexes->Count();
+ if ( selectedIndexesCount == 0 )
+ return NULL;
+
+ // copy the indices and sort numerically
+ RArray<TInt>* orderedSelectedIndices =
+ new (ELeave) RArray< TInt >( selectedIndexesCount );
+
+ // push the allocated array
+ CleanupStack::PushL( orderedSelectedIndices );
+
+ // dispose the array resource
+ CleanupClosePushL( *orderedSelectedIndices );
+
+ // see if the search field is enabled
+ CAknListBoxFilterItems* filter = model->Filter();
+ if ( filter != NULL )
+ {
+ // when filtering enabled, translate indices back to underlying model
+ for ( TInt idx = 0; idx < selectedIndexesCount; idx++ )
+ {
+ TInt filteredItem = ( *selectionIndexes ) [ idx ];
+ TInt actualItem = filter->FilteredItemIndex ( filteredItem );
+ orderedSelectedIndices->InsertInOrder( actualItem );
+ }
+ }
+ else
+ {
+ // the selection indices refer directly to the model
+ for ( TInt idx = 0; idx < selectedIndexesCount; idx++ )
+ orderedSelectedIndices->InsertInOrder( ( *selectionIndexes ) [ idx ] );
+ }
+
+ return orderedSelectedIndices;
+ }
+
+/**
+ * Delete the selected item or items from the list box.
+ */
+void CNPRStoryListBox::DeleteSelectedListBoxItemsL( CEikTextListBox* aListBox )
+ {
+ CAknFilteredTextListBoxModel* model =
+ static_cast< CAknFilteredTextListBoxModel *> ( aListBox->Model() );
+ if ( model->NumberOfItems() == 0 )
+ return;
+
+ RArray< TInt >* orderedSelectedIndices = GetSelectedListBoxItemsLC( aListBox );
+ if ( !orderedSelectedIndices )
+ return;
+
+ // Delete selected items from bottom up so indices don't change on us
+ CDesCArray* itemArray = static_cast< CDesCArray* > ( model->ItemTextArray() );
+ TInt currentItem = 0;
+
+ for ( TInt idx = orderedSelectedIndices->Count(); idx-- > 0; )
+ {
+ currentItem = ( *orderedSelectedIndices )[ idx ];
+ itemArray->Delete ( currentItem );
+ }
+
+ // dispose the array resources
+ CleanupStack::PopAndDestroy();
+
+ // dispose the array pointer
+ CleanupStack::PopAndDestroy( orderedSelectedIndices );
+
+ // refresh listbox's cursor now that items are deleted
+ AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(
+ aListBox, currentItem, ETrue );
+ }
+
+/**
+ * Get the listbox.
+ */
+CAknDoubleLargeStyleListBox* CNPRStoryListBox::ListBox()
+ {
+ return iListBox;
+ }
+
+/**
+ * Create a list box item with the given column values.
+ */
+void CNPRStoryListBox::CreateListBoxItemL( TDes& aBuffer,
+ TInt aIconIndex,
+ const TDesC& aMainText,
+ const TDesC& aSecondaryText )
+ {
+
+ aBuffer.Format( KStringHeader(), aIconIndex, &aMainText, &aSecondaryText);
+ }
+
+/**
+ * Add an item to the list by reading the text items from the array resource
+ * and setting a single image property (if available) from an index
+ * in the list box's icon array.
+ * @param aResourceId id of an ARRAY resource containing the textual
+ * items in the columns
+ * @param aIconIndex the index in the icon array, or -1
+ */
+void CNPRStoryListBox::AddListBoxResourceArrayItemL( TInt aResourceId, TInt aIconIndex )
+ {
+ CDesCArray* array = iCoeEnv->ReadDesCArrayResourceL( aResourceId );
+ CleanupStack::PushL( array );
+ // This is intended to be large enough, but if you get
+ // a USER 11 panic, consider reducing string sizes.
+ TBuf<512> listString;
+ CreateListBoxItemL( listString, aIconIndex, (*array) [0], (*array )[1]);
+ AddListBoxItemL( iListBox, listString );
+ CleanupStack::PopAndDestroy( array );
+ }
+
+/**
+ * Set up the list's icon array.
+ */
+void CNPRStoryListBox::SetupListBoxIconsL()
+ {
+ CArrayPtr< CGulIcon >* icons = new (ELeave) CAknIconArray( 1 );
+ CleanupStack::PushL( icons );
+
+ icons->AppendL(LoadAndScaleIconL(KTestUiFile,
+ EMbmList_iconsNpr_symbian_generic,
+ EMbmList_iconsNpr_symbian_generic_mask,
+ NULL, EAspectRatioPreserved ));
+
+ CleanupStack::Pop( icons );
+
+ if ( icons != NULL )
+ {
+ iListBox->ItemDrawer()->ColumnData()->SetIconArray( icons );
+ }
+ }
+
+/**
+ * Handle commands relating to markable lists.
+ */
+TBool CNPRStoryListBox::HandleMarkableListCommandL(TInt /*aCommand*/)
+ {
+ return EFalse;
+ }
+
+/**
+ * This routine loads and scales a bitmap or icon.
+ *
+ * @param aFileName the MBM or MIF filename
+ * @param aBitmapId the bitmap id
+ * @param aMaskId the mask id or -1 for none
+ * @param aSize the TSize for the icon, or NULL to use real size
+ * @param aScaleMode one of the EAspectRatio* enums when scaling
+ *
+ */
+CGulIcon* CNPRStoryListBox::LoadAndScaleIconL(
+ const TDesC& aFileName,
+ TInt aBitmapId,
+ TInt aMaskId,
+ TSize* aSize,
+ TScaleMode aScaleMode )
+ {
+ CFbsBitmap* bitmap;
+ CFbsBitmap* mask;
+ TRAPD(err, AknIconUtils::CreateIconL( bitmap, mask, aFileName, aBitmapId, aMaskId ));
+
+ TSize size;
+ if ( aSize == NULL )
+ {
+ // Use size from the image header. In case of SVG,
+ // we preserve the image data for a while longer, since ordinarily
+ // it is disposed at the first GetContentDimensions() or SetSize() call.
+ AknIconUtils::PreserveIconData( bitmap );
+ AknIconUtils::GetContentDimensions( bitmap, size );
+ }
+ else
+ {
+ size = *aSize;
+ }
+
+ AknIconUtils::SetSize( bitmap, size, aScaleMode );
+ AknIconUtils::SetSize( mask, size, aScaleMode );
+
+ if ( aSize == NULL )
+ {
+ AknIconUtils::DestroyIconData( bitmap );
+ }
+
+ return CGulIcon::NewL( bitmap, mask );
+ }
+
+TInt CNPRStoryListBox::CurrentItemIndex()
+ {
+ return iListBox->CurrentItemIndex();
+ }
+
+void CNPRStoryListBox::ShowSelectedStoryL()
+ {
+// TInt index = CurrentItemIndex();
+// static_cast<CNPRAppUi*>(CEikonEnv::Static()->EikAppUi())->
+// ActivateLocalViewL(TUid::Uid(ENPRStoryViewerContainerViewId), TUid::Uid(index),KNullDesC8);//TO DO use custum message instead of custum command
+
+ TInt currentItem = iListBox->CurrentItemIndex();
+ if (currentItem==-1)
+ {
+ return;
+ }
+
+ CNPRStory* story=(*iStoryArray)[currentItem];
+
+ //TODO - Move this code into the browser container, so it is seperate from the listbox
+ iHtmlCreator->CreateHtmlFileL(story);
+
+ static_cast<CNPRAppUi*>(CEikonEnv::Static()->EikAppUi())->ActivateLocalViewL(TUid::Uid(ENPRBrowserViewId));
+ }