michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 sts=2 et sw=2 tw=80: */ 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: /** michael@0: * compute sticky positioning, both during reflow and when the scrolling michael@0: * container scrolls michael@0: */ michael@0: michael@0: #ifndef StickyScrollContainer_h michael@0: #define StickyScrollContainer_h michael@0: michael@0: #include "nsPoint.h" michael@0: #include "nsTArray.h" michael@0: #include "nsIScrollPositionListener.h" michael@0: michael@0: class nsRect; michael@0: class nsIFrame; michael@0: class nsIScrollableFrame; michael@0: michael@0: namespace mozilla { michael@0: michael@0: class StickyScrollContainer MOZ_FINAL : public nsIScrollPositionListener michael@0: { michael@0: public: michael@0: /** michael@0: * Find (and create if necessary) the StickyScrollContainer associated with michael@0: * the scroll container of the given frame, if a scroll container exists. michael@0: */ michael@0: static StickyScrollContainer* GetStickyScrollContainerForFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Find the StickyScrollContainer associated with the given scroll frame, michael@0: * if it exists. michael@0: */ michael@0: static StickyScrollContainer* GetStickyScrollContainerForScrollFrame(nsIFrame* aScrollFrame); michael@0: michael@0: /** michael@0: * aFrame may have moved into or out of a scroll frame's frame subtree. michael@0: */ michael@0: static void NotifyReparentedFrameAcrossScrollFrameBoundary(nsIFrame* aFrame, michael@0: nsIFrame* aOldParent); michael@0: michael@0: void AddFrame(nsIFrame* aFrame) { michael@0: mFrames.AppendElement(aFrame); michael@0: } michael@0: void RemoveFrame(nsIFrame* aFrame) { michael@0: mFrames.RemoveElement(aFrame); michael@0: } michael@0: michael@0: nsIScrollableFrame* ScrollFrame() const { michael@0: return mScrollFrame; michael@0: } michael@0: michael@0: // Compute the offsets for a sticky position element michael@0: static void ComputeStickyOffsets(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Compute the position of a sticky positioned frame, based on information michael@0: * stored in its properties along with our scroll frame and scroll position. michael@0: */ michael@0: nsPoint ComputePosition(nsIFrame* aFrame) const; michael@0: michael@0: /** michael@0: * Compute where a frame should not scroll with the page, represented by the michael@0: * difference of two rectangles. michael@0: */ michael@0: void GetScrollRanges(nsIFrame* aFrame, nsRect* aOuter, nsRect* aInner) const; michael@0: michael@0: /** michael@0: * Compute and set the position of a frame and its following continuations. michael@0: */ michael@0: void PositionContinuations(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Compute and set the position of all sticky frames, given the current michael@0: * scroll position of the scroll frame. If not in reflow, aSubtreeRoot should michael@0: * be null; otherwise, overflow-area updates will be limited to not affect michael@0: * aSubtreeRoot or its ancestors. michael@0: */ michael@0: void UpdatePositions(nsPoint aScrollPosition, nsIFrame* aSubtreeRoot); michael@0: michael@0: // nsIScrollPositionListener michael@0: virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) MOZ_OVERRIDE; michael@0: virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: StickyScrollContainer(nsIScrollableFrame* aScrollFrame); michael@0: ~StickyScrollContainer(); michael@0: michael@0: /** michael@0: * Compute two rectangles that determine sticky positioning: |aStick|, based michael@0: * on the scroll container, and |aContain|, based on the containing block. michael@0: * Sticky positioning keeps the frame position (its upper-left corner) always michael@0: * within |aContain| and secondarily within |aStick|. michael@0: */ michael@0: void ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick, michael@0: nsRect* aContain) const; michael@0: michael@0: friend void DestroyStickyScrollContainer(void* aPropertyValue); michael@0: michael@0: nsIScrollableFrame* const mScrollFrame; michael@0: nsTArray mFrames; michael@0: nsPoint mScrollPosition; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif /* StickyScrollContainer_h */