layout/xul/nsListBoxLayout.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsListBoxLayout.h"
     8 #include "nsListBoxBodyFrame.h"
     9 #include "nsBox.h"
    10 #include "nsBoxLayoutState.h"
    11 #include "nsIScrollableFrame.h"
    12 #include "nsIReflowCallback.h"
    13 #include "nsNameSpaceManager.h"
    14 #include "nsGkAtoms.h"
    15 #include "nsContentUtils.h"
    17 nsListBoxLayout::nsListBoxLayout() : nsGridRowGroupLayout()
    18 {
    19 }
    21 ////////// nsBoxLayout //////////////
    23 nsSize
    24 nsListBoxLayout::GetPrefSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
    25 {
    26   nsSize pref = nsGridRowGroupLayout::GetPrefSize(aBox, aBoxLayoutState);
    28   nsListBoxBodyFrame* frame = static_cast<nsListBoxBodyFrame*>(aBox);
    29   if (frame) {
    30     nscoord rowheight = frame->GetRowHeightAppUnits();
    31     pref.height = frame->GetRowCount() * rowheight;
    32     // Pad the height.
    33     nscoord y = frame->GetAvailableHeight();
    34     if (pref.height > y && y > 0 && rowheight > 0) {
    35       nscoord m = (pref.height-y)%rowheight;
    36       nscoord remainder = m == 0 ? 0 : rowheight - m;
    37       pref.height += remainder;
    38     }
    39     if (nsContentUtils::HasNonEmptyAttr(frame->GetContent(), kNameSpaceID_None,
    40                                         nsGkAtoms::sizemode)) {
    41       nscoord width = frame->ComputeIntrinsicWidth(aBoxLayoutState);
    42       if (width > pref.width)
    43         pref.width = width;
    44     }
    45   }
    46   return pref;
    47 }
    49 nsSize
    50 nsListBoxLayout::GetMinSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
    51 {
    52   nsSize minSize = nsGridRowGroupLayout::GetMinSize(aBox, aBoxLayoutState);
    54   nsListBoxBodyFrame* frame = static_cast<nsListBoxBodyFrame*>(aBox);
    55   if (frame) {
    56     nscoord rowheight = frame->GetRowHeightAppUnits();
    57     minSize.height = frame->GetRowCount() * rowheight;
    58     // Pad the height.
    59     nscoord y = frame->GetAvailableHeight();
    60     if (minSize.height > y && y > 0 && rowheight > 0) {
    61       nscoord m = (minSize.height-y)%rowheight;
    62       nscoord remainder = m == 0 ? 0 : rowheight - m;
    63       minSize.height += remainder;
    64     }
    65     if (nsContentUtils::HasNonEmptyAttr(frame->GetContent(), kNameSpaceID_None,
    66                                         nsGkAtoms::sizemode)) {
    67       nscoord width = frame->ComputeIntrinsicWidth(aBoxLayoutState);
    68       if (width > minSize.width)
    69         minSize.width = width;
    70     }
    71   }
    72   return minSize;
    73 }
    75 nsSize
    76 nsListBoxLayout::GetMaxSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
    77 {
    78   nsSize maxSize = nsGridRowGroupLayout::GetMaxSize(aBox, aBoxLayoutState);
    80   nsListBoxBodyFrame* frame = static_cast<nsListBoxBodyFrame*>(aBox);
    81   if (frame) {
    82     nscoord rowheight = frame->GetRowHeightAppUnits();
    83     maxSize.height = frame->GetRowCount() * rowheight;
    84     // Pad the height.
    85     nscoord y = frame->GetAvailableHeight();
    86     if (maxSize.height > y && y > 0 && rowheight > 0) {
    87       nscoord m = (maxSize.height-y)%rowheight;
    88       nscoord remainder = m == 0 ? 0 : rowheight - m;
    89       maxSize.height += remainder;
    90     }
    91   }
    92   return maxSize;
    93 }
    95 NS_IMETHODIMP
    96 nsListBoxLayout::Layout(nsIFrame* aBox, nsBoxLayoutState& aState)
    97 {
    98   return LayoutInternal(aBox, aState);
    99 }
   102 /////////// nsListBoxLayout /////////////////////////
   104 /**
   105  * Called to layout our our children. Does no frame construction
   106  */
   107 NS_IMETHODIMP
   108 nsListBoxLayout::LayoutInternal(nsIFrame* aBox, nsBoxLayoutState& aState)
   109 {
   110   int32_t redrawStart = -1;
   112   // Get the start y position.
   113   nsListBoxBodyFrame* body = static_cast<nsListBoxBodyFrame*>(aBox);
   114   if (!body) {
   115     NS_ERROR("Frame encountered that isn't a listboxbody!");
   116     return NS_ERROR_FAILURE;
   117   }
   119   nsMargin margin;
   121   // Get our client rect.
   122   nsRect clientRect;
   123   aBox->GetClientRect(clientRect);
   125   // Get the starting y position and the remaining available
   126   // height.
   127   nscoord availableHeight = body->GetAvailableHeight();
   128   nscoord yOffset = body->GetYPosition();
   130   if (availableHeight <= 0) {
   131     bool fixed = (body->GetFixedRowSize() != -1);
   132     if (fixed)
   133       availableHeight = 10;
   134     else
   135       return NS_OK;
   136   }
   138   // run through all our currently created children
   139   nsIFrame* box = body->GetChildBox();
   141   // if the reason is resize or initial we must relayout.
   142   nscoord rowHeight = body->GetRowHeightAppUnits();
   144   while (box) {
   145     // If this box is dirty or if it has dirty children, we
   146     // call layout on it.
   147     nsRect childRect(box->GetRect());
   148     box->GetMargin(margin);
   150     // relayout if we must or we are dirty or some of our children are dirty
   151     //   or the client area is wider than us
   152     // XXXldb There should probably be a resize check here too!
   153     if (NS_SUBTREE_DIRTY(box) || childRect.width < clientRect.width) {
   154       childRect.x = 0;
   155       childRect.y = yOffset;
   156       childRect.width = clientRect.width;
   158       nsSize size = box->GetPrefSize(aState);
   159       body->SetRowHeight(size.height);
   161       childRect.height = rowHeight;
   163       childRect.Deflate(margin);
   164       box->SetBounds(aState, childRect);
   165       box->Layout(aState);
   166     } else {
   167       // if the child did not need to be relayed out. Then its easy.
   168       // Place the child by just grabbing its rect and adjusting the y.
   169       int32_t newPos = yOffset+margin.top;
   171       // are we pushing down or pulling up any rows?
   172       // Then we may have to redraw everything below the moved 
   173       // rows.
   174       if (redrawStart == -1 && childRect.y != newPos)
   175         redrawStart = newPos;
   177       childRect.y = newPos;
   178       box->SetBounds(aState, childRect);
   179     }
   181     // Ok now the available size gets smaller and we move the
   182     // starting position of the next child down some.
   183     nscoord size = childRect.height + margin.top + margin.bottom;
   185     yOffset += size;
   186     availableHeight -= size;
   188     box = box->GetNextBox();
   189   }
   191   // We have enough available height left to add some more rows
   192   // Since we can't do this during layout, we post a callback
   193   // that will be processed after the reflow completes.
   194   body->PostReflowCallback();
   196   // if rows were pushed down or pulled up because some rows were added
   197   // before them then redraw everything under the inserted rows. The inserted
   198   // rows will automatically be redrawn because the were marked dirty on insertion.
   199   if (redrawStart > -1) {
   200     aBox->Redraw(aState);
   201   }
   203   return NS_OK;
   204 }
   206 // Creation Routines ///////////////////////////////////////////////////////////////////////
   208 already_AddRefed<nsBoxLayout> NS_NewListBoxLayout()
   209 {
   210   nsRefPtr<nsBoxLayout> layout = new nsListBoxLayout();
   211   return layout.forget();
   212 } 

mercurial