1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * David W. Hyatt <hyatt@netscape.com>
24 : * Ben Goodger <ben@netscape.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 : #include "nsCOMPtr.h"
40 : #include "nsIPopupBoxObject.h"
41 : #include "nsIRootBox.h"
42 : #include "nsBoxObject.h"
43 : #include "nsIPresShell.h"
44 : #include "nsFrameManager.h"
45 : #include "nsIContent.h"
46 : #include "nsIDocument.h"
47 : #include "nsIDOMDocument.h"
48 : #include "nsIDOMElement.h"
49 : #include "nsIFrame.h"
50 : #include "nsINameSpaceManager.h"
51 : #include "nsGkAtoms.h"
52 : #include "nsMenuPopupFrame.h"
53 : #include "nsClientRect.h"
54 :
55 : class nsPopupBoxObject : public nsBoxObject,
56 : public nsIPopupBoxObject
57 : {
58 : public:
59 : NS_DECL_ISUPPORTS_INHERITED
60 : NS_DECL_NSIPOPUPBOXOBJECT
61 :
62 0 : nsPopupBoxObject() {}
63 : protected:
64 0 : virtual ~nsPopupBoxObject() {}
65 :
66 : nsPopupSetFrame* GetPopupSetFrame();
67 0 : nsMenuPopupFrame* GetMenuPopupFrame()
68 : {
69 0 : nsIFrame* frame = GetFrame(false);
70 0 : if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame)
71 0 : return static_cast<nsMenuPopupFrame*>(frame);
72 0 : return nsnull;
73 : }
74 : };
75 :
76 0 : NS_IMPL_ISUPPORTS_INHERITED1(nsPopupBoxObject, nsBoxObject, nsIPopupBoxObject)
77 :
78 : nsPopupSetFrame*
79 0 : nsPopupBoxObject::GetPopupSetFrame()
80 : {
81 0 : nsIRootBox* rootBox = nsIRootBox::GetRootBox(GetPresShell(false));
82 0 : if (!rootBox)
83 0 : return nsnull;
84 :
85 0 : return rootBox->GetPopupSetFrame();
86 : }
87 :
88 : NS_IMETHODIMP
89 0 : nsPopupBoxObject::HidePopup()
90 : {
91 0 : nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
92 0 : if (pm && mContent)
93 0 : pm->HidePopup(mContent, false, true, false);
94 :
95 0 : return NS_OK;
96 : }
97 :
98 : NS_IMETHODIMP
99 0 : nsPopupBoxObject::ShowPopup(nsIDOMElement* aAnchorElement,
100 : nsIDOMElement* aPopupElement,
101 : PRInt32 aXPos, PRInt32 aYPos,
102 : const PRUnichar *aPopupType,
103 : const PRUnichar *aAnchorAlignment,
104 : const PRUnichar *aPopupAlignment)
105 : {
106 0 : NS_ENSURE_TRUE(aPopupElement, NS_ERROR_INVALID_ARG);
107 : // srcContent can be null.
108 :
109 0 : nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
110 0 : if (pm && mContent) {
111 0 : nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
112 0 : nsAutoString popupType(aPopupType);
113 0 : nsAutoString anchor(aAnchorAlignment);
114 0 : nsAutoString align(aPopupAlignment);
115 : pm->ShowPopupWithAnchorAlign(mContent, anchorContent, anchor, align,
116 0 : aXPos, aYPos, popupType.EqualsLiteral("context"));
117 : }
118 :
119 0 : return NS_OK;
120 : }
121 :
122 : NS_IMETHODIMP
123 0 : nsPopupBoxObject::OpenPopup(nsIDOMElement* aAnchorElement,
124 : const nsAString& aPosition,
125 : PRInt32 aXPos, PRInt32 aYPos,
126 : bool aIsContextMenu,
127 : bool aAttributesOverride,
128 : nsIDOMEvent* aTriggerEvent)
129 : {
130 0 : nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
131 0 : if (pm && mContent) {
132 0 : nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
133 : pm->ShowPopup(mContent, anchorContent, aPosition, aXPos, aYPos,
134 0 : aIsContextMenu, aAttributesOverride, false, aTriggerEvent);
135 : }
136 :
137 0 : return NS_OK;
138 : }
139 :
140 : NS_IMETHODIMP
141 0 : nsPopupBoxObject::OpenPopupAtScreen(PRInt32 aXPos, PRInt32 aYPos,
142 : bool aIsContextMenu,
143 : nsIDOMEvent* aTriggerEvent)
144 : {
145 0 : nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
146 0 : if (pm && mContent)
147 0 : pm->ShowPopupAtScreen(mContent, aXPos, aYPos, aIsContextMenu, aTriggerEvent);
148 0 : return NS_OK;
149 : }
150 :
151 : NS_IMETHODIMP
152 0 : nsPopupBoxObject::MoveTo(PRInt32 aLeft, PRInt32 aTop)
153 : {
154 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
155 0 : if (menuPopupFrame) {
156 0 : menuPopupFrame->MoveTo(aLeft, aTop, true);
157 : }
158 :
159 0 : return NS_OK;
160 : }
161 :
162 : NS_IMETHODIMP
163 0 : nsPopupBoxObject::SizeTo(PRInt32 aWidth, PRInt32 aHeight)
164 : {
165 0 : if (!mContent)
166 0 : return NS_OK;
167 :
168 0 : nsAutoString width, height;
169 0 : width.AppendInt(aWidth);
170 0 : height.AppendInt(aHeight);
171 :
172 0 : nsCOMPtr<nsIContent> content = mContent;
173 0 : content->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, false);
174 0 : content->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
175 :
176 0 : return NS_OK;
177 : }
178 :
179 : NS_IMETHODIMP
180 0 : nsPopupBoxObject::GetAutoPosition(bool* aShouldAutoPosition)
181 : {
182 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
183 0 : if (menuPopupFrame) {
184 0 : *aShouldAutoPosition = menuPopupFrame->GetAutoPosition();
185 : }
186 :
187 0 : return NS_OK;
188 : }
189 :
190 : NS_IMETHODIMP
191 0 : nsPopupBoxObject::SetAutoPosition(bool aShouldAutoPosition)
192 : {
193 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
194 0 : if (menuPopupFrame) {
195 0 : menuPopupFrame->SetAutoPosition(aShouldAutoPosition);
196 : }
197 :
198 0 : return NS_OK;
199 : }
200 :
201 : NS_IMETHODIMP
202 0 : nsPopupBoxObject::EnableRollup(bool aShouldRollup)
203 : {
204 : // this does nothing now
205 0 : return NS_OK;
206 : }
207 :
208 : NS_IMETHODIMP
209 0 : nsPopupBoxObject::SetConsumeRollupEvent(PRUint32 aConsume)
210 : {
211 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
212 0 : if (menuPopupFrame) {
213 0 : menuPopupFrame->SetConsumeRollupEvent(aConsume);
214 : }
215 :
216 0 : return NS_OK;
217 : }
218 :
219 : NS_IMETHODIMP
220 0 : nsPopupBoxObject::EnableKeyboardNavigator(bool aEnableKeyboardNavigator)
221 : {
222 0 : if (!mContent)
223 0 : return NS_OK;
224 :
225 : // Use ignorekeys="true" on the popup instead of using this function.
226 0 : if (aEnableKeyboardNavigator)
227 0 : mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys, true);
228 : else
229 : mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys,
230 0 : NS_LITERAL_STRING("true"), true);
231 :
232 0 : return NS_OK;
233 : }
234 :
235 : NS_IMETHODIMP
236 0 : nsPopupBoxObject::GetPopupState(nsAString& aState)
237 : {
238 : // set this here in case there's no frame for the popup
239 0 : aState.AssignLiteral("closed");
240 :
241 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
242 0 : if (menuPopupFrame) {
243 0 : switch (menuPopupFrame->PopupState()) {
244 : case ePopupShowing:
245 : case ePopupOpen:
246 0 : aState.AssignLiteral("showing");
247 0 : break;
248 : case ePopupOpenAndVisible:
249 0 : aState.AssignLiteral("open");
250 0 : break;
251 : case ePopupHiding:
252 : case ePopupInvisible:
253 0 : aState.AssignLiteral("hiding");
254 0 : break;
255 : case ePopupClosed:
256 0 : break;
257 : default:
258 0 : NS_NOTREACHED("Bad popup state");
259 0 : break;
260 : }
261 : }
262 :
263 0 : return NS_OK;
264 : }
265 :
266 : NS_IMETHODIMP
267 0 : nsPopupBoxObject::GetTriggerNode(nsIDOMNode** aTriggerNode)
268 : {
269 0 : *aTriggerNode = nsnull;
270 :
271 0 : nsIContent* triggerContent = nsMenuPopupFrame::GetTriggerContent(GetMenuPopupFrame());
272 0 : if (triggerContent)
273 0 : CallQueryInterface(triggerContent, aTriggerNode);
274 :
275 0 : return NS_OK;
276 : }
277 :
278 : NS_IMETHODIMP
279 0 : nsPopupBoxObject::GetAnchorNode(nsIDOMElement** aAnchor)
280 : {
281 0 : *aAnchor = nsnull;
282 :
283 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
284 0 : if (!menuPopupFrame)
285 0 : return NS_OK;
286 :
287 0 : nsIContent* anchor = menuPopupFrame->GetAnchor();
288 0 : if (anchor)
289 0 : CallQueryInterface(anchor, aAnchor);
290 :
291 0 : return NS_OK;
292 : }
293 :
294 : NS_IMETHODIMP
295 0 : nsPopupBoxObject::GetOuterScreenRect(nsIDOMClientRect** aRect)
296 : {
297 0 : nsClientRect* rect = new nsClientRect();
298 0 : if (!rect)
299 0 : return NS_ERROR_OUT_OF_MEMORY;
300 :
301 0 : NS_ADDREF(*aRect = rect);
302 :
303 0 : nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
304 0 : if (!menuPopupFrame)
305 0 : return NS_OK;
306 :
307 : // Return an empty rectangle if the popup is not open.
308 0 : nsPopupState state = menuPopupFrame->PopupState();
309 0 : if (state != ePopupOpen && state != ePopupOpenAndVisible)
310 0 : return NS_OK;
311 :
312 0 : nsIView* view = menuPopupFrame->GetView();
313 0 : if (view) {
314 0 : nsIWidget* widget = view->GetWidget();
315 0 : if (widget) {
316 0 : nsIntRect screenRect;
317 0 : widget->GetScreenBounds(screenRect);
318 :
319 0 : PRInt32 pp = menuPopupFrame->PresContext()->AppUnitsPerDevPixel();
320 0 : rect->SetLayoutRect(screenRect.ToAppUnits(pp));
321 : }
322 : }
323 :
324 0 : return NS_OK;
325 : }
326 :
327 : // Creation Routine ///////////////////////////////////////////////////////////////////////
328 :
329 : nsresult
330 0 : NS_NewPopupBoxObject(nsIBoxObject** aResult)
331 : {
332 0 : *aResult = new nsPopupBoxObject;
333 0 : if (!*aResult)
334 0 : return NS_ERROR_OUT_OF_MEMORY;
335 0 : NS_ADDREF(*aResult);
336 0 : return NS_OK;
337 : }
|