nsPopupSetFrame.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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/. */
  5. #include "nsPopupSetFrame.h"
  6. #include "nsGkAtoms.h"
  7. #include "nsCOMPtr.h"
  8. #include "nsIContent.h"
  9. #include "nsPresContext.h"
  10. #include "nsStyleContext.h"
  11. #include "nsBoxLayoutState.h"
  12. #include "nsIScrollableFrame.h"
  13. #include "nsIRootBox.h"
  14. #include "nsMenuPopupFrame.h"
  15. nsIFrame*
  16. NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  17. {
  18. return new (aPresShell) nsPopupSetFrame(aContext);
  19. }
  20. NS_IMPL_FRAMEARENA_HELPERS(nsPopupSetFrame)
  21. void
  22. nsPopupSetFrame::Init(nsIContent* aContent,
  23. nsContainerFrame* aParent,
  24. nsIFrame* aPrevInFlow)
  25. {
  26. nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
  27. // Normally the root box is our grandparent, but in case of wrapping
  28. // it can be our great-grandparent.
  29. nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
  30. if (rootBox) {
  31. rootBox->SetPopupSetFrame(this);
  32. }
  33. }
  34. nsIAtom*
  35. nsPopupSetFrame::GetType() const
  36. {
  37. return nsGkAtoms::popupSetFrame;
  38. }
  39. void
  40. nsPopupSetFrame::AppendFrames(ChildListID aListID,
  41. nsFrameList& aFrameList)
  42. {
  43. if (aListID == kPopupList) {
  44. AddPopupFrameList(aFrameList);
  45. return;
  46. }
  47. nsBoxFrame::AppendFrames(aListID, aFrameList);
  48. }
  49. void
  50. nsPopupSetFrame::RemoveFrame(ChildListID aListID,
  51. nsIFrame* aOldFrame)
  52. {
  53. if (aListID == kPopupList) {
  54. RemovePopupFrame(aOldFrame);
  55. return;
  56. }
  57. nsBoxFrame::RemoveFrame(aListID, aOldFrame);
  58. }
  59. void
  60. nsPopupSetFrame::InsertFrames(ChildListID aListID,
  61. nsIFrame* aPrevFrame,
  62. nsFrameList& aFrameList)
  63. {
  64. if (aListID == kPopupList) {
  65. AddPopupFrameList(aFrameList);
  66. return;
  67. }
  68. nsBoxFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
  69. }
  70. void
  71. nsPopupSetFrame::SetInitialChildList(ChildListID aListID,
  72. nsFrameList& aChildList)
  73. {
  74. if (aListID == kPopupList) {
  75. NS_ASSERTION(mPopupList.IsEmpty(),
  76. "SetInitialChildList on non-empty child list");
  77. AddPopupFrameList(aChildList);
  78. return;
  79. }
  80. nsBoxFrame::SetInitialChildList(aListID, aChildList);
  81. }
  82. const nsFrameList&
  83. nsPopupSetFrame::GetChildList(ChildListID aListID) const
  84. {
  85. if (kPopupList == aListID) {
  86. return mPopupList;
  87. }
  88. return nsBoxFrame::GetChildList(aListID);
  89. }
  90. void
  91. nsPopupSetFrame::GetChildLists(nsTArray<ChildList>* aLists) const
  92. {
  93. nsBoxFrame::GetChildLists(aLists);
  94. mPopupList.AppendIfNonempty(aLists, kPopupList);
  95. }
  96. void
  97. nsPopupSetFrame::DestroyFrom(nsIFrame* aDestructRoot)
  98. {
  99. mPopupList.DestroyFramesFrom(aDestructRoot);
  100. // Normally the root box is our grandparent, but in case of wrapping
  101. // it can be our great-grandparent.
  102. nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
  103. if (rootBox) {
  104. rootBox->SetPopupSetFrame(nullptr);
  105. }
  106. nsBoxFrame::DestroyFrom(aDestructRoot);
  107. }
  108. NS_IMETHODIMP
  109. nsPopupSetFrame::DoXULLayout(nsBoxLayoutState& aState)
  110. {
  111. // lay us out
  112. nsresult rv = nsBoxFrame::DoXULLayout(aState);
  113. // lay out all of our currently open popups.
  114. for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) {
  115. nsMenuPopupFrame* popupChild = static_cast<nsMenuPopupFrame*>(e.get());
  116. popupChild->LayoutPopup(aState, nullptr, nullptr, false);
  117. }
  118. return rv;
  119. }
  120. void
  121. nsPopupSetFrame::RemovePopupFrame(nsIFrame* aPopup)
  122. {
  123. NS_PRECONDITION((aPopup->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
  124. aPopup->GetType() == nsGkAtoms::menuPopupFrame,
  125. "removing wrong type of frame in popupset's ::popupList");
  126. mPopupList.DestroyFrame(aPopup);
  127. }
  128. void
  129. nsPopupSetFrame::AddPopupFrameList(nsFrameList& aPopupFrameList)
  130. {
  131. #ifdef DEBUG
  132. for (nsFrameList::Enumerator e(aPopupFrameList); !e.AtEnd(); e.Next()) {
  133. NS_ASSERTION((e.get()->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
  134. e.get()->GetType() == nsGkAtoms::menuPopupFrame,
  135. "adding wrong type of frame in popupset's ::popupList");
  136. }
  137. #endif
  138. mPopupList.InsertFrames(nullptr, nullptr, aPopupFrameList);
  139. }