michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsListBoxBodyFrame_h michael@0: #define nsListBoxBodyFrame_h michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsBoxFrame.h" michael@0: #include "nsIListBoxObject.h" michael@0: #include "nsIScrollbarMediator.h" michael@0: #include "nsIReflowCallback.h" michael@0: #include "nsBoxLayoutState.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsPIBoxObject.h" michael@0: michael@0: class nsPresContext; michael@0: class nsListScrollSmoother; michael@0: nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell, michael@0: nsStyleContext* aContext); michael@0: michael@0: class nsListBoxBodyFrame : public nsBoxFrame, michael@0: public nsIScrollbarMediator, michael@0: public nsIReflowCallback michael@0: { michael@0: nsListBoxBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, michael@0: nsBoxLayout* aLayoutManager); michael@0: virtual ~nsListBoxBodyFrame(); michael@0: michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsListBoxBodyFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: // non-virtual nsIListBoxObject michael@0: nsresult GetRowCount(int32_t *aResult); michael@0: nsresult GetNumberOfVisibleRows(int32_t *aResult); michael@0: nsresult GetIndexOfFirstVisibleRow(int32_t *aResult); michael@0: nsresult EnsureIndexIsVisible(int32_t aRowIndex); michael@0: nsresult ScrollToIndex(int32_t aRowIndex); michael@0: nsresult ScrollByLines(int32_t aNumLines); michael@0: nsresult GetItemAtIndex(int32_t aIndex, nsIDOMElement **aResult); michael@0: nsresult GetIndexOfItem(nsIDOMElement *aItem, int32_t *aResult); michael@0: michael@0: friend nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell, michael@0: nsStyleContext* aContext); michael@0: michael@0: // nsIFrame michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: // nsIScrollbarMediator michael@0: NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) MOZ_OVERRIDE; michael@0: NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE; michael@0: NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE; michael@0: michael@0: // nsIReflowCallback michael@0: virtual bool ReflowFinished() MOZ_OVERRIDE; michael@0: virtual void ReflowCallbackCanceled() MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; michael@0: virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE; michael@0: michael@0: virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; michael@0: virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; michael@0: michael@0: // size calculation michael@0: int32_t GetRowCount(); michael@0: int32_t GetRowHeightAppUnits() { return mRowHeight; } michael@0: int32_t GetFixedRowSize(); michael@0: void SetRowHeight(nscoord aRowHeight); michael@0: nscoord GetYPosition(); michael@0: nscoord GetAvailableHeight(); michael@0: nscoord ComputeIntrinsicWidth(nsBoxLayoutState& aBoxLayoutState); michael@0: michael@0: // scrolling michael@0: nsresult InternalPositionChangedCallback(); michael@0: nsresult InternalPositionChanged(bool aUp, int32_t aDelta); michael@0: // Process pending position changed events, then do the position change. michael@0: // This can wipe out the frametree. michael@0: nsresult DoInternalPositionChangedSync(bool aUp, int32_t aDelta); michael@0: // Actually do the internal position change. This can wipe out the frametree michael@0: nsresult DoInternalPositionChanged(bool aUp, int32_t aDelta); michael@0: nsListScrollSmoother* GetSmoother(); michael@0: void VerticalScroll(int32_t aDelta); michael@0: michael@0: // frames michael@0: nsIFrame* GetFirstFrame(); michael@0: nsIFrame* GetLastFrame(); michael@0: michael@0: // lazy row creation and destruction michael@0: void CreateRows(); michael@0: void DestroyRows(int32_t& aRowsToLose); michael@0: void ReverseDestroyRows(int32_t& aRowsToLose); michael@0: nsIFrame* GetFirstItemBox(int32_t aOffset, bool* aCreated); michael@0: nsIFrame* GetNextItemBox(nsIFrame* aBox, int32_t aOffset, bool* aCreated); michael@0: bool ContinueReflow(nscoord height); michael@0: NS_IMETHOD ListBoxAppendFrames(nsFrameList& aFrameList); michael@0: NS_IMETHOD ListBoxInsertFrames(nsIFrame* aPrevFrame, nsFrameList& aFrameList); michael@0: void OnContentInserted(nsPresContext* aPresContext, nsIContent* aContent); michael@0: void OnContentRemoved(nsPresContext* aPresContext, nsIContent* aContainer, michael@0: nsIFrame* aChildFrame, nsIContent* aOldNextSibling); michael@0: michael@0: void GetListItemContentAt(int32_t aIndex, nsIContent** aContent); michael@0: void GetListItemNextSibling(nsIContent* aListItem, nsIContent** aContent, int32_t& aSiblingIndex); michael@0: michael@0: void PostReflowCallback(); michael@0: michael@0: bool SetBoxObject(nsPIBoxObject* aBoxObject) michael@0: { michael@0: NS_ENSURE_TRUE(!mBoxObject, false); michael@0: mBoxObject = aBoxObject; michael@0: return true; michael@0: } michael@0: michael@0: virtual bool SupportsOrdinalsInChildren() MOZ_OVERRIDE; michael@0: michael@0: virtual bool ComputesOwnOverflowArea() MOZ_OVERRIDE { return true; } michael@0: michael@0: protected: michael@0: class nsPositionChangedEvent; michael@0: friend class nsPositionChangedEvent; michael@0: michael@0: class nsPositionChangedEvent : public nsRunnable michael@0: { michael@0: public: michael@0: nsPositionChangedEvent(nsListBoxBodyFrame* aFrame, michael@0: bool aUp, int32_t aDelta) : michael@0: mFrame(aFrame), mUp(aUp), mDelta(aDelta) michael@0: {} michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE michael@0: { michael@0: if (!mFrame) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: mFrame->mPendingPositionChangeEvents.RemoveElement(this); michael@0: michael@0: return mFrame->DoInternalPositionChanged(mUp, mDelta); michael@0: } michael@0: michael@0: void Revoke() { michael@0: mFrame = nullptr; michael@0: } michael@0: michael@0: nsListBoxBodyFrame* mFrame; michael@0: bool mUp; michael@0: int32_t mDelta; michael@0: }; michael@0: michael@0: void ComputeTotalRowCount(); michael@0: void RemoveChildFrame(nsBoxLayoutState &aState, nsIFrame *aChild); michael@0: michael@0: nsTArray< nsRefPtr > mPendingPositionChangeEvents; michael@0: nsCOMPtr mBoxObject; michael@0: michael@0: // frame markers michael@0: nsWeakFrame mTopFrame; michael@0: nsIFrame* mBottomFrame; michael@0: nsIFrame* mLinkupFrame; michael@0: michael@0: nsListScrollSmoother* mScrollSmoother; michael@0: michael@0: int32_t mRowsToPrepend; michael@0: michael@0: // row height michael@0: int32_t mRowCount; michael@0: nscoord mRowHeight; michael@0: nscoord mAvailableHeight; michael@0: nscoord mStringWidth; michael@0: michael@0: // scrolling michael@0: int32_t mCurrentIndex; // Row-based michael@0: int32_t mOldIndex; michael@0: int32_t mYPosition; michael@0: int32_t mTimePerRow; michael@0: michael@0: // row height michael@0: bool mRowHeightWasSet; michael@0: // scrolling michael@0: bool mScrolling; michael@0: bool mAdjustScroll; michael@0: michael@0: bool mReflowCallbackPosted; michael@0: }; michael@0: michael@0: #endif // nsListBoxBodyFrame_h