Bug 1820634 - Remove nsTreeColFrame. r=Gijs

Layout-wise it doesn't have any special code. Only weirdness is:

 * Invalidation when size changes (we can do that with a
   ResizeObserver).

 * Weird paint retargetting to the splitter, which we can fix by using
   negative margins instead and using a regular splitter.

Differential Revision: https://phabricator.services.mozilla.com/D171768
This commit is contained in:
Emilio Cobos Álvarez
2023-03-07 10:32:32 +00:00
parent caddfbaa2a
commit 195f855583
8 changed files with 42 additions and 234 deletions

View File

@@ -201,8 +201,6 @@ static FrameCtorDebugFlags gFlags[] = {
# define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
#endif
#include "nsTreeColFrame.h"
//------------------------------------------------------------------
nsIFrame* NS_NewLeafBoxFrame(PresShell* aPresShell, ComputedStyle* aStyle);
@@ -4132,7 +4130,6 @@ nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
static constexpr FrameConstructionDataByTag sXULTagData[] = {
SIMPLE_XUL_CREATE(image, NS_NewXULImageFrame),
SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame),
SIMPLE_XUL_CREATE(treecol, NS_NewTreeColFrame),
SIMPLE_TAG_CHAIN(label,
nsCSSFrameConstructor::FindXULLabelOrDescriptionData),
SIMPLE_TAG_CHAIN(description,

View File

@@ -126,7 +126,6 @@ FRAME_CLASSES = [
Frame("nsTextControlFrame", "TextInput", LEAF),
Frame("nsTextFrame", "Text", LEAF),
Frame("nsTreeBodyFrame", "LeafBox", LEAF),
Frame("nsTreeColFrame", "Box", NOT_LEAF),
Frame("nsVideoFrame", "HTMLVideo", NOT_LEAF),
Frame("nsXULScrollFrame", "Scroll", NOT_LEAF),
Frame("ViewportFrame", "Viewport", NOT_LEAF),

View File

@@ -15,14 +15,12 @@ XPIDL_SOURCES += [
XPIDL_MODULE = "layout_xul_tree"
EXPORTS += [
"nsTreeColFrame.h",
"nsTreeColumns.h",
"nsTreeUtils.h",
]
UNIFIED_SOURCES += [
"nsTreeBodyFrame.cpp",
"nsTreeColFrame.cpp",
"nsTreeColumns.cpp",
"nsTreeContentView.cpp",
"nsTreeImageListener.cpp",

View File

@@ -1,161 +0,0 @@
/* -*- 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 "nsTreeColFrame.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/XULTreeElement.h"
#include "mozilla/CSSOrderAwareFrameIterator.h"
#include "nsCOMPtr.h"
#include "nsGkAtoms.h"
#include "nsIContent.h"
#include "nsNameSpaceManager.h"
#include "nsTreeColumns.h"
#include "nsDisplayList.h"
#include "nsTreeBodyFrame.h"
#include "nsXULElement.h"
using namespace mozilla;
using namespace mozilla::dom;
//
// NS_NewTreeColFrame
//
// Creates a new col frame
//
nsIFrame* NS_NewTreeColFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
return new (aPresShell) nsTreeColFrame(aStyle, aPresShell->GetPresContext());
}
NS_IMPL_FRAMEARENA_HELPERS(nsTreeColFrame)
// Destructor
nsTreeColFrame::~nsTreeColFrame() = default;
void nsTreeColFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
InvalidateColumns();
}
void nsTreeColFrame::DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) {
InvalidateColumns(false);
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}
nsresult nsTreeColFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
nsresult rv =
nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
if (aAttribute == nsGkAtoms::primary) {
InvalidateColumns();
}
return rv;
}
void nsTreeColFrame::SetXULBounds(nsBoxLayoutState& aBoxLayoutState,
const nsRect& aRect,
bool aRemoveOverflowArea) {
nscoord oldWidth = mRect.width;
nsBoxFrame::SetXULBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
if (mRect.width != oldWidth) {
RefPtr<XULTreeElement> tree = GetTree();
if (tree) {
tree->Invalidate();
}
}
}
XULTreeElement* nsTreeColFrame::GetTree() {
nsIContent* parent = mContent->GetParent();
return parent ? XULTreeElement::FromNodeOrNull(parent->GetParent()) : nullptr;
}
void nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree) {
RefPtr<XULTreeElement> tree = GetTree();
if (!tree) {
return;
}
nsTreeBodyFrame* body = aCanWalkFrameTree
? tree->GetTreeBodyFrame(FlushType::None)
: tree->GetCachedTreeBodyFrame();
if (!body) {
return;
}
RefPtr<nsTreeColumns> columns = body->Columns();
if (!columns) {
return;
}
columns->InvalidateColumns();
}
namespace mozilla {
class nsDisplayXULTreeColSplitterTarget final : public nsDisplayItem {
public:
nsDisplayXULTreeColSplitterTarget(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayXULTreeColSplitterTarget);
}
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayXULTreeColSplitterTarget)
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget",
TYPE_XUL_TREE_COL_SPLITTER_TARGET)
};
void nsDisplayXULTreeColSplitterTarget::HitTest(
nsDisplayListBuilder* aBuilder, const nsRect& aRect, HitTestState* aState,
nsTArray<nsIFrame*>* aOutFrames) {
nsRect rect = aRect - ToReferenceFrame();
// If we are in either in the first 4 pixels or the last 4 pixels, we're going
// to do something really strange. Check for an adjacent splitter.
bool left = false;
bool right = false;
if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <=
rect.XMost()) {
right = true;
} else if (nsPresContext::CSSPixelsToAppUnits(4) > rect.x) {
left = true;
}
// Swap left and right for RTL trees in order to find the correct splitter
if (mFrame->StyleVisibility()->mDirection == StyleDirection::Rtl) {
std::swap(left, right);
}
if (left || right) {
nsIFrame* child = nsBoxFrame::SlowOrdinalGroupAwareSibling(mFrame, right);
// We are a header. Look for the correct splitter.
if (child && child->GetContent()->IsXULElement(nsGkAtoms::splitter)) {
aOutFrames->AppendElement(child);
}
}
}
} // namespace mozilla
void nsTreeColFrame::BuildDisplayListForChildren(
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
nsBoxFrame::BuildDisplayListForChildren(aBuilder, aLists);
if (aBuilder->IsForEventDelivery()) {
aLists.Content()->AppendNewToTop<nsDisplayXULTreeColSplitterTarget>(
aBuilder, this);
}
}

View File

@@ -1,60 +0,0 @@
/* -*- 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 "mozilla/Attributes.h"
#include "mozilla/ComputedStyle.h"
#include "nsBoxFrame.h"
namespace mozilla {
class PresShell;
namespace dom {
class XULTreeElement;
}
} // namespace mozilla
nsIFrame* NS_NewTreeColFrame(mozilla::PresShell* aPresShell,
mozilla::ComputedStyle* aStyle);
class nsTreeColFrame final : public nsBoxFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(nsTreeColFrame)
explicit nsTreeColFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
: nsBoxFrame(aStyle, aPresContext, kClassID) {}
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
virtual void BuildDisplayListForChildren(
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
virtual void SetXULBounds(nsBoxLayoutState& aBoxLayoutState,
const nsRect& aRect,
bool aRemoveOverflowArea = false) override;
friend nsIFrame* NS_NewTreeColFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
protected:
virtual ~nsTreeColFrame();
/**
* @return the tree that this column belongs to, or nullptr.
*/
mozilla::dom::XULTreeElement* GetTree();
/**
* Helper method that gets the TreeColumns object this column belongs to
* and calls InvalidateColumns() on it.
*/
void InvalidateColumns(bool aCanWalkFrameTree = true);
};

View File

@@ -203,7 +203,7 @@ class nsTreeColumns final : public nsISupports, public nsWrapperCache {
/**
* The first column in the list of columns. All of the columns are supposed
* to be "alive", i.e. have a frame. This is achieved by clearing the columns
* list each time an nsTreeColFrame is destroyed.
* list each time a treecol changes size.
*
* XXX this means that new nsTreeColumn objects are unnecessarily created
* for untouched columns.

View File

@@ -302,6 +302,10 @@
customElements.define("treecolpicker", MozTreecolPicker);
class MozTreecol extends MozElements.BaseControl {
static get observedAttributes() {
return ["primary"];
}
static get inheritedAttributes() {
return {
".treecol-sortdirection": "sortdirection,hidden=hideheader",
@@ -316,6 +320,19 @@
`;
}
get _tree() {
return this.parentNode?.parentNode;
}
_invalidate() {
let tree = this._tree;
if (!tree || !XULTreeElement.isInstance(tree)) {
return;
}
tree.invalidate();
tree.columns?.invalidateColumns();
}
constructor() {
super();
@@ -323,7 +340,7 @@
if (event.button != 0) {
return;
}
if (this.parentNode.parentNode.enableColumnDrag) {
if (this._tree.enableColumnDrag) {
var XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var cols = this.parentNode.getElementsByTagNameNS(XUL_NS, "treecol");
@@ -361,7 +378,7 @@
return;
}
var tree = this.parentNode.parentNode;
var tree = this._tree;
if (tree.columns) {
tree.view.cycleHeader(tree.columns.getColumnFor(this));
}
@@ -379,6 +396,20 @@
if (this.hasAttribute("ordinal")) {
this.style.MozBoxOrdinalGroup = this.getAttribute("ordinal");
}
this._resizeObserver = new ResizeObserver(() => {
this._invalidate();
});
this._resizeObserver.observe(this);
}
disconnectedCallback() {
this._resizeObserver?.unobserve(this);
this._resizeObserver = null;
}
attributeChangedCallback() {
this._invalidate();
}
set ordinal(val) {
@@ -1198,7 +1229,10 @@
for (i = 0; i < cols.length; ++i) {
cols[i].ordinal = parseInt(cols[i].ordinal) - 2;
}
} else {
return;
}
this.columns.invalidateColumns();
}
_getColumnAtX(aX, aThresh, aPos) {

View File

@@ -672,13 +672,14 @@ menulist[popuponly] {
/********** splitter **********/
.tree-splitter {
width: 0;
max-width: 0;
margin-inline: -4px;
width: 8px;
max-width: 8px;
min-width: 8px;
appearance: none !important;
min-width: 0 !important;
min-height: 0 !important;
border: none !important;
-moz-box-ordinal-group: 2147483646;
z-index: 2147483646;
}
/******** scrollbar ********/