1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 * Retrieves and displays icons in native menu items on Mac OS X.
10 /* exception_defines.h defines 'try' to 'if (true)' which breaks objective-c
11 exceptions and produces errors like: error: unexpected '@' in program'.
12 If we define __EXCEPTIONS exception_defines.h will avoid doing this.
14 See bug 666609 for more information.
16 We use <limits> to get the libstdc++ version. */
18 #if __GLIBCXX__ <= 20070719
24 #include "MOZIconHelper.h"
25 #include "mozilla/dom/Document.h"
26 #include "mozilla/dom/DocumentInlines.h"
27 #include "nsCocoaUtils.h"
28 #include "nsComputedDOMStyle.h"
29 #include "nsContentUtils.h"
30 #include "nsGkAtoms.h"
31 #include "nsIContent.h"
32 #include "nsIContentPolicy.h"
33 #include "nsMenuItemX.h"
34 #include "nsMenuItemIconX.h"
35 #include "nsNameSpaceManager.h"
36 #include "nsObjCExceptions.h"
38 using namespace mozilla;
40 using mozilla::dom::Element;
41 using mozilla::widget::IconLoader;
43 static const uint32_t kIconSize = 16;
45 nsMenuItemIconX::nsMenuItemIconX(Listener* aListener) : mListener(aListener) {
46 MOZ_COUNT_CTOR(nsMenuItemIconX);
49 nsMenuItemIconX::~nsMenuItemIconX() {
51 mIconLoader->Destroy();
57 MOZ_COUNT_DTOR(nsMenuItemIconX);
60 void nsMenuItemIconX::SetupIcon(nsIContent* aContent) {
61 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
63 bool shouldHaveIcon = StartIconLoad(aContent);
64 if (!shouldHaveIcon) {
65 // There is no icon for this menu item, as an error occurred while loading
66 // it. An icon might have been set earlier or the place holder icon may have
67 // been set. Clear it.
76 // Set a placeholder icon, so that the menuitem reserves space for the icon
77 // during the load and there is no sudden shift once the icon finishes
79 NSSize iconSize = NSMakeSize(kIconSize, kIconSize);
80 mIconImage = [[MOZIconHelper placeholderIconWithSize:iconSize] retain];
83 NS_OBJC_END_TRY_ABORT_BLOCK;
86 bool nsMenuItemIconX::StartIconLoad(nsIContent* aContent) {
87 RefPtr<nsIURI> iconURI = GetIconURI(aContent);
93 mIconLoader = new IconLoader(this);
96 nsresult rv = mIconLoader->LoadIcon(iconURI, aContent);
97 return NS_SUCCEEDED(rv);
100 already_AddRefed<nsIURI> nsMenuItemIconX::GetIconURI(nsIContent* aContent) {
101 // First, look at the content node's "image" attribute.
102 nsAutoString imageURIString;
104 aContent->IsElement() &&
105 aContent->AsElement()->GetAttr(nsGkAtoms::image, imageURIString);
108 // Use the URL from the image attribute.
109 // If this menu item shouldn't have an icon, the string will be empty,
110 // and NS_NewURI will fail.
111 RefPtr<nsIURI> iconURI;
112 nsresult rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString);
116 return iconURI.forget();
119 // If the content node has no "image" attribute, get the
120 // "list-style-image" property from CSS.
121 RefPtr<mozilla::dom::Document> document = aContent->GetComposedDoc();
122 if (!document || !aContent->IsElement()) {
126 RefPtr<const ComputedStyle> sc =
127 nsComputedDOMStyle::GetComputedStyle(aContent->AsElement());
132 RefPtr<nsIURI> iconURI = sc->StyleList()->GetListStyleImageURI();
137 mComputedStyle = std::move(sc);
138 mPresContext = document->GetPresContext();
140 return iconURI.forget();
144 // mozilla::widget::IconLoader::Listener
147 nsresult nsMenuItemIconX::OnComplete(imgIContainer* aImage) {
148 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
151 [mIconImage release];
154 RefPtr<nsPresContext> pc = mPresContext.get();
155 mIconImage = [[MOZIconHelper
156 iconImageFromImageContainer:aImage
157 withSize:NSMakeSize(kIconSize, kIconSize)
159 computedStyle:mComputedStyle
160 scaleFactor:0.0f] retain];
161 mComputedStyle = nullptr;
162 mPresContext = nullptr;
165 mListener->IconUpdated();
168 mIconLoader->Destroy();
172 NS_OBJC_END_TRY_ABORT_BLOCK;