home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / 01_03.iso / software / ghostzilla_hit / files / ghostzilla-1.0-plus-install.exe / chrome / toolkit.jar / content / global / filepicker.js < prev    next >
Encoding:
Text File  |  2002-05-13  |  16.7 KB  |  581 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is mozilla.org code.
  14.  *
  15.  * The Initial Developer of the Original Code is Netscape Communications
  16.  * Corporation.  Portions created by Netscape are
  17.  * Copyright (C) 2000 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s): 
  21.  *  Stuart Parmenter <pavlov@netscape.com>
  22.  *  Brian Ryner <bryner@netscape.com>
  23.  *  Jan Varga <varga@utcru.sk>
  24.  *  Peter Annema <disttsc@bart.nl>
  25.  */
  26.  
  27. const nsIFilePicker       = Components.interfaces.nsIFilePicker;
  28. const nsIDirectoryServiceProvider = Components.interfaces.nsIDirectoryServiceProvider;
  29. const nsIDirectoryServiceProvider_CONTRACTID = "@mozilla.org/file/directory_service;1";
  30. const nsITreeBoxObject = Components.interfaces.nsITreeBoxObject;
  31. const nsIFileView = Components.interfaces.nsIFileView;
  32. const nsFileView_CONTRACTID = "@mozilla.org/filepicker/fileview;1";
  33. const nsITreeView = Components.interfaces.nsITreeView;
  34. const nsILocalFile = Components.interfaces.nsILocalFile;
  35. const nsLocalFile_CONTRACTID = "@mozilla.org/file/local;1";
  36.  
  37. var sfile = Components.classes[nsLocalFile_CONTRACTID].createInstance(nsILocalFile);
  38. var retvals;
  39. var filePickerMode;
  40. var homeDir;
  41. var treeView;
  42.  
  43. var textInput;
  44. var okButton;
  45.  
  46. var gFilePickerBundle;
  47.  
  48. function filepickerLoad() {
  49.   gFilePickerBundle = document.getElementById("bundle_filepicker");
  50.  
  51.   textInput = document.getElementById("textInput");
  52.   okButton = document.documentElement.getButton("accept");
  53.   treeView = Components.classes[nsFileView_CONTRACTID].createInstance(nsIFileView);
  54.  
  55.   if (window.arguments) {
  56.     var o = window.arguments[0];
  57.     retvals = o.retvals; /* set this to a global var so we can set return values */
  58.     const title = o.title;
  59.     filePickerMode = o.mode;
  60.     if (o.displayDirectory) {
  61.       const directory = o.displayDirectory.path;
  62.     }
  63.     const initialText = o.defaultString;
  64.     const filterTitles = o.filters.titles;
  65.     const filterTypes = o.filters.types;
  66.     const numFilters = filterTitles.length;
  67.  
  68.     window.title = title;
  69.  
  70.     if (initialText) {
  71.       textInput.value = initialText;
  72.     }
  73.   }
  74.  
  75.   if ((filePickerMode == nsIFilePicker.modeOpen) ||
  76.       (filePickerMode == nsIFilePicker.modeSave)) {
  77.  
  78.     treeView.setFilter(filterTypes[0]);
  79.  
  80.     /* build filter popup */
  81.     var filterPopup = document.createElement("menupopup");
  82.  
  83.     for (var i = 0; i < numFilters; i++) {
  84.       var menuItem = document.createElement("menuitem");
  85.       menuItem.setAttribute("label", filterTitles[i] + " (" + filterTypes[i] + ")");
  86.       menuItem.setAttribute("filters", filterTypes[i]);
  87.       filterPopup.appendChild(menuItem);
  88.     }
  89.  
  90.     var filterMenuList = document.getElementById("filterMenuList");
  91.     filterMenuList.appendChild(filterPopup);
  92.     if (numFilters > 0)
  93.       filterMenuList.selectedIndex = 0;
  94.     var filterBox = document.getElementById("filterBox");
  95.     filterBox.removeAttribute("hidden");
  96.  
  97.     filterMenuList.selectedIndex = o.filterIndex;
  98.   } else if (filePickerMode == nsIFilePicker.modeGetFolder) {
  99.     treeView.showOnlyDirectories = true;
  100.   }
  101.  
  102.   // start out with a filename sort
  103.   handleColumnClick("FilenameColumn");
  104.  
  105.   document.documentElement.setAttribute("ondialogcancel", "return onCancel();");
  106.   try {
  107.     var buttonLabel = getOKAction();
  108.     okButton.setAttribute("label", buttonLabel);
  109.   } catch (exception) {
  110.     // keep it set to "OK"
  111.   }
  112.  
  113.   // setup the dialogOverlay.xul button handlers
  114.   retvals.buttonStatus = nsIFilePicker.returnCancel;
  115.  
  116.   var tree = document.getElementById("directoryTree");
  117.   tree.treeBoxObject.view = treeView;
  118.  
  119.   // Start out with the ok button disabled since nothing will be
  120.   // selected and nothing will be in the text field.
  121.   okButton.disabled = true;
  122.   textInput.focus();
  123.  
  124.   // This allows the window to show onscreen before we begin
  125.   // loading the file list
  126.  
  127.   setTimeout(setInitialDirectory, 0, directory);
  128. }
  129.  
  130. function setInitialDirectory(directory)
  131. {
  132.   // get the home dir
  133.   var dirServiceProvider = Components.classes[nsIDirectoryServiceProvider_CONTRACTID]
  134.                                      .getService(nsIDirectoryServiceProvider);
  135.   var persistent = new Object();
  136.   homeDir = dirServiceProvider.getFile("Home", persistent);
  137.  
  138.   if (directory) {
  139.     sfile.initWithPath(directory);
  140.   }
  141.   if (!directory || !(sfile.exists() && sfile.isDirectory())) {
  142.     // Start in the user's home directory
  143.     sfile.initWithPath(homeDir.path);
  144.   }
  145.  
  146.   gotoDirectory(sfile);
  147. }
  148.  
  149. function onFilterChanged(target)
  150. {
  151.   // Do this on a timeout callback so the filter list can roll up
  152.   // and we don't keep the mouse grabbed while we are refiltering.
  153.  
  154.   setTimeout(changeFilter, 0, target.getAttribute("filters"));
  155. }
  156.  
  157. function changeFilter(filterTypes)
  158. {
  159.   window.setCursor("wait");
  160.   treeView.setFilter(filterTypes);
  161.   window.setCursor("auto");
  162. }
  163.  
  164. function showFilePermissionsErrorDialog(titleStrName, messageStrName, file)
  165. {
  166.   var errorTitle =
  167.     gFilePickerBundle.getFormattedString(titleStrName, [file.path]);
  168.   var errorMessage =
  169.     gFilePickerBundle.getFormattedString(messageStrName, [file.path]);
  170.   var promptService =
  171.     Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  172.  
  173.   promptService.alert(window, errorTitle, errorMessage)
  174. }
  175.  
  176. function openOnOK()
  177. {
  178.   var dir = treeView.getSelectedFile();
  179.   if (!dir.isReadable()) {
  180.     showFilePermissionsErrorDialog("errorOpenFileDoesntExistTitle",
  181.                                    "errorDirNotReadableMessage",
  182.                                    dir);
  183.     return false;
  184.   }
  185.  
  186.   if (dir)
  187.     gotoDirectory(dir);
  188.   retvals.file = dir;
  189.   retvals.buttonStatus = nsIFilePicker.returnCancel;
  190.   
  191.   var filterMenuList = document.getElementById("filterMenuList");
  192.   retvals.filterIndex = filterMenuList.selectedIndex;
  193.   
  194.   return false;
  195. }
  196.  
  197. function selectOnOK()
  198. {
  199.   var errorTitle, errorMessage, promptService;
  200.   var ret = nsIFilePicker.returnCancel;
  201.  
  202.   var isDir = false;
  203.   var isFile = false;
  204.  
  205.   var input = textInput.value;
  206.   if (input[0] == '~') // XXX XP?
  207.     input  = homeDir.path + input.substring(1);
  208.  
  209.   var file = sfile.clone().QueryInterface(nsILocalFile);
  210.   if (!file)
  211.     return false;
  212.  
  213.   /* XXX we need an XP way to test for an absolute path! */
  214.   if (input[0] == '/')   /* an absolute path was entered */
  215.     file.initWithPath(input);
  216.   else if ((input.indexOf("/../") > 0) ||
  217.            (input.substr(-3) == "/..") ||
  218.            (input.substr(0,3) == "../") ||
  219.            (input == "..")) {
  220.     /* appendRelativePath doesn't allow .. */
  221.     file.initWithPath(file.path + "/" + input);
  222.     file.normalize();
  223.   }
  224.   else {
  225.     try {
  226.       file.appendRelativePath(input);
  227.     } catch (e) {
  228.       dump("Can't append relative path '"+input+"':\n");
  229.       return false;
  230.     }
  231.   }
  232.  
  233.   if (!file.exists() && (filePickerMode != nsIFilePicker.modeSave)) {
  234.     showFilePermissionsErrorDialog("errorOpenFileDoesntExistTitle",
  235.                                    "errorOpenFileDoesntExistMessage",
  236.                                    file);
  237.     return false;
  238.   }
  239.  
  240.   if (file.exists()) {
  241.     isDir = file.isDirectory();
  242.     isFile = file.isFile();
  243.   }
  244.  
  245.   switch(filePickerMode) {
  246.   case nsIFilePicker.modeOpen:
  247.     if (isFile) {
  248.       if (file.isReadable()) {
  249.         retvals.directory = file.parent.path;
  250.         ret = nsIFilePicker.returnOK;
  251.       } else {
  252.         showFilePermissionsErrorDialog("errorOpeningFileTitle",
  253.                                        "openWithoutPermissionMessage_file",
  254.                                        file);
  255.         ret = nsIFilePicker.returnCancel;
  256.       }
  257.     } else if (isDir) {
  258.       if (!sfile.equals(file)) {
  259.         gotoDirectory(file);
  260.       }
  261.       textInput.value = "";
  262.       doEnabling();
  263.       ret = nsIFilePicker.returnCancel;
  264.     }
  265.     break;
  266.   case nsIFilePicker.modeSave:
  267.     if (isFile) { // can only be true if file.exists()
  268.       if (!file.isWritable()) {
  269.         showFilePermissionsErrorDialog("errorSavingFileTitle",
  270.                                        "saveWithoutPermissionMessage_file",
  271.                                        file);
  272.         ret = nsIFilePicker.returnCancel;
  273.       } else {
  274.         // we need to pop up a dialog asking if you want to save
  275.         var message =
  276.           gFilePickerBundle.getFormattedString("confirmFileReplacing",
  277.                                                [file.path]);
  278.  
  279.         var rv = window.confirm(message);
  280.         if (rv) {
  281.           ret = nsIFilePicker.returnReplace;
  282.           retvals.directory = file.parent.path;
  283.         } else {
  284.           ret = nsIFilePicker.returnCancel;
  285.         }
  286.       }
  287.     } else if (isDir) {
  288.       if (!sfile.equals(file)) {
  289.         gotoDirectory(file);
  290.       }
  291.       textInput.value = "";
  292.       doEnabling();
  293.       ret = nsIFilePicker.returnCancel;
  294.     } else {
  295.       var parent = file.parent;
  296.       if (parent.exists() && parent.isDirectory() && parent.isWritable()) {
  297.         ret = nsIFilePicker.returnOK;
  298.         retvals.directory = parent.path;
  299.       } else {
  300.         var oldParent = parent;
  301.         while (!parent.exists()) {
  302.           oldParent = parent;
  303.           parent = parent.parent;
  304.         }
  305.         var errorTitle =
  306.           gFilePickerBundle.getFormattedString("errorSavingFileTitle",
  307.                                                [file.path]);
  308.         var errorMessage;
  309.         if (parent.isFile()) {
  310.           errorMessage =
  311.             gFilePickerBundle.getFormattedString("saveParentIsFileMessage",
  312.                                                  [parent.path, file.path]);
  313.         } else {
  314.           errorMessage =
  315.             gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage",
  316.                                                  [oldParent.path, file.path]);
  317.         }
  318.         if (!parent.isWritable()) {
  319.           errorMessage =
  320.             gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]);
  321.         }
  322.         promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
  323.                                   .getService(Components.interfaces.nsIPromptService);
  324.         promptService.alert(window, errorTitle, errorMessage);
  325.         ret = nsIFilePicker.returnCancel;
  326.       }
  327.     }
  328.     break;
  329.   case nsIFilePicker.modeGetFolder:
  330.     if (isDir) {
  331.       retvals.directory = file.parent.path;
  332.     } else { // if nothing selected, the current directory will be fine
  333.       retvals.directory = sfile.path;
  334.     }
  335.     ret = nsIFilePicker.returnOK;
  336.     break;
  337.   }
  338.  
  339.   retvals.file = file;
  340.   retvals.buttonStatus = ret;
  341.  
  342.   var filterMenuList = document.getElementById("filterMenuList");
  343.   retvals.filterIndex = filterMenuList.selectedIndex;
  344.   
  345.   return (ret != nsIFilePicker.returnCancel);
  346. }
  347.  
  348. function onCancel()
  349. {
  350.   // Close the window.
  351.   retvals.buttonStatus = nsIFilePicker.returnCancel;
  352.   retvals.file = null;
  353.   return true;
  354. }
  355.  
  356. function onDblClick(e) {
  357.   var t = e.originalTarget;
  358.   if (t.localName != "treechildren")
  359.     return;
  360.  
  361.   openSelectedFile();
  362. }
  363.  
  364. function openSelectedFile() {
  365.   var file = treeView.getSelectedFile();
  366.   if (!file)
  367.     return;
  368.  
  369.   if (file.isDirectory())
  370.     gotoDirectory(file);
  371.   else if (file.isFile())
  372.     document.documentElement.acceptDialog();
  373. }
  374.  
  375. function onClick(e) {
  376.   var t = e.originalTarget;
  377.   if (t.localName == "treecol")
  378.     handleColumnClick(t.id);
  379. }
  380.  
  381. function convertColumnIDtoSortType(columnID) {
  382.   var sortKey;
  383.   
  384.   switch (columnID) {
  385.   case "FilenameColumn":
  386.     sortKey = nsIFileView.sortName;
  387.     break;
  388.   case "FileSizeColumn":
  389.     sortKey = nsIFileView.sortSize;
  390.     break;
  391.   case "LastModifiedColumn":
  392.     sortKey = nsIFileView.sortDate;
  393.     break;
  394.   default:
  395.     dump("unsupported sort column: " + columnID + "\n");
  396.     sortKey = 0;
  397.     break;
  398.   }
  399.   
  400.   return sortKey;
  401. }
  402.  
  403. function handleColumnClick(columnID) {
  404.   var sortType = convertColumnIDtoSortType(columnID);
  405.   var sortOrder = (treeView.sortType == sortType) ? !treeView.reverseSort : false;
  406.   treeView.sort(sortType, sortOrder);
  407.   
  408.   // set the sort indicator on the column we are sorted by
  409.   var sortedColumn = document.getElementById(columnID);
  410.   if (treeView.reverseSort) {
  411.     sortedColumn.setAttribute("sortDirection", "descending");
  412.   } else {
  413.     sortedColumn.setAttribute("sortDirection", "ascending");
  414.   }
  415.   
  416.   // remove the sort indicator from the rest of the columns
  417.   var currCol = sortedColumn.parentNode.firstChild;
  418.   while (currCol) {
  419.     if (currCol != sortedColumn && currCol.localName == "treecol")
  420.       currCol.removeAttribute("sortDirection");
  421.     currCol = currCol.nextSibling;
  422.   }
  423. }
  424.  
  425. function onKeypress(e) {
  426.   if (e.keyCode == 8) /* backspace */
  427.     goUp();
  428.   else if (e.keyCode == 13) { /* enter */
  429.     var file = treeView.getSelectedFile();
  430.     if (file) {
  431.       if (file.isDirectory()) {
  432.         gotoDirectory(file);
  433.         e.preventDefault();
  434.       }
  435.     }
  436.   }
  437. }
  438.  
  439. function doEnabling() {
  440.   // Maybe add check if textInput.value would resolve to an existing
  441.   // file or directory in .modeOpen. Too costly I think.
  442.   var enable = (textInput.value != "");
  443.  
  444.   okButton.disabled = !enable;
  445. }
  446.  
  447. function onTreeFocus(event) {
  448.   // Reset the button label and enabled/disabled state.
  449.   onFileSelected(treeView.getSelectedFile());
  450. }
  451.  
  452. function getOKAction(file) {
  453.   var buttonLabel;
  454.  
  455.   if (file && file.isDirectory() && filePickerMode != nsIFilePicker.modeGetFolder) {
  456.     document.documentElement.setAttribute("ondialogaccept", "return openOnOK();");
  457.     buttonLabel = gFilePickerBundle.getString("openButtonLabel");
  458.   }
  459.   else {
  460.     document.documentElement.setAttribute("ondialogaccept", "return selectOnOK();");
  461.     switch(filePickerMode) {
  462.     case nsIFilePicker.modeGetFolder:
  463.       buttonLabel = gFilePickerBundle.getString("selectFolderButtonLabel");
  464.       break;
  465.     case nsIFilePicker.modeOpen:
  466.       buttonLabel = gFilePickerBundle.getString("openButtonLabel");
  467.       break;
  468.     case nsIFilePicker.modeSave:
  469.       buttonLabel = gFilePickerBundle.getString("saveButtonLabel");
  470.       break;
  471.     }
  472.   }
  473.  
  474.   return buttonLabel;
  475. }
  476.  
  477. function onSelect(event) {
  478.   onFileSelected(treeView.getSelectedFile());
  479. }
  480.  
  481. function onFileSelected(file) {
  482.   if (file) {
  483.     var path = file.leafName;
  484.     
  485.     if (path) {
  486.       if ((filePickerMode == nsIFilePicker.modeGetFolder) || !file.isDirectory())
  487.         textInput.value = path;
  488.       
  489.       var buttonLabel = getOKAction(file);
  490.       okButton.setAttribute("label", buttonLabel);
  491.       okButton.disabled = false;
  492.       return;
  493.     }
  494.   }
  495.  
  496.   okButton.disabled = (textInput.value == "");
  497. }
  498.  
  499. function onTextFieldFocus() {
  500.   var buttonLabel = getOKAction(null);
  501.   okButton.setAttribute("label", buttonLabel);
  502.   doEnabling();
  503. }
  504.  
  505. function onDirectoryChanged(target)
  506. {
  507.   var path = target.getAttribute("label");
  508.  
  509.   var file = Components.classes[nsLocalFile_CONTRACTID].createInstance(nsILocalFile);
  510.   file.initWithPath(path);
  511.  
  512.   if (!sfile.equals(file)) {
  513.     // Do this on a timeout callback so the directory list can roll up
  514.     // and we don't keep the mouse grabbed while we are loading.
  515.  
  516.     setTimeout(gotoDirectory, 0, file);
  517.   }
  518. }
  519.  
  520. function populateAncestorList(directory) {
  521.   var menu = document.getElementById("lookInMenu");
  522.  
  523.   while (menu.hasChildNodes()) {
  524.     menu.removeChild(menu.firstChild);
  525.   }
  526.   
  527.   var menuItem = document.createElement("menuitem");
  528.   menuItem.setAttribute("label", directory.path);
  529.   menuItem.setAttribute("crop", "start");
  530.   menu.appendChild(menuItem);
  531.  
  532.   // .parent is _sometimes_ null, see bug 121489.  Do a dance around that.
  533.   var parent = directory.parent;
  534.   while (parent && !parent.equals(directory)) {
  535.     menuItem = document.createElement("menuitem");
  536.     menuItem.setAttribute("label", parent.path);
  537.     menuItem.setAttribute("crop", "start");
  538.     menu.appendChild(menuItem);
  539.     directory = parent;
  540.     parent = directory.parent;
  541.   }
  542.   
  543.   var menuList = document.getElementById("lookInMenuList");
  544.   menuList.selectedIndex = 0;
  545. }
  546.  
  547. function goUp() {
  548.   try {
  549.     var parent = sfile.parent;
  550.   } catch(ex) { dump("can't get parent directory\n"); }
  551.  
  552.   if (parent) {
  553.     gotoDirectory(parent);
  554.   }
  555. }
  556.  
  557. function goHome() {
  558.   gotoDirectory(homeDir);
  559. }
  560.  
  561. function gotoDirectory(directory) {
  562.   window.setCursor("wait");
  563.   try {
  564.     populateAncestorList(directory);
  565.     treeView.setDirectory(directory);
  566.     document.getElementById("errorShower").selectedIndex = 0;
  567.   } catch(ex) {
  568.     document.getElementById("errorShower").selectedIndex = 1;
  569.   }
  570.  
  571.   window.setCursor("auto");
  572.  
  573.   treeView.QueryInterface(nsITreeView).selection.clearSelection();
  574.   textInput.focus();
  575.   sfile = directory;
  576. }
  577.  
  578. function toggleShowHidden(event) {
  579.   treeView.showHiddenFiles = !treeView.showHiddenFiles;
  580. }
  581.