ListBoxObject.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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 "mozilla/dom/ListBoxObject.h"
  6. #include "nsCOMPtr.h"
  7. #include "nsIFrame.h"
  8. #include "nsGkAtoms.h"
  9. #include "nsIScrollableFrame.h"
  10. #include "nsListBoxBodyFrame.h"
  11. #include "ChildIterator.h"
  12. #include "mozilla/dom/Element.h"
  13. #include "mozilla/dom/ListBoxObjectBinding.h"
  14. namespace mozilla {
  15. namespace dom {
  16. NS_IMPL_ISUPPORTS_INHERITED(ListBoxObject, BoxObject, nsIListBoxObject,
  17. nsPIListBoxObject)
  18. ListBoxObject::ListBoxObject()
  19. : mListBoxBody(nullptr)
  20. {
  21. }
  22. ListBoxObject::~ListBoxObject()
  23. {
  24. }
  25. JSObject* ListBoxObject::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  26. {
  27. return ListBoxObjectBinding::Wrap(aCx, this, aGivenProto);
  28. }
  29. // nsIListBoxObject
  30. NS_IMETHODIMP
  31. ListBoxObject::GetRowCount(int32_t *aResult)
  32. {
  33. *aResult = GetRowCount();
  34. return NS_OK;
  35. }
  36. NS_IMETHODIMP
  37. ListBoxObject::GetItemAtIndex(int32_t index, nsIDOMElement **_retval)
  38. {
  39. nsListBoxBodyFrame* body = GetListBoxBody(true);
  40. if (body) {
  41. return body->GetItemAtIndex(index, _retval);
  42. }
  43. return NS_OK;
  44. }
  45. NS_IMETHODIMP
  46. ListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, int32_t *aResult)
  47. {
  48. *aResult = 0;
  49. nsListBoxBodyFrame* body = GetListBoxBody(true);
  50. if (body) {
  51. return body->GetIndexOfItem(aElement, aResult);
  52. }
  53. return NS_OK;
  54. }
  55. // ListBoxObject
  56. int32_t
  57. ListBoxObject::GetRowCount()
  58. {
  59. nsListBoxBodyFrame* body = GetListBoxBody(true);
  60. if (body) {
  61. return body->GetRowCount();
  62. }
  63. return 0;
  64. }
  65. int32_t
  66. ListBoxObject::GetNumberOfVisibleRows()
  67. {
  68. nsListBoxBodyFrame* body = GetListBoxBody(true);
  69. if (body) {
  70. return body->GetNumberOfVisibleRows();
  71. }
  72. return 0;
  73. }
  74. int32_t
  75. ListBoxObject::GetIndexOfFirstVisibleRow()
  76. {
  77. nsListBoxBodyFrame* body = GetListBoxBody(true);
  78. if (body) {
  79. return body->GetIndexOfFirstVisibleRow();
  80. }
  81. return 0;
  82. }
  83. void
  84. ListBoxObject::EnsureIndexIsVisible(int32_t aRowIndex)
  85. {
  86. nsListBoxBodyFrame* body = GetListBoxBody(true);
  87. if (body) {
  88. body->EnsureIndexIsVisible(aRowIndex);
  89. }
  90. }
  91. void
  92. ListBoxObject::ScrollToIndex(int32_t aRowIndex)
  93. {
  94. nsListBoxBodyFrame* body = GetListBoxBody(true);
  95. if (body) {
  96. body->ScrollToIndex(aRowIndex);
  97. }
  98. }
  99. void
  100. ListBoxObject::ScrollByLines(int32_t aNumLines)
  101. {
  102. nsListBoxBodyFrame* body = GetListBoxBody(true);
  103. if (body) {
  104. body->ScrollByLines(aNumLines);
  105. }
  106. }
  107. already_AddRefed<Element>
  108. ListBoxObject::GetItemAtIndex(int32_t index)
  109. {
  110. nsCOMPtr<nsIDOMElement> el;
  111. GetItemAtIndex(index, getter_AddRefs(el));
  112. nsCOMPtr<Element> ret(do_QueryInterface(el));
  113. return ret.forget();
  114. }
  115. int32_t
  116. ListBoxObject::GetIndexOfItem(Element& aElement)
  117. {
  118. int32_t ret;
  119. nsCOMPtr<nsIDOMElement> el(do_QueryInterface(&aElement));
  120. GetIndexOfItem(el, &ret);
  121. return ret;
  122. }
  123. //////////////////////
  124. static nsIContent*
  125. FindBodyContent(nsIContent* aParent)
  126. {
  127. if (aParent->IsXULElement(nsGkAtoms::listboxbody)) {
  128. return aParent;
  129. }
  130. mozilla::dom::FlattenedChildIterator iter(aParent);
  131. for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
  132. nsIContent* result = FindBodyContent(child);
  133. if (result) {
  134. return result;
  135. }
  136. }
  137. return nullptr;
  138. }
  139. nsListBoxBodyFrame*
  140. ListBoxObject::GetListBoxBody(bool aFlush)
  141. {
  142. if (mListBoxBody) {
  143. return mListBoxBody;
  144. }
  145. nsIPresShell* shell = GetPresShell(false);
  146. if (!shell) {
  147. return nullptr;
  148. }
  149. nsIFrame* frame = aFlush ?
  150. GetFrame(false) /* does Flush_Frames */ :
  151. mContent->GetPrimaryFrame();
  152. if (!frame) {
  153. return nullptr;
  154. }
  155. // Iterate over our content model children looking for the body.
  156. nsCOMPtr<nsIContent> content = FindBodyContent(frame->GetContent());
  157. if (!content) {
  158. return nullptr;
  159. }
  160. // this frame will be a nsGFXScrollFrame
  161. frame = content->GetPrimaryFrame();
  162. if (!frame) {
  163. return nullptr;
  164. }
  165. nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
  166. if (!scrollFrame) {
  167. return nullptr;
  168. }
  169. // this frame will be the one we want
  170. nsIFrame* yeahBaby = scrollFrame->GetScrolledFrame();
  171. if (!yeahBaby) {
  172. return nullptr;
  173. }
  174. // It's a frame. Refcounts are irrelevant.
  175. nsListBoxBodyFrame* listBoxBody = do_QueryFrame(yeahBaby);
  176. NS_ENSURE_TRUE(listBoxBody &&
  177. listBoxBody->SetBoxObject(this),
  178. nullptr);
  179. mListBoxBody = listBoxBody;
  180. return mListBoxBody;
  181. }
  182. void
  183. ListBoxObject::Clear()
  184. {
  185. ClearCachedValues();
  186. BoxObject::Clear();
  187. }
  188. void
  189. ListBoxObject::ClearCachedValues()
  190. {
  191. mListBoxBody = nullptr;
  192. }
  193. } // namespace dom
  194. } // namespace mozilla
  195. // Creation Routine ///////////////////////////////////////////////////////////////////////
  196. nsresult
  197. NS_NewListBoxObject(nsIBoxObject** aResult)
  198. {
  199. NS_ADDREF(*aResult = new mozilla::dom::ListBoxObject());
  200. return NS_OK;
  201. }