--- /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 <eikon.hrh>
+#include <eikhkeyt.h>
+#include <AknDef.h>
+#include <eswtcore.rsg>
+#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<TInt>(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<CFbsBitmap*>(&iImage->SubBitmap(aSize));
+ if (bmp)
+ {
+ if (iImageSizes.Find(aSize) == KErrNotFound)
+ {
+ iImage->AddSubRef(aSize);
+ iImageSizes.Append(aSize);
+ }
+ aBitmap = bmp;
+ aMask = const_cast<CFbsBitmap*>(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<MSwtImage*>(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<MSwtMenuItem>& 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<MSwtMenuItem>& 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);
+ }
+ }
+}