Bug 405719, regression where menus cannot be generated with templates without extra tags, also improve construction by not setting the open attribute too early and instead call the builder directly before opening a menu, r=smaug,sr=neil,a=beltzner

This commit is contained in:
enndeakin@sympatico.ca 2008-02-21 09:40:12 -08:00
parent b327cd3758
commit 841381c960
8 changed files with 65 additions and 27 deletions

View File

@ -1646,7 +1646,7 @@ nsXULElement::EnsureContentsGenerated(void) const
return NS_OK;
}
return builder->CreateContents(unconstThis);
return builder->CreateContents(unconstThis, PR_FALSE);
}
}

View File

@ -3659,7 +3659,7 @@ nsXULDocument::CreateTemplateBuilder(nsIContent* aElement)
}
else {
// Force construction of immediate template sub-content _now_.
builder->CreateContents(aElement);
builder->CreateContents(aElement, PR_FALSE);
}
}

View File

@ -42,8 +42,6 @@
#include "domstubs.idl"
#include "nsISupports.idl"
#include "nsIRDFCompositeDataSource.idl"
#include "nsIRDFResource.idl"
interface nsIAtom;
interface nsIContent;
@ -51,6 +49,8 @@ interface nsIXULBuilderListener;
interface nsIXULTemplateResult;
interface nsIXULTemplateRuleFilter;
interface nsIXULTemplateQueryProcessor;
interface nsIRDFResource;
interface nsIRDFCompositeDataSource;
/**
* A template builder, given an input source of data, a template, and a
@ -158,7 +158,7 @@ interface nsIXULTemplateQueryProcessor;
*
* See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates.
*/
[scriptable, uuid(1762801E-1147-4197-BF0D-D749C903AF74)]
[scriptable, uuid(A583B676-5B02-4F9C-A0C9-CB850CB99818)]
interface nsIXULTemplateBuilder : nsISupports
{
/**
@ -328,10 +328,13 @@ interface nsIXULTemplateBuilder : nsISupports
[noscript] void init(in nsIContent aElement);
/**
* Invoked lazily by a XUL element that needs its child content
* built.
* Invoked lazily by a XUL element that needs its child content built.
* If aForceCreation is true, then the contents of an element will be
* generated even if it is closed. If false, the element will only
* generate its contents if it is open. This behaviour is used with menus.
*/
[noscript] void createContents(in nsIContent aElement);
[noscript] void createContents(in nsIContent aElement,
in boolean aForceCreation);
/**
* Add a listener to this template builder. The template builder

View File

@ -128,7 +128,7 @@ class nsXULContentBuilder : public nsXULTemplateBuilder
{
public:
// nsIXULTemplateBuilder interface
NS_IMETHOD CreateContents(nsIContent* aElement);
NS_IMETHOD CreateContents(nsIContent* aElement, PRBool aForceCreation);
NS_IMETHOD HasGeneratedContent(nsIRDFResource* aResource,
nsIAtom* aTag,
@ -261,11 +261,13 @@ protected:
* was generated.
*
* @param aElement element to generate content inside
* @param aForceCreation true to force creation for closed items such as menus
* @param aContainer container content was added inside
* @param aNewIndexInContainer index with container in which content was added
*/
nsresult
CreateTemplateAndContainerContents(nsIContent* aElement,
PRBool aForceCreation,
nsIContent** aContainer,
PRInt32* aNewIndexInContainer);
@ -275,6 +277,7 @@ protected:
*
* @param aElement element to generate content inside
* @param aResult reference point for query
* @param aForceCreation true to force creation for closed items such as menus
* @param aNotify true to notify of DOM changes
* @param aContainer container content was added inside
* @param aNewIndexInContainer index with container in which content was added
@ -282,6 +285,7 @@ protected:
nsresult
CreateContainerContents(nsIContent* aElement,
nsIXULTemplateResult* aResult,
PRBool aForceCreation,
PRBool aNotify,
nsIContent** aContainer,
PRInt32* aNewIndexInContainer);
@ -853,7 +857,7 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
if (NS_FAILED(rv)) return rv;
if (isGenerationElement) {
rv = CreateContainerContents(realKid, aChild, PR_FALSE,
rv = CreateContainerContents(realKid, aChild, PR_FALSE, PR_FALSE,
nsnull /* don't care */,
nsnull /* don't care */);
if (NS_FAILED(rv)) return rv;
@ -1099,6 +1103,7 @@ nsXULContentBuilder::RemoveMember(nsIContent* aContent)
nsresult
nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
PRBool aForceCreation,
nsIContent** aContainer,
PRInt32* aNewIndexInContainer)
{
@ -1143,8 +1148,8 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
}
if (mRootResult) {
CreateContainerContents(aElement, mRootResult, PR_FALSE,
aContainer, aNewIndexInContainer);
CreateContainerContents(aElement, mRootResult, aForceCreation,
PR_FALSE, aContainer, aNewIndexInContainer);
}
}
else if (!(mFlags & eDontRecurse)) {
@ -1159,8 +1164,8 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
if (NS_FAILED(rv) || !mayProcessChildren)
return rv;
CreateContainerContents(aElement, match->mResult, PR_FALSE,
aContainer, aNewIndexInContainer);
CreateContainerContents(aElement, match->mResult, aForceCreation,
PR_FALSE, aContainer, aNewIndexInContainer);
}
}
@ -1173,6 +1178,7 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
nsresult
nsXULContentBuilder::CreateContainerContents(nsIContent* aElement,
nsIXULTemplateResult* aResult,
PRBool aForceCreation,
PRBool aNotify,
nsIContent** aContainer,
PRInt32* aNewIndexInContainer)
@ -1210,7 +1216,7 @@ nsXULContentBuilder::CreateContainerContents(nsIContent* aElement,
// The tree widget is special. If the item isn't open, then just
// "pretend" that there aren't any contents here. We'll create
// them when OpenContainer() gets called.
if (IsLazyWidgetItem(aElement) && !IsOpen(aElement))
if (!aForceCreation && IsLazyWidgetItem(aElement) && !IsOpen(aElement))
return NS_OK;
// See if the element's templates contents have been generated:
@ -1670,13 +1676,26 @@ nsXULContentBuilder::SetContainerAttrs(nsIContent *aElement,
//
NS_IMETHODIMP
nsXULContentBuilder::CreateContents(nsIContent* aElement)
nsXULContentBuilder::CreateContents(nsIContent* aElement, PRBool aForceCreation)
{
NS_PRECONDITION(aElement != nsnull, "null ptr");
if (! aElement)
return NS_ERROR_NULL_POINTER;
return CreateTemplateAndContainerContents(aElement, nsnull /* don't care */, nsnull /* don't care */);
nsCOMPtr<nsIContent> container;
PRInt32 newIndex;
nsresult rv = CreateTemplateAndContainerContents(aElement, aForceCreation,
getter_AddRefs(container), &newIndex);
NS_ENSURE_SUCCESS(rv, rv);
// if forcing an element to be created, make sure to notify
if (aForceCreation && container) {
MOZ_AUTO_DOC_UPDATE(container->GetCurrentDoc(), UPDATE_CONTENT_MODEL,
PR_TRUE);
nsNodeUtils::ContentAppended(container, newIndex);
}
return NS_OK;
}
NS_IMETHODIMP
@ -2017,7 +2036,8 @@ nsXULContentBuilder::OpenContainer(nsIContent* aElement)
// notify layout where content got created.
nsCOMPtr<nsIContent> container;
PRInt32 newIndex;
CreateContainerContents(aElement, result, PR_FALSE, getter_AddRefs(container), &newIndex);
CreateContainerContents(aElement, result, PR_FALSE,
PR_FALSE, getter_AddRefs(container), &newIndex);
if (container && IsLazyWidgetItem(aElement)) {
// The tree widget is special, and has to be spanked every
@ -2090,7 +2110,7 @@ nsXULContentBuilder::RebuildAll()
// contents for the current element...
nsCOMPtr<nsIContent> container;
PRInt32 newIndex;
CreateTemplateAndContainerContents(mRoot, getter_AddRefs(container), &newIndex);
CreateTemplateAndContainerContents(mRoot, PR_FALSE, getter_AddRefs(container), &newIndex);
if (container) {
MOZ_AUTO_DOC_UPDATE(container->GetCurrentDoc(), UPDATE_CONTENT_MODEL,

View File

@ -457,7 +457,7 @@ nsXULTemplateBuilder::Init(nsIContent* aElement)
}
NS_IMETHODIMP
nsXULTemplateBuilder::CreateContents(nsIContent* aElement)
nsXULTemplateBuilder::CreateContents(nsIContent* aElement, PRBool aForceCreation)
{
return NS_OK;
}

View File

@ -64,6 +64,7 @@ REQUIRES = xpcom \
unicharutil \
xpconnect \
js \
xultmpl \
$(NULL)
ifdef MOZ_ENABLE_CANVAS

View File

@ -45,6 +45,8 @@
#include "nsIDOMDocument.h"
#include "nsIDOMNSEvent.h"
#include "nsIDOMNSUIEvent.h"
#include "nsIDOMXULElement.h"
#include "nsIXULTemplateBuilder.h"
#include "nsIPrivateDOMEvent.h"
#include "nsEventDispatcher.h"
#include "nsEventStateManager.h"
@ -366,6 +368,24 @@ nsXULPopupManager::ShowMenu(nsIContent *aMenu,
PRBool aSelectFirstItem,
PRBool aAsynchronous)
{
// generate any template content first. Otherwise, the menupopup may not
// have been created yet.
if (aMenu) {
nsIContent* element = aMenu;
do {
nsCOMPtr<nsIDOMXULElement> xulelem = do_QueryInterface(element);
if (xulelem) {
nsCOMPtr<nsIXULTemplateBuilder> builder;
xulelem->GetBuilder(getter_AddRefs(builder));
if (builder) {
builder->CreateContents(aMenu, PR_TRUE);
break;
}
}
element = element->GetParent();
} while (element);
}
nsMenuFrame* menuFrame = GetMenuFrameForContent(aMenu);
if (!menuFrame || !menuFrame->IsMenu())
return;
@ -914,12 +934,6 @@ nsXULPopupManager::FirePopupShowingEvent(nsIContent* aPopup,
{
nsCOMPtr<nsIPresShell> presShell = aPresContext->PresShell();
// set the open attribute on the menu first so that templates will generate
// their content before the popupshowing event fires.
if (aMenu)
aMenu->SetAttr(kNameSpaceID_None, nsGkAtoms::open,
NS_LITERAL_STRING("true"), PR_TRUE);
// XXXndeakin (bug 383930)
// eventually, the popup events will be a different event type with
// additional fields for the anchor node and position and so forth. This

View File

@ -277,7 +277,7 @@ menu.menu-iconic {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menu-iconic");
}
menu:empty {
menubar > menu:empty {
visibility: collapse;
}