gecko-dev/layout/xul/base/src/nsBoxFrame.cpp

2668 lines
74 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
1999-03-27 01:35:55 +00:00
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
1999-03-27 01:35:55 +00:00
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
1999-03-27 01:35:55 +00:00
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
1999-03-27 01:35:55 +00:00
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
// How boxes layout
// ----------------
// Boxes layout a bit differently than html. html does a bottom up layout. Where boxes do a top down.
// 1) First thing a box does it goes out and askes each child for its min, max, and preferred sizes.
// 2) It then adds them up to determine its size.
// 3) If the box was asked to layout it self intrinically it will layout its children at their preferred size
// otherwise it will layout the child at the size it was told to. It will squeeze or stretch its children if
// Necessary.
//
// However there is a catch. Some html components like block frames can not determine their preferred size.
// this is their size if they were layed out intrinsically. So the box will flow the child to determine this can
// cache the value.
// Boxes and Incremental Reflow
// ----------------------------
// Boxes layout out top down by adding up their childrens min, max, and preferred sizes. Only problem is if a incremental
// reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change
// any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared
2000-03-31 07:02:06 +00:00
// so when asked for there current size they can relayout themselves.
2000-03-31 07:02:06 +00:00
#include "nsBoxLayoutState.h"
1999-03-27 01:35:55 +00:00
#include "nsBoxFrame.h"
#include "nsStyleContext.h"
#include "nsPresContext.h"
1999-03-27 01:35:55 +00:00
#include "nsCOMPtr.h"
#include "nsUnitConversion.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIContent.h"
#include "nsSpaceManager.h"
#include "nsHTMLParts.h"
#include "nsIViewManager.h"
2000-01-14 10:34:27 +00:00
#include "nsIView.h"
1999-08-19 03:51:25 +00:00
#include "nsIPresShell.h"
#include "nsFrameNavigator.h"
#include "nsCSSRendering.h"
#include "nsIServiceManager.h"
2000-03-31 07:02:06 +00:00
#include "nsBoxToBlockAdaptor.h"
#include "nsIBoxLayout.h"
#include "nsSprocketLayout.h"
#include "nsIDocument.h"
#include "nsIBindingManager.h"
#include "nsIScrollableFrame.h"
2000-06-22 00:48:49 +00:00
#include "nsWidgetsCID.h"
#include "nsLayoutAtoms.h"
#include "nsCSSAnonBoxes.h"
#include "nsViewsCID.h"
#include "nsIScrollableView.h"
2000-09-01 00:59:09 +00:00
#include "nsHTMLContainerFrame.h"
#include "nsIWidget.h"
#include "nsIEventStateManager.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsITheme.h"
#include "nsTransform2D.h"
#include "nsIEventListenerManager.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsContentUtils.h"
2000-06-22 00:48:49 +00:00
// Needed for Print Preview
#include "nsIDocument.h"
#include "nsIURI.h"
2000-06-22 00:48:49 +00:00
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
2000-02-14 01:42:09 +00:00
//define DEBUG_REDRAW
#define DEBUG_SPRING_SIZE 8
#define DEBUG_BORDER_SIZE 2
#define COIL_SIZE 8
2000-02-16 23:00:52 +00:00
//#define TEST_SANITY
#ifdef DEBUG_rods
//#define DO_NOISY_REFLOW
#endif
#ifdef DEBUG_LAYOUT
PRBool nsBoxFrame::gDebug = PR_FALSE;
nsIBox* nsBoxFrame::mDebugChild = nsnull;
#endif
2000-03-31 07:02:06 +00:00
1999-03-27 01:35:55 +00:00
nsresult
NS_NewBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot, nsIBoxLayout* aLayoutManager)
1999-03-27 01:35:55 +00:00
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsBoxFrame* it = new (aPresShell) nsBoxFrame(aPresShell, aIsRoot, aLayoutManager);
2000-03-31 07:02:06 +00:00
1999-03-27 01:35:55 +00:00
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
1999-03-27 01:35:55 +00:00
return NS_OK;
} // NS_NewBoxFrame
nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager)
:nsContainerBox(aPresShell)
1999-03-27 01:35:55 +00:00
{
mState |= NS_STATE_IS_HORIZONTAL;
2000-02-14 01:42:09 +00:00
mState |= NS_STATE_AUTO_STRETCH;
2000-02-16 23:00:52 +00:00
2000-03-31 07:02:06 +00:00
if (aIsRoot)
mState |= NS_STATE_IS_ROOT;
mValign = vAlign_Top;
mHalign = hAlign_Left;
// if no layout manager specified us the static sprocket layout
nsCOMPtr<nsIBoxLayout> layout = aLayoutManager;
if (layout == nsnull) {
NS_NewSprocketLayout(aPresShell, layout);
}
2000-03-31 07:02:06 +00:00
SetLayoutManager(layout);
NeedsRecalc();
}
nsBoxFrame::~nsBoxFrame()
{
1999-03-27 01:35:55 +00:00
}
NS_IMETHODIMP nsBoxFrame::SetParent(const nsIFrame* aParent)
{
nsresult rv = nsContainerFrame::SetParent(aParent);
// our box parent can only be a box. Make sure its a box and set it
// if its not a box then its nsnull
// cast away const so we can call QueryInterface.
nsIFrame* parent = (nsIFrame*)aParent;
// don't use com ptr. Frames don't support ADDREF or RELEASE;
nsIBox* boxParent = nsnull;
if (parent)
parent->QueryInterface(NS_GET_IID(nsIBox), (void**)&boxParent);
nsBox::SetParentBox(boxParent);
return rv;
}
NS_IMETHODIMP
2000-03-31 07:02:06 +00:00
nsBoxFrame::GetVAlign(Valignment& aAlign)
{
aAlign = mValign;
return NS_OK;
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetHAlign(Halignment& aAlign)
{
aAlign = mHalign;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
NS_IMETHODIMP
nsBoxFrame::SetInitialChildList(nsPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
2000-03-31 07:02:06 +00:00
SanityCheck(mFrames);
2000-09-01 00:59:09 +00:00
nsresult r = nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
2000-03-31 07:02:06 +00:00
if (r == NS_OK) {
// initialize our list of infos.
nsBoxLayoutState state(aPresContext->PresShell());
InitChildren(state, aChildList);
CheckFrameOrder();
2000-03-31 07:02:06 +00:00
} else {
NS_WARNING("Warning add child failed!!\n");
2000-03-31 07:02:06 +00:00
}
2000-03-31 07:02:06 +00:00
SanityCheck(mFrames);
return r;
}
2000-03-31 07:02:06 +00:00
PRBool
nsBoxFrame::IsHorizontal() const
{
2000-02-14 01:42:09 +00:00
return mState & NS_STATE_IS_HORIZONTAL;
}
2001-08-15 04:09:41 +00:00
PRBool
nsBoxFrame::IsNormalDirection() const
{
return mState & NS_STATE_IS_DIRECTION_NORMAL;
}
2000-03-31 07:02:06 +00:00
/**
* Initialize us. This is a good time to get the alignment of the box
*/
1999-03-27 01:35:55 +00:00
NS_IMETHODIMP
nsBoxFrame::Init(nsPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow)
1999-03-27 01:35:55 +00:00
{
SetParent(aParent);
mPresContext = aPresContext;
2000-09-01 00:59:09 +00:00
nsresult rv = nsContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
2000-01-08 02:18:14 +00:00
2000-06-22 00:48:49 +00:00
// see if we need a widget. Get our parent. Querty interface the parent we are given.
nsIBox *parent;
if (aParent && NS_SUCCEEDED(CallQueryInterface(aParent, &parent))) {
2000-06-22 00:48:49 +00:00
PRBool needsWidget = PR_FALSE;
parent->ChildrenMustHaveWidgets(needsWidget);
if (needsWidget) {
nsHTMLContainerFrame::CreateViewForFrame(this, nsnull, PR_TRUE);
2000-06-22 00:48:49 +00:00
nsIView* view = GetView();
if (!view->HasWidget())
2000-06-22 00:48:49 +00:00
view->CreateWidget(kWidgetCID);
}
}
CacheAttributes();
#ifdef DEBUG_LAYOUT
// if we are root and this
if (mState & NS_STATE_IS_ROOT)
GetDebugPref(aPresContext);
#endif
2000-02-14 01:42:09 +00:00
mMouseThrough = unset;
2000-03-31 07:02:06 +00:00
UpdateMouseThrough();
// register access key
rv = RegUnregAccessKey(aPresContext, PR_TRUE);
return rv;
}
void nsBoxFrame::UpdateMouseThrough()
{
if (mContent) {
2000-03-31 07:02:06 +00:00
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::mousethrough, value)) {
if (value.EqualsLiteral("never"))
mMouseThrough = never;
else if (value.EqualsLiteral("always"))
mMouseThrough = always;
2000-03-31 07:02:06 +00:00
}
}
2000-02-14 01:42:09 +00:00
}
void
nsBoxFrame::CacheAttributes()
{
/*
printf("Caching: ");
DumpBox(stdout);
printf("\n");
*/
mValign = vAlign_Top;
mHalign = hAlign_Left;
PRBool orient = PR_FALSE;
GetInitialOrientation(orient);
if (orient)
mState |= NS_STATE_IS_HORIZONTAL;
2001-08-02 00:09:27 +00:00
else
mState &= ~NS_STATE_IS_HORIZONTAL;
2001-08-15 04:09:41 +00:00
PRBool normal = PR_TRUE;
GetInitialDirection(normal);
2001-08-15 04:09:41 +00:00
if (normal)
mState |= NS_STATE_IS_DIRECTION_NORMAL;
2001-08-15 04:09:41 +00:00
else
mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
2001-08-15 04:09:41 +00:00
GetInitialVAlignment(mValign);
GetInitialHAlignment(mHalign);
2001-08-02 00:09:27 +00:00
PRBool equalSize = PR_FALSE;
GetInitialEqualSize(equalSize);
if (equalSize)
mState |= NS_STATE_EQUAL_SIZE;
else
mState &= ~NS_STATE_EQUAL_SIZE;
PRBool autostretch = mState & NS_STATE_AUTO_STRETCH;
GetInitialAutoStretch(autostretch);
if (autostretch)
mState |= NS_STATE_AUTO_STRETCH;
else
mState &= ~NS_STATE_AUTO_STRETCH;
#ifdef DEBUG_LAYOUT
PRBool debug = mState & NS_STATE_SET_TO_DEBUG;
PRBool debugSet = GetInitialDebug(debug);
if (debugSet) {
mState |= NS_STATE_DEBUG_WAS_SET;
if (debug)
mState |= NS_STATE_SET_TO_DEBUG;
else
mState &= ~NS_STATE_SET_TO_DEBUG;
} else {
mState &= ~NS_STATE_DEBUG_WAS_SET;
}
#endif
}
#ifdef DEBUG_LAYOUT
PRBool
nsBoxFrame::GetInitialDebug(PRBool& aDebug)
{
2000-03-31 07:02:06 +00:00
nsAutoString value;
nsCOMPtr<nsIContent> content;
GetContentOf(getter_AddRefs(content));
2000-03-31 07:02:06 +00:00
if (!content)
return PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::debug, value)) {
if (value.EqualsLiteral("true")) {
aDebug = PR_TRUE;
return PR_TRUE;
} else if (value.EqualsLiteral("false")) {
aDebug = PR_FALSE;
return PR_TRUE;
}
}
return PR_FALSE;
}
#endif
2000-02-14 01:42:09 +00:00
PRBool
nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment& aHalign)
{
Landing changes Vidur made while the tree was closed for beta1 work, here's a list of the changes. r=me [1] Cutting down the size of content. Made nsIJSScriptObject inherit from nsIScriptObjectOwner [2] Cutting down the size of content. Made nsITextContent inherit from nsIContent. [3] Cutting down the size of content. Moved implementation of nsIDOMReceiver to nsListenerManager. This is not true aggregation since it isn't transitive, but it's OK for now. It will be necessary for nsListenerManager to have a reference to its content in the future anyway, so the transitivity could be done. dom/public/nsDOMPropEnums.h,v - bug 12559 dom/public/nsIJSScriptObject.h,v - [1] dom/public/html/MANIFEST,v - bug 12559 dom/public/html/Makefile.in,v - bug 12559 dom/public/html/makefile.win,v - bug 12559 dom/public/html/nsIDOMHTMLInputElement.h,v - bug 17544 dom/public/idl/html/HTMLAnchorElement.idl,v - bug 12559 dom/public/idl/html/HTMLAreaElement.idl,v - bug 12559 dom/public/idl/html/HTMLInputElement.idl,v - bug 17544 dom/src/base/nsGlobalWindow.cpp,v - bug 30700 dom/src/base/nsGlobalWindow.h,v - [1] dom/src/base/nsLocation.cpp,v - [1] dom/src/html/nsJSHTMLAnchorElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLAreaElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLInputElement.cpp,v - bug 17544 layout/base/public/nsIDocument.h,v - bug 27953 layout/base/public/nsITextContent.h,v - [2] layout/base/src/nsCommentNode.cpp,v - [2] layout/base/src/nsDocument.cpp,v - bug 27953 layout/base/src/nsDocument.h,v - bug 27953 layout/base/src/nsDocumentViewer.cpp,v - bug 27953 layout/base/src/nsGenericDOMDataNode.cpp,v - [3] layout/base/src/nsGenericDOMDataNode.h,v - [3] layout/base/src/nsGenericElement.cpp,v - [3] layout/base/src/nsGenericElement.h,v - [3] layout/base/src/nsNameSpaceManager.cpp,v - bug 7834 layout/base/src/nsStyleContext.cpp,v - outline property shouldn't reflow layout/base/src/nsTextNode.cpp,v - [2] layout/events/src/nsEventListenerManager.cpp,v - [3] layout/events/src/nsEventListenerManager.h,v - [3] layout/html/base/src/nsGfxScrollFrame.cpp,v - nsString->nsAutoString layout/html/content/src/nsAttributeContent.cpp,v - [2] layout/html/content/src/nsHTMLAnchorElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAppletElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBodyElement.cpp,v - [1][3] layout/html/content/src/nsHTMLButtonElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDirectoryElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDivElement.cpp,v - [1][3] layout/html/content/src/nsHTMLEmbedElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFieldSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFormElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadingElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHtmlElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLImageElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInputElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInsElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIsIndexElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLIElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLabelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLayerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLegendElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLinkElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMapElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMenuElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMetaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLModElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLObjectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParagraphElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParamElement.cpp,v - [1][3] layout/html/content/src/nsHTMLPreElement.cpp,v - [1][3] layout/html/content/src/nsHTMLQuoteElement.cpp,v - [1][3] layout/html/content/src/nsHTMLScriptElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSelectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpacerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpanElement.cpp,v - [1][3] layout/html/content/src/nsHTMLStyleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCaptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCellElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableRowElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableSectionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTextAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTitleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLUListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLWBRElement.cpp,v - [1][3] layout/html/document/src/nsHTMLDocument.cpp,v - bug 27953 layout/html/document/src/nsHTMLDocument.h,v - bug 27953 layout/xml/content/src/nsXMLCDATASection.cpp,v - [1][2] layout/xml/content/src/nsXMLDocumentType.cpp,v - [1][2] layout/xml/content/src/nsXMLElement.h,v - [1][2] layout/xml/content/src/nsXMLEntity.cpp,v - [1][2] layout/xml/content/src/nsXMLNotation.cpp,v - [1][2] layout/xml/content/src/nsXMLProcessingInstruction.cpp,v - [1][2] layout/xul/base/src/nsBoxFrame.cpp,v - nsString->nsAutoString layout/xul/base/src/nsSliderFrame.cpp,v - nsString->nsAutoString netwerk/protocol/http/src/nsHTTPRequest.cpp,v - nsString->nsAutoString rdf/content/src/nsXULDocument.cpp,v - bug 27953 rdf/content/src/nsXULDocument.h,v - bug 27953 rdf/content/src/nsXULElement.h,v - [1] xpcom/base/IIDS.h,v - bug 12559
2000-03-17 13:27:00 +00:00
nsAutoString value;
nsCOMPtr<nsIContent> content;
2000-03-31 07:02:06 +00:00
GetContentOf(getter_AddRefs(content));
if (!content)
return PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value)) {
2001-08-02 00:09:27 +00:00
// XXXdwh Everything inside this if statement is deprecated code.
if (value.EqualsLiteral("left")) {
2001-08-02 00:09:27 +00:00
aHalign = nsBoxFrame::hAlign_Left;
return PR_TRUE;
} else if (value.EqualsLiteral("right")) {
2001-08-02 00:09:27 +00:00
aHalign = nsBoxFrame::hAlign_Right;
return PR_TRUE;
}
}
2001-08-02 00:09:27 +00:00
// Now that the deprecated stuff is out of the way, we move on to check the appropriate
// attribute. For horizontal boxes, we are checking the PACK attribute. For vertical boxes
// we are checking the ALIGN attribute.
nsresult res;
if (IsHorizontal())
res = content->GetAttr(kNameSpaceID_None, nsXULAtoms::pack, value);
else res = content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value);
2001-08-02 00:09:27 +00:00
if (res == NS_CONTENT_ATTR_HAS_VALUE) {
if (value.EqualsLiteral("start")) {
2001-08-02 00:09:27 +00:00
aHalign = nsBoxFrame::hAlign_Left;
return PR_TRUE;
} else if (value.EqualsLiteral("center")) {
2001-08-02 00:09:27 +00:00
aHalign = nsBoxFrame::hAlign_Center;
return PR_TRUE;
} else if (value.EqualsLiteral("end")) {
2001-08-02 00:09:27 +00:00
aHalign = nsBoxFrame::hAlign_Right;
return PR_TRUE;
}
2001-08-02 00:09:27 +00:00
// The attr was present but had a nonsensical value. Revert to the default.
return PR_FALSE;
}
2000-02-14 01:42:09 +00:00
2001-08-02 00:09:27 +00:00
// Now that we've checked for the attribute it's time to check CSS. For
// horizontal boxes we're checking PACK. For vertical boxes we are checking
// ALIGN.
const nsStyleXUL* boxInfo = GetStyleXUL();
2001-08-02 00:09:27 +00:00
if (IsHorizontal()) {
switch (boxInfo->mBoxPack) {
case NS_STYLE_BOX_PACK_START:
aHalign = nsBoxFrame::hAlign_Left;
return PR_TRUE;
case NS_STYLE_BOX_PACK_CENTER:
aHalign = nsBoxFrame::hAlign_Center;
return PR_TRUE;
case NS_STYLE_BOX_PACK_END:
aHalign = nsBoxFrame::hAlign_Right;
return PR_TRUE;
default: // Nonsensical value. Just bail.
return PR_FALSE;
}
}
else {
switch (boxInfo->mBoxAlign) {
case NS_STYLE_BOX_ALIGN_START:
aHalign = nsBoxFrame::hAlign_Left;
return PR_TRUE;
case NS_STYLE_BOX_ALIGN_CENTER:
aHalign = nsBoxFrame::hAlign_Center;
return PR_TRUE;
case NS_STYLE_BOX_ALIGN_END:
aHalign = nsBoxFrame::hAlign_Right;
return PR_TRUE;
default: // Nonsensical value. Just bail.
return PR_FALSE;
}
}
2000-02-14 01:42:09 +00:00
return PR_FALSE;
}
PRBool
nsBoxFrame::GetInitialVAlignment(nsBoxFrame::Valignment& aValign)
{
Landing changes Vidur made while the tree was closed for beta1 work, here's a list of the changes. r=me [1] Cutting down the size of content. Made nsIJSScriptObject inherit from nsIScriptObjectOwner [2] Cutting down the size of content. Made nsITextContent inherit from nsIContent. [3] Cutting down the size of content. Moved implementation of nsIDOMReceiver to nsListenerManager. This is not true aggregation since it isn't transitive, but it's OK for now. It will be necessary for nsListenerManager to have a reference to its content in the future anyway, so the transitivity could be done. dom/public/nsDOMPropEnums.h,v - bug 12559 dom/public/nsIJSScriptObject.h,v - [1] dom/public/html/MANIFEST,v - bug 12559 dom/public/html/Makefile.in,v - bug 12559 dom/public/html/makefile.win,v - bug 12559 dom/public/html/nsIDOMHTMLInputElement.h,v - bug 17544 dom/public/idl/html/HTMLAnchorElement.idl,v - bug 12559 dom/public/idl/html/HTMLAreaElement.idl,v - bug 12559 dom/public/idl/html/HTMLInputElement.idl,v - bug 17544 dom/src/base/nsGlobalWindow.cpp,v - bug 30700 dom/src/base/nsGlobalWindow.h,v - [1] dom/src/base/nsLocation.cpp,v - [1] dom/src/html/nsJSHTMLAnchorElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLAreaElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLInputElement.cpp,v - bug 17544 layout/base/public/nsIDocument.h,v - bug 27953 layout/base/public/nsITextContent.h,v - [2] layout/base/src/nsCommentNode.cpp,v - [2] layout/base/src/nsDocument.cpp,v - bug 27953 layout/base/src/nsDocument.h,v - bug 27953 layout/base/src/nsDocumentViewer.cpp,v - bug 27953 layout/base/src/nsGenericDOMDataNode.cpp,v - [3] layout/base/src/nsGenericDOMDataNode.h,v - [3] layout/base/src/nsGenericElement.cpp,v - [3] layout/base/src/nsGenericElement.h,v - [3] layout/base/src/nsNameSpaceManager.cpp,v - bug 7834 layout/base/src/nsStyleContext.cpp,v - outline property shouldn't reflow layout/base/src/nsTextNode.cpp,v - [2] layout/events/src/nsEventListenerManager.cpp,v - [3] layout/events/src/nsEventListenerManager.h,v - [3] layout/html/base/src/nsGfxScrollFrame.cpp,v - nsString->nsAutoString layout/html/content/src/nsAttributeContent.cpp,v - [2] layout/html/content/src/nsHTMLAnchorElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAppletElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBodyElement.cpp,v - [1][3] layout/html/content/src/nsHTMLButtonElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDirectoryElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDivElement.cpp,v - [1][3] layout/html/content/src/nsHTMLEmbedElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFieldSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFormElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadingElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHtmlElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLImageElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInputElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInsElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIsIndexElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLIElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLabelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLayerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLegendElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLinkElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMapElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMenuElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMetaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLModElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLObjectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParagraphElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParamElement.cpp,v - [1][3] layout/html/content/src/nsHTMLPreElement.cpp,v - [1][3] layout/html/content/src/nsHTMLQuoteElement.cpp,v - [1][3] layout/html/content/src/nsHTMLScriptElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSelectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpacerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpanElement.cpp,v - [1][3] layout/html/content/src/nsHTMLStyleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCaptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCellElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableRowElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableSectionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTextAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTitleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLUListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLWBRElement.cpp,v - [1][3] layout/html/document/src/nsHTMLDocument.cpp,v - bug 27953 layout/html/document/src/nsHTMLDocument.h,v - bug 27953 layout/xml/content/src/nsXMLCDATASection.cpp,v - [1][2] layout/xml/content/src/nsXMLDocumentType.cpp,v - [1][2] layout/xml/content/src/nsXMLElement.h,v - [1][2] layout/xml/content/src/nsXMLEntity.cpp,v - [1][2] layout/xml/content/src/nsXMLNotation.cpp,v - [1][2] layout/xml/content/src/nsXMLProcessingInstruction.cpp,v - [1][2] layout/xul/base/src/nsBoxFrame.cpp,v - nsString->nsAutoString layout/xul/base/src/nsSliderFrame.cpp,v - nsString->nsAutoString netwerk/protocol/http/src/nsHTTPRequest.cpp,v - nsString->nsAutoString rdf/content/src/nsXULDocument.cpp,v - bug 27953 rdf/content/src/nsXULDocument.h,v - bug 27953 rdf/content/src/nsXULElement.h,v - [1] xpcom/base/IIDS.h,v - bug 12559
2000-03-17 13:27:00 +00:00
nsAutoString value;
2000-02-14 01:42:09 +00:00
nsCOMPtr<nsIContent> content;
2000-03-31 07:02:06 +00:00
GetContentOf(getter_AddRefs(content));
if (!content)
return PR_FALSE;
2000-02-14 01:42:09 +00:00
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::valign, value)) {
if (value.EqualsLiteral("top")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_Top;
return PR_TRUE;
} else if (value.EqualsLiteral("baseline")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_BaseLine;
return PR_TRUE;
} else if (value.EqualsLiteral("middle")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_Middle;
return PR_TRUE;
} else if (value.EqualsLiteral("bottom")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_Bottom;
return PR_TRUE;
}
}
2001-08-02 00:09:27 +00:00
// Now that the deprecated stuff is out of the way, we move on to check the appropriate
// attribute. For horizontal boxes, we are checking the ALIGN attribute. For vertical boxes
// we are checking the PACK attribute.
nsresult res;
if (IsHorizontal())
res = content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value);
else res = content->GetAttr(kNameSpaceID_None, nsXULAtoms::pack, value);
2001-08-02 00:09:27 +00:00
if (res == NS_CONTENT_ATTR_HAS_VALUE) {
if (value.EqualsLiteral("start")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_Top;
return PR_TRUE;
} else if (value.EqualsLiteral("center")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_Middle;
return PR_TRUE;
} else if (value.EqualsLiteral("baseline")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_BaseLine;
return PR_TRUE;
} else if (value.EqualsLiteral("end")) {
2001-08-02 00:09:27 +00:00
aValign = nsBoxFrame::vAlign_Bottom;
return PR_TRUE;
}
// The attr was present but had a nonsensical value. Revert to the default.
return PR_FALSE;
}
// Now that we've checked for the attribute it's time to check CSS. For
// horizontal boxes we're checking ALIGN. For vertical boxes we are checking
// PACK.
const nsStyleXUL* boxInfo = GetStyleXUL();
2001-08-02 00:09:27 +00:00
if (IsHorizontal()) {
switch (boxInfo->mBoxAlign) {
case NS_STYLE_BOX_ALIGN_START:
aValign = nsBoxFrame::vAlign_Top;
return PR_TRUE;
case NS_STYLE_BOX_ALIGN_CENTER:
aValign = nsBoxFrame::vAlign_Middle;
return PR_TRUE;
case NS_STYLE_BOX_ALIGN_BASELINE:
aValign = nsBoxFrame::vAlign_BaseLine;
return PR_TRUE;
case NS_STYLE_BOX_ALIGN_END:
aValign = nsBoxFrame::vAlign_Bottom;
return PR_TRUE;
default: // Nonsensical value. Just bail.
return PR_FALSE;
}
}
else {
switch (boxInfo->mBoxPack) {
case NS_STYLE_BOX_PACK_START:
aValign = nsBoxFrame::vAlign_Top;
return PR_TRUE;
case NS_STYLE_BOX_PACK_CENTER:
aValign = nsBoxFrame::vAlign_Middle;
return PR_TRUE;
case NS_STYLE_BOX_PACK_END:
aValign = nsBoxFrame::vAlign_Bottom;
return PR_TRUE;
default: // Nonsensical value. Just bail.
return PR_FALSE;
}
}
2000-02-14 01:42:09 +00:00
return PR_FALSE;
}
2000-02-14 01:42:09 +00:00
/* Returns true if it was set.
*/
void
2000-02-14 01:42:09 +00:00
nsBoxFrame::GetInitialOrientation(PRBool& aIsHorizontal)
{
// see if we are a vertical or horizontal box.
Landing changes Vidur made while the tree was closed for beta1 work, here's a list of the changes. r=me [1] Cutting down the size of content. Made nsIJSScriptObject inherit from nsIScriptObjectOwner [2] Cutting down the size of content. Made nsITextContent inherit from nsIContent. [3] Cutting down the size of content. Moved implementation of nsIDOMReceiver to nsListenerManager. This is not true aggregation since it isn't transitive, but it's OK for now. It will be necessary for nsListenerManager to have a reference to its content in the future anyway, so the transitivity could be done. dom/public/nsDOMPropEnums.h,v - bug 12559 dom/public/nsIJSScriptObject.h,v - [1] dom/public/html/MANIFEST,v - bug 12559 dom/public/html/Makefile.in,v - bug 12559 dom/public/html/makefile.win,v - bug 12559 dom/public/html/nsIDOMHTMLInputElement.h,v - bug 17544 dom/public/idl/html/HTMLAnchorElement.idl,v - bug 12559 dom/public/idl/html/HTMLAreaElement.idl,v - bug 12559 dom/public/idl/html/HTMLInputElement.idl,v - bug 17544 dom/src/base/nsGlobalWindow.cpp,v - bug 30700 dom/src/base/nsGlobalWindow.h,v - [1] dom/src/base/nsLocation.cpp,v - [1] dom/src/html/nsJSHTMLAnchorElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLAreaElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLInputElement.cpp,v - bug 17544 layout/base/public/nsIDocument.h,v - bug 27953 layout/base/public/nsITextContent.h,v - [2] layout/base/src/nsCommentNode.cpp,v - [2] layout/base/src/nsDocument.cpp,v - bug 27953 layout/base/src/nsDocument.h,v - bug 27953 layout/base/src/nsDocumentViewer.cpp,v - bug 27953 layout/base/src/nsGenericDOMDataNode.cpp,v - [3] layout/base/src/nsGenericDOMDataNode.h,v - [3] layout/base/src/nsGenericElement.cpp,v - [3] layout/base/src/nsGenericElement.h,v - [3] layout/base/src/nsNameSpaceManager.cpp,v - bug 7834 layout/base/src/nsStyleContext.cpp,v - outline property shouldn't reflow layout/base/src/nsTextNode.cpp,v - [2] layout/events/src/nsEventListenerManager.cpp,v - [3] layout/events/src/nsEventListenerManager.h,v - [3] layout/html/base/src/nsGfxScrollFrame.cpp,v - nsString->nsAutoString layout/html/content/src/nsAttributeContent.cpp,v - [2] layout/html/content/src/nsHTMLAnchorElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAppletElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBodyElement.cpp,v - [1][3] layout/html/content/src/nsHTMLButtonElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDirectoryElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDivElement.cpp,v - [1][3] layout/html/content/src/nsHTMLEmbedElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFieldSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFormElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadingElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHtmlElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLImageElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInputElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInsElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIsIndexElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLIElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLabelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLayerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLegendElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLinkElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMapElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMenuElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMetaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLModElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLObjectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParagraphElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParamElement.cpp,v - [1][3] layout/html/content/src/nsHTMLPreElement.cpp,v - [1][3] layout/html/content/src/nsHTMLQuoteElement.cpp,v - [1][3] layout/html/content/src/nsHTMLScriptElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSelectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpacerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpanElement.cpp,v - [1][3] layout/html/content/src/nsHTMLStyleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCaptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCellElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableRowElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableSectionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTextAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTitleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLUListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLWBRElement.cpp,v - [1][3] layout/html/document/src/nsHTMLDocument.cpp,v - bug 27953 layout/html/document/src/nsHTMLDocument.h,v - bug 27953 layout/xml/content/src/nsXMLCDATASection.cpp,v - [1][2] layout/xml/content/src/nsXMLDocumentType.cpp,v - [1][2] layout/xml/content/src/nsXMLElement.h,v - [1][2] layout/xml/content/src/nsXMLEntity.cpp,v - [1][2] layout/xml/content/src/nsXMLNotation.cpp,v - [1][2] layout/xml/content/src/nsXMLProcessingInstruction.cpp,v - [1][2] layout/xul/base/src/nsBoxFrame.cpp,v - nsString->nsAutoString layout/xul/base/src/nsSliderFrame.cpp,v - nsString->nsAutoString netwerk/protocol/http/src/nsHTTPRequest.cpp,v - nsString->nsAutoString rdf/content/src/nsXULDocument.cpp,v - bug 27953 rdf/content/src/nsXULDocument.h,v - bug 27953 rdf/content/src/nsXULElement.h,v - [1] xpcom/base/IIDS.h,v - bug 12559
2000-03-17 13:27:00 +00:00
nsAutoString value;
1999-10-12 00:16:06 +00:00
nsCOMPtr<nsIContent> content;
2000-03-31 07:02:06 +00:00
GetContentOf(getter_AddRefs(content));
if (!content)
return;
// Check the style system first.
const nsStyleXUL* boxInfo = GetStyleXUL();
if (boxInfo->mBoxOrient == NS_STYLE_BOX_ORIENT_HORIZONTAL)
aIsHorizontal = PR_TRUE;
else
aIsHorizontal = PR_FALSE;
// Now see if we have an attribute. The attribute overrides
// the style system value.
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::orient, value)) {
if (value.EqualsLiteral("vertical"))
aIsHorizontal = PR_FALSE;
else if (value.EqualsLiteral("horizontal"))
aIsHorizontal = PR_TRUE;
}
2000-02-14 01:42:09 +00:00
}
2001-08-15 04:09:41 +00:00
void
nsBoxFrame::GetInitialDirection(PRBool& aIsNormal)
{
nsAutoString value;
nsCOMPtr<nsIContent> content;
GetContentOf(getter_AddRefs(content));
if (!content)
return;
if (IsHorizontal()) {
// For horizontal boxes only, we initialize our value based off the CSS 'direction' property.
// This means that BiDI users will end up with horizontally inverted chrome.
aIsNormal = (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR); // If text runs RTL then so do we.
2001-08-15 04:09:41 +00:00
}
else
aIsNormal = PR_TRUE; // Assume a normal direction in the vertical case.
// Now check the style system to see if we should invert aIsNormal.
const nsStyleXUL* boxInfo = GetStyleXUL();
2001-08-15 04:09:41 +00:00
if (boxInfo->mBoxDirection == NS_STYLE_BOX_DIRECTION_REVERSE)
aIsNormal = !aIsNormal; // Invert our direction.
// Now see if we have an attribute. The attribute overrides
// the style system value.
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::dir, value)) {
if (value.EqualsLiteral("reverse"))
2001-08-15 04:09:41 +00:00
aIsNormal = !aIsNormal; // Invert our direction.
else if (value.EqualsLiteral("ltr"))
2001-08-15 04:24:37 +00:00
aIsNormal = PR_TRUE;
else if (value.EqualsLiteral("rtl"))
2001-08-15 04:24:37 +00:00
aIsNormal = PR_FALSE;
2001-08-15 04:09:41 +00:00
}
}
/* Returns true if it was set.
*/
PRBool
nsBoxFrame::GetInitialEqualSize(PRBool& aEqualSize)
{
// see if we are a vertical or horizontal box.
nsAutoString value;
nsCOMPtr<nsIContent> content;
GetContentOf(getter_AddRefs(content));
if (!content)
return PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::equalsize, value))
{
if (value.EqualsLiteral("always")) {
aEqualSize = PR_TRUE;
return PR_TRUE;
}
}
return PR_FALSE;
}
2000-02-14 01:42:09 +00:00
/* Returns true if it was set.
*/
PRBool
nsBoxFrame::GetInitialAutoStretch(PRBool& aStretch)
{
Landing changes Vidur made while the tree was closed for beta1 work, here's a list of the changes. r=me [1] Cutting down the size of content. Made nsIJSScriptObject inherit from nsIScriptObjectOwner [2] Cutting down the size of content. Made nsITextContent inherit from nsIContent. [3] Cutting down the size of content. Moved implementation of nsIDOMReceiver to nsListenerManager. This is not true aggregation since it isn't transitive, but it's OK for now. It will be necessary for nsListenerManager to have a reference to its content in the future anyway, so the transitivity could be done. dom/public/nsDOMPropEnums.h,v - bug 12559 dom/public/nsIJSScriptObject.h,v - [1] dom/public/html/MANIFEST,v - bug 12559 dom/public/html/Makefile.in,v - bug 12559 dom/public/html/makefile.win,v - bug 12559 dom/public/html/nsIDOMHTMLInputElement.h,v - bug 17544 dom/public/idl/html/HTMLAnchorElement.idl,v - bug 12559 dom/public/idl/html/HTMLAreaElement.idl,v - bug 12559 dom/public/idl/html/HTMLInputElement.idl,v - bug 17544 dom/src/base/nsGlobalWindow.cpp,v - bug 30700 dom/src/base/nsGlobalWindow.h,v - [1] dom/src/base/nsLocation.cpp,v - [1] dom/src/html/nsJSHTMLAnchorElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLAreaElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLInputElement.cpp,v - bug 17544 layout/base/public/nsIDocument.h,v - bug 27953 layout/base/public/nsITextContent.h,v - [2] layout/base/src/nsCommentNode.cpp,v - [2] layout/base/src/nsDocument.cpp,v - bug 27953 layout/base/src/nsDocument.h,v - bug 27953 layout/base/src/nsDocumentViewer.cpp,v - bug 27953 layout/base/src/nsGenericDOMDataNode.cpp,v - [3] layout/base/src/nsGenericDOMDataNode.h,v - [3] layout/base/src/nsGenericElement.cpp,v - [3] layout/base/src/nsGenericElement.h,v - [3] layout/base/src/nsNameSpaceManager.cpp,v - bug 7834 layout/base/src/nsStyleContext.cpp,v - outline property shouldn't reflow layout/base/src/nsTextNode.cpp,v - [2] layout/events/src/nsEventListenerManager.cpp,v - [3] layout/events/src/nsEventListenerManager.h,v - [3] layout/html/base/src/nsGfxScrollFrame.cpp,v - nsString->nsAutoString layout/html/content/src/nsAttributeContent.cpp,v - [2] layout/html/content/src/nsHTMLAnchorElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAppletElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBodyElement.cpp,v - [1][3] layout/html/content/src/nsHTMLButtonElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDirectoryElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDivElement.cpp,v - [1][3] layout/html/content/src/nsHTMLEmbedElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFieldSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFormElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadingElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHtmlElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLImageElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInputElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInsElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIsIndexElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLIElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLabelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLayerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLegendElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLinkElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMapElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMenuElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMetaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLModElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLObjectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParagraphElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParamElement.cpp,v - [1][3] layout/html/content/src/nsHTMLPreElement.cpp,v - [1][3] layout/html/content/src/nsHTMLQuoteElement.cpp,v - [1][3] layout/html/content/src/nsHTMLScriptElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSelectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpacerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpanElement.cpp,v - [1][3] layout/html/content/src/nsHTMLStyleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCaptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCellElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableRowElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableSectionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTextAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTitleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLUListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLWBRElement.cpp,v - [1][3] layout/html/document/src/nsHTMLDocument.cpp,v - bug 27953 layout/html/document/src/nsHTMLDocument.h,v - bug 27953 layout/xml/content/src/nsXMLCDATASection.cpp,v - [1][2] layout/xml/content/src/nsXMLDocumentType.cpp,v - [1][2] layout/xml/content/src/nsXMLElement.h,v - [1][2] layout/xml/content/src/nsXMLEntity.cpp,v - [1][2] layout/xml/content/src/nsXMLNotation.cpp,v - [1][2] layout/xml/content/src/nsXMLProcessingInstruction.cpp,v - [1][2] layout/xul/base/src/nsBoxFrame.cpp,v - nsString->nsAutoString layout/xul/base/src/nsSliderFrame.cpp,v - nsString->nsAutoString netwerk/protocol/http/src/nsHTTPRequest.cpp,v - nsString->nsAutoString rdf/content/src/nsXULDocument.cpp,v - bug 27953 rdf/content/src/nsXULDocument.h,v - bug 27953 rdf/content/src/nsXULElement.h,v - [1] xpcom/base/IIDS.h,v - bug 12559
2000-03-17 13:27:00 +00:00
nsAutoString value;
2000-02-14 01:42:09 +00:00
nsCOMPtr<nsIContent> content;
2000-03-31 07:02:06 +00:00
GetContentOf(getter_AddRefs(content));
if (!content)
return PR_FALSE;
// Check the align attribute.
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value)) {
aStretch = value.EqualsLiteral("stretch");
return PR_TRUE;
2001-08-02 00:09:27 +00:00
}
2000-02-14 01:42:09 +00:00
// Check the CSS box-align property.
const nsStyleXUL* boxInfo = GetStyleXUL();
aStretch = (boxInfo->mBoxAlign == NS_STYLE_BOX_ALIGN_STRETCH);
2001-08-02 00:09:27 +00:00
return PR_TRUE;
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
{
// if we receive a ReflowDirtyChild it is because there is an HTML frame
// just inside us. So must find the adaptor that contains the child and
// tell it that things are dirty.
nsCOMPtr<nsPresContext> context;
aPresShell->GetPresContext(getter_AddRefs(context));
nsBoxLayoutState state(context);
nsIBox* box = nsnull;
GetChildBox(&box);
while (box)
{
nsIFrame* frame = nsnull;
box->GetFrame(&frame);
if (frame == aChild) {
box->MarkDirty(state);
return RelayoutDirtyChild(state, box);
}
box->GetNextBox(&box);
}
NS_ERROR("Could not find an adaptor!");
return NS_OK;
2000-03-31 07:02:06 +00:00
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus)
{
2003-06-01 20:03:13 +00:00
nsFrameState preserveBits =
mState & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
nsresult rv = nsFrame::DidReflow(aPresContext, aReflowState, aStatus);
2003-06-01 20:03:13 +00:00
mState |= preserveBits;
2000-03-31 07:02:06 +00:00
return rv;
}
#ifdef DO_NOISY_REFLOW
static int myCounter = 0;
static void printSize(char * aDesc, nscoord aSize)
{
printf(" %s: ", aDesc);
if (aSize == NS_UNCONSTRAINEDSIZE) {
printf("UC");
} else {
printf("%d", aSize);
}
}
#endif
/**
* Returns PR_TRUE when the reflow reason is "Initial" and doing Print Preview
* when returning PR_FALSE aIsChrome's value is indeterminate
* aIsChrome - Returns PR_TRUE when document is chrome, otherwise PR_FALSE
*/
PRBool
nsBoxFrame::IsInitialReflowForPrintPreview(nsBoxLayoutState& aState,
PRBool& aIsChrome)
{
aIsChrome = PR_FALSE;
const nsHTMLReflowState* reflowState = aState.GetReflowState();
if (reflowState->reason == eReflowReason_Initial) {
// See if we are doing Print Preview
if (aState.PresContext()->Type() == nsPresContext::eContext_PrintPreview) {
// Now, get the current URI to see if we doing chrome
nsIPresShell *presShell = aState.PresShell();
if (!presShell) return PR_FALSE;
nsIDocument *doc = presShell->GetDocument();
if (!doc) return PR_FALSE;
nsIURI *uri = doc->GetDocumentURI();
if (!uri) return PR_FALSE;
uri->SchemeIs("chrome", &aIsChrome);
return PR_TRUE;
}
}
return PR_FALSE;
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
1999-03-27 01:35:55 +00:00
{
// If you make changes to this method, please keep nsLeafBoxFrame::Reflow
// in sync, if the changes are applicable there.
DO_GLOBAL_REFLOW_COUNT("nsBoxFrame", aReflowState.reason);
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
1999-03-27 01:35:55 +00:00
2000-03-31 07:02:06 +00:00
NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0");
#ifdef DO_NOISY_REFLOW
printf("\n-------------Starting BoxFrame Reflow ----------------------------\n");
printf("%p ** nsBF::Reflow %d R: ", this, myCounter++);
switch (aReflowState.reason) {
case eReflowReason_Initial:
printf("Ini");break;
case eReflowReason_Incremental:
printf("Inc");break;
case eReflowReason_Resize:
printf("Rsz");break;
case eReflowReason_StyleChange:
printf("Sty");break;
case eReflowReason_Dirty:
printf("Drt ");
break;
default:printf("<unknown>%d", aReflowState.reason);break;
}
printSize("AW", aReflowState.availableWidth);
printSize("AH", aReflowState.availableHeight);
printSize("CW", aReflowState.mComputedWidth);
printSize("CH", aReflowState.mComputedHeight);
printf(" *\n");
#endif
2000-03-31 07:02:06 +00:00
aStatus = NS_FRAME_COMPLETE;
2000-03-31 07:02:06 +00:00
// create the layout state
nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize);
2000-03-31 07:02:06 +00:00
// coelesce reflows if we are root.
state.HandleReflow(this);
2000-03-31 07:02:06 +00:00
nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight);
1999-09-13 20:24:20 +00:00
2000-03-31 07:02:06 +00:00
nsMargin m;
m = aReflowState.mComputedBorderPadding;
// GetBorderAndPadding(m);
1999-08-30 22:32:25 +00:00
2000-03-31 07:02:06 +00:00
nsSize prefSize(0,0);
1999-09-13 20:24:20 +00:00
2000-03-31 07:02:06 +00:00
// if we are told to layout intrinic then get our preferred size.
if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
nsSize minSize(0,0);
nsSize maxSize(0,0);
2000-03-31 07:02:06 +00:00
GetPrefSize(state, prefSize);
GetMinSize(state, minSize);
GetMaxSize(state, maxSize);
BoundsCheck(minSize, prefSize, maxSize);
}
2000-03-31 07:02:06 +00:00
// get our desiredSize
if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) {
computedSize.width = prefSize.width;
} else {
computedSize.width += m.left + m.right;
}
if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) {
computedSize.height = prefSize.height;
} else {
computedSize.height += m.top + m.bottom;
}
// handle reflow state min and max sizes
if (computedSize.width > aReflowState.mComputedMaxWidth)
computedSize.width = aReflowState.mComputedMaxWidth;
if (computedSize.height > aReflowState.mComputedMaxHeight)
computedSize.height = aReflowState.mComputedMaxHeight;
if (computedSize.width < aReflowState.mComputedMinWidth)
computedSize.width = aReflowState.mComputedMinWidth;
if (computedSize.height < aReflowState.mComputedMinHeight)
computedSize.height = aReflowState.mComputedMinHeight;
nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
2000-03-31 07:02:06 +00:00
SetBounds(state, r);
// layout our children
Layout(state);
// ok our child could have gotten bigger. So lets get its bounds
GetBounds(r);
// get the ascent
nscoord ascent = r.height;
2000-03-31 07:02:06 +00:00
// getting the ascent could be a lot of work. Don't get it if
// we are the root. The viewport doesn't care about it.
if (!(mState & NS_STATE_IS_ROOT)) {
// Only call GetAscent when not doing Initial reflow while in PP
// or when it is Initial reflow while in PP and a chrome doc
// If called again with initial reflow it crashes because the
// frames are fully constructed (I think).
PRBool isChrome;
PRBool isInitialPP = IsInitialReflowForPrintPreview(state, isChrome);
if (!isInitialPP || (isInitialPP && isChrome)) {
GetAscent(state, ascent);
}
}
2000-03-31 07:02:06 +00:00
aDesiredSize.width = r.width;
aDesiredSize.height = r.height;
aDesiredSize.ascent = ascent;
aDesiredSize.descent = r.height - ascent;
// NS_FRAME_OUTSIDE_CHILDREN is set in SetBounds() above
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
nsRect* overflowArea = GetOverflowAreaProperty();
NS_ASSERTION(overflowArea, "Failed to set overflow area property");
aDesiredSize.mOverflowArea = *overflowArea;
}
// max sure the max element size reflects
// our min width
nscoord* maxElementWidth = state.GetMaxElementWidth();
if (maxElementWidth)
{
nsSize minSize(0,0);
GetMinSize(state, minSize);
2003-06-01 20:03:13 +00:00
if (mRect.width > minSize.width &&
aReflowState.mComputedWidth == NS_INTRINSICSIZE)
*maxElementWidth = minSize.width;
else
*maxElementWidth = mRect.width;
}
#ifdef DO_NOISY_REFLOW
{
printf("%p ** nsBF(done) W:%d H:%d ", this, aDesiredSize.width, aDesiredSize.height);
if (maxElementSize) {
printf("MW:%d\n", *maxElementWidth);
} else {
printf("MW:?\n");
}
}
#endif
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
2000-03-31 07:02:06 +00:00
return NS_OK;
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
1999-03-27 01:35:55 +00:00
{
if (!DoesNeedRecalc(mPrefSize)) {
aSize = mPrefSize;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
PropagateDebug(aBoxLayoutState);
#endif
1999-03-27 01:35:55 +00:00
2000-03-31 07:02:06 +00:00
nsresult rv = NS_OK;
rv = nsContainerBox::GetPrefSize(aBoxLayoutState, mPrefSize);
aSize = mPrefSize;
2000-03-31 07:02:06 +00:00
return rv;
}
1999-10-21 20:17:51 +00:00
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent)
{
if (!DoesNeedRecalc(mAscent)) {
aAscent = mAscent;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
1999-07-23 23:30:17 +00:00
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
PropagateDebug(aBoxLayoutState);
#endif
1999-07-23 23:30:17 +00:00
2000-03-31 07:02:06 +00:00
nsresult rv = NS_OK;
rv = nsContainerBox::GetAscent(aBoxLayoutState, mAscent);
1999-07-23 23:30:17 +00:00
aAscent = mAscent;
2000-03-31 07:02:06 +00:00
return rv;
}
1999-07-23 23:30:17 +00:00
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
if (!DoesNeedRecalc(mMinSize)) {
aSize = mMinSize;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
1999-07-23 23:30:17 +00:00
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
PropagateDebug(aBoxLayoutState);
#endif
2000-03-31 07:02:06 +00:00
nsresult rv = NS_OK;
mMinSize.SizeTo(0,0);
rv = nsContainerBox::GetMinSize(aBoxLayoutState, mMinSize);
2000-03-31 07:02:06 +00:00
aSize = mMinSize;
2000-03-31 07:02:06 +00:00
return rv;
}
1999-07-23 23:30:17 +00:00
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
if (!DoesNeedRecalc(mMaxSize)) {
aSize = mMaxSize;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
1999-07-23 23:30:17 +00:00
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
PropagateDebug(aBoxLayoutState);
#endif
2000-03-31 07:02:06 +00:00
nsresult rv = NS_OK;
mMaxSize.SizeTo(0,0);
nsContainerBox::GetMaxSize(aBoxLayoutState, mMaxSize);
2000-03-31 07:02:06 +00:00
aSize = mMaxSize;
2000-03-31 07:02:06 +00:00
return rv;
1999-03-27 01:35:55 +00:00
}
NS_IMETHODIMP
2000-03-31 07:02:06 +00:00
nsBoxFrame::GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex)
{
if (!DoesNeedRecalc(mFlex)) {
aFlex = mFlex;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
2000-03-31 07:02:06 +00:00
nsresult rv = NS_OK;
mFlex = 0;
rv = nsContainerBox::GetFlex(aBoxLayoutState, mFlex);
aFlex = mFlex;
2000-03-31 07:02:06 +00:00
return rv;
}
#ifdef DEBUG_LAYOUT
void
2000-03-31 07:02:06 +00:00
nsBoxFrame::PropagateDebug(nsBoxLayoutState& aState)
{
2000-03-31 07:02:06 +00:00
// propagate debug information
if (mState & NS_STATE_DEBUG_WAS_SET) {
if (mState & NS_STATE_SET_TO_DEBUG)
SetDebug(aState, PR_TRUE);
else
SetDebug(aState, PR_FALSE);
} else if (mState & NS_STATE_IS_ROOT) {
SetDebug(aState, gDebug);
2000-03-31 07:02:06 +00:00
}
}
#endif
1999-03-27 01:35:55 +00:00
NS_IMETHODIMP
nsBoxFrame::BeginLayout(nsBoxLayoutState& aState)
1999-03-27 01:35:55 +00:00
{
nsresult rv = nsContainerBox::BeginLayout(aState);
// mark ourselves as dirty so no child under us
// can post an incremental layout.
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
PropagateDebug(aState);
#endif
2000-03-31 07:02:06 +00:00
return rv;
2000-03-31 07:02:06 +00:00
}
/**
* If subclassing please subclass this method not layout.
* layout will call this method.
*/
NS_IMETHODIMP
nsBoxFrame::DoLayout(nsBoxLayoutState& aState)
{
return nsContainerBox::DoLayout(aState);
}
NS_IMETHODIMP
nsBoxFrame::Destroy(nsPresContext* aPresContext)
{
// unregister access key
RegUnregAccessKey(aPresContext, PR_FALSE);
// clean up the container box's layout manager and child boxes
nsBoxLayoutState state(aPresContext);
nsContainerBox::Destroy(state);
2000-09-01 00:59:09 +00:00
return nsContainerFrame::Destroy(aPresContext);
}
#ifdef DEBUG_LAYOUT
NS_IMETHODIMP
2000-03-31 07:02:06 +00:00
nsBoxFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug)
{
// see if our state matches the given debug state
PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
PRBool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
// if it doesn't then tell each child below us the new debug state
if (debugChanged)
{
if (aDebug) {
mState |= NS_STATE_CURRENTLY_IN_DEBUG;
} else {
mState &= ~NS_STATE_CURRENTLY_IN_DEBUG;
}
2000-03-31 07:02:06 +00:00
SetDebugOnChildList(aState, mFirstChild, aDebug);
2000-03-31 07:02:06 +00:00
NeedsRecalc();
}
return NS_OK;
}
#endif
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::NeedsRecalc()
{
SizeNeedsRecalc(mPrefSize);
SizeNeedsRecalc(mMinSize);
SizeNeedsRecalc(mMaxSize);
CoordNeedsRecalc(mFlex);
CoordNeedsRecalc(mAscent);
2000-03-31 07:02:06 +00:00
return NS_OK;
}
NS_IMETHODIMP
nsBoxFrame::RemoveFrame(nsPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
2000-03-31 07:02:06 +00:00
{
SanityCheck(mFrames);
// remove child from our info list
nsBoxLayoutState state(aPresContext);
Remove(state, aOldFrame);
2000-03-31 07:02:06 +00:00
// remove the child frame
mFrames.DestroyFrame(aPresContext, aOldFrame);
SanityCheck(mFrames);
// mark us dirty and generate a reflow command
MarkDirtyChildren(state);
MarkDirty(state);
return NS_OK;
}
NS_IMETHODIMP
nsBoxFrame::InsertFrames(nsPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
2000-03-31 07:02:06 +00:00
SanityCheck(mFrames);
nsIBox* prevBox = GetBox(aPrevFrame);
if (prevBox == nsnull && aPrevFrame != nsnull) {
#ifdef DEBUG
2001-05-23 03:23:31 +00:00
printf("Warning prev sibling is not in our list!!!\n");
#endif
2000-03-31 07:02:06 +00:00
aPrevFrame = nsnull;
}
// insert the frames to our info list
nsBoxLayoutState state(aPresContext);
Insert(state, aPrevFrame, aFrameList);
// insert the frames in out regular frame list
2000-02-16 23:00:52 +00:00
mFrames.InsertFrames(this, aPrevFrame, aFrameList);
#ifdef DEBUG_LAYOUT
// if we are in debug make sure our children are in debug as well.
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
2000-03-31 07:02:06 +00:00
SetDebugOnChildList(state, mFirstChild, PR_TRUE);
#endif
CheckFrameOrder();
2000-03-31 07:02:06 +00:00
SanityCheck(mFrames);
// mark us dirty and generate a reflow command
2000-03-31 07:02:06 +00:00
MarkDirtyChildren(state);
MarkDirty(state);
return NS_OK;
}
NS_IMETHODIMP
nsBoxFrame::AppendFrames(nsPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
2000-03-31 07:02:06 +00:00
SanityCheck(mFrames);
// append them after
nsBoxLayoutState state(aPresContext);
Append(state,aFrameList);
1999-05-18 04:06:52 +00:00
// append in regular frames
2000-02-16 23:00:52 +00:00
mFrames.AppendFrames(this, aFrameList);
2000-03-31 07:02:06 +00:00
#ifdef DEBUG_LAYOUT
// if we are in debug make sure our children are in debug as well.
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
2000-03-31 07:02:06 +00:00
SetDebugOnChildList(state, mFirstChild, PR_TRUE);
#endif
CheckFrameOrder();
2000-03-31 07:02:06 +00:00
SanityCheck(mFrames);
2000-03-31 07:02:06 +00:00
MarkDirtyChildren(state);
MarkDirty(state);
return NS_OK;
}
1999-03-27 01:35:55 +00:00
NS_IMETHODIMP
nsBoxFrame::AttributeChanged(nsPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
nsresult rv = nsContainerFrame::AttributeChanged(aPresContext, aChild,
aNameSpaceID, aAttribute,
aModType);
// Ignore 'width', 'height', 'screenX', 'screenY' and 'sizemode' on a
// <window>.
nsIAtom *tag = mContent->Tag();
if ((tag == nsXULAtoms::window ||
tag == nsXULAtoms::page ||
tag == nsXULAtoms::dialog ||
tag == nsXULAtoms::wizard) &&
(nsXULAtoms::width == aAttribute ||
nsXULAtoms::height == aAttribute ||
nsXULAtoms::screenX == aAttribute ||
nsXULAtoms::screenY == aAttribute ||
nsXULAtoms::sizemode == aAttribute)) {
return rv;
}
if (aAttribute == nsHTMLAtoms::width ||
aAttribute == nsHTMLAtoms::height ||
aAttribute == nsHTMLAtoms::align ||
aAttribute == nsHTMLAtoms::valign ||
aAttribute == nsHTMLAtoms::left ||
aAttribute == nsHTMLAtoms::top ||
aAttribute == nsXULAtoms::flex ||
aAttribute == nsXULAtoms::orient ||
aAttribute == nsXULAtoms::pack ||
aAttribute == nsXULAtoms::dir ||
aAttribute == nsXULAtoms::mousethrough ||
aAttribute == nsXULAtoms::equalsize) {
if (aAttribute == nsHTMLAtoms::align ||
aAttribute == nsHTMLAtoms::valign ||
aAttribute == nsXULAtoms::orient ||
aAttribute == nsXULAtoms::pack ||
#ifdef DEBUG_LAYOUT
aAttribute == nsXULAtoms::debug ||
#endif
aAttribute == nsXULAtoms::dir) {
mValign = nsBoxFrame::vAlign_Top;
mHalign = nsBoxFrame::hAlign_Left;
PRBool orient = PR_TRUE;
GetInitialOrientation(orient);
if (orient)
mState |= NS_STATE_IS_HORIZONTAL;
else
mState &= ~NS_STATE_IS_HORIZONTAL;
PRBool normal = PR_TRUE;
GetInitialDirection(normal);
if (normal)
mState |= NS_STATE_IS_DIRECTION_NORMAL;
else
mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
GetInitialVAlignment(mValign);
GetInitialHAlignment(mHalign);
PRBool equalSize = PR_FALSE;
GetInitialEqualSize(equalSize);
if (equalSize)
mState |= NS_STATE_EQUAL_SIZE;
else
mState &= ~NS_STATE_EQUAL_SIZE;
#ifdef DEBUG_LAYOUT
PRBool debug = mState & NS_STATE_SET_TO_DEBUG;
PRBool debugSet = GetInitialDebug(debug);
if (debugSet) {
mState |= NS_STATE_DEBUG_WAS_SET;
if (debug)
mState |= NS_STATE_SET_TO_DEBUG;
else
mState &= ~NS_STATE_SET_TO_DEBUG;
} else {
mState &= ~NS_STATE_DEBUG_WAS_SET;
}
#endif
2000-02-14 01:42:09 +00:00
PRBool autostretch = mState & NS_STATE_AUTO_STRETCH;
GetInitialAutoStretch(autostretch);
if (autostretch)
mState |= NS_STATE_AUTO_STRETCH;
else
mState &= ~NS_STATE_AUTO_STRETCH;
2000-03-31 07:02:06 +00:00
}
else if (aAttribute == nsHTMLAtoms::left ||
aAttribute == nsHTMLAtoms::top) {
mState &= ~NS_STATE_STACK_NOT_POSITIONED;
}
else if (aAttribute == nsXULAtoms::mousethrough) {
UpdateMouseThrough();
}
}
else if (aAttribute == nsXULAtoms::ordinal) {
nsBoxLayoutState state(aPresContext->PresShell());
nsIBox* parent;
GetParentBox(&parent);
parent->RelayoutChildAtOrdinal(state, this);
nsIFrame* parentFrame;
parent->GetFrame(&parentFrame);
nsBoxFrame* parentBoxFrame = (nsBoxFrame*) parentFrame;
if (parentBoxFrame)
parentBoxFrame->CheckFrameOrder();
parent->MarkDirty(state);
}
// If the accesskey changed, register for the new value
// The old value has been unregistered in nsXULElement::SetAttr
else if (aAttribute == nsXULAtoms::accesskey) {
RegUnregAccessKey(aPresContext, PR_TRUE);
}
nsBoxLayoutState state(aPresContext);
2003-06-01 20:03:13 +00:00
// XXX This causes us to reflow for any attribute change (e.g.,
// flipping through menus).
MarkDirty(state);
1999-03-27 01:35:55 +00:00
return rv;
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetInset(nsMargin& margin)
{
2000-03-31 07:02:06 +00:00
margin.SizeTo(0,0,0,0);
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
if (mState & NS_STATE_CURRENTLY_IN_DEBUG) {
nsMargin debugMargin(0,0,0,0);
nsMargin debugBorder(0,0,0,0);
nsMargin debugPadding(0,0,0,0);
GetDebugBorder(debugBorder);
PixelMarginToTwips(mPresContext, debugBorder);
GetDebugMargin(debugMargin);
PixelMarginToTwips(mPresContext, debugMargin);
GetDebugMargin(debugPadding);
PixelMarginToTwips(mPresContext, debugPadding);
2000-03-31 07:02:06 +00:00
margin += debugBorder;
margin += debugMargin;
margin += debugPadding;
}
#endif
2000-03-31 07:02:06 +00:00
return NS_OK;
}
#ifdef DEBUG_COELESCED
static PRInt32 StyleCoelesced = 0;
#endif
PRBool
nsBoxFrame::HasStyleChange()
{
return mState & NS_STATE_STYLE_CHANGE;
}
void
nsBoxFrame::SetStyleChangeFlag(PRBool aDirty)
{
nsBox::SetStyleChangeFlag(aDirty);
if (aDirty)
mState |= (NS_STATE_STYLE_CHANGE);
else
mState &= ~NS_STATE_STYLE_CHANGE;
}
nsresult
nsBoxFrame::SyncLayout(nsBoxLayoutState& aState)
{
nsresult rv = nsBox::SyncLayout(aState);
mState &= ~(NS_STATE_STYLE_CHANGE);
return rv;
}
void
nsBoxFrame::CheckFrameOrder()
{
if (mOrderBoxes) {
// synchronize the frame order with the box order by simply walking
// the box list and linking each frame as its box is linked
nsIBox* box = mFirstChild;
nsIFrame* frame1;
box->GetFrame(&frame1);
nsIBox* box2;
nsIFrame* frame;
nsIFrame* frame2;
while (box) {
box->GetNextBox(&box2);
box->GetFrame(&frame);
if (box2)
box2->GetFrame(&frame2);
else
frame2 = nsnull;
frame->SetNextSibling(frame2);
box = box2;
}
mFrames.SetFrames(frame1);
}
}
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
void
nsBoxFrame::GetDebugPref(nsPresContext* aPresContext)
2000-03-31 07:02:06 +00:00
{
gDebug = nsContentUtils::GetBoolPref("xul.debug.box");
2000-03-31 07:02:06 +00:00
}
#endif
2000-03-31 07:02:06 +00:00
2000-09-01 00:59:09 +00:00
NS_IMETHODIMP
nsBoxFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
2000-09-01 00:59:09 +00:00
{
// if collapsed nothing is drawn
if (GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
return NS_OK;
2000-09-01 00:59:09 +00:00
if (NS_FRAME_IS_UNFLOWABLE & mState) {
return NS_OK;
}
2000-09-01 00:59:09 +00:00
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect, 0, PR_FALSE);
2000-09-01 00:59:09 +00:00
}
if (GetType() == nsLayoutAtoms::rootFrame) {
// We are wrapping the root frame of a XUL document. We
// need to check the pres shell to find out if painting is locked
// down (because we're still in the early stages of document
// and frame construction. If painting is locked down, then we
// do not paint our children.
PRBool paintingSuppressed = PR_FALSE;
aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
if (paintingSuppressed)
return NS_OK;
}
2000-09-01 00:59:09 +00:00
// Now paint the kids. Note that child elements have the opportunity to
// override the visibility property and display even if their parent is
// hidden. Don't paint our children if the theme object is a leaf.
const nsStyleDisplay* display = GetStyleDisplay();
if (!(display->mAppearance && nsBox::gTheme &&
gTheme->ThemeSupportsWidget(aPresContext, this, display->mAppearance) &&
!gTheme->WidgetIsContainer(display->mAppearance)))
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
2000-09-01 00:59:09 +00:00
// see if we have to draw a selection frame around this container
return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
/**
* Redefined to handle collapsed as well as removing unneeded crap having to
* do with frame state and overlapping that only applied to HTML not XUL
*/
void
nsBoxFrame::PaintChild(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsIFrame* aFrame,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
2000-09-01 00:59:09 +00:00
// if collapsed don't paint the child.
if (aFrame->GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
2000-09-01 00:59:09 +00:00
return;
if (!aFrame->HasView()) {
nsRect kidRect = aFrame->GetRect();
2000-09-01 00:59:09 +00:00
nsRect damageArea;
PRBool overlap;
// Compute the intersection of the dirty rect and the childs
// rect (both are in our coordinate space). This limits the
// damageArea to just the portion that intersects the childs
// rect.
overlap = damageArea.IntersectRect(aDirtyRect, kidRect);
if (overlap) {
// Translate damage area into the kids coordinate
// system. Translate rendering context into the kids
// coordinate system.
damageArea.x -= kidRect.x;
damageArea.y -= kidRect.y;
// Save the transformation matrix's translation components.
float xMatrix;
float yMatrix;
nsTransform2D *theTransform;
aRenderingContext.GetCurrentTransform(theTransform);
NS_ASSERTION(theTransform != nsnull, "The rendering context transform is null");
theTransform->GetTranslation(&xMatrix, &yMatrix);
aRenderingContext.Translate(kidRect.x, kidRect.y);
2000-09-01 00:59:09 +00:00
// Paint the kid
aFrame->Paint(aPresContext, aRenderingContext, damageArea, aWhichLayer);
// Restore the transformation matrix's translation components.
theTransform->SetTranslation(xMatrix, yMatrix);
2000-09-01 00:59:09 +00:00
}
}
}
void
nsBoxFrame::PaintChildren(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
2000-03-31 07:02:06 +00:00
nsMargin border;
nsRect inner;
GetBorder(border);
#ifdef DEBUG_LAYOUT
nsMargin debugBorder;
nsMargin debugMargin;
nsMargin debugPadding;
2000-03-31 07:02:06 +00:00
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
{
PRBool isHorizontal = IsHorizontal();
GetDebugBorder(debugBorder);
PixelMarginToTwips(aPresContext, debugBorder);
2000-03-31 07:02:06 +00:00
GetDebugMargin(debugMargin);
PixelMarginToTwips(aPresContext, debugMargin);
2000-03-31 07:02:06 +00:00
GetDebugPadding(debugPadding);
PixelMarginToTwips(aPresContext, debugPadding);
2000-03-31 07:02:06 +00:00
GetContentRect(inner);
inner.Deflate(debugMargin);
inner.Deflate(border);
//nsRect borderRect(inner);
2000-03-31 07:02:06 +00:00
nscolor color;
if (isHorizontal) {
color = NS_RGB(0,0,255);
} else {
color = NS_RGB(255,0,0);
}
aRenderingContext.SetColor(color);
//left
nsRect r(inner);
r.width = debugBorder.left;
aRenderingContext.FillRect(r);
// top
r = inner;
r.height = debugBorder.top;
aRenderingContext.FillRect(r);
//right
r = inner;
r.x = r.x + r.width - debugBorder.right;
r.width = debugBorder.right;
aRenderingContext.FillRect(r);
//bottom
r = inner;
r.y = r.y + r.height - debugBorder.bottom;
r.height = debugBorder.bottom;
aRenderingContext.FillRect(r);
// if we have dirty children or we are dirty
// place a green border around us.
PRBool dirty = PR_FALSE;
IsDirty(dirty);
PRBool dirtyc = PR_FALSE;
HasDirtyChildren(dirtyc);
if (dirty || dirtyc) {
IsDirty(dirty);
HasDirtyChildren(dirty);
nsRect dirtyr(inner);
aRenderingContext.SetColor(NS_RGB(0,255,0));
aRenderingContext.DrawRect(dirtyr);
aRenderingContext.SetColor(color);
}
2000-03-31 07:02:06 +00:00
}
#endif
2000-03-31 07:02:06 +00:00
const nsStyleDisplay* disp = GetStyleDisplay();
// Child elements have the opportunity to override the visibility property
// of their parent and display even if the parent is hidden
nsRect r(0,0,mRect.width, mRect.height);
PRBool hasClipped = PR_FALSE;
// If overflow is hidden then set the clip rect so that children
// don't leak out of us
if (NS_STYLE_OVERFLOW_CLIP == disp->mOverflow) {
nsMargin im(0,0,0,0);
GetInset(im);
r.Deflate(im);
r.Deflate(border);
}
2000-03-31 07:02:06 +00:00
nsIBox* kid = nsnull;
GetChildBox(&kid);
while (nsnull != kid) {
2000-03-31 07:02:06 +00:00
nsIFrame* frame = nsnull;
kid->GetFrame(&frame);
if (!hasClipped && NS_STYLE_OVERFLOW_CLIP == disp->mOverflow) {
// if we haven't already clipped and we should
// check to see if the child is in out bounds. If not then
// we begin clipping.
nsRect cr(0,0,0,0);
2000-03-31 07:02:06 +00:00
kid->GetBounds(cr);
// if our rect does not contain the childs then begin clipping
if (!r.Contains(cr)) {
aRenderingContext.PushState();
aRenderingContext.SetClipRect(r, nsClipCombine_kIntersect);
hasClipped = PR_TRUE;
}
}
2000-03-31 07:02:06 +00:00
PaintChild(aPresContext, aRenderingContext, aDirtyRect, frame, aWhichLayer);
kid->GetNextBox(&kid);
}
if (hasClipped)
aRenderingContext.PopState();
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
{
nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
2000-03-31 07:02:06 +00:00
GetContentRect(r);
if (NS_STYLE_OVERFLOW_CLIP == disp->mOverflow) {
GetDebugMargin(debugMargin);
PixelMarginToTwips(aPresContext, debugMargin);
2000-03-31 07:02:06 +00:00
r.Deflate(debugMargin);
}
2000-03-31 07:02:06 +00:00
hasClipped = PR_FALSE;
2000-03-31 07:02:06 +00:00
GetChildBox(&kid);
while (nsnull != kid) {
if (!hasClipped && NS_STYLE_OVERFLOW_CLIP == disp->mOverflow) {
2000-03-31 07:02:06 +00:00
// if we haven't already clipped and we should
// check to see if the child is in out bounds. If not then
// we begin clipping.
nsRect cr(0,0,0,0);
kid->GetBounds(cr);
// if our rect does not contain the childs then begin clipping
if (!r.Contains(cr)) {
aRenderingContext.PushState();
aRenderingContext.SetClipRect(r, nsClipCombine_kIntersect);
2000-03-31 07:02:06 +00:00
hasClipped = PR_TRUE;
}
}
PRBool isHorizontal = IsHorizontal();
nscoord x, y, borderSize, spacerSize;
2000-03-31 07:02:06 +00:00
nsRect cr(0,0,0,0);
kid->GetBounds(cr);
nsMargin margin;
kid->GetMargin(margin);
cr.Inflate(margin);
if (isHorizontal)
{
2000-03-31 07:02:06 +00:00
cr.y = inner.y;
x = cr.x;
y = cr.y + onePixel;
spacerSize = debugBorder.top - onePixel*4;
} else {
2000-03-31 07:02:06 +00:00
cr.x = inner.x;
x = cr.y;
y = cr.x + onePixel;
spacerSize = debugBorder.left - onePixel*4;
}
2000-03-31 07:02:06 +00:00
nsBoxLayoutState state(aPresContext);
nscoord flex = 0;
kid->GetFlex(state, flex);
2000-03-31 07:02:06 +00:00
PRBool isCollapsed = PR_FALSE;
kid->IsCollapsed(state, isCollapsed);
2000-03-31 07:02:06 +00:00
if (!isCollapsed) {
aRenderingContext.SetColor(NS_RGB(255,255,255));
2000-03-31 07:02:06 +00:00
if (isHorizontal)
borderSize = cr.width;
else
borderSize = cr.height;
DrawSpacer(aPresContext, aRenderingContext, isHorizontal, flex, x, y, borderSize, spacerSize);
}
2000-03-31 07:02:06 +00:00
kid->GetNextBox(&kid);
}
if (hasClipped)
aRenderingContext.PopState();
2000-03-31 07:02:06 +00:00
}
#endif
}
NS_IMETHODIMP_(nsrefcnt)
nsBoxFrame::AddRef(void)
1999-03-27 01:35:55 +00:00
{
2000-03-31 07:02:06 +00:00
return NS_OK;
}
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP_(nsrefcnt)
nsBoxFrame::Release(void)
{
2000-03-31 07:02:06 +00:00
return NS_OK;
}
2000-03-31 07:02:06 +00:00
NS_INTERFACE_MAP_BEGIN(nsBoxFrame)
NS_INTERFACE_MAP_ENTRY(nsIBox)
#ifdef NS_DEBUG
NS_INTERFACE_MAP_ENTRY(nsIFrameDebug)
#endif
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox)
2000-09-01 00:59:09 +00:00
NS_INTERFACE_MAP_END_INHERITING(nsContainerFrame)
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetFrame(nsIFrame** aFrame)
{
2000-03-31 07:02:06 +00:00
*aFrame = this;
return NS_OK;
}
#ifdef DEBUG_LAYOUT
void
nsBoxFrame::GetBoxName(nsAutoString& aName)
{
GetFrameName(aName);
}
#endif
#ifdef DEBUG
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetFrameName(nsAString& aResult) const
2000-03-31 07:02:06 +00:00
{
return MakeFrameName(NS_LITERAL_STRING("Box"), aResult);
2000-03-31 07:02:06 +00:00
}
#endif
nsIAtom*
nsBoxFrame::GetType() const
{
return nsLayoutAtoms::boxFrame;
}
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetDebug(PRBool& aDebug)
{
aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG);
return NS_OK;
}
#endif
NS_IMETHODIMP
nsBoxFrame::GetFrameForPoint(nsPresContext* aPresContext,
const nsPoint& aPoint,
2000-03-31 07:02:06 +00:00
nsFramePaintLayer aWhichLayer,
nsIFrame** aFrame)
{
2000-03-31 07:02:06 +00:00
if (!mRect.Contains(aPoint))
return NS_ERROR_FAILURE;
const nsStyleVisibility* vis = GetStyleVisibility();
if (vis->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
return NS_ERROR_FAILURE;
2000-03-31 07:02:06 +00:00
nsIView* view = nsnull;
nsPoint originOffset;
GetOriginToViewOffset(aPresContext, originOffset, &view);
2000-03-31 07:02:06 +00:00
#ifdef DEBUG_LAYOUT
2000-03-31 07:02:06 +00:00
// get the debug frame.
if (view || (mState & NS_STATE_IS_ROOT))
{
nsIBox* box = nsnull;
if (NS_SUCCEEDED(GetDebugBoxAt(aPoint, &box)) && box)
{
PRBool isDebug = PR_FALSE;
box->GetDebug(isDebug);
if (isDebug) {
nsIFrame* frame = nsnull;
box->GetFrame(&frame);
*aFrame = frame;
return NS_OK;
}
}
}
#endif
2000-03-31 07:02:06 +00:00
nsIFrame *hit = nsnull;
nsPoint tmp;
2000-03-31 07:02:06 +00:00
*aFrame = nsnull;
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
if (view)
tmp += originOffset;
nsIBox* kid = nsnull;
GetChildBox(&kid);
while (nsnull != kid) {
nsIFrame* frame = nsnull;
kid->GetFrame(&frame);
GetFrameForPointChild(aPresContext, tmp, aWhichLayer, frame, hit != nsnull, &hit);
kid->GetNextBox(&kid);
}
if (hit)
*aFrame = hit;
if (*aFrame) {
2000-03-31 07:02:06 +00:00
return NS_OK;
}
// if no kids were hit then select us
if (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND && vis->IsVisible()) {
*aFrame = this;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
2000-04-12 02:59:26 +00:00
/* virtual */ nsresult
nsBoxFrame::GetFrameForPointChild(nsPresContext* aPresContext,
const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer,
nsIFrame* aChild,
PRBool aCheckMouseThrough,
nsIFrame** aFrame)
{
nsIFrame *hit = nsnull;
nsresult rv =
aChild->GetFrameForPoint(aPresContext, aPoint, aWhichLayer, &hit);
if (NS_SUCCEEDED(rv) && hit) {
rv = NS_ERROR_FAILURE;
if (!aCheckMouseThrough) {
*aFrame = hit;
rv = NS_OK;
}
else
{
// If we had a lower frame for this point, check whether hit's box has
// mouse through. If so, stick with the lower frame that we found.
PRBool isAdaptor = PR_FALSE;
nsIBox *box = GetBoxForFrame(hit, isAdaptor);
if (box) {
PRBool mouseThrough = PR_FALSE;
box->GetMouseThrough(mouseThrough);
// if the child says it can never mouse though ignore it.
if (!mouseThrough) {
*aFrame = hit;
rv = NS_OK;
}
}
}
}
return rv;
}
nsIBox*
nsBoxFrame::GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor)
{
if (aFrame == nsnull)
return nsnull;
nsIBox* ibox = nsnull;
if (NS_FAILED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox))) {
aIsAdaptor = PR_TRUE;
// if we hit a non box. Find the box in out last container
// and clear its cache.
nsIBox* parentBox = nsnull;
if (NS_FAILED(aFrame->GetParent()->
QueryInterface(NS_GET_IID(nsIBox), (void**)&parentBox)))
return nsnull;
if (parentBox) {
nsIBox* start = nsnull;
parentBox->GetChildBox(&start);
while (start) {
nsIFrame* frame = nsnull;
start->GetFrame(&frame);
if (frame == aFrame) {
ibox = start;
break;
}
2000-04-12 02:59:26 +00:00
start->GetNextBox(&start);
}
}
}
return ibox;
}
2000-04-12 02:59:26 +00:00
/*
NS_IMETHODIMP
nsBoxFrame::GetMouseThrough(PRBool& aMouseThrough)
{
const nsStyleBackground* color = GetStyleBackground();
PRBool transparentBG = NS_STYLE_BG_COLOR_TRANSPARENT ==
(color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT);
if (!transparentBG)
aMouseThrough = never;
else
return nsBox::GetMouseThrough(aMouseThrough);
return NS_OK;
2000-03-31 07:02:06 +00:00
}
*/
1999-10-12 00:16:06 +00:00
NS_IMETHODIMP
nsBoxFrame::GetCursor(nsPresContext* aPresContext,
nsPoint& aPoint,
PRInt32& aCursor)
1999-10-12 00:16:06 +00:00
{
2000-03-31 07:02:06 +00:00
/*
#ifdef NS_DEBUG
printf("Get Cursor: ");
2000-03-31 07:02:06 +00:00
nsFrame::ListTag(stdout, this);
printf("\n");
2000-03-31 07:02:06 +00:00
#endif
*/
nsPoint newPoint;
TranslateEventCoords(aPresContext, aPoint, newPoint);
#ifdef DEBUG_LAYOUT
// if we are in debug and we are in the debug area
// return our own cursor and dump the debug information.
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
{
nsresult rv = DisplayDebugInfoFor(this, aPresContext, newPoint, aCursor);
2000-03-31 07:02:06 +00:00
if (rv == NS_OK)
return rv;
}
#endif
2000-03-31 07:02:06 +00:00
2000-09-01 00:59:09 +00:00
nsresult rv = nsContainerFrame::GetCursor(aPresContext, aPoint, aCursor);
2000-03-31 07:02:06 +00:00
return rv;
1999-10-12 00:16:06 +00:00
}
//XXX the event come's in in view relative coords, but really should
//be in frame relative coords by the time it hits our frame.
// Translate an point that is relative to our view (or a containing
// view) into a localized pixel coordinate that is relative to the
// content area of this frame (inside the border+padding).
void
nsBoxFrame::TranslateEventCoords(nsPresContext* aPresContext,
const nsPoint& aPoint,
nsPoint& aResult)
{
nscoord x = aPoint.x;
nscoord y = aPoint.y;
// If we have a view then the event coordinates are already relative
// to this frame; otherwise we have to adjust the coordinates
// appropriately.
if (!HasView()) {
nsPoint offset;
nsIView* view;
GetOffsetFromView(aPresContext, offset, &view);
if (nsnull != view) {
x -= offset.x;
y -= offset.y;
}
}
aResult.x = x;
aResult.y = y;
}
1999-10-12 00:16:06 +00:00
nsresult
2000-03-31 07:02:06 +00:00
nsBoxFrame::GetContentOf(nsIContent** aContent)
1999-10-12 00:16:06 +00:00
{
// If we don't have a content node find a parent that does.
2000-03-31 07:02:06 +00:00
nsIFrame* frame;
GetFrame(&frame);
while (frame) {
*aContent = frame->GetContent();
if (*aContent) {
NS_ADDREF(*aContent);
return NS_OK;
}
1999-10-12 00:16:06 +00:00
frame = frame->GetParent();
1999-10-12 00:16:06 +00:00
}
*aContent = nsnull;
1999-10-12 00:16:06 +00:00
return NS_OK;
}
/*
nsresult
nsBoxFrame::PaintDebug(nsIBox* aBox,
nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
2000-03-31 07:02:06 +00:00
{
2000-03-31 07:02:06 +00:00
PRBool isHorizontal = IsHorizontal();
2000-03-31 07:02:06 +00:00
nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
2000-03-31 07:02:06 +00:00
nsMargin debugBorder(0,0,0,0);
nsMargin debugMargin(0,0,0,0);
nsMargin debugPadding(0,0,0,0);
2000-03-31 07:02:06 +00:00
GetDebugBorder(debugBorder);
PixelMarginToTwips(aPresContext, debugBorder);
2000-03-31 07:02:06 +00:00
GetDebugMargin(debugMargin);
PixelMarginToTwips(aPresContext, debugMargin);
2000-03-31 07:02:06 +00:00
GetDebugPadding(debugPadding);
PixelMarginToTwips(aPresContext, debugPadding);
2000-03-31 07:02:06 +00:00
nsRect inner(0,0,0,0);
aBox->GetContentRect(inner);
2000-03-31 07:02:06 +00:00
inner.Deflate(debugMargin);
//nsRect borderRect(inner);
2000-03-31 07:02:06 +00:00
nscolor color;
if (isHorizontal) {
color = NS_RGB(0,0,255);
} else {
color = NS_RGB(255,0,0);
}
//left
aRenderingContext.SetColor(color);
nsRect r(inner);
r.width = debugBorder.left;
aRenderingContext.FillRect(r);
// top
r = inner;
r.height = debugBorder.top;
aRenderingContext.FillRect(r);
//right
r = inner;
r.x = r.x + r.width - debugBorder.right;
r.width = debugBorder.right;
aRenderingContext.FillRect(r);
//bottom
r = inner;
r.y = r.y + r.height - debugBorder.bottom;
r.height = debugBorder.bottom;
aRenderingContext.FillRect(r);
// if we have dirty children or we are dirty
// place a green border around us.
PRBool dirty = PR_FALSE;
IsDirty(dirty);
PRBool dirtyc = PR_FALSE;
HasDirtyChildren(dirty);
if (dirty || dirtyc) {
nsRect dirtyr(inner);
aRenderingContext.SetColor(NS_RGB(0,255,0));
aRenderingContext.DrawRect(dirtyr);
}
// paint the spacers.
nscoord x, y, borderSize, spacerSize;
2000-03-31 07:02:06 +00:00
aRenderingContext.SetColor(NS_RGB(255,255,255));
if (isHorizontal)
{
x = inner.x;
y = inner.y + onePixel;
x += debugBorder.left;
spacerSize = debugBorder.top - onePixel*4;
2000-03-31 07:02:06 +00:00
} else {
x = inner.y;
y = inner.x + onePixel;
x += debugBorder.top;
spacerSize = debugBorder.left - onePixel*4;
2000-03-31 07:02:06 +00:00
}
nsIBox* box = nsnull;
aBox->GetChildBox(&box);
nsBoxLayoutState state(aPresContext);
while (box) {
nsSize size;
GetFrameSizeWithMargin(box, size);
PRBool isCollapsed = PR_FALSE;
box->IsCollapsed(state, isCollapsed);
if (!isCollapsed) {
if (isHorizontal)
borderSize = size.width;
else
borderSize = size.height;
2000-03-31 07:02:06 +00:00
nscoord flex = 0;
box->GetFlex(state, flex);
DrawSpacer(aPresContext, aRenderingContext, isHorizontal, flex, x, y, borderSize, spacerSize);
2000-03-31 07:02:06 +00:00
x += borderSize;
}
box->GetNextBox(&box);
}
return NS_OK;
}
*/
2000-03-31 07:02:06 +00:00
void
nsBoxFrame::DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2)
{
2000-03-31 07:02:06 +00:00
if (aHorizontal)
aRenderingContext.DrawLine(x1,y1,x2,y2);
else
aRenderingContext.DrawLine(y1,x1,y2,x2);
}
2000-03-31 07:02:06 +00:00
void
nsBoxFrame::FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height)
{
2000-03-31 07:02:06 +00:00
if (aHorizontal)
aRenderingContext.FillRect(x,y,width,height);
else
aRenderingContext.FillRect(y,x,height,width);
}
2000-03-31 07:02:06 +00:00
void
nsBoxFrame::DrawSpacer(nsPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord spacerSize)
2000-03-31 07:02:06 +00:00
{
nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
2000-03-31 07:02:06 +00:00
// if we do draw the coils
int distance = 0;
int center = 0;
int offset = 0;
int coilSize = COIL_SIZE*onePixel;
int halfSpacer = spacerSize/2;
2000-03-31 07:02:06 +00:00
distance = size;
center = y + halfSpacer;
2000-03-31 07:02:06 +00:00
offset = x;
2000-03-31 07:02:06 +00:00
int coils = distance/coilSize;
2000-03-31 07:02:06 +00:00
int halfCoilSize = coilSize/2;
2000-03-31 07:02:06 +00:00
if (flex == 0) {
DrawLine(aRenderingContext, aHorizontal, x,y + spacerSize/2, x + size, y + spacerSize/2);
2000-03-31 07:02:06 +00:00
} else {
for (int i=0; i < coils; i++)
{
DrawLine(aRenderingContext, aHorizontal, offset, center+halfSpacer, offset+halfCoilSize, center-halfSpacer);
DrawLine(aRenderingContext, aHorizontal, offset+halfCoilSize, center-halfSpacer, offset+coilSize, center+halfSpacer);
2000-03-31 07:02:06 +00:00
offset += coilSize;
}
}
FillRect(aRenderingContext, aHorizontal, x + size - spacerSize/2, y, spacerSize/2, spacerSize);
FillRect(aRenderingContext, aHorizontal, x, y, spacerSize/2, spacerSize);
//DrawKnob(aPresContext, aRenderingContext, x + size - spacerSize, y, spacerSize);
}
#ifdef DEBUG_LAYOUT
void
nsBoxFrame::GetDebugBorder(nsMargin& aInset)
{
2000-03-31 07:02:06 +00:00
aInset.SizeTo(2,2,2,2);
if (IsHorizontal())
2000-03-31 07:02:06 +00:00
aInset.top = 10;
else
aInset.left = 10;
}
void
nsBoxFrame::GetDebugMargin(nsMargin& aInset)
{
2000-03-31 07:02:06 +00:00
aInset.SizeTo(2,2,2,2);
}
void
nsBoxFrame::GetDebugPadding(nsMargin& aPadding)
{
2000-03-31 07:02:06 +00:00
aPadding.SizeTo(2,2,2,2);
}
#endif
2000-03-31 07:02:06 +00:00
void
nsBoxFrame::PixelMarginToTwips(nsPresContext* aPresContext, nsMargin& aMarginPixels)
{
nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
2000-03-31 07:02:06 +00:00
aMarginPixels.left *= onePixel;
aMarginPixels.right *= onePixel;
aMarginPixels.top *= onePixel;
aMarginPixels.bottom *= onePixel;
}
2000-03-31 07:02:06 +00:00
#ifdef DEBUG_LAYOUT
void
nsBoxFrame::GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch)
{
float p2t = aPresContext->ScaledPixelsToTwips();
2000-03-31 07:02:06 +00:00
char width[100];
char height[100];
if (a.width == NS_INTRINSICSIZE)
sprintf(width,"%s","INF");
else
sprintf(width,"%d", nscoord(a.width/*/p2t*/));
if (a.height == NS_INTRINSICSIZE)
sprintf(height,"%s","INF");
else
2000-03-31 07:02:06 +00:00
sprintf(height,"%d", nscoord(a.height/*/p2t*/));
2000-03-31 07:02:06 +00:00
sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[SET]" : ""),
height, (b.height != NS_INTRINSICSIZE ? "[SET]" : ""));
}
void
nsBoxFrame::GetValue(nsPresContext* aPresContext, PRInt32 a, PRInt32 b, char* ch)
{
2000-03-31 07:02:06 +00:00
if (a == NS_INTRINSICSIZE)
sprintf(ch, "%d[SET]", b);
else
sprintf(ch, "%d", a);
}
2000-03-31 07:02:06 +00:00
nsresult
nsBoxFrame::DisplayDebugInfoFor(nsIBox* aBox,
nsPresContext* aPresContext,
nsPoint& aPoint,
PRInt32& aCursor)
2000-03-31 07:02:06 +00:00
{
nsBoxLayoutState state(aPresContext);
nscoord x = aPoint.x;
nscoord y = aPoint.y;
2000-03-31 07:02:06 +00:00
nsIFrame* ourFrame = nsnull;
aBox->GetFrame(&ourFrame);
2000-03-31 07:02:06 +00:00
// get the area inside our border but not our debug margins.
nsRect insideBorder;
aBox->GetContentRect(insideBorder);
nsMargin border(0,0,0,0);
aBox->GetBorderAndPadding(border);
insideBorder.Deflate(border);
PRBool isHorizontal = IsHorizontal();
2000-03-31 07:02:06 +00:00
if (!insideBorder.Contains(nsPoint(x,y)))
return NS_ERROR_FAILURE;
//printf("%%%%%% inside box %%%%%%%\n");
2000-02-14 01:42:09 +00:00
2000-03-31 07:02:06 +00:00
int count = 0;
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
2000-03-31 07:02:06 +00:00
nsMargin m;
nsMargin m2;
GetDebugBorder(m);
PixelMarginToTwips(aPresContext, m);
2000-03-31 07:02:06 +00:00
GetDebugMargin(m2);
PixelMarginToTwips(aPresContext, m2);
m += m2;
if ((isHorizontal && y < insideBorder.y + m.top) ||
(!isHorizontal && x < insideBorder.x + m.left)) {
//printf("**** inside debug border *******\n");
2000-03-31 07:02:06 +00:00
while (child)
{
nsRect r;
child->GetBounds(r);
nsIFrame* childFrame = nsnull;
child->GetFrame(&childFrame);
// if we are not in the child. But in the spacer above the child.
2000-03-31 07:02:06 +00:00
if ((isHorizontal && x >= r.x && x < r.x + r.width) ||
(!isHorizontal && y >= r.y && y < r.y + r.height)) {
aCursor = NS_STYLE_CURSOR_POINTER;
// found it but we already showed it.
if (mDebugChild == child)
return NS_OK;
if (ourFrame->GetContent()) {
printf("---------------\n");
DumpBox(stdout);
printf("\n");
}
2000-03-31 07:02:06 +00:00
if (childFrame->GetContent()) {
printf("child #%d: ", count);
child->DumpBox(stdout);
printf("\n");
2000-03-31 07:02:06 +00:00
}
mDebugChild = child;
nsSize prefSizeCSS(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
nsSize minSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
nsSize maxSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
nscoord flexCSS = NS_INTRINSICSIZE;
nsSize prefSize(0, 0);
nsSize minSize (0, 0);
nsSize maxSize (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
nscoord flexSize = 0;
nscoord ascentSize = 0;
2000-03-31 07:02:06 +00:00
nsIBox::AddCSSPrefSize(state, child, prefSizeCSS);
nsIBox::AddCSSMinSize (state, child, minSizeCSS);
nsIBox::AddCSSMaxSize (state, child, maxSizeCSS);
nsIBox::AddCSSFlex (state, child, flexCSS);
child->GetPrefSize(state, prefSize);
child->GetMinSize(state, minSize);
child->GetMaxSize(state, maxSize);
child->GetFlex(state, flexSize);
child->GetAscent(state, ascentSize);
2000-03-31 07:02:06 +00:00
char min[100];
char pref[100];
char max[100];
char calc[100];
char flex[100];
char ascent[100];
2000-03-31 07:02:06 +00:00
nsSize actualSize;
GetFrameSizeWithMargin(child, actualSize);
nsSize actualSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
GetValue(aPresContext, minSize, minSizeCSS, min);
GetValue(aPresContext, prefSize, prefSizeCSS, pref);
GetValue(aPresContext, maxSize, maxSizeCSS, max);
GetValue(aPresContext, actualSize, actualSizeCSS, calc);
GetValue(aPresContext, flexSize, flexCSS, flex);
GetValue(aPresContext, ascentSize, NS_INTRINSICSIZE, ascent);
printf("min%s, pref%s, max%s, actual%s, flex=%s, ascent=%s\n\n",
2000-03-31 07:02:06 +00:00
min,
pref,
max,
calc,
flex,
ascent
);
2000-03-31 07:02:06 +00:00
return NS_OK;
}
2000-03-31 07:02:06 +00:00
child->GetNextBox(&child);
count++;
}
} else {
}
2000-03-31 07:02:06 +00:00
mDebugChild = nsnull;
2000-03-31 07:02:06 +00:00
return NS_OK;
}
#endif
2000-03-31 07:02:06 +00:00
nsresult
nsBoxFrame::GetFrameSizeWithMargin(nsIBox* aBox, nsSize& aSize)
2000-03-31 07:02:06 +00:00
{
nsRect rect(0,0,0,0);
aBox->GetBounds(rect);
nsMargin margin(0,0,0,0);
aBox->GetMargin(margin);
rect.Inflate(margin);
aSize.width = rect.width;
aSize.height = rect.height;
return NS_OK;
}
/**
* Boxed don't support fixed positionioning of their children.
*/
nsresult
nsBoxFrame::CreateViewForFrame(nsPresContext* aPresContext,
nsIFrame* aFrame,
nsStyleContext* aStyleContext,
PRBool aForce)
{
// If we don't yet have a view, see if we need a view
if (!aFrame->HasView()) {
PRInt32 zIndex = 0;
PRBool autoZIndex = PR_FALSE;
PRBool fixedBackgroundAttachment = PR_FALSE;
const nsStyleBackground* bg;
PRBool isCanvas;
PRBool hasBG =
nsCSSRendering::FindBackground(aPresContext, aFrame, &bg, &isCanvas);
const nsStyleDisplay* disp = aStyleContext->GetStyleDisplay();
if (disp->mOpacity != 1.0f) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsBoxFrame::CreateViewForFrame: frame=%p opacity=%g",
aFrame, disp->mOpacity));
aForce = PR_TRUE;
}
// See if the frame has a fixed background attachment
if (hasBG && NS_STYLE_BG_ATTACHMENT_FIXED == bg->mBackgroundAttachment) {
aForce = PR_TRUE;
fixedBackgroundAttachment = PR_TRUE;
}
// See if the frame is a scrolled frame
if (!aForce) {
if (aStyleContext->GetPseudoType() == nsCSSAnonBoxes::scrolledContent) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsBoxFrame::CreateViewForFrame: scrolled frame=%p", aFrame));
aForce = PR_TRUE;
}
}
if (aForce) {
// Create a view
nsIFrame* parent = aFrame->GetAncestorWithView();
NS_ASSERTION(parent, "GetAncestorWithView failed");
nsIView* parentView = parent->GetView();
NS_ASSERTION(parentView, "no parent with view");
// Create a view
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
nsIView *view;
nsresult result = CallCreateInstance(kViewCID, &view);
if (NS_SUCCEEDED(result)) {
nsIViewManager* viewManager = parentView->GetViewManager();
NS_ASSERTION(nsnull != viewManager, "null view manager");
// Initialize the view
view->Init(viewManager, aFrame->GetRect(), parentView);
// If the frame has a fixed background attachment, then indicate that the
// view's contents should be repainted and not bitblt'd
if (fixedBackgroundAttachment) {
viewManager->SetViewBitBltEnabled(view, PR_FALSE);
}
// Insert the view into the view hierarchy. If the parent view is a
// scrolling view we need to do this differently
nsIScrollableView* scrollingView;
if (NS_SUCCEEDED(CallQueryInterface(parentView, &scrollingView))) {
scrollingView->SetScrolledView(view);
} else {
viewManager->SetViewZIndex(view, autoZIndex, zIndex);
// XXX put view last in document order until we can do better
viewManager->InsertChild(parentView, view, nsnull, PR_TRUE);
}
// See if the view should be hidden
PRBool viewIsVisible = PR_TRUE;
PRBool viewHasTransparentContent =
!isCanvas &&
(!hasBG ||
(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT));
const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
if (NS_STYLE_VISIBILITY_COLLAPSE == vis->mVisible) {
viewIsVisible = PR_FALSE;
}
else if (NS_STYLE_VISIBILITY_HIDDEN == vis->mVisible) {
// If it has a widget, hide the view because the widget can't deal with it
if (view->HasWidget()) {
viewIsVisible = PR_FALSE;
}
else {
// If it's a container element, then leave the view visible, but
// mark it as having transparent content. The reason we need to
// do this is that child elements can override their parent's
// hidden visibility and be visible anyway.
//
// Because this function is called before processing the content
// object's child elements, we can't tell if it's a leaf by looking
// at whether the frame has any child frames
nsIContent* content = aFrame->GetContent();
if (content && content->IsContentOfType(nsIContent::eELEMENT)) {
// The view needs to be visible, but marked as having transparent
// content
viewHasTransparentContent = PR_TRUE;
} else {
// Go ahead and hide the view
viewIsVisible = PR_FALSE;
}
}
}
if (viewIsVisible) {
if (viewHasTransparentContent) {
viewManager->SetViewContentTransparency(view, PR_TRUE);
}
} else {
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
}
viewManager->SetViewOpacity(view, disp->mOpacity);
}
// Remember our view
aFrame->SetView(view);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsBoxFrame::CreateViewForFrame: frame=%p view=%p",
aFrame));
return result;
}
}
return NS_OK;
}
// If you make changes to this function, check its counterparts
// in nsTextBoxFrame and nsAreaFrame
nsresult
nsBoxFrame::RegUnregAccessKey(nsPresContext* aPresContext, PRBool aDoReg)
{
// if we have no content, we can't do anything
if (!mContent)
return NS_ERROR_FAILURE;
// find out what type of element this is
nsIAtom *atom = mContent->Tag();
// only support accesskeys for the following elements
if (atom != nsXULAtoms::button &&
atom != nsXULAtoms::toolbarbutton &&
atom != nsXULAtoms::checkbox &&
atom != nsXULAtoms::textbox &&
atom != nsXULAtoms::tab &&
atom != nsXULAtoms::radio) {
return NS_OK;
}
nsAutoString accessKey;
mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::accesskey, accessKey);
if (accessKey.IsEmpty())
return NS_OK;
// With a valid PresContext we can get the ESM
// and register the access key
nsIEventStateManager *esm = aPresContext->EventStateManager();
nsresult rv;
PRUint32 key = accessKey.First();
if (aDoReg)
rv = esm->RegisterAccessKey(mContent, key);
else
rv = esm->UnregisterAccessKey(mContent, key);
return rv;
}
void
nsBoxFrame::FireDOMEvent(nsPresContext *aPresContext, const nsAString& aDOMEventName)
{
if (mContent) {
// Fire a DOM event for the title change.
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
mContent->GetListenerManager(getter_AddRefs(manager));
if (manager &&
NS_SUCCEEDED(manager->CreateEvent(aPresContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
event->InitEvent(aDOMEventName, PR_TRUE, PR_TRUE);
PRBool noDefault;
aPresContext->EventStateManager()->DispatchNewEvent(mContent, event,
&noDefault);
}
}
}