Bug 669345 - Add support for radio button elements for inline preferences. r=Unfocused
authorGeoff Lankow <geoff@darktrojan.net>
Sat, 30 Jul 2011 20:30:10 +1200
changeset 74062 9230c6aa00ea360622e7a91575b20b013793914b
parent 74061 7532423401ea47fc344f5288294cfb56b1470d95
child 74063 46ad396b43cba5f2106d9dc6b8695a3382d98d3e
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersUnfocused
bugs669345
milestone8.0a1
Bug 669345 - Add support for radio button elements for inline preferences. r=Unfocused
toolkit/mozapps/extensions/content/extensions.css
toolkit/mozapps/extensions/content/setting.xml
toolkit/mozapps/extensions/test/browser/Makefile.in
toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
toolkit/mozapps/extensions/test/browser/more_options.xul
toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
toolkit/themes/pinstripe/mozapps/extensions/extensions.css
toolkit/themes/winstripe/mozapps/extensions/extensions.css
--- a/toolkit/mozapps/extensions/content/extensions.css
+++ b/toolkit/mozapps/extensions/content/extensions.css
@@ -128,16 +128,21 @@ setting[type="color"] {
 }
 
 setting[type="file"],
 setting[type="directory"] {
   display: -moz-grid-line;
   -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-path");
 }
 
+setting[type="radio"] {
+  display: -moz-grid-line;
+  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-radio");
+}
+
 #addonitem-popup > menuitem[disabled="true"] {
   display: none;
 }
 
 #addonitem-popup[addontype="theme"] > #menuitem_enableItem,
 #addonitem-popup[addontype="theme"] > #menuitem_disableItem,
 #addonitem-popup:not([addontype="theme"]) > #menuitem_enableTheme,
 #addonitem-popup:not([addontype="theme"]) > #menuitem_disableTheme {
--- a/toolkit/mozapps/extensions/content/setting.xml
+++ b/toolkit/mozapps/extensions/content/setting.xml
@@ -17,16 +17,17 @@
    - The Initial Developer of the Original Code is
    - Mozilla Corporation.
    - Portions created by the Initial Developer are Copyright (C) 2008
    - the Initial Developer. All Rights Reserved.
    -
    - Contributor(s):
    -   Daniel Brooks <db48x@yahoo.com>
    -   Mark Finkle <mfinkle@mozilla.com>
+   -   Geoff Lankow <geoff@darktrojan.net>
    -
    - Alternatively, the contents of this file may be used under the terms of
    - either the GNU General Public License Version 2 or later (the "GPL"), or
    - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    - in which case the provisions of the GPL or the LGPL are applicable instead
    - of those above. If you wish to allow use of your version of this file only
    - under the terms of either the GPL or the LGPL, and not to allow others to
    - use your version of this file under the terms of the MPL, indicate your
@@ -466,9 +467,79 @@
             } catch (e) {}
           }
           return this.input.value = label;
        ]]>
         </setter>
       </property>
     </implementation>
   </binding>
+
+  <binding id="setting-radio" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
+    <content>
+      <xul:vbox class="setting-label">
+        <xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
+        <xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
+          <children/>
+        </xul:label>
+      </xul:vbox>
+      <xul:hbox class="setting-input">
+        <children include="radiogroup" />
+      </xul:hbox>
+    </content>
+
+    <implementation>
+      <constructor>
+        <![CDATA[
+          let self = this;
+          this.radioGroup.addEventListener("command", function() {
+            self.valueToPreference();
+          }, false);
+        ]]>
+      </constructor>
+
+      <method name="valueFromPreference">
+        <body>
+        <![CDATA[
+          let val;
+          switch (Services.prefs.getPrefType(this.pref)) {
+            case Ci.nsIPrefBranch.PREF_STRING:
+              val = Services.prefs.getCharPref(this.pref);
+              break;
+            case Ci.nsIPrefBranch.PREF_INT:
+              val = Services.prefs.getIntPref(this.pref);
+              break;
+            case Ci.nsIPrefBranch.PREF_BOOL:
+              val = Services.prefs.getBoolPref(this.pref).toString();
+              break;
+            default:
+              return;
+          }
+
+          for (let i = 0; i < this.radioGroup.itemCount; i++) {
+            if (this.radioGroup.getItemAtIndex(i).value == val) {
+              this.radioGroup.selectedIndex = i;
+              break;
+            }
+          }
+        ]]>
+        </body>
+      </method>
+
+      <method name="valueToPreference">
+        <body>
+        <![CDATA[
+          // We might not have a pref already set, so we guess the type from the value attribute
+          let val = this.radioGroup.selectedItem.value;
+          if (val == "true" || val == "false")
+            Services.prefs.setBoolPref(this.pref, val == "true");
+          else if (/^-?\d+$/.test(val))
+            Services.prefs.setIntPref(this.pref, val);
+          else
+            Services.prefs.setCharPref(this.pref, val);
+        ]]>
+        </body>
+      </method>
+
+      <field name="radioGroup">this.getElementsByTagName("radiogroup")[0];</field>
+    </implementation>
+  </binding>
 </bindings>
--- a/toolkit/mozapps/extensions/test/browser/Makefile.in
+++ b/toolkit/mozapps/extensions/test/browser/Makefile.in
@@ -114,16 +114,17 @@ include $(DEPTH)/config/autoconf.mk
   browser_updatessl.rdf^headers^ \
   browser_install.rdf \
   browser_install.rdf^headers^ \
   browser_install.xml \
   browser_install1_3.xpi \
   browser_eula.xml \
   browser_purchase.xml \
   discovery.html \
+  more_options.xul \
   options.xul \
   redirect.sjs \
   releaseNotes.xhtml \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 libs:: $(_MAIN_TEST_FILES)
--- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
@@ -37,16 +37,23 @@ function test() {
 
   gProvider.createAddons([{
     id: "inlinesettings2@tests.mozilla.org",
     name: "Inline Settings (Regular)",
     version: "1",
     optionsURL: CHROMEROOT + "options.xul",
     optionsType: AddonManager.OPTIONS_TYPE_INLINE
   },{
+    id: "inlinesettings3@tests.mozilla.org",
+    name: "Inline Settings (More Options)",
+    description: "Tests for option types introduced after Mozilla 7.0",
+    version: "1",
+    optionsURL: CHROMEROOT + "more_options.xul",
+    optionsType: AddonManager.OPTIONS_TYPE_INLINE
+  },{
     id: "noninlinesettings@tests.mozilla.org",
     name: "Non-Inline Settings",
     version: "1",
     optionsURL: CHROMEROOT + "addon_prefs.xul"
   }]);
 
   installAddon(function () {
     open_manager("addons://list/extension", function(aWindow) {
@@ -65,16 +72,19 @@ function end_test() {
 
   Services.prefs.clearUserPref("extensions.inlinesettings1.bool");
   Services.prefs.clearUserPref("extensions.inlinesettings1.boolint");
   Services.prefs.clearUserPref("extensions.inlinesettings1.integer");
   Services.prefs.clearUserPref("extensions.inlinesettings1.string");
   Services.prefs.clearUserPref("extensions.inlinesettings1.color");
   Services.prefs.clearUserPref("extensions.inlinesettings1.file");
   Services.prefs.clearUserPref("extensions.inlinesettings1.directory");
+  Services.prefs.clearUserPref("extensions.inlinesettings3.radioBool");
+  Services.prefs.clearUserPref("extensions.inlinesettings3.radioInt");
+  Services.prefs.clearUserPref("extensions.inlinesettings3.radioString");
 
   close_manager(gManagerWindow, function() {
     AddonManager.getAddonByID("inlinesettings1@tests.mozilla.org", function(aAddon) {
       aAddon.uninstall();
       finish();
     });
   });
 }
@@ -250,16 +260,73 @@ add_test(function() {
       button = gManagerWindow.document.getElementById("detail-prefs-btn");
       is_element_hidden(button, "Preferences button should not be visible");
 
       gCategoryUtilities.openType("extension", run_next_test);
     }
   });
 });
 
+// Tests for the setting.xml bindings introduced after Mozilla 7
+add_test(function() {
+  var addon = get_addon_element(gManagerWindow, "inlinesettings3@tests.mozilla.org");
+  addon.parentNode.ensureElementIsVisible(addon);
+
+  var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
+  EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
+
+  wait_for_view_load(gManagerWindow, function() {
+    is(observer.lastData, "inlinesettings3@tests.mozilla.org", "Observer notification should have fired");
+
+    var grid = gManagerWindow.document.getElementById("detail-grid");
+    var settings = grid.querySelectorAll("rows > setting");
+    is(settings.length, 3, "Grid should have settings children");
+
+    // Force bindings to apply
+    settings[0].clientTop;
+
+    ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
+    Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false);
+    var radios = settings[0].getElementsByTagName("radio");
+    isnot(radios[0].selected, true, "Correct radio button should be selected");
+    is(radios[1].selected, true, "Correct radio button should be selected");
+    EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow);
+    is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), true, "Radio pref should have been updated");
+    EventUtils.synthesizeMouseAtCenter(radios[1], { clickCount: 1 }, gManagerWindow);
+    is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), false, "Radio pref should have been updated");
+
+    ok(!settings[1].hasAttribute("first-row"), "Not the first row");
+    Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 5);
+    var radios = settings[1].getElementsByTagName("radio");
+    isnot(radios[0].selected, true, "Correct radio button should be selected");
+    is(radios[1].selected, true, "Correct radio button should be selected");
+    isnot(radios[2].selected, true, "Correct radio button should be selected");
+    EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow);
+    is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 4, "Radio pref should have been updated");
+    EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow);
+    is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 6, "Radio pref should have been updated");
+
+    ok(!settings[2].hasAttribute("first-row"), "Not the first row");
+    Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "juliet");
+    var radios = settings[2].getElementsByTagName("radio");
+    isnot(radios[0].selected, true, "Correct radio button should be selected");
+    is(radios[1].selected, true, "Correct radio button should be selected");
+    isnot(radios[2].selected, true, "Correct radio button should be selected");
+    EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow);
+    is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "india", "Radio pref should have been updated");
+    EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow);
+    is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "kilo", "Radio pref should have been updated");
+
+    button = gManagerWindow.document.getElementById("detail-prefs-btn");
+    is_element_hidden(button, "Preferences button should not be visible");
+
+    gCategoryUtilities.openType("extension", run_next_test);
+  });
+});
+
 // Addon with inline preferences as optionsURL
 add_test(function() {
   var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org");
   addon.parentNode.ensureElementIsVisible(addon);
 
   var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
   EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
 
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/more_options.xul
@@ -0,0 +1,23 @@
+<?xml version="1.0" ?>
+<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <setting pref="extensions.inlinesettings3.radioBool" type="radio" title="Radio">
+    <radiogroup>
+      <radio label="Delta" value="true" />
+      <radio label="Echo" value="false" />
+    </radiogroup>
+  </setting>
+  <setting pref="extensions.inlinesettings3.radioInt" type="radio" title="Radio">
+    <radiogroup>
+      <radio label="Foxtrot" value="4" />
+      <radio label="Golf" value="5" />
+      <radio label="Hotel" value="6" />
+    </radiogroup>
+  </setting>
+  <setting pref="extensions.inlinesettings3.radioString" type="radio" title="Radio">
+    <radiogroup>
+      <radio label="India" value="india" />
+      <radio label="Juliet" value="juliet" />
+      <radio label="Kilo" value="kilo" />
+    </radiogroup>
+  </setting>
+</vbox>
--- a/toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
@@ -746,16 +746,20 @@ menulist { /* Fixes some styling inconsi
   margin: 1px 5px 2px 5px;
 }
 
 colorpicker[type="button"] { /* Fixes some styling inconsistencies */
   height: 29px;
   margin: 1px 5px 2px 5px;
 }
 
+setting[type="radio"] > radiogroup {
+  -moz-box-orient: horizontal;
+}
+
 /*** creator ***/
 
 .creator > label {
   -moz-margin-start: 0;
   -moz-margin-end: 0;
 }
 
 .creator > .text-link {
--- a/toolkit/themes/pinstripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/pinstripe/mozapps/extensions/extensions.css
@@ -1093,16 +1093,20 @@ setting[type="color"] colorpicker[type="
   border: 1px solid rgba(60,73,97,0.5);
   box-shadow: inset 0 1px rgba(255,255,255,0.25), 0 1px rgba(255,255,255,0.25);
   background-image: -moz-linear-gradient(rgba(255,255,255,0.45), rgba(255,255,255,0.2));
   background-clip: padding-box;
   color: #252F3B;
   text-shadow: @loweredShadow@;
 }
 
+setting[type="radio"] > radiogroup {
+  -moz-box-orient: horizontal;
+}
+
 .addon-control[disabled="true"] {
   display: none;
 }
 
 setting[type="color"] colorpicker[type="button"] {
   margin: 1px 5px 2px 5px;
   padding: 3px;
   height: 25px;
--- a/toolkit/themes/winstripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/winstripe/mozapps/extensions/extensions.css
@@ -1115,16 +1115,20 @@ setting[type="color"] colorpicker[type="
   box-shadow: 0 0 3px 1px rgba(39, 53, 68, 0.2) inset;
 }
 
 .addon-control > .button-box,
 setting:not([type="integer"]) button > .button-box {
   padding: 1px;
 }
 
+setting[type="radio"] > radiogroup {
+  -moz-box-orient: horizontal;
+}
+
 .addon-control[disabled="true"] {
   display: none;
 }
 
 .button-link {
   -moz-appearance: none;
   background: transparent;
   border: none;