1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Dave Hyatt <hyatt@mozilla.org> (Original Author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsCOMPtr.h"
40 : #include "nsTreeColFrame.h"
41 : #include "nsGkAtoms.h"
42 : #include "nsIContent.h"
43 : #include "nsStyleContext.h"
44 : #include "nsINameSpaceManager.h"
45 : #include "nsIDocument.h"
46 : #include "nsIBoxObject.h"
47 : #include "nsTreeBoxObject.h"
48 : #include "nsIDOMElement.h"
49 : #include "nsITreeBoxObject.h"
50 : #include "nsITreeColumns.h"
51 : #include "nsIDOMXULTreeElement.h"
52 : #include "nsDisplayList.h"
53 : #include "nsTreeBodyFrame.h"
54 :
55 : //
56 : // NS_NewTreeColFrame
57 : //
58 : // Creates a new col frame
59 : //
60 : nsIFrame*
61 0 : NS_NewTreeColFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
62 : {
63 0 : return new (aPresShell) nsTreeColFrame(aPresShell, aContext);
64 : }
65 :
66 0 : NS_IMPL_FRAMEARENA_HELPERS(nsTreeColFrame)
67 :
68 : // Destructor
69 0 : nsTreeColFrame::~nsTreeColFrame()
70 : {
71 0 : }
72 :
73 : NS_IMETHODIMP
74 0 : nsTreeColFrame::Init(nsIContent* aContent,
75 : nsIFrame* aParent,
76 : nsIFrame* aPrevInFlow)
77 : {
78 0 : nsresult rv = nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
79 0 : InvalidateColumns();
80 0 : return rv;
81 : }
82 :
83 : void
84 0 : nsTreeColFrame::DestroyFrom(nsIFrame* aDestructRoot)
85 : {
86 0 : InvalidateColumns(false);
87 0 : nsBoxFrame::DestroyFrom(aDestructRoot);
88 0 : }
89 :
90 : class nsDisplayXULTreeColSplitterTarget : public nsDisplayItem {
91 : public:
92 0 : nsDisplayXULTreeColSplitterTarget(nsDisplayListBuilder* aBuilder,
93 : nsIFrame* aFrame) :
94 0 : nsDisplayItem(aBuilder, aFrame) {
95 0 : MOZ_COUNT_CTOR(nsDisplayXULTreeColSplitterTarget);
96 0 : }
97 : #ifdef NS_BUILD_REFCNT_LOGGING
98 0 : virtual ~nsDisplayXULTreeColSplitterTarget() {
99 0 : MOZ_COUNT_DTOR(nsDisplayXULTreeColSplitterTarget);
100 0 : }
101 : #endif
102 :
103 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
104 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
105 0 : NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget", TYPE_XUL_TREE_COL_SPLITTER_TARGET)
106 : };
107 :
108 : void
109 0 : nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
110 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
111 : {
112 0 : nsRect rect = aRect - ToReferenceFrame();
113 : // If we are in either in the first 4 pixels or the last 4 pixels, we're going to
114 : // do something really strange. Check for an adjacent splitter.
115 0 : bool left = false;
116 0 : bool right = false;
117 0 : if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <= rect.XMost()) {
118 0 : right = true;
119 0 : } else if (nsPresContext::CSSPixelsToAppUnits(4) > rect.x) {
120 0 : left = true;
121 : }
122 :
123 : // Swap left and right for RTL trees in order to find the correct splitter
124 0 : if (mFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
125 0 : bool tmp = left;
126 0 : left = right;
127 0 : right = tmp;
128 : }
129 :
130 0 : if (left || right) {
131 : // We are a header. Look for the correct splitter.
132 : nsIFrame* child;
133 0 : if (left)
134 0 : child = mFrame->GetPrevSibling();
135 : else
136 0 : child = mFrame->GetNextSibling();
137 :
138 0 : if (child && child->GetContent()->NodeInfo()->Equals(nsGkAtoms::splitter,
139 0 : kNameSpaceID_XUL)) {
140 0 : aOutFrames->AppendElement(child);
141 : }
142 : }
143 :
144 0 : }
145 :
146 : nsresult
147 0 : nsTreeColFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
148 : const nsRect& aDirtyRect,
149 : const nsDisplayListSet& aLists)
150 : {
151 0 : if (!aBuilder->IsForEventDelivery())
152 0 : return nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
153 :
154 0 : nsDisplayListCollection set;
155 0 : nsresult rv = nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, set);
156 0 : NS_ENSURE_SUCCESS(rv, rv);
157 :
158 0 : rv = WrapListsInRedirector(aBuilder, set, aLists);
159 0 : NS_ENSURE_SUCCESS(rv, rv);
160 :
161 : return aLists.Content()->AppendNewToTop(new (aBuilder)
162 0 : nsDisplayXULTreeColSplitterTarget(aBuilder, this));
163 : }
164 :
165 : NS_IMETHODIMP
166 0 : nsTreeColFrame::AttributeChanged(PRInt32 aNameSpaceID,
167 : nsIAtom* aAttribute,
168 : PRInt32 aModType)
169 : {
170 : nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
171 0 : aModType);
172 :
173 0 : if (aAttribute == nsGkAtoms::ordinal || aAttribute == nsGkAtoms::primary) {
174 0 : InvalidateColumns();
175 : }
176 :
177 0 : return rv;
178 : }
179 :
180 : void
181 0 : nsTreeColFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState,
182 : const nsRect& aRect,
183 : bool aRemoveOverflowArea) {
184 0 : nscoord oldWidth = mRect.width;
185 :
186 0 : nsBoxFrame::SetBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
187 0 : if (mRect.width != oldWidth) {
188 0 : nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
189 0 : if (treeBoxObject) {
190 0 : treeBoxObject->Invalidate();
191 : }
192 : }
193 0 : }
194 :
195 : nsITreeBoxObject*
196 0 : nsTreeColFrame::GetTreeBoxObject()
197 : {
198 0 : nsITreeBoxObject* result = nsnull;
199 :
200 0 : nsIContent* parent = mContent->GetParent();
201 0 : if (parent) {
202 0 : nsIContent* grandParent = parent->GetParent();
203 0 : nsCOMPtr<nsIDOMXULElement> treeElement = do_QueryInterface(grandParent);
204 0 : if (treeElement) {
205 0 : nsCOMPtr<nsIBoxObject> boxObject;
206 0 : treeElement->GetBoxObject(getter_AddRefs(boxObject));
207 :
208 0 : nsCOMPtr<nsITreeBoxObject> treeBoxObject = do_QueryInterface(boxObject);
209 0 : result = treeBoxObject.get();
210 : }
211 : }
212 0 : return result;
213 : }
214 :
215 : void
216 0 : nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree)
217 : {
218 0 : nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
219 0 : if (treeBoxObject) {
220 0 : nsCOMPtr<nsITreeColumns> columns;
221 :
222 0 : if (aCanWalkFrameTree) {
223 0 : treeBoxObject->GetColumns(getter_AddRefs(columns));
224 : } else {
225 0 : nsTreeBodyFrame* body = static_cast<nsTreeBoxObject*>(treeBoxObject)->GetCachedTreeBody();
226 0 : if (body) {
227 0 : body->GetColumns(getter_AddRefs(columns));
228 : }
229 : }
230 :
231 0 : if (columns)
232 0 : columns->InvalidateColumns();
233 : }
234 0 : }
|