1998-04-13 20:24:54 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIContentDelegate.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIStyleSet.h"
|
|
|
|
#include "nsIStyleContext.h"
|
1998-05-20 16:24:54 +00:00
|
|
|
#include "nsFrame.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsReflowCommand.h"
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "plhash.h"
|
|
|
|
|
|
|
|
#undef NOISY
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
static PLHashNumber
|
|
|
|
HashKey(nsIFrame* key)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return (PLHashNumber) key;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
static PRIntn
|
|
|
|
CompareKeys(nsIFrame* key1, nsIFrame* key2)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return key1 == key2;
|
|
|
|
}
|
|
|
|
|
|
|
|
class FrameHashTable {
|
|
|
|
public:
|
|
|
|
FrameHashTable();
|
|
|
|
~FrameHashTable();
|
|
|
|
|
|
|
|
void* Get(nsIFrame* aKey);
|
|
|
|
void* Put(nsIFrame* aKey, void* aValue);
|
|
|
|
void* Remove(nsIFrame* aKey);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
PLHashTable* mTable;
|
|
|
|
};
|
|
|
|
|
|
|
|
FrameHashTable::FrameHashTable()
|
|
|
|
{
|
|
|
|
mTable = PL_NewHashTable(8, (PLHashFunction) HashKey,
|
|
|
|
(PLHashComparator) CompareKeys,
|
|
|
|
(PLHashComparator) nsnull,
|
|
|
|
nsnull, nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
FrameHashTable::~FrameHashTable()
|
|
|
|
{
|
|
|
|
// XXX if debugging then we should assert that the table is empty
|
|
|
|
PL_HashTableDestroy(mTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the data associated with a frame.
|
|
|
|
*/
|
1998-05-09 03:22:41 +00:00
|
|
|
void*
|
|
|
|
FrameHashTable::Get(nsIFrame* aKey)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
PRInt32 hashCode = (PRInt32) aKey;
|
|
|
|
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
|
|
|
PLHashEntry* he = *hep;
|
|
|
|
if (nsnull != he) {
|
|
|
|
return he->value;
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create an association between a frame and some data. This call
|
|
|
|
* returns an old association if there was one (or nsnull if there
|
|
|
|
* wasn't).
|
|
|
|
*/
|
1998-05-09 03:22:41 +00:00
|
|
|
void*
|
|
|
|
FrameHashTable::Put(nsIFrame* aKey, void* aData)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
PRInt32 hashCode = (PRInt32) aKey;
|
|
|
|
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
|
|
|
PLHashEntry* he = *hep;
|
|
|
|
if (nsnull != he) {
|
|
|
|
void* oldValue = he->value;
|
|
|
|
he->value = aData;
|
|
|
|
return oldValue;
|
|
|
|
}
|
|
|
|
PL_HashTableRawAdd(mTable, hep, hashCode, aKey, aData);
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove an association between a frame and it's data. This returns
|
|
|
|
* the old associated data.
|
|
|
|
*/
|
1998-05-09 03:22:41 +00:00
|
|
|
void*
|
|
|
|
FrameHashTable::Remove(nsIFrame* aKey)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
PRInt32 hashCode = (PRInt32) aKey;
|
|
|
|
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
|
|
|
PLHashEntry* he = *hep;
|
|
|
|
void* oldValue = nsnull;
|
|
|
|
if (nsnull != he) {
|
|
|
|
oldValue = he->value;
|
|
|
|
PL_HashTableRawRemove(mTable, hep, he);
|
|
|
|
}
|
|
|
|
return oldValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID);
|
|
|
|
static NS_DEFINE_IID(kIDocumentObserverIID, NS_IDOCUMENTOBSERVER_IID);
|
|
|
|
|
|
|
|
class PresShell : public nsIPresShell {
|
|
|
|
public:
|
|
|
|
PresShell();
|
|
|
|
|
|
|
|
void* operator new(size_t sz) {
|
|
|
|
void* rv = new char[sz];
|
|
|
|
nsCRT::zero(rv, sz);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIDocumentObserver
|
|
|
|
NS_IMETHOD SetTitle(const nsString& aTitle);
|
|
|
|
virtual void BeginUpdate();
|
|
|
|
virtual void EndUpdate();
|
|
|
|
virtual void ContentChanged(nsIContent* aContent,
|
1998-05-06 16:28:55 +00:00
|
|
|
nsISupports* aSubContent);
|
1998-04-13 20:24:54 +00:00
|
|
|
virtual void ContentAppended(nsIContent* aContainer);
|
|
|
|
virtual void ContentInserted(nsIContent* aContainer,
|
|
|
|
nsIContent* aChild,
|
|
|
|
PRInt32 aIndexInContainer);
|
|
|
|
virtual void ContentReplaced(nsIContent* aContainer,
|
|
|
|
nsIContent* aOldChild,
|
|
|
|
nsIContent* aNewChild,
|
|
|
|
PRInt32 aIndexInContainer);
|
|
|
|
virtual void ContentWillBeRemoved(nsIContent* aContainer,
|
|
|
|
nsIContent* aChild,
|
|
|
|
PRInt32 aIndexInContainer);
|
|
|
|
virtual void ContentHasBeenRemoved(nsIContent* aContainer,
|
|
|
|
nsIContent* aChild,
|
|
|
|
PRInt32 aIndexInContainer);
|
|
|
|
virtual void StyleSheetAdded(nsIStyleSheet* aStyleSheet);
|
|
|
|
|
|
|
|
// nsIPresShell
|
|
|
|
virtual nsresult Init(nsIDocument* aDocument,
|
|
|
|
nsIPresContext* aPresContext,
|
|
|
|
nsIViewManager* aViewManager,
|
|
|
|
nsIStyleSet* aStyleSet);
|
|
|
|
virtual nsIDocument* GetDocument();
|
|
|
|
virtual nsIPresContext* GetPresContext();
|
|
|
|
virtual nsIViewManager* GetViewManager();
|
|
|
|
virtual nsIStyleSet* GetStyleSet();
|
1998-05-09 03:22:41 +00:00
|
|
|
NS_IMETHOD EnterReflowLock();
|
|
|
|
NS_IMETHOD ExitReflowLock();
|
1998-04-13 20:24:54 +00:00
|
|
|
virtual void BeginObservingDocument();
|
|
|
|
virtual void EndObservingDocument();
|
|
|
|
virtual void ResizeReflow(nscoord aWidth, nscoord aHeight);
|
|
|
|
virtual nsIFrame* GetRootFrame();
|
|
|
|
virtual nsIFrame* FindFrameWithContent(nsIContent* aContent);
|
|
|
|
virtual void AppendReflowCommand(nsReflowCommand* aReflowCommand);
|
|
|
|
virtual void ProcessReflowCommands();
|
|
|
|
virtual void PutCachedData(nsIFrame* aKeyFrame, void* aData);
|
|
|
|
virtual void* GetCachedData(nsIFrame* aKeyFrame);
|
|
|
|
virtual void* RemoveCachedData(nsIFrame* aKeyFrame);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
~PresShell();
|
|
|
|
|
1998-05-20 16:24:54 +00:00
|
|
|
void InitFrameVerifyTreeLogModuleInfo();
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
FrameHashTable* mCache;
|
|
|
|
nsIDocument* mDocument;
|
|
|
|
nsIPresContext* mPresContext;
|
|
|
|
nsIStyleSet* mStyleSet;
|
|
|
|
nsIFrame* mRootFrame;
|
|
|
|
nsIViewManager* mViewManager;
|
|
|
|
PRUint32 mUpdateCount;
|
|
|
|
nsVoidArray mReflowCommands;
|
1998-05-09 03:22:41 +00:00
|
|
|
PRUint32 mReflowLockCount;
|
1998-04-13 20:24:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
PresShell::PresShell()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsrefcnt
|
|
|
|
PresShell::AddRef(void)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return ++mRefCnt;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsrefcnt
|
|
|
|
PresShell::Release(void)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(0 != mRefCnt, "bad refcnt");
|
|
|
|
if (--mRefCnt == 0) {
|
|
|
|
delete this;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return mRefCnt;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsresult
|
|
|
|
PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (aIID.Equals(kIPresShellIID)) {
|
|
|
|
*aInstancePtr = (void*) ((nsIPresShell*) this);
|
|
|
|
AddRef();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (aIID.Equals(kIDocumentObserverIID)) {
|
|
|
|
*aInstancePtr = (void*) ((nsIDocumentObserver*) this);
|
|
|
|
AddRef();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (aIID.Equals(kISupportsIID)) {
|
|
|
|
*aInstancePtr = (void*) ((nsISupports*) ((nsIPresShell*)this));
|
|
|
|
AddRef();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PresShell::~PresShell()
|
|
|
|
{
|
|
|
|
delete mCache;
|
|
|
|
|
|
|
|
if (nsnull != mDocument) {
|
|
|
|
mDocument->DeleteShell(this);
|
|
|
|
NS_RELEASE(mDocument);
|
|
|
|
}
|
|
|
|
if (nsnull != mRootFrame) {
|
|
|
|
mRootFrame->DeleteFrame();
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(mPresContext);
|
|
|
|
NS_IF_RELEASE(mViewManager);
|
|
|
|
NS_IF_RELEASE(mStyleSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the presentation shell. Create view manager and style
|
|
|
|
* manager.
|
|
|
|
*/
|
1998-05-09 03:22:41 +00:00
|
|
|
nsresult
|
|
|
|
PresShell::Init(nsIDocument* aDocument,
|
|
|
|
nsIPresContext* aPresContext,
|
|
|
|
nsIViewManager* aViewManager,
|
|
|
|
nsIStyleSet* aStyleSet)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != aDocument, "null ptr");
|
|
|
|
NS_PRECONDITION(nsnull != aPresContext, "null ptr");
|
|
|
|
NS_PRECONDITION(nsnull != aViewManager, "null ptr");
|
|
|
|
if ((nsnull == aDocument) || (nsnull == aPresContext) ||
|
|
|
|
(nsnull == aViewManager)) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
if (nsnull != mDocument) {
|
|
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
mCache = new FrameHashTable();
|
|
|
|
|
|
|
|
mDocument = aDocument;
|
|
|
|
NS_ADDREF(aDocument);
|
|
|
|
mViewManager = aViewManager;
|
|
|
|
NS_ADDREF(mViewManager);
|
|
|
|
|
|
|
|
// Bind the context to the presentation shell.
|
|
|
|
mPresContext = aPresContext;
|
|
|
|
NS_ADDREF(aPresContext);
|
|
|
|
aPresContext->SetShell(this);
|
|
|
|
|
|
|
|
mStyleSet = aStyleSet;
|
|
|
|
NS_ADDREF(aStyleSet);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
NS_METHOD
|
|
|
|
PresShell::EnterReflowLock()
|
|
|
|
{
|
|
|
|
printf("enter reflow lock\n");
|
|
|
|
++mReflowLockCount;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD
|
|
|
|
PresShell::ExitReflowLock()
|
|
|
|
{
|
|
|
|
printf("exit reflow lock\n");
|
1998-05-12 01:30:40 +00:00
|
|
|
PRUint32 newReflowLockCount = mReflowLockCount - 1;
|
|
|
|
if (newReflowLockCount == 0) {
|
|
|
|
ProcessReflowCommands();
|
1998-05-09 03:22:41 +00:00
|
|
|
}
|
1998-05-12 01:30:40 +00:00
|
|
|
mReflowLockCount = newReflowLockCount;
|
1998-05-09 03:22:41 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocument*
|
|
|
|
PresShell::GetDocument()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(mDocument);
|
|
|
|
return mDocument;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsIPresContext*
|
|
|
|
PresShell::GetPresContext()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(mPresContext);
|
|
|
|
return mPresContext;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsIViewManager*
|
|
|
|
PresShell::GetViewManager()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(mViewManager);
|
|
|
|
return mViewManager;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsIStyleSet*
|
|
|
|
PresShell::GetStyleSet()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(mStyleSet);
|
|
|
|
return mStyleSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make shell be a document observer
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::BeginObservingDocument()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (nsnull != mDocument) {
|
|
|
|
mDocument->AddObserver(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make shell stop being a document observer
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::EndObservingDocument()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (nsnull != mDocument) {
|
|
|
|
mDocument->RemoveObserver(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (nsnull != mPresContext) {
|
|
|
|
nsRect r(0, 0, aWidth, aHeight);
|
|
|
|
mPresContext->SetVisibleArea(r);
|
|
|
|
}
|
|
|
|
|
1998-05-25 17:31:49 +00:00
|
|
|
nsReflowReason reflowReason = eReflowReason_Resize;
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
if (nsnull == mRootFrame) {
|
|
|
|
if (nsnull != mDocument) {
|
|
|
|
nsIContent* root = mDocument->GetRootContent();
|
|
|
|
if (nsnull != root) {
|
|
|
|
nsIContentDelegate* cd = root->GetDelegate(mPresContext);
|
|
|
|
if (nsnull != cd) {
|
1998-05-07 00:08:20 +00:00
|
|
|
nsIStyleContext* rootSC =
|
|
|
|
mPresContext->ResolveStyleContextFor(root, nsnull);
|
|
|
|
nsresult rv = cd->CreateFrame(mPresContext, root, nsnull,
|
|
|
|
rootSC, mRootFrame);
|
|
|
|
NS_RELEASE(rootSC);
|
1998-04-13 20:24:54 +00:00
|
|
|
NS_RELEASE(cd);
|
1998-05-25 17:31:49 +00:00
|
|
|
reflowReason = eReflowReason_Initial;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
// Bind root frame to root view (and root window)
|
|
|
|
nsIView* rootView = mViewManager->GetRootView();
|
|
|
|
mRootFrame->SetView(rootView);
|
|
|
|
NS_RELEASE(rootView);
|
|
|
|
}
|
|
|
|
NS_RELEASE(root);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nsnull != mRootFrame) {
|
|
|
|
// Kick off a top-down reflow
|
1998-05-20 16:24:54 +00:00
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
|
|
|
|
("enter nsPresShell::ResizeReflow: %d,%d", aWidth, aHeight));
|
1998-04-13 20:24:54 +00:00
|
|
|
#ifdef NS_DEBUG
|
1998-05-20 16:24:54 +00:00
|
|
|
if (nsIFrame::GetVerifyTreeEnable()) {
|
|
|
|
mRootFrame->VerifyTree();
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
#endif
|
1998-05-22 18:36:40 +00:00
|
|
|
nsRect bounds;
|
|
|
|
mPresContext->GetVisibleArea(bounds);
|
1998-05-20 16:24:54 +00:00
|
|
|
nsSize maxSize(bounds.width, bounds.height);
|
1998-05-25 17:31:49 +00:00
|
|
|
nsReflowMetrics desiredSize(nsnull);
|
1998-05-12 04:17:56 +00:00
|
|
|
nsReflowStatus status;
|
1998-05-25 17:31:49 +00:00
|
|
|
nsReflowState reflowState(reflowReason, maxSize);
|
|
|
|
|
|
|
|
mRootFrame->Reflow(mPresContext, desiredSize, reflowState, status);
|
1998-04-13 20:24:54 +00:00
|
|
|
mRootFrame->SizeTo(desiredSize.width, desiredSize.height);
|
|
|
|
#ifdef NS_DEBUG
|
1998-05-20 16:24:54 +00:00
|
|
|
if (nsIFrame::GetVerifyTreeEnable()) {
|
|
|
|
mRootFrame->VerifyTree();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
#endif
|
1998-05-20 16:24:54 +00:00
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow"));
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// XXX if debugging then we should assert that the cache is empty
|
|
|
|
} else {
|
|
|
|
#ifdef NOISY
|
|
|
|
printf("PresShell::ResizeReflow: null root frame\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsIFrame*
|
|
|
|
PresShell::GetRootFrame()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return mRootFrame;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
NS_METHOD
|
|
|
|
PresShell::SetTitle(const nsString& aTitle)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (nsnull != mPresContext) {
|
|
|
|
nsISupports* container;
|
|
|
|
if (NS_OK == mPresContext->GetContainer(&container)) {
|
|
|
|
if (nsnull != container) {
|
|
|
|
nsIDocumentObserver* docob;
|
|
|
|
if (NS_OK == container->QueryInterface(kIDocumentObserverIID,
|
|
|
|
(void**) &docob)) {
|
|
|
|
docob->SetTitle(aTitle);
|
|
|
|
NS_RELEASE(docob);
|
|
|
|
}
|
|
|
|
NS_RELEASE(container);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::BeginUpdate()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
mUpdateCount++;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::EndUpdate()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(0 != mUpdateCount, "too many EndUpdate's");
|
|
|
|
if (--mUpdateCount == 0) {
|
|
|
|
// XXX do something here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::AppendReflowCommand(nsReflowCommand* aReflowCommand)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
mReflowCommands.AppendElement(aReflowCommand);
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ProcessReflowCommands()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (0 != mReflowCommands.Count()) {
|
1998-05-25 17:31:49 +00:00
|
|
|
nsReflowMetrics desiredSize(nsnull);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
while (0 != mReflowCommands.Count()) {
|
|
|
|
nsReflowCommand* rc = (nsReflowCommand*) mReflowCommands.ElementAt(0);
|
|
|
|
mReflowCommands.RemoveElementAt(0);
|
|
|
|
|
|
|
|
// Dispatch the reflow command
|
1998-04-17 01:41:24 +00:00
|
|
|
nsSize maxSize;
|
|
|
|
|
|
|
|
mRootFrame->GetSize(maxSize);
|
1998-04-13 20:24:54 +00:00
|
|
|
rc->Dispatch(desiredSize, maxSize);
|
|
|
|
delete rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Place and size the root frame
|
|
|
|
mRootFrame->SizeTo(desiredSize.width, desiredSize.height);
|
|
|
|
#ifdef NS_DEBUG
|
1998-05-20 16:24:54 +00:00
|
|
|
if (nsIFrame::GetVerifyTreeEnable()) {
|
|
|
|
mRootFrame->VerifyTree();
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ContentChanged(nsIContent* aContent,
|
|
|
|
nsISupports* aSubContent)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-05-06 16:28:55 +00:00
|
|
|
NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
|
1998-05-12 01:30:40 +00:00
|
|
|
NS_PRECONDITION(0 != mReflowLockCount, "unlocked reflow");
|
1998-05-06 16:28:55 +00:00
|
|
|
|
|
|
|
// Notify the first frame that maps the content. It will generate a reflow
|
|
|
|
// command
|
|
|
|
nsIFrame* frame = FindFrameWithContent(aContent);
|
|
|
|
NS_PRECONDITION(nsnull != frame, "null frame");
|
1998-05-08 04:59:35 +00:00
|
|
|
frame->ContentChanged(this, mPresContext, aContent, aSubContent);
|
1998-05-12 01:30:40 +00:00
|
|
|
|
|
|
|
if (1 == mReflowLockCount) {
|
|
|
|
ProcessReflowCommands();
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ContentAppended(nsIContent* aContainer)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
|
1998-05-03 03:51:48 +00:00
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsIContent* parentContainer = aContainer;
|
|
|
|
while (nsnull != parentContainer) {
|
|
|
|
nsIFrame* frame = FindFrameWithContent(parentContainer);
|
|
|
|
if (nsnull != frame) {
|
|
|
|
frame->ContentAppended(this, mPresContext, aContainer);
|
|
|
|
ProcessReflowCommands();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
parentContainer = parentContainer->GetParent();
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ContentInserted(nsIContent* aContainer,
|
|
|
|
nsIContent* aChild,
|
|
|
|
PRInt32 aIndexInContainer)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
|
1998-05-03 03:51:48 +00:00
|
|
|
|
|
|
|
nsIFrame* frame = FindFrameWithContent(aContainer);
|
|
|
|
NS_PRECONDITION(nsnull != frame, "null frame");
|
|
|
|
frame->ContentInserted(this, mPresContext, aContainer, aChild, aIndexInContainer);
|
1998-04-13 20:24:54 +00:00
|
|
|
ProcessReflowCommands();
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ContentReplaced(nsIContent* aContainer,
|
|
|
|
nsIContent* aOldChild,
|
|
|
|
nsIContent* aNewChild,
|
|
|
|
PRInt32 aIndexInContainer)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
|
1998-05-03 03:51:48 +00:00
|
|
|
|
|
|
|
nsIFrame* frame = FindFrameWithContent(aContainer);
|
|
|
|
NS_PRECONDITION(nsnull != frame, "null frame");
|
|
|
|
frame->ContentReplaced(this, mPresContext, aContainer, aOldChild,
|
|
|
|
aNewChild, aIndexInContainer);
|
1998-04-13 20:24:54 +00:00
|
|
|
ProcessReflowCommands();
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX keep this?
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ContentWillBeRemoved(nsIContent* aContainer,
|
|
|
|
nsIContent* aChild,
|
|
|
|
PRInt32 aIndexInContainer)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::ContentHasBeenRemoved(nsIContent* aContainer,
|
|
|
|
nsIContent* aChild,
|
|
|
|
PRInt32 aIndexInContainer)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
|
1998-05-03 03:51:48 +00:00
|
|
|
|
|
|
|
nsIFrame* frame = FindFrameWithContent(aContainer);
|
|
|
|
NS_PRECONDITION(nsnull != frame, "null frame");
|
|
|
|
frame->ContentDeleted(this, mPresContext, aContainer, aChild, aIndexInContainer);
|
1998-04-13 20:24:54 +00:00
|
|
|
ProcessReflowCommands();
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::StyleSheetAdded(nsIStyleSheet* aStyleSheet)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
static nsIFrame*
|
|
|
|
FindFrameWithContent(nsIFrame* aFrame, nsIContent* aContent)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-04-17 01:41:24 +00:00
|
|
|
nsIContent* frameContent;
|
|
|
|
|
|
|
|
aFrame->GetContent(frameContent);
|
1998-04-13 20:24:54 +00:00
|
|
|
if (frameContent == aContent) {
|
|
|
|
NS_RELEASE(frameContent);
|
|
|
|
return aFrame;
|
|
|
|
}
|
|
|
|
NS_RELEASE(frameContent);
|
|
|
|
|
1998-04-17 01:41:24 +00:00
|
|
|
aFrame->FirstChild(aFrame);
|
1998-04-13 20:24:54 +00:00
|
|
|
while (aFrame) {
|
|
|
|
nsIFrame* result = FindFrameWithContent(aFrame, aContent);
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-04-17 01:41:24 +00:00
|
|
|
aFrame->GetNextSibling(aFrame);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
nsIFrame*
|
|
|
|
PresShell::FindFrameWithContent(nsIContent* aContent)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
// For the time being do a brute force depth-first search of
|
|
|
|
// the frame tree
|
|
|
|
return ::FindFrameWithContent(mRootFrame, aContent);
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void
|
|
|
|
PresShell::PutCachedData(nsIFrame* aKeyFrame, void* aData)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
void* oldData = mCache->Put(aKeyFrame, aData);
|
|
|
|
NS_ASSERTION(nsnull == oldData, "bad cached data usage");
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void*
|
|
|
|
PresShell::GetCachedData(nsIFrame* aKeyFrame)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return mCache->Get(aKeyFrame);
|
|
|
|
}
|
|
|
|
|
1998-05-09 03:22:41 +00:00
|
|
|
void*
|
|
|
|
PresShell::RemoveCachedData(nsIFrame* aKeyFrame)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return mCache->Remove(aKeyFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_LAYOUT nsresult
|
|
|
|
NS_NewPresShell(nsIPresShell** aInstancePtrResult)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
|
|
|
if (nsnull == aInstancePtrResult) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
PresShell* it = new PresShell();
|
|
|
|
if (nsnull == it) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
return it->QueryInterface(kIPresShellIID, (void **) aInstancePtrResult);
|
|
|
|
}
|