LCOV - app.info - layout/xul/base/src/nsSplitterFrame.cpp

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-04-21 | 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