diff -r 5f0182e07bfb -r 5456b4e8b3a8 idlehomescreen/xmluirendering/uiengine/src/xnwidgetextensionadapter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/idlehomescreen/xmluirendering/uiengine/src/xnwidgetextensionadapter.cpp Wed Sep 01 12:32:46 2010 +0100 @@ -0,0 +1,738 @@ +/* +* Copyright (c) 2008 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: +* +*/ + +// System includes +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef RD_TACTILE_FEEDBACK +#include +#endif // RD_TACTILE_FEEDBACK + +// User includes +#include "xnwidgetextensionadapter.h" +#include "xncontroladapter.h" +#include "xncomponentnodeimpl.h" +#include "xncomponent.h" +#include "xnuiengine.h" + +#include "xnnode.h" +#include "xnnodepluginif.h" +#include "xnviewnodeimpl.h" +#include "xnnodepluginif.h" +#include "xndomdocument.h" +#include "xnproperty.h" +#include "xnodt.h" +#include "xntype.h" +#include "xndomnode.h" +#include "xndomstringpool.h" + +#include "xnappuiadapter.h" +#include "xnviewmanager.h" +#include "xnviewdata.h" +#include "xnplugindata.h" + +// Constants +_LIT8( KPopup, "popup" ); +_LIT8( KPositionHint, "_s60-position-hint" ); +_LIT8( KWidgetNodeName, "widget" ); +_LIT8( KParentIdName, "parentid" ); +_LIT8( KDisplay, "display" ); +_LIT8( KNone, "none" ); + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::NewL +// Two-phased constructor. Can leave. +// ----------------------------------------------------------------------------- +// +CXnWidgetExtensionAdapter* CXnWidgetExtensionAdapter::NewL( + CXnNodePluginIf& aNode ) + { + CXnWidgetExtensionAdapter* self = + new ( ELeave ) CXnWidgetExtensionAdapter( aNode ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::~CXnWidgetExtensionAdapter +// Destructor. +// ----------------------------------------------------------------------------- +// +CXnWidgetExtensionAdapter::~CXnWidgetExtensionAdapter() + { + if ( iAppUiAdapter ) + { + iAppUiAdapter->UiStateListener().RemoveObserver( + *( static_cast< MXnUiStateObserver* >( this ) ) ); + iAppUiAdapter->UiStateListener().RemoveObserver( + *( static_cast< MXnUiResourceChangeObserver* >( this ) ) ); + } + GfxTransEffect::Deregister( this ); + } +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::HandleScreenDeviceChangedL +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::HandleScreenDeviceChangedL() + { + if( IsVisible() ) + { + CCoeControl::MakeVisible( EFalse ); + } + CXnControlAdapter::HandleScreenDeviceChangedL(); + + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::CXnWidgetExtensionAdapter +// C++ default constructor. Must not leave. +// ----------------------------------------------------------------------------- +// +CXnWidgetExtensionAdapter::CXnWidgetExtensionAdapter( CXnNodePluginIf& aNode ) + : iPositionHint( AknLayoutUtils::LayoutMirrored() ? EAboveRight : EAboveLeft ), + iNode( aNode ) + { + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::ConstructL +// 2nd phase constructor. Can leave. +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::ConstructL() + { + iAppUiAdapter = static_cast< CXnAppUiAdapter* >( iAvkonAppUi ); + + CreateWindowL(); + + Window().SetRequiredDisplayMode( EColor16MA ); + + // this adapter handles both widgetextension and popup nodes + // we have to decide which one of them is the recent one + + CXnType* typeInfo = iNode.Node().Type(); + User::LeaveIfNull( typeInfo ); + const TDesC8& type = typeInfo->Type(); + + iPermanent = EFalse; + + if ( type == KPopup ) + { + iPopup = ETrue; + CXnProperty* prop( iNode.Node().GetPropertyL( + XnPropertyNames::popup::KPopupType ) ); + + if ( prop && prop->StringValue() == + XnPropertyNames::popup::popuptype::KPermanent ) + { + iPermanent = ETrue; + } + } + + if ( Window().SetTransparencyAlphaChannel() == KErrNone ) + { + Window().SetBackgroundColor( ~0 ); + } + + iUiEngine = iNode.Node().UiEngine(); + CXnControlAdapter::ConstructL( iNode ); + + EnableDragEvents(); + + GfxTransEffect::Register( this, KGfxPreviewPopupControlUid ); + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::MakeVisible +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::MakeVisible( TBool aVisible ) + { + if ( IsVisible() == aVisible ) + { + return; + } + + CXnPluginData* plugin( + iAppUiAdapter->ViewManager().ActiveViewData().Plugin( &iNode.Node() ) ); + + if ( !plugin ) + { + return; + } + + SetPointerCapture( aVisible ); + + plugin->SetIsDisplayingPopup( aVisible, &iNode.Node() ); + + if ( !iPopup ) + { + DrawableWindow()->FadeBehind( aVisible ); + } + + if ( !iPermanent ) + { + if ( aVisible ) + { + iAppUiAdapter->UiStateListener().AddObserver( + *( static_cast< MXnUiStateObserver* >( this ) ) ); + iAppUiAdapter->UiStateListener().AddObserver( + *( static_cast< MXnUiResourceChangeObserver* >( this ) ) ); + } + else + { + iAppUiAdapter->UiStateListener().RemoveObserver( + *( static_cast< MXnUiStateObserver* >( this ) ) ); + iAppUiAdapter->UiStateListener().RemoveObserver( + *( static_cast< MXnUiResourceChangeObserver* >( this ) ) ); + } + } + + if ( aVisible && iPopup ) + { + ChangePopupPosition(); + } + + TBool effectStarted = EFalse; + if ( iAppUiAdapter->IsForeground() ) + { + if ( aVisible ) + { + GfxTransEffect::Begin( this, KGfxControlAppearAction ); + } + else + { + GfxTransEffect::Begin( this, KGfxControlDisappearAction ); + } + effectStarted = ETrue; + } + + CCoeControl::MakeVisible( aVisible ); + + if ( effectStarted ) + { + GfxTransEffect::SetDemarcation( this, iPosition ); + GfxTransEffect::End( this ); + } + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::HandlePointerEventL +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::HandlePointerEventL( + const TPointerEvent& aPointerEvent ) + { + + // in case of popup, we have to make sure that + // it will be closed after tapping outside of the + // area of itself and its parent + if ( iPopup ) + { + // check if the tap was inside of popup + TRect popupRect( Rect() ); + popupRect.Move( Position() ); + + TBool isInPopupWindow( popupRect.Contains( + aPointerEvent.iParentPosition ) ); + + if ( !isInPopupWindow ) + { + // if tap was outside of window, check if tap was + // inside of the parrent + CXnProperty* parentIdProp( iNode.Node().GetPropertyL( + KParentIdName ) ); + + if ( parentIdProp ) + { + const TDesC8& id( parentIdProp->StringValue() ); + + CXnNode* parent( + iUiEngine->FindNodeByIdL( id, iNode.Node().Namespace() ) ); + + + if ( parent ) + { + TRect clientRect( iAppUiAdapter->ClientRect() ); + + TRect parentRect( parent->Rect() ); + parentRect.Move( clientRect.iTl ); + + if ( !parentRect.Contains( aPointerEvent.iParentPosition ) ) + { + // tap was neither in popup nor in its parent - + // we can close it + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { +#ifdef RD_TACTILE_FEEDBACK + MTouchFeedback* fb( MTouchFeedback::Instance() ); + + if ( fb ) + { + fb->InstantFeedback( ETouchFeedbackBasic ); + } +#endif + HidePopupL(); + return; + } + } + else + { + // tap was made inside of popup parent + // we pass the event to it after + // recalculating the taping point + TPointerEvent newPointerEvent; + + newPointerEvent.Copy( aPointerEvent ); + + newPointerEvent.iPosition = TPoint( + aPointerEvent.iParentPosition - clientRect.iTl ); + + parent->Control()->HandlePointerEventL( newPointerEvent ); + } + } + } + else + { +#ifdef RD_TACTILE_FEEDBACK + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + MTouchFeedback* fb( MTouchFeedback::Instance() ); + + if ( fb ) + { + fb->InstantFeedback( ETouchFeedbackBasic ); + } +#endif + HidePopupL(); + } + } + } + } + + CXnControlAdapter::HandlePointerEventL( aPointerEvent ); + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::Draw +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::Draw( const TRect& aRect ) const + { + SystemGc().Clear( aRect ); + CXnControlAdapter::Draw( aRect ); + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::SizeChanged +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::SizeChanged() + { + ChangePopupPosition(); + CXnControlAdapter::SizeChanged(); + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::ChangePopupPosition +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::ChangePopupPosition() + { + if ( iPopup ) + { + // read position-hint property and set-up its variable + CXnProperty* positionHintProp = NULL; + TRAP_IGNORE( positionHintProp = iNode.Node().GetPropertyL( KPositionHint ) ); + + if ( positionHintProp ) + { + const TDesC8& displayHintVal = positionHintProp->StringValue(); + + if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KAboveLeft ) + { + iPositionHint = EAboveLeft; + } + else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KAboveRight ) + { + iPositionHint = EAboveRight; + } + else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KBelowLeft ) + { + iPositionHint = EBelowLeft; + } + else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KBelowRight ) + { + iPositionHint = EBelowRight; + } + else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KRight ) + { + iPositionHint = ERight; + } + else if ( displayHintVal == XnPropertyNames::tooltip::positionhint::KLeft ) + { + iPositionHint = ELeft; + } + else + { + // if the value if of unknown type, use default one + if ( AknLayoutUtils::LayoutMirrored() ) + { + iPositionHint = EAboveRight; + } + else + { + iPositionHint = EAboveLeft; + } + } + } + if ( iPositionHint != ENone ) + { + // the popup is going visible and position-hind is available + // calculate its position + CalculatePosition(); + } + } + } + +// ----------------------------------------------------------------------------- +// CalculatePosition +// This is used only for popup element with position hint +// ----------------------------------------------------------------------------- +void CXnWidgetExtensionAdapter::CalculatePosition() + { + // widget's rectangle + TRect controlRect; + + // get popup's size. + TSize popupSize = iNode.BorderRect().Size(); + + TRect clientRect = static_cast( *iAppUiAdapter ).ClientRect(); + + // get entire screen except control pane + TRect contentRect( 0, 0, clientRect.iBr.iX, clientRect.iBr.iY ); + + // resulting rectangle + TRect rect; + + TPoint offset( clientRect.iTl ); + + // parent widget's rectangle ( first predecesscor which is "widget" ) + CXnNode* parent = iNode.Node().Parent(); + + while ( parent ) + { + const TDesC8& type( parent->DomNode()->Name() ); + if ( type == KWidgetNodeName ) + { + break; + } + parent = parent->Parent(); + } + + // if predecesscor widget was not found, use parent's rectangle + if ( parent == NULL ) + { + controlRect = iNode.Node().Parent()->Rect(); + } + else + { + controlRect = parent->BorderRect(); + } + + // calculate available space for placing the popup + TInt spaceAbove = controlRect.iTl.iY + offset.iY; + TInt spaceBelow = contentRect.iBr.iY - controlRect.iBr.iY - offset.iY; + TInt spaceLeft = controlRect.iTl.iX + offset.iX; + TInt spaceRight = contentRect.iBr.iX - controlRect.iBr.iX - offset.iX; + + switch ( iPositionHint ) + { + + case EAboveLeft: + + // if this position does not fit the screen, + // and if below left is more suitable, use it + if ( spaceAbove < popupSize.iHeight && spaceBelow > spaceAbove ) + { + rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iBr.iY ), + TPoint( controlRect.iTl.iX + popupSize.iWidth, controlRect.iBr.iY + popupSize.iHeight ) ); + } + else + { + // use the above-left position + rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iTl.iY - popupSize.iHeight ), + TPoint( controlRect.iTl.iX + popupSize.iWidth, controlRect.iTl.iY ) ); + + } + break; + + case EAboveRight: + + // if this position does not fit the screen, + // and if below right is more suitable, use it + if ( spaceAbove < popupSize.iHeight && spaceBelow > spaceAbove ) + { + rect = TRect( TPoint( controlRect.iBr.iX - popupSize.iWidth, controlRect.iBr.iY ), + TPoint( controlRect.iBr.iX, controlRect.iBr.iY + popupSize.iHeight ) ); + } + else + { + // use the above-right position + rect = TRect( TPoint( controlRect.iBr.iX - popupSize.iWidth, controlRect.iTl.iY - popupSize.iHeight ), + TPoint( controlRect.iBr.iX, controlRect.iTl.iY ) ); + } + break; + + case EBelowLeft: + + // if this position does not fit the screen, + // and if above left is more suitable, use it + if ( spaceBelow < popupSize.iHeight && spaceBelow < spaceAbove ) + { + rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iTl.iY - popupSize.iHeight ), + TPoint( controlRect.iTl.iX + popupSize.iWidth, controlRect.iTl.iY ) ); + } + else + { + // use the below-left position + rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iBr.iY ), + TPoint( controlRect.iTl.iX + popupSize.iWidth, controlRect.iBr.iY + popupSize.iHeight ) ); + } + break; + + case EBelowRight: + + // if this position does not fit the screen, + // and if above right is more suitable, use it + if ( spaceBelow < popupSize.iHeight && spaceBelow < spaceAbove ) + { + rect = TRect( TPoint( controlRect.iBr.iX - popupSize.iWidth, controlRect.iTl.iY - popupSize.iHeight ), + TPoint( controlRect.iBr.iX, controlRect.iTl.iY ) ); + } + else + { + // use the below-right position + rect = TRect( TPoint( controlRect.iBr.iX - popupSize.iWidth, controlRect.iBr.iY ), + TPoint( controlRect.iBr.iX, controlRect.iBr.iY + popupSize.iHeight ) ); + } + break; + + case ERight: + + // if this position does not fit the screen, + // and if left or above-left is more suitable, use it + if ( spaceRight < popupSize.iWidth ) + { + // use the left position if the space is big enough + if ( spaceLeft >= popupSize.iWidth ) + { + // use left position + rect = TRect( TPoint( controlRect.iTl.iX - popupSize.iWidth, controlRect.iTl.iY ), + TPoint( controlRect.iTl.iX, controlRect.iTl.iY + popupSize.iHeight ) ); + } + else if ( spaceAbove >= popupSize.iHeight ) + { + // use the above-right position + rect = TRect( TPoint( controlRect.iBr.iX - popupSize.iWidth, controlRect.iTl.iY - popupSize.iHeight ), + TPoint( controlRect.iBr.iX, controlRect.iTl.iY ) ); + } + else + { + // use the below-right position + rect = TRect( TPoint( controlRect.iBr.iX - popupSize.iWidth, controlRect.iBr.iY ), + TPoint( controlRect.iBr.iX, controlRect.iBr.iY + popupSize.iHeight ) ); + } + } + else + { + // use the right position + rect = TRect( TPoint( controlRect.iBr.iX, controlRect.iTl.iY ), + TPoint( controlRect.iBr.iX + popupSize.iWidth, controlRect.iTl.iY + popupSize.iHeight ) ); + } + + break; + + case ELeft: + + // if this position does not fit the screen, + // and if right is more suitable, use it + if ( spaceLeft < popupSize.iWidth ) + { + // use the right position, if it the space is big enough + if ( spaceRight >= popupSize.iWidth ) + { + rect = TRect( TPoint( controlRect.iBr.iX, controlRect.iTl.iY ), + TPoint( controlRect.iBr.iX + popupSize.iWidth, controlRect.iTl.iY + popupSize.iHeight ) ); + } + else if ( spaceAbove >= popupSize.iHeight ) + { + // use the above-left position + rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iTl.iY - popupSize.iHeight ), + TPoint( controlRect.iTl.iX + popupSize.iWidth, controlRect.iTl.iY ) ); + } + else + { + // use the below-left position + rect = TRect( TPoint( controlRect.iTl.iX, controlRect.iBr.iY ), + TPoint( controlRect.iTl.iX + popupSize.iWidth, controlRect.iBr.iY + popupSize.iHeight ) ); + } + } + else + { + // use the left position + rect = TRect( TPoint( controlRect.iTl.iX - popupSize.iWidth, controlRect.iTl.iY ), + TPoint( controlRect.iTl.iX, controlRect.iTl.iY + popupSize.iHeight ) ); + } + break; + default: + break; + } + + rect.Move( offset ); + + // if the popup rectangle exceeds the borders of content rectangle, move it. + if ( rect.iTl.iY < contentRect.iTl.iY ) + { + rect.Move( 0, contentRect.iTl.iY - rect.iTl.iY ); + } + if ( rect.iTl.iX < contentRect.iTl.iX ) + { + rect.Move( contentRect.iTl.iX - rect.iTl.iX, 0 ); + } + if ( rect.iBr.iY > contentRect.iBr.iY ) + { + rect.Move( 0, contentRect.iBr.iY - rect.iBr.iY ); + } + if ( rect.iBr.iX > contentRect.iBr.iX ) + { + rect.Move( contentRect.iBr.iX - rect.iBr.iX, 0 ); + } + + SetPosition( rect.iTl ); + SetSizeWithoutNotification( rect.Size() ); + } + + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::NotifyForegroundChanged +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::NotifyForegroundChanged( + TForegroundStatus aStatus ) + { + if ( iPopup && aStatus != EForeground ) + { + TRAP_IGNORE( HidePopupL() ); + } + else if ( !iPopup && aStatus == EForeground ) + { + if ( !DrawableWindow()->IsFaded() ) + { + DrawableWindow()->FadeBehind( ETrue ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::NotifyLightStatusChanged +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::NotifyLightStatusChanged( TBool aLightsOn ) + { + if ( !aLightsOn ) + { + TRAP_IGNORE( HidePopupL() ); + } + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::NotifyInCallStateChaged +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::NotifyInCallStateChaged( TBool /*aInCall*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::HidePopupL +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::HidePopupL() + { + if ( IsVisible() ) + { + CXnDomStringPool* sp( iNode.Node().DomNode()->StringPool() ); + + CXnProperty* prop = CXnProperty::NewL( + KDisplay, KNone, CXnDomPropertyValue::EString, *sp ); + + CleanupStack::PushL( prop ); + + iNode.Node().SetPropertyL( prop ); + + CleanupStack::Pop( prop ); + } + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::NotifyStatusPaneSizeChanged +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::NotifyStatusPaneSizeChanged() + { + } + +// ----------------------------------------------------------------------------- +// CXnWidgetExtensionAdapter::NotifyResourceChanged +// +// ----------------------------------------------------------------------------- +// +void CXnWidgetExtensionAdapter::NotifyResourceChanged( TInt aType ) + { + + // if type is widget extension and fade has changed + // we have to always fade main window + if ( !iPopup && aType == KEikMessageWindowsFadeChange ) + { + if ( !DrawableWindow()->IsFaded() ) + { + DrawableWindow()->FadeBehind( ETrue ); + } + } + } + +// End of File