Mozilla/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp
karnaze%netscape.com d8577654db bug 113424 - mechanism for percent height frames inside table cells to receive special height reflow. sr=attinasi, r=alexsavulov
git-svn-id: svn://10.0.0.236/trunk@110006 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-07 14:51:12 +00:00

322 lines
8.9 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.
*
* 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):
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsLeafBoxFrame.h"
#include "nsBoxFrame.h"
#include "nsCOMPtr.h"
#include "nsIDeviceContext.h"
#include "nsIFontMetrics.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIStyleContext.h"
#include "nsIContent.h"
#include "nsINameSpaceManager.h"
#include "nsBoxLayoutState.h"
#include "nsWidgetsCID.h"
#include "nsIViewManager.h"
#include "nsHTMLContainerFrame.h"
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewLeafBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsLeafBoxFrame* it = new (aPresShell) nsLeafBoxFrame(aPresShell);
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
// it->SetFlags(aFlags);
*aNewFrame = it;
return NS_OK;
} // NS_NewTextFrame
nsLeafBoxFrame::nsLeafBoxFrame(nsIPresShell* aShell):nsBox(aShell)
{
}
void
nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
{
#ifdef DEBUG
GetFrameName(aName);
#endif
}
/**
* Initialize us. This is a good time to get the alignment of the box
*/
NS_IMETHODIMP
nsLeafBoxFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
// see if we need a widget
nsCOMPtr<nsIBox> parent (do_QueryInterface(aParent));
if (parent) {
PRBool needsWidget = PR_FALSE;
parent->ChildrenMustHaveWidgets(needsWidget);
if (needsWidget) {
nsIView* view = nsnull;
GetView(aPresContext, &view);
if (!view) {
nsHTMLContainerFrame::CreateViewForFrame(aPresContext,this,mStyleContext,nsnull,PR_TRUE);
GetView(aPresContext, &view);
}
nsIWidget* widget;
view->GetWidget(widget);
if (!widget)
view->CreateWidget(kWidgetCID);
}
}
mMouseThrough = unset;
UpdateMouseThrough();
return rv;
}
NS_IMETHODIMP
nsLeafBoxFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType,
PRInt32 aHint)
{
nsresult rv = nsLeafFrame::AttributeChanged(aPresContext, aChild,
aNameSpaceID, aAttribute, aModType, aHint);
if (aAttribute == nsXULAtoms::mousethrough)
UpdateMouseThrough();
return rv;
}
void nsLeafBoxFrame::UpdateMouseThrough()
{
if (mContent) {
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::mousethrough, value)) {
if (value.EqualsIgnoreCase("never"))
mMouseThrough = never;
else if (value.EqualsIgnoreCase("always"))
mMouseThrough = always;
}
}
}
NS_IMETHODIMP
nsLeafBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer,
nsIFrame** aFrame)
{
if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND))
return NS_ERROR_FAILURE;
if (!mRect.Contains(aPoint))
return NS_ERROR_FAILURE;
*aFrame = this;
return NS_OK;
}
NS_IMETHODIMP
nsLeafBoxFrame::GetFrame(nsIFrame** aFrame)
{
*aFrame = this;
return NS_OK;
}
NS_IMETHODIMP
nsLeafBoxFrame::DidReflow(nsIPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus)
{
PRBool isDirty = mState & NS_FRAME_IS_DIRTY;
PRBool hasDirtyChildren = mState & NS_FRAME_HAS_DIRTY_CHILDREN;
nsresult rv = nsFrame::DidReflow(aPresContext, aReflowState, aStatus);
if (isDirty)
mState |= NS_FRAME_IS_DIRTY;
if (hasDirtyChildren)
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
return rv;
}
NS_IMETHODIMP
nsLeafBoxFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame", aReflowState.reason);
NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0");
aStatus = NS_FRAME_COMPLETE;
// create the layout state
nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize);
state.HandleReflow(this);
nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight);
nsMargin m;
GetBorderAndPadding(m);
// this happens sometimes. So lets handle it gracefully.
if (aReflowState.mComputedHeight == 0) {
nsSize minSize(0,0);
GetMinSize(state, minSize);
computedSize.height = minSize.height - m.top - m.bottom;
}
// if we are told to layout intrinic then get our preferred size.
if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
nsSize prefSize;
nsSize minSize;
nsSize maxSize;
GetPrefSize(state, prefSize);
GetMinSize(state, minSize);
GetMaxSize(state, maxSize);
BoundsCheck(minSize, prefSize, maxSize);
// get our desiredSize
if (aReflowState.mComputedWidth == NS_INTRINSICSIZE)
computedSize.width = prefSize.width - m.left - m.right;
if (aReflowState.mComputedHeight == NS_INTRINSICSIZE || aReflowState.mComputedHeight == 0)
computedSize.height = prefSize.height - m.top - m.bottom;
}
nsRect r(0,0,computedSize.width, computedSize.height);
r.Inflate(m);
r.x = mRect.x;
r.y = mRect.y;
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;
GetAscent(state, ascent);
aDesiredSize.width = r.width;
aDesiredSize.height = r.height;
aDesiredSize.ascent = ascent;
aDesiredSize.descent = 0;
return NS_OK;
}
#ifdef DEBUG
NS_IMETHODIMP
nsLeafBoxFrame::GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult);
}
#endif
NS_IMETHODIMP_(nsrefcnt)
nsLeafBoxFrame::AddRef(void)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsLeafBoxFrame::Release(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsLeafBoxFrame::ContentChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
nsISupports* aSubContent)
{
NeedsRecalc();
return nsLeafFrame::ContentChanged(aPresContext, aChild, aSubContent);
}
NS_INTERFACE_MAP_BEGIN(nsLeafBoxFrame)
NS_INTERFACE_MAP_ENTRY(nsIBox)
#ifdef NS_DEBUG
NS_INTERFACE_MAP_ENTRY(nsIFrameDebug)
#endif
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox)
NS_INTERFACE_MAP_END_INHERITING(nsLeafFrame)