mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-09 04:54:33 +00:00
1404 lines
51 KiB
XML
1404 lines
51 KiB
XML
<?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>
|
|
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 !== undefined ? rv : (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");
|
|
#ifdef XP_MACOSX
|
|
// 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");
|
|
#endif
|
|
}
|
|
}
|
|
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[
|
|
#ifdef XP_MACOSX
|
|
var paneTitle = aPaneElement.label;
|
|
if (paneTitle != "")
|
|
document.title = paneTitle;
|
|
#endif
|
|
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);
|
|
#ifdef XP_MACOSX
|
|
var animate = true;
|
|
#else
|
|
var animate = false;
|
|
#endif
|
|
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)) {
|
|
var psvc = Components.classes["@mozilla.org/preferences-service;1"]
|
|
.getService(Components.interfaces.nsIPrefBranch);
|
|
var pdocEl = window.opener.document.documentElement;
|
|
if (pdocEl.instantApply) {
|
|
var panes = this.preferencePanes;
|
|
for (var 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) {
|
|
var childPrefs = pdoc.createElement("preferences");
|
|
currentPane.appendChild(childPrefs);
|
|
childPrefs.id = id;
|
|
}
|
|
var panes = this.preferencePanes;
|
|
for (var 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 {
|
|
var panes = this.preferencePanes;
|
|
for (var i = 0; i < panes.length; ++i)
|
|
panes[i].writePreferences(false);
|
|
|
|
var 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>
|
|
|
|
<field name="DeferredTask" readonly="true">
|
|
let targetObj = {};
|
|
Components.utils.import("resource://gre/modules/DeferredTask.jsm", targetObj);
|
|
targetObj.DeferredTask;
|
|
</field>
|
|
<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)
|
|
#
|