1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/nsListBoxObject.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,211 @@ 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 "nsCOMPtr.h" 1.10 +#include "nsPIListBoxObject.h" 1.11 +#include "nsBoxObject.h" 1.12 +#include "nsIFrame.h" 1.13 +#include "nsBindingManager.h" 1.14 +#include "nsIDOMElement.h" 1.15 +#include "nsIDOMNodeList.h" 1.16 +#include "nsGkAtoms.h" 1.17 +#include "nsIScrollableFrame.h" 1.18 +#include "nsListBoxBodyFrame.h" 1.19 +#include "ChildIterator.h" 1.20 + 1.21 +class nsListBoxObject : public nsPIListBoxObject, public nsBoxObject 1.22 +{ 1.23 +public: 1.24 + NS_DECL_ISUPPORTS_INHERITED 1.25 + NS_DECL_NSILISTBOXOBJECT 1.26 + 1.27 + // nsPIListBoxObject 1.28 + virtual nsListBoxBodyFrame* GetListBoxBody(bool aFlush) MOZ_OVERRIDE; 1.29 + 1.30 + nsListBoxObject(); 1.31 + 1.32 + // nsPIBoxObject 1.33 + virtual void Clear() MOZ_OVERRIDE; 1.34 + virtual void ClearCachedValues() MOZ_OVERRIDE; 1.35 + 1.36 +protected: 1.37 + nsListBoxBodyFrame *mListBoxBody; 1.38 +}; 1.39 + 1.40 +NS_IMPL_ISUPPORTS_INHERITED(nsListBoxObject, nsBoxObject, nsIListBoxObject, 1.41 + nsPIListBoxObject) 1.42 + 1.43 +nsListBoxObject::nsListBoxObject() 1.44 + : mListBoxBody(nullptr) 1.45 +{ 1.46 +} 1.47 + 1.48 +////////////////////////////////////////////////////////////////////////// 1.49 +//// nsIListBoxObject 1.50 + 1.51 +NS_IMETHODIMP 1.52 +nsListBoxObject::GetRowCount(int32_t *aResult) 1.53 +{ 1.54 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.55 + if (body) 1.56 + return body->GetRowCount(aResult); 1.57 + return NS_OK; 1.58 +} 1.59 + 1.60 +NS_IMETHODIMP 1.61 +nsListBoxObject::GetNumberOfVisibleRows(int32_t *aResult) 1.62 +{ 1.63 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.64 + if (body) 1.65 + return body->GetNumberOfVisibleRows(aResult); 1.66 + return NS_OK; 1.67 +} 1.68 + 1.69 +NS_IMETHODIMP 1.70 +nsListBoxObject::GetIndexOfFirstVisibleRow(int32_t *aResult) 1.71 +{ 1.72 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.73 + if (body) 1.74 + return body->GetIndexOfFirstVisibleRow(aResult); 1.75 + return NS_OK; 1.76 +} 1.77 + 1.78 +NS_IMETHODIMP nsListBoxObject::EnsureIndexIsVisible(int32_t aRowIndex) 1.79 +{ 1.80 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.81 + if (body) 1.82 + return body->EnsureIndexIsVisible(aRowIndex); 1.83 + return NS_OK; 1.84 +} 1.85 + 1.86 +NS_IMETHODIMP 1.87 +nsListBoxObject::ScrollToIndex(int32_t aRowIndex) 1.88 +{ 1.89 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.90 + if (body) 1.91 + return body->ScrollToIndex(aRowIndex); 1.92 + return NS_OK; 1.93 +} 1.94 + 1.95 +NS_IMETHODIMP 1.96 +nsListBoxObject::ScrollByLines(int32_t aNumLines) 1.97 +{ 1.98 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.99 + if (body) 1.100 + return body->ScrollByLines(aNumLines); 1.101 + return NS_OK; 1.102 +} 1.103 + 1.104 +NS_IMETHODIMP 1.105 +nsListBoxObject::GetItemAtIndex(int32_t index, nsIDOMElement **_retval) 1.106 +{ 1.107 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.108 + if (body) 1.109 + return body->GetItemAtIndex(index, _retval); 1.110 + return NS_OK; 1.111 +} 1.112 + 1.113 +NS_IMETHODIMP 1.114 +nsListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, int32_t *aResult) 1.115 +{ 1.116 + *aResult = 0; 1.117 + 1.118 + nsListBoxBodyFrame* body = GetListBoxBody(true); 1.119 + if (body) 1.120 + return body->GetIndexOfItem(aElement, aResult); 1.121 + return NS_OK; 1.122 +} 1.123 + 1.124 +////////////////////// 1.125 + 1.126 +static nsIContent* 1.127 +FindBodyContent(nsIContent* aParent) 1.128 +{ 1.129 + if (aParent->Tag() == nsGkAtoms::listboxbody) { 1.130 + return aParent; 1.131 + } 1.132 + 1.133 + mozilla::dom::FlattenedChildIterator iter(aParent); 1.134 + for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { 1.135 + nsIContent* result = FindBodyContent(child); 1.136 + if (result) { 1.137 + return result; 1.138 + } 1.139 + } 1.140 + 1.141 + return nullptr; 1.142 +} 1.143 + 1.144 +nsListBoxBodyFrame* 1.145 +nsListBoxObject::GetListBoxBody(bool aFlush) 1.146 +{ 1.147 + if (mListBoxBody) { 1.148 + return mListBoxBody; 1.149 + } 1.150 + 1.151 + nsIPresShell* shell = GetPresShell(false); 1.152 + if (!shell) { 1.153 + return nullptr; 1.154 + } 1.155 + 1.156 + nsIFrame* frame = aFlush ? 1.157 + GetFrame(false) /* does Flush_Frames */ : 1.158 + mContent->GetPrimaryFrame(); 1.159 + if (!frame) 1.160 + return nullptr; 1.161 + 1.162 + // Iterate over our content model children looking for the body. 1.163 + nsCOMPtr<nsIContent> content = FindBodyContent(frame->GetContent()); 1.164 + 1.165 + if (!content) 1.166 + return nullptr; 1.167 + 1.168 + // this frame will be a nsGFXScrollFrame 1.169 + frame = content->GetPrimaryFrame(); 1.170 + if (!frame) 1.171 + return nullptr; 1.172 + nsIScrollableFrame* scrollFrame = do_QueryFrame(frame); 1.173 + if (!scrollFrame) 1.174 + return nullptr; 1.175 + 1.176 + // this frame will be the one we want 1.177 + nsIFrame* yeahBaby = scrollFrame->GetScrolledFrame(); 1.178 + if (!yeahBaby) 1.179 + return nullptr; 1.180 + 1.181 + // It's a frame. Refcounts are irrelevant. 1.182 + nsListBoxBodyFrame* listBoxBody = do_QueryFrame(yeahBaby); 1.183 + NS_ENSURE_TRUE(listBoxBody && 1.184 + listBoxBody->SetBoxObject(this), 1.185 + nullptr); 1.186 + mListBoxBody = listBoxBody; 1.187 + return mListBoxBody; 1.188 +} 1.189 + 1.190 +void 1.191 +nsListBoxObject::Clear() 1.192 +{ 1.193 + ClearCachedValues(); 1.194 + 1.195 + nsBoxObject::Clear(); 1.196 +} 1.197 + 1.198 +void 1.199 +nsListBoxObject::ClearCachedValues() 1.200 +{ 1.201 + mListBoxBody = nullptr; 1.202 +} 1.203 + 1.204 +// Creation Routine /////////////////////////////////////////////////////////////////////// 1.205 + 1.206 +nsresult 1.207 +NS_NewListBoxObject(nsIBoxObject** aResult) 1.208 +{ 1.209 + *aResult = new nsListBoxObject; 1.210 + if (!*aResult) 1.211 + return NS_ERROR_OUT_OF_MEMORY; 1.212 + NS_ADDREF(*aResult); 1.213 + return NS_OK; 1.214 +}