1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/nsPopupSetFrame.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,160 @@ 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 +#include "nsPopupSetFrame.h" 1.10 +#include "nsGkAtoms.h" 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsIContent.h" 1.13 +#include "nsPresContext.h" 1.14 +#include "nsStyleContext.h" 1.15 +#include "nsBoxLayoutState.h" 1.16 +#include "nsIScrollableFrame.h" 1.17 +#include "nsIRootBox.h" 1.18 +#include "nsMenuPopupFrame.h" 1.19 + 1.20 +nsIFrame* 1.21 +NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 1.22 +{ 1.23 + return new (aPresShell) nsPopupSetFrame (aPresShell, aContext); 1.24 +} 1.25 + 1.26 +NS_IMPL_FRAMEARENA_HELPERS(nsPopupSetFrame) 1.27 + 1.28 +void 1.29 +nsPopupSetFrame::Init(nsIContent* aContent, 1.30 + nsIFrame* aParent, 1.31 + nsIFrame* aPrevInFlow) 1.32 +{ 1.33 + nsBoxFrame::Init(aContent, aParent, aPrevInFlow); 1.34 + 1.35 + // Normally the root box is our grandparent, but in case of wrapping 1.36 + // it can be our great-grandparent. 1.37 + nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell()); 1.38 + if (rootBox) { 1.39 + rootBox->SetPopupSetFrame(this); 1.40 + } 1.41 +} 1.42 + 1.43 +nsIAtom* 1.44 +nsPopupSetFrame::GetType() const 1.45 +{ 1.46 + return nsGkAtoms::popupSetFrame; 1.47 +} 1.48 + 1.49 +nsresult 1.50 +nsPopupSetFrame::AppendFrames(ChildListID aListID, 1.51 + nsFrameList& aFrameList) 1.52 +{ 1.53 + if (aListID == kPopupList) { 1.54 + AddPopupFrameList(aFrameList); 1.55 + return NS_OK; 1.56 + } 1.57 + return nsBoxFrame::AppendFrames(aListID, aFrameList); 1.58 +} 1.59 + 1.60 +nsresult 1.61 +nsPopupSetFrame::RemoveFrame(ChildListID aListID, 1.62 + nsIFrame* aOldFrame) 1.63 +{ 1.64 + if (aListID == kPopupList) { 1.65 + RemovePopupFrame(aOldFrame); 1.66 + return NS_OK; 1.67 + } 1.68 + return nsBoxFrame::RemoveFrame(aListID, aOldFrame); 1.69 +} 1.70 + 1.71 +nsresult 1.72 +nsPopupSetFrame::InsertFrames(ChildListID aListID, 1.73 + nsIFrame* aPrevFrame, 1.74 + nsFrameList& aFrameList) 1.75 +{ 1.76 + if (aListID == kPopupList) { 1.77 + AddPopupFrameList(aFrameList); 1.78 + return NS_OK; 1.79 + } 1.80 + return nsBoxFrame::InsertFrames(aListID, aPrevFrame, aFrameList); 1.81 +} 1.82 + 1.83 +nsresult 1.84 +nsPopupSetFrame::SetInitialChildList(ChildListID aListID, 1.85 + nsFrameList& aChildList) 1.86 +{ 1.87 + if (aListID == kPopupList) { 1.88 + NS_ASSERTION(mPopupList.IsEmpty(), 1.89 + "SetInitialChildList on non-empty child list"); 1.90 + AddPopupFrameList(aChildList); 1.91 + return NS_OK; 1.92 + } 1.93 + return nsBoxFrame::SetInitialChildList(aListID, aChildList); 1.94 +} 1.95 + 1.96 +const nsFrameList& 1.97 +nsPopupSetFrame::GetChildList(ChildListID aListID) const 1.98 +{ 1.99 + if (kPopupList == aListID) { 1.100 + return mPopupList; 1.101 + } 1.102 + return nsBoxFrame::GetChildList(aListID); 1.103 +} 1.104 + 1.105 +void 1.106 +nsPopupSetFrame::GetChildLists(nsTArray<ChildList>* aLists) const 1.107 +{ 1.108 + nsBoxFrame::GetChildLists(aLists); 1.109 + mPopupList.AppendIfNonempty(aLists, kPopupList); 1.110 +} 1.111 + 1.112 +void 1.113 +nsPopupSetFrame::DestroyFrom(nsIFrame* aDestructRoot) 1.114 +{ 1.115 + mPopupList.DestroyFramesFrom(aDestructRoot); 1.116 + 1.117 + // Normally the root box is our grandparent, but in case of wrapping 1.118 + // it can be our great-grandparent. 1.119 + nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell()); 1.120 + if (rootBox) { 1.121 + rootBox->SetPopupSetFrame(nullptr); 1.122 + } 1.123 + 1.124 + nsBoxFrame::DestroyFrom(aDestructRoot); 1.125 +} 1.126 + 1.127 +NS_IMETHODIMP 1.128 +nsPopupSetFrame::DoLayout(nsBoxLayoutState& aState) 1.129 +{ 1.130 + // lay us out 1.131 + nsresult rv = nsBoxFrame::DoLayout(aState); 1.132 + 1.133 + // lay out all of our currently open popups. 1.134 + for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) { 1.135 + nsMenuPopupFrame* popupChild = static_cast<nsMenuPopupFrame*>(e.get()); 1.136 + popupChild->LayoutPopup(aState, nullptr, nullptr, false); 1.137 + } 1.138 + 1.139 + return rv; 1.140 +} 1.141 + 1.142 +void 1.143 +nsPopupSetFrame::RemovePopupFrame(nsIFrame* aPopup) 1.144 +{ 1.145 + NS_PRECONDITION((aPopup->GetStateBits() & NS_FRAME_OUT_OF_FLOW) && 1.146 + aPopup->GetType() == nsGkAtoms::menuPopupFrame, 1.147 + "removing wrong type of frame in popupset's ::popupList"); 1.148 + 1.149 + mPopupList.DestroyFrame(aPopup); 1.150 +} 1.151 + 1.152 +void 1.153 +nsPopupSetFrame::AddPopupFrameList(nsFrameList& aPopupFrameList) 1.154 +{ 1.155 +#ifdef DEBUG 1.156 + for (nsFrameList::Enumerator e(aPopupFrameList); !e.AtEnd(); e.Next()) { 1.157 + NS_ASSERTION((e.get()->GetStateBits() & NS_FRAME_OUT_OF_FLOW) && 1.158 + e.get()->GetType() == nsGkAtoms::menuPopupFrame, 1.159 + "adding wrong type of frame in popupset's ::popupList"); 1.160 + } 1.161 +#endif 1.162 + mPopupList.InsertFrames(nullptr, nullptr, aPopupFrameList); 1.163 +}