1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/nsDeckFrame.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,202 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// 1.10 +// Eric Vaughan 1.11 +// Netscape Communications 1.12 +// 1.13 +// See documentation in associated header file 1.14 +// 1.15 + 1.16 +#include "nsDeckFrame.h" 1.17 +#include "nsStyleContext.h" 1.18 +#include "nsPresContext.h" 1.19 +#include "nsIContent.h" 1.20 +#include "nsCOMPtr.h" 1.21 +#include "nsNameSpaceManager.h" 1.22 +#include "nsGkAtoms.h" 1.23 +#include "nsHTMLParts.h" 1.24 +#include "nsIPresShell.h" 1.25 +#include "nsCSSRendering.h" 1.26 +#include "nsViewManager.h" 1.27 +#include "nsBoxLayoutState.h" 1.28 +#include "nsStackLayout.h" 1.29 +#include "nsDisplayList.h" 1.30 +#include "nsContainerFrame.h" 1.31 + 1.32 +#ifdef ACCESSIBILITY 1.33 +#include "nsAccessibilityService.h" 1.34 +#endif 1.35 + 1.36 +nsIFrame* 1.37 +NS_NewDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 1.38 +{ 1.39 + return new (aPresShell) nsDeckFrame(aPresShell, aContext); 1.40 +} 1.41 + 1.42 +NS_IMPL_FRAMEARENA_HELPERS(nsDeckFrame) 1.43 + 1.44 +NS_QUERYFRAME_HEAD(nsDeckFrame) 1.45 + NS_QUERYFRAME_ENTRY(nsDeckFrame) 1.46 +NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame) 1.47 + 1.48 + 1.49 +nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 1.50 + : nsBoxFrame(aPresShell, aContext), mIndex(0) 1.51 +{ 1.52 + nsCOMPtr<nsBoxLayout> layout; 1.53 + NS_NewStackLayout(aPresShell, layout); 1.54 + SetLayoutManager(layout); 1.55 +} 1.56 + 1.57 +nsIAtom* 1.58 +nsDeckFrame::GetType() const 1.59 +{ 1.60 + return nsGkAtoms::deckFrame; 1.61 +} 1.62 + 1.63 +nsresult 1.64 +nsDeckFrame::AttributeChanged(int32_t aNameSpaceID, 1.65 + nsIAtom* aAttribute, 1.66 + int32_t aModType) 1.67 +{ 1.68 + nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, 1.69 + aModType); 1.70 + 1.71 + 1.72 + // if the index changed hide the old element and make the new element visible 1.73 + if (aAttribute == nsGkAtoms::selectedIndex) { 1.74 + IndexChanged(); 1.75 + } 1.76 + 1.77 + return rv; 1.78 +} 1.79 + 1.80 +void 1.81 +nsDeckFrame::Init(nsIContent* aContent, 1.82 + nsIFrame* aParent, 1.83 + nsIFrame* aPrevInFlow) 1.84 +{ 1.85 + nsBoxFrame::Init(aContent, aParent, aPrevInFlow); 1.86 + 1.87 + mIndex = GetSelectedIndex(); 1.88 +} 1.89 + 1.90 +void 1.91 +nsDeckFrame::HideBox(nsIFrame* aBox) 1.92 +{ 1.93 + nsIPresShell::ClearMouseCapture(aBox); 1.94 +} 1.95 + 1.96 +void 1.97 +nsDeckFrame::IndexChanged() 1.98 +{ 1.99 + //did the index change? 1.100 + int32_t index = GetSelectedIndex(); 1.101 + if (index == mIndex) 1.102 + return; 1.103 + 1.104 + // redraw 1.105 + InvalidateFrame(); 1.106 + 1.107 + // hide the currently showing box 1.108 + nsIFrame* currentBox = GetSelectedBox(); 1.109 + if (currentBox) // only hide if it exists 1.110 + HideBox(currentBox); 1.111 + 1.112 + mIndex = index; 1.113 + 1.114 +#ifdef ACCESSIBILITY 1.115 + nsAccessibilityService* accService = GetAccService(); 1.116 + if (accService) { 1.117 + accService->DeckPanelSwitched(PresContext()->GetPresShell(), mContent, 1.118 + currentBox, GetSelectedBox()); 1.119 + } 1.120 +#endif 1.121 +} 1.122 + 1.123 +int32_t 1.124 +nsDeckFrame::GetSelectedIndex() 1.125 +{ 1.126 + // default index is 0 1.127 + int32_t index = 0; 1.128 + 1.129 + // get the index attribute 1.130 + nsAutoString value; 1.131 + if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::selectedIndex, value)) 1.132 + { 1.133 + nsresult error; 1.134 + 1.135 + // convert it to an integer 1.136 + index = value.ToInteger(&error); 1.137 + } 1.138 + 1.139 + return index; 1.140 +} 1.141 + 1.142 +nsIFrame* 1.143 +nsDeckFrame::GetSelectedBox() 1.144 +{ 1.145 + return (mIndex >= 0) ? mFrames.FrameAt(mIndex) : nullptr; 1.146 +} 1.147 + 1.148 +void 1.149 +nsDeckFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.150 + const nsRect& aDirtyRect, 1.151 + const nsDisplayListSet& aLists) 1.152 +{ 1.153 + // if a tab is hidden all its children are too. 1.154 + if (!StyleVisibility()->mVisible) 1.155 + return; 1.156 + 1.157 + nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); 1.158 +} 1.159 + 1.160 +void 1.161 +nsDeckFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder, 1.162 + const nsRect& aDirtyRect, 1.163 + const nsDisplayListSet& aLists) 1.164 +{ 1.165 + // only paint the selected box 1.166 + nsIFrame* box = GetSelectedBox(); 1.167 + if (!box) 1.168 + return; 1.169 + 1.170 + // Putting the child in the background list. This is a little weird but 1.171 + // it matches what we were doing before. 1.172 + nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds()); 1.173 + BuildDisplayListForChild(aBuilder, box, aDirtyRect, set); 1.174 +} 1.175 + 1.176 +NS_IMETHODIMP 1.177 +nsDeckFrame::DoLayout(nsBoxLayoutState& aState) 1.178 +{ 1.179 + // Make sure we tweak the state so it does not resize our children. 1.180 + // We will do that. 1.181 + uint32_t oldFlags = aState.LayoutFlags(); 1.182 + aState.SetLayoutFlags(NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_VISIBILITY); 1.183 + 1.184 + // do a normal layout 1.185 + nsresult rv = nsBoxFrame::DoLayout(aState); 1.186 + 1.187 + // run though each child. Hide all but the selected one 1.188 + nsIFrame* box = GetChildBox(); 1.189 + 1.190 + nscoord count = 0; 1.191 + while (box) 1.192 + { 1.193 + // make collapsed children not show up 1.194 + if (count != mIndex) 1.195 + HideBox(box); 1.196 + 1.197 + box = box->GetNextBox(); 1.198 + count++; 1.199 + } 1.200 + 1.201 + aState.SetLayoutFlags(oldFlags); 1.202 + 1.203 + return rv; 1.204 +} 1.205 +