summaryrefslogtreecommitdiffstats
path: root/layout/xul/nsStackLayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/xul/nsStackLayout.cpp')
-rw-r--r--layout/xul/nsStackLayout.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/layout/xul/nsStackLayout.cpp b/layout/xul/nsStackLayout.cpp
new file mode 100644
index 0000000000..2a377a07f9
--- /dev/null
+++ b/layout/xul/nsStackLayout.cpp
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsStackLayout.h"
+#include "nsCOMPtr.h"
+#include "nsBoxLayoutState.h"
+#include "nsBoxFrame.h"
+#include "nsGkAtoms.h"
+#include "nsIContent.h"
+#include "nsNameSpaceManager.h"
+
+using namespace mozilla;
+
+nsBoxLayout* nsStackLayout::gInstance = nullptr;
+
+nsresult NS_NewStackLayout(nsCOMPtr<nsBoxLayout>& aNewLayout) {
+ if (!nsStackLayout::gInstance) {
+ nsStackLayout::gInstance = new nsStackLayout();
+ NS_IF_ADDREF(nsStackLayout::gInstance);
+ }
+ // we have not instance variables so just return our static one.
+ aNewLayout = nsStackLayout::gInstance;
+ return NS_OK;
+}
+
+/*static*/
+void nsStackLayout::Shutdown() { NS_IF_RELEASE(gInstance); }
+
+nsStackLayout::nsStackLayout() = default;
+
+/*
+ * Sizing: we are as wide as the widest child
+ * we are tall as the tallest child.
+ */
+
+nsSize nsStackLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
+ nsSize prefSize(0, 0);
+
+ nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
+ while (child) {
+ nsSize pref = child->GetXULPrefSize(aState);
+
+ AddXULMargin(child, pref);
+
+ if (pref.width > prefSize.width) {
+ prefSize.width = pref.width;
+ }
+ if (pref.height > prefSize.height) {
+ prefSize.height = pref.height;
+ }
+
+ child = nsIFrame::GetNextXULBox(child);
+ }
+
+ AddXULBorderAndPadding(aBox, prefSize);
+
+ return prefSize;
+}
+
+nsSize nsStackLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
+ nsSize minSize(0, 0);
+
+ nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
+ while (child) {
+ nsSize min = child->GetXULMinSize(aState);
+
+ AddXULMargin(child, min);
+
+ if (min.width > minSize.width) {
+ minSize.width = min.width;
+ }
+ if (min.height > minSize.height) {
+ minSize.height = min.height;
+ }
+
+ child = nsIFrame::GetNextXULBox(child);
+ }
+
+ AddXULBorderAndPadding(aBox, minSize);
+
+ return minSize;
+}
+
+nsSize nsStackLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
+ nsSize maxSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
+
+ nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
+ while (child) {
+ nsSize min = child->GetXULMinSize(aState);
+ nsSize max = child->GetXULMaxSize(aState);
+
+ max = nsIFrame::XULBoundsCheckMinMax(min, max);
+
+ AddXULMargin(child, max);
+
+ if (max.width < maxSize.width) {
+ maxSize.width = max.width;
+ }
+ if (max.height < maxSize.height) {
+ maxSize.height = max.height;
+ }
+
+ child = nsIFrame::GetNextXULBox(child);
+ }
+
+ AddXULBorderAndPadding(aBox, maxSize);
+
+ return maxSize;
+}
+
+nscoord nsStackLayout::GetAscent(nsIFrame* aBox, nsBoxLayoutState& aState) {
+ nscoord vAscent = 0;
+
+ nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
+ while (child) {
+ nscoord ascent = child->GetXULBoxAscent(aState);
+ nsMargin margin;
+ child->GetXULMargin(margin);
+ ascent += margin.top;
+ if (ascent > vAscent) vAscent = ascent;
+
+ child = nsIFrame::GetNextXULBox(child);
+ }
+
+ return vAscent;
+}
+
+NS_IMETHODIMP
+nsStackLayout::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aState) {
+ nsRect clientRect;
+ aBox->GetXULClientRect(clientRect);
+
+ bool grow;
+
+ do {
+ nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
+ grow = false;
+
+ while (child) {
+ nsMargin margin;
+ child->GetXULMargin(margin);
+ nsRect childRect(clientRect);
+ childRect.Deflate(margin);
+
+ if (childRect.width < 0) childRect.width = 0;
+
+ if (childRect.height < 0) childRect.height = 0;
+
+ nsRect oldRect(child->GetRect());
+ bool sizeChanged = !oldRect.IsEqualEdges(childRect);
+
+ // only lay out dirty children or children whose sizes have changed
+ if (sizeChanged || child->IsSubtreeDirty()) {
+ // add in the child's margin
+ nsMargin margin;
+ child->GetXULMargin(margin);
+
+ // Now place the child.
+ child->SetXULBounds(aState, childRect);
+
+ // Flow the child.
+ child->XULLayout(aState);
+
+ // Get the child's new rect.
+ childRect = child->GetRect();
+ childRect.Inflate(margin);
+
+ // Did the child push back on us and get bigger?
+ if (childRect.width > clientRect.width) {
+ clientRect.width = childRect.width;
+ grow = true;
+ }
+
+ if (childRect.height > clientRect.height) {
+ clientRect.height = childRect.height;
+ grow = true;
+ }
+ }
+
+ child = nsIFrame::GetNextXULBox(child);
+ }
+ } while (grow);
+
+ // if some HTML inside us got bigger we need to force ourselves to
+ // get bigger
+ nsRect bounds(aBox->GetRect());
+ nsMargin bp;
+ aBox->GetXULBorderAndPadding(bp);
+ clientRect.Inflate(bp);
+
+ if (clientRect.width > bounds.width || clientRect.height > bounds.height) {
+ if (clientRect.width > bounds.width) bounds.width = clientRect.width;
+ if (clientRect.height > bounds.height) bounds.height = clientRect.height;
+
+ aBox->SetXULBounds(aState, bounds);
+ }
+
+ return NS_OK;
+}