Back to index

lightning-sunbird  0.9+nobinonly
nsGfxScrollFrame.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #ifndef nsGfxScrollFrame_h___
00038 #define nsGfxScrollFrame_h___
00039 
00040 #include "nsHTMLContainerFrame.h"
00041 #include "nsIAnonymousContentCreator.h"
00042 #include "nsBoxFrame.h"
00043 #include "nsIScrollableFrame.h"
00044 #include "nsIScrollPositionListener.h"
00045 #include "nsIStatefulFrame.h"
00046 #include "nsGUIEvent.h"
00047 #include "nsIEventQueue.h"
00048 
00049 class nsISupportsArray;
00050 class nsIScrollableView;
00051 class nsPresContext;
00052 class nsIPresShell;
00053 class nsIContent;
00054 class nsIAtom;
00055 class nsIDocument;
00056 class nsIScrollFrameInternal;
00057 class nsPresState;
00058 struct ScrollReflowState;
00059 
00060 class nsGfxScrollFrameInner : public nsIScrollPositionListener {
00061 public:
00062   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
00063   NS_IMETHOD_(nsrefcnt) AddRef(void);
00064   NS_IMETHOD_(nsrefcnt) Release(void);
00065 
00066   nsGfxScrollFrameInner(nsContainerFrame* aOuter, PRBool aIsRoot);
00067   ~nsGfxScrollFrameInner();
00068 
00069   typedef nsIScrollableFrame::ScrollbarStyles ScrollbarStyles;
00070   ScrollbarStyles GetScrollbarStylesFromFrame() const;
00071 
00072   // If a child frame was added or removed on the scrollframe,
00073   // reload our child frame list.
00074   // We need this if a scrollbar frame is recreated.
00075   void ReloadChildFrames();
00076   PRBool NeedsClipWidget() const;
00077   void CreateScrollableView();
00078 
00079   void CreateAnonymousContent(nsISupportsArray& aAnonymousChildren);
00080   void PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType);
00081   void PostOverflowEvents();
00082 
00083   nsresult GetChildContentAndOffsetsFromPoint(nsPresContext* aCX,
00084                                               const nsPoint&  aPoint,
00085                                               nsIContent **   aNewContent,
00086                                               PRInt32&        aContentOffset,
00087                                               PRInt32&        aContentOffsetEnd,
00088                                               PRBool&         aBeginFrameContent);
00089 
00090   // nsIScrollPositionListener
00091 
00092   NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
00093   NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
00094 
00095   // This gets called when the 'curpos' attribute on one of the scrollbars changes
00096   void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
00097   void PostScrollEvent();
00098   void FireScrollEvent();
00099 
00100   void SetScrollbarEnabled(nsIBox* aBox, nscoord aMaxPos, PRBool aReflow=PR_TRUE);
00101   PRBool SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE);
00102   PRInt32 GetIntegerAttribute(nsIBox* aFrame, nsIAtom* atom, PRInt32 defaultValue);
00103 
00107   void AdjustHorizontalScrollbar();
00108  
00109   // Like ScrollPositionDidChange, but initiated by this frame rather than from the
00110   // scrolling view
00111   void InternalScrollPositionDidChange(nscoord aX, nscoord aY);
00112 
00113   nsIScrollableView* GetScrollableView() const { return mScrollableView; }
00114 
00115   nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const;
00116 
00117   void ScrollToRestoredPosition();
00118 
00119   nsPresState* SaveState();
00120   void RestoreState(nsPresState* aState);
00121 
00122   nsIFrame* GetScrolledFrame() const { return mScrolledFrame; }
00123 
00124   void ScrollbarChanged(nsPresContext* aPresContext, nscoord aX, nscoord aY, PRUint32 aFlags);
00125 
00126   static void SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisible);
00127 
00128   nsSize GetScrolledSize() const;
00129   nsMargin GetActualScrollbarSizes() const;
00130   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
00131   PRBool IsScrollbarOnRight();
00132   void LayoutScrollbars(nsBoxLayoutState& aState,
00133                         const nsRect& aContentArea,
00134                         const nsRect& aOldScrollArea,
00135                         const nsRect& aScrollArea);
00136 
00137   nsCOMPtr<nsIEventQueue> mScrollEventQueue;
00138   nsIScrollableView* mScrollableView;
00139   nsIBox* mHScrollbarBox;
00140   nsIBox* mVScrollbarBox;
00141   nsIFrame* mScrolledFrame;
00142   nsIBox* mScrollCornerBox;
00143   nsContainerFrame* mOuter;
00144   nscoord mOnePixel;
00145 
00146   nsRect mRestoreRect;
00147   nsPoint mLastPos;
00148 
00149   // The last dir value we saw in AddHorizontalScrollbar.  Use PRInt16
00150   // so we can fit all the possible values of a PRUint8 and have a -1
00151   // value that indicates "not set")
00152   PRInt16     mLastDir;
00153   
00154   PRPackedBool mNeverHasVerticalScrollbar:1;
00155   PRPackedBool mNeverHasHorizontalScrollbar:1;
00156   PRPackedBool mHasVerticalScrollbar:1;
00157   PRPackedBool mHasHorizontalScrollbar:1;
00158   PRPackedBool mViewInitiatedScroll:1;
00159   PRPackedBool mFrameInitiatedScroll:1;
00160   PRPackedBool mDidHistoryRestore:1;
00161   // Is this the scrollframe for the document's viewport?
00162   PRPackedBool mIsRoot:1;
00163   PRPackedBool mSupppressScrollbarUpdate:1;
00164   // State used only by PostScrollEvents so we know
00165   // which overflow states have changed.
00166   PRPackedBool mHorizontalOverflow:1;
00167   PRPackedBool mVerticalOverflow:1;
00168 };
00169 
00179 class nsHTMLScrollFrame : public nsHTMLContainerFrame,
00180                           public nsIScrollableFrame,
00181                           public nsIAnonymousContentCreator,
00182                           public nsIStatefulFrame {
00183 public:
00184   friend nsresult NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, 
00185                                         PRBool aIsRoot);
00186 
00187   NS_DECL_ISUPPORTS
00188 
00189   // Called to set the child frames. We typically have three: the scroll area,
00190   // the vertical scrollbar, and the horizontal scrollbar.
00191   NS_IMETHOD SetInitialChildList(nsPresContext* aPresContext,
00192                                  nsIAtom*        aListName,
00193                                  nsIFrame*       aChildList);
00194 
00195   PRBool TryLayout(ScrollReflowState* aState,
00196                    const nsHTMLReflowMetrics& aKidMetrics,
00197                    PRBool aAssumeVScroll, PRBool aAssumeHScroll,
00198                    PRBool aForce);
00199   nsresult ReflowScrolledFrame(const ScrollReflowState& aState,
00200                                PRBool aAssumeHScroll,
00201                                PRBool aAssumeVScroll,
00202                                nsHTMLReflowMetrics* aMetrics,
00203                                PRBool aFirstPass);
00204   nsresult ReflowContents(ScrollReflowState* aState,
00205                           const nsHTMLReflowMetrics& aDesiredSize);
00206   PRBool IsRTLTextControl();
00207   void PlaceScrollArea(const ScrollReflowState& aState);
00208 
00209    NS_IMETHOD Reflow(nsPresContext*          aPresContext,
00210                   nsHTMLReflowMetrics&     aDesiredSize,
00211                   const nsHTMLReflowState& aReflowState,
00212                   nsReflowStatus&          aStatus);
00213 
00214   // Because there can be only one child frame, these two function return
00215   // NS_ERROR_FAILURE
00216   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
00217                           nsIFrame*       aFrameList);
00218   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
00219                           nsIFrame*       aPrevFrame,
00220                           nsIFrame*       aFrameList);
00221 
00222   NS_IMETHOD ReplaceFrame(nsIAtom*        aListName,
00223                           nsIFrame*       aOldFrame,
00224                           nsIFrame*       aNewFrame);
00225 
00226   NS_IMETHOD Destroy(nsPresContext* aPresContext);
00227 
00228   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
00229                          nsIFrame*       aOldFrame);
00230 
00231 
00232   NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aCX,
00233                                            const nsPoint&  aPoint,
00234                                            nsIContent **   aNewContent,
00235                                            PRInt32&        aContentOffset,
00236                                            PRInt32&        aContentOffsetEnd,
00237                                            PRBool&         aBeginFrameContent) {
00238     return mInner.GetChildContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset,
00239                                                      aContentOffsetEnd, aBeginFrameContent);
00240   }
00241 
00242   virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
00243     return mInner.GetParentViewForChildFrame(aFrame);
00244   }
00245 
00246   virtual nsIFrame* GetContentInsertionFrame() {
00247     return mInner.GetScrolledFrame()->GetContentInsertionFrame();
00248   }
00249 
00250   virtual nsIView* GetMouseCapturer() const {
00251     return mInner.GetScrolledFrame()->GetView();
00252   }
00253 
00254   virtual PRBool NeedsView() { return PR_TRUE; }
00255   virtual PRBool DoesClipChildren() { return PR_TRUE; }
00256 
00257   // nsIAnonymousContentCreator
00258   NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext,
00259                                     nsISupportsArray& aAnonymousItems);
00260   NS_IMETHOD CreateFrameFor(nsPresContext*   aPresContext,
00261                             nsIContent *      aContent,
00262                             nsIFrame**        aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; }
00263 
00264   // nsIScrollableFrame
00265   virtual nsIFrame* GetScrolledFrame() const;
00266   virtual nsIScrollableView* GetScrollableView();
00267 
00268   virtual nsPoint GetScrollPosition() const;
00269   virtual void ScrollTo(nsPoint aScrollPosition, PRUint32 aFlags);
00270 
00271   virtual void SetScrollbarVisibility(PRBool aVerticalVisible, PRBool aHorizontalVisible);
00272 
00273   virtual nsIBox* GetScrollbarBox(PRBool aVertical);
00274 
00275   virtual void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
00276 
00277   // nsIStatefulFrame
00278   NS_IMETHOD SaveState(nsPresContext* aPresContext, nsPresState** aState) {
00279     NS_ENSURE_ARG_POINTER(aState);
00280     *aState = mInner.SaveState();
00281     return NS_OK;
00282   }
00283   NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsPresState* aState) {
00284     NS_ENSURE_ARG_POINTER(aState);
00285     mInner.RestoreState(aState);
00286     return NS_OK;
00287   }
00288 
00289   virtual void ScrollToRestoredPosition() {
00290     mInner.ScrollToRestoredPosition();
00291   }
00292 
00293   virtual nsMargin GetActualScrollbarSizes() const {
00294     return mInner.GetActualScrollbarSizes();
00295   }
00296   virtual nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
00297   virtual nsGfxScrollFrameInner::ScrollbarStyles GetScrollbarStyles() const;
00298 
00304   virtual nsIAtom* GetType() const;
00305   
00306 #ifdef NS_DEBUG
00307   NS_IMETHOD GetFrameName(nsAString& aResult) const;
00308 #endif
00309 
00310   virtual nsresult GetContentOf(nsIContent** aContent);
00311 
00312   PRBool DidHistoryRestore() { return mInner.mDidHistoryRestore; }
00313 
00314 #ifdef ACCESSIBILITY
00315   NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
00316 #endif
00317 
00318 protected:
00319   nsHTMLScrollFrame(nsIPresShell* aShell, PRBool aIsRoot);
00320   virtual PRIntn GetSkipSides() const;
00321   
00322   void SetSuppressScrollbarUpdate(PRBool aSuppress) {
00323     mInner.mSupppressScrollbarUpdate = aSuppress;
00324   }
00325 
00326 private:
00327   friend class nsGfxScrollFrameInner;
00328   nsGfxScrollFrameInner mInner;
00329 };
00330 
00340 class nsXULScrollFrame : public nsBoxFrame,
00341                          public nsIScrollableFrame,
00342                          public nsIAnonymousContentCreator,
00343                          public nsIStatefulFrame {
00344 public:
00345   friend nsresult NS_NewXULScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, 
00346                                        PRBool aIsRoot);
00347 
00348   // Called to set the child frames. We typically have three: the scroll area,
00349   // the vertical scrollbar, and the horizontal scrollbar.
00350   NS_IMETHOD SetInitialChildList(nsPresContext* aPresContext,
00351                                  nsIAtom*        aListName,
00352                                  nsIFrame*       aChildList);
00353 
00354   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
00355                   nsHTMLReflowMetrics&     aDesiredSize,
00356                   const nsHTMLReflowState& aReflowState,
00357                   nsReflowStatus&          aStatus);
00358 
00359   // Because there can be only one child frame, these two function return
00360   // NS_ERROR_FAILURE
00361   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
00362                           nsIFrame*       aFrameList);
00363   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
00364                           nsIFrame*       aPrevFrame,
00365                           nsIFrame*       aFrameList);
00366 
00367   NS_IMETHOD ReplaceFrame(nsIAtom*        aListName,
00368                           nsIFrame*       aOldFrame,
00369                           nsIFrame*       aNewFrame);
00370 
00371   NS_IMETHOD Destroy(nsPresContext* aPresContext);
00372 
00373   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
00374                          nsIFrame*       aOldFrame);
00375 
00376 
00377   NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aCX,
00378                                            const nsPoint&  aPoint,
00379                                            nsIContent **   aNewContent,
00380                                            PRInt32&        aContentOffset,
00381                                            PRInt32&        aContentOffsetEnd,
00382                                            PRBool&         aBeginFrameContent) {
00383     return mInner.GetChildContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset,
00384                                                      aContentOffsetEnd, aBeginFrameContent);
00385   }
00386 
00387   virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
00388     return mInner.GetParentViewForChildFrame(aFrame);
00389   }
00390 
00391   virtual nsIFrame* GetContentInsertionFrame() {
00392     return mInner.GetScrolledFrame()->GetContentInsertionFrame();
00393   }
00394 
00395   virtual nsIView* GetMouseCapturer() const {
00396     return mInner.GetScrolledFrame()->GetView();
00397   }
00398 
00399   virtual PRBool NeedsView() { return PR_TRUE; }
00400   virtual PRBool DoesClipChildren() { return PR_TRUE; }
00401 
00402   // nsIAnonymousContentCreator
00403   NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext,
00404                                     nsISupportsArray& aAnonymousItems);
00405   NS_IMETHOD CreateFrameFor(nsPresContext*   aPresContext,
00406                             nsIContent *      aContent,
00407                             nsIFrame**        aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; }
00408 
00409   // nsIBox methods
00410   NS_DECL_ISUPPORTS
00411 
00412   NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
00413   NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
00414   NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
00415   NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent);
00416 
00417   NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
00418   NS_IMETHOD GetPadding(nsMargin& aPadding);
00419 
00420   nsresult Layout(nsBoxLayoutState& aState);
00421   void LayoutScrollArea(nsBoxLayoutState& aState, const nsRect& aRect);
00422 
00423   static PRBool AddRemoveScrollbar(PRBool& aHasScrollbar, 
00424                                    nscoord& aXY, 
00425                                    nscoord& aSize, 
00426                                    nscoord aSbSize, 
00427                                    PRBool aOnRightOrBottom, 
00428                                    PRBool aAdd);
00429   
00430   PRBool AddRemoveScrollbar(nsBoxLayoutState& aState, 
00431                             nsRect& aScrollAreaSize, 
00432                             PRBool aOnTop, 
00433                             PRBool aHorizontal, 
00434                             PRBool aAdd);
00435   
00436   PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
00437   PRBool AddVerticalScrollbar   (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
00438   void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
00439   void RemoveVerticalScrollbar  (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
00440 
00441   static void AdjustReflowStateForPrintPreview(nsBoxLayoutState& aState, PRBool& aSetBack);
00442   static void AdjustReflowStateBack(nsBoxLayoutState& aState, PRBool aSetBack);
00443 
00444   // nsIScrollableFrame
00445   virtual nsIFrame* GetScrolledFrame() const;
00446   virtual nsIScrollableView* GetScrollableView();
00447 
00448   virtual nsPoint GetScrollPosition() const;
00449   virtual void ScrollTo(nsPoint aScrollPosition, PRUint32 aFlags);
00450 
00451   virtual void SetScrollbarVisibility(PRBool aVerticalVisible, PRBool aHorizontalVisible);
00452 
00453   virtual nsIBox* GetScrollbarBox(PRBool aVertical);
00454 
00455   virtual void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
00456 
00457   // nsIStatefulFrame
00458   NS_IMETHOD SaveState(nsPresContext* aPresContext, nsPresState** aState) {
00459     NS_ENSURE_ARG_POINTER(aState);
00460     *aState = mInner.SaveState();
00461     return NS_OK;
00462   }
00463   NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsPresState* aState) {
00464     NS_ENSURE_ARG_POINTER(aState);
00465     mInner.RestoreState(aState);
00466     return NS_OK;
00467   }
00468 
00469   virtual void ScrollToRestoredPosition() {
00470     mInner.ScrollToRestoredPosition();
00471   }
00472 
00473   virtual nsMargin GetActualScrollbarSizes() const {
00474     return mInner.GetActualScrollbarSizes();
00475   }
00476   virtual nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
00477   virtual nsGfxScrollFrameInner::ScrollbarStyles GetScrollbarStyles() const;
00478 
00484   virtual nsIAtom* GetType() const;
00485   
00486 #ifdef NS_DEBUG
00487   NS_IMETHOD GetFrameName(nsAString& aResult) const;
00488 #endif
00489 
00490   virtual nsresult GetContentOf(nsIContent** aContent);
00491 
00492 protected:
00493   nsXULScrollFrame(nsIPresShell* aShell, PRBool aIsRoot);
00494   virtual PRIntn GetSkipSides() const;
00495 
00496 private:
00497   friend class nsGfxScrollFrameInner;
00498   nsGfxScrollFrameInner mInner;
00499   nscoord mMaxElementWidth;
00500 };
00501 
00502 #endif /* nsGfxScrollFrame_h___ */