diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /layout/generic/DetailsFrame.cpp | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/generic/DetailsFrame.cpp')
-rw-r--r-- | layout/generic/DetailsFrame.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/layout/generic/DetailsFrame.cpp b/layout/generic/DetailsFrame.cpp new file mode 100644 index 0000000000..5c62ed5a31 --- /dev/null +++ b/layout/generic/DetailsFrame.cpp @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DetailsFrame.h" + +#include "mozilla/Attributes.h" +#include "mozilla/PresShell.h" +#include "mozilla/dom/HTMLDetailsElement.h" +#include "mozilla/dom/HTMLSummaryElement.h" +#include "nsContentUtils.h" +#include "nsPlaceholderFrame.h" +#include "nsTextNode.h" + +using namespace mozilla; +using namespace mozilla::dom; + +NS_IMPL_FRAMEARENA_HELPERS(DetailsFrame) + +NS_QUERYFRAME_HEAD(DetailsFrame) + NS_QUERYFRAME_ENTRY(DetailsFrame) + NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) +NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame) + +nsBlockFrame* NS_NewDetailsFrame(PresShell* aPresShell, ComputedStyle* aStyle) { + return new (aPresShell) DetailsFrame(aStyle, aPresShell->GetPresContext()); +} + +namespace mozilla { + +DetailsFrame::DetailsFrame(ComputedStyle* aStyle, nsPresContext* aPresContext) + : nsBlockFrame(aStyle, aPresContext, kClassID) {} + +DetailsFrame::~DetailsFrame() = default; + +void DetailsFrame::SetInitialChildList(ChildListID aListID, + nsFrameList& aChildList) { +#ifdef DEBUG + if (aListID == kPrincipalList) { + CheckValidMainSummary(aChildList); + } +#endif + + nsBlockFrame::SetInitialChildList(aListID, aChildList); +} + +#ifdef DEBUG +bool DetailsFrame::CheckValidMainSummary(const nsFrameList& aFrameList) const { + for (nsIFrame* child : aFrameList) { + if (child->IsGeneratedContentFrame()) { + continue; + } + HTMLSummaryElement* summary = + HTMLSummaryElement::FromNode(child->GetContent()); + if (child == aFrameList.FirstChild()) { + if (summary && summary->IsMainSummary()) { + return true; + } else if (child->GetContent() == GetContent()) { + // The child frame's content is the same as our content, which means + // it's a kind of wrapper frame. Descend into its child list to find + // main summary. + if (CheckValidMainSummary(child->PrincipalChildList())) { + return true; + } + } + } else { + NS_ASSERTION(!summary || !summary->IsMainSummary(), + "Rest of the children are either not summary element " + "or are not the main summary!"); + } + } + return false; +} +#endif + +void DetailsFrame::DestroyFrom(nsIFrame* aDestructRoot, + PostDestroyData& aPostDestroyData) { + aPostDestroyData.AddAnonymousContent(mDefaultSummary.forget()); + nsBlockFrame::DestroyFrom(aDestructRoot, aPostDestroyData); +} + +nsresult DetailsFrame::CreateAnonymousContent( + nsTArray<ContentInfo>& aElements) { + auto* details = HTMLDetailsElement::FromNode(GetContent()); + if (details->GetFirstSummary()) { + return NS_OK; + } + + // The <details> element lacks any direct <summary> child. Create a default + // <summary> element as an anonymous content. + nsNodeInfoManager* nodeInfoManager = + GetContent()->NodeInfo()->NodeInfoManager(); + + RefPtr<NodeInfo> nodeInfo = nodeInfoManager->GetNodeInfo( + nsGkAtoms::summary, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE); + mDefaultSummary = new (nodeInfoManager) HTMLSummaryElement(nodeInfo.forget()); + + nsAutoString defaultSummaryText; + nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eFORMS_PROPERTIES, "DefaultSummary", + GetContent()->OwnerDoc(), defaultSummaryText); + RefPtr<nsTextNode> description = + new (nodeInfoManager) nsTextNode(nodeInfoManager); + description->SetText(defaultSummaryText, false); + mDefaultSummary->AppendChildTo(description, false); + + aElements.AppendElement(mDefaultSummary); + + return NS_OK; +} + +void DetailsFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, + uint32_t aFilter) { + if (mDefaultSummary) { + aElements.AppendElement(mDefaultSummary); + } +} + +bool DetailsFrame::HasMainSummaryFrame(nsIFrame* aSummaryFrame) { + const ChildListIDs flowLists = {kPrincipalList, kOverflowList}; + for (nsIFrame* frag = this; frag; frag = frag->GetNextInFlow()) { + for (const auto& [list, listID] : frag->ChildLists()) { + if (!flowLists.contains(listID)) { + continue; + } + for (nsIFrame* child : list) { + child = nsPlaceholderFrame::GetRealFrameFor(child); + // We skip any non-primary frames such as a list-style-position:inside + // bullet frame for the <details> itself. + if (!child->IsGeneratedContentFrame()) { + return aSummaryFrame == child; + } + } + } + } + return false; +} + +} // namespace mozilla |