Line data Source 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/. */
5 :
6 : #include "nsCOMPtr.h"
7 : #include "nsTreeColFrame.h"
8 : #include "nsGkAtoms.h"
9 : #include "nsIContent.h"
10 : #include "nsStyleContext.h"
11 : #include "nsNameSpaceManager.h"
12 : #include "nsIBoxObject.h"
13 : #include "mozilla/ErrorResult.h"
14 : #include "mozilla/dom/TreeBoxObject.h"
15 : #include "nsIDOMElement.h"
16 : #include "nsITreeColumns.h"
17 : #include "nsIDOMXULTreeElement.h"
18 : #include "nsDisplayList.h"
19 : #include "nsTreeBodyFrame.h"
20 : #include "nsXULElement.h"
21 :
22 : //
23 : // NS_NewTreeColFrame
24 : //
25 : // Creates a new col frame
26 : //
27 : nsIFrame*
28 0 : NS_NewTreeColFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
29 : {
30 0 : return new (aPresShell) nsTreeColFrame(aContext);
31 : }
32 :
33 0 : NS_IMPL_FRAMEARENA_HELPERS(nsTreeColFrame)
34 :
35 : // Destructor
36 0 : nsTreeColFrame::~nsTreeColFrame()
37 : {
38 0 : }
39 :
40 : void
41 0 : nsTreeColFrame::Init(nsIContent* aContent,
42 : nsContainerFrame* aParent,
43 : nsIFrame* aPrevInFlow)
44 : {
45 0 : nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
46 0 : InvalidateColumns();
47 0 : }
48 :
49 : void
50 0 : nsTreeColFrame::DestroyFrom(nsIFrame* aDestructRoot)
51 : {
52 0 : InvalidateColumns(false);
53 0 : nsBoxFrame::DestroyFrom(aDestructRoot);
54 0 : }
55 :
56 : class nsDisplayXULTreeColSplitterTarget final : public nsDisplayItem
57 : {
58 : public:
59 0 : nsDisplayXULTreeColSplitterTarget(nsDisplayListBuilder* aBuilder,
60 0 : nsIFrame* aFrame) :
61 0 : nsDisplayItem(aBuilder, aFrame) {
62 0 : MOZ_COUNT_CTOR(nsDisplayXULTreeColSplitterTarget);
63 0 : }
64 : #ifdef NS_BUILD_REFCNT_LOGGING
65 0 : virtual ~nsDisplayXULTreeColSplitterTarget() {
66 0 : MOZ_COUNT_DTOR(nsDisplayXULTreeColSplitterTarget);
67 0 : }
68 : #endif
69 :
70 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
71 : HitTestState* aState,
72 : nsTArray<nsIFrame*> *aOutFrames) override;
73 0 : NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget", TYPE_XUL_TREE_COL_SPLITTER_TARGET)
74 : };
75 :
76 : void
77 0 : nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
78 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
79 : {
80 0 : nsRect rect = aRect - ToReferenceFrame();
81 : // If we are in either in the first 4 pixels or the last 4 pixels, we're going to
82 : // do something really strange. Check for an adjacent splitter.
83 0 : bool left = false;
84 0 : bool right = false;
85 0 : if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <= rect.XMost()) {
86 0 : right = true;
87 0 : } else if (nsPresContext::CSSPixelsToAppUnits(4) > rect.x) {
88 0 : left = true;
89 : }
90 :
91 : // Swap left and right for RTL trees in order to find the correct splitter
92 0 : if (mFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
93 0 : bool tmp = left;
94 0 : left = right;
95 0 : right = tmp;
96 : }
97 :
98 0 : if (left || right) {
99 : // We are a header. Look for the correct splitter.
100 : nsIFrame* child;
101 0 : if (left)
102 0 : child = mFrame->GetPrevSibling();
103 : else
104 0 : child = mFrame->GetNextSibling();
105 :
106 0 : if (child && child->GetContent()->NodeInfo()->Equals(nsGkAtoms::splitter,
107 0 : kNameSpaceID_XUL)) {
108 0 : aOutFrames->AppendElement(child);
109 : }
110 : }
111 :
112 0 : }
113 :
114 : void
115 0 : nsTreeColFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
116 : const nsRect& aDirtyRect,
117 : const nsDisplayListSet& aLists)
118 : {
119 0 : if (!aBuilder->IsForEventDelivery()) {
120 0 : nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
121 0 : return;
122 : }
123 :
124 0 : nsDisplayListCollection set;
125 0 : nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, set);
126 :
127 0 : WrapListsInRedirector(aBuilder, set, aLists);
128 :
129 0 : aLists.Content()->AppendNewToTop(new (aBuilder)
130 0 : nsDisplayXULTreeColSplitterTarget(aBuilder, this));
131 : }
132 :
133 : nsresult
134 0 : nsTreeColFrame::AttributeChanged(int32_t aNameSpaceID,
135 : nsIAtom* aAttribute,
136 : int32_t aModType)
137 : {
138 0 : nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
139 0 : aModType);
140 :
141 0 : if (aAttribute == nsGkAtoms::ordinal || aAttribute == nsGkAtoms::primary) {
142 0 : InvalidateColumns();
143 : }
144 :
145 0 : return rv;
146 : }
147 :
148 : void
149 0 : nsTreeColFrame::SetXULBounds(nsBoxLayoutState& aBoxLayoutState,
150 : const nsRect& aRect,
151 : bool aRemoveOverflowArea)
152 : {
153 0 : nscoord oldWidth = mRect.width;
154 :
155 0 : nsBoxFrame::SetXULBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
156 0 : if (mRect.width != oldWidth) {
157 0 : nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
158 0 : if (treeBoxObject) {
159 0 : treeBoxObject->Invalidate();
160 : }
161 : }
162 0 : }
163 :
164 : nsITreeBoxObject*
165 0 : nsTreeColFrame::GetTreeBoxObject()
166 : {
167 0 : nsITreeBoxObject* result = nullptr;
168 :
169 0 : nsIContent* parent = mContent->GetParent();
170 0 : if (parent) {
171 0 : nsIContent* grandParent = parent->GetParent();
172 : RefPtr<nsXULElement> treeElement =
173 0 : nsXULElement::FromContentOrNull(grandParent);
174 0 : if (treeElement) {
175 0 : IgnoredErrorResult ignored;
176 0 : nsCOMPtr<nsIBoxObject> boxObject = treeElement->GetBoxObject(ignored);
177 :
178 0 : nsCOMPtr<nsITreeBoxObject> treeBoxObject = do_QueryInterface(boxObject);
179 0 : result = treeBoxObject.get();
180 : }
181 : }
182 0 : return result;
183 : }
184 :
185 : void
186 0 : nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree)
187 : {
188 0 : nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
189 0 : if (treeBoxObject) {
190 0 : nsCOMPtr<nsITreeColumns> columns;
191 :
192 0 : if (aCanWalkFrameTree) {
193 0 : treeBoxObject->GetColumns(getter_AddRefs(columns));
194 : } else {
195 : nsTreeBodyFrame* body = static_cast<mozilla::dom::TreeBoxObject*>
196 0 : (treeBoxObject)->GetCachedTreeBodyFrame();
197 0 : if (body) {
198 0 : columns = body->Columns();
199 : }
200 : }
201 :
202 0 : if (columns)
203 0 : columns->InvalidateColumns();
204 : }
205 0 : }
|