/*
* 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:
*
* Description: Popup control adapter
*
*/
// System includes
#include <e32base.h>
#include <e32const.h>
#include <coecntrl.h>
#include <aknstyluspopupmenu.h>
// User includes
#include "xnappuiadapter.h"
#include "xnviewadapter.h"
#include "xnkeyeventdispatcher.h"
#include "xnviewmanager.h"
#include "xnviewdata.h"
#include "xnplugindata.h"
#include "xnproperty.h"
#include "xncontroladapter.h"
#include "xndomnode.h"
#include "xnnodepluginif.h"
#include "xnnode.h"
#include "xntype.h"
#include "xnuiengine.h"
#include "xneditor.h"
#include "xnfocuscontrol.h"
#include "xnpopupcontroladapter.h"
// Constants
_LIT8( KMenuItem, "menuitem" );
_LIT8( KDynMenuItem, "dynmenuitem" );
_LIT8( KWidgetMenuItem, "widgetmenuitem" );
_LIT8( KMenuExtension, "menuextension" );
_LIT8( KSource, "source" );
_LIT8( KTarget, "target" );
// ============================ LOCAL FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// FindWidgetMenuItemL
//
// -----------------------------------------------------------------------------
//
static CXnNode* FindWidgetMenuItemL( CXnPluginData& aPlugin,
const TDesC8& aSource )
{
if ( !aPlugin.Occupied() )
{
return NULL;
}
CXnNode* widget( aPlugin.Node()->LayoutNode() );
RPointerArray< CXnNode >& children( widget->Children() );
for ( TInt i = children.Count() - 1; i >= 0; i-- )
{
if ( children[i]->Type()->Type() == KMenuExtension )
{
RPointerArray< CXnNode >& items( children[i]->Children() );
for ( TInt i = 0; i < items.Count(); i++ )
{
CXnProperty* prop( items[i]->GetPropertyL( KTarget ) );
if ( prop && prop->StringValue() == aSource )
{
return items[i];
}
}
break;
}
}
return NULL;
}
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::NewL
// Two-phased constructor. Can leave.
// -----------------------------------------------------------------------------
//
CXnPopupControlAdapter* CXnPopupControlAdapter::NewL( CXnNodePluginIf& aNode )
{
CXnPopupControlAdapter* self =
new ( ELeave ) CXnPopupControlAdapter();
CleanupStack::PushL( self );
self->ConstructL( aNode );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::~CXnPopupControlAdapter
// Destructor.
// -----------------------------------------------------------------------------
//
CXnPopupControlAdapter::~CXnPopupControlAdapter()
{
delete iStylusPopupMenu;
iMenuItems.Reset();
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::CXnPopupControlAdapter
// C++ default constructor. Must not leave.
// -----------------------------------------------------------------------------
//
CXnPopupControlAdapter::CXnPopupControlAdapter()
{
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::ConstructL
// 2nd phase constructor. Can leave.
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::ConstructL( CXnNodePluginIf& aNode )
{
CXnControlAdapter::ConstructL( aNode );
iNode = &aNode.Node();
iUiEngine = iNode->UiEngine();
iMenuShown = EFalse;
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::ProcessCommandL
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::ProcessCommandL( TInt aCommandId )
{
// Resolve selected item
for ( TInt i = 0; aCommandId != KErrCancel && i < iMenuItems.Count(); i++ )
{
if ( i == aCommandId )
{
// Do the actual item selection
iMenuItems[i]->SetStateL(
XnPropertyNames::style::common::KActive );
break;
}
}
iUiEngine->Editor()->SetTargetPlugin( NULL );
iMenuItems.Reset();
iCommandId = 0;
iMenuShown = EFalse;
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::SetEmphasis
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::SetEmphasis( CCoeControl* /*aMenuControl*/,
TBool /*aEmphasis*/ )
{
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::SetObserver
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::SetObserver(
XnMenuInterface::MXnMenuObserver& aObserver )
{
iObserver = &aObserver;
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::TryDisplayingStylusPopupL
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::TryDisplayingStylusPopupL( CXnNode& aPlugin )
{
HideMenuL();
CXnViewManager* manager( iUiEngine->ViewManager() );
CXnPluginData* plugin( manager->ActiveViewData().Plugin( &aPlugin ) );
if ( !plugin )
{
return;
}
CXnViewAdapter& adapter( iUiEngine->AppUiAdapter().ViewAdapter() );
const TPointerEvent& event( adapter.EventDispatcher()->PointerEvent() );
delete iStylusPopupMenu;
iStylusPopupMenu = NULL;
// Popup is positioned relatively to screen
iStylusPopupMenu = CAknStylusPopUpMenu::NewL( this, event.iParentPosition );
RPointerArray< CXnNode >& children( iNode->Children() );
for ( TInt i = 0; i < children.Count(); i++ )
{
PopulateMenuL( *plugin, children[i] );
}
ShowMenuL( *plugin, event.iParentPosition );
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::HandleScreenDeviceChangedL
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::HandleScreenDeviceChangedL()
{
HideMenuL();
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::PopulateMenuL
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::PopulateMenuL( CXnPluginData& aPlugin,
CXnNode* aItem )
{
CXnNode* menuitem( NULL );
CXnProperty* prop( NULL );
TBool mappedItem( EFalse );
// Map widget menuitem first
if ( aItem->Type()->Type() == KWidgetMenuItem )
{
// Widget menuitem is shown if a widget defined by the "aPlugin"
// defines a proper source - target menuitem pairing
CXnProperty* source( aItem->GetPropertyL( KSource ) );
if ( source )
{
CXnNode* widgetItem(
FindWidgetMenuItemL( aPlugin, source->StringValue() ) );
if ( widgetItem )
{
mappedItem = ETrue;
// Get label from the view item
prop = aItem->LabelL();
if ( !prop )
{
// no localization in view, check from widget
prop = widgetItem->LabelL();
}
// Pretend the original item is this widget item
aItem = widgetItem;
}
}
}
const TDesC8& type( aItem->Type()->Type() );
if ( type == KMenuItem )
{
// By default plain menuitems are always shown
menuitem = aItem;
}
else if ( type == KDynMenuItem && iObserver )
{
CXnNode* plugin( aPlugin.Owner()->LayoutNode() );
// Let observer decide whether dynmenuitem is visible or not
if ( iObserver->DynInitMenuItemL( aItem->AppIfL(), &plugin->AppIfL() ) )
{
menuitem = aItem;
}
}
if ( menuitem )
{
CXnProperty* display( menuitem->DisplayL() );
if ( display && display->StringValue() ==
XnPropertyNames::style::common::display::KNone )
{
return;
}
if ( !mappedItem )
{
prop = menuitem->LabelL();
}
if ( prop )
{
HBufC* label( prop->StringValueL() );
CleanupStack::PushL( label );
iStylusPopupMenu->AddMenuItemL( *label, iCommandId++ );
iMenuItems.AppendL( menuitem );
CleanupStack::PopAndDestroy( label );
}
}
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::ShowMenuL
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::ShowMenuL( CXnPluginData& aPlugin,
TPoint aPosition )
{
if ( iMenuItems.Count() > 0 && !iMenuShown )
{
iUiEngine->AppUiAdapter().HideFocus();
CXnNode* plugin( aPlugin.Owner()->LayoutNode() );
iUiEngine->Editor()->SetTargetPlugin( plugin );
iStylusPopupMenu->SetPosition( aPosition,
CAknStylusPopUpMenu::EPositionTypeRightBottom );
iStylusPopupMenu->ShowMenu();
iMenuShown = ETrue;
}
}
// -----------------------------------------------------------------------------
// CXnPopupControlAdapter::HideMenuL
// -----------------------------------------------------------------------------
//
void CXnPopupControlAdapter::HideMenuL()
{
if ( iMenuShown )
{
ProcessCommandL( KErrCancel );
delete iStylusPopupMenu;
iStylusPopupMenu = NULL;
iMenuShown = EFalse;
}
}
// End of file