1999-04-21 22:46:15 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* 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/
|
1999-04-21 22:46:15 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +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-04-21 22:46:15 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
1999-11-06 03:40:37 +00:00
|
|
|
* Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1999-04-21 22:46:15 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
//
|
|
|
|
// Eric Vaughan
|
|
|
|
// Netscape Communications
|
|
|
|
//
|
|
|
|
// See documentation in associated header file
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "nsDeckFrame.h"
|
|
|
|
#include "nsIStyleContext.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsHTMLIIDs.h"
|
|
|
|
#include "nsUnitConversion.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsXULAtoms.h"
|
1999-05-09 21:46:24 +00:00
|
|
|
#include "nsHTMLAtoms.h"
|
1999-04-21 22:46:15 +00:00
|
|
|
#include "nsIReflowCommand.h"
|
1999-05-19 22:14:11 +00:00
|
|
|
#include "nsHTMLParts.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsStyleChangeList.h"
|
|
|
|
#include "nsCSSRendering.h"
|
1999-07-23 00:11:21 +00:00
|
|
|
#include "nsIViewManager.h"
|
2000-03-31 07:02:06 +00:00
|
|
|
#include "nsBoxLayoutState.h"
|
|
|
|
#include "nsStackLayout.h"
|
2000-06-22 00:48:49 +00:00
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
1999-05-09 21:46:24 +00:00
|
|
|
|
1999-04-21 22:46:15 +00:00
|
|
|
nsresult
|
2000-04-05 00:19:00 +00:00
|
|
|
NS_NewDeckFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIBoxLayout* aLayoutManager)
|
1999-04-21 22:46:15 +00:00
|
|
|
{
|
1999-05-11 22:03:29 +00:00
|
|
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
|
|
|
if (nsnull == aNewFrame) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2000-04-05 00:19:00 +00:00
|
|
|
nsDeckFrame* it = new (aPresShell) nsDeckFrame(aPresShell, aLayoutManager);
|
1999-04-21 22:46:15 +00:00
|
|
|
if (nsnull == it)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
1999-05-11 22:03:29 +00:00
|
|
|
*aNewFrame = it;
|
1999-04-21 22:46:15 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
} // NS_NewDeckFrame
|
|
|
|
|
2000-03-02 03:01:30 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
nsCOMPtr<nsIBoxLayout> nsDeckFrame::gLayout = nsnull;
|
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell, nsIBoxLayout* aLayoutManager):nsBoxFrame(aPresShell),mIndex(0)
|
1999-04-21 22:46:15 +00:00
|
|
|
{
|
2000-04-05 00:19:00 +00:00
|
|
|
// if no layout manager specified us the static sprocket layout
|
|
|
|
nsCOMPtr<nsIBoxLayout> layout = aLayoutManager;
|
|
|
|
|
|
|
|
if (layout == nsnull) {
|
|
|
|
NS_NewStackLayout(aPresShell, layout);
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-05 00:19:00 +00:00
|
|
|
SetLayoutManager(layout);
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
/**
|
|
|
|
* Hack for deck who requires that all its children has widgets
|
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeckFrame::ChildrenMustHaveWidgets(PRBool& aMust)
|
|
|
|
{
|
|
|
|
aMust = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDeckFrame::CreateWidget(nsIPresContext* aPresContext, nsIBox* aBox)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
aBox->GetFrame(&frame);
|
|
|
|
|
|
|
|
nsIView* view = nsnull;
|
|
|
|
frame->GetView(aPresContext, &view);
|
|
|
|
|
|
|
|
if (!view) {
|
|
|
|
nsCOMPtr<nsIStyleContext> context;
|
|
|
|
frame->GetStyleContext(getter_AddRefs(context));
|
|
|
|
nsHTMLContainerFrame::CreateViewForFrame(aPresContext,frame,context,PR_TRUE);
|
|
|
|
frame->GetView(aPresContext, &view);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIWidget* widget;
|
|
|
|
view->GetWidget(widget);
|
|
|
|
|
|
|
|
if (!widget)
|
|
|
|
rv = view->CreateWidget(kWidgetCID);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDeckFrame::CreateWidgets(nsIPresContext* aPresContext)
|
|
|
|
{
|
|
|
|
// create a widget for each child.
|
|
|
|
nsIBox* child = nsnull;
|
|
|
|
GetChildBox(&child);
|
|
|
|
while(child)
|
|
|
|
{
|
|
|
|
CreateWidget(aPresContext, child);
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeckFrame::SetInitialChildList(nsIPresContext* aPresContext,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aChildList)
|
|
|
|
{
|
|
|
|
nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList);
|
|
|
|
//CreateWidgets(aPresContext);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeckFrame::AppendFrames(nsIPresContext* aPresContext,
|
|
|
|
nsIPresShell& aPresShell,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aFrameList)
|
|
|
|
{
|
|
|
|
// Only one child frame allowed
|
|
|
|
nsresult rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
|
|
|
|
//CreateWidgets(aPresContext);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeckFrame::InsertFrames(nsIPresContext* aPresContext,
|
|
|
|
nsIPresShell& aPresShell,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aPrevFrame,
|
|
|
|
nsIFrame* aFrameList)
|
|
|
|
{
|
|
|
|
// Only one child frame allowed
|
|
|
|
nsresult rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
|
|
|
|
//CreateWidgets(aPresContext);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-04-21 22:46:15 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeckFrame::AttributeChanged(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aChild,
|
1999-10-15 23:16:45 +00:00
|
|
|
PRInt32 aNameSpaceID,
|
1999-04-21 22:46:15 +00:00
|
|
|
nsIAtom* aAttribute,
|
|
|
|
PRInt32 aHint)
|
|
|
|
{
|
2000-03-31 07:02:06 +00:00
|
|
|
nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild,
|
1999-10-15 23:16:45 +00:00
|
|
|
aNameSpaceID, aAttribute, aHint);
|
1999-04-21 22:46:15 +00:00
|
|
|
|
1999-04-25 20:07:45 +00:00
|
|
|
|
|
|
|
// if the index changed hide the old element and make the now element visible
|
1999-09-10 23:38:58 +00:00
|
|
|
if (aAttribute == nsHTMLAtoms::index) {
|
2000-06-22 00:48:49 +00:00
|
|
|
IndexChanged(aPresContext);
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
2000-04-25 07:10:48 +00:00
|
|
|
return rv;
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeckFrame::Init(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aContent,
|
|
|
|
nsIFrame* aParent,
|
|
|
|
nsIStyleContext* aStyleContext,
|
|
|
|
nsIFrame* aPrevInFlow)
|
1999-04-21 22:46:15 +00:00
|
|
|
{
|
2000-06-22 00:48:49 +00:00
|
|
|
nsresult rv = nsBoxFrame::Init(aPresContext, aContent,
|
|
|
|
aParent, aStyleContext,
|
|
|
|
aPrevInFlow);
|
|
|
|
|
|
|
|
mIndex = GetSelectedIndex();
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDeckFrame::HideBox(nsIPresContext* aPresContext, nsIBox* aBox)
|
|
|
|
{
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
aBox->GetFrame(&frame);
|
|
|
|
|
|
|
|
nsIView* view = nsnull;
|
|
|
|
frame->GetView(aPresContext, &view);
|
|
|
|
|
|
|
|
if (view) {
|
|
|
|
nsCOMPtr<nsIViewManager> viewManager;
|
|
|
|
view->GetViewManager(*getter_AddRefs(viewManager));
|
|
|
|
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
|
|
|
|
viewManager->ResizeView(view, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
1999-04-21 22:46:15 +00:00
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
void
|
|
|
|
nsDeckFrame::ShowBox(nsIPresContext* aPresContext, nsIBox* aBox)
|
|
|
|
{
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
aBox->GetFrame(&frame);
|
|
|
|
|
|
|
|
nsRect rect;
|
|
|
|
frame->GetRect(rect);
|
|
|
|
nsIView* view = nsnull;
|
|
|
|
frame->GetView(aPresContext, &view);
|
|
|
|
if (view) {
|
|
|
|
nsCOMPtr<nsIViewManager> viewManager;
|
|
|
|
view->GetViewManager(*getter_AddRefs(viewManager));
|
|
|
|
viewManager->ResizeView(view, rect.width, rect.height);
|
|
|
|
viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDeckFrame::IndexChanged(nsIPresContext* aPresContext)
|
|
|
|
{
|
|
|
|
//did the index change?
|
|
|
|
PRInt32 index = GetSelectedIndex();
|
|
|
|
if (index == mIndex)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// redraw
|
|
|
|
nsBoxLayoutState state(aPresContext);
|
|
|
|
Redraw(state);
|
|
|
|
|
|
|
|
// hide the currently showing box
|
|
|
|
nsIBox* currentBox = GetBoxAt(mIndex);
|
|
|
|
HideBox(aPresContext, currentBox);
|
|
|
|
|
|
|
|
// show the new box
|
|
|
|
nsIBox* newBox = GetBoxAt(index);
|
|
|
|
ShowBox(aPresContext, newBox);
|
|
|
|
|
|
|
|
mIndex = index;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsDeckFrame::GetSelectedIndex()
|
|
|
|
{
|
|
|
|
// default index is 0
|
|
|
|
PRInt32 index = 0;
|
1999-04-21 22:46:15 +00:00
|
|
|
|
|
|
|
// get the index attribute
|
|
|
|
nsAutoString value;
|
1999-09-10 23:38:58 +00:00
|
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::index, value))
|
1999-04-21 22:46:15 +00:00
|
|
|
{
|
|
|
|
PRInt32 error;
|
|
|
|
|
|
|
|
// convert it to an integer
|
|
|
|
index = value.ToInteger(&error);
|
|
|
|
}
|
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIBox*
|
|
|
|
nsDeckFrame::GetSelectedBox()
|
|
|
|
{
|
|
|
|
// ok we want to paint only the child that as at the given index
|
|
|
|
PRInt32 index = GetSelectedIndex();
|
|
|
|
|
1999-04-21 22:46:15 +00:00
|
|
|
// get the child at that index.
|
2000-06-22 00:48:49 +00:00
|
|
|
return GetBoxAt(index);
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsDeckFrame::Paint(nsIPresContext* aPresContext,
|
1999-04-21 22:46:15 +00:00
|
|
|
nsIRenderingContext& aRenderingContext,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
nsFramePaintLayer aWhichLayer)
|
|
|
|
{
|
1999-05-19 22:14:11 +00:00
|
|
|
// if a tab is hidden all its children are too.
|
|
|
|
const nsStyleDisplay* disp = (const nsStyleDisplay*)
|
|
|
|
mStyleContext->GetStyleData(eStyleStruct_Display);
|
2000-03-31 07:02:06 +00:00
|
|
|
if (!disp->mVisible)
|
1999-05-19 22:14:11 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
|
2000-03-31 07:02:06 +00:00
|
|
|
if (disp->IsVisible() && mRect.width && mRect.height) {
|
1999-05-19 22:14:11 +00:00
|
|
|
// Paint our background and border
|
|
|
|
PRIntn skipSides = GetSkipSides();
|
|
|
|
const nsStyleColor* color = (const nsStyleColor*)
|
|
|
|
mStyleContext->GetStyleData(eStyleStruct_Color);
|
|
|
|
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
|
|
|
|
mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
|
|
|
|
|
|
|
nsRect rect(0, 0, mRect.width, mRect.height);
|
|
|
|
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
|
|
|
|
aDirtyRect, rect, *color, *spacing, 0, 0);
|
|
|
|
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
|
|
|
|
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
// only paint the seleced box
|
|
|
|
nsIBox* box = GetSelectedBox();
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
box->GetFrame(&frame);
|
1999-05-19 22:14:11 +00:00
|
|
|
|
|
|
|
if (frame != nsnull)
|
|
|
|
PaintChild(aPresContext, aRenderingContext, aDirtyRect, frame, aWhichLayer);
|
1999-04-25 20:07:45 +00:00
|
|
|
|
1999-04-21 22:46:15 +00:00
|
|
|
return NS_OK;
|
1999-05-19 22:14:11 +00:00
|
|
|
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-10-26 04:44:41 +00:00
|
|
|
NS_IMETHODIMP nsDeckFrame::GetFrameForPoint(nsIPresContext* aPresContext,
|
|
|
|
const nsPoint& aPoint,
|
2000-03-31 07:02:06 +00:00
|
|
|
nsFramePaintLayer aWhichLayer,
|
1999-04-21 22:46:15 +00:00
|
|
|
nsIFrame** aFrame)
|
|
|
|
{
|
2000-05-15 04:12:31 +00:00
|
|
|
|
|
|
|
if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// if it is not inside us fail
|
2000-03-22 02:43:08 +00:00
|
|
|
if (!mRect.Contains(aPoint)) {
|
2000-03-31 07:02:06 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2000-03-22 02:43:08 +00:00
|
|
|
}
|
1999-04-21 22:46:15 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// if its not in our child just return us.
|
|
|
|
*aFrame = this;
|
|
|
|
|
1999-04-21 22:46:15 +00:00
|
|
|
// get the selected frame and see if the point is in it.
|
2000-06-22 00:48:49 +00:00
|
|
|
nsIBox* selectedBox = GetSelectedBox();
|
|
|
|
if (selectedBox) {
|
|
|
|
nsIFrame* selectedFrame = nsnull;
|
|
|
|
selectedBox->GetFrame(&selectedFrame);
|
1999-04-21 22:46:15 +00:00
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
nsPoint tmp;
|
|
|
|
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
|
|
|
|
|
|
|
|
return selectedFrame->GetFrameForPoint(aPresContext, tmp, aWhichLayer, aFrame);
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
return NS_OK;
|
1999-04-21 22:46:15 +00:00
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
|
1999-10-29 22:13:57 +00:00
|
|
|
NS_IMETHODIMP
|
2000-03-31 07:02:06 +00:00
|
|
|
nsDeckFrame::Layout(nsBoxLayoutState& aState)
|
1999-05-09 21:46:24 +00:00
|
|
|
{
|
2000-06-22 00:48:49 +00:00
|
|
|
// make sure we tweek the state so it does not resize our children. We will do that.
|
|
|
|
PRUint32 oldFlags = 0;
|
|
|
|
aState.GetLayoutFlags(oldFlags);
|
|
|
|
aState.SetLayoutFlags(NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_VISIBILITY);
|
1999-05-09 21:46:24 +00:00
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
// do a normal layout
|
|
|
|
nsresult rv = nsBoxFrame::Layout(aState);
|
1999-05-19 22:14:11 +00:00
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
// run though each child. Hide all but the selected one
|
2000-03-31 07:02:06 +00:00
|
|
|
nsIBox* box = nsnull;
|
|
|
|
GetChildBox(&box);
|
1999-10-29 22:13:57 +00:00
|
|
|
|
1999-07-23 00:11:21 +00:00
|
|
|
nscoord count = 0;
|
2000-06-22 00:48:49 +00:00
|
|
|
while (box)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
// make collapsed children not show up
|
2000-06-22 00:48:49 +00:00
|
|
|
if (count == mIndex)
|
|
|
|
ShowBox(aState.GetPresContext(), box);
|
|
|
|
else
|
|
|
|
HideBox(aState.GetPresContext(), box);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
nsresult rv2 = box->GetNextBox(&box);
|
|
|
|
NS_ASSERTION(rv2 == NS_OK,"failed to get next child");
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
2000-06-22 00:48:49 +00:00
|
|
|
aState.SetLayoutFlags(oldFlags);
|
1999-07-23 00:11:21 +00:00
|
|
|
|
1999-10-29 22:13:57 +00:00
|
|
|
return rv;
|
1999-07-23 00:11:21 +00:00
|
|
|
}
|
|
|
|
|