toolkit/content/widgets/preferences.xml

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 <?xml version="1.0"?>
     3 <!DOCTYPE bindings [
     4   <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
     5   %preferencesDTD;
     6   <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
     7   %globalKeysDTD;
     8 ]>
    10 <bindings id="preferencesBindings"
    11           xmlns="http://www.mozilla.org/xbl"
    12           xmlns:xbl="http://www.mozilla.org/xbl"
    13           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    15 #
    16 # = Preferences Window Framework
    17 #
    18 #   The syntax for use looks something like:
    19 #
    20 #   <prefwindow>
    21 #     <prefpane id="prefPaneA">
    22 #       <preferences>
    23 #         <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
    24 #         <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
    25 #       </preferences>
    26 #       <checkbox label="Preference" preference="preference1"/>
    27 #     </prefpane>
    28 #   </prefwindow>
    29 #
    31   <binding id="preferences">
    32     <implementation implements="nsIObserver">
    33       <method name="observe">
    34         <parameter name="aSubject"/>
    35         <parameter name="aTopic"/>
    36         <parameter name="aData"/>
    37         <body>
    38         <![CDATA[
    39           for (var i = 0; i < this.childNodes.length; ++i) {
    40             var preference = this.childNodes[i];
    41             if (preference.name == aData) {
    42               preference.value = preference.valueFromPreferences;
    43             }
    44           }
    45         ]]>
    46         </body>
    47       </method>
    49       <method name="fireChangedEvent">
    50         <parameter name="aPreference"/>
    51         <body>
    52         <![CDATA[
    53           // Value changed, synthesize an event
    54           try {
    55             var event = document.createEvent("Events");
    56             event.initEvent("change", true, true);
    57             aPreference.dispatchEvent(event);
    58           }
    59           catch (e) {
    60             Components.utils.reportError(e);
    61           }
    62         ]]>
    63         </body>
    64       </method>
    66       <field name="service">
    67         Components.classes["@mozilla.org/preferences-service;1"]
    68                   .getService(Components.interfaces.nsIPrefService);
    69       </field>
    70       <field name="rootBranch">
    71         Components.classes["@mozilla.org/preferences-service;1"]
    72                   .getService(Components.interfaces.nsIPrefBranch);
    73       </field>
    74       <field name="defaultBranch">
    75         this.service.getDefaultBranch("");
    76       </field>
    77       <field name="rootBranchInternal">
    78         Components.classes["@mozilla.org/preferences-service;1"]
    79                   .getService(Components.interfaces.nsIPrefBranchInternal);
    80       </field>
    81       <property name="type" readonly="true">
    82         <getter>
    83           <![CDATA[
    84             return document.documentElement.type || "";
    85           ]]>
    86         </getter>
    87       </property>
    88       <property name="instantApply" readonly="true">
    89         <getter>
    90           <![CDATA[
    91             var doc = document.documentElement;
    92             return this.type == "child" ? doc.instantApply
    93                                         : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
    94           ]]>
    95         </getter>
    96       </property>
    97     </implementation>
    98   </binding>
   100   <binding id="preference">
   101     <implementation>
   102       <constructor>
   103       <![CDATA[
   104         // if the element has been inserted without the name attribute set,
   105         // we have nothing to do here
   106         if (!this.name)
   107           return;
   109         this.preferences.rootBranchInternal
   110             .addObserver(this.name, this.preferences, false);
   111         // In non-instant apply mode, we must try and use the last saved state
   112         // from any previous opens of a child dialog instead of the value from
   113         // preferences, to pick up any edits a user may have made. 
   114         if (this.preferences.type == "child" && 
   115             !this.instantApply && window.opener) {
   116           var pdoc = window.opener.document;
   118           // Try to find a preference element for the same preference.
   119           var preference = null;
   120           var parentPreferences = pdoc.getElementsByTagName("preferences");
   121           for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
   122             var parentPrefs = parentPreferences[k]
   123                                     .getElementsByAttribute("name", this.name);
   124             for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
   125               if (parentPrefs[l].localName == "preference")
   126                 preference = parentPrefs[l];
   127             }
   128           }
   129           this._setValue(preference ? preference.value 
   130                                     : this.valueFromPreferences, false);
   131         }
   132         else
   133           this._setValue(this.valueFromPreferences, false);
   134       ]]>
   135       </constructor>
   136       <destructor>
   137         this.preferences.rootBranchInternal
   138             .removeObserver(this.name, this.preferences);
   139       </destructor>
   141       <property name="instantApply">
   142         <getter>
   143           return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
   144         </getter>
   145       </property>
   147       <property name="preferences" onget="return this.parentNode"/>
   148       <property name="name" onget="return this.getAttribute('name');">
   149         <setter>
   150           if (val == this.name)
   151             return val;
   153           this.preferences.rootBranchInternal
   154               .removeObserver(this.name, this.preferences);
   155           this.setAttribute('name', val);
   156           this.preferences.rootBranchInternal
   157               .addObserver(val, this.preferences, false);
   159           return val;
   160         </setter>
   161       </property>
   162       <property name="type" onget="return this.getAttribute('type');"
   163                             onset="this.setAttribute('type', val); return val;"/>
   164       <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
   165                                 onset="this.setAttribute('inverted', val); return val;"/>
   166       <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
   167                                 onset="this.setAttribute('readonly', val); return val;"/>
   169       <field name="_value">null</field>
   170       <method name="_setValue">
   171         <parameter name="aValue"/>
   172         <parameter name="aUpdate"/>
   173         <body>
   174         <![CDATA[
   175           if (aUpdate && this.value !== aValue) {
   176             this._value = aValue;
   177             if (this.instantApply)
   178               this.valueFromPreferences = aValue;
   179             this.preferences.fireChangedEvent(this);
   180           }
   181           else if (!aUpdate) {
   182             this._value = aValue;
   183             this.updateElements();
   184           }
   185           return aValue;
   186         ]]>
   187         </body>
   188       </method>
   189       <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/>
   191       <property name="locked">
   192         <getter>
   193           return this.preferences.rootBranch.prefIsLocked(this.name);
   194         </getter>
   195       </property>
   197       <property name="disabled">
   198         <getter>
   199           return this.getAttribute("disabled") == "true";
   200         </getter>
   201         <setter>
   202         <![CDATA[
   203           if (val) 
   204             this.setAttribute("disabled", "true");
   205           else
   206             this.removeAttribute("disabled");
   208           if (!this.id)
   209             return val;
   211           var elements = document.getElementsByAttribute("preference", this.id);
   212           for (var i = 0; i < elements.length; ++i) {
   213             elements[i].disabled = val;
   215             var labels = document.getElementsByAttribute("control", elements[i].id);
   216             for (var j = 0; j < labels.length; ++j)
   217               labels[j].disabled = val;
   218           }
   220           return val;
   221         ]]>
   222         </setter>
   223       </property>
   225       <property name="tabIndex">
   226         <getter>
   227           return parseInt(this.getAttribute("tabindex"));
   228         </getter>
   229         <setter>
   230         <![CDATA[
   231           if (val) 
   232             this.setAttribute("tabindex", val);
   233           else
   234             this.removeAttribute("tabindex");
   236           if (!this.id)
   237             return val;
   239           var elements = document.getElementsByAttribute("preference", this.id);
   240           for (var i = 0; i < elements.length; ++i) {
   241             elements[i].tabIndex = val;
   243             var labels = document.getElementsByAttribute("control", elements[i].id);
   244             for (var j = 0; j < labels.length; ++j)
   245               labels[j].tabIndex = val;
   246           }
   248           return val;
   249         ]]>
   250         </setter>
   251       </property>
   253       <property name="hasUserValue">
   254         <getter>
   255         <![CDATA[
   256           return this.preferences.rootBranch.prefHasUserValue(this.name) &&
   257                  this.value !== undefined;
   258         ]]>
   259         </getter>
   260       </property>
   262       <method name="reset">
   263         <body>
   264           // defer reset until preference update
   265           this.value = undefined;
   266         </body>
   267       </method>
   269       <field name="_useDefault">false</field>      
   270       <property name="defaultValue">
   271         <getter>
   272         <![CDATA[
   273           this._useDefault = true;
   274           var val = this.valueFromPreferences;
   275           this._useDefault = false;
   276           return val;
   277         ]]>
   278         </getter>
   279       </property>
   281       <property name="_branch">
   282         <getter>
   283           return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
   284         </getter>
   285       </property>
   287       <field name="batching">false</field>
   289       <method name="_reportUnknownType">
   290         <body>
   291         <![CDATA[
   292           var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
   293                                          .getService(Components.interfaces.nsIConsoleService);
   294           var msg = "<preference> with id='" + this.id + "' and name='" + 
   295                     this.name + "' has unknown type '" + this.type + "'.";
   296           consoleService.logStringMessage(msg);
   297         ]]>
   298         </body>
   299       </method>
   301       <property name="valueFromPreferences">
   302         <getter>
   303         <![CDATA[
   304           try {
   305             // Force a resync of value with preferences.
   306             switch (this.type) {
   307             case "int":
   308               return this._branch.getIntPref(this.name);
   309             case "bool":
   310               var val = this._branch.getBoolPref(this.name);
   311               return this.inverted ? !val : val;
   312             case "wstring":
   313               return this._branch
   314                          .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
   315                          .data;
   316             case "string":
   317             case "unichar":
   318               return this._branch
   319                          .getComplexValue(this.name, Components.interfaces.nsISupportsString)
   320                          .data;
   321             case "fontname":
   322               var family = this._branch
   323                                .getComplexValue(this.name, Components.interfaces.nsISupportsString)
   324                                .data;
   325               var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
   326                                              .createInstance(Components.interfaces.nsIFontEnumerator);
   327               return fontEnumerator.getStandardFamilyName(family);
   328             case "file":
   329               var f = this._branch
   330                           .getComplexValue(this.name, Components.interfaces.nsILocalFile);
   331               return f;
   332             default:
   333               this._reportUnknownType();
   334             }
   335           }
   336           catch (e) { }
   337           return null;
   338         ]]>
   339         </getter>
   340         <setter>
   341         <![CDATA[
   342           // Exit early if nothing to do.
   343           if (this.readonly || this.valueFromPreferences == val)
   344             return val;
   346           // The special value undefined means 'reset preference to default'.
   347           if (val === undefined) {
   348             this.preferences.rootBranch.clearUserPref(this.name);
   349             return val;
   350           }
   352           // Force a resync of preferences with value.
   353           switch (this.type) {
   354           case "int":
   355             this.preferences.rootBranch.setIntPref(this.name, val);
   356             break;
   357           case "bool":
   358             this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
   359             break;
   360           case "wstring":
   361             var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
   362                                 .createInstance(Components.interfaces.nsIPrefLocalizedString);
   363             pls.data = val;
   364             this.preferences.rootBranch
   365                 .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
   366             break;
   367           case "string":
   368           case "unichar":
   369           case "fontname":
   370             var iss = Components.classes["@mozilla.org/supports-string;1"]
   371                                 .createInstance(Components.interfaces.nsISupportsString);
   372             iss.data = val;
   373             this.preferences.rootBranch
   374                 .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss);
   375             break;
   376           case "file":
   377             var lf;
   378             if (typeof(val) == "string") {
   379               lf = Components.classes["@mozilla.org/file/local;1"]
   380                              .createInstance(Components.interfaces.nsILocalFile);
   381               lf.persistentDescriptor = val;
   382               if (!lf.exists())
   383                 lf.initWithPath(val);
   384             }
   385             else 
   386               lf = val.QueryInterface(Components.interfaces.nsILocalFile);
   387             this.preferences.rootBranch
   388                 .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
   389             break;
   390           default:
   391             this._reportUnknownType();
   392           }
   393           if (!this.batching)
   394             this.preferences.service.savePrefFile(null);
   395           return val;
   396         ]]>
   397         </setter>
   398       </property>
   400       <method name="setElementValue">
   401         <parameter name="aElement"/>
   402         <body>
   403         <![CDATA[
   404           if (this.locked)
   405             aElement.disabled = true;
   407           if (!this.isElementEditable(aElement))
   408             return;
   410           var rv = undefined;
   411           if (aElement.hasAttribute("onsyncfrompreference")) {
   412             // Value changed, synthesize an event
   413             try {
   414               var event = document.createEvent("Events");
   415               event.initEvent("syncfrompreference", true, true);
   416               var f = new Function ("event", 
   417                                     aElement.getAttribute("onsyncfrompreference"));
   418               rv = f.call(aElement, event);
   419             }
   420             catch (e) {
   421               Components.utils.reportError(e);
   422             }
   423           }
   424           var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value);
   425           // if the preference is marked for reset, show default value in UI
   426           if (val === undefined)
   427             val = this.defaultValue;
   429           /**
   430            * Initialize a UI element property with a value. Handles the case 
   431            * where an element has not yet had a XBL binding attached for it and
   432            * the property setter does not yet exist by setting the same attribute
   433            * on the XUL element using DOM apis and assuming the element's 
   434            * constructor or property getters appropriately handle this state. 
   435            */
   436           function setValue(element, attribute, value) {
   437             if (attribute in element) 
   438               element[attribute] = value;
   439             else
   440               element.setAttribute(attribute, value);
   441           }
   442           if (aElement.localName == "checkbox" ||
   443               aElement.localName == "listitem")
   444             setValue(aElement, "checked", val);
   445           else if (aElement.localName == "colorpicker")
   446             setValue(aElement, "color", val);
   447           else if (aElement.localName == "textbox") {
   448             // XXXmano Bug 303998: Avoid a caret placement issue if either the
   449             // preference observer or its setter calls updateElements as a result
   450             // of the input event handler.
   451             if (aElement.value !== val)
   452               setValue(aElement, "value", val);
   453           }
   454           else
   455             setValue(aElement, "value", val);
   456         ]]>
   457         </body>
   458       </method>
   460       <method name="getElementValue">
   461         <parameter name="aElement"/>
   462         <body>
   463         <![CDATA[
   464           if (aElement.hasAttribute("onsynctopreference")) {
   465             // Value changed, synthesize an event
   466             try {
   467               var event = document.createEvent("Events");
   468               event.initEvent("synctopreference", true, true);
   469               var f = new Function ("event", 
   470                                     aElement.getAttribute("onsynctopreference"));
   471               var rv = f.call(aElement, event);
   472               if (rv !== undefined) 
   473                 return rv;
   474             }
   475             catch (e) {
   476               Components.utils.reportError(e);
   477             }
   478           }
   480           /**
   481            * Read the value of an attribute from an element, assuming the 
   482            * attribute is a property on the element's node API. If the property
   483            * is not present in the API, then assume its value is contained in
   484            * an attribute, as is the case before a binding has been attached.
   485            */
   486           function getValue(element, attribute) {
   487             if (attribute in element)
   488               return element[attribute];
   489             return element.getAttribute(attribute);
   490           }
   491           if (aElement.localName == "checkbox" ||
   492               aElement.localName == "listitem")
   493             var value = getValue(aElement, "checked");
   494           else if (aElement.localName == "colorpicker")
   495             value = getValue(aElement, "color");
   496           else
   497             value = getValue(aElement, "value");
   499           switch (this.type) {
   500           case "int":
   501             return parseInt(value, 10) || 0;
   502           case "bool":
   503             return typeof(value) == "boolean" ? value : value == "true";
   504           }
   505           return value;
   506         ]]>
   507         </body>
   508       </method>
   510       <method name="isElementEditable">
   511         <parameter name="aElement"/>
   512         <body>
   513         <![CDATA[
   514           switch (aElement.localName) {
   515           case "checkbox":
   516           case "colorpicker":
   517           case "radiogroup":
   518           case "textbox":
   519           case "listitem":
   520           case "listbox":
   521           case "menulist":
   522             return true;
   523           }
   524           return aElement.getAttribute("preference-editable") == "true";
   525         ]]> 
   526         </body>
   527       </method>
   529       <method name="updateElements">
   530         <body>
   531         <![CDATA[
   532           if (!this.id)
   533             return;
   535           // This "change" event handler tracks changes made to preferences by 
   536           // sources other than the user in this window. 
   537           var elements = document.getElementsByAttribute("preference", this.id);
   538           for (var i = 0; i < elements.length; ++i) 
   539             this.setElementValue(elements[i]);
   540         ]]>
   541         </body>
   542       </method>
   543     </implementation>
   545     <handlers>
   546       <handler event="change">
   547         this.updateElements();
   548       </handler>
   549     </handlers>
   550   </binding>
   552   <binding id="prefwindow"
   553            extends="chrome://global/content/bindings/dialog.xml#dialog">
   554     <resources>
   555       <stylesheet src="chrome://global/skin/preferences.css"/>
   556     </resources>
   557     <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
   558              closebuttonlabel="&preferencesCloseButton.label;"
   559              closebuttonaccesskey="&preferencesCloseButton.accesskey;"
   560              role="dialog"
   561 #ifdef XP_WIN
   562              title="&preferencesDefaultTitleWin.title;">
   563 #else
   564              title="&preferencesDefaultTitleMac.title;">
   565 #endif
   566       <xul:windowdragbox orient="vertical">
   567         <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
   568                         role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
   569       </xul:windowdragbox>
   570       <xul:hbox flex="1" class="paneDeckContainer">
   571         <xul:deck anonid="paneDeck" flex="1">
   572           <children includes="prefpane"/>
   573         </xul:deck>
   574       </xul:hbox>
   575       <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end">
   576 #ifdef XP_UNIX
   577         <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
   578         <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
   579         <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
   580         <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
   581         <xul:spacer anonid="spacer" flex="1"/>
   582         <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
   583         <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
   584 #else
   585         <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
   586         <xul:spacer anonid="spacer" flex="1"/>
   587         <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
   588         <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
   589         <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
   590         <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
   591         <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
   592 #endif
   593       </xul:hbox>
   594       <xul:hbox>
   595         <children/>
   596       </xul:hbox>
   597     </content>
   598     <implementation implements="nsITimerCallback">
   599       <constructor>
   600       <![CDATA[
   601         if (this.type != "child") {
   602           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
   603                                .getService(Components.interfaces.nsIPrefBranch);
   604           this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
   605           if (this.instantApply) {
   606             var docElt = document.documentElement;
   607             var acceptButton = docElt.getButton("accept");
   608             acceptButton.hidden = true;
   609             var cancelButton  = docElt.getButton("cancel");
   610 #ifdef XP_MACOSX
   611             // no buttons on Mac except Help
   612             cancelButton.hidden = true;
   613             // Move Help button to the end
   614             document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true;         
   615             // Also, don't fire onDialogAccept on enter
   616             acceptButton.disabled = true;
   617 #else
   618             // morph the Cancel button into the Close button
   619             cancelButton.setAttribute ("icon", "close");
   620             cancelButton.label = docElt.getAttribute("closebuttonlabel");
   621             cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
   622 #endif
   623           }
   624         }
   625         this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
   626         var panes = this.preferencePanes;
   628         var lastPane = null;
   629         if (this.lastSelected) {
   630           lastPane = document.getElementById(this.lastSelected);
   631           if (!lastPane) {
   632             this.lastSelected = "";
   633           }
   634         }
   636         var paneToLoad;
   637         if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
   638           paneToLoad = document.getElementById(window.arguments[0]);
   639           this.lastSelected = paneToLoad.id;
   640         }
   641         else if (lastPane)
   642           paneToLoad = lastPane;
   643         else
   644           paneToLoad = panes[0];
   646         for (var i = 0; i < panes.length; ++i) {
   647           this._makePaneButton(panes[i]);
   648           if (panes[i].loaded) {
   649             // Inline pane content, fire load event to force initialization.
   650             this._fireEvent("paneload", panes[i]);
   651           }
   652         }
   653         this.showPane(paneToLoad);
   655         if (panes.length == 1)
   656           this._selector.setAttribute("collapsed", "true");
   657       ]]>
   658       </constructor>
   660       <destructor>
   661       <![CDATA[
   662         // Release timers to avoid reference cycles.
   663         if (this._animateTimer) {
   664           this._animateTimer.cancel();
   665           this._animateTimer = null;
   666         }
   667         if (this._fadeTimer) {
   668           this._fadeTimer.cancel();
   669           this._fadeTimer = null;
   670         }
   671       ]]>
   672       </destructor>
   674       <field name="instantApply">false</field>
   676       <property name="preferencePanes"
   677                 onget="return this.getElementsByTagName('prefpane');"/>
   679       <property name="type" onget="return this.getAttribute('type');"/>
   680       <property name="_paneDeck"
   681                 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
   682       <property name="_paneDeckContainer"
   683                 onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
   684       <property name="_selector"
   685                 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
   686       <property name="lastSelected" 
   687                 onget="return this.getAttribute('lastSelected');">
   688         <setter>
   689           this.setAttribute("lastSelected", val); 
   690           document.persist(this.id, "lastSelected");
   691           return val;
   692         </setter>          
   693       </property>
   694       <property name="currentPane"
   695                 onset="return this._currentPane = val;">
   696         <getter>
   697           if (!this._currentPane)
   698             this._currentPane = this.preferencePanes[0];
   700           return this._currentPane;
   701         </getter> 
   702       </property>
   703       <field name="_currentPane">null</field>
   706       <method name="_makePaneButton">
   707         <parameter name="aPaneElement"/>
   708         <body>
   709         <![CDATA[
   710           var radio = document.createElement("radio");
   711           radio.setAttribute("pane", aPaneElement.id);
   712           radio.setAttribute("label", aPaneElement.label);
   713           // Expose preference group choice to accessibility APIs as an unchecked list item
   714           // The parent group is exposed to accessibility APIs as a list
   715           if (aPaneElement.image)
   716             radio.setAttribute("src", aPaneElement.image);
   717           radio.style.listStyleImage = aPaneElement.style.listStyleImage;
   718           this._selector.appendChild(radio);
   719           return radio;
   720         ]]>
   721         </body>
   722       </method>
   724       <method name="showPane">
   725         <parameter name="aPaneElement"/>
   726         <body>
   727         <![CDATA[
   728           if (!aPaneElement)
   729             return;
   731           this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
   732           if (!aPaneElement.loaded) {
   733             let OverlayLoadObserver = function(aPane)
   734             {
   735               this._pane = aPane;
   736             }
   737             OverlayLoadObserver.prototype = { 
   738               _outer: this,
   739               observe: function (aSubject, aTopic, aData) 
   740               {
   741                 this._pane.loaded = true;
   742                 this._outer._fireEvent("paneload", this._pane);
   743                 this._outer._selectPane(this._pane);
   744               }
   745             };
   747             var obs = new OverlayLoadObserver(aPaneElement);
   748             document.loadOverlay(aPaneElement.src, obs);
   749           }
   750           else
   751             this._selectPane(aPaneElement);
   752         ]]>
   753         </body>
   754       </method>
   756       <method name="_fireEvent">
   757         <parameter name="aEventName"/>
   758         <parameter name="aTarget"/>
   759         <body>
   760         <![CDATA[
   761           // Panel loaded, synthesize a load event. 
   762           try {
   763             var event = document.createEvent("Events");
   764             event.initEvent(aEventName, true, true);
   765             var cancel = !aTarget.dispatchEvent(event);
   766             if (aTarget.hasAttribute("on" + aEventName)) {
   767               var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
   768               var rv = fn.call(aTarget, event);
   769               if (rv == false)
   770                 cancel = true;
   771             }
   772             return !cancel;  
   773           }
   774           catch (e) { 
   775             Components.utils.reportError(e);
   776           }
   777           return false;
   778         ]]>
   779         </body>
   780       </method>
   782       <field name="_initialized">false</field>
   783       <method name="_selectPane">
   784         <parameter name="aPaneElement"/>
   785         <body>
   786         <![CDATA[
   787 #ifdef XP_MACOSX
   788           var paneTitle = aPaneElement.label;
   789           if (paneTitle != "")
   790             document.title = paneTitle;
   791 #endif
   792           var helpButton = document.documentElement.getButton("help");
   793           if (aPaneElement.helpTopic)
   794             helpButton.hidden = false;
   795           else
   796             helpButton.hidden = true;
   798           // Find this pane's index in the deck and set the deck's 
   799           // selectedIndex to that value to switch to it.
   800           var prefpanes = this.preferencePanes;
   801           for (var i = 0; i < prefpanes.length; ++i) {
   802             if (prefpanes[i] == aPaneElement) {
   803               this._paneDeck.selectedIndex = i;
   805               if (this.type != "child") {
   806                 if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
   807                     prefpanes.length > 1)
   808                   aPaneElement.removeAttribute("flex");
   809                 // Calling sizeToContent after the first prefpane is loaded
   810                 // will size the windows contents so style information is
   811                 // available to calculate correct sizing.
   812                 if (!this._initialized && prefpanes.length > 1) {
   813                   if (this._shouldAnimate)
   814                     this.style.minHeight = 0;
   815                   window.sizeToContent();
   816                 }
   818                 var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
   819                 oldPane.selected = !(aPaneElement.selected = true);
   820                 this.lastSelected = aPaneElement.id;
   821                 this.currentPane = aPaneElement;
   822                 this._initialized = true;
   824                 // Only animate if we've switched between prefpanes
   825                 if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
   826                   aPaneElement.style.opacity = 0.0;
   827                   this.animate(oldPane, aPaneElement);
   828                 }
   829                 else if (!this._shouldAnimate && prefpanes.length > 1) {
   830                   var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height);
   831                   var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop);
   832                   verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom);
   833                   if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
   834                     // To workaround the bottom border of a groupbox from being
   835                     // cutoff an hbox with a class of bottomBox may enclose it.
   836                     // This needs to include its padding to resize properly.
   837                     // See bug 394433
   838                     var bottomPadding = 0;
   839                     var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
   840                     if (bottomBox)
   841                       bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom);
   842                     window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
   843                   }
   845                   // XXX rstrong - extend the contents of the prefpane to
   846                   // prevent elements from being cutoff (see bug 349098).
   847                   if (aPaneElement.contentHeight + verticalPadding < targetHeight)
   848                     aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
   849                 }
   850               }
   851               break;
   852             }
   853           }
   854         ]]>
   855         </body>
   856       </method>
   858       <property name="_shouldAnimate">
   859         <getter>
   860         <![CDATA[
   861           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
   862                                .getService(Components.interfaces.nsIPrefBranch);
   863 #ifdef XP_MACOSX
   864           var animate = true;
   865 #else
   866           var animate = false;
   867 #endif
   868           try {
   869             animate = psvc.getBoolPref("browser.preferences.animateFadeIn");
   870           }
   871           catch (e) { }
   872           return animate;
   873         ]]>
   874         </getter>
   875       </property>
   877       <method name="animate">
   878         <parameter name="aOldPane"/>
   879         <parameter name="aNewPane"/>
   880         <body>
   881         <![CDATA[
   882           // if we are already resizing, use currentHeight
   883           var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
   885           this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
   886           var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
   887           this._animateRemainder = sizeDelta % this._animateIncrement;
   889           this._setUpAnimationTimer(oldHeight);
   890         ]]>
   891         </body>
   892       </method>
   894       <property name="_sizeIncrement">
   895         <getter>
   896         <![CDATA[
   897           var lastSelectedPane = document.getElementById(this.lastSelected);
   898           var increment = this._animateIncrement * this._multiplier;
   899           var newHeight = this._currentHeight + increment;
   900           if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
   901               (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
   902             return 0;
   904           if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
   905               (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
   906             increment = this._animateRemainder * this._multiplier;
   907           return increment;
   908         ]]>
   909         </getter>
   910       </property>
   912       <method name="notify">
   913         <parameter name="aTimer"/>
   914         <body>
   915         <![CDATA[
   916           if (!document)
   917             aTimer.cancel();
   919           if (aTimer == this._animateTimer) {
   920             var increment = this._sizeIncrement;
   921             if (increment != 0) {
   922               window.innerHeight += increment;
   923               this._currentHeight += increment;
   924             }
   925             else {
   926               aTimer.cancel();
   927               this._setUpFadeTimer();
   928             }
   929           } else if (aTimer == this._fadeTimer) {
   930             var elt = document.getElementById(this.lastSelected);
   931             var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement;
   932             if (newOpacity < 1.0)
   933               elt.style.opacity = newOpacity;
   934             else {
   935               aTimer.cancel();
   936               elt.style.opacity = 1.0;
   937             }
   938           }
   939         ]]>
   940         </body>
   941       </method>
   943       <method name="_setUpAnimationTimer">
   944         <parameter name="aStartHeight"/>
   945         <body>
   946         <![CDATA[
   947           if (!this._animateTimer) 
   948             this._animateTimer = Components.classes["@mozilla.org/timer;1"]
   949                                            .createInstance(Components.interfaces.nsITimer);
   950           else
   951             this._animateTimer.cancel();
   952           this._currentHeight = aStartHeight;
   954           this._animateTimer.initWithCallback(this, this._animateDelay, 
   955                                               Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
   956         ]]>
   957         </body>
   958       </method>
   960       <method name="_setUpFadeTimer">
   961         <body>
   962         <![CDATA[
   963           if (!this._fadeTimer) 
   964             this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
   965                                         .createInstance(Components.interfaces.nsITimer);
   966           else
   967             this._fadeTimer.cancel();
   969           this._fadeTimer.initWithCallback(this, this._fadeDelay, 
   970                                            Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
   971         ]]>
   972         </body>
   973       </method>
   975       <field name="_animateTimer">null</field>
   976       <field name="_fadeTimer">null</field>
   977       <field name="_animateDelay">15</field>
   978       <field name="_animateIncrement">40</field>
   979       <field name="_fadeDelay">5</field>
   980       <field name="_fadeIncrement">0.40</field>
   981       <field name="_animateRemainder">0</field>
   982       <field name="_currentHeight">0</field>
   983       <field name="_multiplier">0</field>
   985       <method name="addPane">
   986         <parameter name="aPaneElement"/>
   987         <body>
   988         <![CDATA[
   989           this.appendChild(aPaneElement);
   991           // Set up pane button
   992           this._makePaneButton(aPaneElement);
   993         ]]>
   994         </body>
   995       </method>
   997       <method name="openSubDialog">
   998         <parameter name="aURL"/>
   999         <parameter name="aFeatures"/>
  1000         <parameter name="aParams"/>
  1001         <body>
  1002           return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
  1003         </body>
  1004       </method>
  1006       <method name="openWindow">
  1007         <parameter name="aWindowType"/>
  1008         <parameter name="aURL"/>
  1009         <parameter name="aFeatures"/>
  1010         <parameter name="aParams"/>
  1011         <body>
  1012         <![CDATA[
  1013           var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  1014                              .getService(Components.interfaces.nsIWindowMediator);
  1015           var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
  1016           if (win) {
  1017             if ("initWithParams" in win)
  1018               win.initWithParams(aParams);
  1019             win.focus();
  1021           else {
  1022             var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
  1023             var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
  1024             win = parentWindow.openDialog(aURL, "_blank", features, aParams);
  1026           return win;
  1027         ]]>
  1028         </body>
  1029       </method>
  1030     </implementation>
  1031     <handlers>
  1032       <handler event="dialogaccept">
  1033       <![CDATA[
  1034         if (!this._fireEvent("beforeaccept", this)){
  1035           return false;
  1038         if (this.type == "child" && window.opener) {
  1039           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1040                                .getService(Components.interfaces.nsIPrefBranch);
  1041           var instantApply = psvc.getBoolPref("browser.preferences.instantApply");
  1042           if (instantApply) {
  1043             var panes = this.preferencePanes;
  1044             for (var i = 0; i < panes.length; ++i)
  1045               panes[i].writePreferences(true);
  1047           else {
  1048             // Clone all the preferences elements from the child document and
  1049             // insert them into the pane collection of the parent. 
  1050             var pdoc = window.opener.document;
  1051             if (pdoc.documentElement.localName == "prefwindow") {
  1052               var currentPane = pdoc.documentElement.currentPane;
  1053               var id = window.location.href + "#childprefs";
  1054               var childPrefs = pdoc.getElementById(id);
  1055               if (!childPrefs) {
  1056                 var childPrefs = pdoc.createElement("preferences");
  1057                 currentPane.appendChild(childPrefs);
  1058                 childPrefs.id = id;
  1060               var panes = this.preferencePanes;
  1061               for (var i = 0; i < panes.length; ++i) {
  1062                 var preferences = panes[i].preferences;
  1063                 for (var j = 0; j < preferences.length; ++j) {
  1064                   // Try to find a preference element for the same preference.
  1065                   var preference = null;
  1066                   var parentPreferences = pdoc.getElementsByTagName("preferences");
  1067                   for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
  1068                     var parentPrefs = parentPreferences[k]
  1069                                          .getElementsByAttribute("name", preferences[j].name);
  1070                     for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
  1071                       if (parentPrefs[l].localName == "preference")
  1072                         preference = parentPrefs[l];
  1075                   if (!preference) {
  1076                     // No matching preference in the parent window.
  1077                     preference = pdoc.createElement("preference");
  1078                     childPrefs.appendChild(preference);
  1079                     preference.name     = preferences[j].name;
  1080                     preference.type     = preferences[j].type;
  1081                     preference.inverted = preferences[j].inverted;
  1082                     preference.readonly = preferences[j].readonly;
  1083                     preference.disabled = preferences[j].disabled;
  1085                   preference.value = preferences[j].value;
  1091         else {
  1092           var panes = this.preferencePanes;
  1093           for (var i = 0; i < panes.length; ++i)
  1094             panes[i].writePreferences(false);
  1096           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1097                                .getService(Components.interfaces.nsIPrefService);
  1098           psvc.savePrefFile(null);
  1101         return true;
  1102       ]]>
  1103       </handler>
  1104       <handler event="command">
  1105         if (event.originalTarget.hasAttribute("pane")) {
  1106           var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
  1107           this.showPane(pane);
  1109       </handler>
  1111       <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
  1112       <![CDATA[
  1113         if (this.instantApply)
  1114           window.close();
  1115         event.stopPropagation();
  1116         event.preventDefault();
  1117       ]]>
  1118       </handler>
  1120       <handler event="keypress"
  1121 #ifdef XP_MACOSX
  1122                key="&openHelpMac.commandkey;" modifiers="accel"
  1123 #else
  1124                keycode="&openHelp.commandkey;"
  1125 #endif
  1126                phase="capturing">
  1127       <![CDATA[
  1128         var helpButton = this.getButton("help");
  1129         if (helpButton.disabled || helpButton.hidden)
  1130           return;
  1131         this._fireEvent("dialoghelp", this);
  1132         event.stopPropagation();
  1133         event.preventDefault();
  1134       ]]>
  1135       </handler>
  1136     </handlers>
  1137   </binding>
  1139   <binding id="prefpane">
  1140     <resources>
  1141       <stylesheet src="chrome://global/skin/preferences.css"/>
  1142     </resources>
  1143     <content>
  1144       <xul:vbox class="content-box" xbl:inherits="flex">
  1145         <children/>
  1146       </xul:vbox>
  1147     </content>
  1148     <implementation>
  1149       <method name="writePreferences">
  1150         <parameter name="aFlushToDisk"/>
  1151         <body>
  1152         <![CDATA[
  1153           // Write all values to preferences.
  1154           var preferences = this.preferences;
  1155           for (var i = 0; i < preferences.length; ++i) {
  1156             var preference = preferences[i];
  1157             preference.batching = true;
  1158             preference.valueFromPreferences = preference.value;
  1159             preference.batching = false;
  1161           if (aFlushToDisk) {
  1162             var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1163                                  .getService(Components.interfaces.nsIPrefService);
  1164             psvc.savePrefFile(null);
  1166         ]]>
  1167         </body>
  1168       </method>
  1170       <property name="src" 
  1171                 onget="return this.getAttribute('src');"
  1172                 onset="this.setAttribute('src', val); return val;"/>
  1173       <property name="selected" 
  1174                 onget="return this.getAttribute('selected') == 'true';"
  1175                 onset="this.setAttribute('selected', val); return val;"/>
  1176       <property name="image" 
  1177                 onget="return this.getAttribute('image');"
  1178                 onset="this.setAttribute('image', val); return val;"/>
  1179       <property name="label" 
  1180                 onget="return this.getAttribute('label');"
  1181                 onset="this.setAttribute('label', val); return val;"/>
  1183       <property name="preferenceElements"
  1184                 onget="return this.getElementsByAttribute('preference', '*');"/>
  1185       <property name="preferences"
  1186                 onget="return this.getElementsByTagName('preference');"/>
  1188       <property name="helpTopic">
  1189         <getter>
  1190         <![CDATA[
  1191           // if there are tabs, and the selected tab provides a helpTopic, return that
  1192           var box = this.getElementsByTagName("tabbox");
  1193           if (box[0]) {
  1194             var tab = box[0].selectedTab;
  1195             if (tab && tab.hasAttribute("helpTopic"))
  1196               return tab.getAttribute("helpTopic");
  1199           // otherwise, return the helpTopic of the current panel
  1200           return this.getAttribute("helpTopic");
  1201         ]]>
  1202         </getter>
  1203       </property>
  1205       <field name="_loaded">false</field>
  1206       <property name="loaded" 
  1207                 onget="return !this.src ? true : this._loaded;"
  1208                 onset="this._loaded = val; return val;"/>
  1210       <method name="preferenceForElement">
  1211         <parameter name="aElement"/>
  1212         <body>
  1213           return document.getElementById(aElement.getAttribute("preference"));
  1214         </body>
  1215       </method>
  1217       <method name="getPreferenceElement">
  1218         <parameter name="aStartElement"/>
  1219         <body>
  1220         <![CDATA[
  1221           var temp = aStartElement;
  1222           while (temp && temp.nodeType == Node.ELEMENT_NODE && 
  1223                  !temp.hasAttribute("preference"))
  1224             temp = temp.parentNode;
  1225           return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement;
  1226         ]]>
  1227         </body>
  1228       </method>
  1230       <method name="userChangedValue">
  1231         <parameter name="aElement"/>
  1232         <body>
  1233         <![CDATA[
  1234           var element = this.getPreferenceElement(aElement);
  1235           if (element.hasAttribute("preference")) {
  1236             var preference = document.getElementById(element.getAttribute("preference"));
  1237             var prefVal = preference.getElementValue(element);
  1238             preference.value = prefVal;
  1240         ]]>
  1241         </body>
  1242       </method>
  1244       <property name="contentHeight">
  1245         <getter>
  1246           var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
  1247           targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
  1248           targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
  1249           return targetHeight;
  1250         </getter>
  1251       </property>
  1252       <field name="_content">
  1253         document.getAnonymousElementByAttribute(this, "class", "content-box");
  1254       </field>
  1255     </implementation>
  1256     <handlers>
  1257       <handler event="command">
  1258         // This "command" event handler tracks changes made to preferences by 
  1259         // the user in this window.
  1260         if (event.sourceEvent)
  1261           event = event.sourceEvent;
  1262         this.userChangedValue(event.target);
  1263       </handler>
  1264       <handler event="select">
  1265         // This "select" event handler tracks changes made to colorpicker 
  1266         // preferences by the user in this window.
  1267         if (event.target.localName == "colorpicker") 
  1268           this.userChangedValue(event.target);
  1269       </handler>
  1270       <handler event="change">
  1271         // This "change" event handler tracks changes made to preferences by 
  1272         // the user in this window. 
  1273         this.userChangedValue(event.target);
  1274       </handler>
  1275       <handler event="input">
  1276         // This "input" event handler tracks changes made to preferences by 
  1277         // the user in this window.
  1278         this.userChangedValue(event.target);
  1279       </handler>
  1280       <handler event="paneload">
  1281       <![CDATA[
  1282         // Initialize all values from preferences.
  1283         var elements = this.preferenceElements;
  1284         for (var i = 0; i < elements.length; ++i) {
  1285           try {
  1286             var preference = this.preferenceForElement(elements[i]);
  1287             preference.setElementValue(elements[i]);
  1289           catch (e) {
  1290             dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
  1293       ]]>      
  1294       </handler>
  1295     </handlers>
  1296   </binding>
  1298   <binding id="panebutton" role="xul:listitem"
  1299            extends="chrome://global/content/bindings/radio.xml#radio">
  1300     <resources>
  1301       <stylesheet src="chrome://global/skin/preferences.css"/>
  1302     </resources>
  1303     <content>
  1304       <xul:image class="paneButtonIcon" xbl:inherits="src"/>
  1305       <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
  1306     </content>
  1307   </binding>
  1309 </bindings>
  1311 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  1312 # This Source Code Form is subject to the terms of the Mozilla Public
  1313 # License, v. 2.0. If a copy of the MPL was not distributed with this
  1314 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  1317 # This is PrefWindow 6. The Code Could Well Be Ready, Are You?
  1319 #    Historical References:
  1320 #    PrefWindow V   (February 1, 2003)
  1321 #    PrefWindow IV  (April 24, 2000)
  1322 #    PrefWindow III (January 6, 2000)
  1323 #    PrefWindow II  (???)
  1324 #    PrefWindow I   (June 4, 1999)

mercurial