toolkit/content/widgets/preferences.xml

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/content/widgets/preferences.xml	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1325 @@
     1.4 +<?xml version="1.0"?>
     1.5 +
     1.6 +<!DOCTYPE bindings [
     1.7 +  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
     1.8 +  %preferencesDTD;
     1.9 +  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
    1.10 +  %globalKeysDTD;
    1.11 +]>
    1.12 +
    1.13 +<bindings id="preferencesBindings"
    1.14 +          xmlns="http://www.mozilla.org/xbl"
    1.15 +          xmlns:xbl="http://www.mozilla.org/xbl"
    1.16 +          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    1.17 +
    1.18 +#
    1.19 +# = Preferences Window Framework
    1.20 +#
    1.21 +#   The syntax for use looks something like:
    1.22 +#
    1.23 +#   <prefwindow>
    1.24 +#     <prefpane id="prefPaneA">
    1.25 +#       <preferences>
    1.26 +#         <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
    1.27 +#         <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
    1.28 +#       </preferences>
    1.29 +#       <checkbox label="Preference" preference="preference1"/>
    1.30 +#     </prefpane>
    1.31 +#   </prefwindow>
    1.32 +#
    1.33 +
    1.34 +  <binding id="preferences">
    1.35 +    <implementation implements="nsIObserver">
    1.36 +      <method name="observe">
    1.37 +        <parameter name="aSubject"/>
    1.38 +        <parameter name="aTopic"/>
    1.39 +        <parameter name="aData"/>
    1.40 +        <body>
    1.41 +        <![CDATA[
    1.42 +          for (var i = 0; i < this.childNodes.length; ++i) {
    1.43 +            var preference = this.childNodes[i];
    1.44 +            if (preference.name == aData) {
    1.45 +              preference.value = preference.valueFromPreferences;
    1.46 +            }
    1.47 +          }
    1.48 +        ]]>
    1.49 +        </body>
    1.50 +      </method>
    1.51 +      
    1.52 +      <method name="fireChangedEvent">
    1.53 +        <parameter name="aPreference"/>
    1.54 +        <body>
    1.55 +        <![CDATA[
    1.56 +          // Value changed, synthesize an event
    1.57 +          try {
    1.58 +            var event = document.createEvent("Events");
    1.59 +            event.initEvent("change", true, true);
    1.60 +            aPreference.dispatchEvent(event);
    1.61 +          }
    1.62 +          catch (e) {
    1.63 +            Components.utils.reportError(e);
    1.64 +          }
    1.65 +        ]]>
    1.66 +        </body>
    1.67 +      </method>
    1.68 +      
    1.69 +      <field name="service">
    1.70 +        Components.classes["@mozilla.org/preferences-service;1"]
    1.71 +                  .getService(Components.interfaces.nsIPrefService);
    1.72 +      </field>
    1.73 +      <field name="rootBranch">
    1.74 +        Components.classes["@mozilla.org/preferences-service;1"]
    1.75 +                  .getService(Components.interfaces.nsIPrefBranch);
    1.76 +      </field>
    1.77 +      <field name="defaultBranch">
    1.78 +        this.service.getDefaultBranch("");
    1.79 +      </field>
    1.80 +      <field name="rootBranchInternal">
    1.81 +        Components.classes["@mozilla.org/preferences-service;1"]
    1.82 +                  .getService(Components.interfaces.nsIPrefBranchInternal);
    1.83 +      </field>
    1.84 +      <property name="type" readonly="true">
    1.85 +        <getter>
    1.86 +          <![CDATA[
    1.87 +            return document.documentElement.type || "";
    1.88 +          ]]>
    1.89 +        </getter>
    1.90 +      </property>
    1.91 +      <property name="instantApply" readonly="true">
    1.92 +        <getter>
    1.93 +          <![CDATA[
    1.94 +            var doc = document.documentElement;
    1.95 +            return this.type == "child" ? doc.instantApply
    1.96 +                                        : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
    1.97 +          ]]>
    1.98 +        </getter>
    1.99 +      </property>
   1.100 +    </implementation>
   1.101 +  </binding>
   1.102 +
   1.103 +  <binding id="preference">
   1.104 +    <implementation>
   1.105 +      <constructor>
   1.106 +      <![CDATA[
   1.107 +        // if the element has been inserted without the name attribute set,
   1.108 +        // we have nothing to do here
   1.109 +        if (!this.name)
   1.110 +          return;
   1.111 +
   1.112 +        this.preferences.rootBranchInternal
   1.113 +            .addObserver(this.name, this.preferences, false);
   1.114 +        // In non-instant apply mode, we must try and use the last saved state
   1.115 +        // from any previous opens of a child dialog instead of the value from
   1.116 +        // preferences, to pick up any edits a user may have made. 
   1.117 +        if (this.preferences.type == "child" && 
   1.118 +            !this.instantApply && window.opener) {
   1.119 +          var pdoc = window.opener.document;
   1.120 +
   1.121 +          // Try to find a preference element for the same preference.
   1.122 +          var preference = null;
   1.123 +          var parentPreferences = pdoc.getElementsByTagName("preferences");
   1.124 +          for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
   1.125 +            var parentPrefs = parentPreferences[k]
   1.126 +                                    .getElementsByAttribute("name", this.name);
   1.127 +            for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
   1.128 +              if (parentPrefs[l].localName == "preference")
   1.129 +                preference = parentPrefs[l];
   1.130 +            }
   1.131 +          }
   1.132 +          this._setValue(preference ? preference.value 
   1.133 +                                    : this.valueFromPreferences, false);
   1.134 +        }
   1.135 +        else
   1.136 +          this._setValue(this.valueFromPreferences, false);
   1.137 +      ]]>
   1.138 +      </constructor>
   1.139 +      <destructor>
   1.140 +        this.preferences.rootBranchInternal
   1.141 +            .removeObserver(this.name, this.preferences);
   1.142 +      </destructor>
   1.143 +      
   1.144 +      <property name="instantApply">
   1.145 +        <getter>
   1.146 +          return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
   1.147 +        </getter>
   1.148 +      </property>
   1.149 +
   1.150 +      <property name="preferences" onget="return this.parentNode"/>
   1.151 +      <property name="name" onget="return this.getAttribute('name');">
   1.152 +        <setter>
   1.153 +          if (val == this.name)
   1.154 +            return val;
   1.155 +            
   1.156 +          this.preferences.rootBranchInternal
   1.157 +              .removeObserver(this.name, this.preferences);
   1.158 +          this.setAttribute('name', val);
   1.159 +          this.preferences.rootBranchInternal
   1.160 +              .addObserver(val, this.preferences, false);
   1.161 +              
   1.162 +          return val;
   1.163 +        </setter>
   1.164 +      </property>
   1.165 +      <property name="type" onget="return this.getAttribute('type');"
   1.166 +                            onset="this.setAttribute('type', val); return val;"/>
   1.167 +      <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
   1.168 +                                onset="this.setAttribute('inverted', val); return val;"/>
   1.169 +      <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
   1.170 +                                onset="this.setAttribute('readonly', val); return val;"/>
   1.171 +
   1.172 +      <field name="_value">null</field>
   1.173 +      <method name="_setValue">
   1.174 +        <parameter name="aValue"/>
   1.175 +        <parameter name="aUpdate"/>
   1.176 +        <body>
   1.177 +        <![CDATA[
   1.178 +          if (aUpdate && this.value !== aValue) {
   1.179 +            this._value = aValue;
   1.180 +            if (this.instantApply)
   1.181 +              this.valueFromPreferences = aValue;
   1.182 +            this.preferences.fireChangedEvent(this);
   1.183 +          }
   1.184 +          else if (!aUpdate) {
   1.185 +            this._value = aValue;
   1.186 +            this.updateElements();
   1.187 +          }
   1.188 +          return aValue;
   1.189 +        ]]>
   1.190 +        </body>
   1.191 +      </method>
   1.192 +      <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/>
   1.193 +      
   1.194 +      <property name="locked">
   1.195 +        <getter>
   1.196 +          return this.preferences.rootBranch.prefIsLocked(this.name);
   1.197 +        </getter>
   1.198 +      </property>
   1.199 +      
   1.200 +      <property name="disabled">
   1.201 +        <getter>
   1.202 +          return this.getAttribute("disabled") == "true";
   1.203 +        </getter>
   1.204 +        <setter>
   1.205 +        <![CDATA[
   1.206 +          if (val) 
   1.207 +            this.setAttribute("disabled", "true");
   1.208 +          else
   1.209 +            this.removeAttribute("disabled");
   1.210 +
   1.211 +          if (!this.id)
   1.212 +            return val;
   1.213 +
   1.214 +          var elements = document.getElementsByAttribute("preference", this.id);
   1.215 +          for (var i = 0; i < elements.length; ++i) {
   1.216 +            elements[i].disabled = val;
   1.217 +            
   1.218 +            var labels = document.getElementsByAttribute("control", elements[i].id);
   1.219 +            for (var j = 0; j < labels.length; ++j)
   1.220 +              labels[j].disabled = val;
   1.221 +          }
   1.222 +            
   1.223 +          return val;
   1.224 +        ]]>
   1.225 +        </setter>
   1.226 +      </property>
   1.227 +      
   1.228 +      <property name="tabIndex">
   1.229 +        <getter>
   1.230 +          return parseInt(this.getAttribute("tabindex"));
   1.231 +        </getter>
   1.232 +        <setter>
   1.233 +        <![CDATA[
   1.234 +          if (val) 
   1.235 +            this.setAttribute("tabindex", val);
   1.236 +          else
   1.237 +            this.removeAttribute("tabindex");
   1.238 +
   1.239 +          if (!this.id)
   1.240 +            return val;
   1.241 +
   1.242 +          var elements = document.getElementsByAttribute("preference", this.id);
   1.243 +          for (var i = 0; i < elements.length; ++i) {
   1.244 +            elements[i].tabIndex = val;
   1.245 +            
   1.246 +            var labels = document.getElementsByAttribute("control", elements[i].id);
   1.247 +            for (var j = 0; j < labels.length; ++j)
   1.248 +              labels[j].tabIndex = val;
   1.249 +          }
   1.250 +            
   1.251 +          return val;
   1.252 +        ]]>
   1.253 +        </setter>
   1.254 +      </property>
   1.255 +
   1.256 +      <property name="hasUserValue">
   1.257 +        <getter>
   1.258 +        <![CDATA[
   1.259 +          return this.preferences.rootBranch.prefHasUserValue(this.name) &&
   1.260 +                 this.value !== undefined;
   1.261 +        ]]>
   1.262 +        </getter>
   1.263 +      </property>
   1.264 +      
   1.265 +      <method name="reset">
   1.266 +        <body>
   1.267 +          // defer reset until preference update
   1.268 +          this.value = undefined;
   1.269 +        </body>
   1.270 +      </method>
   1.271 +
   1.272 +      <field name="_useDefault">false</field>      
   1.273 +      <property name="defaultValue">
   1.274 +        <getter>
   1.275 +        <![CDATA[
   1.276 +          this._useDefault = true;
   1.277 +          var val = this.valueFromPreferences;
   1.278 +          this._useDefault = false;
   1.279 +          return val;
   1.280 +        ]]>
   1.281 +        </getter>
   1.282 +      </property>
   1.283 +      
   1.284 +      <property name="_branch">
   1.285 +        <getter>
   1.286 +          return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
   1.287 +        </getter>
   1.288 +      </property>
   1.289 +      
   1.290 +      <field name="batching">false</field>
   1.291 +      
   1.292 +      <method name="_reportUnknownType">
   1.293 +        <body>
   1.294 +        <![CDATA[
   1.295 +          var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
   1.296 +                                         .getService(Components.interfaces.nsIConsoleService);
   1.297 +          var msg = "<preference> with id='" + this.id + "' and name='" + 
   1.298 +                    this.name + "' has unknown type '" + this.type + "'.";
   1.299 +          consoleService.logStringMessage(msg);
   1.300 +        ]]>
   1.301 +        </body>
   1.302 +      </method>
   1.303 +      
   1.304 +      <property name="valueFromPreferences">
   1.305 +        <getter>
   1.306 +        <![CDATA[
   1.307 +          try {
   1.308 +            // Force a resync of value with preferences.
   1.309 +            switch (this.type) {
   1.310 +            case "int":
   1.311 +              return this._branch.getIntPref(this.name);
   1.312 +            case "bool":
   1.313 +              var val = this._branch.getBoolPref(this.name);
   1.314 +              return this.inverted ? !val : val;
   1.315 +            case "wstring":
   1.316 +              return this._branch
   1.317 +                         .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
   1.318 +                         .data;
   1.319 +            case "string":
   1.320 +            case "unichar":
   1.321 +              return this._branch
   1.322 +                         .getComplexValue(this.name, Components.interfaces.nsISupportsString)
   1.323 +                         .data;
   1.324 +            case "fontname":
   1.325 +              var family = this._branch
   1.326 +                               .getComplexValue(this.name, Components.interfaces.nsISupportsString)
   1.327 +                               .data;
   1.328 +              var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
   1.329 +                                             .createInstance(Components.interfaces.nsIFontEnumerator);
   1.330 +              return fontEnumerator.getStandardFamilyName(family);
   1.331 +            case "file":
   1.332 +              var f = this._branch
   1.333 +                          .getComplexValue(this.name, Components.interfaces.nsILocalFile);
   1.334 +              return f;
   1.335 +            default:
   1.336 +              this._reportUnknownType();
   1.337 +            }
   1.338 +          }
   1.339 +          catch (e) { }
   1.340 +          return null;
   1.341 +        ]]>
   1.342 +        </getter>
   1.343 +        <setter>
   1.344 +        <![CDATA[
   1.345 +          // Exit early if nothing to do.
   1.346 +          if (this.readonly || this.valueFromPreferences == val)
   1.347 +            return val;
   1.348 +
   1.349 +          // The special value undefined means 'reset preference to default'.
   1.350 +          if (val === undefined) {
   1.351 +            this.preferences.rootBranch.clearUserPref(this.name);
   1.352 +            return val;
   1.353 +          }
   1.354 +
   1.355 +          // Force a resync of preferences with value.
   1.356 +          switch (this.type) {
   1.357 +          case "int":
   1.358 +            this.preferences.rootBranch.setIntPref(this.name, val);
   1.359 +            break;
   1.360 +          case "bool":
   1.361 +            this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
   1.362 +            break;
   1.363 +          case "wstring":
   1.364 +            var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
   1.365 +                                .createInstance(Components.interfaces.nsIPrefLocalizedString);
   1.366 +            pls.data = val;
   1.367 +            this.preferences.rootBranch
   1.368 +                .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
   1.369 +            break;
   1.370 +          case "string":
   1.371 +          case "unichar":
   1.372 +          case "fontname":
   1.373 +            var iss = Components.classes["@mozilla.org/supports-string;1"]
   1.374 +                                .createInstance(Components.interfaces.nsISupportsString);
   1.375 +            iss.data = val;
   1.376 +            this.preferences.rootBranch
   1.377 +                .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss);
   1.378 +            break;
   1.379 +          case "file":
   1.380 +            var lf;
   1.381 +            if (typeof(val) == "string") {
   1.382 +              lf = Components.classes["@mozilla.org/file/local;1"]
   1.383 +                             .createInstance(Components.interfaces.nsILocalFile);
   1.384 +              lf.persistentDescriptor = val;
   1.385 +              if (!lf.exists())
   1.386 +                lf.initWithPath(val);
   1.387 +            }
   1.388 +            else 
   1.389 +              lf = val.QueryInterface(Components.interfaces.nsILocalFile);
   1.390 +            this.preferences.rootBranch
   1.391 +                .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
   1.392 +            break;
   1.393 +          default:
   1.394 +            this._reportUnknownType();
   1.395 +          }
   1.396 +          if (!this.batching)
   1.397 +            this.preferences.service.savePrefFile(null);
   1.398 +          return val;
   1.399 +        ]]>
   1.400 +        </setter>
   1.401 +      </property>
   1.402 +      
   1.403 +      <method name="setElementValue">
   1.404 +        <parameter name="aElement"/>
   1.405 +        <body>
   1.406 +        <![CDATA[
   1.407 +          if (this.locked)
   1.408 +            aElement.disabled = true;
   1.409 +
   1.410 +          if (!this.isElementEditable(aElement))
   1.411 +            return;
   1.412 +
   1.413 +          var rv = undefined;
   1.414 +          if (aElement.hasAttribute("onsyncfrompreference")) {
   1.415 +            // Value changed, synthesize an event
   1.416 +            try {
   1.417 +              var event = document.createEvent("Events");
   1.418 +              event.initEvent("syncfrompreference", true, true);
   1.419 +              var f = new Function ("event", 
   1.420 +                                    aElement.getAttribute("onsyncfrompreference"));
   1.421 +              rv = f.call(aElement, event);
   1.422 +            }
   1.423 +            catch (e) {
   1.424 +              Components.utils.reportError(e);
   1.425 +            }
   1.426 +          }
   1.427 +          var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value);
   1.428 +          // if the preference is marked for reset, show default value in UI
   1.429 +          if (val === undefined)
   1.430 +            val = this.defaultValue;
   1.431 +
   1.432 +          /**
   1.433 +           * Initialize a UI element property with a value. Handles the case 
   1.434 +           * where an element has not yet had a XBL binding attached for it and
   1.435 +           * the property setter does not yet exist by setting the same attribute
   1.436 +           * on the XUL element using DOM apis and assuming the element's 
   1.437 +           * constructor or property getters appropriately handle this state. 
   1.438 +           */
   1.439 +          function setValue(element, attribute, value) {
   1.440 +            if (attribute in element) 
   1.441 +              element[attribute] = value;
   1.442 +            else
   1.443 +              element.setAttribute(attribute, value);
   1.444 +          }
   1.445 +          if (aElement.localName == "checkbox" ||
   1.446 +              aElement.localName == "listitem")
   1.447 +            setValue(aElement, "checked", val);
   1.448 +          else if (aElement.localName == "colorpicker")
   1.449 +            setValue(aElement, "color", val);
   1.450 +          else if (aElement.localName == "textbox") {
   1.451 +            // XXXmano Bug 303998: Avoid a caret placement issue if either the
   1.452 +            // preference observer or its setter calls updateElements as a result
   1.453 +            // of the input event handler.
   1.454 +            if (aElement.value !== val)
   1.455 +              setValue(aElement, "value", val);
   1.456 +          }
   1.457 +          else
   1.458 +            setValue(aElement, "value", val);
   1.459 +        ]]>
   1.460 +        </body>
   1.461 +      </method>
   1.462 +
   1.463 +      <method name="getElementValue">
   1.464 +        <parameter name="aElement"/>
   1.465 +        <body>
   1.466 +        <![CDATA[
   1.467 +          if (aElement.hasAttribute("onsynctopreference")) {
   1.468 +            // Value changed, synthesize an event
   1.469 +            try {
   1.470 +              var event = document.createEvent("Events");
   1.471 +              event.initEvent("synctopreference", true, true);
   1.472 +              var f = new Function ("event", 
   1.473 +                                    aElement.getAttribute("onsynctopreference"));
   1.474 +              var rv = f.call(aElement, event);
   1.475 +              if (rv !== undefined) 
   1.476 +                return rv;
   1.477 +            }
   1.478 +            catch (e) {
   1.479 +              Components.utils.reportError(e);
   1.480 +            }
   1.481 +          }
   1.482 +          
   1.483 +          /**
   1.484 +           * Read the value of an attribute from an element, assuming the 
   1.485 +           * attribute is a property on the element's node API. If the property
   1.486 +           * is not present in the API, then assume its value is contained in
   1.487 +           * an attribute, as is the case before a binding has been attached.
   1.488 +           */
   1.489 +          function getValue(element, attribute) {
   1.490 +            if (attribute in element)
   1.491 +              return element[attribute];
   1.492 +            return element.getAttribute(attribute);
   1.493 +          }
   1.494 +          if (aElement.localName == "checkbox" ||
   1.495 +              aElement.localName == "listitem")
   1.496 +            var value = getValue(aElement, "checked");
   1.497 +          else if (aElement.localName == "colorpicker")
   1.498 +            value = getValue(aElement, "color");
   1.499 +          else
   1.500 +            value = getValue(aElement, "value");
   1.501 +
   1.502 +          switch (this.type) {
   1.503 +          case "int":
   1.504 +            return parseInt(value, 10) || 0;
   1.505 +          case "bool":
   1.506 +            return typeof(value) == "boolean" ? value : value == "true";
   1.507 +          }
   1.508 +          return value;
   1.509 +        ]]>
   1.510 +        </body>
   1.511 +      </method>
   1.512 +      
   1.513 +      <method name="isElementEditable">
   1.514 +        <parameter name="aElement"/>
   1.515 +        <body>
   1.516 +        <![CDATA[
   1.517 +          switch (aElement.localName) {
   1.518 +          case "checkbox":
   1.519 +          case "colorpicker":
   1.520 +          case "radiogroup":
   1.521 +          case "textbox":
   1.522 +          case "listitem":
   1.523 +          case "listbox":
   1.524 +          case "menulist":
   1.525 +            return true;
   1.526 +          }
   1.527 +          return aElement.getAttribute("preference-editable") == "true";
   1.528 +        ]]> 
   1.529 +        </body>
   1.530 +      </method>
   1.531 +      
   1.532 +      <method name="updateElements">
   1.533 +        <body>
   1.534 +        <![CDATA[
   1.535 +          if (!this.id)
   1.536 +            return;
   1.537 +
   1.538 +          // This "change" event handler tracks changes made to preferences by 
   1.539 +          // sources other than the user in this window. 
   1.540 +          var elements = document.getElementsByAttribute("preference", this.id);
   1.541 +          for (var i = 0; i < elements.length; ++i) 
   1.542 +            this.setElementValue(elements[i]);
   1.543 +        ]]>
   1.544 +        </body>
   1.545 +      </method>
   1.546 +    </implementation>
   1.547 +    
   1.548 +    <handlers>
   1.549 +      <handler event="change">
   1.550 +        this.updateElements();
   1.551 +      </handler>
   1.552 +    </handlers>
   1.553 +  </binding>
   1.554 +
   1.555 +  <binding id="prefwindow"
   1.556 +           extends="chrome://global/content/bindings/dialog.xml#dialog">
   1.557 +    <resources>
   1.558 +      <stylesheet src="chrome://global/skin/preferences.css"/>
   1.559 +    </resources>
   1.560 +    <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
   1.561 +             closebuttonlabel="&preferencesCloseButton.label;"
   1.562 +             closebuttonaccesskey="&preferencesCloseButton.accesskey;"
   1.563 +             role="dialog"
   1.564 +#ifdef XP_WIN
   1.565 +             title="&preferencesDefaultTitleWin.title;">
   1.566 +#else
   1.567 +             title="&preferencesDefaultTitleMac.title;">
   1.568 +#endif
   1.569 +      <xul:windowdragbox orient="vertical">
   1.570 +        <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
   1.571 +                        role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
   1.572 +      </xul:windowdragbox>
   1.573 +      <xul:hbox flex="1" class="paneDeckContainer">
   1.574 +        <xul:deck anonid="paneDeck" flex="1">
   1.575 +          <children includes="prefpane"/>
   1.576 +        </xul:deck>
   1.577 +      </xul:hbox>
   1.578 +      <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end">
   1.579 +#ifdef XP_UNIX
   1.580 +        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
   1.581 +        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
   1.582 +        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
   1.583 +        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
   1.584 +        <xul:spacer anonid="spacer" flex="1"/>
   1.585 +        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
   1.586 +        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
   1.587 +#else
   1.588 +        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
   1.589 +        <xul:spacer anonid="spacer" flex="1"/>
   1.590 +        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
   1.591 +        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
   1.592 +        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
   1.593 +        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
   1.594 +        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
   1.595 +#endif
   1.596 +      </xul:hbox>
   1.597 +      <xul:hbox>
   1.598 +        <children/>
   1.599 +      </xul:hbox>
   1.600 +    </content>
   1.601 +    <implementation implements="nsITimerCallback">
   1.602 +      <constructor>
   1.603 +      <![CDATA[
   1.604 +        if (this.type != "child") {
   1.605 +          var psvc = Components.classes["@mozilla.org/preferences-service;1"]
   1.606 +                               .getService(Components.interfaces.nsIPrefBranch);
   1.607 +          this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
   1.608 +          if (this.instantApply) {
   1.609 +            var docElt = document.documentElement;
   1.610 +            var acceptButton = docElt.getButton("accept");
   1.611 +            acceptButton.hidden = true;
   1.612 +            var cancelButton  = docElt.getButton("cancel");
   1.613 +#ifdef XP_MACOSX
   1.614 +            // no buttons on Mac except Help
   1.615 +            cancelButton.hidden = true;
   1.616 +            // Move Help button to the end
   1.617 +            document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true;         
   1.618 +            // Also, don't fire onDialogAccept on enter
   1.619 +            acceptButton.disabled = true;
   1.620 +#else
   1.621 +            // morph the Cancel button into the Close button
   1.622 +            cancelButton.setAttribute ("icon", "close");
   1.623 +            cancelButton.label = docElt.getAttribute("closebuttonlabel");
   1.624 +            cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
   1.625 +#endif
   1.626 +          }
   1.627 +        }
   1.628 +        this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
   1.629 +        var panes = this.preferencePanes;
   1.630 +
   1.631 +        var lastPane = null;
   1.632 +        if (this.lastSelected) {
   1.633 +          lastPane = document.getElementById(this.lastSelected);
   1.634 +          if (!lastPane) {
   1.635 +            this.lastSelected = "";
   1.636 +          }
   1.637 +        }
   1.638 +
   1.639 +        var paneToLoad;
   1.640 +        if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
   1.641 +          paneToLoad = document.getElementById(window.arguments[0]);
   1.642 +          this.lastSelected = paneToLoad.id;
   1.643 +        }
   1.644 +        else if (lastPane)
   1.645 +          paneToLoad = lastPane;
   1.646 +        else
   1.647 +          paneToLoad = panes[0];
   1.648 +
   1.649 +        for (var i = 0; i < panes.length; ++i) {
   1.650 +          this._makePaneButton(panes[i]);
   1.651 +          if (panes[i].loaded) {
   1.652 +            // Inline pane content, fire load event to force initialization.
   1.653 +            this._fireEvent("paneload", panes[i]);
   1.654 +          }
   1.655 +        }
   1.656 +        this.showPane(paneToLoad);
   1.657 +
   1.658 +        if (panes.length == 1)
   1.659 +          this._selector.setAttribute("collapsed", "true");
   1.660 +      ]]>
   1.661 +      </constructor>
   1.662 +
   1.663 +      <destructor>
   1.664 +      <![CDATA[
   1.665 +        // Release timers to avoid reference cycles.
   1.666 +        if (this._animateTimer) {
   1.667 +          this._animateTimer.cancel();
   1.668 +          this._animateTimer = null;
   1.669 +        }
   1.670 +        if (this._fadeTimer) {
   1.671 +          this._fadeTimer.cancel();
   1.672 +          this._fadeTimer = null;
   1.673 +        }
   1.674 +      ]]>
   1.675 +      </destructor>
   1.676 +
   1.677 +      <field name="instantApply">false</field>
   1.678 +      
   1.679 +      <property name="preferencePanes"
   1.680 +                onget="return this.getElementsByTagName('prefpane');"/>
   1.681 +
   1.682 +      <property name="type" onget="return this.getAttribute('type');"/>
   1.683 +      <property name="_paneDeck"
   1.684 +                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
   1.685 +      <property name="_paneDeckContainer"
   1.686 +                onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
   1.687 +      <property name="_selector"
   1.688 +                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
   1.689 +      <property name="lastSelected" 
   1.690 +                onget="return this.getAttribute('lastSelected');">
   1.691 +        <setter>
   1.692 +          this.setAttribute("lastSelected", val); 
   1.693 +          document.persist(this.id, "lastSelected");
   1.694 +          return val;
   1.695 +        </setter>          
   1.696 +      </property>
   1.697 +      <property name="currentPane"
   1.698 +                onset="return this._currentPane = val;">
   1.699 +        <getter>
   1.700 +          if (!this._currentPane)
   1.701 +            this._currentPane = this.preferencePanes[0];
   1.702 +          
   1.703 +          return this._currentPane;
   1.704 +        </getter> 
   1.705 +      </property>
   1.706 +      <field name="_currentPane">null</field>
   1.707 +      
   1.708 +      
   1.709 +      <method name="_makePaneButton">
   1.710 +        <parameter name="aPaneElement"/>
   1.711 +        <body>
   1.712 +        <![CDATA[
   1.713 +          var radio = document.createElement("radio");
   1.714 +          radio.setAttribute("pane", aPaneElement.id);
   1.715 +          radio.setAttribute("label", aPaneElement.label);
   1.716 +          // Expose preference group choice to accessibility APIs as an unchecked list item
   1.717 +          // The parent group is exposed to accessibility APIs as a list
   1.718 +          if (aPaneElement.image)
   1.719 +            radio.setAttribute("src", aPaneElement.image);
   1.720 +          radio.style.listStyleImage = aPaneElement.style.listStyleImage;
   1.721 +          this._selector.appendChild(radio);
   1.722 +          return radio;
   1.723 +        ]]>
   1.724 +        </body>
   1.725 +      </method>
   1.726 +
   1.727 +      <method name="showPane">
   1.728 +        <parameter name="aPaneElement"/>
   1.729 +        <body>
   1.730 +        <![CDATA[
   1.731 +          if (!aPaneElement)
   1.732 +            return;
   1.733 +
   1.734 +          this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
   1.735 +          if (!aPaneElement.loaded) {
   1.736 +            let OverlayLoadObserver = function(aPane)
   1.737 +            {
   1.738 +              this._pane = aPane;
   1.739 +            }
   1.740 +            OverlayLoadObserver.prototype = { 
   1.741 +              _outer: this,
   1.742 +              observe: function (aSubject, aTopic, aData) 
   1.743 +              {
   1.744 +                this._pane.loaded = true;
   1.745 +                this._outer._fireEvent("paneload", this._pane);
   1.746 +                this._outer._selectPane(this._pane);
   1.747 +              }
   1.748 +            };
   1.749 +            
   1.750 +            var obs = new OverlayLoadObserver(aPaneElement);
   1.751 +            document.loadOverlay(aPaneElement.src, obs);
   1.752 +          }
   1.753 +          else
   1.754 +            this._selectPane(aPaneElement);
   1.755 +        ]]>
   1.756 +        </body>
   1.757 +      </method>
   1.758 +      
   1.759 +      <method name="_fireEvent">
   1.760 +        <parameter name="aEventName"/>
   1.761 +        <parameter name="aTarget"/>
   1.762 +        <body>
   1.763 +        <![CDATA[
   1.764 +          // Panel loaded, synthesize a load event. 
   1.765 +          try {
   1.766 +            var event = document.createEvent("Events");
   1.767 +            event.initEvent(aEventName, true, true);
   1.768 +            var cancel = !aTarget.dispatchEvent(event);
   1.769 +            if (aTarget.hasAttribute("on" + aEventName)) {
   1.770 +              var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
   1.771 +              var rv = fn.call(aTarget, event);
   1.772 +              if (rv == false)
   1.773 +                cancel = true;
   1.774 +            }
   1.775 +            return !cancel;  
   1.776 +          }
   1.777 +          catch (e) { 
   1.778 +            Components.utils.reportError(e);
   1.779 +          }
   1.780 +          return false;
   1.781 +        ]]>
   1.782 +        </body>
   1.783 +      </method>
   1.784 +      
   1.785 +      <field name="_initialized">false</field>
   1.786 +      <method name="_selectPane">
   1.787 +        <parameter name="aPaneElement"/>
   1.788 +        <body>
   1.789 +        <![CDATA[
   1.790 +#ifdef XP_MACOSX
   1.791 +          var paneTitle = aPaneElement.label;
   1.792 +          if (paneTitle != "")
   1.793 +            document.title = paneTitle;
   1.794 +#endif
   1.795 +          var helpButton = document.documentElement.getButton("help");
   1.796 +          if (aPaneElement.helpTopic)
   1.797 +            helpButton.hidden = false;
   1.798 +          else
   1.799 +            helpButton.hidden = true;
   1.800 +
   1.801 +          // Find this pane's index in the deck and set the deck's 
   1.802 +          // selectedIndex to that value to switch to it.
   1.803 +          var prefpanes = this.preferencePanes;
   1.804 +          for (var i = 0; i < prefpanes.length; ++i) {
   1.805 +            if (prefpanes[i] == aPaneElement) {
   1.806 +              this._paneDeck.selectedIndex = i;
   1.807 +              
   1.808 +              if (this.type != "child") {
   1.809 +                if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
   1.810 +                    prefpanes.length > 1)
   1.811 +                  aPaneElement.removeAttribute("flex");
   1.812 +                // Calling sizeToContent after the first prefpane is loaded
   1.813 +                // will size the windows contents so style information is
   1.814 +                // available to calculate correct sizing.
   1.815 +                if (!this._initialized && prefpanes.length > 1) {
   1.816 +                  if (this._shouldAnimate)
   1.817 +                    this.style.minHeight = 0;
   1.818 +                  window.sizeToContent();
   1.819 +                }
   1.820 +
   1.821 +                var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
   1.822 +                oldPane.selected = !(aPaneElement.selected = true);
   1.823 +                this.lastSelected = aPaneElement.id;
   1.824 +                this.currentPane = aPaneElement;
   1.825 +                this._initialized = true;
   1.826 +
   1.827 +                // Only animate if we've switched between prefpanes
   1.828 +                if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
   1.829 +                  aPaneElement.style.opacity = 0.0;
   1.830 +                  this.animate(oldPane, aPaneElement);
   1.831 +                }
   1.832 +                else if (!this._shouldAnimate && prefpanes.length > 1) {
   1.833 +                  var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height);
   1.834 +                  var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop);
   1.835 +                  verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom);
   1.836 +                  if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
   1.837 +                    // To workaround the bottom border of a groupbox from being
   1.838 +                    // cutoff an hbox with a class of bottomBox may enclose it.
   1.839 +                    // This needs to include its padding to resize properly.
   1.840 +                    // See bug 394433
   1.841 +                    var bottomPadding = 0;
   1.842 +                    var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
   1.843 +                    if (bottomBox)
   1.844 +                      bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom);
   1.845 +                    window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
   1.846 +                  }
   1.847 +
   1.848 +                  // XXX rstrong - extend the contents of the prefpane to
   1.849 +                  // prevent elements from being cutoff (see bug 349098).
   1.850 +                  if (aPaneElement.contentHeight + verticalPadding < targetHeight)
   1.851 +                    aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
   1.852 +                }
   1.853 +              }
   1.854 +              break;
   1.855 +            }
   1.856 +          }
   1.857 +        ]]>
   1.858 +        </body>
   1.859 +      </method>
   1.860 +      
   1.861 +      <property name="_shouldAnimate">
   1.862 +        <getter>
   1.863 +        <![CDATA[
   1.864 +          var psvc = Components.classes["@mozilla.org/preferences-service;1"]
   1.865 +                               .getService(Components.interfaces.nsIPrefBranch);
   1.866 +#ifdef XP_MACOSX
   1.867 +          var animate = true;
   1.868 +#else
   1.869 +          var animate = false;
   1.870 +#endif
   1.871 +          try {
   1.872 +            animate = psvc.getBoolPref("browser.preferences.animateFadeIn");
   1.873 +          }
   1.874 +          catch (e) { }
   1.875 +          return animate;
   1.876 +        ]]>
   1.877 +        </getter>
   1.878 +      </property>
   1.879 +      
   1.880 +      <method name="animate">
   1.881 +        <parameter name="aOldPane"/>
   1.882 +        <parameter name="aNewPane"/>
   1.883 +        <body>
   1.884 +        <![CDATA[
   1.885 +          // if we are already resizing, use currentHeight
   1.886 +          var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
   1.887 +          
   1.888 +          this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
   1.889 +          var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
   1.890 +          this._animateRemainder = sizeDelta % this._animateIncrement;
   1.891 +
   1.892 +          this._setUpAnimationTimer(oldHeight);
   1.893 +        ]]>
   1.894 +        </body>
   1.895 +      </method>
   1.896 +      
   1.897 +      <property name="_sizeIncrement">
   1.898 +        <getter>
   1.899 +        <![CDATA[
   1.900 +          var lastSelectedPane = document.getElementById(this.lastSelected);
   1.901 +          var increment = this._animateIncrement * this._multiplier;
   1.902 +          var newHeight = this._currentHeight + increment;
   1.903 +          if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
   1.904 +              (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
   1.905 +            return 0;
   1.906 +          
   1.907 +          if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
   1.908 +              (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
   1.909 +            increment = this._animateRemainder * this._multiplier;
   1.910 +          return increment;
   1.911 +        ]]>
   1.912 +        </getter>
   1.913 +      </property>
   1.914 +      
   1.915 +      <method name="notify">
   1.916 +        <parameter name="aTimer"/>
   1.917 +        <body>
   1.918 +        <![CDATA[
   1.919 +          if (!document)
   1.920 +            aTimer.cancel();
   1.921 +          
   1.922 +          if (aTimer == this._animateTimer) {
   1.923 +            var increment = this._sizeIncrement;
   1.924 +            if (increment != 0) {
   1.925 +              window.innerHeight += increment;
   1.926 +              this._currentHeight += increment;
   1.927 +            }
   1.928 +            else {
   1.929 +              aTimer.cancel();
   1.930 +              this._setUpFadeTimer();
   1.931 +            }
   1.932 +          } else if (aTimer == this._fadeTimer) {
   1.933 +            var elt = document.getElementById(this.lastSelected);
   1.934 +            var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement;
   1.935 +            if (newOpacity < 1.0)
   1.936 +              elt.style.opacity = newOpacity;
   1.937 +            else {
   1.938 +              aTimer.cancel();
   1.939 +              elt.style.opacity = 1.0;
   1.940 +            }
   1.941 +          }
   1.942 +        ]]>
   1.943 +        </body>
   1.944 +      </method>
   1.945 +      
   1.946 +      <method name="_setUpAnimationTimer">
   1.947 +        <parameter name="aStartHeight"/>
   1.948 +        <body>
   1.949 +        <![CDATA[
   1.950 +          if (!this._animateTimer) 
   1.951 +            this._animateTimer = Components.classes["@mozilla.org/timer;1"]
   1.952 +                                           .createInstance(Components.interfaces.nsITimer);
   1.953 +          else
   1.954 +            this._animateTimer.cancel();
   1.955 +          this._currentHeight = aStartHeight;
   1.956 +          
   1.957 +          this._animateTimer.initWithCallback(this, this._animateDelay, 
   1.958 +                                              Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
   1.959 +        ]]>
   1.960 +        </body>
   1.961 +      </method>
   1.962 +      
   1.963 +      <method name="_setUpFadeTimer">
   1.964 +        <body>
   1.965 +        <![CDATA[
   1.966 +          if (!this._fadeTimer) 
   1.967 +            this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
   1.968 +                                        .createInstance(Components.interfaces.nsITimer);
   1.969 +          else
   1.970 +            this._fadeTimer.cancel();
   1.971 +          
   1.972 +          this._fadeTimer.initWithCallback(this, this._fadeDelay, 
   1.973 +                                           Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
   1.974 +        ]]>
   1.975 +        </body>
   1.976 +      </method>
   1.977 +      
   1.978 +      <field name="_animateTimer">null</field>
   1.979 +      <field name="_fadeTimer">null</field>
   1.980 +      <field name="_animateDelay">15</field>
   1.981 +      <field name="_animateIncrement">40</field>
   1.982 +      <field name="_fadeDelay">5</field>
   1.983 +      <field name="_fadeIncrement">0.40</field>
   1.984 +      <field name="_animateRemainder">0</field>
   1.985 +      <field name="_currentHeight">0</field>
   1.986 +      <field name="_multiplier">0</field>
   1.987 +
   1.988 +      <method name="addPane">
   1.989 +        <parameter name="aPaneElement"/>
   1.990 +        <body>
   1.991 +        <![CDATA[
   1.992 +          this.appendChild(aPaneElement);
   1.993 +          
   1.994 +          // Set up pane button
   1.995 +          this._makePaneButton(aPaneElement);
   1.996 +        ]]>
   1.997 +        </body>
   1.998 +      </method>
   1.999 +      
  1.1000 +      <method name="openSubDialog">
  1.1001 +        <parameter name="aURL"/>
  1.1002 +        <parameter name="aFeatures"/>
  1.1003 +        <parameter name="aParams"/>
  1.1004 +        <body>
  1.1005 +          return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
  1.1006 +        </body>
  1.1007 +      </method>
  1.1008 +      
  1.1009 +      <method name="openWindow">
  1.1010 +        <parameter name="aWindowType"/>
  1.1011 +        <parameter name="aURL"/>
  1.1012 +        <parameter name="aFeatures"/>
  1.1013 +        <parameter name="aParams"/>
  1.1014 +        <body>
  1.1015 +        <![CDATA[
  1.1016 +          var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  1.1017 +                             .getService(Components.interfaces.nsIWindowMediator);
  1.1018 +          var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
  1.1019 +          if (win) {
  1.1020 +            if ("initWithParams" in win)
  1.1021 +              win.initWithParams(aParams);
  1.1022 +            win.focus();
  1.1023 +          }
  1.1024 +          else {
  1.1025 +            var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
  1.1026 +            var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
  1.1027 +            win = parentWindow.openDialog(aURL, "_blank", features, aParams);
  1.1028 +          }
  1.1029 +          return win;
  1.1030 +        ]]>
  1.1031 +        </body>
  1.1032 +      </method>
  1.1033 +    </implementation>
  1.1034 +    <handlers>
  1.1035 +      <handler event="dialogaccept">
  1.1036 +      <![CDATA[
  1.1037 +        if (!this._fireEvent("beforeaccept", this)){
  1.1038 +          return false;
  1.1039 +        }
  1.1040 +
  1.1041 +        if (this.type == "child" && window.opener) {
  1.1042 +          var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1.1043 +                               .getService(Components.interfaces.nsIPrefBranch);
  1.1044 +          var instantApply = psvc.getBoolPref("browser.preferences.instantApply");
  1.1045 +          if (instantApply) {
  1.1046 +            var panes = this.preferencePanes;
  1.1047 +            for (var i = 0; i < panes.length; ++i)
  1.1048 +              panes[i].writePreferences(true);
  1.1049 +          }
  1.1050 +          else {
  1.1051 +            // Clone all the preferences elements from the child document and
  1.1052 +            // insert them into the pane collection of the parent. 
  1.1053 +            var pdoc = window.opener.document;
  1.1054 +            if (pdoc.documentElement.localName == "prefwindow") {
  1.1055 +              var currentPane = pdoc.documentElement.currentPane;
  1.1056 +              var id = window.location.href + "#childprefs";
  1.1057 +              var childPrefs = pdoc.getElementById(id);
  1.1058 +              if (!childPrefs) {
  1.1059 +                var childPrefs = pdoc.createElement("preferences");
  1.1060 +                currentPane.appendChild(childPrefs);
  1.1061 +                childPrefs.id = id;
  1.1062 +              }
  1.1063 +              var panes = this.preferencePanes;
  1.1064 +              for (var i = 0; i < panes.length; ++i) {
  1.1065 +                var preferences = panes[i].preferences;
  1.1066 +                for (var j = 0; j < preferences.length; ++j) {
  1.1067 +                  // Try to find a preference element for the same preference.
  1.1068 +                  var preference = null;
  1.1069 +                  var parentPreferences = pdoc.getElementsByTagName("preferences");
  1.1070 +                  for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
  1.1071 +                    var parentPrefs = parentPreferences[k]
  1.1072 +                                         .getElementsByAttribute("name", preferences[j].name);
  1.1073 +                    for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
  1.1074 +                      if (parentPrefs[l].localName == "preference")
  1.1075 +                        preference = parentPrefs[l];
  1.1076 +                    }
  1.1077 +                  }
  1.1078 +                  if (!preference) {
  1.1079 +                    // No matching preference in the parent window.
  1.1080 +                    preference = pdoc.createElement("preference");
  1.1081 +                    childPrefs.appendChild(preference);
  1.1082 +                    preference.name     = preferences[j].name;
  1.1083 +                    preference.type     = preferences[j].type;
  1.1084 +                    preference.inverted = preferences[j].inverted;
  1.1085 +                    preference.readonly = preferences[j].readonly;
  1.1086 +                    preference.disabled = preferences[j].disabled;
  1.1087 +                  }
  1.1088 +                  preference.value = preferences[j].value;
  1.1089 +                }
  1.1090 +              }
  1.1091 +            }
  1.1092 +          }
  1.1093 +        }
  1.1094 +        else {
  1.1095 +          var panes = this.preferencePanes;
  1.1096 +          for (var i = 0; i < panes.length; ++i)
  1.1097 +            panes[i].writePreferences(false);
  1.1098 +
  1.1099 +          var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1.1100 +                               .getService(Components.interfaces.nsIPrefService);
  1.1101 +          psvc.savePrefFile(null);
  1.1102 +        }
  1.1103 +
  1.1104 +        return true;
  1.1105 +      ]]>
  1.1106 +      </handler>
  1.1107 +      <handler event="command">
  1.1108 +        if (event.originalTarget.hasAttribute("pane")) {
  1.1109 +          var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
  1.1110 +          this.showPane(pane);
  1.1111 +        }
  1.1112 +      </handler>
  1.1113 +
  1.1114 +      <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
  1.1115 +      <![CDATA[
  1.1116 +        if (this.instantApply)
  1.1117 +          window.close();
  1.1118 +        event.stopPropagation();
  1.1119 +        event.preventDefault();
  1.1120 +      ]]>
  1.1121 +      </handler>
  1.1122 +
  1.1123 +      <handler event="keypress"
  1.1124 +#ifdef XP_MACOSX
  1.1125 +               key="&openHelpMac.commandkey;" modifiers="accel"
  1.1126 +#else
  1.1127 +               keycode="&openHelp.commandkey;"
  1.1128 +#endif
  1.1129 +               phase="capturing">
  1.1130 +      <![CDATA[
  1.1131 +        var helpButton = this.getButton("help");
  1.1132 +        if (helpButton.disabled || helpButton.hidden)
  1.1133 +          return;
  1.1134 +        this._fireEvent("dialoghelp", this);
  1.1135 +        event.stopPropagation();
  1.1136 +        event.preventDefault();
  1.1137 +      ]]>
  1.1138 +      </handler>
  1.1139 +    </handlers>
  1.1140 +  </binding>
  1.1141 +  
  1.1142 +  <binding id="prefpane">
  1.1143 +    <resources>
  1.1144 +      <stylesheet src="chrome://global/skin/preferences.css"/>
  1.1145 +    </resources>
  1.1146 +    <content>
  1.1147 +      <xul:vbox class="content-box" xbl:inherits="flex">
  1.1148 +        <children/>
  1.1149 +      </xul:vbox>
  1.1150 +    </content>
  1.1151 +    <implementation>
  1.1152 +      <method name="writePreferences">
  1.1153 +        <parameter name="aFlushToDisk"/>
  1.1154 +        <body>
  1.1155 +        <![CDATA[
  1.1156 +          // Write all values to preferences.
  1.1157 +          var preferences = this.preferences;
  1.1158 +          for (var i = 0; i < preferences.length; ++i) {
  1.1159 +            var preference = preferences[i];
  1.1160 +            preference.batching = true;
  1.1161 +            preference.valueFromPreferences = preference.value;
  1.1162 +            preference.batching = false;
  1.1163 +          }
  1.1164 +          if (aFlushToDisk) {
  1.1165 +            var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1.1166 +                                 .getService(Components.interfaces.nsIPrefService);
  1.1167 +            psvc.savePrefFile(null);
  1.1168 +          }
  1.1169 +        ]]>
  1.1170 +        </body>
  1.1171 +      </method>
  1.1172 +      
  1.1173 +      <property name="src" 
  1.1174 +                onget="return this.getAttribute('src');"
  1.1175 +                onset="this.setAttribute('src', val); return val;"/>
  1.1176 +      <property name="selected" 
  1.1177 +                onget="return this.getAttribute('selected') == 'true';"
  1.1178 +                onset="this.setAttribute('selected', val); return val;"/>
  1.1179 +      <property name="image" 
  1.1180 +                onget="return this.getAttribute('image');"
  1.1181 +                onset="this.setAttribute('image', val); return val;"/>
  1.1182 +      <property name="label" 
  1.1183 +                onget="return this.getAttribute('label');"
  1.1184 +                onset="this.setAttribute('label', val); return val;"/>
  1.1185 +      
  1.1186 +      <property name="preferenceElements"
  1.1187 +                onget="return this.getElementsByAttribute('preference', '*');"/>
  1.1188 +      <property name="preferences"
  1.1189 +                onget="return this.getElementsByTagName('preference');"/>
  1.1190 +
  1.1191 +      <property name="helpTopic">
  1.1192 +        <getter>
  1.1193 +        <![CDATA[
  1.1194 +          // if there are tabs, and the selected tab provides a helpTopic, return that
  1.1195 +          var box = this.getElementsByTagName("tabbox");
  1.1196 +          if (box[0]) {
  1.1197 +            var tab = box[0].selectedTab;
  1.1198 +            if (tab && tab.hasAttribute("helpTopic"))
  1.1199 +              return tab.getAttribute("helpTopic");
  1.1200 +          }
  1.1201 +
  1.1202 +          // otherwise, return the helpTopic of the current panel
  1.1203 +          return this.getAttribute("helpTopic");
  1.1204 +        ]]>
  1.1205 +        </getter>
  1.1206 +      </property>
  1.1207 +
  1.1208 +      <field name="_loaded">false</field>
  1.1209 +      <property name="loaded" 
  1.1210 +                onget="return !this.src ? true : this._loaded;"
  1.1211 +                onset="this._loaded = val; return val;"/>
  1.1212 +      
  1.1213 +      <method name="preferenceForElement">
  1.1214 +        <parameter name="aElement"/>
  1.1215 +        <body>
  1.1216 +          return document.getElementById(aElement.getAttribute("preference"));
  1.1217 +        </body>
  1.1218 +      </method>
  1.1219 +      
  1.1220 +      <method name="getPreferenceElement">
  1.1221 +        <parameter name="aStartElement"/>
  1.1222 +        <body>
  1.1223 +        <![CDATA[
  1.1224 +          var temp = aStartElement;
  1.1225 +          while (temp && temp.nodeType == Node.ELEMENT_NODE && 
  1.1226 +                 !temp.hasAttribute("preference"))
  1.1227 +            temp = temp.parentNode;
  1.1228 +          return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement;
  1.1229 +        ]]>
  1.1230 +        </body>
  1.1231 +      </method>
  1.1232 +      
  1.1233 +      <method name="userChangedValue">
  1.1234 +        <parameter name="aElement"/>
  1.1235 +        <body>
  1.1236 +        <![CDATA[
  1.1237 +          var element = this.getPreferenceElement(aElement);
  1.1238 +          if (element.hasAttribute("preference")) {
  1.1239 +            var preference = document.getElementById(element.getAttribute("preference"));
  1.1240 +            var prefVal = preference.getElementValue(element);
  1.1241 +            preference.value = prefVal;
  1.1242 +          }
  1.1243 +        ]]>
  1.1244 +        </body>
  1.1245 +      </method>
  1.1246 +      
  1.1247 +      <property name="contentHeight">
  1.1248 +        <getter>
  1.1249 +          var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
  1.1250 +          targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
  1.1251 +          targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
  1.1252 +          return targetHeight;
  1.1253 +        </getter>
  1.1254 +      </property>
  1.1255 +      <field name="_content">
  1.1256 +        document.getAnonymousElementByAttribute(this, "class", "content-box");
  1.1257 +      </field>
  1.1258 +    </implementation>
  1.1259 +    <handlers>
  1.1260 +      <handler event="command">
  1.1261 +        // This "command" event handler tracks changes made to preferences by 
  1.1262 +        // the user in this window.
  1.1263 +        if (event.sourceEvent)
  1.1264 +          event = event.sourceEvent;
  1.1265 +        this.userChangedValue(event.target);
  1.1266 +      </handler>
  1.1267 +      <handler event="select">
  1.1268 +        // This "select" event handler tracks changes made to colorpicker 
  1.1269 +        // preferences by the user in this window.
  1.1270 +        if (event.target.localName == "colorpicker") 
  1.1271 +          this.userChangedValue(event.target);
  1.1272 +      </handler>
  1.1273 +      <handler event="change">
  1.1274 +        // This "change" event handler tracks changes made to preferences by 
  1.1275 +        // the user in this window. 
  1.1276 +        this.userChangedValue(event.target);
  1.1277 +      </handler>
  1.1278 +      <handler event="input">
  1.1279 +        // This "input" event handler tracks changes made to preferences by 
  1.1280 +        // the user in this window.
  1.1281 +        this.userChangedValue(event.target);
  1.1282 +      </handler>
  1.1283 +      <handler event="paneload">
  1.1284 +      <![CDATA[
  1.1285 +        // Initialize all values from preferences.
  1.1286 +        var elements = this.preferenceElements;
  1.1287 +        for (var i = 0; i < elements.length; ++i) {
  1.1288 +          try {
  1.1289 +            var preference = this.preferenceForElement(elements[i]);
  1.1290 +            preference.setElementValue(elements[i]);
  1.1291 +          }
  1.1292 +          catch (e) {
  1.1293 +            dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
  1.1294 +          }
  1.1295 +        }
  1.1296 +      ]]>      
  1.1297 +      </handler>
  1.1298 +    </handlers>
  1.1299 +  </binding>
  1.1300 +          
  1.1301 +  <binding id="panebutton" role="xul:listitem"
  1.1302 +           extends="chrome://global/content/bindings/radio.xml#radio">
  1.1303 +    <resources>
  1.1304 +      <stylesheet src="chrome://global/skin/preferences.css"/>
  1.1305 +    </resources>
  1.1306 +    <content>
  1.1307 +      <xul:image class="paneButtonIcon" xbl:inherits="src"/>
  1.1308 +      <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
  1.1309 +    </content>
  1.1310 +  </binding>
  1.1311 +
  1.1312 +</bindings>
  1.1313 +
  1.1314 +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  1.1315 +# This Source Code Form is subject to the terms of the Mozilla Public
  1.1316 +# License, v. 2.0. If a copy of the MPL was not distributed with this
  1.1317 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
  1.1318 +
  1.1319 +#
  1.1320 +# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
  1.1321 +#
  1.1322 +#    Historical References:
  1.1323 +#    PrefWindow V   (February 1, 2003)
  1.1324 +#    PrefWindow IV  (April 24, 2000)
  1.1325 +#    PrefWindow III (January 6, 2000)
  1.1326 +#    PrefWindow II  (???)
  1.1327 +#    PrefWindow I   (June 4, 1999)
  1.1328 +#

mercurial