Back to index

lightning-sunbird  0.9+nobinonly
inLayoutUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "inLayoutUtils.h"
00039 
00040 #include "nsIDOMDocumentView.h"
00041 #include "nsIDOMAbstractView.h"
00042 #include "nsIDOMNodeList.h"
00043 #include "nsIDocument.h"
00044 #include "nsIContent.h"
00045 #include "nsIContentViewer.h"
00046 #include "nsIScriptGlobalObject.h"
00047 #include "nsPIDOMWindow.h"
00048 #include "nsIDocShell.h"
00049 #include "nsIDocShellTreeItem.h"
00050 #include "nsIWebNavigation.h"
00051 #include "nsIPresShell.h"
00052 #include "nsIViewManager.h"
00053 #include "nsIWidget.h"
00054 #include "nsPresContext.h"
00055 #include "nsXULAtoms.h"
00056 #include "nsHTMLAtoms.h"
00057 
00059 
00060 nsIDOMWindowInternal*
00061 inLayoutUtils::GetWindowFor(nsIDOMNode* aNode)
00062 {
00063   nsCOMPtr<nsIDOMDocument> doc1;
00064   aNode->GetOwnerDocument(getter_AddRefs(doc1));
00065   return GetWindowFor(doc1.get());
00066 }
00067 
00068 nsIDOMWindowInternal*
00069 inLayoutUtils::GetWindowFor(nsIDOMDocument* aDoc)
00070 {
00071   nsCOMPtr<nsIDOMDocumentView> doc = do_QueryInterface(aDoc);
00072   if (!doc) return nsnull;
00073   
00074   nsCOMPtr<nsIDOMAbstractView> view;
00075   doc->GetDefaultView(getter_AddRefs(view));
00076   if (!view) return nsnull;
00077   
00078   nsCOMPtr<nsIDOMWindowInternal> window = do_QueryInterface(view);
00079   return window;
00080 }
00081 
00082 nsIPresShell* 
00083 inLayoutUtils::GetPresShellFor(nsISupports* aThing)
00084 {
00085   nsCOMPtr<nsIScriptGlobalObject> so = do_QueryInterface(aThing);
00086 
00087   nsCOMPtr<nsIPresShell> presShell;
00088   so->GetDocShell()->GetPresShell(getter_AddRefs(presShell));
00089 
00090   return presShell;
00091 }
00092 
00093 /*static*/
00094 nsIFrame*
00095 inLayoutUtils::GetFrameFor(nsIDOMElement* aElement, nsIPresShell* aShell)
00096 {
00097   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
00098   nsIFrame* frame = nsnull;
00099   aShell->GetPrimaryFrameFor(content, &frame);
00100 
00101   return frame;
00102 }
00103 
00104 already_AddRefed<nsIRenderingContext>
00105 inLayoutUtils::GetRenderingContextFor(nsIPresShell* aShell)
00106 {
00107   nsCOMPtr<nsIWidget> widget;
00108   aShell->GetViewManager()->GetWidget(getter_AddRefs(widget));
00109   return widget->GetRenderingContext(); // AddRefs
00110 }
00111 
00112 nsIEventStateManager*
00113 inLayoutUtils::GetEventStateManagerFor(nsIDOMElement *aElement)
00114 {
00115   NS_PRECONDITION(aElement, "Passing in a null element is bad");
00116 
00117   nsCOMPtr<nsIDOMDocument> domDoc;
00118   aElement->GetOwnerDocument(getter_AddRefs(domDoc));
00119   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
00120 
00121   if (!doc) {
00122     NS_WARNING("Could not get an nsIDocument!");
00123     return nsnull;
00124   }
00125 
00126   nsIPresShell *shell = doc->GetShellAt(0);
00127   NS_ASSERTION(shell, "No pres shell");
00128 
00129   return shell->GetPresContext()->EventStateManager();
00130 }
00131 
00132 nsPoint
00133 inLayoutUtils::GetClientOrigin(nsIFrame* aFrame)
00134 {
00135   nsPoint result(0,0);
00136   nsIView* view;
00137   aFrame->GetOffsetFromView(result, &view);
00138   nsIView* rootView = nsnull;
00139   if (view) {
00140       nsIViewManager* viewManager = view->GetViewManager();
00141       NS_ASSERTION(viewManager, "View must have a viewmanager");
00142       viewManager->GetRootView(rootView);
00143   }
00144   while (view) {
00145     result += view->GetPosition();
00146     if (view == rootView) {
00147       break;
00148     }
00149     view = view->GetParent();
00150   }
00151   return result;
00152 }
00153 
00154 nsRect& 
00155 inLayoutUtils::GetScreenOrigin(nsIDOMElement* aElement)
00156 {
00157   nsRect* rect = new nsRect(0,0,0,0);
00158  
00159   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
00160   nsCOMPtr<nsIDocument> doc = content->GetDocument();
00161 
00162   if (doc) {
00163     // Get Presentation shell 0
00164     nsIPresShell *presShell = doc->GetShellAt(0);
00165 
00166     if (presShell) {
00167       // Flush all pending notifications so that our frames are uptodate
00168       doc->FlushPendingNotifications(Flush_Layout);
00169 
00170       nsPresContext *presContext = presShell->GetPresContext();
00171       
00172       if (presContext) {
00173         nsIFrame* frame = nsnull;
00174         presShell->GetPrimaryFrameFor(content, &frame);
00175         
00176         PRInt32 offsetX = 0;
00177         PRInt32 offsetY = 0;
00178         nsIWidget* widget = nsnull;
00179         
00180         while (frame) {
00181           // Look for a widget so we can get screen coordinates
00182           nsIView* view = frame->GetViewExternal();
00183           if (view) {
00184             widget = view->GetWidget();
00185             if (widget)
00186               break;
00187           }
00188           
00189           // No widget yet, so count up the coordinates of the frame 
00190           nsPoint origin = frame->GetPosition();
00191           offsetX += origin.x;
00192           offsetY += origin.y;
00193       
00194           frame = frame->GetParent();
00195         }
00196         
00197         if (widget) {
00198           // Get the widget's screen coordinates
00199           nsRect oldBox(0,0,0,0);
00200           widget->WidgetToScreen(oldBox, *rect);
00201 
00202           // Get the scale from that Presentation Context
00203           float p2t;
00204           p2t = presContext->PixelsToTwips();
00205 
00206           // Convert screen rect to twips
00207           rect->x = NSIntPixelsToTwips(rect->x, p2t);
00208           rect->y = NSIntPixelsToTwips(rect->y, p2t);
00209 
00210           //  Add the offset we've counted
00211           rect->x += offsetX;
00212           rect->y += offsetY;
00213         }
00214       }
00215     }
00216   }
00217   
00218   return *rect;
00219 }
00220 
00221 nsIBindingManager* 
00222 inLayoutUtils::GetBindingManagerFor(nsIDOMNode* aNode)
00223 {
00224   nsCOMPtr<nsIDOMDocument> domdoc;
00225   aNode->GetOwnerDocument(getter_AddRefs(domdoc));
00226   if (domdoc) {
00227     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
00228     return doc->BindingManager();
00229   }
00230   
00231   return nsnull;
00232 }
00233 
00234 nsIDOMDocument*
00235 inLayoutUtils::GetSubDocumentFor(nsIDOMNode* aNode)
00236 {
00237   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
00238   if (content) {
00239     nsCOMPtr<nsIDocument> doc = content->GetDocument();
00240     if (doc) {
00241       nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(doc->GetSubDocumentFor(content)));
00242 
00243       return domdoc;
00244     }
00245   }
00246   
00247   return nsnull;
00248 }
00249 
00250 nsIDOMNode*
00251 inLayoutUtils::GetContainerFor(nsIDOMDocument* aDoc)
00252 {
00253   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
00254   if (!doc) return nsnull;
00255 
00256   nsPIDOMWindow *pwin = doc->GetWindow();
00257   if (!pwin) return nsnull;
00258 
00259   return pwin->GetFrameElementInternal();
00260 }
00261