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