Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Attributes | Private Member Functions
nsMenuItemIcon Class Reference

#include <nsMenuItemIcon.h>

Inheritance diagram for nsMenuItemIcon:
Inheritance graph
[legend]
Collaboration diagram for nsMenuItemIcon:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsMenuItemIcon (nsISupports *aMenuItem, nsIMenu_MOZILLA_1_8_BRANCH *aMenu, nsIContent *aContent)
NS_DECL_ISUPPORTS
NS_DECL_IMGICONTAINEROBSERVER
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGIDECODEROBSERVER_MOZILLA_1_8_BRANCH
nsresult 
SetupIcon ()
nsresult GetIconURI (nsIURI **aIconURI)
nsresult LoadIcon (nsIURI *aIconURI)
PRBool ShouldLoadSync (nsIURI *aURI)
void onStartDecode (in imgIRequest aRequest)
 called as soon as the image begins getting decoded
void onStartContainer (in imgIRequest aRequest, in imgIContainer aContainer)
 called once the image has been inited and therefore has a width and height
void onStartFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame)
 called when each frame is created
void onDataAvailable (in imgIRequest aRequest, in gfxIImageFrame aFrame,[const ] in nsIntRect aRect)
 called when some part of the frame has new data in it
void onStopFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame)
 called when a frame is finished decoding
void onStopContainer (in imgIRequest aRequest, in imgIContainer aContainer)
 probably not needed.
void onStopDecode (in imgIRequest aRequest, in nsresult status, in wstring statusArg)
 called when the decoder is dying off
void frameChanged (in imgIContainer aContainer, in gfxIImageFrame aFrame, in nsIntRect aDirtyRect)
void onStartRequest (in imgIRequest aRequest)
 called at the same time that nsIRequestObserver::onStartRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)
void onStopRequest (in imgIRequest aRequest, in boolean aIsLastPart)
 called at the same time that nsIRequestObserver::onStopRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)

Protected Attributes

nsCOMPtr< nsIContentmContent
nsCOMPtr< imgIRequestmIconRequest
nsISupports * mMenuItem
nsIMenu_MOZILLA_1_8_BRANCHmMenu
MenuRef mMenuRef
PRUint16 mMenuItemIndex
PRPackedBool mLoadedIcon
PRPackedBool mSetIcon

Private Member Functions

 ~nsMenuItemIcon ()

Detailed Description

Definition at line 58 of file nsMenuItemIcon.h.


Constructor & Destructor Documentation

nsMenuItemIcon::nsMenuItemIcon ( nsISupports *  aMenuItem,
nsIMenu_MOZILLA_1_8_BRANCH aMenu,
nsIContent aContent 
)

Definition at line 103 of file nsMenuItemIcon.cpp.


Member Function Documentation

void imgIContainerObserver::frameChanged ( in imgIContainer  aContainer,
in gfxIImageFrame  aFrame,
in nsIntRect  aDirtyRect 
) [inherited]

Definition at line 144 of file nsMenuItemIcon.cpp.

{
  // Mac native menu items support having both a checkmark and an icon
  // simultaneously, but this is unheard of in the cross-platform toolkit,
  // seemingly because the win32 theme is unable to cope with both at once.
  // The downside is that it's possible to get a menu item marked with a
  // native checkmark and a checkmark for an icon.  Head off that possibility
  // by pretending that no icon exists if this is a checkable menu item.
  nsCOMPtr<nsIMenuItem> menuItem = do_QueryInterface(mMenuItem);
  if (menuItem) {
    nsIMenuItem::EMenuItemType menuItemType;
    menuItem->GetMenuItemType(&menuItemType);
    if (menuItemType == nsIMenuItem::eCheckbox ||
        menuItemType == nsIMenuItem::eRadio)
      return NS_ERROR_FAILURE;
  }

  if (!mContent) return NS_ERROR_FAILURE;

  // First, look at the content node's "image" attribute.
  nsAutoString imageURIString;
  nsresult rv = mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::image,
                                  imageURIString);

  if (rv != NS_CONTENT_ATTR_HAS_VALUE) {
    // If the content node has no "image" attribute, get the
    // "list-style-image" property from CSS.
    nsCOMPtr<nsIDOMDocumentView> domDocumentView =
     do_QueryInterface(mContent->GetDocument());
    if (!domDocumentView) return NS_ERROR_FAILURE;

    nsCOMPtr<nsIDOMAbstractView> domAbstractView;
    rv = domDocumentView->GetDefaultView(getter_AddRefs(domAbstractView));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIDOMViewCSS> domViewCSS = do_QueryInterface(domAbstractView);
    if (!domViewCSS) return NS_ERROR_FAILURE;

    nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mContent);
    if (!domElement) return NS_ERROR_FAILURE;

    nsCOMPtr<nsIDOMCSSStyleDeclaration> cssStyleDecl;
    nsAutoString empty;
    rv = domViewCSS->GetComputedStyle(domElement, empty,
                                      getter_AddRefs(cssStyleDecl));
    if (NS_FAILED(rv)) return rv;

    NS_NAMED_LITERAL_STRING(listStyleImage, "list-style-image");
    nsCOMPtr<nsIDOMCSSValue> cssValue;
    rv = cssStyleDecl->GetPropertyCSSValue(listStyleImage,
                                           getter_AddRefs(cssValue));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue =
     do_QueryInterface(cssValue);
    if (!primitiveValue) return NS_ERROR_FAILURE;

    PRUint16 primitiveType;
    rv = primitiveValue->GetPrimitiveType(&primitiveType);
    if (NS_FAILED(rv)) return rv;
    if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_URI)
      return NS_ERROR_FAILURE;

    rv = primitiveValue->GetStringValue(imageURIString);
    if (NS_FAILED(rv)) return rv;
  }

  // If this menu item shouldn't have an icon, the string will be empty,
  // and NS_NewURI will fail.
  nsCOMPtr<nsIURI> iconURI;
  rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString);
  if (NS_FAILED(rv)) return rv;

  *aIconURI = iconURI;
  NS_ADDREF(*aIconURI);
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 224 of file nsMenuItemIcon.cpp.

{
  if (mIconRequest) {
    // Another icon request is already in flight.  Kill it.
    mIconRequest->Cancel(NS_BINDING_ABORTED);
    mIconRequest = nsnull;
  }

  mLoadedIcon = PR_FALSE;

  if (!mContent) return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDocument> document = mContent->GetOwnerDoc();
  if (!document) return NS_ERROR_FAILURE;

  nsCOMPtr<nsILoadGroup> loadGroup = document->GetDocumentLoadGroup();
  if (!loadGroup) return NS_ERROR_FAILURE;

  nsresult rv = NS_ERROR_FAILURE;
  nsCOMPtr<imgILoader> loader = do_GetService("@mozilla.org/image/loader;1",
                                              &rv);
  if (NS_FAILED(rv)) return rv;

  if (!mSetIcon) {
    // Set a completely transparent 16x16 image as the icon on this menu item
    // as a placeholder.  This keeps the menu item text displayed in the same
    // position that it will be displayed when the real icon is loaded, and
    // prevents it from jumping around or looking misaligned.

    static PRBool sInitializedPlaceholder;
    static CGImageRef sPlaceholderIconImage;
    if (!sInitializedPlaceholder) {
      sInitializedPlaceholder = PR_TRUE;

      PRUint8* bitmap = (PRUint8*)PR_Malloc(kIconBytes);

      CGColorSpaceRef colorSpace = ::CGColorSpaceCreateDeviceRGB();

      CGContextRef bitmapContext;
      bitmapContext = ::CGBitmapContextCreate(bitmap, kIconWidth, kIconHeight,
                                              kIconBitsPerComponent,
                                              kIconBytesPerRow,
                                              colorSpace,
                                              kCGImageAlphaPremultipliedFirst);
      if (!bitmapContext) {
        PR_Free(bitmap);
        ::CGColorSpaceRelease(colorSpace);
        return NS_ERROR_FAILURE;
      }

      CGRect iconRect = ::CGRectMake(0, 0, kIconWidth, kIconHeight);
      ::CGContextClearRect(bitmapContext, iconRect);
      ::CGContextRelease(bitmapContext);

      CGDataProviderRef provider;
      provider = ::CGDataProviderCreateWithData(NULL, bitmap, kIconBytes,
                                              PRAllocCGFree);
      if (!provider) {
        PR_Free(bitmap);
        ::CGColorSpaceRelease(colorSpace);
        return NS_ERROR_FAILURE;
      }

      sPlaceholderIconImage =
       ::CGImageCreate(kIconWidth, kIconHeight, kIconBitsPerComponent,
                       kIconBitsPerPixel, kIconBytesPerRow, colorSpace,
                       kCGImageAlphaPremultipliedFirst, provider, NULL, TRUE,
                       kCGRenderingIntentDefault);
      ::CGColorSpaceRelease(colorSpace);
      ::CGDataProviderRelease(provider);
    }

    if (!sPlaceholderIconImage) return NS_ERROR_FAILURE;

    OSStatus err;
    err = ::SetMenuItemIconHandle(mMenuRef, mMenuItemIndex, kMenuCGImageRefType,
                                  (Handle)sPlaceholderIconImage);
    if (err != noErr) return NS_ERROR_FAILURE;
  }

  rv = loader->LoadImage(aIconURI, nsnull, nsnull, loadGroup, this,
                         nsnull, nsIRequest::LOAD_NORMAL, nsnull,
                         nsnull, getter_AddRefs(mIconRequest));
  if (NS_FAILED(rv)) return rv;

  // The icon will be picked up in OnStopFrame, which may be called after
  // LoadImage returns.  If the load is to be synchronous, ensure that
  // it completes now.

  if (ShouldLoadSync(aIconURI)) {
    // If there are any failures at this point, just return NS_OK and let
    // the image load asynchronously to completion.

    nsCOMPtr<nsIEventQueueService> eventQueueService = 
     do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
    if (NS_FAILED(rv)) return NS_OK;

    nsCOMPtr<nsIEventQueue> eventQueue;
    rv = eventQueueService->GetSpecialEventQueue(
     nsIEventQueueService::CURRENT_THREAD_EVENT_QUEUE,
     getter_AddRefs(eventQueue));
    if (NS_FAILED(rv)) return NS_OK;

    PLEvent* event;
    rv = NS_OK;
    while (!mLoadedIcon && mIconRequest && NS_SUCCEEDED(rv)) {
      rv = eventQueue->WaitForEvent(&event);
      if (NS_SUCCEEDED(rv))
        rv = eventQueue->HandleEvent(event);
    }
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void imgIDecoderObserver::onDataAvailable ( in imgIRequest  aRequest,
in gfxIImageFrame  aFrame,
[const ] in nsIntRect  aRect 
) [inherited]

called when some part of the frame has new data in it

void imgIDecoderObserver::onStartContainer ( in imgIRequest  aRequest,
in imgIContainer  aContainer 
) [inherited]

called once the image has been inited and therefore has a width and height

Here is the caller graph for this function:

called as soon as the image begins getting decoded

Here is the caller graph for this function:

void imgIDecoderObserver::onStartFrame ( in imgIRequest  aRequest,
in gfxIImageFrame  aFrame 
) [inherited]

called when each frame is created

called at the same time that nsIRequestObserver::onStartRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)

Unlike nsIRequestObserver::onStartRequest, this can be called synchronously.

void imgIDecoderObserver::onStopContainer ( in imgIRequest  aRequest,
in imgIContainer  aContainer 
) [inherited]

probably not needed.

called right before onStopDecode

Here is the caller graph for this function:

void imgIDecoderObserver::onStopDecode ( in imgIRequest  aRequest,
in nsresult  status,
in wstring  statusArg 
) [inherited]

called when the decoder is dying off

Here is the caller graph for this function:

void imgIDecoderObserver::onStopFrame ( in imgIRequest  aRequest,
in gfxIImageFrame  aFrame 
) [inherited]

called when a frame is finished decoding

called at the same time that nsIRequestObserver::onStopRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)

Unlike nsIRequestObserver::onStartRequest, this can be called synchronously.

Definition at line 111 of file nsMenuItemIcon.cpp.

{
  nsresult rv;
  if (!mMenuRef || !mMenuItemIndex) {
    // These values are initialized here instead of in the constructor
    // because they depend on the parent menu, mMenu, having inserted
    // this object into its array of children.  That can only happen after
    // the object is constructed.
    rv = mMenu->GetMenuRefAndItemIndexForMenuItem(mMenuItem,
                                                  (void**)&mMenuRef,
                                                  &mMenuItemIndex);
    if (NS_FAILED(rv)) return rv;
  }

  nsCOMPtr<nsIURI> iconURI;
  rv = GetIconURI(getter_AddRefs(iconURI));
  if (NS_FAILED(rv)) {
    // There is no icon for this menu item.  An icon might have been set
    // earlier.  Clear it.
    OSStatus err;
    err = ::SetMenuItemIconHandle(mMenuRef, mMenuItemIndex, kMenuNoIcon, NULL);
    if (err != noErr) return NS_ERROR_FAILURE;

    return NS_OK;
  }

  rv = LoadIcon(iconURI);

  return rv;
}

Here is the call graph for this function:

Definition at line 341 of file nsMenuItemIcon.cpp.

{
  // Older menu managers are unable to cope with menu item icons changing
  // while a menu is open in tracking.  On Panther (10.3), the updated icon
  // will not be displayed and highlighting of menu items in the affected
  // menu will be incorrect until menu tracking ends and the menu is
  // reopened.  On Jaguar (10.2), the updated icon will not be displayed
  // until the menu item is selected or deselected.  Tiger (10.4) does
  // not have these problems.
  //
  // Because icons are set in an imgIDecoderObserver notification, it's
  // possible and even likely that some icons will not be set until after the
  // menu is open.  On systems where this is known to cause trouble,
  // LoadIcon is made to set the icon on the menu item synchronously when
  // the source of the icon is local, as determined by the URI scheme.
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
  return PR_FALSE;
#else
  static PRBool sNeedsSync;

  static PRBool sInitialized;
  if (!sInitialized) {
    sInitialized = PR_TRUE;
    sNeedsSync = (nsToolkit::OSXVersion() < MAC_OS_X_VERSION_10_4_HEX);
  }

  if (sNeedsSync) {
    PRBool isLocalScheme;
    if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isLocalScheme)) &&
        isLocalScheme)
      return PR_TRUE;
    if (NS_SUCCEEDED(aURI->SchemeIs("data", &isLocalScheme)) &&
        isLocalScheme)
      return PR_TRUE;
    if (NS_SUCCEEDED(aURI->SchemeIs("moz-anno", &isLocalScheme)) &&
        isLocalScheme)
      return PR_TRUE;
  }

  return PR_FALSE;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 90 of file nsMenuItemIcon.h.

Definition at line 91 of file nsMenuItemIcon.h.

Definition at line 96 of file nsMenuItemIcon.h.

Definition at line 93 of file nsMenuItemIcon.h.

nsISupports* nsMenuItemIcon::mMenuItem [protected]

Definition at line 92 of file nsMenuItemIcon.h.

Definition at line 95 of file nsMenuItemIcon.h.

MenuRef nsMenuItemIcon::mMenuRef [protected]

Definition at line 94 of file nsMenuItemIcon.h.

Definition at line 97 of file nsMenuItemIcon.h.


The documentation for this class was generated from the following files: