Bug 16999: Get default button labels from .properties file instead of html.css (GfxButtonControlFrame -> anonymous content creator). r=rods a=rickg
git-svn-id: svn://10.0.0.236/trunk@61376 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -25,9 +25,16 @@
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsFormControlFrame.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID);
|
||||
static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID);
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
|
||||
const nscoord kSuggestedNotSet = -1;
|
||||
|
||||
@@ -36,6 +43,7 @@ nsGfxButtonControlFrame::nsGfxButtonControlFrame()
|
||||
mRenderer.SetNameSpace(kNameSpaceID_None);
|
||||
mSuggestedWidth = kSuggestedNotSet;
|
||||
mSuggestedHeight = kSuggestedNotSet;
|
||||
mUpdateValue = "";
|
||||
}
|
||||
|
||||
PRBool
|
||||
@@ -127,6 +135,42 @@ nsGfxButtonControlFrame::IsSubmit(PRInt32 type)
|
||||
}
|
||||
}
|
||||
|
||||
// Special check for the browse button of a file input.
|
||||
//
|
||||
// Since this is actually type "NS_FORM_INPUT_BUTTON", we
|
||||
// can't tell if it is part of a file input by the type.
|
||||
// We'll return PR_TRUE if either:
|
||||
// (a) type is NS_FORM_BROWSE or
|
||||
// (b) type is NS_FORM_INPUT_BUTTON and our parent is a file input
|
||||
PRBool
|
||||
nsGfxButtonControlFrame::IsBrowse(PRInt32 type)
|
||||
{
|
||||
if (NS_FORM_BROWSE == type) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (NS_FORM_INPUT_BUTTON == type) {
|
||||
|
||||
// Check to see if parent is a file input
|
||||
nsIContent* parentContent;
|
||||
mContent->GetParent(parentContent);
|
||||
nsIAtom* atom;
|
||||
if (parentContent->GetTag(atom) == NS_OK && atom == nsHTMLAtoms::input) {
|
||||
|
||||
// It's an input, is it a file input?
|
||||
nsString value;
|
||||
if (NS_CONTENT_ATTR_HAS_VALUE == parentContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, value)) {
|
||||
value.ToUpperCase();
|
||||
nsString file("FILE");
|
||||
if (value == file) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(parentContent);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: this ::GetIID() method has no meaning in life and should be
|
||||
* removed.
|
||||
@@ -184,33 +228,11 @@ nsGfxButtonControlFrame::DoNavQuirksReflow(nsIPresContext* aPresContext
|
||||
|
||||
// Get the text from the "value" attribute
|
||||
// for measuring the height, width of the text
|
||||
// if there is no value attr or its length is 0
|
||||
// then go to the generated content to get it
|
||||
// This shouldn't be zero because if it was we set it to
|
||||
// a default. See CreateAnonymousContent and Reflow
|
||||
nsAutoString value;
|
||||
GetValue(&value);
|
||||
|
||||
// if there was no value specified
|
||||
// then go get the content of the generated content
|
||||
// we can't make any assumption as to what the default would be
|
||||
// because of the value is specified in the html.css and for
|
||||
// for non-english platforms it might not be the string
|
||||
// "Reset" or "Submit Query"
|
||||
if (value.Length() == 0) {
|
||||
value = " ";
|
||||
// The child frame will br the generated content
|
||||
nsIFrame* fKid;
|
||||
firstKid->FirstChild(aPresContext, nsnull, &fKid);
|
||||
if (fKid) {
|
||||
const nsStyleContent* content;
|
||||
fKid->GetStyleData(eStyleStruct_Content, (const nsStyleStruct *&)content);
|
||||
PRUint32 count = content->ContentCount();
|
||||
// XXX not sure if I need to get more than the first index?
|
||||
if (count > 0) {
|
||||
nsStyleContentType contentType = eStyleContentType_String;
|
||||
content->GetContentAt(0, contentType, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
const nsStyleText* textStyle;
|
||||
GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)textStyle);
|
||||
if (!textStyle->WhiteSpaceIsSignificant()) {
|
||||
@@ -320,6 +342,164 @@ nsGfxButtonControlFrame::DoNavQuirksReflow(nsIPresContext* aPresContext
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create the text content used as label for the button.
|
||||
// The frame will be generated by the frame constructor.
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext,
|
||||
nsISupportsArray& aChildList)
|
||||
{
|
||||
nsresult result;
|
||||
|
||||
// Get the text from the "value" attribute.
|
||||
// If it is zero length, set it to a default value (localized)
|
||||
nsAutoString initvalue, value;
|
||||
GetValue(&initvalue);
|
||||
value = initvalue;
|
||||
if (value.Length() == 0) {
|
||||
// Generate localized label.
|
||||
// We can't make any assumption as to what the default would be
|
||||
// because the value is localized for non-english platforms, thus
|
||||
// it might not be the string "Reset", "Submit Query", or "Browse..."
|
||||
result = GetDefaultLabel(value);
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Compress whitespace out of label if needed.
|
||||
const nsStyleText* textStyle;
|
||||
GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)textStyle);
|
||||
if (!textStyle->WhiteSpaceIsSignificant()) {
|
||||
value.CompressWhitespace();
|
||||
if (value.Length() == 0) {
|
||||
value = " ";
|
||||
}
|
||||
}
|
||||
|
||||
// Cache this value away until we have created
|
||||
// a frame so we can update the value attribute.
|
||||
// This makes input.value return the default string as in Nav and IE.
|
||||
if (initvalue != value) {
|
||||
mUpdateValue = value;
|
||||
}
|
||||
|
||||
// Add a child text content node for the label
|
||||
nsCOMPtr<nsIContent> labelContent;
|
||||
result = NS_NewTextNode(getter_AddRefs(labelContent));
|
||||
if (NS_SUCCEEDED(result) && labelContent) {
|
||||
// set the value of the text node
|
||||
labelContent->QueryInterface(NS_GET_IID(nsITextContent), getter_AddRefs(mTextContent));
|
||||
mTextContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE);
|
||||
aChildList.AppendElement(mTextContent);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Frames are not refcounted, no need to AddRef
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
} else if (aIID.Equals(NS_GET_IID(nsIAnonymousContentCreator))) {
|
||||
*aInstancePtr = (void*)(nsIAnonymousContentCreator*) this;
|
||||
return NS_OK;
|
||||
}
|
||||
return nsHTMLButtonControlFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
// Initially we hardcoded the default strings here.
|
||||
// Next, we used html.css to store the default label for various types
|
||||
// of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20)
|
||||
// However, since html.css is not internationalized, we now grab the default
|
||||
// label from a string bundle as is done for all other UI strings.
|
||||
// See bug 16999 for further details.
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::GetDefaultLabel(nsString& aString)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRInt32 type;
|
||||
GetType(&type);
|
||||
if (IsReset(type)) {
|
||||
rv = ButtonLocalize("Reset", aString);
|
||||
}
|
||||
else if (IsSubmit(type)) {
|
||||
rv = ButtonLocalize("Submit", aString);
|
||||
}
|
||||
else if (IsBrowse(type)) {
|
||||
rv = ButtonLocalize("Browse", aString);
|
||||
}
|
||||
else {
|
||||
aString = " ";
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define form_properties "chrome://layout/locale/HtmlForm.properties"
|
||||
|
||||
// Return localised string for resource string (e.g. "Submit" -> "Submit Query")
|
||||
// This code is derived from nsBookmarksService::Init() and cookie_Localize()
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::ButtonLocalize(char* aKey, nsString& oVal)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
|
||||
// Create a URL for the string resource file
|
||||
// Create a bundle for the localization
|
||||
NS_WITH_SERVICE(nsIIOService, pNetService, kIOServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && pNetService) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = pNetService->NewURI(form_properties, nsnull, getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv) && uri) {
|
||||
|
||||
// Create bundle
|
||||
NS_WITH_SERVICE(nsIStringBundleService, stringService, kStringBundleServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && stringService) {
|
||||
nsXPIDLCString spec;
|
||||
rv = uri->GetSpec(getter_Copies(spec));
|
||||
if (NS_SUCCEEDED(rv) && spec) {
|
||||
nsCOMPtr<nsILocale> locale = nsnull;
|
||||
rv = stringService->CreateBundle(spec, locale, getter_AddRefs(bundle));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine default label from string bundle
|
||||
if (NS_SUCCEEDED(rv) && bundle && aKey) {
|
||||
nsXPIDLString valUni;
|
||||
nsAutoString key(aKey);
|
||||
rv = bundle->GetStringFromName(key.GetUnicode(), getter_Copies(valUni));
|
||||
if (NS_SUCCEEDED(rv) && valUni) {
|
||||
oVal = valUni;
|
||||
} else {
|
||||
oVal.Truncate();
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint)
|
||||
{
|
||||
// If the value attribute is set, update the text of the label
|
||||
if (nsHTMLAtoms::value == aAttribute) {
|
||||
nsString value;
|
||||
if (nsnull != mTextContent && NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value)) {
|
||||
mTextContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return nsHTMLButtonControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@@ -328,8 +508,27 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext,
|
||||
{
|
||||
// The mFormFrame is set in the initial reflow within nsHTMLButtonControlFrame
|
||||
nsresult rv = NS_OK;
|
||||
if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) {
|
||||
nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this));
|
||||
if (eReflowReason_Initial == aReflowState.reason) {
|
||||
if (!mFormFrame) {
|
||||
nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this));
|
||||
}
|
||||
// If we cached a value (mUpdateValue) in CreateAnonymousContent(),
|
||||
// set the value attribute of the button to this generated label.
|
||||
// This will allow e.g. submit inputs to return a value of Submit Query
|
||||
// when none is specified, as they do in IE 5.0 and Nav 4.x. We have to
|
||||
// wait until now because updating our value attribute will cause a
|
||||
// reflow and the frame must exist.
|
||||
if (mUpdateValue.Length() != 0) {
|
||||
if (mContent) {
|
||||
nsIHTMLContent* formControl = nsnull;
|
||||
rv = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl);
|
||||
if (NS_SUCCEEDED(rv) && formControl) {
|
||||
rv = formControl->SetHTMLAttribute(nsHTMLAtoms::value, mUpdateValue, PR_TRUE);
|
||||
NS_RELEASE(formControl);
|
||||
}
|
||||
}
|
||||
mUpdateValue = "";
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
Reference in New Issue
Block a user