Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef nsListBoxBodyFrame_h |
michael@0 | 7 | #define nsListBoxBodyFrame_h |
michael@0 | 8 | |
michael@0 | 9 | #include "mozilla/Attributes.h" |
michael@0 | 10 | #include "nsCOMPtr.h" |
michael@0 | 11 | #include "nsBoxFrame.h" |
michael@0 | 12 | #include "nsIListBoxObject.h" |
michael@0 | 13 | #include "nsIScrollbarMediator.h" |
michael@0 | 14 | #include "nsIReflowCallback.h" |
michael@0 | 15 | #include "nsBoxLayoutState.h" |
michael@0 | 16 | #include "nsThreadUtils.h" |
michael@0 | 17 | #include "nsPIBoxObject.h" |
michael@0 | 18 | |
michael@0 | 19 | class nsPresContext; |
michael@0 | 20 | class nsListScrollSmoother; |
michael@0 | 21 | nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell, |
michael@0 | 22 | nsStyleContext* aContext); |
michael@0 | 23 | |
michael@0 | 24 | class nsListBoxBodyFrame : public nsBoxFrame, |
michael@0 | 25 | public nsIScrollbarMediator, |
michael@0 | 26 | public nsIReflowCallback |
michael@0 | 27 | { |
michael@0 | 28 | nsListBoxBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, |
michael@0 | 29 | nsBoxLayout* aLayoutManager); |
michael@0 | 30 | virtual ~nsListBoxBodyFrame(); |
michael@0 | 31 | |
michael@0 | 32 | public: |
michael@0 | 33 | NS_DECL_QUERYFRAME_TARGET(nsListBoxBodyFrame) |
michael@0 | 34 | NS_DECL_QUERYFRAME |
michael@0 | 35 | NS_DECL_FRAMEARENA_HELPERS |
michael@0 | 36 | |
michael@0 | 37 | // non-virtual nsIListBoxObject |
michael@0 | 38 | nsresult GetRowCount(int32_t *aResult); |
michael@0 | 39 | nsresult GetNumberOfVisibleRows(int32_t *aResult); |
michael@0 | 40 | nsresult GetIndexOfFirstVisibleRow(int32_t *aResult); |
michael@0 | 41 | nsresult EnsureIndexIsVisible(int32_t aRowIndex); |
michael@0 | 42 | nsresult ScrollToIndex(int32_t aRowIndex); |
michael@0 | 43 | nsresult ScrollByLines(int32_t aNumLines); |
michael@0 | 44 | nsresult GetItemAtIndex(int32_t aIndex, nsIDOMElement **aResult); |
michael@0 | 45 | nsresult GetIndexOfItem(nsIDOMElement *aItem, int32_t *aResult); |
michael@0 | 46 | |
michael@0 | 47 | friend nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell, |
michael@0 | 48 | nsStyleContext* aContext); |
michael@0 | 49 | |
michael@0 | 50 | // nsIFrame |
michael@0 | 51 | virtual void Init(nsIContent* aContent, |
michael@0 | 52 | nsIFrame* aParent, |
michael@0 | 53 | nsIFrame* aPrevInFlow) MOZ_OVERRIDE; |
michael@0 | 54 | virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; |
michael@0 | 55 | |
michael@0 | 56 | virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE; |
michael@0 | 57 | |
michael@0 | 58 | // nsIScrollbarMediator |
michael@0 | 59 | NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) MOZ_OVERRIDE; |
michael@0 | 60 | NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE; |
michael@0 | 61 | NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE; |
michael@0 | 62 | |
michael@0 | 63 | // nsIReflowCallback |
michael@0 | 64 | virtual bool ReflowFinished() MOZ_OVERRIDE; |
michael@0 | 65 | virtual void ReflowCallbackCanceled() MOZ_OVERRIDE; |
michael@0 | 66 | |
michael@0 | 67 | NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
michael@0 | 68 | virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE; |
michael@0 | 69 | |
michael@0 | 70 | virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
michael@0 | 71 | virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
michael@0 | 72 | |
michael@0 | 73 | // size calculation |
michael@0 | 74 | int32_t GetRowCount(); |
michael@0 | 75 | int32_t GetRowHeightAppUnits() { return mRowHeight; } |
michael@0 | 76 | int32_t GetFixedRowSize(); |
michael@0 | 77 | void SetRowHeight(nscoord aRowHeight); |
michael@0 | 78 | nscoord GetYPosition(); |
michael@0 | 79 | nscoord GetAvailableHeight(); |
michael@0 | 80 | nscoord ComputeIntrinsicWidth(nsBoxLayoutState& aBoxLayoutState); |
michael@0 | 81 | |
michael@0 | 82 | // scrolling |
michael@0 | 83 | nsresult InternalPositionChangedCallback(); |
michael@0 | 84 | nsresult InternalPositionChanged(bool aUp, int32_t aDelta); |
michael@0 | 85 | // Process pending position changed events, then do the position change. |
michael@0 | 86 | // This can wipe out the frametree. |
michael@0 | 87 | nsresult DoInternalPositionChangedSync(bool aUp, int32_t aDelta); |
michael@0 | 88 | // Actually do the internal position change. This can wipe out the frametree |
michael@0 | 89 | nsresult DoInternalPositionChanged(bool aUp, int32_t aDelta); |
michael@0 | 90 | nsListScrollSmoother* GetSmoother(); |
michael@0 | 91 | void VerticalScroll(int32_t aDelta); |
michael@0 | 92 | |
michael@0 | 93 | // frames |
michael@0 | 94 | nsIFrame* GetFirstFrame(); |
michael@0 | 95 | nsIFrame* GetLastFrame(); |
michael@0 | 96 | |
michael@0 | 97 | // lazy row creation and destruction |
michael@0 | 98 | void CreateRows(); |
michael@0 | 99 | void DestroyRows(int32_t& aRowsToLose); |
michael@0 | 100 | void ReverseDestroyRows(int32_t& aRowsToLose); |
michael@0 | 101 | nsIFrame* GetFirstItemBox(int32_t aOffset, bool* aCreated); |
michael@0 | 102 | nsIFrame* GetNextItemBox(nsIFrame* aBox, int32_t aOffset, bool* aCreated); |
michael@0 | 103 | bool ContinueReflow(nscoord height); |
michael@0 | 104 | NS_IMETHOD ListBoxAppendFrames(nsFrameList& aFrameList); |
michael@0 | 105 | NS_IMETHOD ListBoxInsertFrames(nsIFrame* aPrevFrame, nsFrameList& aFrameList); |
michael@0 | 106 | void OnContentInserted(nsPresContext* aPresContext, nsIContent* aContent); |
michael@0 | 107 | void OnContentRemoved(nsPresContext* aPresContext, nsIContent* aContainer, |
michael@0 | 108 | nsIFrame* aChildFrame, nsIContent* aOldNextSibling); |
michael@0 | 109 | |
michael@0 | 110 | void GetListItemContentAt(int32_t aIndex, nsIContent** aContent); |
michael@0 | 111 | void GetListItemNextSibling(nsIContent* aListItem, nsIContent** aContent, int32_t& aSiblingIndex); |
michael@0 | 112 | |
michael@0 | 113 | void PostReflowCallback(); |
michael@0 | 114 | |
michael@0 | 115 | bool SetBoxObject(nsPIBoxObject* aBoxObject) |
michael@0 | 116 | { |
michael@0 | 117 | NS_ENSURE_TRUE(!mBoxObject, false); |
michael@0 | 118 | mBoxObject = aBoxObject; |
michael@0 | 119 | return true; |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | virtual bool SupportsOrdinalsInChildren() MOZ_OVERRIDE; |
michael@0 | 123 | |
michael@0 | 124 | virtual bool ComputesOwnOverflowArea() MOZ_OVERRIDE { return true; } |
michael@0 | 125 | |
michael@0 | 126 | protected: |
michael@0 | 127 | class nsPositionChangedEvent; |
michael@0 | 128 | friend class nsPositionChangedEvent; |
michael@0 | 129 | |
michael@0 | 130 | class nsPositionChangedEvent : public nsRunnable |
michael@0 | 131 | { |
michael@0 | 132 | public: |
michael@0 | 133 | nsPositionChangedEvent(nsListBoxBodyFrame* aFrame, |
michael@0 | 134 | bool aUp, int32_t aDelta) : |
michael@0 | 135 | mFrame(aFrame), mUp(aUp), mDelta(aDelta) |
michael@0 | 136 | {} |
michael@0 | 137 | |
michael@0 | 138 | NS_IMETHOD Run() MOZ_OVERRIDE |
michael@0 | 139 | { |
michael@0 | 140 | if (!mFrame) { |
michael@0 | 141 | return NS_OK; |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | mFrame->mPendingPositionChangeEvents.RemoveElement(this); |
michael@0 | 145 | |
michael@0 | 146 | return mFrame->DoInternalPositionChanged(mUp, mDelta); |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | void Revoke() { |
michael@0 | 150 | mFrame = nullptr; |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | nsListBoxBodyFrame* mFrame; |
michael@0 | 154 | bool mUp; |
michael@0 | 155 | int32_t mDelta; |
michael@0 | 156 | }; |
michael@0 | 157 | |
michael@0 | 158 | void ComputeTotalRowCount(); |
michael@0 | 159 | void RemoveChildFrame(nsBoxLayoutState &aState, nsIFrame *aChild); |
michael@0 | 160 | |
michael@0 | 161 | nsTArray< nsRefPtr<nsPositionChangedEvent> > mPendingPositionChangeEvents; |
michael@0 | 162 | nsCOMPtr<nsPIBoxObject> mBoxObject; |
michael@0 | 163 | |
michael@0 | 164 | // frame markers |
michael@0 | 165 | nsWeakFrame mTopFrame; |
michael@0 | 166 | nsIFrame* mBottomFrame; |
michael@0 | 167 | nsIFrame* mLinkupFrame; |
michael@0 | 168 | |
michael@0 | 169 | nsListScrollSmoother* mScrollSmoother; |
michael@0 | 170 | |
michael@0 | 171 | int32_t mRowsToPrepend; |
michael@0 | 172 | |
michael@0 | 173 | // row height |
michael@0 | 174 | int32_t mRowCount; |
michael@0 | 175 | nscoord mRowHeight; |
michael@0 | 176 | nscoord mAvailableHeight; |
michael@0 | 177 | nscoord mStringWidth; |
michael@0 | 178 | |
michael@0 | 179 | // scrolling |
michael@0 | 180 | int32_t mCurrentIndex; // Row-based |
michael@0 | 181 | int32_t mOldIndex; |
michael@0 | 182 | int32_t mYPosition; |
michael@0 | 183 | int32_t mTimePerRow; |
michael@0 | 184 | |
michael@0 | 185 | // row height |
michael@0 | 186 | bool mRowHeightWasSet; |
michael@0 | 187 | // scrolling |
michael@0 | 188 | bool mScrolling; |
michael@0 | 189 | bool mAdjustScroll; |
michael@0 | 190 | |
michael@0 | 191 | bool mReflowCallbackPosted; |
michael@0 | 192 | }; |
michael@0 | 193 | |
michael@0 | 194 | #endif // nsListBoxBodyFrame_h |