layout/xul/tree/nsTreeColumns.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     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 "nsNameSpaceManager.h"
     7 #include "nsGkAtoms.h"
     8 #include "nsIDOMElement.h"
     9 #include "nsIBoxObject.h"
    10 #include "nsTreeColumns.h"
    11 #include "nsTreeUtils.h"
    12 #include "nsStyleContext.h"
    13 #include "nsDOMClassInfoID.h"
    14 #include "nsINodeInfo.h"
    15 #include "nsContentUtils.h"
    16 #include "nsTreeBodyFrame.h"
    17 #include "mozilla/dom/Element.h"
    18 #include "mozilla/dom/TreeColumnsBinding.h"
    20 using namespace mozilla;
    22 // Column class that caches all the info about our column.
    23 nsTreeColumn::nsTreeColumn(nsTreeColumns* aColumns, nsIContent* aContent)
    24   : mContent(aContent),
    25     mColumns(aColumns),
    26     mPrevious(nullptr)
    27 {
    28   NS_ASSERTION(aContent &&
    29                aContent->NodeInfo()->Equals(nsGkAtoms::treecol,
    30                                             kNameSpaceID_XUL),
    31                "nsTreeColumn's content must be a <xul:treecol>");
    33   Invalidate();
    34 }
    36 nsTreeColumn::~nsTreeColumn()
    37 {
    38   if (mNext) {
    39     mNext->SetPrevious(nullptr);
    40   }
    41 }
    43 NS_IMPL_CYCLE_COLLECTION_CLASS(nsTreeColumn)
    45 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTreeColumn)
    46   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
    47   if (tmp->mNext) {
    48     tmp->mNext->SetPrevious(nullptr);
    49     NS_IMPL_CYCLE_COLLECTION_UNLINK(mNext)
    50   }
    51 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    52 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTreeColumn)
    53   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
    54   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNext)
    55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    57 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeColumn)
    58 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeColumn)
    60 DOMCI_DATA(TreeColumn, nsTreeColumn)
    62 // QueryInterface implementation for nsTreeColumn
    63 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeColumn)
    64   NS_INTERFACE_MAP_ENTRY(nsITreeColumn)
    65   NS_INTERFACE_MAP_ENTRY(nsISupports)
    66   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TreeColumn)
    67   if (aIID.Equals(NS_GET_IID(nsTreeColumn))) {
    68     AddRef();
    69     *aInstancePtr = this;
    70     return NS_OK;
    71   }
    72   else
    73 NS_INTERFACE_MAP_END
    75 nsIFrame*
    76 nsTreeColumn::GetFrame()
    77 {
    78   NS_ENSURE_TRUE(mContent, nullptr);
    80   return mContent->GetPrimaryFrame();
    81 }
    83 bool
    84 nsTreeColumn::IsLastVisible(nsTreeBodyFrame* aBodyFrame)
    85 {
    86   NS_ASSERTION(GetFrame(), "should have checked for this already");
    88   // cyclers are fixed width, don't adjust them
    89   if (IsCycler())
    90     return false;
    92   // we're certainly not the last visible if we're not visible
    93   if (GetFrame()->GetRect().width == 0)
    94     return false;
    96   // try to find a visible successor
    97   for (nsTreeColumn *next = GetNext(); next; next = next->GetNext()) {
    98     nsIFrame* frame = next->GetFrame();
    99     if (frame && frame->GetRect().width > 0)
   100       return false;
   101   }
   102   return true;
   103 }
   105 nsresult
   106 nsTreeColumn::GetRect(nsTreeBodyFrame* aBodyFrame, nscoord aY, nscoord aHeight, nsRect* aResult)
   107 {
   108   nsIFrame* frame = GetFrame();
   109   if (!frame) {
   110     *aResult = nsRect();
   111     return NS_ERROR_FAILURE;
   112   }
   114   bool isRTL = aBodyFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
   115   *aResult = frame->GetRect();
   116   aResult->y = aY;
   117   aResult->height = aHeight;
   118   if (isRTL)
   119     aResult->x += aBodyFrame->mAdjustWidth;
   120   else if (IsLastVisible(aBodyFrame))
   121     aResult->width += aBodyFrame->mAdjustWidth;
   122   return NS_OK;
   123 }
   125 nsresult
   126 nsTreeColumn::GetXInTwips(nsTreeBodyFrame* aBodyFrame, nscoord* aResult)
   127 {
   128   nsIFrame* frame = GetFrame();
   129   if (!frame) {
   130     *aResult = 0;
   131     return NS_ERROR_FAILURE;
   132   }
   133   *aResult = frame->GetRect().x;
   134   return NS_OK;
   135 }
   137 nsresult
   138 nsTreeColumn::GetWidthInTwips(nsTreeBodyFrame* aBodyFrame, nscoord* aResult)
   139 {
   140   nsIFrame* frame = GetFrame();
   141   if (!frame) {
   142     *aResult = 0;
   143     return NS_ERROR_FAILURE;
   144   }
   145   *aResult = frame->GetRect().width;
   146   if (IsLastVisible(aBodyFrame))
   147     *aResult += aBodyFrame->mAdjustWidth;
   148   return NS_OK;
   149 }
   152 NS_IMETHODIMP
   153 nsTreeColumn::GetElement(nsIDOMElement** aElement)
   154 {
   155   if (mContent) {
   156     return CallQueryInterface(mContent, aElement);
   157   }
   158   *aElement = nullptr;
   159   return NS_ERROR_FAILURE;
   160 }
   162 NS_IMETHODIMP
   163 nsTreeColumn::GetColumns(nsITreeColumns** aColumns)
   164 {
   165   NS_IF_ADDREF(*aColumns = mColumns);
   166   return NS_OK;
   167 }
   169 NS_IMETHODIMP
   170 nsTreeColumn::GetX(int32_t* aX)
   171 {
   172   nsIFrame* frame = GetFrame();
   173   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
   175   *aX = nsPresContext::AppUnitsToIntCSSPixels(frame->GetRect().x);
   176   return NS_OK;
   177 }
   179 NS_IMETHODIMP
   180 nsTreeColumn::GetWidth(int32_t* aWidth)
   181 {
   182   nsIFrame* frame = GetFrame();
   183   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
   185   *aWidth = nsPresContext::AppUnitsToIntCSSPixels(frame->GetRect().width);
   186   return NS_OK;
   187 }
   189 NS_IMETHODIMP
   190 nsTreeColumn::GetId(nsAString& aId)
   191 {
   192   aId = GetId();
   193   return NS_OK;
   194 }
   196 NS_IMETHODIMP
   197 nsTreeColumn::GetIdConst(const char16_t** aIdConst)
   198 {
   199   *aIdConst = mId.get();
   200   return NS_OK;
   201 }
   203 NS_IMETHODIMP
   204 nsTreeColumn::GetAtom(nsIAtom** aAtom)
   205 {
   206   NS_IF_ADDREF(*aAtom = GetAtom());
   207   return NS_OK;
   208 }
   210 NS_IMETHODIMP
   211 nsTreeColumn::GetIndex(int32_t* aIndex)
   212 {
   213   *aIndex = GetIndex();
   214   return NS_OK;
   215 }
   217 NS_IMETHODIMP
   218 nsTreeColumn::GetPrimary(bool* aPrimary)
   219 {
   220   *aPrimary = IsPrimary();
   221   return NS_OK;
   222 }
   224 NS_IMETHODIMP
   225 nsTreeColumn::GetCycler(bool* aCycler)
   226 {
   227   *aCycler = IsCycler();
   228   return NS_OK;
   229 }
   231 NS_IMETHODIMP
   232 nsTreeColumn::GetEditable(bool* aEditable)
   233 {
   234   *aEditable = IsEditable();
   235   return NS_OK;
   236 }
   238 NS_IMETHODIMP
   239 nsTreeColumn::GetSelectable(bool* aSelectable)
   240 {
   241   *aSelectable = IsSelectable();
   242   return NS_OK;
   243 }
   245 NS_IMETHODIMP
   246 nsTreeColumn::GetType(int16_t* aType)
   247 {
   248   *aType = GetType();
   249   return NS_OK;
   250 }
   252 NS_IMETHODIMP
   253 nsTreeColumn::GetNext(nsITreeColumn** _retval)
   254 {
   255   NS_IF_ADDREF(*_retval = GetNext());
   256   return NS_OK;
   257 }
   259 NS_IMETHODIMP
   260 nsTreeColumn::GetPrevious(nsITreeColumn** _retval)
   261 {
   262   NS_IF_ADDREF(*_retval = GetPrevious());
   263   return NS_OK;
   264 }
   266 NS_IMETHODIMP
   267 nsTreeColumn::Invalidate()
   268 {
   269   nsIFrame* frame = GetFrame();
   270   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
   272   // Fetch the Id.
   273   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, mId);
   275   // If we have an Id, cache the Id as an atom.
   276   if (!mId.IsEmpty()) {
   277     mAtom = do_GetAtom(mId);
   278   }
   280   // Cache our index.
   281   nsTreeUtils::GetColumnIndex(mContent, &mIndex);
   283   const nsStyleVisibility* vis = frame->StyleVisibility();
   285   // Cache our text alignment policy.
   286   const nsStyleText* textStyle = frame->StyleText();
   288   mTextAlignment = textStyle->mTextAlign;
   289   // DEFAULT or END alignment sometimes means RIGHT
   290   if ((mTextAlignment == NS_STYLE_TEXT_ALIGN_DEFAULT &&
   291        vis->mDirection == NS_STYLE_DIRECTION_RTL) ||
   292       (mTextAlignment == NS_STYLE_TEXT_ALIGN_END &&
   293        vis->mDirection == NS_STYLE_DIRECTION_LTR)) {
   294     mTextAlignment = NS_STYLE_TEXT_ALIGN_RIGHT;
   295   } else if (mTextAlignment == NS_STYLE_TEXT_ALIGN_DEFAULT ||
   296              mTextAlignment == NS_STYLE_TEXT_ALIGN_END) {
   297     mTextAlignment = NS_STYLE_TEXT_ALIGN_LEFT;
   298   }
   300   // Figure out if we're the primary column (that has to have indentation
   301   // and twisties drawn.
   302   mIsPrimary = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary,
   303                                      nsGkAtoms::_true, eCaseMatters);
   305   // Figure out if we're a cycling column (one that doesn't cause a selection
   306   // to happen).
   307   mIsCycler = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::cycler,
   308                                     nsGkAtoms::_true, eCaseMatters);
   310   mIsEditable = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
   311                                      nsGkAtoms::_true, eCaseMatters);
   313   mIsSelectable = !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::selectable,
   314                                          nsGkAtoms::_false, eCaseMatters);
   316   mOverflow = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::overflow,
   317                                     nsGkAtoms::_true, eCaseMatters);
   319   // Figure out our column type. Default type is text.
   320   mType = nsITreeColumn::TYPE_TEXT;
   321   static nsIContent::AttrValuesArray typestrings[] =
   322     {&nsGkAtoms::checkbox, &nsGkAtoms::progressmeter, nullptr};
   323   switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type,
   324                                     typestrings, eCaseMatters)) {
   325     case 0: mType = nsITreeColumn::TYPE_CHECKBOX; break;
   326     case 1: mType = nsITreeColumn::TYPE_PROGRESSMETER; break;
   327   }
   329   // Fetch the crop style.
   330   mCropStyle = 0;
   331   static nsIContent::AttrValuesArray cropstrings[] =
   332     {&nsGkAtoms::center, &nsGkAtoms::left, &nsGkAtoms::start, nullptr};
   333   switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::crop,
   334                                     cropstrings, eCaseMatters)) {
   335     case 0:
   336       mCropStyle = 1;
   337       break;
   338     case 1:
   339     case 2:
   340       mCropStyle = 2;
   341       break;
   342   }
   344   return NS_OK;
   345 }
   348 nsTreeColumns::nsTreeColumns(nsTreeBodyFrame* aTree)
   349   : mTree(aTree),
   350     mFirstColumn(nullptr)
   351 {
   352   SetIsDOMBinding();
   353 }
   355 nsTreeColumns::~nsTreeColumns()
   356 {
   357   nsTreeColumns::InvalidateColumns();
   358 }
   360 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsTreeColumns)
   362 // QueryInterface implementation for nsTreeColumns
   363 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeColumns)
   364   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   365   NS_INTERFACE_MAP_ENTRY(nsITreeColumns)
   366   NS_INTERFACE_MAP_ENTRY(nsISupports)
   367 NS_INTERFACE_MAP_END
   369 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeColumns)
   370 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeColumns)
   372 nsIContent*
   373 nsTreeColumns::GetParentObject() const
   374 {
   375   return mTree ? mTree->GetBaseElement() : nullptr;
   376 }
   378 /* virtual */ JSObject*
   379 nsTreeColumns::WrapObject(JSContext* aCx)
   380 {
   381   return dom::TreeColumnsBinding::Wrap(aCx, this);
   382 }
   384 nsITreeBoxObject*
   385 nsTreeColumns::GetTree() const
   386 {
   387   return mTree ? mTree->GetTreeBoxObject() : nullptr;
   388 }
   390 NS_IMETHODIMP
   391 nsTreeColumns::GetTree(nsITreeBoxObject** _retval)
   392 {
   393   NS_IF_ADDREF(*_retval = GetTree());
   394   return NS_OK;
   395 }
   397 uint32_t
   398 nsTreeColumns::Count()
   399 {
   400   EnsureColumns();
   401   uint32_t count = 0;
   402   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   403     ++count;
   404   }
   405   return count;
   406 }
   408 NS_IMETHODIMP
   409 nsTreeColumns::GetCount(int32_t* _retval)
   410 {
   411   *_retval = Count();
   412   return NS_OK;
   413 }
   415 NS_IMETHODIMP
   416 nsTreeColumns::GetLength(int32_t* _retval)
   417 {
   418   *_retval = Length();
   419   return NS_OK;
   420 }
   422 NS_IMETHODIMP
   423 nsTreeColumns::GetFirstColumn(nsITreeColumn** _retval)
   424 {
   425   NS_IF_ADDREF(*_retval = GetFirstColumn());
   426   return NS_OK;
   427 }
   429 nsTreeColumn*
   430 nsTreeColumns::GetLastColumn()
   431 {
   432   EnsureColumns();
   433   nsTreeColumn* currCol = mFirstColumn;
   434   while (currCol) {
   435     nsTreeColumn* next = currCol->GetNext();
   436     if (!next) {
   437       return currCol;
   438     }
   439     currCol = next;
   440   }
   441   return nullptr;
   442 }
   444 NS_IMETHODIMP
   445 nsTreeColumns::GetLastColumn(nsITreeColumn** _retval)
   446 {
   447   NS_IF_ADDREF(*_retval = GetLastColumn());
   448   return NS_OK;
   449 }
   451 NS_IMETHODIMP
   452 nsTreeColumns::GetPrimaryColumn(nsITreeColumn** _retval)
   453 {
   454   NS_IF_ADDREF(*_retval = GetPrimaryColumn());
   455   return NS_OK;
   456 }
   458 nsTreeColumn*
   459 nsTreeColumns::GetSortedColumn()
   460 {
   461   EnsureColumns();
   462   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   463     if (currCol->mContent &&
   464         nsContentUtils::HasNonEmptyAttr(currCol->mContent, kNameSpaceID_None,
   465                                         nsGkAtoms::sortDirection)) {
   466       return currCol;
   467     }
   468   }
   469   return nullptr;
   470 }
   472 NS_IMETHODIMP
   473 nsTreeColumns::GetSortedColumn(nsITreeColumn** _retval)
   474 {
   475   NS_IF_ADDREF(*_retval = GetSortedColumn());
   476   return NS_OK;
   477 }
   479 nsTreeColumn*
   480 nsTreeColumns::GetKeyColumn()
   481 {
   482   EnsureColumns();
   484   nsTreeColumn* first = nullptr;
   485   nsTreeColumn* primary = nullptr;
   486   nsTreeColumn* sorted = nullptr;
   488   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   489     // Skip hidden columns.
   490     if (!currCol->mContent ||
   491         currCol->mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
   492                                        nsGkAtoms::_true, eCaseMatters))
   493       continue;
   495     // Skip non-text column
   496     if (currCol->GetType() != nsITreeColumn::TYPE_TEXT)
   497       continue;
   499     if (!first)
   500       first = currCol;
   502     if (nsContentUtils::HasNonEmptyAttr(currCol->mContent, kNameSpaceID_None,
   503                                         nsGkAtoms::sortDirection)) {
   504       // Use sorted column as the key.
   505       sorted = currCol;
   506       break;
   507     }
   509     if (currCol->IsPrimary())
   510       if (!primary)
   511         primary = currCol;
   512   }
   514   if (sorted)
   515     return sorted;
   516   if (primary)
   517     return primary;
   518   return first;
   519 }
   521 NS_IMETHODIMP
   522 nsTreeColumns::GetKeyColumn(nsITreeColumn** _retval)
   523 {
   524   NS_IF_ADDREF(*_retval = GetKeyColumn());
   525   return NS_OK;
   526 }
   528 nsTreeColumn*
   529 nsTreeColumns::GetColumnFor(dom::Element* aElement)
   530 {
   531   EnsureColumns();
   532   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   533     if (currCol->mContent == aElement) {
   534       return currCol;
   535     }
   536   }
   537   return nullptr;
   538 }
   540 NS_IMETHODIMP
   541 nsTreeColumns::GetColumnFor(nsIDOMElement* aElement, nsITreeColumn** _retval)
   542 {
   543   nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
   544   NS_ADDREF(*_retval = GetColumnFor(element));
   545   return NS_OK;
   546 }
   548 nsTreeColumn*
   549 nsTreeColumns::NamedGetter(const nsAString& aId, bool& aFound)
   550 {
   551   EnsureColumns();
   552   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   553     if (currCol->GetId().Equals(aId)) {
   554       aFound = true;
   555       return currCol;
   556     }
   557   }
   558   aFound = false;
   559   return nullptr;
   560 }
   562 bool
   563 nsTreeColumns::NameIsEnumerable(const nsAString& aName)
   564 {
   565   return true;
   566 }
   568 nsTreeColumn*
   569 nsTreeColumns::GetNamedColumn(const nsAString& aId)
   570 {
   571   bool dummy;
   572   return NamedGetter(aId, dummy);
   573 }
   575 NS_IMETHODIMP
   576 nsTreeColumns::GetNamedColumn(const nsAString& aId, nsITreeColumn** _retval)
   577 {
   578   NS_IF_ADDREF(*_retval = GetNamedColumn(aId));
   579   return NS_OK;
   580 }
   582 void
   583 nsTreeColumns::GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
   584 {
   585   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   586     aNames.AppendElement(currCol->GetId());
   587   }
   588 }
   591 nsTreeColumn*
   592 nsTreeColumns::IndexedGetter(uint32_t aIndex, bool& aFound)
   593 {
   594   EnsureColumns();
   595   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   596     if (currCol->GetIndex() == static_cast<int32_t>(aIndex)) {
   597       aFound = true;
   598       return currCol;
   599     }
   600   }
   601   aFound = false;
   602   return nullptr;
   603 }
   605 nsTreeColumn*
   606 nsTreeColumns::GetColumnAt(uint32_t aIndex)
   607 {
   608   bool dummy;
   609   return IndexedGetter(aIndex, dummy);
   610 }
   612 NS_IMETHODIMP
   613 nsTreeColumns::GetColumnAt(int32_t aIndex, nsITreeColumn** _retval)
   614 {
   615   NS_IF_ADDREF(*_retval = GetColumnAt(static_cast<uint32_t>(aIndex)));
   616   return NS_OK;
   617 }
   619 NS_IMETHODIMP
   620 nsTreeColumns::InvalidateColumns()
   621 {
   622   for (nsTreeColumn* currCol = mFirstColumn; currCol;
   623        currCol = currCol->GetNext()) {
   624     currCol->SetColumns(nullptr);
   625   }
   626   NS_IF_RELEASE(mFirstColumn);
   627   return NS_OK;
   628 }
   630 NS_IMETHODIMP
   631 nsTreeColumns::RestoreNaturalOrder()
   632 {
   633   if (!mTree)
   634     return NS_OK;
   636   nsIContent* content = mTree->GetBaseElement();
   638   // Strong ref, since we'll be setting attributes
   639   nsCOMPtr<nsIContent> colsContent =
   640     nsTreeUtils::GetImmediateChild(content, nsGkAtoms::treecols);
   641   if (!colsContent)
   642     return NS_OK;
   644   for (uint32_t i = 0; i < colsContent->GetChildCount(); ++i) {
   645     nsCOMPtr<nsIContent> child = colsContent->GetChildAt(i);
   646     nsAutoString ordinal;
   647     ordinal.AppendInt(i);
   648     child->SetAttr(kNameSpaceID_None, nsGkAtoms::ordinal, ordinal, true);
   649   }
   651   nsTreeColumns::InvalidateColumns();
   653   if (mTree) {
   654     mTree->Invalidate();
   655   }
   656   return NS_OK;
   657 }
   659 nsTreeColumn*
   660 nsTreeColumns::GetPrimaryColumn()
   661 {
   662   EnsureColumns();
   663   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
   664     if (currCol->IsPrimary()) {
   665       return currCol;
   666     }
   667   }
   668   return nullptr;
   669 }
   671 void
   672 nsTreeColumns::EnsureColumns()
   673 {
   674   if (mTree && !mFirstColumn) {
   675     nsIContent* treeContent = mTree->GetBaseElement();
   676     nsIContent* colsContent =
   677       nsTreeUtils::GetDescendantChild(treeContent, nsGkAtoms::treecols);
   678     if (!colsContent)
   679       return;
   681     nsIContent* colContent =
   682       nsTreeUtils::GetDescendantChild(colsContent, nsGkAtoms::treecol);
   683     if (!colContent)
   684       return;
   686     nsIFrame* colFrame = colContent->GetPrimaryFrame();
   687     if (!colFrame)
   688       return;
   690     colFrame = colFrame->GetParent();
   691     if (!colFrame)
   692       return;
   694     colFrame = colFrame->GetFirstPrincipalChild();
   695     if (!colFrame)
   696       return;
   698     // Now that we have the first visible column,
   699     // we can enumerate the columns in visible order
   700     nsTreeColumn* currCol = nullptr;
   701     while (colFrame) {
   702       nsIContent* colContent = colFrame->GetContent();
   704       if (colContent->NodeInfo()->Equals(nsGkAtoms::treecol,
   705                                          kNameSpaceID_XUL)) {
   706         // Create a new column structure.
   707         nsTreeColumn* col = new nsTreeColumn(this, colContent);
   708         if (!col)
   709           return;
   711         if (currCol) {
   712           currCol->SetNext(col);
   713           col->SetPrevious(currCol);
   714         }
   715         else {
   716           NS_ADDREF(mFirstColumn = col);
   717         }
   718         currCol = col;
   719       }
   721       colFrame = colFrame->GetNextSibling();
   722     }
   723   }
   724 }

mercurial