diff -r 4ea6f81c838a -r 0e9bb658ef58 mulwidgets/alfviewwidget/src/alfviewwidget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mulwidgets/alfviewwidget/src/alfviewwidget.cpp Wed Sep 01 12:23:18 2010 +0100 @@ -0,0 +1,738 @@ +/* +* Copyright (c) 2007 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: The implementation for presentation elements. +* +*/ + + + +#include "alfviewwidget.h" +#include "alfviewcontrol.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "alf/alfwidget.h" +#include +#include +#include +#include +#include +#include + +#include + +#include "alfviewwidgetexception.h" + +#include +#include +#include + +namespace Alf + { + +/** + * Observer class to observe changes in the relative order of control groups in associated + * roster object and to notify view object about possible view activation (view coming + * top-most) and deactivation. + * + * This class is a Symbian - specific implementation class. + */ +class AlfViewWidgetZOrderChangedObserver : public MAlfControlGroupOrderChangedObserver + { + public: + + /** + * Default constructor + */ + AlfViewWidgetZOrderChangedObserver(CAlfDisplay& aDisplay, AlfViewWidget& aView) + : iDisplay(aDisplay), iView(aView) + { + aDisplay.Roster().AddControlGroupOrderChangedObserverL(*this); + } + + /** + * Default destructor + */ + ~AlfViewWidgetZOrderChangedObserver() + { + int index = CAlfEnv::Static()->FindDisplayIndex(iDisplay); + if(index != -1) + { + iDisplay.Roster().RemoveControlGroupOrderChangedObserver(*this); + } + } + + /** + * Callback method called by roster when control group order changes. + */ + void NotifyControlGroupOrderChanged() + { + // If the associated view is on top, notify it about view activation + // and the view below it about view deactivation. + if(iView.getViewStackPosition() == 0) + { + AlfViewWidget* viewBelow = getViewFromStack(1); + if(viewBelow) + { + viewBelow->notifyViewActivated(false); + } + + iView.notifyViewActivated(true); + } + } + + private: + + /** + * Utility method to return view from specified z-position on the view stack. + * Returns 0 if the index is out of bounds. + */ + AlfViewWidget* getViewFromStack(int index) + { + int zPos = 0; + + // Iterate through the control groups in the roster + for(int i = (iDisplay.Roster().Count() - 1); i >= 0; --i) + { + CAlfControlGroup& group = iDisplay.Roster().ControlGroup(i); + + // Investigate whether this is a control group of a view widget + if(group.Count() > 0) + { + CAlfControl& control = group.Control(0); + CAlfViewControl* viewControl = dynamic_cast(&control); + if(viewControl != 0) + { + // View widget found from the roster + if(zPos == index) + { + return &viewControl->viewWidget(); + } + zPos++; + } + } + } + + return 0; + } + + /** Roster to which this callback object is added to. */ + CAlfDisplay& iDisplay; + + /** View widget that this observer notifies. */ + AlfViewWidget& iView; + + }; + + +AlfViewWidget::AlfViewWidget(const char* aWidgetName, int aControlGroupId, CAlfEnv& aEnv, + CAlfDisplay& aDisplay, DuiNode* aNode, const char *aFilePath) : + mEnv(&aEnv), mDisplay(&aDisplay), mControlGroup(0), + mZOrderChangedObserver(0), + mControlGroupResourceId(aControlGroupId), + mShown(false), mControlPaneEnabled(true), mStatusPaneEnabled(true), + mSkinEnabled(false), mSkinId(KAknsIIDQsnBgScreen), mHasFocus(false) + { + mChildWidgetName.setAutoDelete(true); + mWidget.reset(new (EMM) AlfWidget(aWidgetName)); + + TRAPD(err,aEnv.AddActionObserverL(this)); + if(err!=KErrNone) + { + ALF_THROW(AlfViewWidgetException, err, + "CAlfEnv::AddActionObserverL() - failed."); + } + + // By default, we use ClientRect() as the area of the view widget + TRect rect = ((CAknAppUi*)CEikonEnv::Static()->AppUi())->ClientRect(); + mDisplayRect = TRect(rect); + + mZOrderChangedObserver.reset(new (EMM) AlfViewWidgetZOrderChangedObserver(aDisplay, *this)); + + constructDefault(aEnv); + + } + +AlfViewWidget::~AlfViewWidget() + { + //If the view widget is deleted before the AlfEnv is deleted, + //the control group needs to be destroyed. + if(mEnv->FindControlGroup(mControlGroupResourceId)) + { + mEnv->DeleteControlGroup(mControlGroup->ResourceId()); + } + + mEnv->RemoveActionObserver(this); + + IAlfWidget* childWidget = NULL; + + IAlfWidgetFactory& factory = AlfWidgetEnvExtension::widgetFactory(*(CAlfEnv::Static())); + for(int i =0 ;i < mChildWidgetName.count();i++) + { + childWidget = factory.findWidget(mChildWidgetName.at(i)->getUtf8()); + if(childWidget) + { + factory.destroyWidget(childWidget); + childWidget = NULL; + } + } + mChildWidgetName.clear(); + } + +CAlfWidgetControl* AlfViewWidget::control() const + { + return mWidget->control(); + } + +IAlfContainerWidget* AlfViewWidget::parent() const + { + return mWidget->parent(); + } + +void AlfViewWidget::setControl(CAlfWidgetControl* aControl, bool aDeletePreviousControl) + { + CAlfWidgetControl* prevControl = mWidget->control(); + + // Set new control to the widget implementation. + // Never delete the previous control in this phase, so that we can + // still remove it from the control group if this call is succesfull. + mWidget->setControl(aControl, false); + + // Remove the previous control from control group. + if(prevControl != 0) + { + assert(prevControl->ControlGroup() == mControlGroup); + if(aDeletePreviousControl) + { + mControlGroup->Remove(prevControl); + delete prevControl; + } + } + + // Append the new control into the control group. + if(aControl) + { + TRAPD(err, mControlGroup->AppendL(aControl)); + if(err != KErrNone) + { + mWidget->setControl(0, false); + ALF_THROW(AlfViewWidgetException, err, "CAlfControlGroup::AppendL() - failed."); + } + } + } + +void AlfViewWidget::setChildNameToDelete( UString aChildName ) + { + UString* childName = new(EMM)UString(aChildName.getUtf8()); + mChildWidgetName.resize(mChildWidgetName.count()+1); + mChildWidgetName.insert(mChildWidgetName.count(),childName); + } + +IAlfModel* AlfViewWidget::model() + { + return 0; + } + +void AlfViewWidget::setModel(IAlfModel* /*aModel*/, bool /*aTakeOwnership*/) + { + //Do nothing. + } + +const char* AlfViewWidget::widgetName() const + { + return mWidget->widgetName(); + } + +void AlfViewWidget::setChildFocus(bool /*aFocus*/) + { + + } + +//--------------------------------------------------------------------------- +// Creates the presentation for the widget from XML. Destroys any existing +// presentation. +//--------------------------------------------------------------------------- +// +void AlfViewWidget::setPresentation (const char* aFilePath) + { + if(mWidget.get()) + { + mWidget->setPresentation(aFilePath); + } + } + +int AlfViewWidget::widgetCount() const + { + return mWidget->widgetCount(); + } + +void AlfViewWidget::addWidget(IAlfWidget& aWidget) + { + mWidget->addWidget(aWidget); + } + +IAlfWidget* AlfViewWidget::getWidget(int aIndex) const + { + return mWidget->getWidget(aIndex); + } + +int AlfViewWidget::getWidgetIndex(IAlfWidget& aWidget) const + { + return mWidget->getWidgetIndex(aWidget); + } + +void AlfViewWidget::removeWidget(int aIndex) + { + mWidget->removeWidget(aIndex); + } + +void AlfViewWidget::applyLayout(IAlfLayoutManager& aLayout) + { + mWidget->applyLayout(aLayout); + } + +IAlfInterfaceBase* AlfViewWidget::makeInterface(const IfId& aType) + { + // Type cast to IAlfWidget + if(!strcmp(aType.mImplementationId, IAlfWidget::type().mImplementationId)) + { + return static_cast(this); + } + + // Type cast to IAlfContainerWidget + if (!strcmp(aType.mImplementationId, IAlfContainerWidget::type().mImplementationId)) + { + return static_cast(this); + } + + // Type cast to IAlfViewWidget + if(!strcmp(aType.mImplementationId, IAlfViewWidget::type().mImplementationId)) + { + return static_cast(this); + } + + return mWidget->makeInterface(aType); + } + +void AlfViewWidget::notifyViewActivated(bool aIsActivated) + { + if(aIsActivated) + { + // Update control pane, status pane and background according to state of the view. + updateStatusPane(); + updateControlPane(); + // When a view is activated, it sets the size of the display to full screen + // This is done so that the view widget gets pointer events in the entire screen + TRect screenRect(TPoint(0,0), TSize(AlfUtil::ScreenSize())); + control()->Env().PrimaryDisplay().SetVisibleArea(screenRect); + setRect(mDisplayRect); + + // Restore the focus here + IAlfWidget* focusedWidget = 0; + focusedWidget = AlfWidgetEnvExtension::widgetFactory(*mEnv).findWidget(mFocusedChildWidgetID.c_str()); + if(focusedWidget == 0 && widgetCount() > 0) + { + focusedWidget = getWidget(0); + } + if(!mHasFocus) + { + mHasFocus = true; + if(focusedWidget != 0) + { + focusedWidget->control()->AcquireFocus(); + } + else + { + control()->AcquireFocus(); + } + } + } + else + { + // Cache and release the focus here + // FocusedControl function is not exported from the toolkit + CAlfControl* focusedCtrl = focusedControl(); + if(focusedCtrl) + { + CAlfWidgetControl* focusedWidgetControl = dynamic_cast(focusedCtrl); + if(focusedWidgetControl != 0) + { + mFocusedChildWidgetID = focusedWidgetControl->widget()->widgetName(); + } + focusedCtrl->RelinquishFocus(); + } + mHasFocus = false; + } + } + +CAlfControl* AlfViewWidget::focusedControl() + { + CAlfControl* focusedconnection = control(); + + // Iterate through the focused connections and return the control + // that has the focus. + while(focusedconnection != 0) + { + if(focusedconnection->Focus()) + { + // There should be no connections leading outside from the control + // group of the view. + assert(focusedconnection->ControlGroup() == mControlGroup); + return focusedconnection; + } + focusedconnection = focusedconnection->FocusedConnection(); + } + + return 0; + } + +void AlfViewWidget::show(bool aShow) + { + mShown = aShow; + if (aShow) + { + TRAPD(err, mDisplay->Roster().ShowL(*mControlGroup)); + if (err != KErrNone) + { + ALF_THROW(AlfViewWidgetException, err, "AlfViewWidget::show(): View Widget Show failed"); + } + } + else + { + // Notify this view that it is being deactivated. + notifyViewActivated(false); + + // Hide the control group + mDisplay->Roster().Hide(*mControlGroup); + } + } + +void AlfViewWidget::acceptEvents(bool aAccept) + { + assert(mControlGroup); + mControlGroup->SetAcceptInput(aAccept); + } + +void AlfViewWidget::enableStatusPane(bool aEnable) + { + if(aEnable != mStatusPaneEnabled) + { + mStatusPaneEnabled = aEnable; + + // Update status pane and background image state if this view is active. + if(getViewStackPosition() == 0) + { + updateStatusPane(); + } + } + } + +void AlfViewWidget::enableControlPane(bool aEnable) + { + if (aEnable != mControlPaneEnabled) + { + mControlPaneEnabled=aEnable; + + // Update control pane and background image state if this view is active. + if(getViewStackPosition() == 0) + { + updateControlPane(); + } + } + } + +void AlfViewWidget::useSkinBackground(bool aSkinBackground) + { + if(mSkinEnabled != aSkinBackground) + { + mSkinEnabled = aSkinBackground; + updateBackGroundImage(); + } + + } + +void AlfViewWidget::setSkinBackground(TAknsItemID aSkinID) + { + mSkinEnabled = true; + mSkinId = aSkinID; + updateBackGroundImage(); + } + +bool AlfViewWidget::shown() + { + return mShown; + } + +int AlfViewWidget::getViewStackPosition() const + { + int ret = 0; + const CAlfRoster& roster = mDisplay->Roster(); + + // Iterate through the control groups in the roster + for(int i = (roster.Count() - 1); i >= 0; --i) + { + CAlfControlGroup& group = roster.ControlGroup(i); + + // Compare the control group with this view's control group + if(mControlGroup == &group) + { + return ret; + } + + // Investigate whether this is a control group of a view widget + if(group.Count() > 0) + { + CAlfControl& control = group.Control(0); + if(dynamic_cast(&control) != 0) + { + ret++; + } + } + } + + return -1; + } + +bool AlfViewWidget::eventsAccepted() + { + assert(mControlGroup); + return mControlGroup->AcceptInput(); + } + +bool AlfViewWidget::statusPaneEnabled() + { + return mStatusPaneEnabled; + } + +bool AlfViewWidget::controlPaneEnabled() + { + return mControlPaneEnabled; + } + +bool AlfViewWidget::usingSkinBackground() + { + return mSkinEnabled; + } + +TAknsItemID AlfViewWidget::skinBackground() + { + return mSkinId; + } + +// --------------------------------------------------------------------------- +// Constructs components from node +// --------------------------------------------------------------------------- +// +void AlfViewWidget::constructComponentsFromNode(CAlfEnv& aEnv) + { + constructDefault(aEnv, false); + + //check, if the layoutmanager is already set. + IAlfLayoutManager* layoutManager = + IAlfInterfaceBase::makeInterface(control()); + if (!layoutManager) + { + setDefaultLayoutManager(); + } + } + +//--------------------------------------------------------------------------- +// Constructs widget using the presentation XML. Other widget parts +// are default. +//--------------------------------------------------------------------------- +// +void AlfViewWidget::constructFromPresentationXML(CAlfEnv& aEnv, const char* /**aFilePath*/) + { + constructDefault(aEnv, true); + } + +// --------------------------------------------------------------------------- +// Imperative construction +// --------------------------------------------------------------------------- +// +void AlfViewWidget::constructDefault(CAlfEnv& aEnv, bool aCreateLM) + { + TRAPD( err, + mControlGroup = &aEnv.NewControlGroupL(mControlGroupResourceId); + ); + + if(err != KErrNone) + { + if (err == KErrAlreadyExists) + { + ALF_THROW(AlfViewWidgetException, + EControlGroupAlreadyExists, "AlfViewWidget::AlfViewWidget() - Tried to create a control group with already existing ID."); + } + else + { + ALF_THROW(AlfViewWidgetException, + err, "AlfViewWidget::AlfViewWidget() - Control group creation failed."); + } + } + + // Create control for the view widget + auto_ptr control( new (EMM) CAlfViewControl(aEnv, *this) ); + setControl(control.get()); + control.release(); + + if (aCreateLM) + { + setDefaultLayoutManager(); + } + } + +// --------------------------------------------------------------------------- +// Imperative createDefaultLayoutManager +// --------------------------------------------------------------------------- +// +void AlfViewWidget::setDefaultLayoutManager() + { + // A root layout covering the entire display is created to grab all pointer events in the screen + // Note that this layout is just dummy and does not do any actual layouting + CAlfControl* ctrl = (CAlfControl*)control(); + CAlfLayout* fullDisplayLayout = CAlfLayout::AddNewL(*ctrl); + + // Default layout manager provided by the view widget + auto_ptr layoutManager(new (EMM) AlfAnchorLayoutManager()); + this->applyLayout(*layoutManager.get()); + + layoutManager.release(); + } + +void AlfViewWidget::updateStatusPane() + { + /*CEikStatusPane *sp = CEikonEnv::Static()->AppUiFactory()->StatusPane(); + if(sp) + { + sp->MakeVisible(mStatusPaneEnabled); +// mDisplay->SetVisibleArea(CEikonEnv::Static()->AppUiFactory()->ClientRect()); + }*/ + } + +void AlfViewWidget::updateControlPane() + { + /*CEikButtonGroupContainer* cba= CEikonEnv::Static()->AppUiFactory()->Cba(); + if(cba) + { + cba->MakeVisible(mControlPaneEnabled); +// mDisplay->SetVisibleArea(CEikonEnv::Static()->AppUiFactory()->ClientRect()); + }*/ + + } + +void AlfViewWidget::updateBackGroundImage() + { + TAknsItemID skinId=KAknsIIDQsnBgScreen; + // Do background related stuff only if the view is showing + if(mSkinEnabled ) + { + skinId=mSkinId; + } + if(mShown) + { + TAlfDisplayBackgroundItem bgItem(mDisplay->VisibleArea(),skinId); + RArray bgItemArray; + bgItemArray.Append(bgItem); + TRAPD(err,mDisplay->SetBackgroundItemsL(bgItemArray)); + if(err!=KErrNone) + { + ALF_THROW(AlfViewWidgetException, err,"Skin Background could not be set"); + } + bgItemArray.Reset(); + } + + } + + +void AlfViewWidget::HandleActionL(const TAlfActionCommand& aActionCommand) + { + if(KAlfActionIdDeviceLayoutChanged == aActionCommand.Id()) + { + TAlfCustomEventCommand command(KAlfActionIdDeviceLayoutChanged); + control()->Env().Send(command,0); + if(mShown && getViewStackPosition() == 0) + { + TRect screenRect(TPoint(0,0), TSize(AlfUtil::ScreenSize())); + + // SetVisibleArea() only have an effect if the application is on foreground! + control()->Env().PrimaryDisplay().SetVisibleArea(screenRect); + } + + } + + else if(KAlfActionIdForegroundGained == aActionCommand.Id()) + { + + TRect screenRect(TPoint(0,0), TSize(AlfUtil::ScreenSize())); + + // SetVisibleArea() only have an effect if the application is on foreground! + + control()->Env().PrimaryDisplay().SetVisibleArea(screenRect); + + + } + + } + +TBool AlfViewWidget::OfferEventL(const TAlfEvent& /*aEvent*/) + { +/* if(aEvent.IsCustomEvent() && aEvent.CustomParameter() == KAlfActionIdDeviceLayoutChanged) + { + if(mShown && getViewStackPosition() == 0) + { + //need to do this to overwrite the displayrect done by menuApp + // TRect rect= control()->Env().PrimaryDisplay().VisibleArea(); + // control()->Env().PrimaryDisplay().SetVisibleArea(mDisplayRect); + updateBackGroundImage(); + } + return ETrue; + } + */ return EFalse; + } + +void AlfViewWidget::setRect(const TRect& aRect) + { + mDisplayRect = aRect; + + IAlfLayoutManager* layoutManager = IAlfInterfaceBase::makeInterface(control()); + if (layoutManager) + { + // Set the area of the root layout of the view widget to the one specified + CAlfLayout& layout = layoutManager->getLayout(); + layout.SetFlag(EAlfVisualFlagManualLayout); + TAlfRealRect rect(mDisplayRect); + layout.SetRect(rect); + } + + TRect visibleRect = control()->Env().PrimaryDisplay().VisibleArea(); + TRect screenRect(TPoint(0,0), TSize(AlfUtil::ScreenSize())); + + if(visibleRect != screenRect && getViewStackPosition() == 0) + { + // the display area is required to be full screen, for the pointer grab to work + // check here whether the display area is full screen. If not, set it to full screen + control()->Env().PrimaryDisplay().SetVisibleArea(screenRect); + } + } + + } //Alf + + +//End of file +