Mozilla/mozilla/xpfc/parser/src/nsXPFCXMLContentSink.cpp
dmose%mozilla.org ce50f7d151 updated license boilerplate to xPL 1.1, a=chofmann@netscape.com,r=endico@mozilla.org
git-svn-id: svn://10.0.0.236/trunk@52900 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 02:47:15 +00:00

986 lines
23 KiB
C++

/* -*- 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.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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsHTMLTokens.h"
#include "nsXPFCXMLDTD.h"
#include "nsxpfcCIID.h"
#include "nsIXMLParserObject.h"
#include "nsXPFCXMLContentSink.h"
#include "nsIXPFCMenuBar.h"
#include "nsIXPFCMenuItem.h"
#include "nsIXPFCMenuContainer.h"
#include "nsIXPFCCanvas.h"
#include "nsIButton.h"
#include "nsITextWidget.h"
#include "nsITabWidget.h"
#include "nsWidgetsCID.h"
#include "nsXPFCToolkit.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
static NS_DEFINE_IID(kClassIID, NS_XPFCXMLCONTENTSINK_IID);
static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kIXMLParserObjectIID, NS_IXML_PARSER_OBJECT_IID);
static NS_DEFINE_IID(kCXPFCMenuBarCID, NS_XPFCMENUBAR_CID);
static NS_DEFINE_IID(kCXPFCMenuItemCID, NS_XPFCMENUITEM_CID);
static NS_DEFINE_IID(kCXPFCMenuContainerCID, NS_XPFCMENUCONTAINER_CID);
static NS_DEFINE_IID(kCIXPFCMenuBarIID, NS_IXPFCMENUBAR_IID);
static NS_DEFINE_IID(kCIXPFCMenuItemIID, NS_IXPFCMENUITEM_IID);
static NS_DEFINE_IID(kCIXPFCMenuContainerIID, NS_IXPFCMENUCONTAINER_IID);
static NS_DEFINE_IID(kCXPFCToolbarCID, NS_XPFC_TOOLBAR_CID);
static NS_DEFINE_IID(kCIXPFCToolbarIID, NS_IXPFC_TOOLBAR_IID);
static NS_DEFINE_IID(kCXPFCDialogCID, NS_XPFC_DIALOG_CID);
static NS_DEFINE_IID(kCIXPFCDialogIID, NS_IXPFC_DIALOG_IID);
static NS_DEFINE_IID(kCXPFCCanvasCID, NS_XPFC_CANVAS_CID);
static NS_DEFINE_IID(kIXPFCCanvasIID, NS_IXPFC_CANVAS_IID);
static NS_DEFINE_IID(kCButtonCID, NS_BUTTON_CID);
static NS_DEFINE_IID(kCTextWidgetCID, NS_TEXTFIELD_CID);
static NS_DEFINE_IID(kCTabWidgetCID, NS_TABWIDGET_CID);
static NS_DEFINE_IID(kCXPFCButtonCID, NS_XPFC_BUTTON_CID);
static NS_DEFINE_IID(kCXPButtonCID, NS_XP_BUTTON_CID);
static NS_DEFINE_IID(kCXPFCTabWidgetCID, NS_XPFC_TABWIDGET_CID);
static NS_DEFINE_IID(kCXPFCTextWidgetCID, NS_XPFC_TEXTWIDGET_CID);
static NS_DEFINE_IID(kIXPFCXMLContentSinkIID, NS_IXPFC_XML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kIXPFCContentSinkIID, NS_IXPFC_CONTENT_SINK_IID);
#define XPFC_PARSING_STATE_UNKNOWN 0
#define XPFC_PARSING_STATE_TOOLBAR 1
#define XPFC_PARSING_STATE_MENUBAR 2
#define XPFC_PARSING_STATE_DIALOG 3
#define XPFC_PARSING_STATE_APPLICATION 4
class ContainerListEntry {
public:
nsIXMLParserObject * object;
nsString container;
ContainerListEntry(nsIXMLParserObject * aObject,
nsString aContainer) {
object = aObject;
container = aContainer;
}
~ContainerListEntry() {
}
};
nsXPFCXMLContentSink::nsXPFCXMLContentSink() : nsIHTMLContentSink()
{
NS_INIT_REFCNT();
mViewerContainer = nsnull;
mContainerList = nsnull;
mState = XPFC_PARSING_STATE_UNKNOWN;
static NS_DEFINE_IID(kCVectorCID, NS_ARRAY_CID);
nsresult res = nsRepository::CreateInstance(kCVectorCID,
nsnull,
kCVectorCID,
(void **)&mOrphanMenuList);
if (NS_OK != res)
return ;
mOrphanMenuList->Init();
static NS_DEFINE_IID(kCStackCID, NS_STACK_CID);
res = nsRepository::CreateInstance(kCStackCID,
nsnull,
kCStackCID,
(void **)&mXPFCStack);
if (NS_OK != res)
return ;
mXPFCStack->Init();
if (mContainerList == nsnull) {
static NS_DEFINE_IID(kCVectorIteratorCID, NS_ARRAY_ITERATOR_CID);
static NS_DEFINE_IID(kCVectorCID, NS_ARRAY_CID);
nsresult res = nsRepository::CreateInstance(kCVectorCID,
nsnull,
kCVectorCID,
(void **)&mContainerList);
if (NS_OK != res)
return ;
mContainerList->Init();
}
}
nsXPFCXMLContentSink::~nsXPFCXMLContentSink()
{
NS_RELEASE(mOrphanMenuList);
NS_RELEASE(mXPFCStack);
if (mContainerList != nsnull) {
nsIIterator * iterator;
mContainerList->CreateIterator(&iterator);
iterator->Init();
ContainerListEntry * item;
while(!(iterator->IsDone()))
{
item = (ContainerListEntry *) iterator->CurrentItem();
delete item;
iterator->Next();
}
NS_RELEASE(iterator);
mContainerList->RemoveAll();
NS_RELEASE(mContainerList);
}
}
NS_IMPL_ADDREF(nsXPFCXMLContentSink)
NS_IMPL_RELEASE(nsXPFCXMLContentSink)
nsresult nsXPFCXMLContentSink::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if(aIID.Equals(kISupportsIID)) { //do IUnknown...
*aInstancePtr = (nsIContentSink*)(this);
}
else if(aIID.Equals(kIContentSinkIID)) { //do nsIContentSink base class...
*aInstancePtr = (nsIContentSink*)(this);
}
else if(aIID.Equals(kIHTMLContentSinkIID)) {
*aInstancePtr = (nsIHTMLContentSink*)(this);
}
else if(aIID.Equals(kClassIID)) { //do this class...
*aInstancePtr = (nsXPFCXMLContentSink*)(this);
}
else if(aIID.Equals(kIXPFCXMLContentSinkIID)) { //do this class...
*aInstancePtr = (nsIXPFCXMLContentSink*)(this);
}
else if(aIID.Equals(kIXPFCContentSinkIID)) { //do this class...
*aInstancePtr = (nsIXPFCContentSink*)(this);
}
else {
*aInstancePtr=0;
return NS_NOINTERFACE;
}
((nsISupports*) *aInstancePtr)->AddRef();
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::Init()
{
return NS_OK;
}
/*
* this method gets invoked whenever a container type tag
* is encountered.
*/
NS_IMETHODIMP nsXPFCXMLContentSink::OpenContainer(const nsIParserNode& aNode)
{
nsIXMLParserObject * object = nsnull;
eXPFCXMLTags tag = (eXPFCXMLTags) aNode.GetNodeType();
nsresult res;
nsCID aclass;
nsString toLoadUrl;
if (eXPFCXMLTag_menubar == tag)
mState = XPFC_PARSING_STATE_MENUBAR;
else if (eXPFCXMLTag_toolbar == tag)
mState = XPFC_PARSING_STATE_TOOLBAR;
else if (eXPFCXMLTag_dialog == tag)
mState = XPFC_PARSING_STATE_DIALOG;
else if (eXPFCXMLTag_application == tag)
mState = XPFC_PARSING_STATE_APPLICATION;
if (mState == XPFC_PARSING_STATE_APPLICATION)
{
if (eXPFCXMLTag_canvas == tag)
{
PRInt32 i = 0;
nsString key,value;
for (i = 0; i < aNode.GetAttributeCount(); i++)
{
key = aNode.GetKeyAt(i);
value = aNode.GetValueAt(i);
key.StripChars("\"");
value.StripChars("\"");
if (key.EqualsIgnoreCase("src"))
{
// Load the url!
toLoadUrl = value;
break;
}
}
}
//return NS_OK;
}
nsString text = aNode.GetText();
res = CIDFromTag(tag, aclass);
if (NS_OK != res)
return res ;
res = nsRepository::CreateInstance(aclass,
nsnull,
kIXMLParserObjectIID,
(void **)&object);
if (NS_OK != res)
return res ;
/*
* ConsumeAttributes
*/
AddToHierarchy(*object, PR_TRUE);
object->Init();
ConsumeAttributes(aNode,*object);
/*
* If this is a menu bar, tell the widget.
* Probably want a general notification scheme for menubar
* changes
*/
if (eXPFCXMLTag_menubar == tag)
{
nsIXPFCMenuBar * menubar;
res = object->QueryInterface(kCIXPFCMenuBarIID,(void**)&menubar);
if (NS_OK == res)
{
mViewerContainer->SetMenuBar(menubar);
NS_RELEASE(menubar);
}
}
/*
* If this is a menu bar, tell the widget.
* Probably want a general notification scheme for menubar
* changes
*/
if (eXPFCXMLTag_toolbar == tag)
{
nsIXPFCToolbar * toolbar;
res = object->QueryInterface(kCIXPFCToolbarIID,(void**)&toolbar);
if (NS_OK == res)
{
mViewerContainer->AddToolbar(toolbar);
NS_RELEASE(toolbar);
}
}
if (eXPFCXMLTag_dialog == tag)
{
nsIXPFCDialog * dialog;
res = object->QueryInterface(kCIXPFCDialogIID,(void**)&dialog);
if (NS_OK == res)
{
mViewerContainer->ShowDialog(dialog);
NS_RELEASE(dialog);
}
}
/*
* If this was a root panel, add it to the widget
*/
if (eXPFCXMLTag_application == tag)
{
nsIXPFCCanvas * child = (nsIXPFCCanvas *) mXPFCStack->Top();
if (child != nsnull)
{
nsIXPFCCanvas * root ;
gXPFCToolkit->GetRootCanvas(&root);
root->DeleteChildren();
root->AddChildCanvas(child);
NS_RELEASE(root);
}
}
if (toLoadUrl.Length() > 0)
{
nsIXPFCCanvas * canvas = nsnull;
if (toLoadUrl.Find(".cal") != -1)
object->QueryInterface(kIXPFCCanvasIID,(void**)&canvas);
mViewerContainer->LoadURL(toLoadUrl,nsnull,canvas);
NS_IF_RELEASE(canvas);
}
NS_RELEASE(object);
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseContainer(const nsIParserNode& aNode)
{
nsISupports * container = (nsISupports *)mXPFCStack->Pop();
/*
* If we popped the topmost canvas, lay it out
*/
nsISupports * parent = (nsISupports *) mXPFCStack->Top();
if (parent == nsnull && container != nsnull)
{
nsIXPFCCanvas * canvas ;
nsresult res = container->QueryInterface(kIXPFCCanvasIID,(void**)&canvas);
if (res == NS_OK)
{
canvas->Layout();
NS_RELEASE(canvas);
}
}
NS_IF_RELEASE(container);
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::AddLeaf(const nsIParserNode& aNode)
{
nsIXMLParserObject * object = nsnull;
eXPFCXMLTags tag = (eXPFCXMLTags) aNode.GetNodeType();
nsresult res;
nsCID aclass;
// XXX Til we implement separators
if (tag == eXPFCXMLTag_separator)
return NS_OK;
/*
* The XML may specify this as a leaf, but it's parameters
* will reference a child object, in which case it's
* runtime is a container
*/
if (IsContainer(aNode) == PR_TRUE)
{
res = OpenContainer(aNode);
CloseContainer(aNode);
return res;
}
nsString text = aNode.GetText();
res = CIDFromTag(tag, aclass);
res = nsRepository::CreateInstance(aclass,
nsnull,
kIXMLParserObjectIID,
(void **)&object);
if (NS_OK != res)
return res ;
AddToHierarchy(*object, PR_FALSE);
object->Init();
ConsumeAttributes(aNode,*object);
// XXX: Need a way to identify that native widgets are
// involved!
if (tag == eXPFCXMLTag_button
|| tag == eXPFCXMLTag_tabwidget
|| tag == eXPFCXMLTag_editfield)
{
nsIXPFCCanvas * canvas = nsnull;
res = object->QueryInterface(kIXPFCCanvasIID,(void**)&canvas);
if (NS_OK == res)
{
canvas->CreateView();
NS_RELEASE(canvas);
}
}
NS_RELEASE(object);
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::PushMark()
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::OpenHTML(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseHTML(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::OpenHead(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseHead(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::SetTitle(const nsString& aValue)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::OpenBody(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseBody(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::OpenForm(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseForm(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::OpenMap(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseMap(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::OpenFrameset(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::CloseFrameset(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::WillBuildModel(void)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::DidBuildModel(PRInt32 aQualityLevel)
{
if (mState == XPFC_PARSING_STATE_MENUBAR)
{
nsIIterator * iterator;
mContainerList->CreateIterator(&iterator);
iterator->Init();
ContainerListEntry * item ;
while(!(iterator->IsDone()))
{
item = (ContainerListEntry *) iterator->CurrentItem();
/*
* item->object is the parent container
* item->container is the name of the target child container
*
* There should be a nsIXPFCMenuContainer in the free list with this
* name. Let's find it, make it the child, and remove from free list
*/
nsIIterator * iterator2 ;
nsIXPFCMenuContainer * menu_container;
nsString child;
nsIXPFCMenuItem * container_item = nsnull;
nsresult res = mOrphanMenuList->CreateIterator(&iterator2);
if (NS_OK != res)
return nsnull;
iterator2->Init();
while(!(iterator2->IsDone()))
{
menu_container = (nsIXPFCMenuContainer *) iterator2->CurrentItem();
res = menu_container->QueryInterface(kCIXPFCMenuItemIID,(void**)&container_item);
if (res == NS_OK)
{
child = container_item->GetName();
if (child == item->container) {
/*
* Set as child
*/
nsIXPFCMenuContainer * parent = nsnull;
res = item->object->QueryInterface(kCIXPFCMenuContainerIID, (void**)&parent);
if (res == NS_OK)
{
parent->AddChild((nsIXPFCMenuItem *)container_item);
NS_RELEASE(parent);
}
mOrphanMenuList->Remove(child);
NS_RELEASE(container_item);
break;
}
NS_RELEASE(container_item);
}
iterator2->Next();
}
NS_RELEASE(iterator2);
iterator->Next();
}
NS_IF_RELEASE(iterator);
mViewerContainer->UpdateMenuBar();
} else if (mState == XPFC_PARSING_STATE_TOOLBAR)
{
mViewerContainer->UpdateToolbars();
}
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::WillInterrupt(void)
{
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::WillResume(void)
{
return NS_OK;
}
nsresult nsXPFCXMLContentSink::SetViewerContainer(nsIWebViewerContainer * aViewerContainer)
{
mViewerContainer = aViewerContainer;
return NS_OK;
}
/*
* Find the CID from the XML Tag Object
*/
NS_IMETHODIMP nsXPFCXMLContentSink::CIDFromTag(eXPFCXMLTags tag, nsCID &aClass)
{
switch(tag)
{
case eXPFCXMLTag_menuitem:
aClass = kCXPFCMenuItemCID;
break;
case eXPFCXMLTag_menucontainer:
aClass = kCXPFCMenuContainerCID;
break;
case eXPFCXMLTag_menubar:
aClass = kCXPFCMenuBarCID;
break;
case eXPFCXMLTag_toolbar:
aClass = kCXPFCToolbarCID;
break;
case eXPFCXMLTag_dialog:
aClass = kCXPFCDialogCID;
break;
case eXPFCXMLTag_application:
case eXPFCXMLTag_canvas:
case eXPFCXMLTag_separator:
aClass = kCXPFCCanvasCID;
break;
case eXPFCXMLTag_editfield:
aClass = kCXPFCTextWidgetCID;
break;
case eXPFCXMLTag_button:
aClass = kCXPFCButtonCID;
break;
case eXPFCXMLTag_xpbutton:
aClass = kCXPButtonCID;
break;
case eXPFCXMLTag_tabwidget:
aClass = kCXPFCTabWidgetCID;
break;
default:
return (NS_ERROR_UNEXPECTED);
break;
}
return NS_OK;
}
NS_IMETHODIMP nsXPFCXMLContentSink::ConsumeAttributes(const nsIParserNode& aNode, nsIXMLParserObject& aObject)
{
PRInt32 i = 0;
nsString key,value;
nsString scontainer;
PRBool container = PR_FALSE;
for (i = 0; i < aNode.GetAttributeCount(); i++) {
key = aNode.GetKeyAt(i);
value = aNode.GetValueAt(i);
key.StripChars("\"");
value.StripChars("\"");
aObject.SetParameter(key,value);
if (key.EqualsIgnoreCase(XPFC_STRING_CONTAINER)) {
container = PR_TRUE;
scontainer = value;
}
}
eXPFCXMLTags tag = (eXPFCXMLTags) aNode.GetNodeType();
//if (container == PR_TRUE)
// aObject.SetParameter(nsString("popup"),nsString("popup"));
/*
* If this object has something it wants to control, store away the string and source
* object. Later on, we'll walk the content tree Registering appropriate subjects
* and observers.
*/
if (container == PR_TRUE)
{
mContainerList->Append(new ContainerListEntry(&aObject, scontainer));
}
return NS_OK;
}
PRBool nsXPFCXMLContentSink::IsContainer(const nsIParserNode& aNode)
{
PRInt32 i = 0;
nsString key;
PRBool container = PR_FALSE;
for (i = 0; i < aNode.GetAttributeCount(); i++) {
key = aNode.GetKeyAt(i);
key.StripChars("\"");
if (key.EqualsIgnoreCase(XPFC_STRING_CONTAINER)) {
container = PR_TRUE;
break;
}
}
return container;
}
NS_IMETHODIMP nsXPFCXMLContentSink::AddToHierarchy(nsIXMLParserObject& aObject, PRBool aPush)
{
if (mState == XPFC_PARSING_STATE_TOOLBAR)
{
nsIXPFCToolbar * container = nsnull;
nsIXPFCCanvas * parent = nsnull;
nsIXPFCCanvas * child_canvas = nsnull;
aObject.QueryInterface(kIXPFCCanvasIID,(void**)&child_canvas);
nsresult res = aObject.QueryInterface(kCIXPFCToolbarIID,(void**)&container);
parent = (nsIXPFCCanvas *) mXPFCStack->Top();
if (parent == nsnull)
{
mViewerContainer->GetToolbarManager()->AddToolbar(container);
} else {
if (child_canvas != nsnull)
{
parent->AddChildCanvas(child_canvas);
}
}
if (aPush == PR_TRUE)
PushComponent(child_canvas);
NS_IF_RELEASE(child_canvas);
NS_IF_RELEASE(container);
return NS_OK;
} else if (mState == XPFC_PARSING_STATE_MENUBAR)
{
nsIXPFCMenuContainer * container = nsnull;
nsIXPFCMenuContainer * parent = nsnull;
nsresult res = aObject.QueryInterface(kCIXPFCMenuContainerIID,(void**)&container);
parent = (nsIXPFCMenuContainer *) mXPFCStack->Top();
if (NS_OK != res)
{
/*
* Must be a menu item. Add as child to top of stack
*/
nsIXPFCMenuItem * item = nsnull;
aObject.QueryInterface(kCIXPFCMenuItemIID,(void**)&item);
parent->AddChild(item);
item->SetMenuID(mViewerContainer->GetMenuManager()->GetID());
item->SetReceiver(mViewerContainer->GetMenuManager()->GetDefaultReceiver());
NS_RELEASE(item);
return res;
}
if (res == NS_OK && parent != nsnull)
{
nsIXPFCMenuItem * item = nsnull;
nsresult res = aObject.QueryInterface(kCIXPFCMenuItemIID,(void**)&item);
parent->AddChild(item);
item->SetMenuID(mViewerContainer->GetMenuManager()->GetID());
item->SetReceiver(mViewerContainer->GetMenuManager()->GetDefaultReceiver());
NS_RELEASE(item);
}
if (parent == nsnull)
{
/*
* Add all toplevel menucontainer's to the menu manager
*/
mViewerContainer->GetMenuManager()->AddMenuContainer(container);
/*
* We probably can get rid of the orphanlist now that we
* have a menu manager.
*/
mOrphanMenuList->Append(container);
}
if (aPush == PR_TRUE)
PushComponent(container);
container->Release();
return NS_OK;
} else if (mState == XPFC_PARSING_STATE_DIALOG)
{
nsIXPFCDialog * container = nsnull;
nsIXPFCDialog * parent = nsnull;
nsresult res = aObject.QueryInterface(kCIXPFCDialogIID,(void**)&container);
parent = (nsIXPFCDialog *) mXPFCStack->Top();
if (parent == nsnull)
{
//mViewerContainer->GetToolbarManager()->AddDialog(container);
if (aPush == PR_TRUE)
PushComponent(container);
} else {
nsIXPFCCanvas * parent_canvas = nsnull;
nsIXPFCCanvas * child_canvas = nsnull;
res = aObject.QueryInterface(kIXPFCCanvasIID,(void**)&child_canvas);
if (NS_OK == res)
{
res = parent->QueryInterface(kIXPFCCanvasIID,(void**)&parent_canvas);
if (NS_OK == res)
{
parent_canvas->AddChildCanvas(child_canvas);
NS_RELEASE(parent_canvas);
}
if (aPush == PR_TRUE)
PushComponent(child_canvas);
NS_RELEASE(child_canvas);
}
}
return NS_OK;
} else if (mState == XPFC_PARSING_STATE_APPLICATION)
{
nsIXPFCCanvas * container = nsnull;
nsIXPFCCanvas * parent = nsnull;
nsresult res = aObject.QueryInterface(kIXPFCCanvasIID,(void**)&container);
parent = (nsIXPFCCanvas *) mXPFCStack->Top();
if (parent != nsnull)
parent->AddChildCanvas(container);
if (aPush == PR_TRUE)
PushComponent(container);
NS_RELEASE(container);
return NS_OK;
} else {
return NS_OK;
}
return NS_OK;
}
nsresult nsXPFCXMLContentSink::SetContentSinkContainer(nsISupports *
aContentSinkContainer)
{
nsresult res;
nsIXPFCCanvas * canvas;
static NS_DEFINE_IID(kIXPFCCanvasIID, NS_IXPFC_CANVAS_IID);
res = aContentSinkContainer->QueryInterface(kIXPFCCanvasIID, (void **)&canvas);
if (NS_OK == res)
{
res = SetRootCanvas(canvas);
NS_RELEASE(canvas);
}
return res;
}
nsresult nsXPFCXMLContentSink::SetRootCanvas(nsIXPFCCanvas * aCanvas)
{
PushComponent(aCanvas);
return NS_OK;
}
nsresult nsXPFCXMLContentSink::PushComponent(nsISupports* aComponent)
{
mXPFCStack->Push(aComponent);
NS_ADDREF(aComponent);
return NS_OK;
}