/*
* Copyright (c) 2002-2004 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: ODT parser
*
*/
#include <aisystemuids.hrh>
#include <xnextrenderingpluginadapter.h>
#include <ecom/ecom.h>
#include <ecom/implementationinformation.h>
#include "xnextrenderingpluginwrapper.h"
#include "xnodt.h"
#include "xndomdocument.h"
#include "xndomnode.h"
#include "xndomattribute.h"
#include "xndomlist.h"
#include "xnnode.h"
#include "xnecomhandler.h"
#include "xnuiengine.h"
#include "xntype.h"
#include "xncontroladapter.h"
#include "xnviewcontroladapter.h"
#include "xnpopupcontroladapter.h"
#include "xnwidgetextensionadapter.h"
#include "xnscrollablecontroladapter.h"
#include "xnlistquerydialogadapter.h"
#include "xncomponent.h"
#include "xncomponentnodeimpl.h"
#include "xnviewnodeimpl.h"
#include "xnviewsnodeimpl.h"
#include "xnproperty.h"
#include "xncomponentfactory.h"
#include "xnarray.h"
#include "xnviewmanager.h"
#include "xnplugindata.h"
#include "xnrootdata.h"
#include "xnviewdata.h"
#include "xnodtparser.h"
_LIT8( KWidgetBgSkinId, "SKIN(268458534 9916)" );
// CONSTANTS
_LIT8( KXMLUIMLNodeName, "xmluiml" );
_LIT8( KViewsNodeName, "views" );
_LIT8( KViewNodeName, "view" );
_LIT8( KBoxNodeName, "box" );
_LIT8( KButtonNodeName, "button" );
_LIT8( KStylusPopupNodeName, "styluspopup" );
_LIT8( KImageNodeName, "image" );
_LIT8( KTooltipNodeName, "tooltip" );
_LIT8( KMenuBarNodeName, "menubar" );
_LIT8( KMenuNodeName, "menu" );
_LIT8( KMenuItemNodeName, "menuitem" );
_LIT8( KDynMenuItemNodeName, "dynmenuitem" );
_LIT8( KWidgetMenuItemNodeName, "widgetmenuitem" );
_LIT8( KActionsNodeName, "actions" );
_LIT8( KActionNodeName, "action" );
_LIT8( KTriggerNodeName, "trigger" );
_LIT8( KEventNodeName, "event" );
_LIT8( KTextNodeName, "text" );
_LIT8( KMarqueeNodeName, "marquee" );
_LIT8( KObjectNodeName, "object" );
_LIT8( KTracksterNodeName, "trackster" );
_LIT8( KPropertyNodeName, "property" );
_LIT8( KConfigurationNodeName, "configuration" );
_LIT8( KNewstickerNodeName, "newsticker" );
_LIT8( KAttributeNodeName, "attribute" );
_LIT8( KItemNodeName, "item" );
_LIT8( KDescNodeName, "desc" );
_LIT8( KTextZoomNodeName, "textzoom" );
_LIT8( KVolumeControlNodeName, "volumecontrol" );
_LIT8( KPluginNodeName, "plugin" );
_LIT8( KWidgetNodeName, "widget" );
_LIT8( KSliderNodeName, "slider" );
_LIT8( KClockNodeName, "clock" );
_LIT8( KSoftkeyNodeName,"softkey" );
_LIT8( KConditionalTrigger,"conditional" );
_LIT8( KCondtionalOn, "true" );
_LIT8( KListQueryDialogNodeName, "listquerydialog" );
_LIT8( KSettingsConfigurationNodeName, "settingsconfiguration" );
_LIT8( KContentSourceNodeName, "contentsource" );
_LIT8( KMenuExtensionNodeName, "menuextension" );
_LIT8( KWidgetExtensionNodeName, "widgetextension" );
_LIT8( KTextEditorNodeName, "texteditor" );
_LIT8( KActionsHandlerNodeName, "actionshandler" );
_LIT8( KScrollableBoxNodeName, "scrollablebox" );
_LIT8( KPopUpNodeName, "popup" );
// LOCAL FUNCTION PROTOTYPES
#ifdef _XN3_DEBUG_
#include <flogger.h>
#include <utf.h>
static void PrintDomL( CXnDomDocument* aDomDocument );
#endif
static CXnNode* BuildRootNodeL( CXnUiEngine& aEngine );
static CXnNode* FindAncestorWhoActAsParent( CXnDomNode& aSource );
static TBool CreateTriggerInLayoutNodeTree( CXnDomNode& aSource );
static void CopyPropertiesFromDomNodeToNodeL(
CXnNode& aTarget,
CXnDomNode& aSource,
CXnDomStringPool& aStringPool );
static CXnNode* ConstructNodeFromPluginL(
CXnEcomHandler& aEcomHandler,
CXnDomNode& aSource );
static CXnNode* ConstructKnownBuiltinNodeL( CXnDomNode& aSource );
static CXnNode* ConstructGeneralNodeL( CXnDomNode& aSource );
// ============================= LOCAL FUNCTIONS ===============================
// ----------------------------------------------------------------------------
// CleanupResetAndDestroy()
// ----------------------------------------------------------------------------
//
template<class T>
static void CleanupResetAndDestroy( TAny* aObj )
{
if( aObj )
{
static_cast<T*>( aObj )->ResetAndDestroy();
}
}
// ----------------------------------------------------------------------------
// CleanupResetAndDestroyPushL
// ----------------------------------------------------------------------------
//
template<class T>
static void CleanupResetAndDestroyPushL(T& aArray)
{
CleanupStack::PushL( TCleanupItem( &CleanupResetAndDestroy<T>, &aArray ) );
}
#ifdef _XN3_DEBUG_
_LIT( KLogFolder," xnlayoutengine" );
_LIT( KLogDom, "dom.log" );
#define _LOGT( aDescription ) RFileLogger::Write( \
KLogFolder, KLogDom, EFileLoggingModeOverwrite, aDescription );
#define _LOGTFRM1( a, b ) RFileLogger::WriteFormat( \
KLogFolder, KLogDom, EFileLoggingModeOverwrite, ( a ), ( b ) )
#define _LOGTFRM2( a, b, c ) RFileLogger::WriteFormat( \
KLogFolder, KLogDom, EFileLoggingModeOverwrite, ( a ), ( b ), ( c ) );
#define _LOGTFRM3( a, b, c, d ) RFileLogger::WriteFormat( \
KLogFolder, KLogDom, EFileLoggingModeOverwrite, ( a ), ( b ), ( c ), ( d ) );
static const TInt GetNodeDepth( CXnDomNode *aNode )
{
TInt depth = 0;
CXnDomNode* node( aNode );
while ( node )
{
node = node->Parent();
if ( node )
{
depth++;
}
}
return depth;
}
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
static HBufC8* GetFixedTextLC(
const TDesC8& aText,
const TInt aDepth,
const TDesC8& aDelim )
{
HBufC8 *buf = HBufC8::NewL( aDepth * aDelim.Length() + aText.Length() + 1 );
TInt i = 0;
for ( ; i < aDepth; i++ )
{
buf->Des().Append( aDelim );
}
buf->Des().Append( aText );
return buf;
}
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
static void PrintDomL( CXnDomDocument* aDomDocument )
{
__UHEAP_MARK;
TInt attrCount( 0 );
TInt propCount( 0 );
CXnDomDepthIterator* iter =
CXnDomDepthIterator::NewL( *aDomDocument->RootNode() );
CleanupStack::PushL( iter );
_LIT8( KDelim, "\t" );
CXnDomNode* nodeParent( NULL );
CXnDomNode* node = iter->First();
while ( node )
{
const TInt depth = GetNodeDepth( node );
HBufC8 *nameBuf = GetFixedTextLC( node->Name(), depth, KDelim );
CleanupStack::PushL( nameBuf );
const TDesC8& name = nameBuf->Des();
HBufC8 *nsBuf = GetFixedTextLC( node->Namespace(), depth, KDelim );
CleanupStack::PushL( nsBuf );
const TDesC8& ns = nsBuf->Des();
_LOGTFRM2( _L8( "%S -------------------------- %S\n" ), &name, &ns );
CXnDomList& attrList = node->AttributeList();
TInt length( attrList.Length() );
attrCount += length;
for ( TInt i = 0; i < length; i++ )
{
CXnDomAttribute* attr = static_cast< CXnDomAttribute* >(
attrList.Item( i ) );
HBufC8 *attrBuf = GetFixedTextLC( attr->Name(), depth, KDelim );
CleanupStack::PushL( attrBuf );
const TDesC8& attrName = attrBuf->Des();
const TDesC8& attrValue = attr->Value();
_LOGTFRM2( _L8( "%S=%S\n" ), &attrName, &attrValue );
CleanupStack::PopAndDestroy( attrBuf );
}
if ( node->Parent() )
{
nodeParent = node;
}
node = iter->NextL();
CleanupStack::PopAndDestroy( nsBuf );
CleanupStack::PopAndDestroy( nameBuf );
}
CleanupStack::PopAndDestroy( iter );
_LOGTFRM1( _L8( "****DOM Size: %d ****\n" ), aDomDocument->Size() );
_LOGTFRM1( _L8( "****DOM Node Count: %d ****\n" ), aDomDocument->DomNodeCount() );
_LOGTFRM1( _L8( "****DOM Attribute Count: %d ****\n" ), attrCount );
__UHEAP_MARKEND;
}
#endif
// -----------------------------------------------------------------------------
// BuildRootNodeL()
// Builds root node
// -----------------------------------------------------------------------------
//
static CXnNode* BuildRootNodeL( CXnUiEngine& aEngine )
{
CXnType* type = CXnType::NewL( KXMLUIMLNodeName );
CleanupStack::PushL( type );
CXnNodeImpl* impl = CXnNodeImpl::NewL( type );
CleanupStack::Pop( type );
CleanupStack::PushL( impl );
CXnNode* node = CXnNode::NewL();
node->SetRootNodeImpl( impl );
CleanupStack::Pop( impl );
node->SetUiEngine( aEngine );
return node;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CXnNode* FindAncestorWhoActAsParent( CXnDomNode& aSource )
{
CXnNode* ret( NULL );
CXnDomNode* parent = aSource.Parent();
while ( !ret && parent )
{
ret = parent->LayoutNode();
parent = parent->Parent();
}
return ret;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CreateTriggerInLayoutNodeTree( CXnDomNode& aSource )
{
TBool ret( EFalse );
CXnDomAttribute* attribute = static_cast< CXnDomAttribute* >(
aSource.AttributeList().FindByName( KConditionalTrigger ) );
if ( attribute && attribute->Value() == KCondtionalOn )
{
ret = ETrue;
}
return ret;
}
// -----------------------------------------------------------------------------
// CopyDomPropertiesFromDomNodeToNodeL
// -----------------------------------------------------------------------------
//
static void CopyDomPropertiesFromDomNodeToNodeL(
CXnNode& aTarget,
CXnDomNode& aSource )
{
CXnDomList& propertyList = aSource.PropertyList();
for ( TInt count = propertyList.Length() - 1; count >= 0; --count )
{
CXnDomProperty* domProperty = static_cast< CXnDomProperty* >(
propertyList.Item( count ) );
CXnProperty* property = CXnProperty::NewSharedL( domProperty );
CleanupStack::PushL( property );
aTarget.InitializePropertyL( property );
CleanupStack::Pop( property );
}
}
// -----------------------------------------------------------------------------
// CopyDomAtributesFromDomNodeToNodeL
// -----------------------------------------------------------------------------
//
static void CopyDomAttributesFromDomNodeToNodeL(
CXnNode& aTarget,
CXnDomNode& aSource,
CXnDomStringPool& aStringPool )
{
CXnDomList& attributeList = aSource.AttributeList();
for ( TInt count = attributeList.Length() - 1; count >= 0; --count )
{
CXnDomAttribute* attribute = static_cast< CXnDomAttribute* >(
attributeList.Item( count ) );
#ifdef _DEBUG
const TDesC8& name = attribute->Name();
const TDesC8& attrValue = attribute->Value();
#endif
if ( attribute->ValueStringPoolIndex() == KErrNotFound )
{
continue;
}
if ( attribute->NameStringPoolIndex() == KErrNotFound )
{
continue;
}
CXnDomProperty* clone =
CXnDomProperty::NewL( attribute->NameStringPoolIndex(), &aStringPool );
CleanupStack::PushL( clone );
CXnDomPropertyValue* propertyValue =
CXnDomPropertyValue::NewL( &aStringPool );
CleanupStack::PushL( propertyValue );
propertyValue->SetStringPoolIndexL(
CXnDomPropertyValue::EString, attribute->ValueStringPoolIndex() );
CXnDomList& propertyList = clone->PropertyValueList();
propertyList.AddItemL( propertyValue );
CleanupStack::Pop( propertyValue );
CXnProperty* property = CXnProperty::NewL( clone );
CleanupStack::Pop( clone );
CleanupStack::PushL( property );
aTarget.InitializePropertyL( property );
CleanupStack::Pop( property );
}
//aSource.DeleteAttributeList();
// delete attributes from dom node tree
if ( aSource.Name() != KTriggerNodeName )
{
CXnDomList& attrList = aSource.AttributeList();
while ( attrList.Length() )
{
attrList.DeleteItem( attrList.Length() - 1 );
}
}
}
// -----------------------------------------------------------------------------
// CopyPropertiesFromDomNodeToNodeL
// -----------------------------------------------------------------------------
//
static void CopyPropertiesFromDomNodeToNodeL(
CXnNode& aTarget,
CXnDomNode& aSource,
CXnDomStringPool& aStringPool )
{
CopyDomPropertiesFromDomNodeToNodeL( aTarget, aSource );
CopyDomAttributesFromDomNodeToNodeL( aTarget, aSource, aStringPool );
}
// -----------------------------------------------------------------------------
// ConstructNodeFromPluginL
// -----------------------------------------------------------------------------
//
static CXnNode* ConstructNodeFromPluginL(
CXnEcomHandler& aEcomHandler,
CXnDomNode& aSource )
{
CXnNode* returnValue = NULL;
const TDesC8& name = aSource.Name();
CXnArray* componentFactories = CXnArray::NewL();
CleanupStack::PushL( componentFactories );
TUid interfaceUid = { AI3_RENDERING_PLUGIN_ECOM_FACTORY_UID };
aEcomHandler.PluginsL( interfaceUid, name, *componentFactories );
TInt count = componentFactories->Container().Count();
TBool componentNodeImplNeeded = ETrue;
// invoke factory chain
for ( TInt i = 0; i < count; ++i )
{
MXnComponentFactory* factory = static_cast< MXnComponentFactory* >(
componentFactories->Container()[i] );
componentNodeImplNeeded = factory->DoesNodeNeedComponentImplL( name );
}
CleanupStack::PopAndDestroy( componentFactories );
if ( componentNodeImplNeeded )
{
CXnType* type = CXnType::NewL( name );
CleanupStack::PushL( type );
CXnComponentNodeImpl* impl = CXnComponentNodeImpl::NewL( type );
CleanupStack::Pop( type );
CleanupStack::PushL( impl );
returnValue = CXnNode::NewL();
returnValue->SetComponentNodeImpl( impl );
CleanupStack::Pop( impl );
}
else
{
if ( name == KActionsNodeName ||
name == KActionNodeName ||
name == KEventNodeName ||
name == KTriggerNodeName ||
name == KMenuNodeName ||
name == KMenuItemNodeName ||
name == KPropertyNodeName ||
name == KSoftkeyNodeName )
{
return ConstructGeneralNodeL( aSource );
}
}
return returnValue;
}
// -----------------------------------------------------------------------------
// ConstructKnownBuiltinNodeL
// -----------------------------------------------------------------------------
//
static CXnNode* ConstructKnownBuiltinNodeL( CXnDomNode& aSource )
{
CXnNode* returnValue = NULL;
const TDesC8& name = aSource.Name();
if ( name == KMenuNodeName ||
name == KMenuItemNodeName ||
name == KPropertyNodeName ||
name == KSoftkeyNodeName ||
name == KTriggerNodeName )
{
return ConstructGeneralNodeL( aSource );
}
CXnType* type = CXnType::NewL( name );
CleanupStack::PushL( type );
if ( name == KViewsNodeName )
{
CXnViewsNodeImpl* impl = CXnViewsNodeImpl::NewL( type );
CleanupStack::Pop( type );
CleanupStack::PushL( impl );
returnValue = CXnNode::NewL();
returnValue->SetViewsNodeImpl( impl );
CleanupStack::Pop( impl );
}
else if ( name == KViewNodeName )
{
CXnViewNodeImpl* impl = CXnViewNodeImpl::NewL( type );
CleanupStack::Pop( type );
CleanupStack::PushL( impl );
returnValue = CXnNode::NewL();
returnValue->SetViewNodeImpl( impl );
CleanupStack::Pop( impl );
}
else if ( name == KBoxNodeName ||
name == KButtonNodeName ||
name == KImageNodeName ||
name == KMenuBarNodeName ||
name == KTooltipNodeName ||
name == KMarqueeNodeName ||
name == KTextNodeName ||
name == KObjectNodeName ||
name == KTracksterNodeName ||
name == KNewstickerNodeName ||
name == KSliderNodeName ||
name == KClockNodeName ||
name == KStylusPopupNodeName ||
name == KPopUpNodeName ||
name == KWidgetExtensionNodeName ||
name == KTextEditorNodeName )
{
CXnComponentNodeImpl* impl = CXnComponentNodeImpl::NewL( type );
CleanupStack::Pop( type ) ;
CleanupStack::PushL( impl );
returnValue = CXnNode::NewL();
returnValue->SetComponentNodeImpl( impl );
CleanupStack::Pop( impl );
}
else
{
CleanupStack::PopAndDestroy( type );
if ( name == KVolumeControlNodeName ||
name == KWidgetNodeName ||
name == KPluginNodeName )
{
CXnType* type = CXnType::NewL( KBoxNodeName );
CleanupStack::PushL( type );
CXnComponentNodeImpl* impl = CXnComponentNodeImpl::NewL( type );
CleanupStack::Pop( type );
CleanupStack::PushL( impl );
returnValue = CXnNode::NewL();
returnValue->SetComponentNodeImpl( impl );
CleanupStack::Pop( impl );
}
}
return returnValue;
}
// -----------------------------------------------------------------------------
// ConstructGeneralNodeL
// -----------------------------------------------------------------------------
//
static CXnNode* ConstructGeneralNodeL( CXnDomNode& aSource )
{
CXnType* type = CXnType::NewL( aSource.Name() );
CleanupStack::PushL( type );
CXnNodeImpl* impl = CXnNodeImpl::NewL( type );
CleanupStack::Pop( type );
CleanupStack::PushL( impl );
CXnNode* tmpNode = CXnNode::NewL();
tmpNode->SetImpl( impl );
CleanupStack::Pop( impl );
return tmpNode;
}
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CXnODTParser::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CXnODTParser* CXnODTParser::NewL( CXnViewManager& aManager,
CXnEcomHandler& aEcomHandler )
{
CXnODTParser* self = new ( ELeave ) CXnODTParser( aManager, aEcomHandler );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CXnODTParser::CXnODTParser
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CXnODTParser::CXnODTParser( CXnViewManager& aManager,
CXnEcomHandler& aEcomHandler )
: iManager( aManager ), iUiEngine( aManager.UiEngine() ),
iEcomHandler( aEcomHandler )
{
}
// -----------------------------------------------------------------------------
// CXnODTParser::~CXnODTParser
// Destructor.
// -----------------------------------------------------------------------------
//
CXnODTParser::~CXnODTParser()
{
}
// -----------------------------------------------------------------------------
// CXnODTParser::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CXnODTParser::ConstructL()
{
}
// -----------------------------------------------------------------------------
// CXnODTParser::LoadRootL
// -----------------------------------------------------------------------------
//
void CXnODTParser::LoadRootL( CXnRootData& aRootData, TUid /*aAppUid*/ )
{
CXnDomNode* root( aRootData.Owner() );
CXnDomStringPool* sp( root->StringPool() );
CXnAppUiAdapter& appui( iManager.AppUiAdapter() );
// Build root
CXnNode* node( BuildRootNodeL( iUiEngine ) );
// Let root nodes to know each other
CXnDomNode* dom( aRootData.ODT()->DomDocument().RootNode() );
dom->SetLayoutNode( node );
node->SetDomNode( dom );
CreateNodesL( root, *sp, aRootData );
// root doesn't have any controls
aRootData.SetOccupied();
}
// -----------------------------------------------------------------------------
// CXnODTParser::LoadViewL
// -----------------------------------------------------------------------------
//
void CXnODTParser::LoadViewL( CXnViewData& aViewData )
{
// <view> element
CXnDomNode* view( aViewData.Node() );
CXnDomStringPool* sp( view->StringPool() );
// from <view> element
CreateNodesL( view, *sp, aViewData );
CreateControlsL( view, aViewData );
// By default make controls invisible
CXnControlAdapter* adapter( view->LayoutNode()->Control() );
if( adapter )
{
adapter->MakeVisible( EFalse );
}
aViewData.SetOccupied();
}
// -----------------------------------------------------------------------------
// CXnODTParser::DestroyView
// -----------------------------------------------------------------------------
//
void CXnODTParser::DestroyView( CXnViewData& aViewData )
{
CXnNode* view( aViewData.Node()->LayoutNode() );
// Destroy view and all its child nodes
CXnNode* parent( view->Parent() );
RPointerArray< CXnNode >& children( parent->Children() );
TInt index( children.Find( view ) );
if ( index != KErrNotFound )
{
children.Remove( index );
delete view;
view = NULL;
CXnDomNode* owner( aViewData.Owner() );
owner->DeleteChild( aViewData.Node() );
}
}
// -----------------------------------------------------------------------------
// CXnODTParser::LoadWidgetL
// -----------------------------------------------------------------------------
//
void CXnODTParser::LoadWidgetL( CXnPluginData& aPluginData )
{
if ( aPluginData.Empty() )
{
// Holds "empty" widget
return;
}
// <widget> element
CXnDomNode* widget( aPluginData.Node() );
CXnDomStringPool* sp( widget->StringPool() );
// from <widget> element
CreateNodesL( widget, *sp, aPluginData );
CreateControlsL( widget, aPluginData );
HandleWidgetBackgroundL( widget->LayoutNode() );
// By default make controls invisible
CXnControlAdapter* adapter( widget->LayoutNode()->Control() );
if( adapter )
{
adapter->MakeVisible( EFalse );
}
aPluginData.SetOccupied();
}
// -----------------------------------------------------------------------------
// CXnODTParser::DestroyWidget
// -----------------------------------------------------------------------------
//
void CXnODTParser::DestroyWidgetL( CXnPluginData& aPluginData )
{
CXnViewData& parent(
static_cast< CXnViewData& >( *aPluginData.Parent() ) );
// Check is any of plugin data's controls in views draw chain and remove
CXnControlAdapter* control( parent.Node()->LayoutNode()->Control() );
RPointerArray< CXnControlAdapter >& controls( control->ChildAdapters() );
RPointerArray< CXnControlAdapter > pluginControls;
CleanupClosePushL( pluginControls );
aPluginData.ControlsL( pluginControls );
// Remove from view chain if found
for ( TInt i = 0; i < pluginControls.Count(); i++ )
{
CXnControlAdapter* control( pluginControls[i] );
TInt index( controls.Find( control ) );
if ( index != KErrNotFound )
{
controls.Remove( index );
}
}
CleanupStack::PopAndDestroy( &pluginControls );
CXnNode* widgetNode( aPluginData.Node()->LayoutNode() );
CXnNode* owner( widgetNode->Parent() );
CXnControlAdapter* widgetControl( widgetNode->Control() );
RPointerArray< CXnControlAdapter >&
childAdapters( owner->Control()->ChildAdapters() );
childAdapters.Remove( childAdapters.Find( widgetControl ) );
childAdapters.Compress();
RPointerArray< CXnNode >& children( owner->Children() );
TInt index( children.Find( widgetNode ) );
// Destroy widget and all its child nodes
if ( index != KErrNotFound )
{
children.Remove( index );
delete widgetNode;
widgetNode = NULL;
CXnDomNode* owner( aPluginData.Owner() );
owner->DeleteChild( aPluginData.Node() );
}
}
// -----------------------------------------------------------------------------
// CXnODTParser::CreateNodesL
// Creates node tree
// -----------------------------------------------------------------------------
//
void CXnODTParser::CreateNodesL(
CXnDomNode* aSourceNode,
CXnDomStringPool& aSp,
CXnPluginData& aPluginData )
{
if ( aSourceNode )
{
ConstructNodeL( *aSourceNode, aSp, aPluginData );
CXnDomList& childList( aSourceNode->ChildNodes() );
TInt count( childList.Length() );
for ( TInt i = 0; i < count; ++i )
{
CreateNodesL(
static_cast< CXnDomNode* >( childList.Item( i ) ),
aSp, aPluginData );
}
}
}
// -----------------------------------------------------------------------------
// CXnODTParser::ConstructNodeL
// Creates layout node and control for it
// -----------------------------------------------------------------------------
//
void CXnODTParser::ConstructNodeL(
CXnDomNode& aSource,
CXnDomStringPool& aSp,
CXnPluginData& aPluginData )
{
const TDesC8& name( aSource.Name() );
if ( name == KActionsNodeName ||
name == KActionNodeName ||
name == KEventNodeName ||
name == KXMLUIMLNodeName ||
name == KAttributeNodeName ||
name == KItemNodeName )
{
return;
}
if ( name == KTriggerNodeName )
{
if ( !CreateTriggerInLayoutNodeTree( aSource ) )
{
return;
}
}
const TDesC8& parentName( aSource.Parent()->Name() );
if ( name == KPropertyNodeName &&
( parentName == KTriggerNodeName ||
parentName == KEventNodeName ||
parentName == KPropertyNodeName ||
parentName == KAttributeNodeName ) )
{
return;
}
CXnNode* node( ConstructKnownBuiltinNodeL( aSource ) );
if ( !node )
{
node = ConstructNodeFromPluginL( iEcomHandler, aSource );
if ( !node )
{
node = ConstructGeneralNodeL( aSource );
if ( !node )
{
return;
}
}
}
if ( name == KMenuBarNodeName ||
name == KListQueryDialogNodeName ||
name == KMenuNodeName ||
name == KMenuItemNodeName ||
name == KDynMenuItemNodeName ||
name == KWidgetMenuItemNodeName ||
name == KPropertyNodeName ||
name == KDescNodeName ||
name == KTextZoomNodeName ||
name == KConfigurationNodeName ||
name == KSoftkeyNodeName ||
name == KTriggerNodeName ||
name == KSettingsConfigurationNodeName ||
name == KContentSourceNodeName ||
name == KMenuExtensionNodeName ||
name == KStylusPopupNodeName ||
name == KActionsHandlerNodeName )
{
node->SetLayoutCapable( EFalse );
}
CXnNode* parent( FindAncestorWhoActAsParent( aSource ) );
if( !parent )
{
delete node;
return;
}
parent->AddChildL( node );
if ( !parent->IsLayoutCapable() )
{
node->SetLayoutCapable( EFalse );
}
aSource.SetLayoutNode( node );
node->SetDomNode( &aSource );
node->SetUiEngine( iUiEngine );
CopyPropertiesFromDomNodeToNodeL( *node, aSource, aSp );
if ( name == KTriggerNodeName )
{
if ( iUiEngine.IsEditMode() )
{
node->SetStateL( XnPropertyNames::style::common::KEdit );
}
}
// Mark adaptive layoutable nodes
TInt adaptive( XnAdaptive::ENone );
CXnProperty* width( node->WidthL() );
if ( width )
{
const TDesC8& w( width->StringValue() );
if ( w == XnPropertyNames::style::common::KAdaptive )
{
adaptive = XnAdaptive::EWidth;
}
}
CXnProperty* height( node->HeightL() );
if ( height )
{
const TDesC8& h( height->StringValue() );
if ( h == XnPropertyNames::style::common::KAdaptive )
{
adaptive |= XnAdaptive::EHeight;
}
}
if ( adaptive != XnAdaptive::ENone )
{
node->SetAdaptiveL( adaptive );
}
// Collect nodes, which nav-index property is 'appearance' to
// an array
CXnProperty* navindex( node->NavIndexL() );
if ( navindex &&
navindex->StringValue() == XnPropertyNames::style::common::KAppearance )
{
aPluginData.SetAppearanceNodeL( node );
}
// Collect initial focus nodes.
CXnProperty* initialFocusProp( node->InitialFocusL() );
if ( initialFocusProp )
{
aPluginData.SetInitialFocusNodeL( node );
}
}
// -----------------------------------------------------------------------------
// CXnODTParser::CreateControlsL()
// Run control creation 1st phase
// -----------------------------------------------------------------------------
//
void CXnODTParser::CreateControlsL( CXnDomNode* aNode,
CXnPluginData& aPluginData )
{
if ( aNode )
{
ConstructControlL( aNode->LayoutNode(), aPluginData );
CXnDomList& childList( aNode->ChildNodes() );
TInt count( childList.Length() );
for ( TInt i = 0; i < count; ++i )
{
CreateControlsL(
static_cast< CXnDomNode* >( childList.Item( i ) ), aPluginData );
}
}
}
// -----------------------------------------------------------------------------
// CXnODTParser::ConstructControlL()
// Run control creation 1st phase
// -----------------------------------------------------------------------------
//
void CXnODTParser::ConstructControlL( CXnNode* aNode,
CXnPluginData& aPluginData )
{
if( !aNode )
{
return;
}
CXnComponentNodeImpl* impl( aNode->ComponentNodeImpl() );
CXnViewNodeImpl* viewImpl( aNode->ViewNodeImpl() );
TBool needsCreation( EFalse );
if ( ( impl && impl->DoesComponentNeedCreation() ) || viewImpl )
{
needsCreation = ETrue;
}
const TDesC8& name( aNode->Type()->Type() );
if ( needsCreation )
{
// Try if builtin control can be created
if ( !CreateBuiltInControlL( *aNode, name ) )
{
// Not builtin, invoke factory chain
CreateFactoryControlL( *aNode, name );
}
// Fill plugin data
aPluginData.SetControlL( aNode );
}
if ( name == KContentSourceNodeName )
{
aPluginData.SetContentSourceNodeL( aNode );
}
}
// -----------------------------------------------------------------------------
// CXnODTParser::CreateExternalControlL()
// Creates external control
// -----------------------------------------------------------------------------
//
TBool CXnODTParser::CreateExternalControlL( CXnNode& aNode,
const TDesC8& aName )
{
CXnExtRenderingPluginAdapter* adapter( NULL );
// Get implementations via ECom
RImplInfoPtrArray plugins;
CleanupResetAndDestroyPushL( plugins );
REComSession::ListImplementationsL(
TUid::Uid( AI3_EXTERNAL_RENDERING_PLUGIN_ECOM_UID ), plugins );
for( TInt i = 0; i < plugins.Count(); i++ )
{
CImplementationInformation* information( plugins[i] );
if( information->DataType().Compare( aName ) == 0 )
{
adapter = CXnExtRenderingPluginAdapter::NewL(
information->ImplementationUid() );
break;
}
}
CleanupStack::PopAndDestroy(); // plugins
if( adapter )
{
CXnComponent* component = CXnComponent::NewL();
CleanupStack::PushL( component );
CXnControlAdapter* parentAdapter( NULL );
// Find parent control
CXnNode* parent( aNode.Parent() );
for ( ; parent; parent = parent->Parent() )
{
parentAdapter = parent->Control();
if ( parentAdapter )
{
break;
}
}
if( parentAdapter )
{
CXnExtRenderingPluginWrapper* wrapper =
CXnExtRenderingPluginWrapper::NewL( aNode.PluginIfL(), *adapter );
CleanupStack::PushL( wrapper );
parentAdapter->AppendChildL( *wrapper, aNode );
CleanupStack::Pop( wrapper );
component->SetControlAdapter( wrapper );
aNode.ComponentNodeImpl()->SetComponent( component );
component->SetNode( aNode.PluginIfL() );
wrapper->SetComponent( component );
wrapper->SetComponentsToInheritVisibility( ETrue );
wrapper->ActivateL();
CleanupStack::Pop( component );
return ETrue;
}
else
{
CleanupStack::Pop( component );
return EFalse;
}
}
else
{
return EFalse;
}
}
// CXnODTParser::CreateFactoryControlL()
// Creates factory control
// -----------------------------------------------------------------------------
//
void CXnODTParser::CreateFactoryControlL( CXnNode& aNode,
const TDesC8& aName )
{
CXnArray* factories = CXnArray::NewL();
CleanupStack::PushL( factories );
TUid interfaceUid = { AI3_RENDERING_PLUGIN_ECOM_FACTORY_UID };
iEcomHandler.PluginsL( interfaceUid, aName, *factories );
CXnComponent* component( NULL );
TInt count( factories->Container().Count() );
// Invoke factory chain
for ( TInt i = 0; i < count; i++ )
{
MXnComponentFactory* factory =
static_cast< MXnComponentFactory* >(
( factories->Container() )[i] );
if ( factory->CreateXnComponentL( aNode.PluginIfL(), component ) ==
MXnComponentFactory::EXnFactoryResponseComponentConstructed )
{
// All done
break;
}
}
CleanupStack::PopAndDestroy( factories );
}
// -----------------------------------------------------------------------------
// CXnODTParser::CreateBuiltInControlL()
// Creates builtin control
// -----------------------------------------------------------------------------
//
TBool CXnODTParser::CreateBuiltInControlL( CXnNode& aNode,
const TDesC8& aName )
{
if ( aName != KBoxNodeName && aName != KButtonNodeName &&
aName != KStylusPopupNodeName && aName != KScrollableBoxNodeName&&
aName != KWidgetExtensionNodeName &&
aName != KPopUpNodeName && aName != KViewNodeName &&
aName != XnPropertyNames::listquerydialog::KListQueryDialog )
{
return CreateExternalControlL( aNode, aName );
}
CXnComponent* component = CXnComponent::NewL();
CleanupStack::PushL( component );
CXnControlAdapter* parentAdapter( NULL );
CXnProperty* position( aNode.PositionL() );
if ( position )
{
const TDesC8& value( position->StringValue() );
if ( value == XnPropertyNames::style::common::position::KFloating )
{
// Find view node and append floating control to its compound
for ( CXnNode* node = &aNode; node; node = node->Parent() )
{
if ( node->ViewNodeImpl() )
{
parentAdapter = node->Control();
break;
}
}
}
}
if ( !parentAdapter )
{
// Find parent control
CXnNode* parent( aNode.Parent() );
for ( ; parent; parent = parent->Parent() )
{
parentAdapter = parent->Control();
if ( parentAdapter )
{
break;
}
}
}
CXnControlAdapter* adapter( NULL );
if( aName == KViewNodeName )
{
adapter = CXnViewControlAdapter::NewL( aNode.PluginIfL() );
CleanupStack::PushL( adapter );
}
else if( aName == KStylusPopupNodeName )
{
adapter = CXnPopupControlAdapter::NewL( aNode.PluginIfL() );
CleanupStack::PushL( adapter );
}
else if( aName == KWidgetExtensionNodeName ||
aName == KPopUpNodeName )
{
adapter = CXnWidgetExtensionAdapter::NewL( aNode.PluginIfL() );
CleanupStack::PushL( adapter );
CXnProperty* prop = CXnProperty::NewL(
XnPropertyNames::style::common::KPosition,
XnPropertyNames::style::common::position::KFloating,
CXnDomPropertyValue::EString,
*aNode.UiEngine()->ODT()->DomDocument().StringPool() );
CleanupStack::PushL( prop );
aNode.SetPropertyL( prop );
CleanupStack::Pop( prop );
}
else if( aName == KScrollableBoxNodeName )
{
adapter = CXnScrollableControlAdapter::NewL( aNode.PluginIfL() );
CleanupStack::PushL( adapter );
}
else if( aName == XnPropertyNames::listquerydialog::KListQueryDialog )
{
CleanupStack::PopAndDestroy( component );
CXnListQueryDialog* listQuery = CXnListQueryDialog::NewL();
component = static_cast<CXnComponent*>( listQuery );
CleanupStack::PushL( component );
adapter = CXnListQueryDialogAdapter::NewL( aNode.PluginIfL() );
CleanupStack::PushL( adapter );
}
else
{
adapter = CXnControlAdapter::NewL( aNode.PluginIfL() );
CleanupStack::PushL( adapter );
}
if ( parentAdapter )
{
parentAdapter->AppendChildL( *adapter, aNode );
}
component->SetControlAdapter( adapter ); // ovnership transferred
CleanupStack::Pop( adapter );
__ASSERT_DEBUG( adapter, User::Leave( KErrGeneral ) );
if( aName == KViewNodeName )
{
aNode.ViewNodeImpl()->SetComponent( component );
}
else
{
aNode.ComponentNodeImpl()->SetComponent( component );
}
component->SetNode( aNode.PluginIfL() );
adapter->SetComponent( component );
adapter->SetComponentsToInheritVisibility( ETrue );
adapter->ActivateL();
CleanupStack::Pop( component );
return ETrue;
}
// --------------------------------------------------------------------------
// CXnODTParser::HandleWidgetBackgroundL()
//
// --------------------------------------------------------------------------
//
void CXnODTParser::HandleWidgetBackgroundL( CXnNode* aWidgetNode )
{
if( aWidgetNode )
{
CXnUiEngine* uiengine = aWidgetNode->UiEngine();
CXnProperty* bgImageProp = aWidgetNode->BackgroundImageL();
CXnProperty* bgColorProp = aWidgetNode->BackgroundColorL();
// Set default bg color if it has not been defined by a widget
if( !bgImageProp && !bgColorProp && uiengine )
{
CXnDomPropertyValue* value = CXnDomPropertyValue::NewL(
uiengine->ODT()->DomDocument().StringPool() );
CleanupStack::PushL( value );
value->SetStringValueL( CXnDomPropertyValue::EString, KWidgetBgSkinId );
CXnProperty* bgColor = CXnProperty::NewL(
XnPropertyNames::appearance::common::KBackGroundColor,
value, *uiengine->ODT()->DomDocument().StringPool() );
CleanupStack::Pop( value );
CleanupStack::PushL( bgColor );
aWidgetNode->SetPropertyL( bgColor );
CleanupStack::Pop( bgColor );
}
}
}
// End of file