LCOV - code coverage report
Current view: top level - layout/xul - nsSplitterFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 56 464 12.1 %
Date: 2017-07-14 16:53:18 Functions: 13 46 28.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : //
       7             : // Eric Vaughan
       8             : // Netscape Communications
       9             : //
      10             : // See documentation in associated header file
      11             : //
      12             : 
      13             : #include "gfxContext.h"
      14             : #include "nsSplitterFrame.h"
      15             : #include "nsGkAtoms.h"
      16             : #include "nsIDOMElement.h"
      17             : #include "nsXULElement.h"
      18             : #include "nsPresContext.h"
      19             : #include "nsIDocument.h"
      20             : #include "nsNameSpaceManager.h"
      21             : #include "nsScrollbarButtonFrame.h"
      22             : #include "nsIDOMEventListener.h"
      23             : #include "nsIDOMMouseEvent.h"
      24             : #include "nsIPresShell.h"
      25             : #include "nsFrameList.h"
      26             : #include "nsHTMLParts.h"
      27             : #include "nsStyleContext.h"
      28             : #include "nsBoxLayoutState.h"
      29             : #include "nsIServiceManager.h"
      30             : #include "nsContainerFrame.h"
      31             : #include "nsContentCID.h"
      32             : #include "mozilla/GeckoStyleContext.h"
      33             : #include "mozilla/StyleSetHandle.h"
      34             : #include "mozilla/StyleSetHandleInlines.h"
      35             : #include "nsLayoutUtils.h"
      36             : #include "nsDisplayList.h"
      37             : #include "nsContentUtils.h"
      38             : #include "mozilla/dom/Element.h"
      39             : #include "mozilla/dom/Event.h"
      40             : #include "mozilla/MouseEvents.h"
      41             : #include "mozilla/UniquePtr.h"
      42             : 
      43             : using namespace mozilla;
      44             : 
      45           0 : class nsSplitterInfo {
      46             : public:
      47             :   nscoord min;
      48             :   nscoord max;
      49             :   nscoord current;
      50             :   nscoord changed;
      51             :   nsCOMPtr<nsIContent> childElem;
      52             :   int32_t flex;
      53             :   int32_t index;
      54             : };
      55             : 
      56             : class nsSplitterFrameInner final : public nsIDOMEventListener
      57             : {
      58             : protected:
      59             :   virtual ~nsSplitterFrameInner();
      60             : 
      61             : public:
      62             : 
      63             :   NS_DECL_ISUPPORTS
      64             :   NS_DECL_NSIDOMEVENTLISTENER
      65             : 
      66           1 :   explicit nsSplitterFrameInner(nsSplitterFrame* aSplitter)
      67           1 :   {
      68           1 :     mOuter = aSplitter;
      69           1 :     mPressed = false;
      70           1 :   }
      71             : 
      72           0 :   void Disconnect() { mOuter = nullptr; }
      73             : 
      74             :   nsresult MouseDown(nsIDOMEvent* aMouseEvent);
      75             :   nsresult MouseUp(nsIDOMEvent* aMouseEvent);
      76             :   nsresult MouseMove(nsIDOMEvent* aMouseEvent);
      77             : 
      78             :   void MouseDrag(nsPresContext* aPresContext, WidgetGUIEvent* aEvent);
      79             :   void MouseUp(nsPresContext* aPresContext, WidgetGUIEvent* aEvent);
      80             : 
      81             :   void AdjustChildren(nsPresContext* aPresContext);
      82             :   void AdjustChildren(nsPresContext* aPresContext, nsSplitterInfo* aChildInfos, int32_t aCount, bool aIsHorizontal);
      83             : 
      84             :   void AddRemoveSpace(nscoord aDiff,
      85             :                     nsSplitterInfo* aChildInfos,
      86             :                     int32_t aCount,
      87             :                     int32_t& aSpaceLeft);
      88             : 
      89             :   void ResizeChildTo(nscoord& aDiff,
      90             :                      nsSplitterInfo* aChildrenBeforeInfos,
      91             :                      nsSplitterInfo* aChildrenAfterInfos,
      92             :                      int32_t aChildrenBeforeCount,
      93             :                      int32_t aChildrenAfterCount,
      94             :                      bool aBounded);
      95             : 
      96             :   void UpdateState();
      97             : 
      98             :   void AddListener();
      99             :   void RemoveListener();
     100             : 
     101             :   enum ResizeType { Closest, Farthest, Flex, Grow };
     102             :   enum State { Open, CollapsedBefore, CollapsedAfter, Dragging };
     103             :   enum CollapseDirection { Before, After };
     104             : 
     105             :   ResizeType GetResizeBefore();
     106             :   ResizeType GetResizeAfter();
     107             :   State GetState();
     108             : 
     109             :   void Reverse(UniquePtr<nsSplitterInfo[]>& aIndexes, int32_t aCount);
     110             :   bool SupportsCollapseDirection(CollapseDirection aDirection);
     111             : 
     112             :   void EnsureOrient();
     113             :   void SetPreferredSize(nsBoxLayoutState& aState, nsIFrame* aChildBox, nscoord aOnePixel, bool aIsHorizontal, nscoord* aSize);
     114             : 
     115             :   nsSplitterFrame* mOuter;
     116             :   bool mDidDrag;
     117             :   nscoord mDragStart;
     118             :   nscoord mCurrentPos;
     119             :   nsIFrame* mParentBox;
     120             :   bool mPressed;
     121             :   UniquePtr<nsSplitterInfo[]> mChildInfosBefore;
     122             :   UniquePtr<nsSplitterInfo[]> mChildInfosAfter;
     123             :   int32_t mChildInfosBeforeCount;
     124             :   int32_t mChildInfosAfterCount;
     125             :   State mState;
     126             :   nscoord mSplitterPos;
     127             :   bool mDragging;
     128             : 
     129             : };
     130             : 
     131           9 : NS_IMPL_ISUPPORTS(nsSplitterFrameInner, nsIDOMEventListener)
     132             : 
     133             : nsSplitterFrameInner::ResizeType
     134           0 : nsSplitterFrameInner::GetResizeBefore()
     135             : {
     136             :   static nsIContent::AttrValuesArray strings[] =
     137             :     {&nsGkAtoms::farthest, &nsGkAtoms::flex, nullptr};
     138           0 :   switch (mOuter->GetContent()->FindAttrValueIn(kNameSpaceID_None,
     139             :                                                 nsGkAtoms::resizebefore,
     140           0 :                                                 strings, eCaseMatters)) {
     141           0 :     case 0: return Farthest;
     142           0 :     case 1: return Flex;
     143             :   }
     144           0 :   return Closest;
     145             : }
     146             : 
     147           0 : nsSplitterFrameInner::~nsSplitterFrameInner()
     148             : {
     149           0 : }
     150             : 
     151             : nsSplitterFrameInner::ResizeType
     152           0 : nsSplitterFrameInner::GetResizeAfter()
     153             : {
     154             :   static nsIContent::AttrValuesArray strings[] =
     155             :     {&nsGkAtoms::farthest, &nsGkAtoms::flex, &nsGkAtoms::grow, nullptr};
     156           0 :   switch (mOuter->GetContent()->FindAttrValueIn(kNameSpaceID_None,
     157             :                                                 nsGkAtoms::resizeafter,
     158           0 :                                                 strings, eCaseMatters)) {
     159           0 :     case 0: return Farthest;
     160           0 :     case 1: return Flex;
     161           0 :     case 2: return Grow;
     162             :   }
     163           0 :   return Closest;
     164             : }
     165             : 
     166             : nsSplitterFrameInner::State
     167           1 : nsSplitterFrameInner::GetState()
     168             : {
     169             :   static nsIContent::AttrValuesArray strings[] =
     170             :     {&nsGkAtoms::dragging, &nsGkAtoms::collapsed, nullptr};
     171             :   static nsIContent::AttrValuesArray strings_substate[] =
     172             :     {&nsGkAtoms::before, &nsGkAtoms::after, nullptr};
     173           2 :   switch (mOuter->GetContent()->FindAttrValueIn(kNameSpaceID_None,
     174             :                                                 nsGkAtoms::state,
     175           1 :                                                 strings, eCaseMatters)) {
     176           0 :     case 0: return Dragging;
     177             :     case 1:
     178           0 :       switch (mOuter->GetContent()->FindAttrValueIn(kNameSpaceID_None,
     179             :                                                     nsGkAtoms::substate,
     180             :                                                     strings_substate,
     181           0 :                                                     eCaseMatters)) {
     182           0 :         case 0: return CollapsedBefore;
     183           0 :         case 1: return CollapsedAfter;
     184             :         default:
     185           0 :           if (SupportsCollapseDirection(After))
     186           0 :             return CollapsedAfter;
     187           0 :           return CollapsedBefore;
     188             :       }
     189             :   }
     190           1 :   return Open;
     191             : }
     192             : 
     193             : //
     194             : // NS_NewSplitterFrame
     195             : //
     196             : // Creates a new Toolbar frame and returns it
     197             : //
     198             : nsIFrame*
     199           1 : NS_NewSplitterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
     200             : {
     201           1 :   return new (aPresShell) nsSplitterFrame(aContext);
     202             : }
     203             : 
     204           1 : NS_IMPL_FRAMEARENA_HELPERS(nsSplitterFrame)
     205             : 
     206           1 : nsSplitterFrame::nsSplitterFrame(nsStyleContext* aContext)
     207             : : nsBoxFrame(aContext, kClassID),
     208           1 :   mInner(0)
     209             : {
     210           1 : }
     211             : 
     212             : void
     213           0 : nsSplitterFrame::DestroyFrom(nsIFrame* aDestructRoot)
     214             : {
     215           0 :   if (mInner) {
     216           0 :     mInner->RemoveListener();
     217           0 :     mInner->Disconnect();
     218           0 :     mInner->Release();
     219           0 :     mInner = nullptr;
     220             :   }
     221           0 :   nsBoxFrame::DestroyFrom(aDestructRoot);
     222           0 : }
     223             : 
     224             : 
     225             : nsresult
     226           0 : nsSplitterFrame::GetCursor(const nsPoint&    aPoint,
     227             :                            nsIFrame::Cursor& aCursor)
     228             : {
     229           0 :   return nsBoxFrame::GetCursor(aPoint, aCursor);
     230             : 
     231             :   /*
     232             :     if (IsXULHorizontal())
     233             :       aCursor = NS_STYLE_CURSOR_N_RESIZE;
     234             :     else
     235             :       aCursor = NS_STYLE_CURSOR_W_RESIZE;
     236             : 
     237             :     return NS_OK;
     238             :   */
     239             : }
     240             : 
     241             : nsresult
     242           0 : nsSplitterFrame::AttributeChanged(int32_t aNameSpaceID,
     243             :                                   nsIAtom* aAttribute,
     244             :                                   int32_t aModType)
     245             : {
     246           0 :   nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
     247           0 :                                              aModType);
     248             :   // if the alignment changed. Let the grippy know
     249           0 :   if (aAttribute == nsGkAtoms::align) {
     250             :     // tell the slider its attribute changed so it can
     251             :     // update itself
     252           0 :     nsIFrame* grippy = nullptr;
     253           0 :     nsScrollbarButtonFrame::GetChildWithTag(nsGkAtoms::grippy, this, grippy);
     254           0 :     if (grippy)
     255           0 :       grippy->AttributeChanged(aNameSpaceID, aAttribute, aModType);
     256           0 :   } else if (aAttribute == nsGkAtoms::state) {
     257           0 :     mInner->UpdateState();
     258             :   }
     259             : 
     260           0 :   return rv;
     261             : }
     262             : 
     263             : /**
     264             :  * Initialize us. If we are in a box get our alignment so we know what direction we are
     265             :  */
     266             : void
     267           1 : nsSplitterFrame::Init(nsIContent*       aContent,
     268             :                       nsContainerFrame* aParent,
     269             :                       nsIFrame*         aPrevInFlow)
     270             : {
     271           1 :   MOZ_ASSERT(!mInner);
     272           1 :   mInner = new nsSplitterFrameInner(this);
     273             : 
     274           1 :   mInner->AddRef();
     275           1 :   mInner->mState = nsSplitterFrameInner::Open;
     276           1 :   mInner->mDragging = false;
     277             : 
     278             :   // determine orientation of parent, and if vertical, set orient to vertical
     279             :   // on splitter content, then re-resolve style
     280             :   // XXXbz this is pretty messed up, since this can change whether we should
     281             :   // have a frame at all.  This really needs a better solution.
     282           1 :   if (aParent && aParent->IsXULBoxFrame()) {
     283           1 :     if (!aParent->IsXULHorizontal()) {
     284           0 :       if (!nsContentUtils::HasNonEmptyAttr(aContent, kNameSpaceID_None,
     285             :                                            nsGkAtoms::orient)) {
     286           0 :         aContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orient,
     287           0 :                           NS_LITERAL_STRING("vertical"), false);
     288           0 :         GeckoStyleContext* parentStyleContext = StyleContext()->GetParent();
     289           0 :         RefPtr<nsStyleContext> newContext = PresContext()->StyleSet()->
     290           0 :           ResolveStyleFor(aContent->AsElement(), parentStyleContext,
     291           0 :                           LazyComputeBehavior::Allow);
     292           0 :         SetStyleContextWithoutNotification(newContext);
     293             :       }
     294             :     }
     295             :   }
     296             : 
     297           1 :   nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
     298             : 
     299           1 :   mInner->mState = nsSplitterFrameInner::Open;
     300           1 :   mInner->AddListener();
     301           1 :   mInner->mParentBox = nullptr;
     302           1 : }
     303             : 
     304             : NS_IMETHODIMP
     305           1 : nsSplitterFrame::DoXULLayout(nsBoxLayoutState& aState)
     306             : {
     307           1 :   if (GetStateBits() & NS_FRAME_FIRST_REFLOW)
     308             :   {
     309           1 :     mInner->mParentBox = nsBox::GetParentXULBox(this);
     310           1 :     mInner->UpdateState();
     311             :   }
     312             : 
     313           1 :   return nsBoxFrame::DoXULLayout(aState);
     314             : }
     315             : 
     316             : 
     317             : void
     318           3 : nsSplitterFrame::GetInitialOrientation(bool& aIsHorizontal)
     319             : {
     320           3 :   nsIFrame* box = nsBox::GetParentXULBox(this);
     321           3 :   if (box) {
     322           3 :     aIsHorizontal = !box->IsXULHorizontal();
     323             :   }
     324             :   else
     325           0 :     nsBoxFrame::GetInitialOrientation(aIsHorizontal);
     326           3 : }
     327             : 
     328             : NS_IMETHODIMP
     329           0 : nsSplitterFrame::HandlePress(nsPresContext* aPresContext,
     330             :                              WidgetGUIEvent* aEvent,
     331             :                              nsEventStatus* aEventStatus)
     332             : {
     333           0 :   return NS_OK;
     334             : }
     335             : 
     336             : NS_IMETHODIMP
     337           0 : nsSplitterFrame::HandleMultiplePress(nsPresContext* aPresContext,
     338             :                                      WidgetGUIEvent* aEvent,
     339             :                                      nsEventStatus* aEventStatus,
     340             :                                      bool aControlHeld)
     341             : {
     342           0 :   return NS_OK;
     343             : }
     344             : 
     345             : NS_IMETHODIMP
     346           0 : nsSplitterFrame::HandleDrag(nsPresContext* aPresContext,
     347             :                             WidgetGUIEvent* aEvent,
     348             :                             nsEventStatus* aEventStatus)
     349             : {
     350           0 :   return NS_OK;
     351             : }
     352             : 
     353             : NS_IMETHODIMP
     354           0 : nsSplitterFrame::HandleRelease(nsPresContext* aPresContext,
     355             :                                WidgetGUIEvent* aEvent,
     356             :                                nsEventStatus* aEventStatus)
     357             : {
     358           0 :   return NS_OK;
     359             : }
     360             : 
     361             : void
     362          22 : nsSplitterFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     363             :                                   const nsRect&           aDirtyRect,
     364             :                                   const nsDisplayListSet& aLists)
     365             : {
     366          22 :   nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
     367             : 
     368             :   // if the mouse is captured always return us as the frame.
     369          22 :   if (mInner->mDragging)
     370             :   {
     371             :     // XXX It's probably better not to check visibility here, right?
     372           0 :     aLists.Outlines()->AppendNewToTop(new (aBuilder)
     373           0 :       nsDisplayEventReceiver(aBuilder, this));
     374           0 :     return;
     375             :   }
     376             : }
     377             : 
     378             : nsresult
     379           0 : nsSplitterFrame::HandleEvent(nsPresContext* aPresContext,
     380             :                              WidgetGUIEvent* aEvent,
     381             :                              nsEventStatus* aEventStatus)
     382             : {
     383           0 :   NS_ENSURE_ARG_POINTER(aEventStatus);
     384           0 :   if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     385           0 :     return NS_OK;
     386             :   }
     387             : 
     388           0 :   AutoWeakFrame weakFrame(this);
     389           0 :   RefPtr<nsSplitterFrameInner> inner(mInner);
     390           0 :   switch (aEvent->mMessage) {
     391             :     case eMouseMove:
     392           0 :       inner->MouseDrag(aPresContext, aEvent);
     393           0 :       break;
     394             : 
     395             :     case eMouseUp:
     396           0 :       if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
     397           0 :         inner->MouseUp(aPresContext, aEvent);
     398             :       }
     399           0 :       break;
     400             : 
     401             :     default:
     402           0 :       break;
     403             :   }
     404             : 
     405           0 :   NS_ENSURE_STATE(weakFrame.IsAlive());
     406           0 :   return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
     407             : }
     408             : 
     409             : void
     410           0 : nsSplitterFrameInner::MouseUp(nsPresContext* aPresContext,
     411             :                               WidgetGUIEvent* aEvent)
     412             : {
     413           0 :   if (mDragging && mOuter) {
     414           0 :     AdjustChildren(aPresContext);
     415           0 :     AddListener();
     416           0 :     nsIPresShell::SetCapturingContent(nullptr, 0); // XXXndeakin is this needed?
     417           0 :     mDragging = false;
     418           0 :     State newState = GetState();
     419             :     // if the state is dragging then make it Open.
     420           0 :     if (newState == Dragging)
     421           0 :       mOuter->mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::state, EmptyString(), true);
     422             : 
     423           0 :     mPressed = false;
     424             : 
     425             :     // if we dragged then fire a command event.
     426           0 :     if (mDidDrag) {
     427             :       RefPtr<nsXULElement> element =
     428           0 :         nsXULElement::FromContent(mOuter->GetContent());
     429           0 :       element->DoCommand();
     430             :     }
     431             : 
     432             :     //printf("MouseUp\n");
     433             :   }
     434             : 
     435           0 :   mChildInfosBefore = nullptr;
     436           0 :   mChildInfosAfter = nullptr;
     437           0 :   mChildInfosBeforeCount = 0;
     438           0 :   mChildInfosAfterCount = 0;
     439           0 : }
     440             : 
     441             : void
     442           0 : nsSplitterFrameInner::MouseDrag(nsPresContext* aPresContext,
     443             :                                 WidgetGUIEvent* aEvent)
     444             : {
     445           0 :   if (mDragging && mOuter) {
     446             : 
     447             :     //printf("Dragging\n");
     448             : 
     449           0 :     bool isHorizontal = !mOuter->IsXULHorizontal();
     450             :     // convert coord to pixels
     451             :     nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
     452           0 :                                                               mParentBox);
     453           0 :     nscoord pos = isHorizontal ? pt.x : pt.y;
     454             : 
     455             :     // mDragStart is in frame coordinates
     456           0 :     nscoord start = mDragStart;
     457             : 
     458             :     // take our current position and subtract the start location
     459           0 :     pos -= start;
     460             : 
     461             :     //printf("Diff=%d\n", pos);
     462             : 
     463           0 :     ResizeType resizeAfter  = GetResizeAfter();
     464             : 
     465             :     bool bounded;
     466             : 
     467           0 :     if (resizeAfter == nsSplitterFrameInner::Grow)
     468           0 :       bounded = false;
     469             :     else
     470           0 :       bounded = true;
     471             : 
     472             :     int i;
     473           0 :     for (i=0; i < mChildInfosBeforeCount; i++)
     474           0 :       mChildInfosBefore[i].changed = mChildInfosBefore[i].current;
     475             : 
     476           0 :     for (i=0; i < mChildInfosAfterCount; i++)
     477           0 :       mChildInfosAfter[i].changed = mChildInfosAfter[i].current;
     478             : 
     479           0 :     nscoord oldPos = pos;
     480             : 
     481           0 :     ResizeChildTo(pos,
     482             :                   mChildInfosBefore.get(), mChildInfosAfter.get(),
     483           0 :                   mChildInfosBeforeCount, mChildInfosAfterCount, bounded);
     484             : 
     485           0 :     State currentState = GetState();
     486           0 :     bool supportsBefore = SupportsCollapseDirection(Before);
     487           0 :     bool supportsAfter = SupportsCollapseDirection(After);
     488             : 
     489           0 :     const bool isRTL = mOuter->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
     490           0 :     bool pastEnd = oldPos > 0 && oldPos > pos;
     491           0 :     bool pastBegin = oldPos < 0 && oldPos < pos;
     492           0 :     if (isRTL) {
     493             :       // Swap the boundary checks in RTL mode
     494           0 :       bool tmp = pastEnd;
     495           0 :       pastEnd = pastBegin;
     496           0 :       pastBegin = tmp;
     497             :     }
     498           0 :     const bool isCollapsedBefore = pastBegin && supportsBefore;
     499           0 :     const bool isCollapsedAfter = pastEnd && supportsAfter;
     500             : 
     501             :     // if we are in a collapsed position
     502           0 :     if (isCollapsedBefore || isCollapsedAfter)
     503             :     {
     504             :       // and we are not collapsed then collapse
     505           0 :       if (currentState == Dragging) {
     506           0 :         if (pastEnd)
     507             :         {
     508             :           //printf("Collapse right\n");
     509           0 :           if (supportsAfter)
     510             :           {
     511           0 :             nsCOMPtr<nsIContent> outer = mOuter->mContent;
     512           0 :             outer->SetAttr(kNameSpaceID_None, nsGkAtoms::substate,
     513           0 :                            NS_LITERAL_STRING("after"),
     514           0 :                            true);
     515           0 :             outer->SetAttr(kNameSpaceID_None, nsGkAtoms::state,
     516           0 :                            NS_LITERAL_STRING("collapsed"),
     517           0 :                            true);
     518             :           }
     519             : 
     520           0 :         } else if (pastBegin)
     521             :         {
     522             :           //printf("Collapse left\n");
     523           0 :           if (supportsBefore)
     524             :           {
     525           0 :             nsCOMPtr<nsIContent> outer = mOuter->mContent;
     526           0 :             outer->SetAttr(kNameSpaceID_None, nsGkAtoms::substate,
     527           0 :                            NS_LITERAL_STRING("before"),
     528           0 :                            true);
     529           0 :             outer->SetAttr(kNameSpaceID_None, nsGkAtoms::state,
     530           0 :                            NS_LITERAL_STRING("collapsed"),
     531           0 :                            true);
     532             :           }
     533             :         }
     534           0 :       }
     535             :     } else {
     536             :       // if we are not in a collapsed position and we are not dragging make sure
     537             :       // we are dragging.
     538           0 :       if (currentState != Dragging)
     539           0 :         mOuter->mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::state, NS_LITERAL_STRING("dragging"), true);
     540           0 :       AdjustChildren(aPresContext);
     541             :     }
     542             : 
     543           0 :     mDidDrag = true;
     544             :   }
     545           0 : }
     546             : 
     547             : void
     548           1 : nsSplitterFrameInner::AddListener()
     549             : {
     550           1 :   mOuter->GetContent()->
     551           2 :     AddEventListener(NS_LITERAL_STRING("mouseup"), this, false, false);
     552           1 :   mOuter->GetContent()->
     553           2 :     AddEventListener(NS_LITERAL_STRING("mousedown"), this, false, false);
     554           1 :   mOuter->GetContent()->
     555           2 :     AddEventListener(NS_LITERAL_STRING("mousemove"), this, false, false);
     556           1 :   mOuter->GetContent()->
     557           2 :     AddEventListener(NS_LITERAL_STRING("mouseout"), this, false, false);
     558           1 : }
     559             : 
     560             : void
     561           0 : nsSplitterFrameInner::RemoveListener()
     562             : {
     563           0 :   ENSURE_TRUE(mOuter);
     564           0 :   mOuter->GetContent()->
     565           0 :     RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, false);
     566           0 :   mOuter->GetContent()->
     567           0 :     RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, false);
     568           0 :   mOuter->GetContent()->
     569           0 :     RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, false);
     570           0 :   mOuter->GetContent()->
     571           0 :     RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
     572             : }
     573             : 
     574             : nsresult
     575           0 : nsSplitterFrameInner::HandleEvent(nsIDOMEvent* aEvent)
     576             : {
     577           0 :   nsAutoString eventType;
     578           0 :   aEvent->GetType(eventType);
     579           0 :   if (eventType.EqualsLiteral("mouseup"))
     580           0 :     return MouseUp(aEvent);
     581           0 :   if (eventType.EqualsLiteral("mousedown"))
     582           0 :     return MouseDown(aEvent);
     583           0 :   if (eventType.EqualsLiteral("mousemove") ||
     584           0 :       eventType.EqualsLiteral("mouseout"))
     585           0 :     return MouseMove(aEvent);
     586             : 
     587           0 :   NS_ABORT();
     588           0 :   return NS_OK;
     589             : }
     590             : 
     591             : nsresult
     592           0 : nsSplitterFrameInner::MouseUp(nsIDOMEvent* aMouseEvent)
     593             : {
     594           0 :   NS_ENSURE_TRUE(mOuter, NS_OK);
     595           0 :   mPressed = false;
     596             : 
     597           0 :   nsIPresShell::SetCapturingContent(nullptr, 0);
     598             : 
     599           0 :   return NS_OK;
     600             : }
     601             : 
     602             : nsresult
     603           0 : nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent)
     604             : {
     605           0 :   NS_ENSURE_TRUE(mOuter, NS_OK);
     606           0 :   nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
     607           0 :   if (!mouseEvent)
     608           0 :     return NS_OK;
     609             : 
     610           0 :   int16_t button = 0;
     611           0 :   mouseEvent->GetButton(&button);
     612             : 
     613             :   // only if left button
     614           0 :   if (button != 0)
     615           0 :      return NS_OK;
     616             : 
     617           0 :   if (mOuter->GetContent()->
     618           0 :         AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
     619             :                     nsGkAtoms::_true, eCaseMatters))
     620           0 :     return NS_OK;
     621             : 
     622           0 :   mParentBox = nsBox::GetParentXULBox(mOuter);
     623           0 :   if (!mParentBox)
     624           0 :     return NS_OK;
     625             : 
     626             :   // get our index
     627           0 :   nsPresContext* outerPresContext = mOuter->PresContext();
     628           0 :   const nsFrameList& siblingList(mParentBox->PrincipalChildList());
     629           0 :   int32_t childIndex = siblingList.IndexOf(mOuter);
     630             :   // if it's 0 (or not found) then stop right here.
     631             :   // It might be not found if we're not in the parent's primary frame list.
     632           0 :   if (childIndex <= 0)
     633           0 :     return NS_OK;
     634             : 
     635           0 :   int32_t childCount = siblingList.GetLength();
     636             :   // if it's the last index then we need to allow for resizeafter="grow"
     637           0 :   if (childIndex == childCount - 1 && GetResizeAfter() != Grow)
     638           0 :     return NS_OK;
     639             : 
     640             :   RefPtr<gfxContext> rc =
     641           0 :     outerPresContext->PresShell()->CreateReferenceRenderingContext();
     642           0 :   nsBoxLayoutState state(outerPresContext, rc);
     643           0 :   mCurrentPos = 0;
     644           0 :   mPressed = true;
     645             : 
     646           0 :   mDidDrag = false;
     647             : 
     648           0 :   EnsureOrient();
     649           0 :   bool isHorizontal = !mOuter->IsXULHorizontal();
     650             : 
     651           0 :   ResizeType resizeBefore = GetResizeBefore();
     652           0 :   ResizeType resizeAfter  = GetResizeAfter();
     653             : 
     654           0 :   mChildInfosBefore = MakeUnique<nsSplitterInfo[]>(childCount);
     655           0 :   mChildInfosAfter  = MakeUnique<nsSplitterInfo[]>(childCount);
     656             : 
     657             :   // create info 2 lists. One of the children before us and one after.
     658           0 :   int32_t count = 0;
     659           0 :   mChildInfosBeforeCount = 0;
     660           0 :   mChildInfosAfterCount = 0;
     661             : 
     662           0 :   nsIFrame* childBox = nsBox::GetChildXULBox(mParentBox);
     663             : 
     664           0 :   while (nullptr != childBox)
     665             :   {
     666           0 :     nsIContent* content = childBox->GetContent();
     667           0 :     nsIDocument* doc = content->OwnerDoc();
     668             :     int32_t dummy;
     669           0 :     nsIAtom* atom = doc->BindingManager()->ResolveTag(content, &dummy);
     670             : 
     671             :     // skip over any splitters
     672           0 :     if (atom != nsGkAtoms::splitter) {
     673           0 :         nsSize prefSize = childBox->GetXULPrefSize(state);
     674           0 :         nsSize minSize = childBox->GetXULMinSize(state);
     675           0 :         nsSize maxSize = nsBox::BoundsCheckMinMax(minSize, childBox->GetXULMaxSize(state));
     676           0 :         prefSize = nsBox::BoundsCheck(minSize, prefSize, maxSize);
     677             : 
     678           0 :         mOuter->AddMargin(childBox, minSize);
     679           0 :         mOuter->AddMargin(childBox, prefSize);
     680           0 :         mOuter->AddMargin(childBox, maxSize);
     681             : 
     682           0 :         nscoord flex = childBox->GetXULFlex();
     683             : 
     684           0 :         nsMargin margin(0,0,0,0);
     685           0 :         childBox->GetXULMargin(margin);
     686           0 :         nsRect r(childBox->GetRect());
     687           0 :         r.Inflate(margin);
     688             : 
     689             :         // We need to check for hidden attribute too, since treecols with
     690             :         // the hidden="true" attribute are not really hidden, just collapsed
     691           0 :         if (!content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::fixed,
     692           0 :                                   nsGkAtoms::_true, eCaseMatters) &&
     693           0 :             !content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
     694             :                                   nsGkAtoms::_true, eCaseMatters)) {
     695           0 :             if (count < childIndex && (resizeBefore != Flex || flex > 0)) {
     696           0 :                 mChildInfosBefore[mChildInfosBeforeCount].childElem = content;
     697           0 :                 mChildInfosBefore[mChildInfosBeforeCount].min     = isHorizontal ? minSize.width : minSize.height;
     698           0 :                 mChildInfosBefore[mChildInfosBeforeCount].max     = isHorizontal ? maxSize.width : maxSize.height;
     699           0 :                 mChildInfosBefore[mChildInfosBeforeCount].current = isHorizontal ? r.width : r.height;
     700           0 :                 mChildInfosBefore[mChildInfosBeforeCount].flex    = flex;
     701           0 :                 mChildInfosBefore[mChildInfosBeforeCount].index   = count;
     702           0 :                 mChildInfosBefore[mChildInfosBeforeCount].changed = mChildInfosBefore[mChildInfosBeforeCount].current;
     703           0 :                 mChildInfosBeforeCount++;
     704           0 :             } else if (count > childIndex && (resizeAfter != Flex || flex > 0)) {
     705           0 :                 mChildInfosAfter[mChildInfosAfterCount].childElem = content;
     706           0 :                 mChildInfosAfter[mChildInfosAfterCount].min     = isHorizontal ? minSize.width : minSize.height;
     707           0 :                 mChildInfosAfter[mChildInfosAfterCount].max     = isHorizontal ? maxSize.width : maxSize.height;
     708           0 :                 mChildInfosAfter[mChildInfosAfterCount].current = isHorizontal ? r.width : r.height;
     709           0 :                 mChildInfosAfter[mChildInfosAfterCount].flex    = flex;
     710           0 :                 mChildInfosAfter[mChildInfosAfterCount].index   = count;
     711           0 :                 mChildInfosAfter[mChildInfosAfterCount].changed = mChildInfosAfter[mChildInfosAfterCount].current;
     712           0 :                 mChildInfosAfterCount++;
     713             :             }
     714             :         }
     715             :     }
     716             : 
     717           0 :     childBox = nsBox::GetNextXULBox(childBox);
     718           0 :     count++;
     719             :   }
     720             : 
     721           0 :   if (!mParentBox->IsXULNormalDirection()) {
     722             :     // The before array is really the after array, and the order needs to be reversed.
     723             :     // First reverse both arrays.
     724           0 :     Reverse(mChildInfosBefore, mChildInfosBeforeCount);
     725           0 :     Reverse(mChildInfosAfter, mChildInfosAfterCount);
     726             : 
     727             :     // Now swap the two arrays.
     728           0 :     Swap(mChildInfosBeforeCount, mChildInfosAfterCount);
     729           0 :     Swap(mChildInfosBefore, mChildInfosAfter);
     730             :   }
     731             : 
     732             :   // if resizebefore is not Farthest, reverse the list because the first child
     733             :   // in the list is the farthest, and we want the first child to be the closest.
     734           0 :   if (resizeBefore != Farthest)
     735           0 :      Reverse(mChildInfosBefore, mChildInfosBeforeCount);
     736             : 
     737             :   // if the resizeafter is the Farthest we must reverse the list because the first child in the list
     738             :   // is the closest we want the first child to be the Farthest.
     739           0 :   if (resizeAfter == Farthest)
     740           0 :      Reverse(mChildInfosAfter, mChildInfosAfterCount);
     741             : 
     742             :   // grow only applys to the children after. If grow is set then no space should be taken out of any children after
     743             :   // us. To do this we just set the size of that list to be 0.
     744           0 :   if (resizeAfter == Grow)
     745           0 :      mChildInfosAfterCount = 0;
     746             : 
     747             :   int32_t c;
     748           0 :   nsPoint pt = nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(mouseEvent->AsEvent(),
     749           0 :                                                                mParentBox);
     750           0 :   if (isHorizontal) {
     751           0 :      c = pt.x;
     752           0 :      mSplitterPos = mOuter->mRect.x;
     753             :   } else {
     754           0 :      c = pt.y;
     755           0 :      mSplitterPos = mOuter->mRect.y;
     756             :   }
     757             : 
     758           0 :   mDragStart = c;
     759             : 
     760             :   //printf("Pressed mDragStart=%d\n",mDragStart);
     761             : 
     762           0 :   nsIPresShell::SetCapturingContent(mOuter->GetContent(), CAPTURE_IGNOREALLOWED);
     763             : 
     764           0 :   return NS_OK;
     765             : }
     766             : 
     767             : nsresult
     768           0 : nsSplitterFrameInner::MouseMove(nsIDOMEvent* aMouseEvent)
     769             : {
     770           0 :   NS_ENSURE_TRUE(mOuter, NS_OK);
     771           0 :   if (!mPressed)
     772           0 :     return NS_OK;
     773             : 
     774           0 :   if (mDragging)
     775           0 :     return NS_OK;
     776             : 
     777           0 :   nsCOMPtr<nsIDOMEventListener> kungfuDeathGrip(this);
     778           0 :   mOuter->mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::state,
     779           0 :                             NS_LITERAL_STRING("dragging"), true);
     780             : 
     781           0 :   RemoveListener();
     782           0 :   mDragging = true;
     783             : 
     784           0 :   return NS_OK;
     785             : }
     786             : 
     787             : void
     788           0 : nsSplitterFrameInner::Reverse(UniquePtr<nsSplitterInfo[]>& aChildInfos, int32_t aCount)
     789             : {
     790           0 :     UniquePtr<nsSplitterInfo[]> infos(new nsSplitterInfo[aCount]);
     791             : 
     792           0 :     for (int i=0; i < aCount; i++)
     793           0 :        infos[i] = aChildInfos[aCount - 1 - i];
     794             : 
     795           0 :     aChildInfos = Move(infos);
     796           0 : }
     797             : 
     798             : bool
     799           0 : nsSplitterFrameInner::SupportsCollapseDirection
     800             : (
     801             :   nsSplitterFrameInner::CollapseDirection aDirection
     802             : )
     803             : {
     804             :   static nsIContent::AttrValuesArray strings[] =
     805             :     {&nsGkAtoms::before, &nsGkAtoms::after, &nsGkAtoms::both, nullptr};
     806             : 
     807           0 :   switch (mOuter->mContent->FindAttrValueIn(kNameSpaceID_None,
     808             :                                             nsGkAtoms::collapse,
     809           0 :                                             strings, eCaseMatters)) {
     810             :     case 0:
     811           0 :       return (aDirection == Before);
     812             :     case 1:
     813           0 :       return (aDirection == After);
     814             :     case 2:
     815           0 :       return true;
     816             :   }
     817             : 
     818           0 :   return false;
     819             : }
     820             : 
     821             : void
     822           1 : nsSplitterFrameInner::UpdateState()
     823             : {
     824             :   // State Transitions:
     825             :   //   Open            -> Dragging
     826             :   //   Open            -> CollapsedBefore
     827             :   //   Open            -> CollapsedAfter
     828             :   //   CollapsedBefore -> Open
     829             :   //   CollapsedBefore -> Dragging
     830             :   //   CollapsedAfter  -> Open
     831             :   //   CollapsedAfter  -> Dragging
     832             :   //   Dragging        -> Open
     833             :   //   Dragging        -> CollapsedBefore (auto collapse)
     834             :   //   Dragging        -> CollapsedAfter (auto collapse)
     835             : 
     836           1 :   State newState = GetState();
     837             : 
     838           1 :   if (newState == mState) {
     839             :     // No change.
     840           1 :     return;
     841             :   }
     842             : 
     843           0 :   if ((SupportsCollapseDirection(Before) || SupportsCollapseDirection(After)) &&
     844           0 :       mOuter->GetParent()->IsXULBoxFrame()) {
     845             :     // Find the splitter's immediate sibling.
     846             :     nsIFrame* splitterSibling;
     847           0 :     if (newState == CollapsedBefore || mState == CollapsedBefore) {
     848           0 :       splitterSibling = mOuter->GetPrevSibling();
     849             :     } else {
     850           0 :       splitterSibling = mOuter->GetNextSibling();
     851             :     }
     852             : 
     853           0 :     if (splitterSibling) {
     854           0 :       nsCOMPtr<nsIContent> sibling = splitterSibling->GetContent();
     855           0 :       if (sibling) {
     856           0 :         if (mState == CollapsedBefore || mState == CollapsedAfter) {
     857             :           // CollapsedBefore -> Open
     858             :           // CollapsedBefore -> Dragging
     859             :           // CollapsedAfter -> Open
     860             :           // CollapsedAfter -> Dragging
     861             :           nsContentUtils::AddScriptRunner(
     862           0 :             new nsUnsetAttrRunnable(sibling, nsGkAtoms::collapsed));
     863           0 :         } else if ((mState == Open || mState == Dragging)
     864           0 :                    && (newState == CollapsedBefore ||
     865             :                        newState == CollapsedAfter)) {
     866             :           // Open -> CollapsedBefore / CollapsedAfter
     867             :           // Dragging -> CollapsedBefore / CollapsedAfter
     868           0 :           nsContentUtils::AddScriptRunner(
     869             :             new nsSetAttrRunnable(sibling, nsGkAtoms::collapsed,
     870           0 :                                   NS_LITERAL_STRING("true")));
     871             :         }
     872             :       }
     873             :     }
     874             :   }
     875           0 :   mState = newState;
     876             : }
     877             : 
     878             : void
     879           0 : nsSplitterFrameInner::EnsureOrient()
     880             : {
     881           0 :   bool isHorizontal = !(mParentBox->GetStateBits() & NS_STATE_IS_HORIZONTAL);
     882           0 :   if (isHorizontal)
     883           0 :     mOuter->mState |= NS_STATE_IS_HORIZONTAL;
     884             :   else
     885           0 :     mOuter->mState &= ~NS_STATE_IS_HORIZONTAL;
     886           0 : }
     887             : 
     888             : void
     889           0 : nsSplitterFrameInner::AdjustChildren(nsPresContext* aPresContext)
     890             : {
     891           0 :   EnsureOrient();
     892           0 :   bool isHorizontal = !mOuter->IsXULHorizontal();
     893             : 
     894           0 :   AdjustChildren(aPresContext, mChildInfosBefore.get(),
     895           0 :                  mChildInfosBeforeCount, isHorizontal);
     896           0 :   AdjustChildren(aPresContext, mChildInfosAfter.get(),
     897           0 :                  mChildInfosAfterCount, isHorizontal);
     898           0 : }
     899             : 
     900           0 : static nsIFrame* GetChildBoxForContent(nsIFrame* aParentBox, nsIContent* aContent)
     901             : {
     902           0 :   nsIFrame* childBox = nsBox::GetChildXULBox(aParentBox);
     903             : 
     904           0 :   while (nullptr != childBox) {
     905           0 :     if (childBox->GetContent() == aContent) {
     906           0 :       return childBox;
     907             :     }
     908           0 :     childBox = nsBox::GetNextXULBox(childBox);
     909             :   }
     910           0 :   return nullptr;
     911             : }
     912             : 
     913             : void
     914           0 : nsSplitterFrameInner::AdjustChildren(nsPresContext* aPresContext, nsSplitterInfo* aChildInfos, int32_t aCount, bool aIsHorizontal)
     915             : {
     916             :   ///printf("------- AdjustChildren------\n");
     917             : 
     918           0 :   nsBoxLayoutState state(aPresContext);
     919             : 
     920           0 :   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
     921             : 
     922             :   // first set all the widths.
     923           0 :   nsIFrame* child =  nsBox::GetChildXULBox(mOuter);
     924           0 :   while(child)
     925             :   {
     926           0 :     SetPreferredSize(state, child, onePixel, aIsHorizontal, nullptr);
     927           0 :     child = nsBox::GetNextXULBox(child);
     928             :   }
     929             : 
     930             :   // now set our changed widths.
     931           0 :   for (int i=0; i < aCount; i++)
     932             :   {
     933           0 :     nscoord   pref       = aChildInfos[i].changed;
     934           0 :     nsIFrame* childBox     = GetChildBoxForContent(mParentBox, aChildInfos[i].childElem);
     935             : 
     936           0 :     if (childBox) {
     937           0 :       SetPreferredSize(state, childBox, onePixel, aIsHorizontal, &pref);
     938             :     }
     939             :   }
     940           0 : }
     941             : 
     942             : void
     943           0 : nsSplitterFrameInner::SetPreferredSize(nsBoxLayoutState& aState, nsIFrame* aChildBox, nscoord aOnePixel, bool aIsHorizontal, nscoord* aSize)
     944             : {
     945           0 :   nsRect rect(aChildBox->GetRect());
     946           0 :   nscoord pref = 0;
     947             : 
     948           0 :   if (!aSize)
     949             :   {
     950           0 :     if (aIsHorizontal)
     951           0 :       pref = rect.width;
     952             :     else
     953           0 :       pref = rect.height;
     954             :   } else {
     955           0 :     pref = *aSize;
     956             :   }
     957             : 
     958           0 :   nsMargin margin(0,0,0,0);
     959           0 :   aChildBox->GetXULMargin(margin);
     960             : 
     961           0 :   nsCOMPtr<nsIAtom> attribute;
     962             : 
     963           0 :   if (aIsHorizontal) {
     964           0 :     pref -= (margin.left + margin.right);
     965           0 :     attribute = nsGkAtoms::width;
     966             :   } else {
     967           0 :     pref -= (margin.top + margin.bottom);
     968           0 :     attribute = nsGkAtoms::height;
     969             :   }
     970             : 
     971           0 :   nsIContent* content = aChildBox->GetContent();
     972             : 
     973             :   // set its preferred size.
     974           0 :   nsAutoString prefValue;
     975           0 :   prefValue.AppendInt(pref/aOnePixel);
     976           0 :   if (content->AttrValueIs(kNameSpaceID_None, attribute,
     977             :                            prefValue, eCaseMatters))
     978           0 :      return;
     979             : 
     980           0 :   AutoWeakFrame weakBox(aChildBox);
     981           0 :   content->SetAttr(kNameSpaceID_None, attribute, prefValue, true);
     982           0 :   ENSURE_TRUE(weakBox.IsAlive());
     983           0 :   aState.PresShell()->FrameNeedsReflow(aChildBox, nsIPresShell::eStyleChange,
     984           0 :                                        NS_FRAME_IS_DIRTY);
     985             : }
     986             : 
     987             : 
     988             : void
     989           0 : nsSplitterFrameInner::AddRemoveSpace(nscoord aDiff,
     990             :                                     nsSplitterInfo* aChildInfos,
     991             :                                     int32_t aCount,
     992             :                                     int32_t& aSpaceLeft)
     993             : {
     994           0 :   aSpaceLeft = 0;
     995             : 
     996           0 :   for (int i=0; i < aCount; i++) {
     997           0 :     nscoord min    = aChildInfos[i].min;
     998           0 :     nscoord max    = aChildInfos[i].max;
     999           0 :     nscoord& c     = aChildInfos[i].changed;
    1000             : 
    1001             :     // figure our how much space to add or remove
    1002           0 :     if (c + aDiff < min) {
    1003           0 :       aDiff += (c - min);
    1004           0 :       c = min;
    1005           0 :     } else if (c + aDiff > max) {
    1006           0 :       aDiff -= (max - c);
    1007           0 :       c = max;
    1008             :     } else {
    1009           0 :       c += aDiff;
    1010           0 :       aDiff = 0;
    1011             :     }
    1012             : 
    1013             :     // there is not space left? We are done
    1014           0 :     if (aDiff == 0)
    1015           0 :       break;
    1016             :   }
    1017             : 
    1018           0 :   aSpaceLeft = aDiff;
    1019           0 : }
    1020             : 
    1021             : /**
    1022             :  * Ok if we want to resize a child we will know the actual size in pixels we want it to be.
    1023             :  * This is not the preferred size. But they only way we can change a child is my manipulating its
    1024             :  * preferred size. So give the actual pixel size this return method will return figure out the preferred
    1025             :  * size and set it.
    1026             :  */
    1027             : 
    1028             : void
    1029           0 : nsSplitterFrameInner::ResizeChildTo(nscoord& aDiff,
    1030             :                                     nsSplitterInfo* aChildrenBeforeInfos,
    1031             :                                     nsSplitterInfo* aChildrenAfterInfos,
    1032             :                                     int32_t aChildrenBeforeCount,
    1033             :                                     int32_t aChildrenAfterCount,
    1034             :                                     bool aBounded)
    1035             : {
    1036             :   nscoord spaceLeft;
    1037           0 :   AddRemoveSpace(aDiff, aChildrenBeforeInfos,aChildrenBeforeCount,spaceLeft);
    1038             : 
    1039             :   // if there is any space left over remove it from the dif we were originally given
    1040           0 :   aDiff -= spaceLeft;
    1041           0 :   AddRemoveSpace(-aDiff, aChildrenAfterInfos,aChildrenAfterCount,spaceLeft);
    1042             : 
    1043           0 :   if (spaceLeft != 0) {
    1044           0 :     if (aBounded) {
    1045           0 :        aDiff += spaceLeft;
    1046           0 :        AddRemoveSpace(spaceLeft, aChildrenBeforeInfos,aChildrenBeforeCount,spaceLeft);
    1047             :     }
    1048             :   }
    1049           0 : }

Generated by: LCOV version 1.13