PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/toolkit/content/widgets/preferences.xml

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