layout/xul/tree/nsTreeColFrame.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsCOMPtr.h"
     7 #include "nsTreeColFrame.h"
     8 #include "nsGkAtoms.h"
     9 #include "nsIContent.h"
    10 #include "nsStyleContext.h"
    11 #include "nsNameSpaceManager.h"
    12 #include "nsIBoxObject.h"
    13 #include "nsTreeBoxObject.h"
    14 #include "nsIDOMElement.h"
    15 #include "nsITreeBoxObject.h"
    16 #include "nsITreeColumns.h"
    17 #include "nsIDOMXULTreeElement.h"
    18 #include "nsDisplayList.h"
    19 #include "nsTreeBodyFrame.h"
    21 //
    22 // NS_NewTreeColFrame
    23 //
    24 // Creates a new col frame
    25 //
    26 nsIFrame*
    27 NS_NewTreeColFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    28 {
    29   return new (aPresShell) nsTreeColFrame(aPresShell, aContext);
    30 }
    32 NS_IMPL_FRAMEARENA_HELPERS(nsTreeColFrame)
    34 // Destructor
    35 nsTreeColFrame::~nsTreeColFrame()
    36 {
    37 }
    39 void
    40 nsTreeColFrame::Init(nsIContent*      aContent,
    41                      nsIFrame*        aParent,
    42                      nsIFrame*        aPrevInFlow)
    43 {
    44   nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
    45   InvalidateColumns();
    46 }
    48 void
    49 nsTreeColFrame::DestroyFrom(nsIFrame* aDestructRoot)
    50 {
    51   InvalidateColumns(false);
    52   nsBoxFrame::DestroyFrom(aDestructRoot);
    53 }
    55 class nsDisplayXULTreeColSplitterTarget : public nsDisplayItem {
    56 public:
    57   nsDisplayXULTreeColSplitterTarget(nsDisplayListBuilder* aBuilder,
    58                                     nsIFrame* aFrame) :
    59     nsDisplayItem(aBuilder, aFrame) {
    60     MOZ_COUNT_CTOR(nsDisplayXULTreeColSplitterTarget);
    61   }
    62 #ifdef NS_BUILD_REFCNT_LOGGING
    63   virtual ~nsDisplayXULTreeColSplitterTarget() {
    64     MOZ_COUNT_DTOR(nsDisplayXULTreeColSplitterTarget);
    65   }
    66 #endif
    68   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    69                        HitTestState* aState,
    70                        nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
    71   NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget", TYPE_XUL_TREE_COL_SPLITTER_TARGET)
    72 };
    74 void
    75 nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    76                                            HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
    77 {
    78   nsRect rect = aRect - ToReferenceFrame();
    79   // If we are in either in the first 4 pixels or the last 4 pixels, we're going to
    80   // do something really strange.  Check for an adjacent splitter.
    81   bool left = false;
    82   bool right = false;
    83   if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <= rect.XMost()) {
    84     right = true;
    85   } else if (nsPresContext::CSSPixelsToAppUnits(4) > rect.x) {
    86     left = true;
    87   }
    89   // Swap left and right for RTL trees in order to find the correct splitter
    90   if (mFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
    91     bool tmp = left;
    92     left = right;
    93     right = tmp;
    94   }
    96   if (left || right) {
    97     // We are a header. Look for the correct splitter.
    98     nsIFrame* child;
    99     if (left)
   100       child = mFrame->GetPrevSibling();
   101     else
   102       child = mFrame->GetNextSibling();
   104     if (child && child->GetContent()->NodeInfo()->Equals(nsGkAtoms::splitter,
   105                                                          kNameSpaceID_XUL)) {
   106       aOutFrames->AppendElement(child);
   107     }
   108   }
   110 }
   112 void
   113 nsTreeColFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
   114                                             const nsRect&           aDirtyRect,
   115                                             const nsDisplayListSet& aLists)
   116 {
   117   if (!aBuilder->IsForEventDelivery()) {
   118     nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
   119     return;
   120   }
   122   nsDisplayListCollection set;
   123   nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, set);
   125   WrapListsInRedirector(aBuilder, set, aLists);
   127   aLists.Content()->AppendNewToTop(new (aBuilder)
   128     nsDisplayXULTreeColSplitterTarget(aBuilder, this));
   129 }
   131 nsresult
   132 nsTreeColFrame::AttributeChanged(int32_t aNameSpaceID,
   133                                  nsIAtom* aAttribute,
   134                                  int32_t aModType)
   135 {
   136   nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
   137                                              aModType);
   139   if (aAttribute == nsGkAtoms::ordinal || aAttribute == nsGkAtoms::primary) {
   140     InvalidateColumns();
   141   }
   143   return rv;
   144 }
   146 void
   147 nsTreeColFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState,
   148                           const nsRect& aRect,
   149                           bool aRemoveOverflowArea) {
   150   nscoord oldWidth = mRect.width;
   152   nsBoxFrame::SetBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
   153   if (mRect.width != oldWidth) {
   154     nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
   155     if (treeBoxObject) {
   156       treeBoxObject->Invalidate();
   157     }
   158   }
   159 }
   161 nsITreeBoxObject*
   162 nsTreeColFrame::GetTreeBoxObject()
   163 {
   164   nsITreeBoxObject* result = nullptr;
   166   nsIContent* parent = mContent->GetParent();
   167   if (parent) {
   168     nsIContent* grandParent = parent->GetParent();
   169     nsCOMPtr<nsIDOMXULElement> treeElement = do_QueryInterface(grandParent);
   170     if (treeElement) {
   171       nsCOMPtr<nsIBoxObject> boxObject;
   172       treeElement->GetBoxObject(getter_AddRefs(boxObject));
   174       nsCOMPtr<nsITreeBoxObject> treeBoxObject = do_QueryInterface(boxObject);
   175       result = treeBoxObject.get();
   176     }
   177   }
   178   return result;
   179 }
   181 void
   182 nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree)
   183 {
   184   nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
   185   if (treeBoxObject) {
   186     nsCOMPtr<nsITreeColumns> columns;
   188     if (aCanWalkFrameTree) {
   189       treeBoxObject->GetColumns(getter_AddRefs(columns));
   190     } else {
   191       nsTreeBodyFrame* body = static_cast<nsTreeBoxObject*>(treeBoxObject)->GetCachedTreeBody();
   192       if (body) {
   193         columns = body->Columns();
   194       }
   195     }
   197     if (columns)
   198       columns->InvalidateColumns();
   199   }
   200 }

mercurial