layout/xul/nsBoxObject.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     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/. */
     6 #include "nsBoxObject.h"
     7 #include "nsCOMPtr.h"
     8 #include "nsIDocument.h"
     9 #include "nsIPresShell.h"
    10 #include "nsPresContext.h"
    11 #include "nsIContent.h"
    12 #include "nsIFrame.h"
    13 #include "nsIDocShell.h"
    14 #include "nsReadableUtils.h"
    15 #include "nsDOMClassInfoID.h"
    16 #include "nsView.h"
    17 #ifdef MOZ_XUL
    18 #include "nsIDOMXULElement.h"
    19 #else
    20 #include "nsIDOMElement.h"
    21 #endif
    22 #include "nsLayoutUtils.h"
    23 #include "nsISupportsPrimitives.h"
    24 #include "nsSupportsPrimitives.h"
    25 #include "mozilla/dom/Element.h"
    26 #include "nsComponentManagerUtils.h"
    28 using namespace mozilla::dom;
    30 // Implementation /////////////////////////////////////////////////////////////////
    32 // Static member variable initialization
    34 // Implement our nsISupports methods
    36 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBoxObject)
    37 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBoxObject)
    39 DOMCI_DATA(BoxObject, nsBoxObject)
    41 // QueryInterface implementation for nsBoxObject
    42 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsBoxObject)
    43   NS_INTERFACE_MAP_ENTRY(nsIBoxObject)
    44   NS_INTERFACE_MAP_ENTRY(nsPIBoxObject)
    45   NS_INTERFACE_MAP_ENTRY(nsISupports)
    46   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BoxObject)
    47 NS_INTERFACE_MAP_END
    49 static PLDHashOperator
    50 PropertyTraverser(const nsAString& aKey, nsISupports* aProperty, void* userArg)
    51 {
    52   nsCycleCollectionTraversalCallback *cb = 
    53     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
    55   cb->NoteXPCOMChild(aProperty);
    57   return PL_DHASH_NEXT;
    58 }
    60 NS_IMPL_CYCLE_COLLECTION_CLASS(nsBoxObject)
    62 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsBoxObject)
    63 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBoxObject)
    64   if (tmp->mPropertyTable) {
    65     tmp->mPropertyTable->EnumerateRead(PropertyTraverser, &cb);
    66   }
    67 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    69 // Constructors/Destructors
    70 nsBoxObject::nsBoxObject(void)
    71   :mContent(nullptr)
    72 {
    73 }
    75 nsBoxObject::~nsBoxObject(void)
    76 {
    77 }
    79 NS_IMETHODIMP
    80 nsBoxObject::GetElement(nsIDOMElement** aResult)
    81 {
    82   if (mContent) {
    83     return CallQueryInterface(mContent, aResult);
    84   }
    86   *aResult = nullptr;
    87   return NS_OK;
    88 }
    90 // nsPIBoxObject //////////////////////////////////////////////////////////////////////////
    92 nsresult
    93 nsBoxObject::Init(nsIContent* aContent)
    94 {
    95   mContent = aContent;
    96   return NS_OK;
    97 }
    99 void
   100 nsBoxObject::Clear()
   101 {
   102   mPropertyTable = nullptr;
   103   mContent = nullptr;
   104 }
   106 void
   107 nsBoxObject::ClearCachedValues()
   108 {
   109 }
   111 nsIFrame*
   112 nsBoxObject::GetFrame(bool aFlushLayout)
   113 {
   114   nsIPresShell* shell = GetPresShell(aFlushLayout);
   115   if (!shell)
   116     return nullptr;
   118   if (!aFlushLayout) {
   119     // If we didn't flush layout when getting the presshell, we should at least
   120     // flush to make sure our frame model is up to date.
   121     // XXXbz should flush on document, no?  Except people call this from
   122     // frame code, maybe?
   123     shell->FlushPendingNotifications(Flush_Frames);
   124   }
   126   // The flush might have killed mContent.
   127   if (!mContent) {
   128     return nullptr;
   129   }
   131   return mContent->GetPrimaryFrame();
   132 }
   134 nsIPresShell*
   135 nsBoxObject::GetPresShell(bool aFlushLayout)
   136 {
   137   if (!mContent) {
   138     return nullptr;
   139   }
   141   nsCOMPtr<nsIDocument> doc = mContent->GetCurrentDoc();
   142   if (!doc) {
   143     return nullptr;
   144   }
   146   if (aFlushLayout) {
   147     doc->FlushPendingNotifications(Flush_Layout);
   148   }
   150   return doc->GetShell();
   151 }
   153 nsresult 
   154 nsBoxObject::GetOffsetRect(nsIntRect& aRect)
   155 {
   156   aRect.SetRect(0, 0, 0, 0);
   158   if (!mContent)
   159     return NS_ERROR_NOT_INITIALIZED;
   161   // Get the Frame for our content
   162   nsIFrame* frame = GetFrame(true);
   163   if (frame) {
   164     // Get its origin
   165     nsPoint origin = frame->GetPositionIgnoringScrolling();
   167     // Find the frame parent whose content is the document element.
   168     Element *docElement = mContent->GetCurrentDoc()->GetRootElement();
   169     nsIFrame* parent = frame->GetParent();
   170     for (;;) {
   171       // If we've hit the document element, break here
   172       if (parent->GetContent() == docElement) {
   173         break;
   174       }
   176       nsIFrame* next = parent->GetParent();
   177       if (!next) {
   178         NS_WARNING("We should have hit the document element...");
   179         origin += parent->GetPosition();
   180         break;
   181       }
   183       // Add the parent's origin to our own to get to the
   184       // right coordinate system
   185       origin += next->GetPositionOfChildIgnoringScrolling(parent);
   186       parent = next;
   187     }
   189     // For the origin, add in the border for the frame
   190     const nsStyleBorder* border = frame->StyleBorder();
   191     origin.x += border->GetComputedBorderWidth(NS_SIDE_LEFT);
   192     origin.y += border->GetComputedBorderWidth(NS_SIDE_TOP);
   194     // And subtract out the border for the parent
   195     const nsStyleBorder* parentBorder = parent->StyleBorder();
   196     origin.x -= parentBorder->GetComputedBorderWidth(NS_SIDE_LEFT);
   197     origin.y -= parentBorder->GetComputedBorderWidth(NS_SIDE_TOP);
   199     aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
   200     aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
   202     // Get the union of all rectangles in this and continuation frames.
   203     // It doesn't really matter what we use as aRelativeTo here, since
   204     // we only care about the size. Using 'parent' might make things
   205     // a bit faster by speeding up the internal GetOffsetTo operations.
   206     nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
   207     aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
   208     aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
   209   }
   211   return NS_OK;
   212 }
   214 nsresult
   215 nsBoxObject::GetScreenPosition(nsIntPoint& aPoint)
   216 {
   217   aPoint.x = aPoint.y = 0;
   219   if (!mContent)
   220     return NS_ERROR_NOT_INITIALIZED;
   222   nsIFrame* frame = GetFrame(true);
   223   if (frame) {
   224     nsIntRect rect = frame->GetScreenRect();
   225     aPoint.x = rect.x;
   226     aPoint.y = rect.y;
   227   }
   229   return NS_OK;
   230 }
   232 NS_IMETHODIMP
   233 nsBoxObject::GetX(int32_t* aResult)
   234 {
   235   nsIntRect rect;
   236   GetOffsetRect(rect);
   237   *aResult = rect.x;
   238   return NS_OK;
   239 }
   241 NS_IMETHODIMP 
   242 nsBoxObject::GetY(int32_t* aResult)
   243 {
   244   nsIntRect rect;
   245   GetOffsetRect(rect);
   246   *aResult = rect.y;
   247   return NS_OK;
   248 }
   250 NS_IMETHODIMP
   251 nsBoxObject::GetWidth(int32_t* aResult)
   252 {
   253   nsIntRect rect;
   254   GetOffsetRect(rect);
   255   *aResult = rect.width;
   256   return NS_OK;
   257 }
   259 NS_IMETHODIMP 
   260 nsBoxObject::GetHeight(int32_t* aResult)
   261 {
   262   nsIntRect rect;
   263   GetOffsetRect(rect);
   264   *aResult = rect.height;
   265   return NS_OK;
   266 }
   268 NS_IMETHODIMP
   269 nsBoxObject::GetScreenX(int32_t *_retval)
   270 {
   271   nsIntPoint position;
   272   nsresult rv = GetScreenPosition(position);
   273   if (NS_FAILED(rv)) return rv;
   275   *_retval = position.x;
   277   return NS_OK;
   278 }
   280 NS_IMETHODIMP
   281 nsBoxObject::GetScreenY(int32_t *_retval)
   282 {
   283   nsIntPoint position;
   284   nsresult rv = GetScreenPosition(position);
   285   if (NS_FAILED(rv)) return rv;
   287   *_retval = position.y;
   289   return NS_OK;
   290 }
   292 NS_IMETHODIMP
   293 nsBoxObject::GetPropertyAsSupports(const char16_t* aPropertyName, nsISupports** aResult)
   294 {
   295   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
   296   if (!mPropertyTable) {
   297     *aResult = nullptr;
   298     return NS_OK;
   299   }
   300   nsDependentString propertyName(aPropertyName);
   301   mPropertyTable->Get(propertyName, aResult); // Addref here.
   302   return NS_OK;
   303 }
   305 NS_IMETHODIMP
   306 nsBoxObject::SetPropertyAsSupports(const char16_t* aPropertyName, nsISupports* aValue)
   307 {
   308   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
   310   if (!mPropertyTable) {  
   311     mPropertyTable = new nsInterfaceHashtable<nsStringHashKey,nsISupports>(8);
   312   }
   314   nsDependentString propertyName(aPropertyName);
   315   mPropertyTable->Put(propertyName, aValue);
   316   return NS_OK;
   317 }
   319 NS_IMETHODIMP
   320 nsBoxObject::GetProperty(const char16_t* aPropertyName, char16_t** aResult)
   321 {
   322   nsCOMPtr<nsISupports> data;
   323   nsresult rv = GetPropertyAsSupports(aPropertyName,getter_AddRefs(data));
   324   NS_ENSURE_SUCCESS(rv, rv);
   326   if (!data) {
   327     *aResult = nullptr;
   328     return NS_OK;
   329   }
   331   nsCOMPtr<nsISupportsString> supportsStr = do_QueryInterface(data);
   332   if (!supportsStr) 
   333     return NS_ERROR_FAILURE;
   335   return supportsStr->ToString(aResult);
   336 }
   338 NS_IMETHODIMP
   339 nsBoxObject::SetProperty(const char16_t* aPropertyName, const char16_t* aPropertyValue)
   340 {
   341   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
   343   nsDependentString propertyName(aPropertyName);
   344   nsDependentString propertyValue;
   345   if (aPropertyValue) {
   346     propertyValue.Rebind(aPropertyValue);
   347   } else {
   348     propertyValue.SetIsVoid(true);
   349   }
   351   nsCOMPtr<nsISupportsString> supportsStr(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
   352   NS_ENSURE_TRUE(supportsStr, NS_ERROR_OUT_OF_MEMORY);
   353   supportsStr->SetData(propertyValue);
   355   return SetPropertyAsSupports(aPropertyName,supportsStr);
   356 }
   358 NS_IMETHODIMP
   359 nsBoxObject::RemoveProperty(const char16_t* aPropertyName)
   360 {
   361   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
   363   if (!mPropertyTable) return NS_OK;
   365   nsDependentString propertyName(aPropertyName);
   366   mPropertyTable->Remove(propertyName);
   367   return NS_OK;
   368 }
   370 NS_IMETHODIMP 
   371 nsBoxObject::GetParentBox(nsIDOMElement * *aParentBox)
   372 {
   373   *aParentBox = nullptr;
   374   nsIFrame* frame = GetFrame(false);
   375   if (!frame) return NS_OK;
   376   nsIFrame* parent = frame->GetParent();
   377   if (!parent) return NS_OK;
   379   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(parent->GetContent());
   380   *aParentBox = el;
   381   NS_IF_ADDREF(*aParentBox);
   382   return NS_OK;
   383 }
   385 NS_IMETHODIMP 
   386 nsBoxObject::GetFirstChild(nsIDOMElement * *aFirstVisibleChild)
   387 {
   388   *aFirstVisibleChild = nullptr;
   389   nsIFrame* frame = GetFrame(false);
   390   if (!frame) return NS_OK;
   391   nsIFrame* firstFrame = frame->GetFirstPrincipalChild();
   392   if (!firstFrame) return NS_OK;
   393   // get the content for the box and query to a dom element
   394   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(firstFrame->GetContent());
   395   el.swap(*aFirstVisibleChild);
   396   return NS_OK;
   397 }
   399 NS_IMETHODIMP
   400 nsBoxObject::GetLastChild(nsIDOMElement * *aLastVisibleChild)
   401 {
   402   *aLastVisibleChild = nullptr;
   403   nsIFrame* frame = GetFrame(false);
   404   if (!frame) return NS_OK;
   405   return GetPreviousSibling(frame, nullptr, aLastVisibleChild);
   406 }
   408 NS_IMETHODIMP
   409 nsBoxObject::GetNextSibling(nsIDOMElement **aNextOrdinalSibling)
   410 {
   411   *aNextOrdinalSibling = nullptr;
   412   nsIFrame* frame = GetFrame(false);
   413   if (!frame) return NS_OK;
   414   nsIFrame* nextFrame = frame->GetNextSibling();
   415   if (!nextFrame) return NS_OK;
   416   // get the content for the box and query to a dom element
   417   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(nextFrame->GetContent());
   418   el.swap(*aNextOrdinalSibling);
   419   return NS_OK;
   420 }
   422 NS_IMETHODIMP
   423 nsBoxObject::GetPreviousSibling(nsIDOMElement **aPreviousOrdinalSibling)
   424 {
   425   *aPreviousOrdinalSibling = nullptr;
   426   nsIFrame* frame = GetFrame(false);
   427   if (!frame) return NS_OK;
   428   nsIFrame* parentFrame = frame->GetParent();
   429   if (!parentFrame) return NS_OK;
   430   return GetPreviousSibling(parentFrame, frame, aPreviousOrdinalSibling);
   431 }
   433 nsresult
   434 nsBoxObject::GetPreviousSibling(nsIFrame* aParentFrame, nsIFrame* aFrame,
   435                                 nsIDOMElement** aResult)
   436 {
   437   *aResult = nullptr;
   438   nsIFrame* nextFrame = aParentFrame->GetFirstPrincipalChild();
   439   nsIFrame* prevFrame = nullptr;
   440   while (nextFrame) {
   441     if (nextFrame == aFrame)
   442       break;
   443     prevFrame = nextFrame;
   444     nextFrame = nextFrame->GetNextSibling();
   445   }
   447   if (!prevFrame) return NS_OK;
   448   // get the content for the box and query to a dom element
   449   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(prevFrame->GetContent());
   450   el.swap(*aResult);
   451   return NS_OK;
   452 }
   454 // Creation Routine ///////////////////////////////////////////////////////////////////////
   456 nsresult
   457 NS_NewBoxObject(nsIBoxObject** aResult)
   458 {
   459   *aResult = new nsBoxObject;
   460   if (!*aResult)
   461     return NS_ERROR_OUT_OF_MEMORY;
   462   NS_ADDREF(*aResult);
   463   return NS_OK;
   464 }

mercurial