/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsTreeBodyFrame_h #define nsTreeBodyFrame_h #include "mozilla/Attributes.h" #include "nsLeafBoxFrame.h" #include "nsITreeView.h" #include "nsICSSPseudoComparator.h" #include "nsIScrollbarMediator.h" #include "nsITimer.h" #include "nsIReflowCallback.h" #include "nsTArray.h" #include "nsTreeStyleCache.h" #include "nsTreeColumns.h" #include "nsAutoPtr.h" #include "nsDataHashtable.h" #include "imgIRequest.h" #include "imgINotificationObserver.h" #include "nsScrollbarFrame.h" #include "nsThreadUtils.h" #include "mozilla/LookAndFeel.h" class nsOverflowChecker; class nsTreeImageListener; // An entry in the tree's image cache struct nsTreeImageCacheEntry { nsTreeImageCacheEntry() {} nsTreeImageCacheEntry(imgIRequest *aRequest, imgINotificationObserver *aListener) : request(aRequest), listener(aListener) {} nsCOMPtr request; nsCOMPtr listener; }; // The actual frame that paints the cells and rows. class nsTreeBodyFrame MOZ_FINAL : public nsLeafBoxFrame , public nsICSSPseudoComparator , public nsIScrollbarMediator , public nsIReflowCallback { public: nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); ~nsTreeBodyFrame(); NS_DECL_QUERYFRAME_TARGET(nsTreeBodyFrame) NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS // Callback handler methods for refresh driver based animations. // Calls to these functions are forwarded from nsTreeImageListener. These // mirror how nsImageFrame works. nsresult OnImageIsAnimated(imgIRequest* aRequest); // non-virtual signatures like nsITreeBodyFrame nsresult GetColumns(nsITreeColumns **aColumns); nsresult GetView(nsITreeView **aView); nsresult SetView(nsITreeView *aView); nsresult GetFocused(bool *aFocused); nsresult SetFocused(bool aFocused); nsresult GetTreeBody(nsIDOMElement **aElement); nsresult GetRowHeight(int32_t *aValue); nsresult GetRowWidth(int32_t *aValue); nsresult GetHorizontalPosition(int32_t *aValue); nsresult GetSelectionRegion(nsIScriptableRegion **aRegion); nsresult GetFirstVisibleRow(int32_t *aValue); nsresult GetLastVisibleRow(int32_t *aValue); nsresult GetPageLength(int32_t *aValue); nsresult EnsureRowIsVisible(int32_t aRow); nsresult EnsureCellIsVisible(int32_t aRow, nsITreeColumn *aCol); nsresult ScrollToRow(int32_t aRow); nsresult ScrollByLines(int32_t aNumLines); nsresult ScrollByPages(int32_t aNumPages); nsresult ScrollToCell(int32_t aRow, nsITreeColumn *aCol); nsresult ScrollToColumn(nsITreeColumn *aCol); nsresult ScrollToHorizontalPosition(int32_t aValue); nsresult Invalidate(); nsresult InvalidateColumn(nsITreeColumn *aCol); nsresult InvalidateRow(int32_t aRow); nsresult InvalidateCell(int32_t aRow, nsITreeColumn *aCol); nsresult InvalidateRange(int32_t aStart, int32_t aEnd); nsresult InvalidateColumnRange(int32_t aStart, int32_t aEnd, nsITreeColumn *aCol); nsresult GetRowAt(int32_t aX, int32_t aY, int32_t *aValue); nsresult GetCellAt(int32_t aX, int32_t aY, int32_t *aRow, nsITreeColumn **aCol, nsACString &aChildElt); nsresult GetCoordsForCellItem(int32_t aRow, nsITreeColumn *aCol, const nsACString &aElt, int32_t *aX, int32_t *aY, int32_t *aWidth, int32_t *aHeight); nsresult IsCellCropped(int32_t aRow, nsITreeColumn *aCol, bool *aResult); nsresult RowCountChanged(int32_t aIndex, int32_t aCount); nsresult BeginUpdateBatch(); nsresult EndUpdateBatch(); nsresult ClearStyleAndImageCaches(); virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState); virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect, bool aRemoveOverflowArea = false); // nsIReflowCallback virtual bool ReflowFinished() MOZ_OVERRIDE; virtual void ReflowCallbackCanceled() MOZ_OVERRIDE; // nsICSSPseudoComparator virtual bool PseudoMatches(nsCSSSelector* aSelector) MOZ_OVERRIDE; // nsIScrollbarMediator NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex); NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE; NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE { Invalidate(); return NS_OK; } // Overridden from nsIFrame to cache our pres context. NS_IMETHOD Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) MOZ_OVERRIDE; virtual void DestroyFrom(nsIFrame* aDestructRoot); NS_IMETHOD GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor); NS_IMETHOD HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) MOZ_OVERRIDE; virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext); friend nsIFrame* NS_NewTreeBodyFrame(nsIPresShell* aPresShell); friend class nsTreeColumn; struct ScrollParts { nsScrollbarFrame* mVScrollbar; nsCOMPtr mVScrollbarContent; nsScrollbarFrame* mHScrollbar; nsCOMPtr mHScrollbarContent; nsIFrame* mColumnsFrame; nsIScrollableFrame* mColumnsScrollFrame; }; void PaintTreeBody(nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt); nsITreeBoxObject* GetTreeBoxObject() const { return mTreeBoxObject; } bool GetVerticalOverflow() const { return mVerticalOverflow; } bool GetHorizontalOverflow() const {return mHorizontalOverflow; } protected: friend class nsOverflowChecker; // This method paints a specific column background of the tree. void PaintColumn(nsTreeColumn* aColumn, const nsRect& aColumnRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect); // This method paints a single row in the tree. void PaintRow(int32_t aRowIndex, const nsRect& aRowRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt); // This method paints a single separator in the tree. void PaintSeparator(int32_t aRowIndex, const nsRect& aSeparatorRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect); // This method paints a specific cell in a given row of the tree. void PaintCell(int32_t aRowIndex, nsTreeColumn* aColumn, const nsRect& aCellRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nscoord& aCurrX, nsPoint aPt); // This method paints the twisty inside a cell in the primary column of an tree. void PaintTwisty(int32_t aRowIndex, nsTreeColumn* aColumn, const nsRect& aTwistyRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nscoord& aRemainingWidth, nscoord& aCurrX); // This method paints the image inside the cell of an tree. void PaintImage(int32_t aRowIndex, nsTreeColumn* aColumn, const nsRect& aImageRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nscoord& aRemainingWidth, nscoord& aCurrX); // This method paints the text string inside a particular cell of the tree. void PaintText(int32_t aRowIndex, nsTreeColumn* aColumn, const nsRect& aTextRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nscoord& aCurrX, bool aTextRTL); // This method paints the checkbox inside a particular cell of the tree. void PaintCheckbox(int32_t aRowIndex, nsTreeColumn* aColumn, const nsRect& aCheckboxRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect); // This method paints the progress meter inside a particular cell of the tree. void PaintProgressMeter(int32_t aRowIndex, nsTreeColumn* aColumn, const nsRect& aProgressMeterRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect); // This method paints a drop feedback of the tree. void PaintDropFeedback(const nsRect& aDropFeedbackRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt); // This method is called with a specific style context and rect to // paint the background rect as if it were a full-blown frame. void PaintBackgroundLayer(nsStyleContext* aStyleContext, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aRect, const nsRect& aDirtyRect); int32_t GetLastVisibleRow() { return mTopRowIndex + mPageLength; } // An internal hit test. aX and aY are expected to be in twips in the // coordinate system of this frame. int32_t GetRowAt(nscoord aX, nscoord aY); // Check for bidi characters in the text, and if there are any, ensure // that the prescontext is in bidi mode. void CheckTextForBidi(nsAutoString& aText); void AdjustForCellText(nsAutoString& aText, int32_t aRowIndex, nsTreeColumn* aColumn, nsRenderingContext& aRenderingContext, nsRect& aTextRect); // A helper used when hit testing. nsIAtom* GetItemWithinCellAt(nscoord aX, const nsRect& aCellRect, int32_t aRowIndex, nsTreeColumn* aColumn); // An internal hit test. aX and aY are expected to be in twips in the // coordinate system of this frame. void GetCellAt(nscoord aX, nscoord aY, int32_t* aRow, nsTreeColumn** aCol, nsIAtom** aChildElt); // Retrieve the area for the twisty for a cell. nsITheme* GetTwistyRect(int32_t aRowIndex, nsTreeColumn* aColumn, nsRect& aImageRect, nsRect& aTwistyRect, nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, nsStyleContext* aTwistyContext); // Fetch an image from the image cache. nsresult GetImage(int32_t aRowIndex, nsTreeColumn* aCol, bool aUseContext, nsStyleContext* aStyleContext, bool& aAllowImageRegions, imgIContainer** aResult); // Returns the size of a given image. This size *includes* border and // padding. It does not include margins. nsRect GetImageSize(int32_t aRowIndex, nsTreeColumn* aCol, bool aUseContext, nsStyleContext* aStyleContext); // Returns the destination size of the image, not including borders and padding. nsSize GetImageDestSize(nsStyleContext* aStyleContext, bool useImageRegion, imgIContainer* image); // Returns the source rectangle of the image to be displayed. nsRect GetImageSourceRect(nsStyleContext* aStyleContext, bool useImageRegion, imgIContainer* image); // Returns the height of rows in the tree. int32_t GetRowHeight(); // Returns our indentation width. int32_t GetIndentation(); // Calculates our width/height once border and padding have been removed. void CalcInnerBox(); // Calculate the total width of our scrollable portion nscoord CalcHorzWidth(const ScrollParts& aParts); // Looks up a style context in the style cache. On a cache miss we resolve // the pseudo-styles passed in and place them into the cache. nsStyleContext* GetPseudoStyleContext(nsIAtom* aPseudoElement); // Retrieves the scrollbars and scrollview relevant to this treebody. We // traverse the frame tree under our base element, in frame order, looking // for the first relevant vertical scrollbar, horizontal scrollbar, and // scrollable frame (with associated content and scrollable view). These // are all volatile and should not be retained. ScrollParts GetScrollParts(); // Update the curpos of the scrollbar. void UpdateScrollbars(const ScrollParts& aParts); // Update the maxpos of the scrollbar. void InvalidateScrollbars(const ScrollParts& aParts, nsWeakFrame& aWeakColumnsFrame); // Check overflow and generate events. void CheckOverflow(const ScrollParts& aParts); // Calls UpdateScrollbars, Invalidate aNeedsFullInvalidation if true, // InvalidateScrollbars and finally CheckOverflow. // returns true if the frame is still alive after the method call. bool FullScrollbarsUpdate(bool aNeedsFullInvalidation); // Use to auto-fill some of the common properties without the view having to do it. // Examples include container, open, selected, and focus. void PrefillPropertyArray(int32_t aRowIndex, nsTreeColumn* aCol); // Our internal scroll method, used by all the public scroll methods. nsresult ScrollInternal(const ScrollParts& aParts, int32_t aRow); nsresult ScrollToRowInternal(const ScrollParts& aParts, int32_t aRow); nsresult ScrollToColumnInternal(const ScrollParts& aParts, nsITreeColumn* aCol); nsresult ScrollHorzInternal(const ScrollParts& aParts, int32_t aPosition); nsresult EnsureRowIsVisibleInternal(const ScrollParts& aParts, int32_t aRow); // Convert client pixels into appunits in our coordinate space. nsPoint AdjustClientCoordsToBoxCoordSpace(int32_t aX, int32_t aY); // Cache the box object void EnsureBoxObject(); void EnsureView(); // Get the base element, or