1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/tree/nsTreeColumns.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,724 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsNameSpaceManager.h" 1.10 +#include "nsGkAtoms.h" 1.11 +#include "nsIDOMElement.h" 1.12 +#include "nsIBoxObject.h" 1.13 +#include "nsTreeColumns.h" 1.14 +#include "nsTreeUtils.h" 1.15 +#include "nsStyleContext.h" 1.16 +#include "nsDOMClassInfoID.h" 1.17 +#include "nsINodeInfo.h" 1.18 +#include "nsContentUtils.h" 1.19 +#include "nsTreeBodyFrame.h" 1.20 +#include "mozilla/dom/Element.h" 1.21 +#include "mozilla/dom/TreeColumnsBinding.h" 1.22 + 1.23 +using namespace mozilla; 1.24 + 1.25 +// Column class that caches all the info about our column. 1.26 +nsTreeColumn::nsTreeColumn(nsTreeColumns* aColumns, nsIContent* aContent) 1.27 + : mContent(aContent), 1.28 + mColumns(aColumns), 1.29 + mPrevious(nullptr) 1.30 +{ 1.31 + NS_ASSERTION(aContent && 1.32 + aContent->NodeInfo()->Equals(nsGkAtoms::treecol, 1.33 + kNameSpaceID_XUL), 1.34 + "nsTreeColumn's content must be a <xul:treecol>"); 1.35 + 1.36 + Invalidate(); 1.37 +} 1.38 + 1.39 +nsTreeColumn::~nsTreeColumn() 1.40 +{ 1.41 + if (mNext) { 1.42 + mNext->SetPrevious(nullptr); 1.43 + } 1.44 +} 1.45 + 1.46 +NS_IMPL_CYCLE_COLLECTION_CLASS(nsTreeColumn) 1.47 + 1.48 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTreeColumn) 1.49 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent) 1.50 + if (tmp->mNext) { 1.51 + tmp->mNext->SetPrevious(nullptr); 1.52 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mNext) 1.53 + } 1.54 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.55 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTreeColumn) 1.56 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent) 1.57 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNext) 1.58 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.59 + 1.60 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeColumn) 1.61 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeColumn) 1.62 + 1.63 +DOMCI_DATA(TreeColumn, nsTreeColumn) 1.64 + 1.65 +// QueryInterface implementation for nsTreeColumn 1.66 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeColumn) 1.67 + NS_INTERFACE_MAP_ENTRY(nsITreeColumn) 1.68 + NS_INTERFACE_MAP_ENTRY(nsISupports) 1.69 + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TreeColumn) 1.70 + if (aIID.Equals(NS_GET_IID(nsTreeColumn))) { 1.71 + AddRef(); 1.72 + *aInstancePtr = this; 1.73 + return NS_OK; 1.74 + } 1.75 + else 1.76 +NS_INTERFACE_MAP_END 1.77 + 1.78 +nsIFrame* 1.79 +nsTreeColumn::GetFrame() 1.80 +{ 1.81 + NS_ENSURE_TRUE(mContent, nullptr); 1.82 + 1.83 + return mContent->GetPrimaryFrame(); 1.84 +} 1.85 + 1.86 +bool 1.87 +nsTreeColumn::IsLastVisible(nsTreeBodyFrame* aBodyFrame) 1.88 +{ 1.89 + NS_ASSERTION(GetFrame(), "should have checked for this already"); 1.90 + 1.91 + // cyclers are fixed width, don't adjust them 1.92 + if (IsCycler()) 1.93 + return false; 1.94 + 1.95 + // we're certainly not the last visible if we're not visible 1.96 + if (GetFrame()->GetRect().width == 0) 1.97 + return false; 1.98 + 1.99 + // try to find a visible successor 1.100 + for (nsTreeColumn *next = GetNext(); next; next = next->GetNext()) { 1.101 + nsIFrame* frame = next->GetFrame(); 1.102 + if (frame && frame->GetRect().width > 0) 1.103 + return false; 1.104 + } 1.105 + return true; 1.106 +} 1.107 + 1.108 +nsresult 1.109 +nsTreeColumn::GetRect(nsTreeBodyFrame* aBodyFrame, nscoord aY, nscoord aHeight, nsRect* aResult) 1.110 +{ 1.111 + nsIFrame* frame = GetFrame(); 1.112 + if (!frame) { 1.113 + *aResult = nsRect(); 1.114 + return NS_ERROR_FAILURE; 1.115 + } 1.116 + 1.117 + bool isRTL = aBodyFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; 1.118 + *aResult = frame->GetRect(); 1.119 + aResult->y = aY; 1.120 + aResult->height = aHeight; 1.121 + if (isRTL) 1.122 + aResult->x += aBodyFrame->mAdjustWidth; 1.123 + else if (IsLastVisible(aBodyFrame)) 1.124 + aResult->width += aBodyFrame->mAdjustWidth; 1.125 + return NS_OK; 1.126 +} 1.127 + 1.128 +nsresult 1.129 +nsTreeColumn::GetXInTwips(nsTreeBodyFrame* aBodyFrame, nscoord* aResult) 1.130 +{ 1.131 + nsIFrame* frame = GetFrame(); 1.132 + if (!frame) { 1.133 + *aResult = 0; 1.134 + return NS_ERROR_FAILURE; 1.135 + } 1.136 + *aResult = frame->GetRect().x; 1.137 + return NS_OK; 1.138 +} 1.139 + 1.140 +nsresult 1.141 +nsTreeColumn::GetWidthInTwips(nsTreeBodyFrame* aBodyFrame, nscoord* aResult) 1.142 +{ 1.143 + nsIFrame* frame = GetFrame(); 1.144 + if (!frame) { 1.145 + *aResult = 0; 1.146 + return NS_ERROR_FAILURE; 1.147 + } 1.148 + *aResult = frame->GetRect().width; 1.149 + if (IsLastVisible(aBodyFrame)) 1.150 + *aResult += aBodyFrame->mAdjustWidth; 1.151 + return NS_OK; 1.152 +} 1.153 + 1.154 + 1.155 +NS_IMETHODIMP 1.156 +nsTreeColumn::GetElement(nsIDOMElement** aElement) 1.157 +{ 1.158 + if (mContent) { 1.159 + return CallQueryInterface(mContent, aElement); 1.160 + } 1.161 + *aElement = nullptr; 1.162 + return NS_ERROR_FAILURE; 1.163 +} 1.164 + 1.165 +NS_IMETHODIMP 1.166 +nsTreeColumn::GetColumns(nsITreeColumns** aColumns) 1.167 +{ 1.168 + NS_IF_ADDREF(*aColumns = mColumns); 1.169 + return NS_OK; 1.170 +} 1.171 + 1.172 +NS_IMETHODIMP 1.173 +nsTreeColumn::GetX(int32_t* aX) 1.174 +{ 1.175 + nsIFrame* frame = GetFrame(); 1.176 + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); 1.177 + 1.178 + *aX = nsPresContext::AppUnitsToIntCSSPixels(frame->GetRect().x); 1.179 + return NS_OK; 1.180 +} 1.181 + 1.182 +NS_IMETHODIMP 1.183 +nsTreeColumn::GetWidth(int32_t* aWidth) 1.184 +{ 1.185 + nsIFrame* frame = GetFrame(); 1.186 + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); 1.187 + 1.188 + *aWidth = nsPresContext::AppUnitsToIntCSSPixels(frame->GetRect().width); 1.189 + return NS_OK; 1.190 +} 1.191 + 1.192 +NS_IMETHODIMP 1.193 +nsTreeColumn::GetId(nsAString& aId) 1.194 +{ 1.195 + aId = GetId(); 1.196 + return NS_OK; 1.197 +} 1.198 + 1.199 +NS_IMETHODIMP 1.200 +nsTreeColumn::GetIdConst(const char16_t** aIdConst) 1.201 +{ 1.202 + *aIdConst = mId.get(); 1.203 + return NS_OK; 1.204 +} 1.205 + 1.206 +NS_IMETHODIMP 1.207 +nsTreeColumn::GetAtom(nsIAtom** aAtom) 1.208 +{ 1.209 + NS_IF_ADDREF(*aAtom = GetAtom()); 1.210 + return NS_OK; 1.211 +} 1.212 + 1.213 +NS_IMETHODIMP 1.214 +nsTreeColumn::GetIndex(int32_t* aIndex) 1.215 +{ 1.216 + *aIndex = GetIndex(); 1.217 + return NS_OK; 1.218 +} 1.219 + 1.220 +NS_IMETHODIMP 1.221 +nsTreeColumn::GetPrimary(bool* aPrimary) 1.222 +{ 1.223 + *aPrimary = IsPrimary(); 1.224 + return NS_OK; 1.225 +} 1.226 + 1.227 +NS_IMETHODIMP 1.228 +nsTreeColumn::GetCycler(bool* aCycler) 1.229 +{ 1.230 + *aCycler = IsCycler(); 1.231 + return NS_OK; 1.232 +} 1.233 + 1.234 +NS_IMETHODIMP 1.235 +nsTreeColumn::GetEditable(bool* aEditable) 1.236 +{ 1.237 + *aEditable = IsEditable(); 1.238 + return NS_OK; 1.239 +} 1.240 + 1.241 +NS_IMETHODIMP 1.242 +nsTreeColumn::GetSelectable(bool* aSelectable) 1.243 +{ 1.244 + *aSelectable = IsSelectable(); 1.245 + return NS_OK; 1.246 +} 1.247 + 1.248 +NS_IMETHODIMP 1.249 +nsTreeColumn::GetType(int16_t* aType) 1.250 +{ 1.251 + *aType = GetType(); 1.252 + return NS_OK; 1.253 +} 1.254 + 1.255 +NS_IMETHODIMP 1.256 +nsTreeColumn::GetNext(nsITreeColumn** _retval) 1.257 +{ 1.258 + NS_IF_ADDREF(*_retval = GetNext()); 1.259 + return NS_OK; 1.260 +} 1.261 + 1.262 +NS_IMETHODIMP 1.263 +nsTreeColumn::GetPrevious(nsITreeColumn** _retval) 1.264 +{ 1.265 + NS_IF_ADDREF(*_retval = GetPrevious()); 1.266 + return NS_OK; 1.267 +} 1.268 + 1.269 +NS_IMETHODIMP 1.270 +nsTreeColumn::Invalidate() 1.271 +{ 1.272 + nsIFrame* frame = GetFrame(); 1.273 + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); 1.274 + 1.275 + // Fetch the Id. 1.276 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, mId); 1.277 + 1.278 + // If we have an Id, cache the Id as an atom. 1.279 + if (!mId.IsEmpty()) { 1.280 + mAtom = do_GetAtom(mId); 1.281 + } 1.282 + 1.283 + // Cache our index. 1.284 + nsTreeUtils::GetColumnIndex(mContent, &mIndex); 1.285 + 1.286 + const nsStyleVisibility* vis = frame->StyleVisibility(); 1.287 + 1.288 + // Cache our text alignment policy. 1.289 + const nsStyleText* textStyle = frame->StyleText(); 1.290 + 1.291 + mTextAlignment = textStyle->mTextAlign; 1.292 + // DEFAULT or END alignment sometimes means RIGHT 1.293 + if ((mTextAlignment == NS_STYLE_TEXT_ALIGN_DEFAULT && 1.294 + vis->mDirection == NS_STYLE_DIRECTION_RTL) || 1.295 + (mTextAlignment == NS_STYLE_TEXT_ALIGN_END && 1.296 + vis->mDirection == NS_STYLE_DIRECTION_LTR)) { 1.297 + mTextAlignment = NS_STYLE_TEXT_ALIGN_RIGHT; 1.298 + } else if (mTextAlignment == NS_STYLE_TEXT_ALIGN_DEFAULT || 1.299 + mTextAlignment == NS_STYLE_TEXT_ALIGN_END) { 1.300 + mTextAlignment = NS_STYLE_TEXT_ALIGN_LEFT; 1.301 + } 1.302 + 1.303 + // Figure out if we're the primary column (that has to have indentation 1.304 + // and twisties drawn. 1.305 + mIsPrimary = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary, 1.306 + nsGkAtoms::_true, eCaseMatters); 1.307 + 1.308 + // Figure out if we're a cycling column (one that doesn't cause a selection 1.309 + // to happen). 1.310 + mIsCycler = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::cycler, 1.311 + nsGkAtoms::_true, eCaseMatters); 1.312 + 1.313 + mIsEditable = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable, 1.314 + nsGkAtoms::_true, eCaseMatters); 1.315 + 1.316 + mIsSelectable = !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::selectable, 1.317 + nsGkAtoms::_false, eCaseMatters); 1.318 + 1.319 + mOverflow = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::overflow, 1.320 + nsGkAtoms::_true, eCaseMatters); 1.321 + 1.322 + // Figure out our column type. Default type is text. 1.323 + mType = nsITreeColumn::TYPE_TEXT; 1.324 + static nsIContent::AttrValuesArray typestrings[] = 1.325 + {&nsGkAtoms::checkbox, &nsGkAtoms::progressmeter, nullptr}; 1.326 + switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, 1.327 + typestrings, eCaseMatters)) { 1.328 + case 0: mType = nsITreeColumn::TYPE_CHECKBOX; break; 1.329 + case 1: mType = nsITreeColumn::TYPE_PROGRESSMETER; break; 1.330 + } 1.331 + 1.332 + // Fetch the crop style. 1.333 + mCropStyle = 0; 1.334 + static nsIContent::AttrValuesArray cropstrings[] = 1.335 + {&nsGkAtoms::center, &nsGkAtoms::left, &nsGkAtoms::start, nullptr}; 1.336 + switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::crop, 1.337 + cropstrings, eCaseMatters)) { 1.338 + case 0: 1.339 + mCropStyle = 1; 1.340 + break; 1.341 + case 1: 1.342 + case 2: 1.343 + mCropStyle = 2; 1.344 + break; 1.345 + } 1.346 + 1.347 + return NS_OK; 1.348 +} 1.349 + 1.350 + 1.351 +nsTreeColumns::nsTreeColumns(nsTreeBodyFrame* aTree) 1.352 + : mTree(aTree), 1.353 + mFirstColumn(nullptr) 1.354 +{ 1.355 + SetIsDOMBinding(); 1.356 +} 1.357 + 1.358 +nsTreeColumns::~nsTreeColumns() 1.359 +{ 1.360 + nsTreeColumns::InvalidateColumns(); 1.361 +} 1.362 + 1.363 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsTreeColumns) 1.364 + 1.365 +// QueryInterface implementation for nsTreeColumns 1.366 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeColumns) 1.367 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.368 + NS_INTERFACE_MAP_ENTRY(nsITreeColumns) 1.369 + NS_INTERFACE_MAP_ENTRY(nsISupports) 1.370 +NS_INTERFACE_MAP_END 1.371 + 1.372 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeColumns) 1.373 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeColumns) 1.374 + 1.375 +nsIContent* 1.376 +nsTreeColumns::GetParentObject() const 1.377 +{ 1.378 + return mTree ? mTree->GetBaseElement() : nullptr; 1.379 +} 1.380 + 1.381 +/* virtual */ JSObject* 1.382 +nsTreeColumns::WrapObject(JSContext* aCx) 1.383 +{ 1.384 + return dom::TreeColumnsBinding::Wrap(aCx, this); 1.385 +} 1.386 + 1.387 +nsITreeBoxObject* 1.388 +nsTreeColumns::GetTree() const 1.389 +{ 1.390 + return mTree ? mTree->GetTreeBoxObject() : nullptr; 1.391 +} 1.392 + 1.393 +NS_IMETHODIMP 1.394 +nsTreeColumns::GetTree(nsITreeBoxObject** _retval) 1.395 +{ 1.396 + NS_IF_ADDREF(*_retval = GetTree()); 1.397 + return NS_OK; 1.398 +} 1.399 + 1.400 +uint32_t 1.401 +nsTreeColumns::Count() 1.402 +{ 1.403 + EnsureColumns(); 1.404 + uint32_t count = 0; 1.405 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.406 + ++count; 1.407 + } 1.408 + return count; 1.409 +} 1.410 + 1.411 +NS_IMETHODIMP 1.412 +nsTreeColumns::GetCount(int32_t* _retval) 1.413 +{ 1.414 + *_retval = Count(); 1.415 + return NS_OK; 1.416 +} 1.417 + 1.418 +NS_IMETHODIMP 1.419 +nsTreeColumns::GetLength(int32_t* _retval) 1.420 +{ 1.421 + *_retval = Length(); 1.422 + return NS_OK; 1.423 +} 1.424 + 1.425 +NS_IMETHODIMP 1.426 +nsTreeColumns::GetFirstColumn(nsITreeColumn** _retval) 1.427 +{ 1.428 + NS_IF_ADDREF(*_retval = GetFirstColumn()); 1.429 + return NS_OK; 1.430 +} 1.431 + 1.432 +nsTreeColumn* 1.433 +nsTreeColumns::GetLastColumn() 1.434 +{ 1.435 + EnsureColumns(); 1.436 + nsTreeColumn* currCol = mFirstColumn; 1.437 + while (currCol) { 1.438 + nsTreeColumn* next = currCol->GetNext(); 1.439 + if (!next) { 1.440 + return currCol; 1.441 + } 1.442 + currCol = next; 1.443 + } 1.444 + return nullptr; 1.445 +} 1.446 + 1.447 +NS_IMETHODIMP 1.448 +nsTreeColumns::GetLastColumn(nsITreeColumn** _retval) 1.449 +{ 1.450 + NS_IF_ADDREF(*_retval = GetLastColumn()); 1.451 + return NS_OK; 1.452 +} 1.453 + 1.454 +NS_IMETHODIMP 1.455 +nsTreeColumns::GetPrimaryColumn(nsITreeColumn** _retval) 1.456 +{ 1.457 + NS_IF_ADDREF(*_retval = GetPrimaryColumn()); 1.458 + return NS_OK; 1.459 +} 1.460 + 1.461 +nsTreeColumn* 1.462 +nsTreeColumns::GetSortedColumn() 1.463 +{ 1.464 + EnsureColumns(); 1.465 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.466 + if (currCol->mContent && 1.467 + nsContentUtils::HasNonEmptyAttr(currCol->mContent, kNameSpaceID_None, 1.468 + nsGkAtoms::sortDirection)) { 1.469 + return currCol; 1.470 + } 1.471 + } 1.472 + return nullptr; 1.473 +} 1.474 + 1.475 +NS_IMETHODIMP 1.476 +nsTreeColumns::GetSortedColumn(nsITreeColumn** _retval) 1.477 +{ 1.478 + NS_IF_ADDREF(*_retval = GetSortedColumn()); 1.479 + return NS_OK; 1.480 +} 1.481 + 1.482 +nsTreeColumn* 1.483 +nsTreeColumns::GetKeyColumn() 1.484 +{ 1.485 + EnsureColumns(); 1.486 + 1.487 + nsTreeColumn* first = nullptr; 1.488 + nsTreeColumn* primary = nullptr; 1.489 + nsTreeColumn* sorted = nullptr; 1.490 + 1.491 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.492 + // Skip hidden columns. 1.493 + if (!currCol->mContent || 1.494 + currCol->mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden, 1.495 + nsGkAtoms::_true, eCaseMatters)) 1.496 + continue; 1.497 + 1.498 + // Skip non-text column 1.499 + if (currCol->GetType() != nsITreeColumn::TYPE_TEXT) 1.500 + continue; 1.501 + 1.502 + if (!first) 1.503 + first = currCol; 1.504 + 1.505 + if (nsContentUtils::HasNonEmptyAttr(currCol->mContent, kNameSpaceID_None, 1.506 + nsGkAtoms::sortDirection)) { 1.507 + // Use sorted column as the key. 1.508 + sorted = currCol; 1.509 + break; 1.510 + } 1.511 + 1.512 + if (currCol->IsPrimary()) 1.513 + if (!primary) 1.514 + primary = currCol; 1.515 + } 1.516 + 1.517 + if (sorted) 1.518 + return sorted; 1.519 + if (primary) 1.520 + return primary; 1.521 + return first; 1.522 +} 1.523 + 1.524 +NS_IMETHODIMP 1.525 +nsTreeColumns::GetKeyColumn(nsITreeColumn** _retval) 1.526 +{ 1.527 + NS_IF_ADDREF(*_retval = GetKeyColumn()); 1.528 + return NS_OK; 1.529 +} 1.530 + 1.531 +nsTreeColumn* 1.532 +nsTreeColumns::GetColumnFor(dom::Element* aElement) 1.533 +{ 1.534 + EnsureColumns(); 1.535 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.536 + if (currCol->mContent == aElement) { 1.537 + return currCol; 1.538 + } 1.539 + } 1.540 + return nullptr; 1.541 +} 1.542 + 1.543 +NS_IMETHODIMP 1.544 +nsTreeColumns::GetColumnFor(nsIDOMElement* aElement, nsITreeColumn** _retval) 1.545 +{ 1.546 + nsCOMPtr<dom::Element> element = do_QueryInterface(aElement); 1.547 + NS_ADDREF(*_retval = GetColumnFor(element)); 1.548 + return NS_OK; 1.549 +} 1.550 + 1.551 +nsTreeColumn* 1.552 +nsTreeColumns::NamedGetter(const nsAString& aId, bool& aFound) 1.553 +{ 1.554 + EnsureColumns(); 1.555 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.556 + if (currCol->GetId().Equals(aId)) { 1.557 + aFound = true; 1.558 + return currCol; 1.559 + } 1.560 + } 1.561 + aFound = false; 1.562 + return nullptr; 1.563 +} 1.564 + 1.565 +bool 1.566 +nsTreeColumns::NameIsEnumerable(const nsAString& aName) 1.567 +{ 1.568 + return true; 1.569 +} 1.570 + 1.571 +nsTreeColumn* 1.572 +nsTreeColumns::GetNamedColumn(const nsAString& aId) 1.573 +{ 1.574 + bool dummy; 1.575 + return NamedGetter(aId, dummy); 1.576 +} 1.577 + 1.578 +NS_IMETHODIMP 1.579 +nsTreeColumns::GetNamedColumn(const nsAString& aId, nsITreeColumn** _retval) 1.580 +{ 1.581 + NS_IF_ADDREF(*_retval = GetNamedColumn(aId)); 1.582 + return NS_OK; 1.583 +} 1.584 + 1.585 +void 1.586 +nsTreeColumns::GetSupportedNames(unsigned, nsTArray<nsString>& aNames) 1.587 +{ 1.588 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.589 + aNames.AppendElement(currCol->GetId()); 1.590 + } 1.591 +} 1.592 + 1.593 + 1.594 +nsTreeColumn* 1.595 +nsTreeColumns::IndexedGetter(uint32_t aIndex, bool& aFound) 1.596 +{ 1.597 + EnsureColumns(); 1.598 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.599 + if (currCol->GetIndex() == static_cast<int32_t>(aIndex)) { 1.600 + aFound = true; 1.601 + return currCol; 1.602 + } 1.603 + } 1.604 + aFound = false; 1.605 + return nullptr; 1.606 +} 1.607 + 1.608 +nsTreeColumn* 1.609 +nsTreeColumns::GetColumnAt(uint32_t aIndex) 1.610 +{ 1.611 + bool dummy; 1.612 + return IndexedGetter(aIndex, dummy); 1.613 +} 1.614 + 1.615 +NS_IMETHODIMP 1.616 +nsTreeColumns::GetColumnAt(int32_t aIndex, nsITreeColumn** _retval) 1.617 +{ 1.618 + NS_IF_ADDREF(*_retval = GetColumnAt(static_cast<uint32_t>(aIndex))); 1.619 + return NS_OK; 1.620 +} 1.621 + 1.622 +NS_IMETHODIMP 1.623 +nsTreeColumns::InvalidateColumns() 1.624 +{ 1.625 + for (nsTreeColumn* currCol = mFirstColumn; currCol; 1.626 + currCol = currCol->GetNext()) { 1.627 + currCol->SetColumns(nullptr); 1.628 + } 1.629 + NS_IF_RELEASE(mFirstColumn); 1.630 + return NS_OK; 1.631 +} 1.632 + 1.633 +NS_IMETHODIMP 1.634 +nsTreeColumns::RestoreNaturalOrder() 1.635 +{ 1.636 + if (!mTree) 1.637 + return NS_OK; 1.638 + 1.639 + nsIContent* content = mTree->GetBaseElement(); 1.640 + 1.641 + // Strong ref, since we'll be setting attributes 1.642 + nsCOMPtr<nsIContent> colsContent = 1.643 + nsTreeUtils::GetImmediateChild(content, nsGkAtoms::treecols); 1.644 + if (!colsContent) 1.645 + return NS_OK; 1.646 + 1.647 + for (uint32_t i = 0; i < colsContent->GetChildCount(); ++i) { 1.648 + nsCOMPtr<nsIContent> child = colsContent->GetChildAt(i); 1.649 + nsAutoString ordinal; 1.650 + ordinal.AppendInt(i); 1.651 + child->SetAttr(kNameSpaceID_None, nsGkAtoms::ordinal, ordinal, true); 1.652 + } 1.653 + 1.654 + nsTreeColumns::InvalidateColumns(); 1.655 + 1.656 + if (mTree) { 1.657 + mTree->Invalidate(); 1.658 + } 1.659 + return NS_OK; 1.660 +} 1.661 + 1.662 +nsTreeColumn* 1.663 +nsTreeColumns::GetPrimaryColumn() 1.664 +{ 1.665 + EnsureColumns(); 1.666 + for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) { 1.667 + if (currCol->IsPrimary()) { 1.668 + return currCol; 1.669 + } 1.670 + } 1.671 + return nullptr; 1.672 +} 1.673 + 1.674 +void 1.675 +nsTreeColumns::EnsureColumns() 1.676 +{ 1.677 + if (mTree && !mFirstColumn) { 1.678 + nsIContent* treeContent = mTree->GetBaseElement(); 1.679 + nsIContent* colsContent = 1.680 + nsTreeUtils::GetDescendantChild(treeContent, nsGkAtoms::treecols); 1.681 + if (!colsContent) 1.682 + return; 1.683 + 1.684 + nsIContent* colContent = 1.685 + nsTreeUtils::GetDescendantChild(colsContent, nsGkAtoms::treecol); 1.686 + if (!colContent) 1.687 + return; 1.688 + 1.689 + nsIFrame* colFrame = colContent->GetPrimaryFrame(); 1.690 + if (!colFrame) 1.691 + return; 1.692 + 1.693 + colFrame = colFrame->GetParent(); 1.694 + if (!colFrame) 1.695 + return; 1.696 + 1.697 + colFrame = colFrame->GetFirstPrincipalChild(); 1.698 + if (!colFrame) 1.699 + return; 1.700 + 1.701 + // Now that we have the first visible column, 1.702 + // we can enumerate the columns in visible order 1.703 + nsTreeColumn* currCol = nullptr; 1.704 + while (colFrame) { 1.705 + nsIContent* colContent = colFrame->GetContent(); 1.706 + 1.707 + if (colContent->NodeInfo()->Equals(nsGkAtoms::treecol, 1.708 + kNameSpaceID_XUL)) { 1.709 + // Create a new column structure. 1.710 + nsTreeColumn* col = new nsTreeColumn(this, colContent); 1.711 + if (!col) 1.712 + return; 1.713 + 1.714 + if (currCol) { 1.715 + currCol->SetNext(col); 1.716 + col->SetPrevious(currCol); 1.717 + } 1.718 + else { 1.719 + NS_ADDREF(mFirstColumn = col); 1.720 + } 1.721 + currCol = col; 1.722 + } 1.723 + 1.724 + colFrame = colFrame->GetNextSibling(); 1.725 + } 1.726 + } 1.727 +}