diff -r f5050f1da672 -r 04becd199f91 javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtmenuitem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtmenuitem.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,732 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia Corporation - S60 implementation + *******************************************************************************/ + + +#include +#include +#include +#include +#include "swtcontrolhelper.h" +#include "swtmenuitem.h" + + +_LIT(KExtraSpaces, " "); + + +// ======== MEMBER FUNCTIONS ======== + + +// --------------------------------------------------------------------------- +// CSwtMenuItem::CSwtMenuItem +// --------------------------------------------------------------------------- +// +inline CSwtMenuItem::CSwtMenuItem(MSwtDisplay& aDisplay, TSwtPeer aPeer, + MSwtMenu& aParent, TInt aIndex, TInt aStyle, TInt aCommandId) + : iDisplay(aDisplay) + , iPeer(aPeer) + , iParent(aParent) + , iIndexOfCreation(aIndex) + , iStyle(aStyle) + , iEnabled(ETrue) +{ + if (aCommandId != 0) + { + iCommandId = aCommandId; + } + else + { + iCommandId = reinterpret_cast(this); + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::CSwtMenuItem +// --------------------------------------------------------------------------- +// +CSwtMenuItem::~CSwtMenuItem() +{ + // Own + delete iText; + delete iDummyMask; + iText = NULL; + iDummyMask = NULL; + + // Not own + TInt imageSizesCount = iImageSizes.Count(); + for (TInt i = 0; i < imageSizesCount; i++) + { + if (iImage) + { + iImage->RemoveSubRef(iImageSizes[i]); + } + } + iImageSizes.Close(); + if (iImage) + { + iImage->RemoveRef(); + } + iImage = NULL; + iMenu = NULL; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::ConstructL +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::ConstructL() +{ + iParent.RegisterChildL(*this, iIndexOfCreation); + + CEikMenuPane* pane = Pane(); + if (pane) + { + CEikMenuPaneItem::SData itemData; + itemData.iText = KNullDesC; + itemData.iExtraText = KNullDesC; + itemData.iFlags = 0; + itemData.iCascadeId = 0; + itemData.iCommandId = iCommandId; + + pane->AddMenuItemL(itemData); + UpdatePaneL(*pane, ESwtMenuItemDataFlags); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } + + iDisplay.MenuArranger().HandleMenuChangedL(iParent, + MSwtMenuArranger::ESwtMenuItemAdded); +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::NewL +// --------------------------------------------------------------------------- +// +CSwtMenuItem* CSwtMenuItem::NewL(MSwtDisplay& aDisplay, TSwtPeer aPeer, + MSwtMenu& aParent, TInt aIndex, TInt aStyle, TInt aCommandId /* = 0 */) +{ + CSwtMenuItem* self = new(ELeave) CSwtMenuItem(aDisplay, aPeer, aParent, + aIndex, aStyle, aCommandId); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Dispose +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TSwtPeer CSwtMenuItem::Dispose() +{ + iParent.UnregisterChild(*this); + + CleanPane(); + + TRAP_IGNORE(iDisplay.MenuArranger().HandleMenuChangedL(iParent, + MSwtMenuArranger::ESwtMenuItemRemoved)); + + // Actual dispose + TSwtPeer peer(iPeer); + delete this; + return peer; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::JavaPeer +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TSwtPeer CSwtMenuItem::JavaPeer() const +{ + return iPeer; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::GetSelection +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TBool CSwtMenuItem::GetSelection() const +{ + return iSelected; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::SetAcceleratorL +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::SetAcceleratorL(TInt aAccelerator) +{ + iAccelerator = aAccelerator; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::SetEnabled +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::SetEnabled(TBool aEnabled) +{ + if (iEnabled != aEnabled) + { + iEnabled = aEnabled; + + CEikMenuPane* pane = Pane(); + if (pane) + { + if (iEnabled) + { + CEikMenuPaneItem::SData itemData; + itemData.iText = KNullDesC; + itemData.iExtraText = KNullDesC; + itemData.iFlags = 0; + itemData.iCascadeId = 0; + itemData.iCommandId = iCommandId; + + TRAP_IGNORE( + pane->AddMenuItemL(itemData); + UpdatePaneL(*pane, ESwtMenuItemDataAll); + ); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } + else + { + CleanPane(); + } + } + + TRAP_IGNORE(iDisplay.MenuArranger().HandleMenuChangedL(iParent, + MSwtMenuArranger::ESwtMenuItemEnableStateChanged)); + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::SetImageL +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::SetImageL(const MSwtImage* aImage) +{ + TInt imageSizesCount = iImageSizes.Count(); + for (TInt i = 0; i < imageSizesCount; i++) + { + if (iImage) + { + iImage->RemoveSubRef(iImageSizes[i]); + } + } + iImageSizes.Close(); + if (iImage) + { + iImage->RemoveRef(); + } + iImage = aImage; + if (iImage) + { + iImage->AddRef(); + } + + CEikMenuPane* pane = Pane(); + if (pane) + { + UpdatePaneL(*pane, ESwtMenuItemDataImage); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::SetMenuL +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::SetMenuL(const MSwtMenu* aMenu) +{ + if (iMenu == aMenu) + { + return; + } + + // If item displayed, close cascade menu. + CEikMenuPane* pane = Pane(); + if (pane) + { + pane->CloseCascadeMenu(); + } + + if (iMenu) + { + iDisplay.MenuArranger().HandleMenuChangedL(*iMenu, + MSwtMenuArranger::ESwtMenuRemoved); + } + + iMenu = aMenu; + + if (iMenu) + { + iDisplay.MenuArranger().HandleMenuChangedL(*iMenu, + MSwtMenuArranger::ESwtMenuAdded); + } + + // If item displayed, update cascade icon + if (pane) + { + UpdatePaneL(*pane, ESwtMenuItemDataCascade); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::SetSelection +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::SetSelection(TBool aSelected) +{ + iSelected = aSelected; + + CEikMenuPane* pane = Pane(); + if (pane) + { + TRAP_IGNORE(UpdatePaneL(*pane, ESwtMenuItemDataSelection)); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::SetTextL +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::SetTextL(const TDesC& aText) +{ + if (iText) + { + delete iText; + iText = NULL; + } + iText = aText.AllocL(); + + CEikMenuPane* pane = Pane(); + if (pane) + { + UpdatePaneL(*pane, ESwtMenuItemDataText); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Accelerator +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TInt CSwtMenuItem::Accelerator() const +{ + return iAccelerator; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::IsEnabled +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TBool CSwtMenuItem::IsEnabled() const +{ + return iEnabled; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Image +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +const MSwtImage* CSwtMenuItem::Image() const +{ + return iImage; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::GetImageBitmapsL +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::GetImageBitmapsL(CFbsBitmap*& aBitmap, CFbsBitmap*& aMask, + const TSize& aSize) +{ + aBitmap = NULL; + aMask = NULL; + if (!iImage) + { + return; + } + + CFbsBitmap* bmp = const_cast(&iImage->SubBitmap(aSize)); + if (bmp) + { + if (iImageSizes.Find(aSize) == KErrNotFound) + { + iImage->AddSubRef(aSize); + iImageSizes.Append(aSize); + } + aBitmap = bmp; + aMask = const_cast(iImage->SubMaskBitmap(aSize, ETrue)); + + if (aMask == NULL) + { + if (!iDummyMask) + { + // MenuItem drawing does not support images with a NULL mask. + // So create a 2-bit black image mask with the same size as aSize + iDummyMask = new(ELeave) CFbsBitmap; + User::LeaveIfError(iDummyMask->Create(aSize, EGray2)); + + CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(iDummyMask); + CleanupStack::PushL(device); + CFbsBitGc* gc = CFbsBitGc::NewL(); + CleanupStack::PushL(gc); + + gc->Activate(device); + gc->SetPenStyle(CGraphicsContext::ENullPen); + gc->SetBrushStyle(CGraphicsContext::ESolidBrush); + gc->SetBrushColor(KRgbBlack); + gc->DrawRect(TRect(aSize)); + + CleanupStack::PopAndDestroy(gc); + CleanupStack::PopAndDestroy(device); + } + aMask = iDummyMask; + } + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Menu +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +const MSwtMenu* CSwtMenuItem::Menu() const +{ + return iMenu; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Text +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +const TDesC& CSwtMenuItem::Text() const +{ + if (iText) + { + return *iText; + } + else + { + return KNullDesC; + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::CommandId +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TInt CSwtMenuItem::CommandId() const +{ + return iCommandId; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Style +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +TInt CSwtMenuItem::Style() const +{ + return iStyle; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Parent +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +const MSwtMenu& CSwtMenuItem::Parent() const +{ + return iParent; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::UpdatePaneL +// From MSwtMenuItem +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::UpdatePaneL(CEikMenuPane& aPane, TSwtMenuItemData aDetail) +{ + TInt paneItemIndex; + CEikMenuPaneItem* paneItem(NULL); + + if (!aPane.MenuItemExists(iCommandId, paneItemIndex)) + { + return; + } + + paneItem = aPane.ItemAndPos(iCommandId, paneItemIndex); + if (!paneItem || paneItemIndex == KErrNotFound) + { + return; + } + + CEikMenuPaneItem::SData& data = paneItem->iData; + + // Text + if (aDetail == ESwtMenuItemDataAll || aDetail == ESwtMenuItemDataText) + { + TInt maxLength = data.iText.MaxLength(); + if (Text().Length() <= maxLength) + { + data.iText = Text(); + } + else + { + data.iText = Text().Left(maxLength - 1); + } + + // If push or cascade add some space after text to fix overlapping image + if (!(Style() & (KSwtStyleCheck | KSwtStyleRadio)) + && aPane.IsCascadeMenuPane() + && data.iText.Length() > 0) + { + TInt diff = data.iText.MaxLength() - data.iText.Length(); + if (diff >= KExtraSpaces().Length()) + { + data.iText.Append(KExtraSpaces); + } + } + + data.iExtraText = KNullDesC; + + if (aDetail != ESwtMenuItemDataAll) + { + return; + } + } + + // Cascade + if (aDetail == ESwtMenuItemDataAll || aDetail == ESwtMenuItemDataCascade) + { + if (iMenu) + { + if (iMenu->HasRadioGroup()) + { + data.iCascadeId = R_SWT_SUBMENUPANE_WITHRADIOGROUP; + } + else + { + data.iCascadeId = R_SWT_SUBMENUPANE; + } + } + else + { + data.iCascadeId = 0; + } + + if (aDetail != ESwtMenuItemDataAll) + { + return; + } + } + + // Selection + if (aDetail == ESwtMenuItemDataAll || aDetail == ESwtMenuItemDataSelection) + { + if (GetSelection()) + { + aPane.SetItemButtonState(iCommandId, EEikMenuItemSymbolOn); + } + else + { + aPane.SetItemButtonState(iCommandId, EEikMenuItemSymbolIndeterminate); + } + + if (aDetail != ESwtMenuItemDataAll) + { + return; + } + } + + // Flags + if (aDetail == ESwtMenuItemDataAll || aDetail == ESwtMenuItemDataFlags) + { + TInt index = Index(); + if (Style() & KSwtStyleRadio) + { + TInt firstRadioIndex = FirstRadioSibbling(); + TInt lastRadioIndex = LastRadioSibbling(); + if (index == firstRadioIndex) + { + if (index == firstRadioIndex) + { + data.iFlags |= EEikMenuItemRadioStart; + } + else if (index == lastRadioIndex) + { + data.iFlags |= EEikMenuItemRadioEnd; + } + else + { + data.iFlags |= EEikMenuItemRadioMiddle; + } + } + } + else if (Style() & KSwtStyleCheck) + { + data.iFlags |= EEikMenuItemCheckBox; + } + + if (iParent.Items() && index < iParent.Items()->Count() - 1 + && ((*iParent.Items())[index + 1]->Style() & KSwtStyleSeparator)) + { + data.iFlags |= EEikMenuItemSeparatorAfter; + } + + if (iParent.DefaultItem() == this) + { + aPane.SetSelectedItem(paneItemIndex); + } + + if (aDetail != ESwtMenuItemDataAll) + { + return; + } + } + + // Image. Keep it last. + if ((aDetail == ESwtMenuItemDataAll || aDetail == ESwtMenuItemDataImage)) + { + if (Image()) + { + // const cast for CreateIconL but bitmaps set as owned externally + // CeikMenuPaneItem does not modify the image so that using cast + // in relation to SetBitmapsOwnedExternally is safe. + MSwtImage* image = const_cast(Image()); + TSize iconRealSize = SwtControlHelper::GetAspectRatioScaledBitmapSize( + image->Bitmap().SizeInPixels(), iDisplay.MenuArranger().ImageSize()); + + CFbsBitmap* bmp = NULL; + CFbsBitmap* mask = NULL; + GetImageBitmapsL(bmp, mask, iconRealSize); + if (bmp) + { + paneItem->CreateIconL(bmp, mask); // bmp cannot be NULL here + paneItem->SetBitmapsOwnedExternally(ETrue); // Bitmaps deleted by CSwtImage + } + } + else + { + paneItem->SetIcon(NULL); + } + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Pane +// --------------------------------------------------------------------------- +// +CEikMenuPane* CSwtMenuItem::Pane() const +{ + CEikMenuPane* pane = iParent.Host(); + if (pane && pane->IsVisible()) + { + return pane; + } + else + { + return NULL; + } +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::FirstRadioSibbling +// --------------------------------------------------------------------------- +// +TInt CSwtMenuItem::FirstRadioSibbling() const +{ + if (iParent.Items()) + { + const RPointerArray& items = *iParent.Items(); + TInt count = items.Count(); + for (TInt i = 0; i < count; i++) + { + MSwtMenuItem* item = items[i]; + if (item && item->Style() & KSwtStyleRadio) + { + return i; + } + } + } + return KErrNotFound; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::LastRadioSibbling +// --------------------------------------------------------------------------- +// +TInt CSwtMenuItem::LastRadioSibbling() const +{ + if (iParent.Items()) + { + const RPointerArray& items = *iParent.Items(); + for (TInt i = items.Count() - 1; i >= 0; i--) + { + MSwtMenuItem* item = items[i]; + if (item && item->Style() & KSwtStyleRadio) + { + return i; + } + } + } + return KErrNotFound; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::Index +// --------------------------------------------------------------------------- +// +TInt CSwtMenuItem::Index() const +{ + TInt res = KErrNotFound; + if (iParent.Items()) + { + res = iParent.Items()->Find(this); + } + return res; +} + +// --------------------------------------------------------------------------- +// CSwtMenuItem::CleanPane +// --------------------------------------------------------------------------- +// +void CSwtMenuItem::CleanPane() const +{ + CEikMenuPane* pane = Pane(); + if (pane) + { + TInt index(KErrNotFound); + if (pane->MenuItemExists(iCommandId, index)) + { + pane->CloseCascadeMenu(); + pane->SetSelectedItem(0); + pane->DeleteMenuItem(iCommandId); + pane->HandleResourceChange(KEikDynamicLayoutVariantSwitch); + } + } +}