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