690 +#endif |
668 +#endif |
691 + </handlers> |
669 + </handlers> |
692 + |
670 + |
693 + </binding> |
671 + </binding> |
694 + |
672 + |
695 + <binding id="dialogheader"> |
|
696 + <resources> |
|
697 + <stylesheet src="chrome://global/skin/dialog.css"/> |
|
698 + </resources> |
|
699 + <content> |
|
700 + <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/> |
|
701 + <xul:label class="dialogheader-description" xbl:inherits="value=description"/> |
|
702 + </content> |
|
703 + </binding> |
|
704 + |
|
705 +</bindings> |
673 +</bindings> |
706 diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml |
|
707 new file mode 100644 |
|
708 --- /dev/null |
|
709 +++ b/toolkit/content/widgets/preferences-kde.xml |
|
710 @@ -0,0 +1,1409 @@ |
|
711 +<?xml version="1.0"?> |
|
712 + |
|
713 +<!DOCTYPE bindings [ |
|
714 + <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd"> |
|
715 + %preferencesDTD; |
|
716 + <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> |
|
717 + %globalKeysDTD; |
|
718 +]> |
|
719 + |
|
720 +<bindings id="preferencesBindings" |
|
721 + xmlns="http://www.mozilla.org/xbl" |
|
722 + xmlns:xbl="http://www.mozilla.org/xbl" |
|
723 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|
724 + |
|
725 +# |
|
726 +# = Preferences Window Framework |
|
727 +# |
|
728 +# The syntax for use looks something like: |
|
729 +# |
|
730 +# <prefwindow> |
|
731 +# <prefpane id="prefPaneA"> |
|
732 +# <preferences> |
|
733 +# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/> |
|
734 +# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/> |
|
735 +# </preferences> |
|
736 +# <checkbox label="Preference" preference="preference1"/> |
|
737 +# </prefpane> |
|
738 +# </prefwindow> |
|
739 +# |
|
740 + |
|
741 + <binding id="preferences"> |
|
742 + <implementation implements="nsIObserver"> |
|
743 + <method name="_constructAfterChildren"> |
|
744 + <body> |
|
745 + <![CDATA[ |
|
746 + // This method will be called after the last of the child |
|
747 + // <preference> elements is constructed. Its purpose is to propagate |
|
748 + // the values to the associated form elements. Sometimes the code for |
|
749 + // some <preference> initializers depend on other <preference> elements |
|
750 + // being initialized so we wait and call updateElements on all of them |
|
751 + // once the last one has been constructed. See bugs 997570 and 992185. |
|
752 + |
|
753 + var elements = this.getElementsByTagName("preference"); |
|
754 + for (let element of elements) { |
|
755 + element.updateElements(); |
|
756 + } |
|
757 + |
|
758 + this._constructAfterChildrenCalled = true; |
|
759 + ]]> |
|
760 + </body> |
|
761 + </method> |
|
762 + <method name="observe"> |
|
763 + <parameter name="aSubject"/> |
|
764 + <parameter name="aTopic"/> |
|
765 + <parameter name="aData"/> |
|
766 + <body> |
|
767 + <![CDATA[ |
|
768 + for (var i = 0; i < this.childNodes.length; ++i) { |
|
769 + var preference = this.childNodes[i]; |
|
770 + if (preference.name == aData) { |
|
771 + preference.value = preference.valueFromPreferences; |
|
772 + } |
|
773 + } |
|
774 + ]]> |
|
775 + </body> |
|
776 + </method> |
|
777 + |
|
778 + <method name="fireChangedEvent"> |
|
779 + <parameter name="aPreference"/> |
|
780 + <body> |
|
781 + <![CDATA[ |
|
782 + // Value changed, synthesize an event |
|
783 + try { |
|
784 + var event = document.createEvent("Events"); |
|
785 + event.initEvent("change", true, true); |
|
786 + aPreference.dispatchEvent(event); |
|
787 + } catch (e) { |
|
788 + Components.utils.reportError(e); |
|
789 + } |
|
790 + ]]> |
|
791 + </body> |
|
792 + </method> |
|
793 + |
|
794 + <field name="service"> |
|
795 + Components.classes["@mozilla.org/preferences-service;1"] |
|
796 + .getService(Components.interfaces.nsIPrefService); |
|
797 + </field> |
|
798 + <field name="rootBranch"> |
|
799 + Components.classes["@mozilla.org/preferences-service;1"] |
|
800 + .getService(Components.interfaces.nsIPrefBranch); |
|
801 + </field> |
|
802 + <field name="defaultBranch"> |
|
803 + this.service.getDefaultBranch(""); |
|
804 + </field> |
|
805 + <field name="rootBranchInternal"> |
|
806 + Components.classes["@mozilla.org/preferences-service;1"] |
|
807 + .getService(Components.interfaces.nsIPrefBranch); |
|
808 + </field> |
|
809 + <property name="type" readonly="true"> |
|
810 + <getter> |
|
811 + <![CDATA[ |
|
812 + return document.documentElement.type || ""; |
|
813 + ]]> |
|
814 + </getter> |
|
815 + </property> |
|
816 + <property name="instantApply" readonly="true"> |
|
817 + <getter> |
|
818 + <![CDATA[ |
|
819 + var doc = document.documentElement; |
|
820 + return this.type == "child" ? doc.instantApply |
|
821 + : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply"); |
|
822 + ]]> |
|
823 + </getter> |
|
824 + </property> |
|
825 + |
|
826 + <!-- We want to call _constructAfterChildren after all child |
|
827 + <preference> elements have been constructed. To do this, we get |
|
828 + and store the node list of all child <preference> elements in the |
|
829 + constructor, and maintain a count which is incremented in the |
|
830 + constructor of <preference>. _constructAfterChildren is called |
|
831 + when the count matches the length of the list. --> |
|
832 + <field name="_constructedChildrenCount">0</field> |
|
833 + <field name="_preferenceChildren">null</field> |
|
834 + <!-- Some <preference> elements are added dynamically after |
|
835 + _constructAfterChildren has already been called - we want to |
|
836 + avoid looping over all of them again in this case so we remember |
|
837 + if we already called it. --> |
|
838 + <field name="_constructAfterChildrenCalled">false</field> |
|
839 + <constructor> |
|
840 + <![CDATA[ |
|
841 + this._preferenceChildren = this.getElementsByTagName("preference"); |
|
842 + ]]> |
|
843 + </constructor> |
|
844 + </implementation> |
|
845 + </binding> |
|
846 + |
|
847 + <binding id="preference"> |
|
848 + <implementation> |
|
849 + <constructor> |
|
850 + <![CDATA[ |
|
851 + // if the element has been inserted without the name attribute set, |
|
852 + // we have nothing to do here |
|
853 + if (!this.name) |
|
854 + return; |
|
855 + |
|
856 + this.preferences.rootBranchInternal |
|
857 + .addObserver(this.name, this.preferences); |
|
858 + // In non-instant apply mode, we must try and use the last saved state |
|
859 + // from any previous opens of a child dialog instead of the value from |
|
860 + // preferences, to pick up any edits a user may have made. |
|
861 + |
|
862 + var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] |
|
863 + .getService(Components.interfaces.nsIScriptSecurityManager); |
|
864 + if (this.preferences.type == "child" && |
|
865 + !this.instantApply && window.opener && |
|
866 + secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) { |
|
867 + var pdoc = window.opener.document; |
|
868 + |
|
869 + // Try to find a preference element for the same preference. |
|
870 + var preference = null; |
|
871 + var parentPreferences = pdoc.getElementsByTagName("preferences"); |
|
872 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) { |
|
873 + var parentPrefs = parentPreferences[k] |
|
874 + .getElementsByAttribute("name", this.name); |
|
875 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) { |
|
876 + if (parentPrefs[l].localName == "preference") |
|
877 + preference = parentPrefs[l]; |
|
878 + } |
|
879 + } |
|
880 + |
|
881 + // Don't use the value setter here, we don't want updateElements to be prematurely fired. |
|
882 + this._value = preference ? preference.value : this.valueFromPreferences; |
|
883 + } else { |
|
884 + this._value = this.valueFromPreferences; |
|
885 + } |
|
886 + if (this.preferences._constructAfterChildrenCalled) { |
|
887 + // This <preference> was added after _constructAfterChildren() was already called. |
|
888 + // We can directly call updateElements(). |
|
889 + this.updateElements(); |
|
890 + return; |
|
891 + } |
|
892 + this.preferences._constructedChildrenCount++; |
|
893 + if (this.preferences._constructedChildrenCount == |
|
894 + this.preferences._preferenceChildren.length) { |
|
895 + // This is the last <preference>, time to updateElements() on all of them. |
|
896 + this.preferences._constructAfterChildren(); |
|
897 + } |
|
898 + ]]> |
|
899 + </constructor> |
|
900 + <destructor> |
|
901 + this.preferences.rootBranchInternal |
|
902 + .removeObserver(this.name, this.preferences); |
|
903 + </destructor> |
|
904 + <field name="_constructed">false</field> |
|
905 + <property name="instantApply"> |
|
906 + <getter> |
|
907 + if (this.getAttribute("instantApply") == "false") |
|
908 + return false; |
|
909 + return this.getAttribute("instantApply") == "true" || this.preferences.instantApply; |
|
910 + </getter> |
|
911 + </property> |
|
912 + |
|
913 + <property name="preferences" onget="return this.parentNode"/> |
|
914 + <property name="name" onget="return this.getAttribute('name');"> |
|
915 + <setter> |
|
916 + if (val == this.name) |
|
917 + return val; |
|
918 + |
|
919 + this.preferences.rootBranchInternal |
|
920 + .removeObserver(this.name, this.preferences); |
|
921 + this.setAttribute("name", val); |
|
922 + this.preferences.rootBranchInternal |
|
923 + .addObserver(val, this.preferences); |
|
924 + |
|
925 + return val; |
|
926 + </setter> |
|
927 + </property> |
|
928 + <property name="type" onget="return this.getAttribute('type');" |
|
929 + onset="this.setAttribute('type', val); return val;"/> |
|
930 + <property name="inverted" onget="return this.getAttribute('inverted') == 'true';" |
|
931 + onset="this.setAttribute('inverted', val); return val;"/> |
|
932 + <property name="readonly" onget="return this.getAttribute('readonly') == 'true';" |
|
933 + onset="this.setAttribute('readonly', val); return val;"/> |
|
934 + |
|
935 + <field name="_value">null</field> |
|
936 + <method name="_setValue"> |
|
937 + <parameter name="aValue"/> |
|
938 + <body> |
|
939 + <![CDATA[ |
|
940 + if (this.value !== aValue) { |
|
941 + this._value = aValue; |
|
942 + if (this.instantApply) |
|
943 + this.valueFromPreferences = aValue; |
|
944 + this.preferences.fireChangedEvent(this); |
|
945 + } |
|
946 + return aValue; |
|
947 + ]]> |
|
948 + </body> |
|
949 + </method> |
|
950 + <property name="value" onget="return this._value" onset="return this._setValue(val);"/> |
|
951 + |
|
952 + <property name="locked"> |
|
953 + <getter> |
|
954 + return this.preferences.rootBranch.prefIsLocked(this.name); |
|
955 + </getter> |
|
956 + </property> |
|
957 + |
|
958 + <property name="disabled"> |
|
959 + <getter> |
|
960 + return this.getAttribute("disabled") == "true"; |
|
961 + </getter> |
|
962 + <setter> |
|
963 + <![CDATA[ |
|
964 + if (val) |
|
965 + this.setAttribute("disabled", "true"); |
|
966 + else |
|
967 + this.removeAttribute("disabled"); |
|
968 + |
|
969 + if (!this.id) |
|
970 + return val; |
|
971 + |
|
972 + var elements = document.getElementsByAttribute("preference", this.id); |
|
973 + for (var i = 0; i < elements.length; ++i) { |
|
974 + elements[i].disabled = val; |
|
975 + |
|
976 + var labels = document.getElementsByAttribute("control", elements[i].id); |
|
977 + for (var j = 0; j < labels.length; ++j) |
|
978 + labels[j].disabled = val; |
|
979 + } |
|
980 + |
|
981 + return val; |
|
982 + ]]> |
|
983 + </setter> |
|
984 + </property> |
|
985 + |
|
986 + <property name="tabIndex"> |
|
987 + <getter> |
|
988 + return parseInt(this.getAttribute("tabindex")); |
|
989 + </getter> |
|
990 + <setter> |
|
991 + <![CDATA[ |
|
992 + if (val) |
|
993 + this.setAttribute("tabindex", val); |
|
994 + else |
|
995 + this.removeAttribute("tabindex"); |
|
996 + |
|
997 + if (!this.id) |
|
998 + return val; |
|
999 + |
|
1000 + var elements = document.getElementsByAttribute("preference", this.id); |
|
1001 + for (var i = 0; i < elements.length; ++i) { |
|
1002 + elements[i].tabIndex = val; |
|
1003 + |
|
1004 + var labels = document.getElementsByAttribute("control", elements[i].id); |
|
1005 + for (var j = 0; j < labels.length; ++j) |
|
1006 + labels[j].tabIndex = val; |
|
1007 + } |
|
1008 + |
|
1009 + return val; |
|
1010 + ]]> |
|
1011 + </setter> |
|
1012 + </property> |
|
1013 + |
|
1014 + <property name="hasUserValue"> |
|
1015 + <getter> |
|
1016 + <![CDATA[ |
|
1017 + return this.preferences.rootBranch.prefHasUserValue(this.name) && |
|
1018 + this.value !== undefined; |
|
1019 + ]]> |
|
1020 + </getter> |
|
1021 + </property> |
|
1022 + |
|
1023 + <method name="reset"> |
|
1024 + <body> |
|
1025 + // defer reset until preference update |
|
1026 + this.value = undefined; |
|
1027 + </body> |
|
1028 + </method> |
|
1029 + |
|
1030 + <field name="_useDefault">false</field> |
|
1031 + <property name="defaultValue"> |
|
1032 + <getter> |
|
1033 + <![CDATA[ |
|
1034 + this._useDefault = true; |
|
1035 + var val = this.valueFromPreferences; |
|
1036 + this._useDefault = false; |
|
1037 + return val; |
|
1038 + ]]> |
|
1039 + </getter> |
|
1040 + </property> |
|
1041 + |
|
1042 + <property name="_branch"> |
|
1043 + <getter> |
|
1044 + return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch; |
|
1045 + </getter> |
|
1046 + </property> |
|
1047 + |
|
1048 + <field name="batching">false</field> |
|
1049 + |
|
1050 + <method name="_reportUnknownType"> |
|
1051 + <body> |
|
1052 + <![CDATA[ |
|
1053 + var consoleService = Components.classes["@mozilla.org/consoleservice;1"] |
|
1054 + .getService(Components.interfaces.nsIConsoleService); |
|
1055 + var msg = "<preference> with id='" + this.id + "' and name='" + |
|
1056 + this.name + "' has unknown type '" + this.type + "'."; |
|
1057 + consoleService.logStringMessage(msg); |
|
1058 + ]]> |
|
1059 + </body> |
|
1060 + </method> |
|
1061 + |
|
1062 + <property name="valueFromPreferences"> |
|
1063 + <getter> |
|
1064 + <![CDATA[ |
|
1065 + try { |
|
1066 + // Force a resync of value with preferences. |
|
1067 + switch (this.type) { |
|
1068 + case "int": |
|
1069 + return this._branch.getIntPref(this.name); |
|
1070 + case "bool": |
|
1071 + var val = this._branch.getBoolPref(this.name); |
|
1072 + return this.inverted ? !val : val; |
|
1073 + case "wstring": |
|
1074 + return this._branch |
|
1075 + .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString) |
|
1076 + .data; |
|
1077 + case "string": |
|
1078 + case "unichar": |
|
1079 + return this._branch.getStringPref(this.name); |
|
1080 + case "fontname": |
|
1081 + var family = this._branch.getStringPref(this.name); |
|
1082 + var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"] |
|
1083 + .createInstance(Components.interfaces.nsIFontEnumerator); |
|
1084 + return fontEnumerator.getStandardFamilyName(family); |
|
1085 + case "file": |
|
1086 + var f = this._branch |
|
1087 + .getComplexValue(this.name, Components.interfaces.nsIFile); |
|
1088 + return f; |
|
1089 + default: |
|
1090 + this._reportUnknownType(); |
|
1091 + } |
|
1092 + } catch (e) { } |
|
1093 + return null; |
|
1094 + ]]> |
|
1095 + </getter> |
|
1096 + <setter> |
|
1097 + <![CDATA[ |
|
1098 + // Exit early if nothing to do. |
|
1099 + if (this.readonly || this.valueFromPreferences == val) |
|
1100 + return val; |
|
1101 + |
|
1102 + // The special value undefined means 'reset preference to default'. |
|
1103 + if (val === undefined) { |
|
1104 + this.preferences.rootBranch.clearUserPref(this.name); |
|
1105 + return val; |
|
1106 + } |
|
1107 + |
|
1108 + // Force a resync of preferences with value. |
|
1109 + switch (this.type) { |
|
1110 + case "int": |
|
1111 + this.preferences.rootBranch.setIntPref(this.name, val); |
|
1112 + break; |
|
1113 + case "bool": |
|
1114 + this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val); |
|
1115 + break; |
|
1116 + case "wstring": |
|
1117 + var pls = Components.classes["@mozilla.org/pref-localizedstring;1"] |
|
1118 + .createInstance(Components.interfaces.nsIPrefLocalizedString); |
|
1119 + pls.data = val; |
|
1120 + this.preferences.rootBranch |
|
1121 + .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls); |
|
1122 + break; |
|
1123 + case "string": |
|
1124 + case "unichar": |
|
1125 + case "fontname": |
|
1126 + this.preferences.rootBranch.setStringPref(this.name, val); |
|
1127 + break; |
|
1128 + case "file": |
|
1129 + var lf; |
|
1130 + if (typeof(val) == "string") { |
|
1131 + lf = Components.classes["@mozilla.org/file/local;1"] |
|
1132 + .createInstance(Components.interfaces.nsIFile); |
|
1133 + lf.persistentDescriptor = val; |
|
1134 + if (!lf.exists()) |
|
1135 + lf.initWithPath(val); |
|
1136 + } else |
|
1137 + lf = val.QueryInterface(Components.interfaces.nsIFile); |
|
1138 + this.preferences.rootBranch |
|
1139 + .setComplexValue(this.name, Components.interfaces.nsIFile, lf); |
|
1140 + break; |
|
1141 + default: |
|
1142 + this._reportUnknownType(); |
|
1143 + } |
|
1144 + if (!this.batching) |
|
1145 + this.preferences.service.savePrefFile(null); |
|
1146 + return val; |
|
1147 + ]]> |
|
1148 + </setter> |
|
1149 + </property> |
|
1150 + |
|
1151 + <method name="setElementValue"> |
|
1152 + <parameter name="aElement"/> |
|
1153 + <body> |
|
1154 + <![CDATA[ |
|
1155 + if (this.locked) |
|
1156 + aElement.disabled = true; |
|
1157 + |
|
1158 + if (!this.isElementEditable(aElement)) |
|
1159 + return; |
|
1160 + |
|
1161 + var rv = undefined; |
|
1162 + if (aElement.hasAttribute("onsyncfrompreference")) { |
|
1163 + // Value changed, synthesize an event |
|
1164 + try { |
|
1165 + var event = document.createEvent("Events"); |
|
1166 + event.initEvent("syncfrompreference", true, true); |
|
1167 + var f = new Function("event", |
|
1168 + aElement.getAttribute("onsyncfrompreference")); |
|
1169 + rv = f.call(aElement, event); |
|
1170 + } catch (e) { |
|
1171 + Components.utils.reportError(e); |
|
1172 + } |
|
1173 + } |
|
1174 + var val = rv; |
|
1175 + if (val === undefined) |
|
1176 + val = this.instantApply ? this.valueFromPreferences : this.value; |
|
1177 + // if the preference is marked for reset, show default value in UI |
|
1178 + if (val === undefined) |
|
1179 + val = this.defaultValue; |
|
1180 + |
|
1181 + /** |
|
1182 + * Initialize a UI element property with a value. Handles the case |
|
1183 + * where an element has not yet had a XBL binding attached for it and |
|
1184 + * the property setter does not yet exist by setting the same attribute |
|
1185 + * on the XUL element using DOM apis and assuming the element's |
|
1186 + * constructor or property getters appropriately handle this state. |
|
1187 + */ |
|
1188 + function setValue(element, attribute, value) { |
|
1189 + if (attribute in element) |
|
1190 + element[attribute] = value; |
|
1191 + else |
|
1192 + element.setAttribute(attribute, value); |
|
1193 + } |
|
1194 + if (aElement.localName == "checkbox" || |
|
1195 + aElement.localName == "listitem") |
|
1196 + setValue(aElement, "checked", val); |
|
1197 + else if (aElement.localName == "colorpicker") |
|
1198 + setValue(aElement, "color", val); |
|
1199 + else if (aElement.localName == "textbox") { |
|
1200 + // XXXmano Bug 303998: Avoid a caret placement issue if either the |
|
1201 + // preference observer or its setter calls updateElements as a result |
|
1202 + // of the input event handler. |
|
1203 + if (aElement.value !== val) |
|
1204 + setValue(aElement, "value", val); |
|
1205 + } else |
|
1206 + setValue(aElement, "value", val); |
|
1207 + ]]> |
|
1208 + </body> |
|
1209 + </method> |
|
1210 + |
|
1211 + <method name="getElementValue"> |
|
1212 + <parameter name="aElement"/> |
|
1213 + <body> |
|
1214 + <![CDATA[ |
|
1215 + if (aElement.hasAttribute("onsynctopreference")) { |
|
1216 + // Value changed, synthesize an event |
|
1217 + try { |
|
1218 + var event = document.createEvent("Events"); |
|
1219 + event.initEvent("synctopreference", true, true); |
|
1220 + var f = new Function("event", |
|
1221 + aElement.getAttribute("onsynctopreference")); |
|
1222 + var rv = f.call(aElement, event); |
|
1223 + if (rv !== undefined) |
|
1224 + return rv; |
|
1225 + } catch (e) { |
|
1226 + Components.utils.reportError(e); |
|
1227 + } |
|
1228 + } |
|
1229 + |
|
1230 + /** |
|
1231 + * Read the value of an attribute from an element, assuming the |
|
1232 + * attribute is a property on the element's node API. If the property |
|
1233 + * is not present in the API, then assume its value is contained in |
|
1234 + * an attribute, as is the case before a binding has been attached. |
|
1235 + */ |
|
1236 + function getValue(element, attribute) { |
|
1237 + if (attribute in element) |
|
1238 + return element[attribute]; |
|
1239 + return element.getAttribute(attribute); |
|
1240 + } |
|
1241 + if (aElement.localName == "checkbox" || |
|
1242 + aElement.localName == "listitem") |
|
1243 + var value = getValue(aElement, "checked"); |
|
1244 + else if (aElement.localName == "colorpicker") |
|
1245 + value = getValue(aElement, "color"); |
|
1246 + else |
|
1247 + value = getValue(aElement, "value"); |
|
1248 + |
|
1249 + switch (this.type) { |
|
1250 + case "int": |
|
1251 + return parseInt(value, 10) || 0; |
|
1252 + case "bool": |
|
1253 + return typeof(value) == "boolean" ? value : value == "true"; |
|
1254 + } |
|
1255 + return value; |
|
1256 + ]]> |
|
1257 + </body> |
|
1258 + </method> |
|
1259 + |
|
1260 + <method name="isElementEditable"> |
|
1261 + <parameter name="aElement"/> |
|
1262 + <body> |
|
1263 + <![CDATA[ |
|
1264 + switch (aElement.localName) { |
|
1265 + case "checkbox": |
|
1266 + case "colorpicker": |
|
1267 + case "radiogroup": |
|
1268 + case "textbox": |
|
1269 + case "listitem": |
|
1270 + case "listbox": |
|
1271 + case "menulist": |
|
1272 + return true; |
|
1273 + } |
|
1274 + return aElement.getAttribute("preference-editable") == "true"; |
|
1275 + ]]> |
|
1276 + </body> |
|
1277 + </method> |
|
1278 + |
|
1279 + <method name="updateElements"> |
|
1280 + <body> |
|
1281 + <![CDATA[ |
|
1282 + if (!this.id) |
|
1283 + return; |
|
1284 + |
|
1285 + // This "change" event handler tracks changes made to preferences by |
|
1286 + // sources other than the user in this window. |
|
1287 + var elements = document.getElementsByAttribute("preference", this.id); |
|
1288 + for (var i = 0; i < elements.length; ++i) |
|
1289 + this.setElementValue(elements[i]); |
|
1290 + ]]> |
|
1291 + </body> |
|
1292 + </method> |
|
1293 + </implementation> |
|
1294 + |
|
1295 + <handlers> |
|
1296 + <handler event="change"> |
|
1297 + this.updateElements(); |
|
1298 + </handler> |
|
1299 + </handlers> |
|
1300 + </binding> |
|
1301 + |
|
1302 + <binding id="prefwindow" |
|
1303 + extends="chrome://global/content/bindings/dialog.xml#dialog"> |
|
1304 + <resources> |
|
1305 + <stylesheet src="chrome://global/skin/preferences.css"/> |
|
1306 + </resources> |
|
1307 + <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY" |
|
1308 + closebuttonlabel="&preferencesCloseButton.label;" |
|
1309 + closebuttonaccesskey="&preferencesCloseButton.accesskey;" |
|
1310 + role="dialog" |
|
1311 +#ifdef XP_WIN |
|
1312 + title="&preferencesDefaultTitleWin.title;"> |
|
1313 +#else |
|
1314 + title="&preferencesDefaultTitleMac.title;"> |
|
1315 +#endif |
|
1316 + <xul:windowdragbox orient="vertical"> |
|
1317 + <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar" |
|
1318 + role="listbox"/> <!-- Expose to accessibility APIs as a listbox --> |
|
1319 + </xul:windowdragbox> |
|
1320 + <xul:hbox flex="1" class="paneDeckContainer"> |
|
1321 + <xul:deck anonid="paneDeck" flex="1"> |
|
1322 + <children includes="prefpane"/> |
|
1323 + </xul:deck> |
|
1324 + </xul:hbox> |
|
1325 + <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end"> |
|
1326 +#ifndef XP_UNIX |
|
1327 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> |
|
1328 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> |
|
1329 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> |
|
1330 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> |
|
1331 + <xul:spacer anonid="spacer" flex="1"/> |
|
1332 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> |
|
1333 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> |
|
1334 +#else |
|
1335 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> |
|
1336 + <xul:spacer anonid="spacer" flex="1"/> |
|
1337 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> |
|
1338 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> |
|
1339 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> |
|
1340 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> |
|
1341 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> |
|
1342 +#endif |
|
1343 + </xul:hbox> |
|
1344 + <xul:hbox> |
|
1345 + <children/> |
|
1346 + </xul:hbox> |
|
1347 + </content> |
|
1348 + <implementation implements="nsITimerCallback"> |
|
1349 + <constructor> |
|
1350 + <![CDATA[ |
|
1351 + if (this.type != "child") { |
|
1352 + if (!this._instantApplyInitialized) { |
|
1353 + let psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1354 + .getService(Components.interfaces.nsIPrefBranch); |
|
1355 + this.instantApply = psvc.getBoolPref("browser.preferences.instantApply"); |
|
1356 + } |
|
1357 + if (this.instantApply) { |
|
1358 + var docElt = document.documentElement; |
|
1359 + var acceptButton = docElt.getButton("accept"); |
|
1360 + acceptButton.hidden = true; |
|
1361 + var cancelButton = docElt.getButton("cancel"); |
|
1362 + if (/Mac/.test(navigator.platform)) { |
|
1363 + // no buttons on Mac except Help |
|
1364 + cancelButton.hidden = true; |
|
1365 + // Move Help button to the end |
|
1366 + document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true; |
|
1367 + // Also, don't fire onDialogAccept on enter |
|
1368 + acceptButton.disabled = true; |
|
1369 + } else { |
|
1370 + // morph the Cancel button into the Close button |
|
1371 + cancelButton.setAttribute("icon", "close"); |
|
1372 + cancelButton.label = docElt.getAttribute("closebuttonlabel"); |
|
1373 + cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey"); |
|
1374 + } |
|
1375 + } |
|
1376 + } |
|
1377 + this.setAttribute("animated", this._shouldAnimate ? "true" : "false"); |
|
1378 + var panes = this.preferencePanes; |
|
1379 + |
|
1380 + var lastPane = null; |
|
1381 + if (this.lastSelected) { |
|
1382 + lastPane = document.getElementById(this.lastSelected); |
|
1383 + if (!lastPane) { |
|
1384 + this.lastSelected = ""; |
|
1385 + } |
|
1386 + } |
|
1387 + |
|
1388 + var paneToLoad; |
|
1389 + if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") { |
|
1390 + paneToLoad = document.getElementById(window.arguments[0]); |
|
1391 + this.lastSelected = paneToLoad.id; |
|
1392 + } else if (lastPane) |
|
1393 + paneToLoad = lastPane; |
|
1394 + else |
|
1395 + paneToLoad = panes[0]; |
|
1396 + |
|
1397 + for (var i = 0; i < panes.length; ++i) { |
|
1398 + this._makePaneButton(panes[i]); |
|
1399 + if (panes[i].loaded) { |
|
1400 + // Inline pane content, fire load event to force initialization. |
|
1401 + this._fireEvent("paneload", panes[i]); |
|
1402 + } |
|
1403 + } |
|
1404 + this.showPane(paneToLoad); |
|
1405 + |
|
1406 + if (panes.length == 1) |
|
1407 + this._selector.setAttribute("collapsed", "true"); |
|
1408 + ]]> |
|
1409 + </constructor> |
|
1410 + |
|
1411 + <destructor> |
|
1412 + <![CDATA[ |
|
1413 + // Release timers to avoid reference cycles. |
|
1414 + if (this._animateTimer) { |
|
1415 + this._animateTimer.cancel(); |
|
1416 + this._animateTimer = null; |
|
1417 + } |
|
1418 + if (this._fadeTimer) { |
|
1419 + this._fadeTimer.cancel(); |
|
1420 + this._fadeTimer = null; |
|
1421 + } |
|
1422 + ]]> |
|
1423 + </destructor> |
|
1424 + |
|
1425 + <!-- Derived bindings can set this to true to cause us to skip |
|
1426 + reading the browser.preferences.instantApply pref in the constructor. |
|
1427 + Then they can set instantApply to their wished value. --> |
|
1428 + <field name="_instantApplyInitialized">false</field> |
|
1429 + <!-- Controls whether changed pref values take effect immediately. --> |
|
1430 + <field name="instantApply">false</field> |
|
1431 + |
|
1432 + <property name="preferencePanes" |
|
1433 + onget="return this.getElementsByTagName('prefpane');"/> |
|
1434 + |
|
1435 + <property name="type" onget="return this.getAttribute('type');"/> |
|
1436 + <property name="_paneDeck" |
|
1437 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/> |
|
1438 + <property name="_paneDeckContainer" |
|
1439 + onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/> |
|
1440 + <property name="_selector" |
|
1441 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/> |
|
1442 + <property name="lastSelected" |
|
1443 + onget="return this.getAttribute('lastSelected');"> |
|
1444 + <setter> |
|
1445 + this.setAttribute("lastSelected", val); |
|
1446 + document.persist(this.id, "lastSelected"); |
|
1447 + return val; |
|
1448 + </setter> |
|
1449 + </property> |
|
1450 + <property name="currentPane" |
|
1451 + onset="return this._currentPane = val;"> |
|
1452 + <getter> |
|
1453 + if (!this._currentPane) |
|
1454 + this._currentPane = this.preferencePanes[0]; |
|
1455 + |
|
1456 + return this._currentPane; |
|
1457 + </getter> |
|
1458 + </property> |
|
1459 + <field name="_currentPane">null</field> |
|
1460 + |
|
1461 + |
|
1462 + <method name="_makePaneButton"> |
|
1463 + <parameter name="aPaneElement"/> |
|
1464 + <body> |
|
1465 + <![CDATA[ |
|
1466 + var radio = document.createElement("radio"); |
|
1467 + radio.setAttribute("pane", aPaneElement.id); |
|
1468 + radio.setAttribute("label", aPaneElement.label); |
|
1469 + // Expose preference group choice to accessibility APIs as an unchecked list item |
|
1470 + // The parent group is exposed to accessibility APIs as a list |
|
1471 + if (aPaneElement.image) |
|
1472 + radio.setAttribute("src", aPaneElement.image); |
|
1473 + radio.style.listStyleImage = aPaneElement.style.listStyleImage; |
|
1474 + this._selector.appendChild(radio); |
|
1475 + return radio; |
|
1476 + ]]> |
|
1477 + </body> |
|
1478 + </method> |
|
1479 + |
|
1480 + <method name="showPane"> |
|
1481 + <parameter name="aPaneElement"/> |
|
1482 + <body> |
|
1483 + <![CDATA[ |
|
1484 + if (!aPaneElement) |
|
1485 + return; |
|
1486 + |
|
1487 + this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id); |
|
1488 + if (!aPaneElement.loaded) { |
|
1489 + let OverlayLoadObserver = function(aPane) { |
|
1490 + this._pane = aPane; |
|
1491 + } |
|
1492 + OverlayLoadObserver.prototype = { |
|
1493 + _outer: this, |
|
1494 + observe(aSubject, aTopic, aData) { |
|
1495 + this._pane.loaded = true; |
|
1496 + this._outer._fireEvent("paneload", this._pane); |
|
1497 + this._outer._selectPane(this._pane); |
|
1498 + } |
|
1499 + }; |
|
1500 + |
|
1501 + var obs = new OverlayLoadObserver(aPaneElement); |
|
1502 + document.loadOverlay(aPaneElement.src, obs); |
|
1503 + } else |
|
1504 + this._selectPane(aPaneElement); |
|
1505 + ]]> |
|
1506 + </body> |
|
1507 + </method> |
|
1508 + |
|
1509 + <method name="_fireEvent"> |
|
1510 + <parameter name="aEventName"/> |
|
1511 + <parameter name="aTarget"/> |
|
1512 + <body> |
|
1513 + <![CDATA[ |
|
1514 + // Panel loaded, synthesize a load event. |
|
1515 + try { |
|
1516 + var event = document.createEvent("Events"); |
|
1517 + event.initEvent(aEventName, true, true); |
|
1518 + var cancel = !aTarget.dispatchEvent(event); |
|
1519 + if (aTarget.hasAttribute("on" + aEventName)) { |
|
1520 + var fn = new Function("event", aTarget.getAttribute("on" + aEventName)); |
|
1521 + var rv = fn.call(aTarget, event); |
|
1522 + if (rv == false) |
|
1523 + cancel = true; |
|
1524 + } |
|
1525 + return !cancel; |
|
1526 + } catch (e) { |
|
1527 + Components.utils.reportError(e); |
|
1528 + } |
|
1529 + return false; |
|
1530 + ]]> |
|
1531 + </body> |
|
1532 + </method> |
|
1533 + |
|
1534 + <field name="_initialized">false</field> |
|
1535 + <method name="_selectPane"> |
|
1536 + <parameter name="aPaneElement"/> |
|
1537 + <body> |
|
1538 + <![CDATA[ |
|
1539 + if (/Mac/.test(navigator.platform)) { |
|
1540 + var paneTitle = aPaneElement.label; |
|
1541 + if (paneTitle != "") |
|
1542 + document.title = paneTitle; |
|
1543 + } |
|
1544 + var helpButton = document.documentElement.getButton("help"); |
|
1545 + if (aPaneElement.helpTopic) |
|
1546 + helpButton.hidden = false; |
|
1547 + else |
|
1548 + helpButton.hidden = true; |
|
1549 + |
|
1550 + // Find this pane's index in the deck and set the deck's |
|
1551 + // selectedIndex to that value to switch to it. |
|
1552 + var prefpanes = this.preferencePanes; |
|
1553 + for (var i = 0; i < prefpanes.length; ++i) { |
|
1554 + if (prefpanes[i] == aPaneElement) { |
|
1555 + this._paneDeck.selectedIndex = i; |
|
1556 + |
|
1557 + if (this.type != "child") { |
|
1558 + if (aPaneElement.hasAttribute("flex") && this._shouldAnimate && |
|
1559 + prefpanes.length > 1) |
|
1560 + aPaneElement.removeAttribute("flex"); |
|
1561 + // Calling sizeToContent after the first prefpane is loaded |
|
1562 + // will size the windows contents so style information is |
|
1563 + // available to calculate correct sizing. |
|
1564 + if (!this._initialized && prefpanes.length > 1) { |
|
1565 + if (this._shouldAnimate) |
|
1566 + this.style.minHeight = 0; |
|
1567 + window.sizeToContent(); |
|
1568 + } |
|
1569 + |
|
1570 + var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0]; |
|
1571 + oldPane.selected = !(aPaneElement.selected = true); |
|
1572 + this.lastSelected = aPaneElement.id; |
|
1573 + this.currentPane = aPaneElement; |
|
1574 + this._initialized = true; |
|
1575 + |
|
1576 + // Only animate if we've switched between prefpanes |
|
1577 + if (this._shouldAnimate && oldPane.id != aPaneElement.id) { |
|
1578 + aPaneElement.style.opacity = 0.0; |
|
1579 + this.animate(oldPane, aPaneElement); |
|
1580 + } else if (!this._shouldAnimate && prefpanes.length > 1) { |
|
1581 + var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height); |
|
1582 + var verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop); |
|
1583 + verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom); |
|
1584 + if (aPaneElement.contentHeight > targetHeight - verticalPadding) { |
|
1585 + // To workaround the bottom border of a groupbox from being |
|
1586 + // cutoff an hbox with a class of bottomBox may enclose it. |
|
1587 + // This needs to include its padding to resize properly. |
|
1588 + // See bug 394433 |
|
1589 + var bottomPadding = 0; |
|
1590 + var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0]; |
|
1591 + if (bottomBox) |
|
1592 + bottomPadding = parseInt(window.getComputedStyle(bottomBox).paddingBottom); |
|
1593 + window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight; |
|
1594 + } |
|
1595 + |
|
1596 + // XXX rstrong - extend the contents of the prefpane to |
|
1597 + // prevent elements from being cutoff (see bug 349098). |
|
1598 + if (aPaneElement.contentHeight + verticalPadding < targetHeight) |
|
1599 + aPaneElement._content.style.height = targetHeight - verticalPadding + "px"; |
|
1600 + } |
|
1601 + } |
|
1602 + break; |
|
1603 + } |
|
1604 + } |
|
1605 + ]]> |
|
1606 + </body> |
|
1607 + </method> |
|
1608 + |
|
1609 + <property name="_shouldAnimate"> |
|
1610 + <getter> |
|
1611 + <![CDATA[ |
|
1612 + var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1613 + .getService(Components.interfaces.nsIPrefBranch); |
|
1614 + return psvc.getBoolPref("browser.preferences.animateFadeIn", |
|
1615 + /Mac/.test(navigator.platform)); |
|
1616 + ]]> |
|
1617 + </getter> |
|
1618 + </property> |
|
1619 + |
|
1620 + <method name="animate"> |
|
1621 + <parameter name="aOldPane"/> |
|
1622 + <parameter name="aNewPane"/> |
|
1623 + <body> |
|
1624 + <![CDATA[ |
|
1625 + // if we are already resizing, use currentHeight |
|
1626 + var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight; |
|
1627 + |
|
1628 + this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1; |
|
1629 + var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight); |
|
1630 + this._animateRemainder = sizeDelta % this._animateIncrement; |
|
1631 + |
|
1632 + this._setUpAnimationTimer(oldHeight); |
|
1633 + ]]> |
|
1634 + </body> |
|
1635 + </method> |
|
1636 + |
|
1637 + <property name="_sizeIncrement"> |
|
1638 + <getter> |
|
1639 + <![CDATA[ |
|
1640 + var lastSelectedPane = document.getElementById(this.lastSelected); |
|
1641 + var increment = this._animateIncrement * this._multiplier; |
|
1642 + var newHeight = this._currentHeight + increment; |
|
1643 + if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) || |
|
1644 + (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight)) |
|
1645 + return 0; |
|
1646 + |
|
1647 + if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) || |
|
1648 + (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight)) |
|
1649 + increment = this._animateRemainder * this._multiplier; |
|
1650 + return increment; |
|
1651 + ]]> |
|
1652 + </getter> |
|
1653 + </property> |
|
1654 + |
|
1655 + <method name="notify"> |
|
1656 + <parameter name="aTimer"/> |
|
1657 + <body> |
|
1658 + <![CDATA[ |
|
1659 + if (!document) |
|
1660 + aTimer.cancel(); |
|
1661 + |
|
1662 + if (aTimer == this._animateTimer) { |
|
1663 + var increment = this._sizeIncrement; |
|
1664 + if (increment != 0) { |
|
1665 + window.innerHeight += increment; |
|
1666 + this._currentHeight += increment; |
|
1667 + } else { |
|
1668 + aTimer.cancel(); |
|
1669 + this._setUpFadeTimer(); |
|
1670 + } |
|
1671 + } else if (aTimer == this._fadeTimer) { |
|
1672 + var elt = document.getElementById(this.lastSelected); |
|
1673 + var newOpacity = parseFloat(window.getComputedStyle(elt).opacity) + this._fadeIncrement; |
|
1674 + if (newOpacity < 1.0) |
|
1675 + elt.style.opacity = newOpacity; |
|
1676 + else { |
|
1677 + aTimer.cancel(); |
|
1678 + elt.style.opacity = 1.0; |
|
1679 + } |
|
1680 + } |
|
1681 + ]]> |
|
1682 + </body> |
|
1683 + </method> |
|
1684 + |
|
1685 + <method name="_setUpAnimationTimer"> |
|
1686 + <parameter name="aStartHeight"/> |
|
1687 + <body> |
|
1688 + <![CDATA[ |
|
1689 + if (!this._animateTimer) |
|
1690 + this._animateTimer = Components.classes["@mozilla.org/timer;1"] |
|
1691 + .createInstance(Components.interfaces.nsITimer); |
|
1692 + else |
|
1693 + this._animateTimer.cancel(); |
|
1694 + this._currentHeight = aStartHeight; |
|
1695 + |
|
1696 + this._animateTimer.initWithCallback(this, this._animateDelay, |
|
1697 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); |
|
1698 + ]]> |
|
1699 + </body> |
|
1700 + </method> |
|
1701 + |
|
1702 + <method name="_setUpFadeTimer"> |
|
1703 + <body> |
|
1704 + <![CDATA[ |
|
1705 + if (!this._fadeTimer) |
|
1706 + this._fadeTimer = Components.classes["@mozilla.org/timer;1"] |
|
1707 + .createInstance(Components.interfaces.nsITimer); |
|
1708 + else |
|
1709 + this._fadeTimer.cancel(); |
|
1710 + |
|
1711 + this._fadeTimer.initWithCallback(this, this._fadeDelay, |
|
1712 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); |
|
1713 + ]]> |
|
1714 + </body> |
|
1715 + </method> |
|
1716 + |
|
1717 + <field name="_animateTimer">null</field> |
|
1718 + <field name="_fadeTimer">null</field> |
|
1719 + <field name="_animateDelay">15</field> |
|
1720 + <field name="_animateIncrement">40</field> |
|
1721 + <field name="_fadeDelay">5</field> |
|
1722 + <field name="_fadeIncrement">0.40</field> |
|
1723 + <field name="_animateRemainder">0</field> |
|
1724 + <field name="_currentHeight">0</field> |
|
1725 + <field name="_multiplier">0</field> |
|
1726 + |
|
1727 + <method name="addPane"> |
|
1728 + <parameter name="aPaneElement"/> |
|
1729 + <body> |
|
1730 + <![CDATA[ |
|
1731 + this.appendChild(aPaneElement); |
|
1732 + |
|
1733 + // Set up pane button |
|
1734 + this._makePaneButton(aPaneElement); |
|
1735 + ]]> |
|
1736 + </body> |
|
1737 + </method> |
|
1738 + |
|
1739 + <method name="openSubDialog"> |
|
1740 + <parameter name="aURL"/> |
|
1741 + <parameter name="aFeatures"/> |
|
1742 + <parameter name="aParams"/> |
|
1743 + <body> |
|
1744 + return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams); |
|
1745 + </body> |
|
1746 + </method> |
|
1747 + |
|
1748 + <method name="openWindow"> |
|
1749 + <parameter name="aWindowType"/> |
|
1750 + <parameter name="aURL"/> |
|
1751 + <parameter name="aFeatures"/> |
|
1752 + <parameter name="aParams"/> |
|
1753 + <body> |
|
1754 + <![CDATA[ |
|
1755 + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] |
|
1756 + .getService(Components.interfaces.nsIWindowMediator); |
|
1757 + var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null; |
|
1758 + if (win) { |
|
1759 + if ("initWithParams" in win) |
|
1760 + win.initWithParams(aParams); |
|
1761 + win.focus(); |
|
1762 + } else { |
|
1763 + var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : ""); |
|
1764 + var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener; |
|
1765 + win = parentWindow.openDialog(aURL, "_blank", features, aParams); |
|
1766 + } |
|
1767 + return win; |
|
1768 + ]]> |
|
1769 + </body> |
|
1770 + </method> |
|
1771 + </implementation> |
|
1772 + <handlers> |
|
1773 + <handler event="dialogaccept"> |
|
1774 + <![CDATA[ |
|
1775 + if (!this._fireEvent("beforeaccept", this)) { |
|
1776 + return false; |
|
1777 + } |
|
1778 + |
|
1779 + var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] |
|
1780 + .getService(Components.interfaces.nsIScriptSecurityManager); |
|
1781 + if (this.type == "child" && window.opener && |
|
1782 + secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) { |
|
1783 + var pdocEl = window.opener.document.documentElement; |
|
1784 + if (pdocEl.instantApply) { |
|
1785 + let panes = this.preferencePanes; |
|
1786 + for (let i = 0; i < panes.length; ++i) |
|
1787 + panes[i].writePreferences(true); |
|
1788 + } else { |
|
1789 + // Clone all the preferences elements from the child document and |
|
1790 + // insert them into the pane collection of the parent. |
|
1791 + var pdoc = window.opener.document; |
|
1792 + if (pdoc.documentElement.localName == "prefwindow") { |
|
1793 + var currentPane = pdoc.documentElement.currentPane; |
|
1794 + var id = window.location.href + "#childprefs"; |
|
1795 + var childPrefs = pdoc.getElementById(id); |
|
1796 + if (!childPrefs) { |
|
1797 + childPrefs = pdoc.createElement("preferences"); |
|
1798 + currentPane.appendChild(childPrefs); |
|
1799 + childPrefs.id = id; |
|
1800 + } |
|
1801 + let panes = this.preferencePanes; |
|
1802 + for (let i = 0; i < panes.length; ++i) { |
|
1803 + var preferences = panes[i].preferences; |
|
1804 + for (var j = 0; j < preferences.length; ++j) { |
|
1805 + // Try to find a preference element for the same preference. |
|
1806 + var preference = null; |
|
1807 + var parentPreferences = pdoc.getElementsByTagName("preferences"); |
|
1808 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) { |
|
1809 + var parentPrefs = parentPreferences[k] |
|
1810 + .getElementsByAttribute("name", preferences[j].name); |
|
1811 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) { |
|
1812 + if (parentPrefs[l].localName == "preference") |
|
1813 + preference = parentPrefs[l]; |
|
1814 + } |
|
1815 + } |
|
1816 + if (!preference) { |
|
1817 + // No matching preference in the parent window. |
|
1818 + preference = pdoc.createElement("preference"); |
|
1819 + childPrefs.appendChild(preference); |
|
1820 + preference.name = preferences[j].name; |
|
1821 + preference.type = preferences[j].type; |
|
1822 + preference.inverted = preferences[j].inverted; |
|
1823 + preference.readonly = preferences[j].readonly; |
|
1824 + preference.disabled = preferences[j].disabled; |
|
1825 + } |
|
1826 + preference.value = preferences[j].value; |
|
1827 + } |
|
1828 + } |
|
1829 + } |
|
1830 + } |
|
1831 + } else { |
|
1832 + let panes = this.preferencePanes; |
|
1833 + for (var i = 0; i < panes.length; ++i) |
|
1834 + panes[i].writePreferences(false); |
|
1835 + |
|
1836 + let psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1837 + .getService(Components.interfaces.nsIPrefService); |
|
1838 + psvc.savePrefFile(null); |
|
1839 + } |
|
1840 + |
|
1841 + return true; |
|
1842 + ]]> |
|
1843 + </handler> |
|
1844 + <handler event="command"> |
|
1845 + if (event.originalTarget.hasAttribute("pane")) { |
|
1846 + var pane = document.getElementById(event.originalTarget.getAttribute("pane")); |
|
1847 + this.showPane(pane); |
|
1848 + } |
|
1849 + </handler> |
|
1850 + |
|
1851 + <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing"> |
|
1852 + <![CDATA[ |
|
1853 + if (this.instantApply) |
|
1854 + window.close(); |
|
1855 + event.stopPropagation(); |
|
1856 + event.preventDefault(); |
|
1857 + ]]> |
|
1858 + </handler> |
|
1859 + |
|
1860 + <handler event="keypress" |
|
1861 +#ifdef XP_MACOSX |
|
1862 + key="&openHelpMac.commandkey;" modifiers="accel" |
|
1863 +#else |
|
1864 + keycode="&openHelp.commandkey;" |
|
1865 +#endif |
|
1866 + phase="capturing"> |
|
1867 + <![CDATA[ |
|
1868 + var helpButton = this.getButton("help"); |
|
1869 + if (helpButton.disabled || helpButton.hidden) |
|
1870 + return; |
|
1871 + this._fireEvent("dialoghelp", this); |
|
1872 + event.stopPropagation(); |
|
1873 + event.preventDefault(); |
|
1874 + ]]> |
|
1875 + </handler> |
|
1876 + </handlers> |
|
1877 + </binding> |
|
1878 + |
|
1879 + <binding id="prefpane"> |
|
1880 + <resources> |
|
1881 + <stylesheet src="chrome://global/skin/preferences.css"/> |
|
1882 + </resources> |
|
1883 + <content> |
|
1884 + <xul:vbox class="content-box" xbl:inherits="flex"> |
|
1885 + <children/> |
|
1886 + </xul:vbox> |
|
1887 + </content> |
|
1888 + <implementation> |
|
1889 + <method name="writePreferences"> |
|
1890 + <parameter name="aFlushToDisk"/> |
|
1891 + <body> |
|
1892 + <![CDATA[ |
|
1893 + // Write all values to preferences. |
|
1894 + if (this._deferredValueUpdateElements.size) { |
|
1895 + this._finalizeDeferredElements(); |
|
1896 + } |
|
1897 + |
|
1898 + var preferences = this.preferences; |
|
1899 + for (var i = 0; i < preferences.length; ++i) { |
|
1900 + var preference = preferences[i]; |
|
1901 + preference.batching = true; |
|
1902 + preference.valueFromPreferences = preference.value; |
|
1903 + preference.batching = false; |
|
1904 + } |
|
1905 + if (aFlushToDisk) { |
|
1906 + var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1907 + .getService(Components.interfaces.nsIPrefService); |
|
1908 + psvc.savePrefFile(null); |
|
1909 + } |
|
1910 + ]]> |
|
1911 + </body> |
|
1912 + </method> |
|
1913 + |
|
1914 + <property name="src" |
|
1915 + onget="return this.getAttribute('src');" |
|
1916 + onset="this.setAttribute('src', val); return val;"/> |
|
1917 + <property name="selected" |
|
1918 + onget="return this.getAttribute('selected') == 'true';" |
|
1919 + onset="this.setAttribute('selected', val); return val;"/> |
|
1920 + <property name="image" |
|
1921 + onget="return this.getAttribute('image');" |
|
1922 + onset="this.setAttribute('image', val); return val;"/> |
|
1923 + <property name="label" |
|
1924 + onget="return this.getAttribute('label');" |
|
1925 + onset="this.setAttribute('label', val); return val;"/> |
|
1926 + |
|
1927 + <property name="preferenceElements" |
|
1928 + onget="return this.getElementsByAttribute('preference', '*');"/> |
|
1929 + <property name="preferences" |
|
1930 + onget="return this.getElementsByTagName('preference');"/> |
|
1931 + |
|
1932 + <property name="helpTopic"> |
|
1933 + <getter> |
|
1934 + <![CDATA[ |
|
1935 + // if there are tabs, and the selected tab provides a helpTopic, return that |
|
1936 + var box = this.getElementsByTagName("tabbox"); |
|
1937 + if (box[0]) { |
|
1938 + var tab = box[0].selectedTab; |
|
1939 + if (tab && tab.hasAttribute("helpTopic")) |
|
1940 + return tab.getAttribute("helpTopic"); |
|
1941 + } |
|
1942 + |
|
1943 + // otherwise, return the helpTopic of the current panel |
|
1944 + return this.getAttribute("helpTopic"); |
|
1945 + ]]> |
|
1946 + </getter> |
|
1947 + </property> |
|
1948 + |
|
1949 + <field name="_loaded">false</field> |
|
1950 + <property name="loaded" |
|
1951 + onget="return !this.src ? true : this._loaded;" |
|
1952 + onset="this._loaded = val; return val;"/> |
|
1953 + |
|
1954 + <method name="preferenceForElement"> |
|
1955 + <parameter name="aElement"/> |
|
1956 + <body> |
|
1957 + return document.getElementById(aElement.getAttribute("preference")); |
|
1958 + </body> |
|
1959 + </method> |
|
1960 + |
|
1961 + <method name="getPreferenceElement"> |
|
1962 + <parameter name="aStartElement"/> |
|
1963 + <body> |
|
1964 + <![CDATA[ |
|
1965 + var temp = aStartElement; |
|
1966 + while (temp && temp.nodeType == Node.ELEMENT_NODE && |
|
1967 + !temp.hasAttribute("preference")) |
|
1968 + temp = temp.parentNode; |
|
1969 + return temp && temp.nodeType == Node.ELEMENT_NODE ? |
|
1970 + temp : aStartElement; |
|
1971 + ]]> |
|
1972 + </body> |
|
1973 + </method> |
|
1974 + |
|
1975 + <property name="DeferredTask" readonly="true"> |
|
1976 + <getter><![CDATA[ |
|
1977 + let module = {}; |
|
1978 + Components.utils.import("resource://gre/modules/DeferredTask.jsm", module); |
|
1979 + Object.defineProperty(this, "DeferredTask", { |
|
1980 + configurable: true, |
|
1981 + enumerable: true, |
|
1982 + writable: true, |
|
1983 + value: module.DeferredTask |
|
1984 + }); |
|
1985 + return module.DeferredTask; |
|
1986 + ]]></getter> |
|
1987 + </property> |
|
1988 + <method name="_deferredValueUpdate"> |
|
1989 + <parameter name="aElement"/> |
|
1990 + <body> |
|
1991 + <![CDATA[ |
|
1992 + delete aElement._deferredValueUpdateTask; |
|
1993 + let preference = document.getElementById(aElement.getAttribute("preference")); |
|
1994 + let prefVal = preference.getElementValue(aElement); |
|
1995 + preference.value = prefVal; |
|
1996 + this._deferredValueUpdateElements.delete(aElement); |
|
1997 + ]]> |
|
1998 + </body> |
|
1999 + </method> |
|
2000 + <field name="_deferredValueUpdateElements"> |
|
2001 + new Set(); |
|
2002 + </field> |
|
2003 + <method name="_finalizeDeferredElements"> |
|
2004 + <body> |
|
2005 + <![CDATA[ |
|
2006 + for (let el of this._deferredValueUpdateElements) { |
|
2007 + if (el._deferredValueUpdateTask) { |
|
2008 + el._deferredValueUpdateTask.finalize(); |
|
2009 + } |
|
2010 + } |
|
2011 + ]]> |
|
2012 + </body> |
|
2013 + </method> |
|
2014 + <method name="userChangedValue"> |
|
2015 + <parameter name="aElement"/> |
|
2016 + <body> |
|
2017 + <![CDATA[ |
|
2018 + let element = this.getPreferenceElement(aElement); |
|
2019 + if (element.hasAttribute("preference")) { |
|
2020 + if (element.getAttribute("delayprefsave") != "true") { |
|
2021 + var preference = document.getElementById(element.getAttribute("preference")); |
|
2022 + var prefVal = preference.getElementValue(element); |
|
2023 + preference.value = prefVal; |
|
2024 + } else { |
|
2025 + if (!element._deferredValueUpdateTask) { |
|
2026 + element._deferredValueUpdateTask = new this.DeferredTask(this._deferredValueUpdate.bind(this, element), 1000); |
|
2027 + this._deferredValueUpdateElements.add(element); |
|
2028 + } else { |
|
2029 + // Each time the preference is changed, restart the delay. |
|
2030 + element._deferredValueUpdateTask.disarm(); |
|
2031 + } |
|
2032 + element._deferredValueUpdateTask.arm(); |
|
2033 + } |
|
2034 + } |
|
2035 + ]]> |
|
2036 + </body> |
|
2037 + </method> |
|
2038 + |
|
2039 + <property name="contentHeight"> |
|
2040 + <getter> |
|
2041 + var targetHeight = parseInt(window.getComputedStyle(this._content).height); |
|
2042 + targetHeight += parseInt(window.getComputedStyle(this._content).marginTop); |
|
2043 + targetHeight += parseInt(window.getComputedStyle(this._content).marginBottom); |
|
2044 + return targetHeight; |
|
2045 + </getter> |
|
2046 + </property> |
|
2047 + <field name="_content"> |
|
2048 + document.getAnonymousElementByAttribute(this, "class", "content-box"); |
|
2049 + </field> |
|
2050 + </implementation> |
|
2051 + <handlers> |
|
2052 + <handler event="command"> |
|
2053 + // This "command" event handler tracks changes made to preferences by |
|
2054 + // the user in this window. |
|
2055 + if (event.sourceEvent) |
|
2056 + event = event.sourceEvent; |
|
2057 + this.userChangedValue(event.target); |
|
2058 + </handler> |
|
2059 + <handler event="select"> |
|
2060 + // This "select" event handler tracks changes made to colorpicker |
|
2061 + // preferences by the user in this window. |
|
2062 + if (event.target.localName == "colorpicker") |
|
2063 + this.userChangedValue(event.target); |
|
2064 + </handler> |
|
2065 + <handler event="change"> |
|
2066 + // This "change" event handler tracks changes made to preferences by |
|
2067 + // the user in this window. |
|
2068 + this.userChangedValue(event.target); |
|
2069 + </handler> |
|
2070 + <handler event="input"> |
|
2071 + // This "input" event handler tracks changes made to preferences by |
|
2072 + // the user in this window. |
|
2073 + this.userChangedValue(event.target); |
|
2074 + </handler> |
|
2075 + <handler event="paneload"> |
|
2076 + <![CDATA[ |
|
2077 + // Initialize all values from preferences. |
|
2078 + var elements = this.preferenceElements; |
|
2079 + for (var i = 0; i < elements.length; ++i) { |
|
2080 + try { |
|
2081 + var preference = this.preferenceForElement(elements[i]); |
|
2082 + preference.setElementValue(elements[i]); |
|
2083 + } catch (e) { |
|
2084 + dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n"); |
|
2085 + } |
|
2086 + } |
|
2087 + ]]> |
|
2088 + </handler> |
|
2089 + </handlers> |
|
2090 + </binding> |
|
2091 + |
|
2092 + <binding id="panebutton" role="xul:listitem" |
|
2093 + extends="chrome://global/content/bindings/radio.xml#radio"> |
|
2094 + <resources> |
|
2095 + <stylesheet src="chrome://global/skin/preferences.css"/> |
|
2096 + </resources> |
|
2097 + <content> |
|
2098 + <xul:image class="paneButtonIcon" xbl:inherits="src"/> |
|
2099 + <xul:label class="paneButtonLabel" xbl:inherits="value=label"/> |
|
2100 + </content> |
|
2101 + </binding> |
|
2102 + |
|
2103 +</bindings> |
|
2104 + |
|
2105 +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2106 +# This Source Code Form is subject to the terms of the Mozilla Public |
|
2107 +# License, v. 2.0. If a copy of the MPL was not distributed with this |
|
2108 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
2109 + |
|
2110 +# |
|
2111 +# This is PrefWindow 6. The Code Could Well Be Ready, Are You? |
|
2112 +# |
|
2113 +# Historical References: |
|
2114 +# PrefWindow V (February 1, 2003) |
|
2115 +# PrefWindow IV (April 24, 2000) |
|
2116 +# PrefWindow III (January 6, 2000) |
|
2117 +# PrefWindow II (???) |
|
2118 +# PrefWindow I (June 4, 1999) |
|
2119 +# |
|
2120 diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js |
674 diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js |
2121 --- a/toolkit/mozapps/downloads/nsHelperAppDlg.js |
675 --- a/toolkit/mozapps/downloads/nsHelperAppDlg.js |
2122 +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js |
676 +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js |
2123 @@ -626,17 +626,17 @@ nsUnknownContentTypeDialog.prototype = { |
677 @@ -626,17 +626,17 @@ nsUnknownContentTypeDialog.prototype = { |
2124 else |
678 else |