layout/xul/tree/nsTreeColFrame.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/xul/tree/nsTreeColFrame.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,200 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsCOMPtr.h"
    1.10 +#include "nsTreeColFrame.h"
    1.11 +#include "nsGkAtoms.h"
    1.12 +#include "nsIContent.h"
    1.13 +#include "nsStyleContext.h"
    1.14 +#include "nsNameSpaceManager.h"
    1.15 +#include "nsIBoxObject.h"
    1.16 +#include "nsTreeBoxObject.h"
    1.17 +#include "nsIDOMElement.h"
    1.18 +#include "nsITreeBoxObject.h"
    1.19 +#include "nsITreeColumns.h"
    1.20 +#include "nsIDOMXULTreeElement.h"
    1.21 +#include "nsDisplayList.h"
    1.22 +#include "nsTreeBodyFrame.h"
    1.23 +
    1.24 +//
    1.25 +// NS_NewTreeColFrame
    1.26 +//
    1.27 +// Creates a new col frame
    1.28 +//
    1.29 +nsIFrame*
    1.30 +NS_NewTreeColFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    1.31 +{
    1.32 +  return new (aPresShell) nsTreeColFrame(aPresShell, aContext);
    1.33 +}
    1.34 +
    1.35 +NS_IMPL_FRAMEARENA_HELPERS(nsTreeColFrame)
    1.36 +
    1.37 +// Destructor
    1.38 +nsTreeColFrame::~nsTreeColFrame()
    1.39 +{
    1.40 +}
    1.41 +
    1.42 +void
    1.43 +nsTreeColFrame::Init(nsIContent*      aContent,
    1.44 +                     nsIFrame*        aParent,
    1.45 +                     nsIFrame*        aPrevInFlow)
    1.46 +{
    1.47 +  nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
    1.48 +  InvalidateColumns();
    1.49 +}
    1.50 +
    1.51 +void
    1.52 +nsTreeColFrame::DestroyFrom(nsIFrame* aDestructRoot)
    1.53 +{
    1.54 +  InvalidateColumns(false);
    1.55 +  nsBoxFrame::DestroyFrom(aDestructRoot);
    1.56 +}
    1.57 +
    1.58 +class nsDisplayXULTreeColSplitterTarget : public nsDisplayItem {
    1.59 +public:
    1.60 +  nsDisplayXULTreeColSplitterTarget(nsDisplayListBuilder* aBuilder,
    1.61 +                                    nsIFrame* aFrame) :
    1.62 +    nsDisplayItem(aBuilder, aFrame) {
    1.63 +    MOZ_COUNT_CTOR(nsDisplayXULTreeColSplitterTarget);
    1.64 +  }
    1.65 +#ifdef NS_BUILD_REFCNT_LOGGING
    1.66 +  virtual ~nsDisplayXULTreeColSplitterTarget() {
    1.67 +    MOZ_COUNT_DTOR(nsDisplayXULTreeColSplitterTarget);
    1.68 +  }
    1.69 +#endif
    1.70 +
    1.71 +  virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    1.72 +                       HitTestState* aState,
    1.73 +                       nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
    1.74 +  NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget", TYPE_XUL_TREE_COL_SPLITTER_TARGET)
    1.75 +};
    1.76 +
    1.77 +void
    1.78 +nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    1.79 +                                           HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
    1.80 +{
    1.81 +  nsRect rect = aRect - ToReferenceFrame();
    1.82 +  // If we are in either in the first 4 pixels or the last 4 pixels, we're going to
    1.83 +  // do something really strange.  Check for an adjacent splitter.
    1.84 +  bool left = false;
    1.85 +  bool right = false;
    1.86 +  if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <= rect.XMost()) {
    1.87 +    right = true;
    1.88 +  } else if (nsPresContext::CSSPixelsToAppUnits(4) > rect.x) {
    1.89 +    left = true;
    1.90 +  }
    1.91 +
    1.92 +  // Swap left and right for RTL trees in order to find the correct splitter
    1.93 +  if (mFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
    1.94 +    bool tmp = left;
    1.95 +    left = right;
    1.96 +    right = tmp;
    1.97 +  }
    1.98 +
    1.99 +  if (left || right) {
   1.100 +    // We are a header. Look for the correct splitter.
   1.101 +    nsIFrame* child;
   1.102 +    if (left)
   1.103 +      child = mFrame->GetPrevSibling();
   1.104 +    else
   1.105 +      child = mFrame->GetNextSibling();
   1.106 +
   1.107 +    if (child && child->GetContent()->NodeInfo()->Equals(nsGkAtoms::splitter,
   1.108 +                                                         kNameSpaceID_XUL)) {
   1.109 +      aOutFrames->AppendElement(child);
   1.110 +    }
   1.111 +  }
   1.112 +
   1.113 +}
   1.114 +
   1.115 +void
   1.116 +nsTreeColFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
   1.117 +                                            const nsRect&           aDirtyRect,
   1.118 +                                            const nsDisplayListSet& aLists)
   1.119 +{
   1.120 +  if (!aBuilder->IsForEventDelivery()) {
   1.121 +    nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
   1.122 +    return;
   1.123 +  }
   1.124 +  
   1.125 +  nsDisplayListCollection set;
   1.126 +  nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, set);
   1.127 +  
   1.128 +  WrapListsInRedirector(aBuilder, set, aLists);
   1.129 +
   1.130 +  aLists.Content()->AppendNewToTop(new (aBuilder)
   1.131 +    nsDisplayXULTreeColSplitterTarget(aBuilder, this));
   1.132 +}
   1.133 +
   1.134 +nsresult
   1.135 +nsTreeColFrame::AttributeChanged(int32_t aNameSpaceID,
   1.136 +                                 nsIAtom* aAttribute,
   1.137 +                                 int32_t aModType)
   1.138 +{
   1.139 +  nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
   1.140 +                                             aModType);
   1.141 +
   1.142 +  if (aAttribute == nsGkAtoms::ordinal || aAttribute == nsGkAtoms::primary) {
   1.143 +    InvalidateColumns();
   1.144 +  }
   1.145 +
   1.146 +  return rv;
   1.147 +}
   1.148 +
   1.149 +void
   1.150 +nsTreeColFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState,
   1.151 +                          const nsRect& aRect,
   1.152 +                          bool aRemoveOverflowArea) {
   1.153 +  nscoord oldWidth = mRect.width;
   1.154 +
   1.155 +  nsBoxFrame::SetBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
   1.156 +  if (mRect.width != oldWidth) {
   1.157 +    nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
   1.158 +    if (treeBoxObject) {
   1.159 +      treeBoxObject->Invalidate();
   1.160 +    }
   1.161 +  }
   1.162 +}
   1.163 +
   1.164 +nsITreeBoxObject*
   1.165 +nsTreeColFrame::GetTreeBoxObject()
   1.166 +{
   1.167 +  nsITreeBoxObject* result = nullptr;
   1.168 +
   1.169 +  nsIContent* parent = mContent->GetParent();
   1.170 +  if (parent) {
   1.171 +    nsIContent* grandParent = parent->GetParent();
   1.172 +    nsCOMPtr<nsIDOMXULElement> treeElement = do_QueryInterface(grandParent);
   1.173 +    if (treeElement) {
   1.174 +      nsCOMPtr<nsIBoxObject> boxObject;
   1.175 +      treeElement->GetBoxObject(getter_AddRefs(boxObject));
   1.176 +
   1.177 +      nsCOMPtr<nsITreeBoxObject> treeBoxObject = do_QueryInterface(boxObject);
   1.178 +      result = treeBoxObject.get();
   1.179 +    }
   1.180 +  }
   1.181 +  return result;
   1.182 +}
   1.183 +
   1.184 +void
   1.185 +nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree)
   1.186 +{
   1.187 +  nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
   1.188 +  if (treeBoxObject) {
   1.189 +    nsCOMPtr<nsITreeColumns> columns;
   1.190 +
   1.191 +    if (aCanWalkFrameTree) {
   1.192 +      treeBoxObject->GetColumns(getter_AddRefs(columns));
   1.193 +    } else {
   1.194 +      nsTreeBodyFrame* body = static_cast<nsTreeBoxObject*>(treeBoxObject)->GetCachedTreeBody();
   1.195 +      if (body) {
   1.196 +        columns = body->Columns();
   1.197 +      }
   1.198 +    }
   1.199 +
   1.200 +    if (columns)
   1.201 +      columns->InvalidateColumns();
   1.202 +  }
   1.203 +}

mercurial