<?xml version="1.0"?> <!DOCTYPE bindings [ <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd"> %preferencesDTD; <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> %globalKeysDTD; ]> <bindings id="preferencesBindings" xmlns="http://www.mozilla.org/xbl" xmlns:xbl="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> # # = Preferences Window Framework # # The syntax for use looks something like: # # <prefwindow> # <prefpane id="prefPaneA"> # <preferences> # <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/> # <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/> # </preferences> # <checkbox label="Preference" preference="preference1"/> # </prefpane> # </prefwindow> # <binding id="preferences"> <implementation implements="nsIObserver"> <method name="_constructAfterChildren"> <body> <![CDATA[ // This method will be called after each one of the child // <preference> elements is constructed. Its purpose is to propagate // the values to the associated form elements var elements = this.getElementsByTagName("preference"); for (let element of elements) { if (!element._constructed) { return; } } for (let element of elements) { element.updateElements(); } ]]> </body> </method> <method name="observe"> <parameter name="aSubject"/> <parameter name="aTopic"/> <parameter name="aData"/> <body> <![CDATA[ for (var i = 0; i < this.childNodes.length; ++i) { var preference = this.childNodes[i]; if (preference.name == aData) { preference.value = preference.valueFromPreferences; } } ]]> </body> </method> <method name="fireChangedEvent"> <parameter name="aPreference"/> <body> <![CDATA[ // Value changed, synthesize an event try { var event = document.createEvent("Events"); event.initEvent("change", true, true); aPreference.dispatchEvent(event); } catch (e) { Components.utils.reportError(e); } ]]> </body> </method> <field name="service"> Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); </field> <field name="rootBranch"> Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); </field> <field name="defaultBranch"> this.service.getDefaultBranch(""); </field> <field name="rootBranchInternal"> Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranchInternal); </field> <property name="type" readonly="true"> <getter> <![CDATA[ return document.documentElement.type || ""; ]]> </getter> </property> <property name="instantApply" readonly="true"> <getter> <![CDATA[ var doc = document.documentElement; return this.type == "child" ? doc.instantApply : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply"); ]]> </getter> </property> </implementation> </binding> <binding id="preference"> <implementation> <constructor> <![CDATA[ this._constructed = true; // if the element has been inserted without the name attribute set, // we have nothing to do here if (!this.name) return; this.preferences.rootBranchInternal .addObserver(this.name, this.preferences, false); // In non-instant apply mode, we must try and use the last saved state // from any previous opens of a child dialog instead of the value from // preferences, to pick up any edits a user may have made. var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] .getService(Components.interfaces.nsIScriptSecurityManager); if (this.preferences.type == "child" && !this.instantApply && window.opener && secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) { var pdoc = window.opener.document; // Try to find a preference element for the same preference. var preference = null; var parentPreferences = pdoc.getElementsByTagName("preferences"); for (var k = 0; (k < parentPreferences.length && !preference); ++k) { var parentPrefs = parentPreferences[k] .getElementsByAttribute("name", this.name); for (var l = 0; (l < parentPrefs.length && !preference); ++l) { if (parentPrefs[l].localName == "preference") preference = parentPrefs[l]; } } // Don't use the value setter here, we don't want updateElements to be prematurely fired. this._value = preference ? preference.value : this.valueFromPreferences; } else this._value = this.valueFromPreferences; this.preferences._constructAfterChildren(); ]]> </constructor> <destructor> this.preferences.rootBranchInternal .removeObserver(this.name, this.preferences); </destructor> <field name="_constructed">false</field> <property name="instantApply"> <getter> if (this.getAttribute("instantApply") == "false") return false; return this.getAttribute("instantApply") == "true" || this.preferences.instantApply; </getter> </property> <property name="preferences" onget="return this.parentNode"/> <property name="name" onget="return this.getAttribute('name');"> <setter> if (val == this.name) return val; this.preferences.rootBranchInternal .removeObserver(this.name, this.preferences); this.setAttribute('name', val); this.preferences.rootBranchInternal .addObserver(val, this.preferences, false); return val; </setter> </property> <property name="type" onget="return this.getAttribute('type');" onset="this.setAttribute('type', val); return val;"/> <property name="inverted" onget="return this.getAttribute('inverted') == 'true';" onset="this.setAttribute('inverted', val); return val;"/> <property name="readonly" onget="return this.getAttribute('readonly') == 'true';" onset="this.setAttribute('readonly', val); return val;"/> <field name="_value">null</field> <method name="_setValue"> <parameter name="aValue"/> <body> <![CDATA[ if (this.value !== aValue) { this._value = aValue; if (this.instantApply) this.valueFromPreferences = aValue; this.preferences.fireChangedEvent(this); } return aValue; ]]> </body> </method> <property name="value" onget="return this._value" onset="return this._setValue(val);"/> <property name="locked"> <getter> return this.preferences.rootBranch.prefIsLocked(this.name); </getter> </property> <property name="disabled"> <getter> return this.getAttribute("disabled") == "true"; </getter> <setter> <![CDATA[ if (val) this.setAttribute("disabled", "true"); else this.removeAttribute("disabled"); if (!this.id) return val; var elements = document.getElementsByAttribute("preference", this.id); for (var i = 0; i < elements.length; ++i) { elements[i].disabled = val; var labels = document.getElementsByAttribute("control", elements[i].id); for (var j = 0; j < labels.length; ++j) labels[j].disabled = val; } return val; ]]> </setter> </property> <property name="tabIndex"> <getter> return parseInt(this.getAttribute("tabindex")); </getter> <setter> <![CDATA[ if (val) this.setAttribute("tabindex", val); else this.removeAttribute("tabindex"); if (!this.id) return val; var elements = document.getElementsByAttribute("preference", this.id); for (var i = 0; i < elements.length; ++i) { elements[i].tabIndex = val; var labels = document.getElementsByAttribute("control", elements[i].id); for (var j = 0; j < labels.length; ++j) labels[j].tabIndex = val; } return val; ]]> </setter> </property> <property name="hasUserValue"> <getter> <![CDATA[ return this.preferences.rootBranch.prefHasUserValue(this.name) && this.value !== undefined; ]]> </getter> </property> <method name="reset"> <body> // defer reset until preference update this.value = undefined; </body> </method> <field name="_useDefault">false</field> <property name="defaultValue"> <getter> <![CDATA[ this._useDefault = true; var val = this.valueFromPreferences; this._useDefault = false; return val; ]]> </getter> </property> <property name="_branch"> <getter> return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch; </getter> </property> <field name="batching">false</field> <method name="_reportUnknownType"> <body> <![CDATA[ var consoleService = Components.classes["@mozilla.org/consoleservice;1"] .getService(Components.interfaces.nsIConsoleService); var msg = "<preference> with id='" + this.id + "' and name='" + this.name + "' has unknown type '" + this.type + "'."; consoleService.logStringMessage(msg); ]]> </body> </method> <property name="valueFromPreferences"> <getter> <![CDATA[ try { // Force a resync of value with preferences. switch (this.type) { case "int": return this._branch.getIntPref(this.name); case "bool": var val = this._branch.getBoolPref(this.name); return this.inverted ? !val : val; case "wstring": return this._branch .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString) .data; case "string": case "unichar": return this._branch .getComplexValue(this.name, Components.interfaces.nsISupportsString) .data; case "fontname": var family = this._branch .getComplexValue(this.name, Components.interfaces.nsISupportsString) .data; var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"] .createInstance(Components.interfaces.nsIFontEnumerator); return fontEnumerator.getStandardFamilyName(family); case "file": var f = this._branch .getComplexValue(this.name, Components.interfaces.nsILocalFile); return f; default: this._reportUnknownType(); } } catch (e) { } return null; ]]> </getter> <setter> <![CDATA[ // Exit early if nothing to do. if (this.readonly || this.valueFromPreferences == val) return val; // The special value undefined means 'reset preference to default'. if (val === undefined) { this.preferences.rootBranch.clearUserPref(this.name); return val; } // Force a resync of preferences with value. switch (this.type) { case "int": this.preferences.rootBranch.setIntPref(this.name, val); break; case "bool": this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val); break; case "wstring": var pls = Components.classes["@mozilla.org/pref-localizedstring;1"] .createInstance(Components.interfaces.nsIPrefLocalizedString); pls.data = val; this.preferences.rootBranch .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls); break; case "string": case "unichar": case "fontname": var iss = Components.classes["@mozilla.org/supports-string;1"] .createInstance(Components.interfaces.nsISupportsString); iss.data = val; this.preferences.rootBranch .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss); break; case "file": var lf; if (typeof(val) == "string") { lf = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); lf.persistentDescriptor = val; if (!lf.exists()) lf.initWithPath(val); } else lf = val.QueryInterface(Components.interfaces.nsILocalFile); this.preferences.rootBranch .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf); break; default: this._reportUnknownType(); } if (!this.batching) this.preferences.service.savePrefFile(null); return val; ]]> </setter> </property> <method name="setElementValue"> <parameter name="aElement"/> <body> <![CDATA[ if (this.locked) aElement.disabled = true; if (!this.isElementEditable(aElement)) return; var rv = undefined; if (aElement.hasAttribute("onsyncfrompreference")) { // Value changed, synthesize an event try { var event = document.createEvent("Events"); event.initEvent("syncfrompreference", true, true); var f = new Function ("event", aElement.getAttribute("onsyncfrompreference")); rv = f.call(aElement, event); } catch (e) { Components.utils.reportError(e); } } var val = rv; if (val === undefined) val = this.instantApply ? this.valueFromPreferences : this.value; // if the preference is marked for reset, show default value in UI if (val === undefined) val = this.defaultValue; /** * Initialize a UI element property with a value. Handles the case * where an element has not yet had a XBL binding attached for it and * the property setter does not yet exist by setting the same attribute * on the XUL element using DOM apis and assuming the element's * constructor or property getters appropriately handle this state. */ function setValue(element, attribute, value) { if (attribute in element) element[attribute] = value; else element.setAttribute(attribute, value); } if (aElement.localName == "checkbox" || aElement.localName == "listitem") setValue(aElement, "checked", val); else if (aElement.localName == "colorpicker") setValue(aElement, "color", val); else if (aElement.localName == "textbox") { // XXXmano Bug 303998: Avoid a caret placement issue if either the // preference observer or its setter calls updateElements as a result // of the input event handler. if (aElement.value !== val) setValue(aElement, "value", val); } else setValue(aElement, "value", val); ]]> </body> </method> <method name="getElementValue"> <parameter name="aElement"/> <body> <![CDATA[ if (aElement.hasAttribute("onsynctopreference")) { // Value changed, synthesize an event try { var event = document.createEvent("Events"); event.initEvent("synctopreference", true, true); var f = new Function ("event", aElement.getAttribute("onsynctopreference")); var rv = f.call(aElement, event); if (rv !== undefined) return rv; } catch (e) { Components.utils.reportError(e); } } /** * Read the value of an attribute from an element, assuming the * attribute is a property on the element's node API. If the property * is not present in the API, then assume its value is contained in * an attribute, as is the case before a binding has been attached. */ function getValue(element, attribute) { if (attribute in element) return element[attribute]; return element.getAttribute(attribute); } if (aElement.localName == "checkbox" || aElement.localName == "listitem") var value = getValue(aElement, "checked"); else if (aElement.localName == "colorpicker") value = getValue(aElement, "color"); else value = getValue(aElement, "value"); switch (this.type) { case "int": return parseInt(value, 10) || 0; case "bool": return typeof(value) == "boolean" ? value : value == "true"; } return value; ]]> </body> </method> <method name="isElementEditable"> <parameter name="aElement"/> <body> <![CDATA[ switch (aElement.localName) { case "checkbox": case "colorpicker": case "radiogroup": case "textbox": case "listitem": case "listbox": case "menulist": return true; } return aElement.getAttribute("preference-editable") == "true"; ]]> </body> </method> <method name="updateElements"> <body> <![CDATA[ if (!this.id) return; // This "change" event handler tracks changes made to preferences by // sources other than the user in this window. var elements = document.getElementsByAttribute("preference", this.id); for (var i = 0; i < elements.length; ++i) this.setElementValue(elements[i]); ]]> </body> </method> </implementation> <handlers> <handler event="change"> this.updateElements(); </handler> </handlers> </binding> <binding id="prefwindow" extends="chrome://global/content/bindings/dialog.xml#dialog"> <resources> <stylesheet src="chrome://global/skin/preferences.css"/> </resources> <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY" closebuttonlabel="&preferencesCloseButton.label;" closebuttonaccesskey="&preferencesCloseButton.accesskey;" role="dialog" #ifdef XP_WIN title="&preferencesDefaultTitleWin.title;"> #else title="&preferencesDefaultTitleMac.title;"> #endif <xul:windowdragbox orient="vertical"> <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar" role="listbox"/> <!-- Expose to accessibility APIs as a listbox --> </xul:windowdragbox> <xul:hbox flex="1" class="paneDeckContainer"> <xul:deck anonid="paneDeck" flex="1"> <children includes="prefpane"/> </xul:deck> </xul:hbox> <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end"> #ifdef XP_UNIX <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> <xul:spacer anonid="spacer" flex="1"/> <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> #else <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> <xul:spacer anonid="spacer" flex="1"/> <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> #endif </xul:hbox> <xul:hbox> <children/> </xul:hbox> </content> <implementation implements="nsITimerCallback"> <constructor> <![CDATA[ if (this.type != "child") { if (!this._instantApplyInitialized) { let psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); this.instantApply = psvc.getBoolPref("browser.preferences.instantApply"); } if (this.instantApply) { var docElt = document.documentElement; var acceptButton = docElt.getButton("accept"); acceptButton.hidden = true; var cancelButton = docElt.getButton("cancel"); if (/Mac/.test(navigator.platform)) { // no buttons on Mac except Help cancelButton.hidden = true; // Move Help button to the end document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true; // Also, don't fire onDialogAccept on enter acceptButton.disabled = true; } else { // morph the Cancel button into the Close button cancelButton.setAttribute ("icon", "close"); cancelButton.label = docElt.getAttribute("closebuttonlabel"); cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey"); } } } this.setAttribute("animated", this._shouldAnimate ? "true" : "false"); var panes = this.preferencePanes; var lastPane = null; if (this.lastSelected) { lastPane = document.getElementById(this.lastSelected); if (!lastPane) { this.lastSelected = ""; } } var paneToLoad; if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") { paneToLoad = document.getElementById(window.arguments[0]); this.lastSelected = paneToLoad.id; } else if (lastPane) paneToLoad = lastPane; else paneToLoad = panes[0]; for (var i = 0; i < panes.length; ++i) { this._makePaneButton(panes[i]); if (panes[i].loaded) { // Inline pane content, fire load event to force initialization. this._fireEvent("paneload", panes[i]); } } this.showPane(paneToLoad); if (panes.length == 1) this._selector.setAttribute("collapsed", "true"); ]]> </constructor> <destructor> <![CDATA[ // Release timers to avoid reference cycles. if (this._animateTimer) { this._animateTimer.cancel(); this._animateTimer = null; } if (this._fadeTimer) { this._fadeTimer.cancel(); this._fadeTimer = null; } ]]> </destructor> <!-- Derived bindings can set this to true to cause us to skip reading the browser.preferences.instantApply pref in the constructor. Then they can set instantApply to their wished value. --> <field name="_instantApplyInitialized">false</field> <!-- Controls whether changed pref values take effect immediately. --> <field name="instantApply">false</field> <property name="preferencePanes" onget="return this.getElementsByTagName('prefpane');"/> <property name="type" onget="return this.getAttribute('type');"/> <property name="_paneDeck" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/> <property name="_paneDeckContainer" onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/> <property name="_selector" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/> <property name="lastSelected" onget="return this.getAttribute('lastSelected');"> <setter> this.setAttribute("lastSelected", val); document.persist(this.id, "lastSelected"); return val; </setter> </property> <property name="currentPane" onset="return this._currentPane = val;"> <getter> if (!this._currentPane) this._currentPane = this.preferencePanes[0]; return this._currentPane; </getter> </property> <field name="_currentPane">null</field> <method name="_makePaneButton"> <parameter name="aPaneElement"/> <body> <![CDATA[ var radio = document.createElement("radio"); radio.setAttribute("pane", aPaneElement.id); radio.setAttribute("label", aPaneElement.label); // Expose preference group choice to accessibility APIs as an unchecked list item // The parent group is exposed to accessibility APIs as a list if (aPaneElement.image) radio.setAttribute("src", aPaneElement.image); radio.style.listStyleImage = aPaneElement.style.listStyleImage; this._selector.appendChild(radio); return radio; ]]> </body> </method> <method name="showPane"> <parameter name="aPaneElement"/> <body> <![CDATA[ if (!aPaneElement) return; this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id); if (!aPaneElement.loaded) { let OverlayLoadObserver = function(aPane) { this._pane = aPane; } OverlayLoadObserver.prototype = { _outer: this, observe: function (aSubject, aTopic, aData) { this._pane.loaded = true; this._outer._fireEvent("paneload", this._pane); this._outer._selectPane(this._pane); } }; var obs = new OverlayLoadObserver(aPaneElement); document.loadOverlay(aPaneElement.src, obs); } else this._selectPane(aPaneElement); ]]> </body> </method> <method name="_fireEvent"> <parameter name="aEventName"/> <parameter name="aTarget"/> <body> <![CDATA[ // Panel loaded, synthesize a load event. try { var event = document.createEvent("Events"); event.initEvent(aEventName, true, true); var cancel = !aTarget.dispatchEvent(event); if (aTarget.hasAttribute("on" + aEventName)) { var fn = new Function ("event", aTarget.getAttribute("on" + aEventName)); var rv = fn.call(aTarget, event); if (rv == false) cancel = true; } return !cancel; } catch (e) { Components.utils.reportError(e); } return false; ]]> </body> </method> <field name="_initialized">false</field> <method name="_selectPane"> <parameter name="aPaneElement"/> <body> <![CDATA[ if (/Mac/.test(navigator.platform)) { var paneTitle = aPaneElement.label; if (paneTitle != "") document.title = paneTitle; } var helpButton = document.documentElement.getButton("help"); if (aPaneElement.helpTopic) helpButton.hidden = false; else helpButton.hidden = true; // Find this pane's index in the deck and set the deck's // selectedIndex to that value to switch to it. var prefpanes = this.preferencePanes; for (var i = 0; i < prefpanes.length; ++i) { if (prefpanes[i] == aPaneElement) { this._paneDeck.selectedIndex = i; if (this.type != "child") { if (aPaneElement.hasAttribute("flex") && this._shouldAnimate && prefpanes.length > 1) aPaneElement.removeAttribute("flex"); // Calling sizeToContent after the first prefpane is loaded // will size the windows contents so style information is // available to calculate correct sizing. if (!this._initialized && prefpanes.length > 1) { if (this._shouldAnimate) this.style.minHeight = 0; window.sizeToContent(); } var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0]; oldPane.selected = !(aPaneElement.selected = true); this.lastSelected = aPaneElement.id; this.currentPane = aPaneElement; this._initialized = true; // Only animate if we've switched between prefpanes if (this._shouldAnimate && oldPane.id != aPaneElement.id) { aPaneElement.style.opacity = 0.0; this.animate(oldPane, aPaneElement); } else if (!this._shouldAnimate && prefpanes.length > 1) { var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height); var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop); verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom); if (aPaneElement.contentHeight > targetHeight - verticalPadding) { // To workaround the bottom border of a groupbox from being // cutoff an hbox with a class of bottomBox may enclose it. // This needs to include its padding to resize properly. // See bug 394433 var bottomPadding = 0; var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0]; if (bottomBox) bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom); window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight; } // XXX rstrong - extend the contents of the prefpane to // prevent elements from being cutoff (see bug 349098). if (aPaneElement.contentHeight + verticalPadding < targetHeight) aPaneElement._content.style.height = targetHeight - verticalPadding + "px"; } } break; } } ]]> </body> </method> <property name="_shouldAnimate"> <getter> <![CDATA[ var psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); var animate = /Mac/.test(navigator.platform); try { animate = psvc.getBoolPref("browser.preferences.animateFadeIn"); } catch (e) { } return animate; ]]> </getter> </property> <method name="animate"> <parameter name="aOldPane"/> <parameter name="aNewPane"/> <body> <![CDATA[ // if we are already resizing, use currentHeight var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight; this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1; var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight); this._animateRemainder = sizeDelta % this._animateIncrement; this._setUpAnimationTimer(oldHeight); ]]> </body> </method> <property name="_sizeIncrement"> <getter> <![CDATA[ var lastSelectedPane = document.getElementById(this.lastSelected); var increment = this._animateIncrement * this._multiplier; var newHeight = this._currentHeight + increment; if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) || (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight)) return 0; if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) || (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight)) increment = this._animateRemainder * this._multiplier; return increment; ]]> </getter> </property> <method name="notify"> <parameter name="aTimer"/> <body> <![CDATA[ if (!document) aTimer.cancel(); if (aTimer == this._animateTimer) { var increment = this._sizeIncrement; if (increment != 0) { window.innerHeight += increment; this._currentHeight += increment; } else { aTimer.cancel(); this._setUpFadeTimer(); } } else if (aTimer == this._fadeTimer) { var elt = document.getElementById(this.lastSelected); var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement; if (newOpacity < 1.0) elt.style.opacity = newOpacity; else { aTimer.cancel(); elt.style.opacity = 1.0; } } ]]> </body> </method> <method name="_setUpAnimationTimer"> <parameter name="aStartHeight"/> <body> <![CDATA[ if (!this._animateTimer) this._animateTimer = Components.classes["@mozilla.org/timer;1"] .createInstance(Components.interfaces.nsITimer); else this._animateTimer.cancel(); this._currentHeight = aStartHeight; this._animateTimer.initWithCallback(this, this._animateDelay, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); ]]> </body> </method> <method name="_setUpFadeTimer"> <body> <![CDATA[ if (!this._fadeTimer) this._fadeTimer = Components.classes["@mozilla.org/timer;1"] .createInstance(Components.interfaces.nsITimer); else this._fadeTimer.cancel(); this._fadeTimer.initWithCallback(this, this._fadeDelay, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); ]]> </body> </method> <field name="_animateTimer">null</field> <field name="_fadeTimer">null</field> <field name="_animateDelay">15</field> <field name="_animateIncrement">40</field> <field name="_fadeDelay">5</field> <field name="_fadeIncrement">0.40</field> <field name="_animateRemainder">0</field> <field name="_currentHeight">0</field> <field name="_multiplier">0</field> <method name="addPane"> <parameter name="aPaneElement"/> <body> <![CDATA[ this.appendChild(aPaneElement); // Set up pane button this._makePaneButton(aPaneElement); ]]> </body> </method> <method name="openSubDialog"> <parameter name="aURL"/> <parameter name="aFeatures"/> <parameter name="aParams"/> <body> return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams); </body> </method> <method name="openWindow"> <parameter name="aWindowType"/> <parameter name="aURL"/> <parameter name="aFeatures"/> <parameter name="aParams"/> <body> <![CDATA[ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator); var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null; if (win) { if ("initWithParams" in win) win.initWithParams(aParams); win.focus(); } else { var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : ""); var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener; win = parentWindow.openDialog(aURL, "_blank", features, aParams); } return win; ]]> </body> </method> </implementation> <handlers> <handler event="dialogaccept"> <![CDATA[ if (!this._fireEvent("beforeaccept", this)) { return false; } var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] .getService(Components.interfaces.nsIScriptSecurityManager); if (this.type == "child" && window.opener && secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) { let psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); var pdocEl = window.opener.document.documentElement; if (pdocEl.instantApply) { let panes = this.preferencePanes; for (let i = 0; i < panes.length; ++i) panes[i].writePreferences(true); } else { // Clone all the preferences elements from the child document and // insert them into the pane collection of the parent. var pdoc = window.opener.document; if (pdoc.documentElement.localName == "prefwindow") { var currentPane = pdoc.documentElement.currentPane; var id = window.location.href + "#childprefs"; var childPrefs = pdoc.getElementById(id); if (!childPrefs) { childPrefs = pdoc.createElement("preferences"); currentPane.appendChild(childPrefs); childPrefs.id = id; } let panes = this.preferencePanes; for (let i = 0; i < panes.length; ++i) { var preferences = panes[i].preferences; for (var j = 0; j < preferences.length; ++j) { // Try to find a preference element for the same preference. var preference = null; var parentPreferences = pdoc.getElementsByTagName("preferences"); for (var k = 0; (k < parentPreferences.length && !preference); ++k) { var parentPrefs = parentPreferences[k] .getElementsByAttribute("name", preferences[j].name); for (var l = 0; (l < parentPrefs.length && !preference); ++l) { if (parentPrefs[l].localName == "preference") preference = parentPrefs[l]; } } if (!preference) { // No matching preference in the parent window. preference = pdoc.createElement("preference"); childPrefs.appendChild(preference); preference.name = preferences[j].name; preference.type = preferences[j].type; preference.inverted = preferences[j].inverted; preference.readonly = preferences[j].readonly; preference.disabled = preferences[j].disabled; } preference.value = preferences[j].value; } } } } } else { let panes = this.preferencePanes; for (var i = 0; i < panes.length; ++i) panes[i].writePreferences(false); let psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); psvc.savePrefFile(null); } return true; ]]> </handler> <handler event="command"> if (event.originalTarget.hasAttribute("pane")) { var pane = document.getElementById(event.originalTarget.getAttribute("pane")); this.showPane(pane); } </handler> <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing"> <![CDATA[ if (this.instantApply) window.close(); event.stopPropagation(); event.preventDefault(); ]]> </handler> <handler event="keypress" #ifdef XP_MACOSX key="&openHelpMac.commandkey;" modifiers="accel" #else keycode="&openHelp.commandkey;" #endif phase="capturing"> <![CDATA[ var helpButton = this.getButton("help"); if (helpButton.disabled || helpButton.hidden) return; this._fireEvent("dialoghelp", this); event.stopPropagation(); event.preventDefault(); ]]> </handler> </handlers> </binding> <binding id="prefpane"> <resources> <stylesheet src="chrome://global/skin/preferences.css"/> </resources> <content> <xul:vbox class="content-box" xbl:inherits="flex"> <children/> </xul:vbox> </content> <implementation> <method name="writePreferences"> <parameter name="aFlushToDisk"/> <body> <![CDATA[ // Write all values to preferences. if (this._deferredValueUpdateElements.size) { this._finalizeDeferredElements(); } var preferences = this.preferences; for (var i = 0; i < preferences.length; ++i) { var preference = preferences[i]; preference.batching = true; preference.valueFromPreferences = preference.value; preference.batching = false; } if (aFlushToDisk) { var psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); psvc.savePrefFile(null); } ]]> </body> </method> <property name="src" onget="return this.getAttribute('src');" onset="this.setAttribute('src', val); return val;"/> <property name="selected" onget="return this.getAttribute('selected') == 'true';" onset="this.setAttribute('selected', val); return val;"/> <property name="image" onget="return this.getAttribute('image');" onset="this.setAttribute('image', val); return val;"/> <property name="label" onget="return this.getAttribute('label');" onset="this.setAttribute('label', val); return val;"/> <property name="preferenceElements" onget="return this.getElementsByAttribute('preference', '*');"/> <property name="preferences" onget="return this.getElementsByTagName('preference');"/> <property name="helpTopic"> <getter> <![CDATA[ // if there are tabs, and the selected tab provides a helpTopic, return that var box = this.getElementsByTagName("tabbox"); if (box[0]) { var tab = box[0].selectedTab; if (tab && tab.hasAttribute("helpTopic")) return tab.getAttribute("helpTopic"); } // otherwise, return the helpTopic of the current panel return this.getAttribute("helpTopic"); ]]> </getter> </property> <field name="_loaded">false</field> <property name="loaded" onget="return !this.src ? true : this._loaded;" onset="this._loaded = val; return val;"/> <method name="preferenceForElement"> <parameter name="aElement"/> <body> return document.getElementById(aElement.getAttribute("preference")); </body> </method> <method name="getPreferenceElement"> <parameter name="aStartElement"/> <body> <![CDATA[ var temp = aStartElement; while (temp && temp.nodeType == Node.ELEMENT_NODE && !temp.hasAttribute("preference")) temp = temp.parentNode; return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement; ]]> </body> </method> <property name="DeferredTask" readonly="true"> <getter><![CDATA[ let module = {}; Components.utils.import("resource://gre/modules/DeferredTask.jsm", module); Object.defineProperty(this, "DeferredTask", { configurable: true, enumerable: true, writable: true, value: module.DeferredTask }); return module.DeferredTask; ]]></getter> </property> <method name="_deferredValueUpdate"> <parameter name="aElement"/> <body> <![CDATA[ delete aElement._deferredValueUpdateTask; let preference = document.getElementById(aElement.getAttribute("preference")); let prefVal = preference.getElementValue(aElement); preference.value = prefVal; this._deferredValueUpdateElements.delete(aElement); ]]> </body> </method> <field name="_deferredValueUpdateElements"> new Set(); </field> <method name="_finalizeDeferredElements"> <body> <![CDATA[ for (let el of this._deferredValueUpdateElements) { if (el._deferredValueUpdateTask) { el._deferredValueUpdateTask.finalize(); } } ]]> </body> </method> <method name="userChangedValue"> <parameter name="aElement"/> <body> <![CDATA[ let element = this.getPreferenceElement(aElement); if (element.hasAttribute("preference")) { if (element.getAttribute("delayprefsave") != "true") { var preference = document.getElementById(element.getAttribute("preference")); var prefVal = preference.getElementValue(element); preference.value = prefVal; } else { if (!element._deferredValueUpdateTask) { element._deferredValueUpdateTask = new this.DeferredTask(this._deferredValueUpdate.bind(this, element), 1000); this._deferredValueUpdateElements.add(element); } else { // Each time the preference is changed, restart the delay. element._deferredValueUpdateTask.disarm(); } element._deferredValueUpdateTask.arm(); } } ]]> </body> </method> <property name="contentHeight"> <getter> var targetHeight = parseInt(window.getComputedStyle(this._content, "").height); targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop); targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom); return targetHeight; </getter> </property> <field name="_content"> document.getAnonymousElementByAttribute(this, "class", "content-box"); </field> </implementation> <handlers> <handler event="command"> // This "command" event handler tracks changes made to preferences by // the user in this window. if (event.sourceEvent) event = event.sourceEvent; this.userChangedValue(event.target); </handler> <handler event="select"> // This "select" event handler tracks changes made to colorpicker // preferences by the user in this window. if (event.target.localName == "colorpicker") this.userChangedValue(event.target); </handler> <handler event="change"> // This "change" event handler tracks changes made to preferences by // the user in this window. this.userChangedValue(event.target); </handler> <handler event="input"> // This "input" event handler tracks changes made to preferences by // the user in this window. this.userChangedValue(event.target); </handler> <handler event="paneload"> <![CDATA[ // Initialize all values from preferences. var elements = this.preferenceElements; for (var i = 0; i < elements.length; ++i) { try { var preference = this.preferenceForElement(elements[i]); preference.setElementValue(elements[i]); } catch (e) { dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n"); } } ]]> </handler> </handlers> </binding> <binding id="panebutton" role="xul:listitem" extends="chrome://global/content/bindings/radio.xml#radio"> <resources> <stylesheet src="chrome://global/skin/preferences.css"/> </resources> <content> <xul:image class="paneButtonIcon" xbl:inherits="src"/> <xul:label class="paneButtonLabel" xbl:inherits="value=label"/> </content> </binding> </bindings> # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # This is PrefWindow 6. The Code Could Well Be Ready, Are You? # # Historical References: # PrefWindow V (February 1, 2003) # PrefWindow IV (April 24, 2000) # PrefWindow III (January 6, 2000) # PrefWindow II (???) # PrefWindow I (June 4, 1999) #