LCOV - code coverage report
Current view: directory - layout/xul/base/src - nsSplitterFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 468 0 0.0 %
Date: 2012-06-02 Functions: 47 0 0.0 %

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

Generated by: LCOV version 1.7