home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 July & August / PCWorld_2005-07-08_cd.bin / komunikace / netscape / nsb-install-8-0.exe / chrome / toolkit.jar / content / global / config.js < prev    next >
Text File  |  2004-11-25  |  16KB  |  510 lines

  1.  
  2. const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
  3. const nsISupportsString = Components.interfaces.nsISupportsString;
  4. const nsIPromptService = Components.interfaces.nsIPromptService;
  5. const nsIPrefService = Components.interfaces.nsIPrefService;
  6. const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
  7. const nsIClipboardHelper = Components.interfaces.nsIClipboardHelper;
  8. const nsIAtomService = Components.interfaces.nsIAtomService;
  9.  
  10. const nsSupportsString_CONTRACTID = "@mozilla.org/supports-string;1";
  11. const nsPrompt_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
  12. const nsPrefService_CONTRACTID = "@mozilla.org/preferences-service;1";
  13. const nsClipboardHelper_CONTRACTID = "@mozilla.org/widget/clipboardhelper;1";
  14. const nsAtomService_CONTRACTID = "@mozilla.org/atom-service;1";
  15.  
  16. const gPromptService = Components.classes[nsPrompt_CONTRACTID].getService(nsIPromptService);
  17. const gPrefService = Components.classes[nsPrefService_CONTRACTID].getService(nsIPrefService);
  18. const gPrefBranch = gPrefService.getBranch(null).QueryInterface(Components.interfaces.nsIPrefBranchInternal);
  19. const gClipboardHelper = Components.classes[nsClipboardHelper_CONTRACTID].getService(nsIClipboardHelper);
  20. const gAtomService = Components.classes[nsAtomService_CONTRACTID].getService(nsIAtomService);
  21.  
  22. var gLockAtoms = [gAtomService.getAtom("default"), gAtomService.getAtom("user"), gAtomService.getAtom("locked")];
  23. // we get these from a string bundle
  24. var gLockStrs = [];
  25. var gTypeStrs = [];
  26.  
  27. const PREF_IS_DEFAULT_VALUE = 0;
  28. const PREF_IS_USER_SET = 1;
  29. const PREF_IS_LOCKED = 2;
  30.  
  31. var gPrefHash = {};
  32. var gPrefArray = [];
  33. var gPrefView = gPrefArray; // share the JS array
  34. var gFastIndex = 0;
  35. var gSortedColumn = "prefCol";
  36. var gSortFunction = null;
  37. var gSortDirection = 1; // 1 is ascending; -1 is descending
  38. var gConfigBundle = null;
  39.  
  40. var view = {
  41.   get rowCount() { return gPrefView.length; },
  42.   getCellText : function(index, col) {
  43.     if (!(index in gPrefView))
  44.       return "";
  45.     
  46.     var value = gPrefView[index][col];
  47.  
  48.     switch (col) {
  49.       case "lockCol":           
  50.         return gLockStrs[value];
  51.       case "typeCol":
  52.         return gTypeStrs[value];
  53.       default:
  54.         return value;
  55.     }
  56.   },
  57.   getRowProperties : function(index, prop) {},
  58.   getCellProperties : function(index, col, prop) {
  59.     if (index in gPrefView)
  60.       prop.AppendElement(gLockAtoms[gPrefView[index].lockCol]);
  61.   },
  62.   getColumnProperties : function(col, elt, prop) {},
  63.   treebox : null,
  64.   selection : null,
  65.   isContainer : function(index) { return false; },
  66.   isContainerOpen : function(index) { return false; },
  67.   isContainerEmpty : function(index) { return false; },
  68.   isSorted : function() { return true; },
  69.   canDropOn : function(index) { return false; },
  70.   canDropBeforeAfter : function(index, before) { return false; },
  71.   drop : function(row,orientation) {},
  72.   setTree : function(out) { this.treebox = out; },
  73.   getParentIndex: function(rowIndex) { return -1; },
  74.   hasNextSibling: function(rowIndex, afterIndex) { return false; },
  75.   getLevel: function(index) { return 1; },
  76.   getImageSrc: function(row, colID) { return ""; },
  77.   toggleOpenState : function(index) {},
  78.   cycleHeader: function(colID, elt) {
  79.     var index = this.selection.currentIndex;
  80.     if (colID == gSortedColumn)
  81.       gSortDirection = -gSortDirection;
  82.     if (colID == gSortedColumn && gFastIndex == gPrefArray.length) {
  83.       gPrefArray.reverse();
  84.       if (gPrefView != gPrefArray)
  85.         gPrefView.reverse();
  86.       if (index >= 0)
  87.         index = gPrefView.length - index - 1;
  88.     }
  89.     else {
  90.       var pref = null;
  91.       if (index >= 0) {
  92.         if (gPrefArray != gPrefView)
  93.           index = gPrefView.length - index - 1;
  94.         else
  95.           pref = gPrefArray[index];
  96.       }
  97.       var old = document.getElementById(gSortedColumn);
  98.       old.setAttribute("sortDirection", "");
  99.       gPrefArray.sort(gSortFunction = gSortFunctions[colID]);
  100.       if (gPrefView != gPrefArray) {
  101.         if (colID == gSortedColumn)
  102.           gPrefView.reverse();
  103.         else
  104.           gPrefView.sort(gSortFunction);
  105.       }
  106.       gSortedColumn = colID;
  107.       if (pref)
  108.         index = getIndexOfPref(pref);
  109.     }
  110.     elt.setAttribute("sortDirection", gSortDirection > 0 ? "ascending" : "descending");
  111.     this.treebox.invalidate();
  112.     if (index >= 0) {
  113.       this.selection.select(index);
  114.       this.treebox.ensureRowIsVisible(index);
  115.     }
  116.     gFastIndex = gPrefArray.length;
  117.   },
  118.   selectionChanged : function() {},
  119.   cycleCell: function(row, colID) {},
  120.   isEditable: function(row, colID) {return false; },
  121.   setCellText: function(row, colID, value) {},
  122.   performAction: function(action) {},
  123.   performActionOnRow: function(action, row) {},
  124.   performActionOnCell: function(action, row, colID) {},
  125.   isSeparator: function(index) {return false; }
  126. };
  127.  
  128. // find the index in gPrefView of a pref object
  129. // or -1 if it does not exist in the filtered view
  130. function getViewIndexOfPref(pref)
  131. {
  132.   var low = -1, high = gPrefView.length;
  133.   var index = (low + high) >> 1;
  134.   while (index > low) {
  135.     var mid = gPrefView[index];
  136.     if (mid == pref)
  137.       return index;
  138.     if (gSortFunction(mid, pref) < 0)
  139.       low = index;
  140.     else
  141.       high = index;
  142.     index = (low + high) >> 1;
  143.   }
  144.   return -1;
  145. }
  146.  
  147. // find the index in gPrefArray of a pref object
  148. // either one that was looked up in gPrefHash
  149. // or in case it was moved after sorting
  150. function getIndexOfPref(pref)
  151. {
  152.   var low = -1, high = gFastIndex;
  153.   var index = (low + high) >> 1;
  154.   while (index > low) {
  155.     var mid = gPrefArray[index];
  156.     if (mid == pref)
  157.       return index;
  158.     if (gSortFunction(mid, pref) < 0)
  159.       low = index;
  160.     else
  161.       high = index;
  162.     index = (low + high) >> 1;
  163.   }
  164.  
  165.   for (index = gFastIndex; index < gPrefArray.length; ++index)
  166.     if (gPrefArray[index] == pref)
  167.       break;
  168.   return index;
  169. }
  170.  
  171. function getNearestIndexOfPref(pref)
  172. {
  173.   var low = -1, high = gFastIndex;
  174.   var index = (low + high) >> 1;
  175.   while (index > low) {
  176.     if (gSortFunction(gPrefArray[index], pref) < 0)
  177.       low = index;
  178.     else
  179.       high = index;
  180.     index = (low + high) >> 1;
  181.   }
  182.   return high;
  183. }
  184.  
  185. var gPrefListener =
  186. {
  187.   observe: function(subject, topic, prefName)
  188.   {
  189.     if (topic != "nsPref:changed")
  190.       return;
  191.  
  192.     if (/^capability\./.test(prefName)) // avoid displaying "private" preferences
  193.       return;
  194.  
  195.     var index = gPrefArray.length;
  196.     if (prefName in gPrefHash) {
  197.       index = getViewIndexOfPref(gPrefHash[prefName]);
  198.       fetchPref(prefName, getIndexOfPref(gPrefHash[prefName]));
  199.       if (index >= 0) {
  200.         // Might need to update the filtered view
  201.         gPrefView[index] = gPrefHash[prefName];
  202.         view.treebox.invalidateRow(index);
  203.       }
  204.       if (gSortedColumn == "lockCol" || gSortedColumn == "valueCol")
  205.         gFastIndex = 1; // TODO: reinsert and invalidate range
  206.     } else {
  207.       fetchPref(prefName, index);
  208.       if (index == gFastIndex) {
  209.         // Keep the array sorted by reinserting the pref object
  210.         var pref = gPrefArray.pop();
  211.         index = getNearestIndexOfPref(pref);
  212.         gPrefArray.splice(index, 0, pref);
  213.         gFastIndex = gPrefArray.length;
  214.       }
  215.       if (gPrefView == gPrefArray)
  216.         view.treebox.rowCountChanged(index, 1);
  217.     }
  218.   }
  219. };
  220.  
  221. function prefObject(prefName, prefIndex)
  222. {
  223.   this.prefCol = prefName;
  224. }
  225.  
  226. prefObject.prototype =
  227. {
  228.   lockCol: PREF_IS_DEFAULT_VALUE,
  229.   typeCol: nsIPrefBranch.PREF_STRING,
  230.   valueCol: ""
  231. };
  232.  
  233. function fetchPref(prefName, prefIndex)
  234. {
  235.   var pref = new prefObject(prefName);
  236.  
  237.   gPrefHash[prefName] = pref;
  238.   gPrefArray[prefIndex] = pref;
  239.  
  240.   if (gPrefBranch.prefIsLocked(prefName))
  241.     pref.lockCol = PREF_IS_LOCKED;
  242.   else if (gPrefBranch.prefHasUserValue(prefName))
  243.     pref.lockCol = PREF_IS_USER_SET;
  244.  
  245.   try {
  246.     switch (gPrefBranch.getPrefType(prefName)) {
  247.       case gPrefBranch.PREF_BOOL:
  248.         pref.typeCol = gPrefBranch.PREF_BOOL;
  249.         // convert to a string
  250.         pref.valueCol = gPrefBranch.getBoolPref(prefName).toString();
  251.         break;
  252.       case gPrefBranch.PREF_INT:
  253.         pref.typeCol = gPrefBranch.PREF_INT;
  254.         // convert to a string
  255.         pref.valueCol = gPrefBranch.getIntPref(prefName).toString();
  256.         break;
  257.       default:
  258.       case gPrefBranch.PREF_STRING:
  259.         pref.valueCol = gPrefBranch.getComplexValue(prefName, nsISupportsString).data;
  260.         // Try in case it's a localized string (will throw an exception if not)
  261.         if (pref.lockCol == PREF_IS_DEFAULT_VALUE &&
  262.             /^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.valueCol))
  263.           pref.valueCol = gPrefBranch.getComplexValue(prefName, nsIPrefLocalizedString).data;
  264.         break;
  265.     }
  266.   } catch (e) {
  267.     // Also catch obscure cases in which you can't tell in advance
  268.     // that the pref exists but has no user or default value...
  269.   }
  270. }
  271.  
  272. function onConfigLoad()
  273. {
  274.   // Load strings
  275.   gConfigBundle = document.getElementById("configBundle");
  276.   document.title = gConfigBundle.getString("title");
  277.  
  278.   gLockStrs[PREF_IS_DEFAULT_VALUE] = gConfigBundle.getString("default");
  279.   gLockStrs[PREF_IS_USER_SET] = gConfigBundle.getString("user");
  280.   gLockStrs[PREF_IS_LOCKED] = gConfigBundle.getString("locked");
  281.  
  282.   gTypeStrs[nsIPrefBranch.PREF_STRING] = gConfigBundle.getString("string");
  283.   gTypeStrs[nsIPrefBranch.PREF_INT] = gConfigBundle.getString("int");
  284.   gTypeStrs[nsIPrefBranch.PREF_BOOL] = gConfigBundle.getString("bool");
  285.  
  286.   var prefCount = { value: 0 };
  287.   var prefArray = gPrefBranch.getChildList("", prefCount);
  288.  
  289.   for (var i = 0; i < prefCount.value; ++i) 
  290.   {
  291.     var prefName = prefArray[i];
  292.     if (/^capability\./.test(prefName)) // avoid displaying "private" preferences
  293.       continue;
  294.  
  295.     fetchPref(prefName, gPrefArray.length);
  296.   }
  297.  
  298.   var descending = document.getElementsByAttribute("sortDirection", "descending");
  299.   if (descending.length) {
  300.     gSortedColumn = descending[0].id;
  301.     gSortDirection = -1;
  302.   }
  303.   else {
  304.     var ascending = document.getElementsByAttribute("sortDirection", "ascending");
  305.     if (ascending.length)
  306.       gSortedColumn = ascending[0].id;
  307.     else
  308.       document.getElementById(gSortedColumn).setAttribute("sortDirection", "ascending");
  309.   }
  310.   gSortFunction = gSortFunctions[gSortedColumn];
  311.   gPrefArray.sort(gSortFunction);
  312.   gFastIndex = gPrefArray.length;
  313.   
  314.   gPrefBranch.addObserver("", gPrefListener, false);
  315.  
  316.   document.getElementById("configTree").view = view;
  317.   
  318.   document.getElementById("textbox").focus();
  319. }
  320.  
  321. function onConfigUnload()
  322. {
  323.   gPrefBranch.removeObserver("", gPrefListener);
  324.   document.getElementById("configTree").view = null;
  325. }
  326.  
  327. function FilterPrefs()
  328. {
  329.   var substring = document.getElementById("textbox").value.toLowerCase();
  330.   var prefCol = view.selection.currentIndex < 0 ? null : gPrefView[view.selection.currentIndex].prefCol;
  331.   var array = gPrefView;
  332.   gPrefView = gPrefArray;
  333.   if (substring) {
  334.     gPrefView = [];
  335.     for (var i = 0; i < gPrefArray.length; ++i)
  336.       if (gPrefArray[i].prefCol.toLowerCase().indexOf(substring) >= 0)
  337.         gPrefView.push(gPrefArray[i]);
  338.     if (gFastIndex < gPrefArray.length)
  339.       gPrefView.sort(gSortFunction);
  340.   }
  341.   view.treebox.invalidate();
  342.   view.treebox.rowCountChanged(array.length, gPrefView.length - array.length);
  343.   gotoPref(prefCol);
  344.   document.getElementById("button").disabled = !substring;
  345. }
  346.  
  347. function ClearFilter(button)
  348. {
  349.   var textbox = document.getElementById("textbox");
  350.   textbox.value = "";
  351.   textbox.focus();
  352.   FilterPrefs();
  353. }
  354.  
  355. function prefColSortFunction(x, y)
  356. {
  357.   if (x.prefCol > y.prefCol)
  358.     return gSortDirection;
  359.   if (x.prefCol < y.prefCol) 
  360.     return -gSortDirection;
  361.   return 0;
  362. }
  363.  
  364. function lockColSortFunction(x, y)
  365. {
  366.   if (x.lockCol != y.lockCol)
  367.     return gSortDirection * (y.lockCol - x.lockCol);
  368.   return prefColSortFunction(x, y);
  369. }
  370.  
  371. function typeColSortFunction(x, y)
  372. {
  373.   if (x.typeCol != y.typeCol) 
  374.     return gSortDirection * (y.typeCol - x.typeCol);
  375.   return prefColSortFunction(x, y);
  376. }
  377.  
  378. function valueColSortFunction(x, y)
  379. {
  380.   if (x.valueCol > y.valueCol)
  381.     return gSortDirection;
  382.   if (x.valueCol < y.valueCol) 
  383.     return -gSortDirection;
  384.   return prefColSortFunction(x, y);
  385. }
  386.  
  387. const gSortFunctions =
  388. {
  389.   prefCol: prefColSortFunction, 
  390.   lockCol: lockColSortFunction, 
  391.   typeCol: typeColSortFunction, 
  392.   valueCol: valueColSortFunction
  393. };
  394.  
  395. function updateContextMenu()
  396. {
  397.   var lockCol = PREF_IS_LOCKED;
  398.   var typeCol = nsIPrefBranch.PREF_STRING;
  399.   var valueCol = "";
  400.   var copyDisabled = true;
  401.  
  402.   if (view.selection.currentIndex >= 0) {
  403.     var prefRow = gPrefView[view.selection.currentIndex];
  404.     lockCol = prefRow.lockCol;
  405.     typeCol = prefRow.typeCol;
  406.     valueCol = prefRow.valueCol;
  407.     copyDisabled = false;
  408.   }
  409.  
  410.   var copyName = document.getElementById("copyName");
  411.   copyName.setAttribute("disabled", copyDisabled);
  412.  
  413.   var copyValue = document.getElementById("copyValue");
  414.   copyValue.setAttribute("disabled", copyDisabled);
  415.  
  416.   var resetSelected = document.getElementById("resetSelected");
  417.   resetSelected.setAttribute("disabled", lockCol != PREF_IS_USER_SET);
  418.  
  419.   var canToggle = typeCol == nsIPrefBranch.PREF_BOOL && valueCol != "";
  420.  
  421.   var modifySelected = document.getElementById("modifySelected");
  422.   modifySelected.setAttribute("disabled", lockCol == PREF_IS_LOCKED);
  423.   modifySelected.hidden = canToggle;
  424.  
  425.   var toggleSelected = document.getElementById("toggleSelected");
  426.   toggleSelected.setAttribute("disabled", lockCol == PREF_IS_LOCKED);
  427.   toggleSelected.hidden = !canToggle;
  428. }
  429.  
  430. function copyName()
  431. {
  432.   gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].prefCol);
  433. }
  434.  
  435. function copyValue()
  436. {
  437.   gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].valueCol);
  438. }
  439.  
  440. function ModifySelected()
  441. {
  442.   if (view.selection.currentIndex >= 0)
  443.     ModifyPref(gPrefView[view.selection.currentIndex]);
  444. }
  445.  
  446. function ResetSelected()
  447. {
  448.   var entry = gPrefView[view.selection.currentIndex];
  449.   gPrefBranch.clearUserPref(entry.prefCol);
  450. }
  451.  
  452. function NewPref(type)
  453. {
  454.   var result = { value: "" };
  455.   var dummy = { value: 0 };
  456.   if (gPromptService.prompt(window,
  457.                             gConfigBundle.getFormattedString("new_title", [gTypeStrs[type]]),
  458.                             gConfigBundle.getString("new_prompt"),
  459.                             result,
  460.                             null,
  461.                             dummy)) {
  462.     var pref;
  463.     if (result.value in gPrefHash)
  464.       pref = gPrefHash[result.value];
  465.     else
  466.       pref = { prefCol: result.value, lockCol: PREF_IS_DEFAULT_VALUE, typeCol: type, valueCol: "" };
  467.     if (ModifyPref(pref))
  468.       setTimeout(gotoPref, 0, result.value);
  469.   }
  470. }
  471.  
  472. function gotoPref(pref)
  473. {
  474.   // make sure the pref exists and is displayed in the current view
  475.   var index = pref in gPrefHash ? getViewIndexOfPref(gPrefHash[pref]) : -1;
  476.   if (index >= 0) {
  477.     view.selection.select(index);
  478.     view.treebox.ensureRowIsVisible(index);
  479.   } else {
  480.     view.selection.clearSelection();
  481.     view.selection.currentIndex = -1;
  482.   }
  483. }
  484.  
  485. function ModifyPref(entry)
  486. {
  487.   if (entry.lockCol == PREF_IS_LOCKED)
  488.     return false;
  489.   var title = gConfigBundle.getFormattedString("modify_title", [gTypeStrs[entry.typeCol]]);
  490.   if (entry.typeCol == nsIPrefBranch.PREF_BOOL) {
  491.     var check = { value: entry.valueCol == "false" };
  492.     if (!entry.valueCol && !gPromptService.select(window, title, entry.prefCol, 2, [false, true], check))
  493.       return false;
  494.     gPrefBranch.setBoolPref(entry.prefCol, check.value);
  495.   } else {
  496.     var result = { value: entry.valueCol };
  497.     var dummy = { value: 0 };
  498.     if (!gPromptService.prompt(window, title, entry.prefCol, result, null, dummy))
  499.       return false;
  500.     if (entry.typeCol == nsIPrefBranch.PREF_INT) {
  501.       gPrefBranch.setIntPref(entry.prefCol, parseInt(result.value, 10));
  502.     } else {
  503.       var supportsString = Components.classes[nsSupportsString_CONTRACTID].createInstance(nsISupportsString);
  504.       supportsString.data = result.value;
  505.       gPrefBranch.setComplexValue(entry.prefCol, nsISupportsString, supportsString);
  506.     }
  507.   }
  508.   return true;
  509. }
  510.