Bug 936442 - part 1: refactor CharsetMenu to allow Australis code to use it, r=Unfocused

This commit is contained in:
Gijs Kruitbosch 2014-01-27 11:56:04 +00:00
parent 8b52f68cbb
commit 06759240a2
7 changed files with 146 additions and 128 deletions

View File

@ -11,52 +11,11 @@
#endif
oncommand="MultiplexHandler(event)"
#ifdef OMIT_ACCESSKEYS
#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__', false);"
#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__', false);"
#else
#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__');"
#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__');"
#endif
onpopupshown="UpdateMenus(event);">
<menupopup>
<menu label="&charsetMenuAutodet.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.accesskey;"
#endif
>
<menupopup>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.off"
label="&charsetMenuAutodet.off.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.off.accesskey;"
#endif
/>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.ja_parallel_state_machine"
label="&charsetMenuAutodet.ja.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.ja.accesskey;"
#endif
/>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.ruprob"
label="&charsetMenuAutodet.ru.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.ru.accesskey;"
#endif
/>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.ukprob"
label="&charsetMenuAutodet.uk.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.uk.accesskey;"
#endif
/>
</menupopup>
</menu>
<menuseparator/>
</menupopup>
</menu>

View File

@ -150,7 +150,7 @@
<vbox id="PanelUI-characterEncodingView-customlist"
class="PanelUI-characterEncodingView-list"/>
<vbox>
<label value="&charsetMenuAutodet.label;"/>
<label id="PanelUI-characterEncodingView-autodetect-label"/>
<vbox id="PanelUI-characterEncodingView-autodetect"
class="PanelUI-characterEncodingView-list"/>
</vbox>

View File

@ -21,6 +21,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
XPCOMUtils.defineLazyServiceGetter(this, "CharsetManager",
"@mozilla.org/charset-converter-manager;1",
"nsICharsetConverterManager");
XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
const kCharsetBundle = "chrome://global/locale/charsetMenu.properties";
return Services.strings.createBundle(kCharsetBundle);
});
XPCOMUtils.defineLazyGetter(this, "BrandBundle", function() {
const kBrandBundle = "chrome://branding/locale/brand.properties";
return Services.strings.createBundle(kBrandBundle);
@ -765,6 +770,11 @@ const CustomizableWidgets = [{
onViewShowing: function(aEvent) {
let document = aEvent.target.ownerDocument;
let autoDetectLabelId = "PanelUI-characterEncodingView-autodetect-label";
let autoDetectLabel = document.getElementById(autoDetectLabelId);
let label = CharsetBundle.GetStringFromName("charsetMenuAutodet");
autoDetectLabel.setAttribute("value", label);
this.populateList(document,
"PanelUI-characterEncodingView-customlist",
"browser");

View File

@ -202,35 +202,9 @@
label="&charsetMenu.label;"
accesskey="&charsetMenu.accesskey;"
oncommand="MultiplexHandler(event);"
onpopupshowing="CharsetMenu.build(event);"
onpopupshowing="CharsetMenu.build(event.target);"
onpopupshown="UpdateMenus();">
<menupopup>
<menu label="&charsetMenuAutodet.label;"
accesskey="&charsetMenuAutodet.accesskey;">
<menupopup>
<menuitem type="radio"
name="detectorGroup"
id="chardet.off"
label="&charsetMenuAutodet.off.label;"
accesskey="&charsetMenuAutodet.off.accesskey;"/>
<menuitem type="radio"
name="detectorGroup"
id="chardet.ja_parallel_state_machine"
label="&charsetMenuAutodet.ja.label;"
accesskey="&charsetMenuAutodet.ja.accesskey;"/>
<menuitem type="radio"
name="detectorGroup"
id="chardet.ruprob"
label="&charsetMenuAutodet.ru.label;"
accesskey="&charsetMenuAutodet.ru.accesskey;"/>
<menuitem type="radio"
name="detectorGroup"
id="chardet.ukprob"
label="&charsetMenuAutodet.uk.label;"
accesskey="&charsetMenuAutodet.uk.accesskey;"/>
</menupopup>
</menu>
<menuseparator/>
</menupopup>
</menu>
<menuseparator/>

View File

@ -4,15 +4,3 @@
<!ENTITY charsetMenu.label "Character Encoding">
<!ENTITY charsetMenu.accesskey "C">
<!ENTITY charsetMenuAutodet.label "Auto-Detect">
<!ENTITY charsetMenuAutodet.accesskey "D"><!-- A reserved for Arabic -->
<!ENTITY charsetMenuAutodet.off.label "(off)">
<!ENTITY charsetMenuAutodet.off.accesskey "o">
<!ENTITY charsetMenuAutodet.ja.label "Japanese">
<!ENTITY charsetMenuAutodet.ja.accesskey "J">
<!ENTITY charsetMenuAutodet.ru.label "Russian">
<!ENTITY charsetMenuAutodet.ru.accesskey "R">
<!ENTITY charsetMenuAutodet.uk.label "Ukrainian">
<!ENTITY charsetMenuAutodet.uk.accesskey "U">

View File

@ -24,6 +24,20 @@
# (When this code was developed, all localizations appeared to use
# U+0028 LEFT PARENTHESIS for this purpose.)
# Auto-Detect (sub)menu
charsetMenuCharsets = Character Encoding
charsetMenuAutodet = Auto-Detect
# 'A' is reserved for Arabic:
charsetMenuAutodet.key = D
charsetMenuAutodet.off = (off)
charsetMenuAutodet.off.key = o
charsetMenuAutodet.ja = Japanese
charsetMenuAutodet.ja.key = J
charsetMenuAutodet.ru = Russian
charsetMenuAutodet.ru.key = R
charsetMenuAutodet.uk = Ukrainian
charsetMenuAutodet.uk.key = U
# Globally-relevant
UTF-8.key = U
UTF-8 = Unicode

View File

@ -12,6 +12,14 @@ XPCOMUtils.defineLazyGetter(this, "gBundle", function() {
const kUrl = "chrome://global/locale/charsetMenu.properties";
return Services.strings.createBundle(kUrl);
});
const kAutoDetectors = [
["off", "off"],
["ja", "ja_parallel_state_machine"],
["ru", "ruprob"],
["uk", "ukprob"]
];
/**
* This set contains encodings that are in the Encoding Standard, except:
* - XSS-dangerous encodings (except ISO-2022-JP which is assumed to be
@ -80,53 +88,94 @@ const kPinned = [
"windows-1252"
];
this.CharsetMenu = Object.freeze({
build: function BuildCharsetMenu(event, idPrefix="", showAccessKeys=true) {
let parent = event.target;
if (parent.lastChild.localName != "menuseparator") {
kPinned.forEach(x => kEncodings.delete(x));
let gDetectorInfoCache, gCharsetInfoCache, gPinnedInfoCache;
let CharsetMenu = {
build: function(parent, idPrefix="", showAccessKeys=true) {
function createDOMNode(doc, nodeInfo) {
let node = doc.createElement("menuitem");
node.setAttribute("type", "radio");
node.setAttribute("name", nodeInfo.name);
node.setAttribute("label", nodeInfo.label);
if (showAccessKeys && nodeInfo.accesskey) {
node.setAttribute("accesskey", nodeInfo.accesskey);
}
if (idPrefix) {
node.id = idPrefix + nodeInfo.id;
} else {
node.id = nodeInfo.id;
}
return node;
}
if (parent.childElementCount > 0) {
// Detector menu or charset menu already built
return;
}
let doc = parent.ownerDocument;
function createItem(encoding) {
let menuItem = doc.createElement("menuitem");
menuItem.setAttribute("type", "radio");
menuItem.setAttribute("name", "charsetGroup");
try {
menuItem.setAttribute("label", gBundle.GetStringFromName(encoding));
} catch (e) {
// Localization error but put *something* in the menu to recover.
menuItem.setAttribute("label", encoding);
}
if (showAccessKeys) {
try {
menuItem.setAttribute("accesskey",
gBundle.GetStringFromName(encoding + ".key"));
} catch (e) {
// Some items intentionally don't have an accesskey
}
}
menuItem.setAttribute("id", idPrefix + "charset." + encoding);
return menuItem;
let menuNode = doc.createElement("menu");
menuNode.setAttribute("label", gBundle.GetStringFromName("charsetMenuAutodet"));
if (showAccessKeys) {
menuNode.setAttribute("accesskey", gBundle.GetStringFromName("charsetMenuAutodet.key"));
}
parent.appendChild(menuNode);
// Clone the set in order to be able to remove the pinned encodings from
// the cloned set.
let encodings = new Set(kEncodings);
for (let encoding of kPinned) {
encodings.delete(encoding);
parent.appendChild(createItem(encoding));
}
let menuPopupNode = doc.createElement("menupopup");
menuNode.appendChild(menuPopupNode);
this._ensureDataReady();
gDetectorInfoCache.forEach(detectorInfo => menuPopupNode.appendChild(createDOMNode(doc, detectorInfo)));
parent.appendChild(doc.createElement("menuseparator"));
let list = [];
for (let encoding of encodings) {
list.push(createItem(encoding));
gPinnedInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo)));
parent.appendChild(doc.createElement("menuseparator"));
gCharsetInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo)));
},
getData: function() {
this._ensureDataReady();
return {
detectors: gDetectorInfoCache,
pinnedCharsets: gPinnedInfoCache,
otherCharsets: gCharsetInfoCache
};
},
_ensureDataReady: function() {
if (!gDetectorInfoCache) {
gDetectorInfoCache = this.getDetectorInfo();
gPinnedInfoCache = this.getCharsetInfo(kPinned, false);
gCharsetInfoCache = this.getCharsetInfo([...kEncodings]);
}
},
getDetectorInfo: function() {
return kAutoDetectors.map(([detectorName, nodeId]) => ({
id: "chardet." + nodeId,
label: this._getDetectorLabel(detectorName),
accesskey: this._getDetectorAccesskey(detectorName),
name: "detectorGroup",
}));
},
getCharsetInfo: function(charsets, sort=true) {
let list = charsets.map(charset => ({
id: "charset." + charset,
label: this._getCharsetLabel(charset),
accesskey: this._getCharsetAccessKey(charset),
name: "charsetGroup",
}));
if (!sort) {
return list;
}
list.sort(function (a, b) {
let titleA = a.getAttribute("label");
let titleB = b.getAttribute("label");
let titleA = a.label;
let titleB = b.label;
// Normal sorting sorts the part in parenthesis in an order that
// happens to make the less frequently-used items first.
let index;
@ -143,19 +192,43 @@ this.CharsetMenu = Object.freeze({
// secondarily reverse sort by encoding name to sort "windows" or
// "shift_jis" first. This works regardless of localization, because
// the ids aren't localized.
let idA = a.getAttribute("id");
let idB = b.getAttribute("id");
if (idA < idB) {
if (a.id < b.id) {
return 1;
}
if (idB < idA) {
if (b.id < a.id) {
return -1;
}
return 0;
});
for (let item of list) {
parent.appendChild(item);
}
return list;
},
});
_getDetectorLabel: function(detector) {
try {
return gBundle.GetStringFromName("charsetMenuAutodet." + detector);
} catch (ex) {}
return detector;
},
_getDetectorAccesskey: function(detector) {
try {
return gBundle.GetStringFromName("charsetMenuAutodet." + detector + ".key");
} catch (ex) {}
return "";
},
_getCharsetLabel: function(charset) {
try {
return gBundle.GetStringFromName(charset);
} catch (ex) {}
return charset;
},
_getCharsetAccessKey: function(charset) {
try {
accesskey = gBundle.GetStringFromName(charset + ".key");
} catch (ex) {}
return "";
},
};
Object.freeze(CharsetMenu);