Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Bug 710107 - Support radio type for simple-prefs #597

Merged
merged 7 commits into from
Oct 17, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/dev-guide-source/tutorials/l10n.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,12 @@ When the browser's locale is set to "fr-FR", they see this:

<img class="image-center" src="static-files/media/screenshots/preference-french.png" alt="screenshot of French preference localization">

The `menulist` and the `radio` preference types have options.
The `label` attribute of each option is displayed to the user.
If the locale file has a entry with the value of the `label` attribute
prefixed with "{name}_options." as its key, where {name} is the name of
the preference, its value is used as a localized label.

## Using Identifiers ##

If the localization system can't find an entry for a particular identifier
Expand Down
73 changes: 71 additions & 2 deletions doc/module-source/sdk/simple-prefs.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ They are documented along with the

The setting types map to the
[inline settings types](https://developer.mozilla.org/en/Extensions/Inline_Options)
used by the Add-on Manager. All the inline settings are supported except
for `radio` and `menulist`.
used by the Add-on Manager. All the inline settings are supported.

<table>
<tr>
Expand Down Expand Up @@ -226,6 +225,76 @@ for `radio` and `menulist`.
"title": "Select a directory"
}</pre></td>
</tr>
<tr>
<td><code>menulist</code></td>
<td><p>Displayed as a drop-down list.
The type of the stored value depends on the default value.</p>
<p>The options are specified by a mandatory "options" attribute,
that is an array of objects with mandatory attributes
"label" and "value"<p>
<p>The values of the "value" attributes must be supplied as strings.</p>
<p>The values of the "label" attributes prefixed with "{name}_options.",
where {name} is the name of the preference,
are used as localization keys.
If no matching entries are found, the value of the "label"
attributes is used verbatim as labels.</p></td>
<td><pre>
{
"name": "typeOfBreath",
"type": "menulist",
"title": "Type of breath",
"value": 0,
"options": [
{
"value": "0",
"label": "Fire"
},
{
"value": "1",
"label": "Cold"
},
{
"value": "2",
"label": "Disintegration"
}
]
}<pre></td>
</tr>
<tr>
<td><code>radio</code></td>
<td><p>Displayed as radio buttons.
The type of the stored value depends on the default value.</p>
<p>The options are specified by a mandatory "options" attribute,
that is an array of objects with mandatory attributes
"label" and "value"<p>
<p>The values of the "value" attributes must be supplied as strings.</p>
<p>The values of the "label" attributes prefixed with "{name}_options.",
where {name} is the name of the preference,
are used as localization keys.
If no matching entries are found, the value of the "label"
attributes is used verbatim as labels.</p></td>
<td><pre>
{
"name": "alignment",
"type": "radio",
"title": "Alignment",
"value": "N",
"options": [
{
"value": "L",
"label": "Lawful"
},
{
"value": "N",
"label": "Neutral"
},
{
"value": "C",
"label": "Chaotic"
}
]
}<pre></td>
</tr>
<tr>
<td><code>control</code></td>
<td><p>Displays a button.</p>
Expand Down
7 changes: 7 additions & 0 deletions lib/sdk/l10n/prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ function onOptionsDisplayed(document, addonId) {
let title = core.get(name + "_title");
if (title)
node.setAttribute("title", title);

for (let item of node.querySelectorAll("menuitem, radio")) {
let key = name + "_options." + item.getAttribute("label");
let label = core.get(key);
if (label)
item.setAttribute("label", label);
}
}
else if (node.tagName == "button") {
let label = core.get(name + "_label");
Expand Down
32 changes: 31 additions & 1 deletion python-lib/cuddlefish/options_xul.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from xml.dom.minidom import Document

VALID_PREF_TYPES = ['bool', 'boolint', 'integer', 'string', 'color', 'file',
'directory', 'control']
'directory', 'control', 'menulist', 'radio']

class Error(Exception):
pass
Expand All @@ -31,6 +31,18 @@ def validate_prefs(options):
if ("label" not in pref):
raise MissingPrefAttr("The 'control' inline pref type requires a 'label'")

# Make sure the 'menulist' type has a 'menulist'
if (pref["type"] == "menulist" or pref["type"] == "radio"):
if ("options" not in pref):
raise MissingPrefAttr("The 'menulist' and the 'radio' inline pref types requires a 'options'")

# Make sure each option has a 'value' and a 'label'
for item in pref["options"]:
if ("value" not in item):
raise MissingPrefAttr("'options' requires a 'value'")
if ("label" not in item):
raise MissingPrefAttr("'options' requires a 'label'")

# TODO: Check that pref["type"] matches default value type

def parse_options(options, jetpack_id):
Expand Down Expand Up @@ -62,6 +74,24 @@ def parse_options(options, jetpack_id):
elif (pref["type"] == "boolint"):
setting.setAttribute("on", pref["on"])
setting.setAttribute("off", pref["off"])
elif (pref["type"] == "menulist"):
menulist = doc.createElement("menulist")
menupopup = doc.createElement("menupopup")
for item in pref["options"]:
menuitem = doc.createElement("menuitem")
menuitem.setAttribute("value", item["value"])
menuitem.setAttribute("label", item["label"])
menupopup.appendChild(menuitem)
menulist.appendChild(menupopup)
setting.appendChild(menulist)
elif (pref["type"] == "radio"):
radiogroup = doc.createElement("radiogroup")
for item in pref["options"]:
radio = doc.createElement("radio")
radio.setAttribute("value", item["value"])
radio.setAttribute("label", item["label"])
radiogroup.appendChild(radio)
setting.appendChild(radiogroup)

root.appendChild(setting)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@
"type": "string",
"title": "tëst",
"value": "ünicødé"
},
{
"name": "test3",
"type": "menulist",
"title": "\"><test",
"value": "1",
"options": [
{
"value": "0",
"label": "label1"
},
{
"value": "1",
"label": "label2"
}
]
},
{
"name": "test4",
"type": "radio",
"title": "tëst",
"value": "red",
"options": [
{
"value": "red",
"label": "rouge"
},
{
"value": "blue",
"label": "bleu"
}
]
}],
"loader": "lib/main.js"
}
44 changes: 40 additions & 4 deletions python-lib/cuddlefish/tests/test_xpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from cuddlefish.tests import test_packaging
from test_linker import up

import xml.etree.ElementTree as ElementTree

xpi_template_path = os.path.join(test_packaging.static_files_path,
'xpi-template')

Expand Down Expand Up @@ -40,15 +42,49 @@ def testPackageWithSimplePrefs(self):
self.makexpi('simple-prefs')
self.failUnless('options.xul' in self.xpi.namelist())
optsxul = self.xpi.read('options.xul').decode("utf-8")
self.failUnless('pref="extensions.jid1-fZHqN9JfrDBa8A@jetpack.test"'
in optsxul, optsxul)
self.failUnless('type="bool"' in optsxul, optsxul)
self.failUnless(u'title="t\u00EBst"' in optsxul, repr(optsxul))
self.failUnlessEqual(self.xpi_harness_options["jetpackID"],
"jid1-fZHqN9JfrDBa8A@jetpack")

root = ElementTree.XML(optsxul.encode('utf-8'))

xulNamespacePrefix = \
"{http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul}"

settings = root.findall(xulNamespacePrefix + 'setting')

def assertPref(setting, name, prefType, title):
packageName = 'jid1-fZHqN9JfrDBa8A@jetpack'
self.failUnlessEqual(setting.get('data-jetpack-id'), packageName)
self.failUnlessEqual(setting.get('pref'),
'extensions.' + packageName + '.' + name)
self.failUnlessEqual(setting.get('pref-name'), name)
self.failUnlessEqual(setting.get('type'), prefType)
self.failUnlessEqual(setting.get('title'), title)

assertPref(settings[0], 'test', 'bool', u't\u00EBst')
assertPref(settings[1], 'test2', 'string', u't\u00EBst')
assertPref(settings[2], 'test3', 'menulist', '"><test')
assertPref(settings[3], 'test4', 'radio', u't\u00EBst')

menuItems = settings[2].findall(
'{0}menulist/{0}menupopup/{0}menuitem'.format(xulNamespacePrefix))
radios = settings[3].findall(
'{0}radiogroup/{0}radio'.format(xulNamespacePrefix))

def assertOption(option, value, label):
self.failUnlessEqual(option.get('value'), value)
self.failUnlessEqual(option.get('label'), label)

assertOption(menuItems[0], "0", "label1")
assertOption(menuItems[1], "1", "label2")
assertOption(radios[0], "red", "rouge")
assertOption(radios[1], "blue", "bleu")

prefsjs = self.xpi.read('defaults/preferences/prefs.js').decode("utf-8")
exp = [u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test", false);',
u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test2", "\u00FCnic\u00F8d\u00E9");',
u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test3", "1");',
u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test4", "red");',
]
self.failUnlessEqual(prefsjs, "\n".join(exp)+"\n")

Expand Down