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 //
7 // Eric Vaughan
8 // Netscape Communications
9 //
10 // See documentation in associated header file
11 //
13 #include "nsDeckFrame.h"
14 #include "nsStyleContext.h"
15 #include "nsPresContext.h"
16 #include "nsIContent.h"
17 #include "nsCOMPtr.h"
18 #include "nsNameSpaceManager.h"
19 #include "nsGkAtoms.h"
20 #include "nsHTMLParts.h"
21 #include "nsIPresShell.h"
22 #include "nsCSSRendering.h"
23 #include "nsViewManager.h"
24 #include "nsBoxLayoutState.h"
25 #include "nsStackLayout.h"
26 #include "nsDisplayList.h"
27 #include "nsContainerFrame.h"
29 #ifdef ACCESSIBILITY
30 #include "nsAccessibilityService.h"
31 #endif
33 nsIFrame*
34 NS_NewDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
35 {
36 return new (aPresShell) nsDeckFrame(aPresShell, aContext);
37 }
39 NS_IMPL_FRAMEARENA_HELPERS(nsDeckFrame)
41 NS_QUERYFRAME_HEAD(nsDeckFrame)
42 NS_QUERYFRAME_ENTRY(nsDeckFrame)
43 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
46 nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
47 : nsBoxFrame(aPresShell, aContext), mIndex(0)
48 {
49 nsCOMPtr<nsBoxLayout> layout;
50 NS_NewStackLayout(aPresShell, layout);
51 SetLayoutManager(layout);
52 }
54 nsIAtom*
55 nsDeckFrame::GetType() const
56 {
57 return nsGkAtoms::deckFrame;
58 }
60 nsresult
61 nsDeckFrame::AttributeChanged(int32_t aNameSpaceID,
62 nsIAtom* aAttribute,
63 int32_t aModType)
64 {
65 nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
66 aModType);
69 // if the index changed hide the old element and make the new element visible
70 if (aAttribute == nsGkAtoms::selectedIndex) {
71 IndexChanged();
72 }
74 return rv;
75 }
77 void
78 nsDeckFrame::Init(nsIContent* aContent,
79 nsIFrame* aParent,
80 nsIFrame* aPrevInFlow)
81 {
82 nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
84 mIndex = GetSelectedIndex();
85 }
87 void
88 nsDeckFrame::HideBox(nsIFrame* aBox)
89 {
90 nsIPresShell::ClearMouseCapture(aBox);
91 }
93 void
94 nsDeckFrame::IndexChanged()
95 {
96 //did the index change?
97 int32_t index = GetSelectedIndex();
98 if (index == mIndex)
99 return;
101 // redraw
102 InvalidateFrame();
104 // hide the currently showing box
105 nsIFrame* currentBox = GetSelectedBox();
106 if (currentBox) // only hide if it exists
107 HideBox(currentBox);
109 mIndex = index;
111 #ifdef ACCESSIBILITY
112 nsAccessibilityService* accService = GetAccService();
113 if (accService) {
114 accService->DeckPanelSwitched(PresContext()->GetPresShell(), mContent,
115 currentBox, GetSelectedBox());
116 }
117 #endif
118 }
120 int32_t
121 nsDeckFrame::GetSelectedIndex()
122 {
123 // default index is 0
124 int32_t index = 0;
126 // get the index attribute
127 nsAutoString value;
128 if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::selectedIndex, value))
129 {
130 nsresult error;
132 // convert it to an integer
133 index = value.ToInteger(&error);
134 }
136 return index;
137 }
139 nsIFrame*
140 nsDeckFrame::GetSelectedBox()
141 {
142 return (mIndex >= 0) ? mFrames.FrameAt(mIndex) : nullptr;
143 }
145 void
146 nsDeckFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
147 const nsRect& aDirtyRect,
148 const nsDisplayListSet& aLists)
149 {
150 // if a tab is hidden all its children are too.
151 if (!StyleVisibility()->mVisible)
152 return;
154 nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
155 }
157 void
158 nsDeckFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
159 const nsRect& aDirtyRect,
160 const nsDisplayListSet& aLists)
161 {
162 // only paint the selected box
163 nsIFrame* box = GetSelectedBox();
164 if (!box)
165 return;
167 // Putting the child in the background list. This is a little weird but
168 // it matches what we were doing before.
169 nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
170 BuildDisplayListForChild(aBuilder, box, aDirtyRect, set);
171 }
173 NS_IMETHODIMP
174 nsDeckFrame::DoLayout(nsBoxLayoutState& aState)
175 {
176 // Make sure we tweak the state so it does not resize our children.
177 // We will do that.
178 uint32_t oldFlags = aState.LayoutFlags();
179 aState.SetLayoutFlags(NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_VISIBILITY);
181 // do a normal layout
182 nsresult rv = nsBoxFrame::DoLayout(aState);
184 // run though each child. Hide all but the selected one
185 nsIFrame* box = GetChildBox();
187 nscoord count = 0;
188 while (box)
189 {
190 // make collapsed children not show up
191 if (count != mIndex)
192 HideBox(box);
194 box = box->GetNextBox();
195 count++;
196 }
198 aState.SetLayoutFlags(oldFlags);
200 return rv;
201 }