diff -r 000000000000 -r 1f04cf54edd8 symhelp/helpmodel/tsrc/THelpView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symhelp/helpmodel/tsrc/THelpView.cpp Tue Jan 26 15:15:23 2010 +0200 @@ -0,0 +1,692 @@ +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#pragma message(__FILE__ "(5) : This test code memory leaks on exit due to a bug in the code...fix when have time") + +#include "THelpView.h" + +// System includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hlpmodel.h" +#include + +// User includes +#include "thelpviewctrls.h" +#include "THelpView.hrh" + +// Constants +const TInt KSizeSearchPromptIndent = 5; +const TInt KSizeSearchPromptHeight = 25; +const TInt KResultsViewWidth = 150; + +// Panic enum +enum THlpViewerPanic + { + EHlpViewPanicNoSearchSpec + }; + + +// +// ----> Global functions / Entry points (source) +// + +LOCAL_C CApaApplication* NewApplication() +// Ordinal 1 export for App Dll's + { + return new CHlpApplication(); + } + +GLDEF_C TInt E32Main() + { + return EikStart::RunApplication(NewApplication); + } + + +void Panic(THlpViewerPanic aPanic) + { + _LIT(KHlpViewPanicCategory, "HlpView"); + User::Panic(KHlpViewPanicCategory, aPanic); + } + + + +// +// ----> CHlpApplication (source) +// +TUid CHlpApplication::AppDllUid() const + { + return KUidHelpViewApp; + } + +CApaDocument* CHlpApplication::CreateDocumentL() + { + CHlpDocument* document = new(ELeave) CHlpDocument(*this); + CleanupStack::PushL(document); + document->NewDocumentL(); + CleanupStack::Pop(); + return document; + } + + + + + +// +// ----> CHlpAppUi (source) +// +CHlpDocument::CHlpDocument(CEikApplication& aApp) +: CEikDocument(aApp) + { + } + +CHlpDocument::~CHlpDocument() + { + delete iModel; + } + +CEikAppUi* CHlpDocument::CreateAppUiL() + { + return(new(ELeave) CHlpAppUi()); + } + +void CHlpDocument::NewDocumentL() + { + CHlpModel* model = CHlpModel::NewL(Process()->FsSession(), NULL); + CleanupStack::PushL(model); + model->OpenL(); + delete iModel; + iModel = model; + CleanupStack::Pop(); // model + } + + + + + +// +// ----> CHlpAppUi (source) +// +CHlpAppUi::~CHlpAppUi() + { + CCoeAppUi::RemoveFromStack(iView); + delete iView; + } + +void CHlpAppUi::ConstructL() + { + BaseConstructL(); + + iView = new(ELeave) CHlpMainView(*this, Document().Model()); + iView->ConstructL(); + iView->SetRect(ClientRect()); + + AddToStackL(iView); + } + +// +// FROM CEikAppUi +// + +void CHlpAppUi::HandleCommandL(TInt aCommand) + { + switch (aCommand) + { + case EEikCmdExit: + Exit(); + break; + + case EHlpCmdSearch: + iView->ShowSearchPrompt(ETrue); + break; + + case EHlpCmdSearchDone: + iView->MakeResultsVisible(EFalse); + break; + + case EEikCmdZoomIn: + case EEikCmdZoomOut: + HandleZoomL(aCommand); + break; + + default: + User::Leave(KErrNotSupported); + break; + } + } + +void CHlpAppUi::DynInitMenuPaneL(TInt aMenuId, CEikMenuPane* aMenuPane) + { + switch (aMenuId) + { + case R_HELPVIEW_TOOLS_MENU: + aMenuPane->SetItemDimmed(EHlpCmdSearchDone, !iView->IsSearchResultVisible()); + break; + } + } + +// +// NEW +// + +void CHlpAppUi::HandleZoomL(TInt aZoomEvent) + { + if (!iZoomHandler) + return; + iZoomHandler->HandleZoomEventL(STATIC_CAST(MZoomableControl::TZoomEvent, aZoomEvent)); + } + + + + + + +// +// ----> CHlpView (source) +// +CHlpView::CHlpView(CHlpAppUi& aAppUi, CHlpModel& aModel) +: iAppUi(aAppUi), iHelpModel(aModel), iCurrentZoom(EZoomStateTwo) + { + } + +CHlpView::~CHlpView() + { + delete iHelpCategories; + delete iHelpTopicsForCategory; + delete iRichTextEditor; + delete iCurrentTopics; + delete iLastTopic; + + // Remove this when the memory leak is finished... + iCoeEnv->DisableExitChecks(ETrue); + } + +void CHlpView::ConstructL() + { + iLastTopic = CHlpTopic::NewL(); + iZoom.SetGraphicsDeviceMap(iCoeEnv->ScreenDevice()); + + iHelpModel.SetObserver(this); + + iHelpCategories = new(ELeave) CEikChoiceList(); + iHelpCategories->SetContainerWindowL(*this); + iHelpCategories->SetFocus(ETrue); + iHelpCategories->SetObserver(this); + + iHelpTopicsForCategory = new(ELeave) CEikChoiceList(); + iHelpTopicsForCategory->SetContainerWindowL(*this); + iHelpTopicsForCategory->SetObserver(this); + + iRichTextEditor = new(ELeave) CEikRichTextEditor(); + iRichTextEditor->SetContainerWindowL(*this); + iRichTextEditor->ConstructL(this, 6, 100000, CEikEdwin::EWidthInPixels | CEikEdwin::EReadOnly | CEikEdwin::ENoAutoSelection | CEikEdwin::EKeepDocument); + iRichTextEditor->SetZoomFactorL(&iZoom); + iRichTextEditor->CreateTextViewL(); + iRichTextEditor->CreateScrollBarFrameL()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto); + iRichTextEditor->SetObserver(this); + + HandleZoomEventL(EEventZoomDefault); + PopulateCategoryListL(); + + iHelpModel.SetZoomFactors(EHlpZoomStateSmall, 750); + iHelpModel.SetZoomFactors(EHlpZoomStateMedium, 1000); + iHelpModel.SetZoomFactors(EHlpZoomStateLarge, 1250); + } + + +// +// NEW +// +void CHlpView::PopulateCategoryListL() + { + // First get a category listing, then get the list of topics + // for each specified category. + // Get and print the category listing + CDesCArrayFlat* array = new(ELeave) CDesCArrayFlat(5); + CleanupStack::PushL(array); + iHelpModel.CategoryListL(array); + + if (!array->Count()) + User::Leave(KErrArgument); // ?? + + iHelpCategories->SetArrayExternalOwnership(EFalse); + iHelpCategories->SetArrayL(array); + iHelpCategories->SetArrayExternalOwnership(EFalse); + iHelpCategories->SetCurrentItem(0); + + PopulateTopicListL(iHelpCategories->Array()->MdcaPoint(iHelpCategories->CurrentItem())); + + CleanupStack::Pop(); + } + +void CHlpView::PopulateTopicListL(const TDesC& aTopic) + { + iHelpModel.SearchL(ETopicListForCategory, aTopic); + + CHlpList* list = CHlpList::NewLC(); + iHelpModel.LoadListL(list); + iHelpTopicsForCategory->SetArrayL(list); // Derrives from MDesCArray so we can do this + delete iCurrentTopics; + iCurrentTopics = list; + iHelpTopicsForCategory->SetArrayExternalOwnership(ETrue); // owned by this class + CleanupStack::Pop(); // list + + if (list->MdcaCount()) + { + UpdateEdwinL(*list->Item(0)); + iHelpTopicsForCategory->SetCurrentItem(0); + iHelpTopicsForCategory->DrawNow(); + } + } + + +void CHlpView::UpdateEdwinL(const CHlpItem& aItem) +// +// Extract the rich text from the help file and display it in the +// read only edit window. +// + { + // Search for a specific topic. + iHelpModel.TopicSearchL(aItem); + if (iLastResponseFromHelpModel == ETopicAvailable) + { + CHlpTopic* topic = CHlpTopic::NewLC(); + iHelpModel.LoadTopicL(topic); + iRichTextEditor->SetDocumentContentL(*topic->TopicText(), CEikEdwin::EUseText); + iRichTextEditor->NotifyNewFormatL(); + iRichTextEditor->TextView()->SetViewLineAtTopL(1); + iRichTextEditor->UpdateScrollBarsL(); + delete iLastTopic; + iLastTopic = topic; + CleanupStack::Pop(); // topic + } + else + iEikonEnv->InfoMsg(R_HELPVIEW_TEXT_NO_TOPIC_FOR_ID); + } + +// +// FROM MZoomableControl +// + +void CHlpView::HandleZoomEventL(TZoomEvent aEvent) + { + switch(aEvent) + { + case EEventZoomIn: + if (++iCurrentZoom>=KNumberOfZoomStates) + iCurrentZoom = 0; + break; + case EEventZoomOut: + if (--iCurrentZoom < 0) + iCurrentZoom = KNumberOfZoomStates-1; + break; + case EEventZoomDefault: + iCurrentZoom = 1; + break; + default: + User::Leave(KErrNotSupported); + } + + // Select bitmap zoom size in the 'hlpmodel', according to the value of 'iCurrentZoom' + switch (iCurrentZoom) + { + case 0: + iHelpModel.SetZoomSizeL(EHlpZoomStateSmall); + break; + default: + case 1: + iHelpModel.SetZoomSizeL(EHlpZoomStateMedium); + break; + case 2: + iHelpModel.SetZoomSizeL(EHlpZoomStateLarge); + break; + } + + + iZoom.SetZoomFactor(ZoomForIndex(iCurrentZoom)); + iRichTextEditor->NotifyNewFormatL(); + iRichTextEditor->UpdateScrollBarsL(); + iRichTextEditor->DrawNow(); + } + +TInt CHlpView::ZoomForIndex(TInt aIndex) + { + switch(aIndex) + { + case 0: + return EZoomStateOne; + default: + case 1: + return EZoomStateTwo; + case 2: + return EZoomStateThree; + } + } + +// +// FROM CCoeControl +// + +void CHlpView::SizeChanged() + { + const TInt KKludgeFactor = 4; + + TRect rect(Position(), Rect().Size()); + TSize choiceListSize = iHelpCategories->MinimumSize() + TSize(0, KKludgeFactor); + + TPoint topLeft(rect.iTl); + + iHelpCategories->SetExtent(topLeft, TSize(rect.Width()/2, choiceListSize.iHeight)); + iHelpTopicsForCategory->SetExtent(TPoint(rect.Size().iWidth/2,topLeft.iY), TSize(rect.Size().iWidth/2, choiceListSize.iHeight)); + iRichTextEditor->SetRect(TRect(TPoint(topLeft.iX, choiceListSize.iHeight), rect.iBr)); + } + +TInt CHlpView::CountComponentControls() const + { + return 3; + } + +CCoeControl* CHlpView::ComponentControl(TInt aIndex) const + { + switch (aIndex) + { + default: + case 0: + return iHelpCategories; + case 1: + return iHelpTopicsForCategory; + case 2: + return iRichTextEditor; + } + } + +TKeyResponse CHlpView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) + { + return iRichTextEditor->OfferKeyEventL(aKeyEvent, aType); + } + +// +// FROM MCoeControlObserver +// +void CHlpView::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType) + { + if (aEventType == EEventRequestFocus) + { + if (iFocusedControl) + { + iFocusedControl->PrepareForFocusLossL(); + iFocusedControl->SetFocus(EFalse); + } + iFocusedControl = aControl; + iFocusedControl->SetFocus(ETrue); + } + else if (aControl == iHelpCategories && aEventType == EEventStateChanged) + { + // Update the list of topics available for this category + PopulateTopicListL(iHelpCategories->Array()->MdcaPoint(iHelpCategories->CurrentItem())); + } + else if (aControl == iHelpTopicsForCategory && aEventType == EEventStateChanged) + { + // Update the edwin contents + UpdateEdwinL(*iCurrentTopics->Item(iHelpTopicsForCategory->CurrentItem())); + } + } + +// +// FROM MHlpModelObserver +// +void CHlpView::HandleModelEventL(TInt aEvent) + { + iLastResponseFromHelpModel = aEvent; + } + + + + + + + +// +// ----> CHlpMainView (source) +// + +CHlpMainView::CHlpMainView(CHlpAppUi& aAppUi, CHlpModel& aModel) +: iAppUi(aAppUi), iModel(aModel) + { + } + +CHlpMainView::~CHlpMainView() + { + delete iSearchResults; + delete iSearchPrompt; + delete iView; + } + +void CHlpMainView::ConstructL() + { + CreateWindowL(); + + iView = new(ELeave) CHlpView(iAppUi, iModel); + iView->SetContainerWindowL(*this); + iView->ConstructL(); + iAppUi.SetZoomHandler(iView); + + iSearchPrompt = new(ELeave) CHlpSearchPrompt(); + iSearchPrompt->ConstructL(*this); + iSearchPrompt->SetObserver(this); + iSearchPrompt->MakeVisible(EFalse); + + iSearchResults = new(ELeave) CHlpListBox(); + iSearchResults->ConstructL(*this); + iSearchResults->SetObserver(this); + iSearchResults->MakeVisible(EFalse); + + iView->SetFocus(ETrue); + + ActivateL(); + } + +// +// ACCESS +// + +TBool CHlpMainView::IsSearchPromptVisible() const + { + return iSearchPrompt->IsVisible(); + } + +TBool CHlpMainView::IsSearchResultVisible() const + { + return iSearchResults->IsVisible(); + } + +void CHlpMainView::ShowSearchPrompt(TBool aShow) + { + iSearchPrompt->MakeVisible(aShow); + } + +void CHlpMainView::MakeResultsVisible(TBool aVisible) + { + TRect rect(Rect()); + TSize resultsSize = iSearchResults->Size(); + + if (!aVisible) + { + // Make the main view rect 'full size' again + iView->SetRect(rect); + iSearchResults->ListBox()->SetFocus(EFalse); + iView->SetFocus(ETrue); + } + else + { + rect.iBr.iX -= resultsSize.iWidth; + iView->SetRect(rect); + iView->SetFocus(EFalse); + iSearchResults->ListBox()->SetFocus(ETrue); + } + iSearchResults->MakeVisible(aVisible); + DrawNow(); + } + +// +// FROM CCoeControl +// + +void CHlpMainView::SizeChanged() + { + iView->SetRect(Rect()); + + TRect rect(Rect()); + TSize KScreenSize(iCoeEnv->ScreenDevice()->SizeInPixels()); + + // Work out the size of the search prompt minus the inset for the left and right + // hand size. Kludge this a bit to make sure we allow for the size of any scrollbar + // (hence the *6 rather than the expected *2) + TSize searchPromptSize(KScreenSize.iWidth - (4*KSizeSearchPromptIndent), KSizeSearchPromptHeight); + iSearchPrompt->SetExtent(TPoint(KSizeSearchPromptIndent, rect.iBr.iY - KSizeSearchPromptHeight - KSizeSearchPromptIndent), searchPromptSize); + + TRect resultsRect(rect); + resultsRect.iTl.iX = resultsRect.iBr.iX - KResultsViewWidth; + iSearchResults->SetRect(resultsRect); + } + +TInt CHlpMainView::CountComponentControls() const + { + return 3; + } + +CCoeControl* CHlpMainView::ComponentControl(TInt aIndex) const + { + switch (aIndex) + { + default: + case 0: + return iView; + case 1: + return iSearchPrompt; + case 2: + return iSearchResults; + } + } + +TKeyResponse CHlpMainView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) + { + // Send cursors to the rich text edwin (kludgy) + if (aKeyEvent.iCode >= EKeyPageUp && aKeyEvent.iCode <= EKeyDownArrow) + { + if (iView->IsFocused()) + return iView->OfferKeyEventL(aKeyEvent, aType); + else + return iSearchResults->OfferKeyEventL(aKeyEvent, aType); + } + else + { + if (!iSearchPrompt->IsVisible() && aType == EEventKey) + { + iSearchPrompt->MakeVisible(ETrue); + iSearchPrompt->SetFocus(ETrue); + } + return iSearchPrompt->OfferKeyEventL(aKeyEvent, aType); + } + } + +// +// FROM MCoeControlObserver +// + +void CHlpMainView::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType) + { + if (aControl == iSearchPrompt && aEventType == EEventStateChanged) + { + // Action the search + DoSearchL(); + + // Update the list of topics available for this category + iSearchPrompt->MakeVisible(EFalse); + + // Reset the search prompt + iSearchPrompt->ResetSearchL(); + } + else if (aControl == iSearchResults && aEventType == EEventRequestExit) + { + // Finished with results + MakeResultsVisible(EFalse); + } + else if (aControl == iSearchResults && aEventType == EEventStateChanged) + { + // Display the selected topic that the user searched for + iView->UpdateEdwinL(iSearchResults->HelpItemL()); + } + } + +// +// FROM MHlpModelObserver +// + +void CHlpMainView::HandleModelEventL(TInt aEvent) + { + iLastHelpModelResponse = aEvent; + + if (aEvent == ESearchListAvailable || aEvent == ESearchListNoneFound) + { + iEikonEnv->BusyMsgCancel(); + + // This is a special case which is initiated by full text searching... + iModel.SetObserver(iView); + + // Now populate the search results listbox. + if (iLastHelpModelResponse == ESearchListNoneFound) + { + iEikonEnv->InfoMsg(R_HELPVIEW_TEXT_NO_SEARCH_RESULTS); + return; + } + + // Get a topic list (because some were found) + CHlpList* list = CHlpList::NewL(); + iModel.LoadListL(list); + iSearchResults->PopulateListBoxL(list); // takes ownership + MakeResultsVisible(ETrue); // show results + } + } + +// +// INTERNAL +// + +void CHlpMainView::DoSearchL() + { + HBufC* searchSpec = iSearchPrompt->SearchTextLC(); + __ASSERT_DEBUG(searchSpec, Panic(EHlpViewPanicNoSearchSpec)); + + // Set this class as the observer (kludge) + iModel.SetObserver(this); + + // Request a search + iModel.SearchL(EFullTextSearch, searchSpec); // Asynch... + iEikonEnv->BusyMsgL(R_HELPVIEW_TEXT_SEARCHING, 0); + + CleanupStack::PopAndDestroy(); // searchSpec + } + + + +