LCOV - code coverage report
Current view: directory - layout/xul/base/src - nsBoxObject.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 236 15 6.4 %
Date: 2012-06-02 Functions: 38 7 18.4 %

       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                 :  *   Original Author: David W. Hyatt (hyatt@netscape.com)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsBoxObject.h"
      40                 : #include "nsCOMPtr.h"
      41                 : #include "nsIDocument.h"
      42                 : #include "nsIPresShell.h"
      43                 : #include "nsPresContext.h"
      44                 : #include "nsIContent.h"
      45                 : #include "nsIFrame.h"
      46                 : #include "nsIDocShell.h"
      47                 : #include "nsReadableUtils.h"
      48                 : #include "nsDOMClassInfoID.h"
      49                 : #include "nsIView.h"
      50                 : #ifdef MOZ_XUL
      51                 : #include "nsIDOMXULElement.h"
      52                 : #else
      53                 : #include "nsIDOMElement.h"
      54                 : #endif
      55                 : #include "nsLayoutUtils.h"
      56                 : #include "nsISupportsPrimitives.h"
      57                 : #include "prtypes.h"
      58                 : #include "nsSupportsPrimitives.h"
      59                 : #include "mozilla/dom/Element.h"
      60                 : 
      61                 : using namespace mozilla::dom;
      62                 : 
      63                 : // Implementation /////////////////////////////////////////////////////////////////
      64                 : 
      65                 : // Static member variable initialization
      66                 : 
      67                 : // Implement our nsISupports methods
      68                 : 
      69            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsBoxObject)
      70                 : 
      71               4 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBoxObject)
      72               4 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBoxObject)
      73                 : 
      74                 : DOMCI_DATA(BoxObject, nsBoxObject)
      75                 : 
      76                 : // QueryInterface implementation for nsBoxObject
      77               7 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsBoxObject)
      78               7 :   NS_INTERFACE_MAP_ENTRY(nsIBoxObject)
      79               5 :   NS_INTERFACE_MAP_ENTRY(nsPIBoxObject)
      80               5 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      81               4 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BoxObject)
      82               3 : NS_INTERFACE_MAP_END
      83                 : 
      84                 : PR_STATIC_CALLBACK(PLDHashOperator)
      85               0 : PropertyTraverser(const nsAString& aKey, nsISupports* aProperty, void* userArg)
      86                 : {
      87                 :   nsCycleCollectionTraversalCallback *cb = 
      88               0 :     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
      89                 : 
      90               0 :   cb->NoteXPCOMChild(aProperty);
      91                 : 
      92               0 :   return PL_DHASH_NEXT;
      93                 : }
      94                 : 
      95               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsBoxObject)
      96               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBoxObject)
      97               0 :   if (tmp->mPropertyTable) {
      98               0 :     tmp->mPropertyTable->EnumerateRead(PropertyTraverser, &cb);
      99                 :   }
     100               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     101                 : 
     102                 : // Constructors/Destructors
     103               1 : nsBoxObject::nsBoxObject(void)
     104               1 :   :mContent(nsnull)
     105                 : {
     106               1 : }
     107                 : 
     108               1 : nsBoxObject::~nsBoxObject(void)
     109                 : {
     110               2 : }
     111                 : 
     112                 : NS_IMETHODIMP
     113               0 : nsBoxObject::GetElement(nsIDOMElement** aResult)
     114                 : {
     115               0 :   if (mContent) {
     116               0 :     return CallQueryInterface(mContent, aResult);
     117                 :   }
     118                 : 
     119               0 :   *aResult = nsnull;
     120               0 :   return NS_OK;
     121                 : }
     122                 : 
     123                 : // nsPIBoxObject //////////////////////////////////////////////////////////////////////////
     124                 : 
     125                 : nsresult
     126               0 : nsBoxObject::Init(nsIContent* aContent)
     127                 : {
     128               0 :   mContent = aContent;
     129               0 :   return NS_OK;
     130                 : }
     131                 : 
     132                 : void
     133               0 : nsBoxObject::Clear()
     134                 : {
     135               0 :   mPropertyTable = nsnull;
     136               0 :   mContent = nsnull;
     137               0 : }
     138                 : 
     139                 : void
     140               0 : nsBoxObject::ClearCachedValues()
     141                 : {
     142               0 : }
     143                 : 
     144                 : nsIFrame*
     145               0 : nsBoxObject::GetFrame(bool aFlushLayout)
     146                 : {
     147               0 :   nsIPresShell* shell = GetPresShell(aFlushLayout);
     148               0 :   if (!shell)
     149               0 :     return nsnull;
     150                 : 
     151               0 :   if (!aFlushLayout) {
     152                 :     // If we didn't flush layout when getting the presshell, we should at least
     153                 :     // flush to make sure our frame model is up to date.
     154                 :     // XXXbz should flush on document, no?  Except people call this from
     155                 :     // frame code, maybe?
     156               0 :     shell->FlushPendingNotifications(Flush_Frames);
     157                 :   }
     158                 : 
     159                 :   // The flush might have killed mContent.
     160               0 :   if (!mContent) {
     161               0 :     return nsnull;
     162                 :   }
     163                 : 
     164               0 :   return mContent->GetPrimaryFrame();
     165                 : }
     166                 : 
     167                 : nsIPresShell*
     168               0 : nsBoxObject::GetPresShell(bool aFlushLayout)
     169                 : {
     170               0 :   if (!mContent) {
     171               0 :     return nsnull;
     172                 :   }
     173                 : 
     174               0 :   nsIDocument* doc = mContent->GetCurrentDoc();
     175               0 :   if (!doc) {
     176               0 :     return nsnull;
     177                 :   }
     178                 : 
     179               0 :   if (aFlushLayout) {
     180               0 :     doc->FlushPendingNotifications(Flush_Layout);
     181                 :   }
     182                 : 
     183               0 :   return doc->GetShell();
     184                 : }
     185                 : 
     186                 : nsresult 
     187               0 : nsBoxObject::GetOffsetRect(nsIntRect& aRect)
     188                 : {
     189               0 :   aRect.SetRect(0, 0, 0, 0);
     190                 :  
     191               0 :   if (!mContent)
     192               0 :     return NS_ERROR_NOT_INITIALIZED;
     193                 : 
     194                 :   // Get the Frame for our content
     195               0 :   nsIFrame* frame = GetFrame(true);
     196               0 :   if (frame) {
     197                 :     // Get its origin
     198               0 :     nsPoint origin = frame->GetPositionIgnoringScrolling();
     199                 : 
     200                 :     // Find the frame parent whose content is the document element.
     201               0 :     Element *docElement = mContent->GetCurrentDoc()->GetRootElement();
     202               0 :     nsIFrame* parent = frame->GetParent();
     203               0 :     for (;;) {
     204                 :       // If we've hit the document element, break here
     205               0 :       if (parent->GetContent() == docElement) {
     206               0 :         break;
     207                 :       }
     208                 : 
     209               0 :       nsIFrame* next = parent->GetParent();
     210               0 :       if (!next) {
     211               0 :         NS_WARNING("We should have hit the document element...");
     212               0 :         origin += parent->GetPosition();
     213               0 :         break;
     214                 :       }
     215                 : 
     216                 :       // Add the parent's origin to our own to get to the
     217                 :       // right coordinate system
     218               0 :       origin += next->GetPositionOfChildIgnoringScrolling(parent);
     219               0 :       parent = next;
     220                 :     }
     221                 :   
     222                 :     // For the origin, add in the border for the frame
     223               0 :     const nsStyleBorder* border = frame->GetStyleBorder();
     224               0 :     origin.x += border->GetActualBorderWidth(NS_SIDE_LEFT);
     225               0 :     origin.y += border->GetActualBorderWidth(NS_SIDE_TOP);
     226                 : 
     227                 :     // And subtract out the border for the parent
     228               0 :     const nsStyleBorder* parentBorder = parent->GetStyleBorder();
     229               0 :     origin.x -= parentBorder->GetActualBorderWidth(NS_SIDE_LEFT);
     230               0 :     origin.y -= parentBorder->GetActualBorderWidth(NS_SIDE_TOP);
     231                 : 
     232               0 :     aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
     233               0 :     aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
     234                 :     
     235                 :     // Get the union of all rectangles in this and continuation frames.
     236                 :     // It doesn't really matter what we use as aRelativeTo here, since
     237                 :     // we only care about the size. Using 'parent' might make things
     238                 :     // a bit faster by speeding up the internal GetOffsetTo operations.
     239               0 :     nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
     240               0 :     aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
     241               0 :     aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
     242                 :   }
     243                 : 
     244               0 :   return NS_OK;
     245                 : }
     246                 : 
     247                 : nsresult
     248               0 : nsBoxObject::GetScreenPosition(nsIntPoint& aPoint)
     249                 : {
     250               0 :   aPoint.x = aPoint.y = 0;
     251                 :   
     252               0 :   if (!mContent)
     253               0 :     return NS_ERROR_NOT_INITIALIZED;
     254                 : 
     255               0 :   nsIFrame* frame = GetFrame(true);
     256               0 :   if (frame) {
     257               0 :     nsIntRect rect = frame->GetScreenRect();
     258               0 :     aPoint.x = rect.x;
     259               0 :     aPoint.y = rect.y;
     260                 :   }
     261                 :   
     262               0 :   return NS_OK;
     263                 : }
     264                 : 
     265                 : NS_IMETHODIMP
     266               0 : nsBoxObject::GetX(PRInt32* aResult)
     267                 : {
     268               0 :   nsIntRect rect;
     269               0 :   GetOffsetRect(rect);
     270               0 :   *aResult = rect.x;
     271               0 :   return NS_OK;
     272                 : }
     273                 : 
     274                 : NS_IMETHODIMP 
     275               0 : nsBoxObject::GetY(PRInt32* aResult)
     276                 : {
     277               0 :   nsIntRect rect;
     278               0 :   GetOffsetRect(rect);
     279               0 :   *aResult = rect.y;
     280               0 :   return NS_OK;
     281                 : }
     282                 : 
     283                 : NS_IMETHODIMP
     284               0 : nsBoxObject::GetWidth(PRInt32* aResult)
     285                 : {
     286               0 :   nsIntRect rect;
     287               0 :   GetOffsetRect(rect);
     288               0 :   *aResult = rect.width;
     289               0 :   return NS_OK;
     290                 : }
     291                 : 
     292                 : NS_IMETHODIMP 
     293               0 : nsBoxObject::GetHeight(PRInt32* aResult)
     294                 : {
     295               0 :   nsIntRect rect;
     296               0 :   GetOffsetRect(rect);
     297               0 :   *aResult = rect.height;
     298               0 :   return NS_OK;
     299                 : }
     300                 : 
     301                 : NS_IMETHODIMP
     302               0 : nsBoxObject::GetScreenX(PRInt32 *_retval)
     303                 : {
     304               0 :   nsIntPoint position;
     305               0 :   nsresult rv = GetScreenPosition(position);
     306               0 :   if (NS_FAILED(rv)) return rv;
     307                 :   
     308               0 :   *_retval = position.x;
     309                 :   
     310               0 :   return NS_OK;
     311                 : }
     312                 : 
     313                 : NS_IMETHODIMP
     314               0 : nsBoxObject::GetScreenY(PRInt32 *_retval)
     315                 : {
     316               0 :   nsIntPoint position;
     317               0 :   nsresult rv = GetScreenPosition(position);
     318               0 :   if (NS_FAILED(rv)) return rv;
     319                 :   
     320               0 :   *_retval = position.y;
     321                 :   
     322               0 :   return NS_OK;
     323                 : }
     324                 : 
     325                 : NS_IMETHODIMP
     326               0 : nsBoxObject::GetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports** aResult)
     327                 : {
     328               0 :   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
     329               0 :   if (!mPropertyTable) {
     330               0 :     *aResult = nsnull;
     331               0 :     return NS_OK;
     332                 :   }
     333               0 :   nsDependentString propertyName(aPropertyName);
     334               0 :   mPropertyTable->Get(propertyName, aResult); // Addref here.
     335               0 :   return NS_OK;
     336                 : }
     337                 : 
     338                 : NS_IMETHODIMP
     339               0 : nsBoxObject::SetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports* aValue)
     340                 : {
     341               0 :   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
     342                 :   
     343               0 :   if (!mPropertyTable) {  
     344               0 :     mPropertyTable = new nsInterfaceHashtable<nsStringHashKey,nsISupports>;  
     345               0 :     if (!mPropertyTable) return NS_ERROR_OUT_OF_MEMORY;
     346               0 :     if (!mPropertyTable->Init(8)) {
     347               0 :        mPropertyTable = nsnull;
     348               0 :        return NS_ERROR_FAILURE;
     349                 :     }
     350                 :   }
     351                 : 
     352               0 :   nsDependentString propertyName(aPropertyName);
     353               0 :   if (!mPropertyTable->Put(propertyName, aValue))
     354               0 :     return NS_ERROR_OUT_OF_MEMORY;
     355               0 :   return NS_OK;
     356                 : }
     357                 : 
     358                 : NS_IMETHODIMP
     359               0 : nsBoxObject::GetProperty(const PRUnichar* aPropertyName, PRUnichar** aResult)
     360                 : {
     361               0 :   nsCOMPtr<nsISupports> data;
     362               0 :   nsresult rv = GetPropertyAsSupports(aPropertyName,getter_AddRefs(data));
     363               0 :   NS_ENSURE_SUCCESS(rv, rv);
     364                 : 
     365               0 :   if (!data) {
     366               0 :     *aResult = nsnull;
     367               0 :     return NS_OK;
     368                 :   }
     369                 : 
     370               0 :   nsCOMPtr<nsISupportsString> supportsStr = do_QueryInterface(data);
     371               0 :   if (!supportsStr) 
     372               0 :     return NS_ERROR_FAILURE;
     373                 :   
     374               0 :   return supportsStr->ToString(aResult);
     375                 : }
     376                 : 
     377                 : NS_IMETHODIMP
     378               0 : nsBoxObject::SetProperty(const PRUnichar* aPropertyName, const PRUnichar* aPropertyValue)
     379                 : {
     380               0 :   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
     381                 : 
     382               0 :   nsDependentString propertyName(aPropertyName);
     383               0 :   nsDependentString propertyValue;
     384               0 :   if (aPropertyValue) {
     385               0 :     propertyValue.Rebind(aPropertyValue);
     386                 :   } else {
     387               0 :     propertyValue.SetIsVoid(true);
     388                 :   }
     389                 :   
     390               0 :   nsCOMPtr<nsISupportsString> supportsStr(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
     391               0 :   NS_ENSURE_TRUE(supportsStr, NS_ERROR_OUT_OF_MEMORY);
     392               0 :   supportsStr->SetData(propertyValue);
     393                 : 
     394               0 :   return SetPropertyAsSupports(aPropertyName,supportsStr);
     395                 : }
     396                 : 
     397                 : NS_IMETHODIMP
     398               0 : nsBoxObject::RemoveProperty(const PRUnichar* aPropertyName)
     399                 : {
     400               0 :   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
     401                 : 
     402               0 :   if (!mPropertyTable) return NS_OK;
     403                 : 
     404               0 :   nsDependentString propertyName(aPropertyName);
     405               0 :   mPropertyTable->Remove(propertyName);
     406               0 :   return NS_OK;
     407                 : }
     408                 : 
     409                 : NS_IMETHODIMP 
     410               0 : nsBoxObject::GetParentBox(nsIDOMElement * *aParentBox)
     411                 : {
     412               0 :   *aParentBox = nsnull;
     413               0 :   nsIFrame* frame = GetFrame(false);
     414               0 :   if (!frame) return NS_OK;
     415               0 :   nsIFrame* parent = frame->GetParent();
     416               0 :   if (!parent) return NS_OK;
     417                 : 
     418               0 :   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(parent->GetContent());
     419               0 :   *aParentBox = el;
     420               0 :   NS_IF_ADDREF(*aParentBox);
     421               0 :   return NS_OK;
     422                 : }
     423                 : 
     424                 : NS_IMETHODIMP 
     425               0 : nsBoxObject::GetFirstChild(nsIDOMElement * *aFirstVisibleChild)
     426                 : {
     427               0 :   *aFirstVisibleChild = nsnull;
     428               0 :   nsIFrame* frame = GetFrame(false);
     429               0 :   if (!frame) return NS_OK;
     430               0 :   nsIFrame* firstFrame = frame->GetFirstPrincipalChild();
     431               0 :   if (!firstFrame) return NS_OK;
     432                 :   // get the content for the box and query to a dom element
     433               0 :   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(firstFrame->GetContent());
     434               0 :   el.swap(*aFirstVisibleChild);
     435               0 :   return NS_OK;
     436                 : }
     437                 : 
     438                 : NS_IMETHODIMP
     439               0 : nsBoxObject::GetLastChild(nsIDOMElement * *aLastVisibleChild)
     440                 : {
     441               0 :   *aLastVisibleChild = nsnull;
     442               0 :   nsIFrame* frame = GetFrame(false);
     443               0 :   if (!frame) return NS_OK;
     444               0 :   return GetPreviousSibling(frame, nsnull, aLastVisibleChild);
     445                 : }
     446                 : 
     447                 : NS_IMETHODIMP
     448               0 : nsBoxObject::GetNextSibling(nsIDOMElement **aNextOrdinalSibling)
     449                 : {
     450               0 :   *aNextOrdinalSibling = nsnull;
     451               0 :   nsIFrame* frame = GetFrame(false);
     452               0 :   if (!frame) return NS_OK;
     453               0 :   nsIFrame* nextFrame = frame->GetNextSibling();
     454               0 :   if (!nextFrame) return NS_OK;
     455                 :   // get the content for the box and query to a dom element
     456               0 :   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(nextFrame->GetContent());
     457               0 :   el.swap(*aNextOrdinalSibling);
     458               0 :   return NS_OK;
     459                 : }
     460                 : 
     461                 : NS_IMETHODIMP
     462               0 : nsBoxObject::GetPreviousSibling(nsIDOMElement **aPreviousOrdinalSibling)
     463                 : {
     464               0 :   *aPreviousOrdinalSibling = nsnull;
     465               0 :   nsIFrame* frame = GetFrame(false);
     466               0 :   if (!frame) return NS_OK;
     467               0 :   nsIFrame* parentFrame = frame->GetParent();
     468               0 :   if (!parentFrame) return NS_OK;
     469               0 :   return GetPreviousSibling(parentFrame, frame, aPreviousOrdinalSibling);
     470                 : }
     471                 : 
     472                 : nsresult
     473               0 : nsBoxObject::GetPreviousSibling(nsIFrame* aParentFrame, nsIFrame* aFrame,
     474                 :                                 nsIDOMElement** aResult)
     475                 : {
     476               0 :   *aResult = nsnull;
     477               0 :   nsIFrame* nextFrame = aParentFrame->GetFirstPrincipalChild();
     478               0 :   nsIFrame* prevFrame = nsnull;
     479               0 :   while (nextFrame) {
     480               0 :     if (nextFrame == aFrame)
     481               0 :       break;
     482               0 :     prevFrame = nextFrame;
     483               0 :     nextFrame = nextFrame->GetNextSibling();
     484                 :   }
     485                 :    
     486               0 :   if (!prevFrame) return NS_OK;
     487                 :   // get the content for the box and query to a dom element
     488               0 :   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(prevFrame->GetContent());
     489               0 :   el.swap(*aResult);
     490               0 :   return NS_OK;
     491                 : }
     492                 : 
     493                 : // Creation Routine ///////////////////////////////////////////////////////////////////////
     494                 : 
     495                 : nsresult
     496               0 : NS_NewBoxObject(nsIBoxObject** aResult)
     497                 : {
     498               0 :   *aResult = new nsBoxObject;
     499               0 :   if (!*aResult)
     500               0 :     return NS_ERROR_OUT_OF_MEMORY;
     501               0 :   NS_ADDREF(*aResult);
     502               0 :   return NS_OK;
     503            4392 : }
     504                 : 

Generated by: LCOV version 1.7