diff options
Diffstat (limited to 'toolkit/components/filepicker/content')
-rw-r--r-- | toolkit/components/filepicker/content/filepicker.js | 833 | ||||
-rw-r--r-- | toolkit/components/filepicker/content/filepicker.xul | 80 |
2 files changed, 913 insertions, 0 deletions
diff --git a/toolkit/components/filepicker/content/filepicker.js b/toolkit/components/filepicker/content/filepicker.js new file mode 100644 index 000000000..6f91066ba --- /dev/null +++ b/toolkit/components/filepicker/content/filepicker.js @@ -0,0 +1,833 @@ +// -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const nsIFilePicker = Components.interfaces.nsIFilePicker; +const nsIProperties = Components.interfaces.nsIProperties; +const NS_DIRECTORYSERVICE_CONTRACTID = "@mozilla.org/file/directory_service;1"; +const NS_IOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1"; +const nsIFileView = Components.interfaces.nsIFileView; +const NS_FILEVIEW_CONTRACTID = "@mozilla.org/filepicker/fileview;1"; +const nsITreeView = Components.interfaces.nsITreeView; +const nsILocalFile = Components.interfaces.nsILocalFile; +const nsIFile = Components.interfaces.nsIFile; +const NS_LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1"; +const NS_PROMPTSERVICE_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1"; + +var sfile = Components.classes[NS_LOCAL_FILE_CONTRACTID].createInstance(nsILocalFile); +var retvals; +var filePickerMode; +var homeDir; +var treeView; +var allowURLs; + +var textInput; +var okButton; + +var gFilePickerBundle; + +// name of new directory entered by the user to be remembered +// for next call of newDir() in case something goes wrong with creation +var gNewDirName = { value: "" }; + +function filepickerLoad() { + gFilePickerBundle = document.getElementById("bundle_filepicker"); + + textInput = document.getElementById("textInput"); + okButton = document.documentElement.getButton("accept"); + treeView = Components.classes[NS_FILEVIEW_CONTRACTID].createInstance(nsIFileView); + + if (window.arguments) { + var o = window.arguments[0]; + retvals = o.retvals; /* set this to a global var so we can set return values */ + const title = o.title; + filePickerMode = o.mode; + if (o.displayDirectory) { + var directory = o.displayDirectory.path; + } + + const initialText = o.defaultString; + var filterTitles = o.filters.titles; + var filterTypes = o.filters.types; + var numFilters = filterTitles.length; + + document.title = title; + allowURLs = o.allowURLs; + + if (initialText) { + textInput.value = initialText; + } + } + + if (filePickerMode != nsIFilePicker.modeOpen && filePickerMode != nsIFilePicker.modeOpenMultiple) { + var newDirButton = document.getElementById("newDirButton"); + newDirButton.removeAttribute("hidden"); + } + + if (filePickerMode == nsIFilePicker.modeGetFolder) { + var textInputLabel = document.getElementById("textInputLabel"); + textInputLabel.value = gFilePickerBundle.getString("dirTextInputLabel"); + textInputLabel.accessKey = gFilePickerBundle.getString("dirTextInputAccesskey"); + } + + if ((filePickerMode == nsIFilePicker.modeOpen) || + (filePickerMode == nsIFilePicker.modeOpenMultiple) || + (filePickerMode == nsIFilePicker.modeSave)) { + + /* build filter popup */ + var filterPopup = document.createElement("menupopup"); + + for (var i = 0; i < numFilters; i++) { + var menuItem = document.createElement("menuitem"); + if (filterTypes[i] == "..apps") + menuItem.setAttribute("label", filterTitles[i]); + else + menuItem.setAttribute("label", filterTitles[i] + " (" + filterTypes[i] + ")"); + menuItem.setAttribute("filters", filterTypes[i]); + filterPopup.appendChild(menuItem); + } + + var filterMenuList = document.getElementById("filterMenuList"); + filterMenuList.appendChild(filterPopup); + if (numFilters > 0) + filterMenuList.selectedIndex = 0; + var filterBox = document.getElementById("filterBox"); + filterBox.removeAttribute("hidden"); + + filterMenuList.selectedIndex = o.filterIndex; + + treeView.setFilter(filterTypes[o.filterIndex]); + + } else if (filePickerMode == nsIFilePicker.modeGetFolder) { + treeView.showOnlyDirectories = true; + } + + // The dialog defaults to an "open" icon, change it to "save" if applicable + if (filePickerMode == nsIFilePicker.modeSave) + okButton.setAttribute("icon", "save"); + + // start out with a filename sort + handleColumnClick("FilenameColumn"); + + try { + setOKAction(); + } catch (exception) { + // keep it set to "OK" + } + + // setup the dialogOverlay.xul button handlers + retvals.buttonStatus = nsIFilePicker.returnCancel; + + var tree = document.getElementById("directoryTree"); + if (filePickerMode == nsIFilePicker.modeOpenMultiple) + tree.removeAttribute("seltype"); + + tree.view = treeView; + + // Start out with the ok button disabled since nothing will be + // selected and nothing will be in the text field. + okButton.disabled = filePickerMode != nsIFilePicker.modeGetFolder; + + // This allows the window to show onscreen before we begin + // loading the file list + + setTimeout(setInitialDirectory, 0, directory); +} + +function setInitialDirectory(directory) +{ + // Start in the user's home directory + var dirService = Components.classes[NS_DIRECTORYSERVICE_CONTRACTID] + .getService(nsIProperties); + homeDir = dirService.get("Home", Components.interfaces.nsIFile); + + if (directory) { + sfile.initWithPath(directory); + if (!sfile.exists() || !sfile.isDirectory()) + directory = false; + } + if (!directory) { + sfile.initWithPath(homeDir.path); + } + + gotoDirectory(sfile); +} + +function onFilterChanged(target) +{ + // Do this on a timeout callback so the filter list can roll up + // and we don't keep the mouse grabbed while we are refiltering. + + setTimeout(changeFilter, 0, target.getAttribute("filters")); +} + +function changeFilter(filterTypes) +{ + window.setCursor("wait"); + treeView.setFilter(filterTypes); + window.setCursor("auto"); +} + +function showErrorDialog(titleStrName, messageStrName, file) +{ + var errorTitle = + gFilePickerBundle.getFormattedString(titleStrName, [file.path]); + var errorMessage = + gFilePickerBundle.getFormattedString(messageStrName, [file.path]); + var promptService = + Components.classes[NS_PROMPTSERVICE_CONTRACTID].getService(Components.interfaces.nsIPromptService); + + promptService.alert(window, errorTitle, errorMessage); +} + +function openOnOK() +{ + var dir = treeView.selectedFiles.queryElementAt(0, nsIFile); + if (dir) + gotoDirectory(dir); + + return false; +} + +function selectOnOK() +{ + var errorTitle, errorMessage, promptService; + var ret = nsIFilePicker.returnOK; + + var isDir = false; + var isFile = false; + + retvals.filterIndex = document.getElementById("filterMenuList").selectedIndex; + retvals.fileURL = null; + + if (allowURLs) { + try { + var ios = Components.classes[NS_IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService); + retvals.fileURL = ios.newURI(textInput.value, null, null); + let fileList = []; + if (retvals.fileURL instanceof Components.interfaces.nsIFileURL) + fileList.push(retvals.fileURL.file); + gFilesEnumerator.mFiles = fileList; + retvals.files = gFilesEnumerator; + retvals.buttonStatus = ret; + + return true; + } catch (e) { + } + } + + var fileList = processPath(textInput.value); + if (!fileList) { + // generic error message, should probably never happen + showErrorDialog("errorPathProblemTitle", + "errorPathProblemMessage", + textInput.value); + return false; + } + + var curFileIndex; + for (curFileIndex = 0; curFileIndex < fileList.length && + ret != nsIFilePicker.returnCancel; ++curFileIndex) { + var file = fileList[curFileIndex].QueryInterface(nsIFile); + + // try to normalize - if this fails we will ignore the error + // because we will notice the + // error later and show a fitting error alert. + try { + file.normalize(); + } catch (e) { + // promptService.alert(window, "Problem", "normalize failed, continuing"); + } + + var fileExists = file.exists(); + + if (!fileExists && (filePickerMode == nsIFilePicker.modeOpen || + filePickerMode == nsIFilePicker.modeOpenMultiple)) { + showErrorDialog("errorOpenFileDoesntExistTitle", + "errorOpenFileDoesntExistMessage", + file); + return false; + } + + if (!fileExists && filePickerMode == nsIFilePicker.modeGetFolder) { + showErrorDialog("errorDirDoesntExistTitle", + "errorDirDoesntExistMessage", + file); + return false; + } + + if (fileExists) { + isDir = file.isDirectory(); + isFile = file.isFile(); + } + + switch (filePickerMode) { + case nsIFilePicker.modeOpen: + case nsIFilePicker.modeOpenMultiple: + if (isFile) { + if (file.isReadable()) { + retvals.directory = file.parent.path; + } else { + showErrorDialog("errorOpeningFileTitle", + "openWithoutPermissionMessage_file", + file); + ret = nsIFilePicker.returnCancel; + } + } else if (isDir) { + if (!sfile.equals(file)) { + gotoDirectory(file); + } + textInput.value = ""; + doEnabling(); + ret = nsIFilePicker.returnCancel; + } + break; + case nsIFilePicker.modeSave: + if (isFile) { // can only be true if file.exists() + if (!file.isWritable()) { + showErrorDialog("errorSavingFileTitle", + "saveWithoutPermissionMessage_file", + file); + ret = nsIFilePicker.returnCancel; + } else { + // we need to pop up a dialog asking if you want to save + var confirmTitle = gFilePickerBundle.getString("confirmTitle"); + var message = + gFilePickerBundle.getFormattedString("confirmFileReplacing", + [file.path]); + + promptService = Components.classes[NS_PROMPTSERVICE_CONTRACTID].getService(Components.interfaces.nsIPromptService); + var rv = promptService.confirm(window, confirmTitle, message); + if (rv) { + ret = nsIFilePicker.returnReplace; + retvals.directory = file.parent.path; + } else { + ret = nsIFilePicker.returnCancel; + } + } + } else if (isDir) { + if (!sfile.equals(file)) { + gotoDirectory(file); + } + textInput.value = ""; + doEnabling(); + ret = nsIFilePicker.returnCancel; + } else { + var parent = file.parent; + if (parent.exists() && parent.isDirectory() && parent.isWritable()) { + retvals.directory = parent.path; + } else { + var oldParent = parent; + while (!parent.exists()) { + oldParent = parent; + parent = parent.parent; + } + errorTitle = + gFilePickerBundle.getFormattedString("errorSavingFileTitle", + [file.path]); + if (parent.isFile()) { + errorMessage = + gFilePickerBundle.getFormattedString("saveParentIsFileMessage", + [parent.path, file.path]); + } else { + errorMessage = + gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage", + [oldParent.path, file.path]); + } + if (!parent.isWritable()) { + errorMessage = + gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]); + } + promptService = Components.classes[NS_PROMPTSERVICE_CONTRACTID].getService(Components.interfaces.nsIPromptService); + promptService.alert(window, errorTitle, errorMessage); + ret = nsIFilePicker.returnCancel; + } + } + break; + case nsIFilePicker.modeGetFolder: + if (isDir) { + retvals.directory = file.parent.path; + } else { // if nothing selected, the current directory will be fine + retvals.directory = sfile.path; + } + break; + } + } + + gFilesEnumerator.mFiles = fileList; + + retvals.files = gFilesEnumerator; + retvals.buttonStatus = ret; + + return (ret != nsIFilePicker.returnCancel); +} + +var gFilesEnumerator = { + mFiles: null, + mIndex: 0, + + hasMoreElements: function() + { + return (this.mIndex < this.mFiles.length); + }, + getNext: function() + { + if (this.mIndex >= this.mFiles.length) + throw Components.results.NS_ERROR_FAILURE; + return this.mFiles[this.mIndex++]; + } +}; + +function onCancel() +{ + // Close the window. + retvals.buttonStatus = nsIFilePicker.returnCancel; + retvals.file = null; + retvals.files = null; + return true; +} + +function onDblClick(e) { + // we only care about button 0 (left click) events + if (e.button != 0) return; + + var t = e.originalTarget; + if (t.localName != "treechildren") + return; + + openSelectedFile(); +} + +function openSelectedFile() { + var fileList = treeView.selectedFiles; + if (fileList.length == 0) + return; + + var file = fileList.queryElementAt(0, nsIFile); + if (file.isDirectory()) + gotoDirectory(file); + else if (file.isFile()) + document.documentElement.acceptDialog(); +} + +function onClick(e) { + var t = e.originalTarget; + if (t.localName == "treecol") + handleColumnClick(t.id); +} + +function convertColumnIDtoSortType(columnID) { + var sortKey; + + switch (columnID) { + case "FilenameColumn": + sortKey = nsIFileView.sortName; + break; + case "FileSizeColumn": + sortKey = nsIFileView.sortSize; + break; + case "LastModifiedColumn": + sortKey = nsIFileView.sortDate; + break; + default: + dump("unsupported sort column: " + columnID + "\n"); + sortKey = 0; + break; + } + + return sortKey; +} + +function handleColumnClick(columnID) { + var sortType = convertColumnIDtoSortType(columnID); + var sortOrder = (treeView.sortType == sortType) ? !treeView.reverseSort : false; + treeView.sort(sortType, sortOrder); + + // set the sort indicator on the column we are sorted by + var sortedColumn = document.getElementById(columnID); + if (treeView.reverseSort) { + sortedColumn.setAttribute("sortDirection", "descending"); + } else { + sortedColumn.setAttribute("sortDirection", "ascending"); + } + + // remove the sort indicator from the rest of the columns + var currCol = sortedColumn.parentNode.firstChild; + while (currCol) { + if (currCol != sortedColumn && currCol.localName == "treecol") + currCol.removeAttribute("sortDirection"); + currCol = currCol.nextSibling; + } +} + +function onKeypress(e) { + if (e.keyCode == 8) /* backspace */ + goUp(); + + /* enter is handled by the ondialogaccept handler */ +} + +function doEnabling() { + if (filePickerMode != nsIFilePicker.modeGetFolder) + // Maybe add check if textInput.value would resolve to an existing + // file or directory in .modeOpen. Too costly I think. + okButton.disabled = (textInput.value == "") +} + +function onTreeFocus(event) { + // Reset the button label and enabled/disabled state. + onFileSelected(treeView.selectedFiles); +} + +function setOKAction(file) { + var buttonLabel; + var buttonIcon = "open"; // used in all but one case + + if (file && file.isDirectory()) { + document.documentElement.setAttribute("ondialogaccept", "return openOnOK();"); + buttonLabel = gFilePickerBundle.getString("openButtonLabel"); + } + else { + document.documentElement.setAttribute("ondialogaccept", "return selectOnOK();"); + switch (filePickerMode) { + case nsIFilePicker.modeGetFolder: + buttonLabel = gFilePickerBundle.getString("selectFolderButtonLabel"); + break; + case nsIFilePicker.modeOpen: + case nsIFilePicker.modeOpenMultiple: + buttonLabel = gFilePickerBundle.getString("openButtonLabel"); + break; + case nsIFilePicker.modeSave: + buttonLabel = gFilePickerBundle.getString("saveButtonLabel"); + buttonIcon = "save"; + break; + } + } + okButton.setAttribute("label", buttonLabel); + okButton.setAttribute("icon", buttonIcon); +} + +function onSelect(event) { + onFileSelected(treeView.selectedFiles); +} + +function onFileSelected(/* nsIArray */ selectedFileList) { + var validFileSelected = false; + var invalidSelection = false; + var file; + var fileCount = selectedFileList.length; + + for (var index = 0; index < fileCount; ++index) { + file = selectedFileList.queryElementAt(index, nsIFile); + if (file) { + var path = file.leafName; + + if (path) { + var isDir = file.isDirectory(); + if ((filePickerMode == nsIFilePicker.modeGetFolder) || !isDir) { + if (!validFileSelected) + textInput.value = ""; + addToTextFieldValue(path); + } + + if (isDir && fileCount > 1) { + // The user has selected multiple items, and one of them is + // a directory. This is not a valid state, so we'll disable + // the ok button. + invalidSelection = true; + } + + validFileSelected = true; + } + } + } + + if (validFileSelected) { + setOKAction(file); + okButton.disabled = invalidSelection; + } else if (filePickerMode != nsIFilePicker.modeGetFolder) + okButton.disabled = (textInput.value == ""); +} + +function addToTextFieldValue(path) +{ + var newValue = ""; + + if (textInput.value == "") + newValue = path.replace(/\"/g, "\\\""); + else { + // Quote the existing text if needed, + // then append the new filename (quoted and escaped) + if (textInput.value[0] != '"') + newValue = '"' + textInput.value.replace(/\"/g, "\\\"") + '"'; + else + newValue = textInput.value; + + newValue = newValue + ' "' + path.replace(/\"/g, "\\\"") + '"'; + } + + textInput.value = newValue; +} + +function onTextFieldFocus() { + setOKAction(null); + doEnabling(); +} + +function onDirectoryChanged(target) +{ + var path = target.getAttribute("label"); + + var file = Components.classes[NS_LOCAL_FILE_CONTRACTID].createInstance(nsILocalFile); + file.initWithPath(path); + + if (!sfile.equals(file)) { + // Do this on a timeout callback so the directory list can roll up + // and we don't keep the mouse grabbed while we are loading. + + setTimeout(gotoDirectory, 0, file); + } +} + +function populateAncestorList(directory) { + var menu = document.getElementById("lookInMenu"); + + while (menu.hasChildNodes()) { + menu.removeChild(menu.firstChild); + } + + var menuItem = document.createElement("menuitem"); + menuItem.setAttribute("label", directory.path); + menuItem.setAttribute("crop", "start"); + menu.appendChild(menuItem); + + // .parent is _sometimes_ null, see bug 121489. Do a dance around that. + var parent = directory.parent; + while (parent && !parent.equals(directory)) { + menuItem = document.createElement("menuitem"); + menuItem.setAttribute("label", parent.path); + menuItem.setAttribute("crop", "start"); + menu.appendChild(menuItem); + directory = parent; + parent = directory.parent; + } + + var menuList = document.getElementById("lookInMenuList"); + menuList.selectedIndex = 0; +} + +function goUp() { + try { + var parent = sfile.parent; + } catch (ex) { dump("can't get parent directory\n"); } + + if (parent) { + gotoDirectory(parent); + } +} + +function goHome() { + gotoDirectory(homeDir); +} + +function newDir() { + var file; + var promptService = + Components.classes[NS_PROMPTSERVICE_CONTRACTID].getService(Components.interfaces.nsIPromptService); + var dialogTitle = + gFilePickerBundle.getString("promptNewDirTitle"); + var dialogMsg = + gFilePickerBundle.getString("promptNewDirMessage"); + var ret = promptService.prompt(window, dialogTitle, dialogMsg, gNewDirName, null, {value:0}); + + if (ret) { + file = processPath(gNewDirName.value); + if (!file) { + showErrorDialog("errorCreateNewDirTitle", + "errorCreateNewDirMessage", + file); + return false; + } + + file = file[0].QueryInterface(nsIFile); + if (file.exists()) { + showErrorDialog("errorNewDirDoesExistTitle", + "errorNewDirDoesExistMessage", + file); + return false; + } + + var parent = file.parent; + if (!(parent.exists() && parent.isDirectory() && parent.isWritable())) { + while (!parent.exists()) { + parent = parent.parent; + } + if (parent.isFile()) { + showErrorDialog("errorCreateNewDirTitle", + "errorCreateNewDirIsFileMessage", + parent); + return false; + } + if (!parent.isWritable()) { + showErrorDialog("errorCreateNewDirTitle", + "errorCreateNewDirPermissionMessage", + parent); + return false; + } + } + + try { + file.create(nsIFile.DIRECTORY_TYPE, 0o755); + } catch (e) { + showErrorDialog("errorCreateNewDirTitle", + "errorCreateNewDirMessage", + file); + return false; + } + file.normalize(); // ... in case ".." was used in the path + gotoDirectory(file); + // we remember and reshow a dirname if something goes wrong + // so that errors can be corrected more easily. If all went well, + // reset the default value to blank + gNewDirName = { value: "" }; + } + return true; +} + +function gotoDirectory(directory) { + window.setCursor("wait"); + try { + populateAncestorList(directory); + treeView.setDirectory(directory); + document.getElementById("errorShower").selectedIndex = 0; + } catch (ex) { + document.getElementById("errorShower").selectedIndex = 1; + } + + window.setCursor("auto"); + + if (filePickerMode == nsIFilePicker.modeGetFolder) { + textInput.value = ""; + } + textInput.focus(); + textInput.setAttribute("autocompletesearchparam", directory.path); + sfile = directory; +} + +function toggleShowHidden(event) { + treeView.showHiddenFiles = !treeView.showHiddenFiles; +} + +// from the current directory and whatever was entered +// in the entry field, try to make a new path. This +// uses "/" as the directory separator, "~" as a shortcut +// for the home directory (but only when seen at the start +// of a path), and ".." to denote the parent directory. +// returns an array of the files listed, +// or false if an error occurred. +function processPath(path) +{ + var fileArray = new Array(); + var strLength = path.length; + + if (path[0] == '"' && filePickerMode == nsIFilePicker.modeOpenMultiple && + strLength > 1) { + // we have a quoted list of filenames, separated by spaces. + // iterate the list and process each file. + + var curFileStart = 1; + + while (1) { + var nextQuote; + + // Look for an unescaped quote + var quoteSearchStart = curFileStart + 1; + do { + nextQuote = path.indexOf('"', quoteSearchStart); + quoteSearchStart = nextQuote + 1; + } while (nextQuote != -1 && path[nextQuote - 1] == '\\'); + + if (nextQuote == -1) { + // we have a filename with no trailing quote. + // just assume that the filename ends at the end of the string. + + if (!processPathEntry(path.substring(curFileStart), fileArray)) + return false; + break; + } + + if (!processPathEntry(path.substring(curFileStart, nextQuote), fileArray)) + return false; + + curFileStart = path.indexOf('"', nextQuote + 1); + if (curFileStart == -1) { + // no more quotes, but if we're not at the end of the string, + // go ahead and process the remaining text. + + if (nextQuote < strLength - 1) + if (!processPathEntry(path.substring(nextQuote + 1), fileArray)) + return false; + break; + } + ++curFileStart; + } + } else if (!processPathEntry(path, fileArray)) { + // If we didn't start with a quote, assume we just have a single file. + return false; + } + + return fileArray; +} + +function processPathEntry(path, fileArray) +{ + var filePath; + var file; + + try { + file = sfile.clone().QueryInterface(nsILocalFile); + } catch (e) { + dump("Couldn't clone\n"+e); + return false; + } + + var tilde_file = file.clone(); + tilde_file.append("~"); + if (path[0] == '~' && // Expand ~ to $HOME, except: + !(path == "~" && tilde_file.exists()) && // If ~ was entered and such a file exists, don't expand + (path.length == 1 || path[1] == "/")) // We don't want to expand ~file to ${HOME}file + filePath = homeDir.path + path.substring(1); + else + filePath = path; + + // Unescape quotes + filePath = filePath.replace(/\\\"/g, "\""); + + if (filePath[0] == '/') /* an absolute path was entered */ + file.initWithPath(filePath); + else if ((filePath.indexOf("/../") > 0) || + (filePath.substr(-3) == "/..") || + (filePath.substr(0, 3) == "../") || + (filePath == "..")) { + /* appendRelativePath doesn't allow .. */ + try { + file.initWithPath(file.path + "/" + filePath); + } catch (e) { + dump("Couldn't init path\n"+e); + return false; + } + } + else { + try { + file.appendRelativePath(filePath); + } catch (e) { + dump("Couldn't append path\n"+e); + return false; + } + } + + fileArray[fileArray.length] = file; + return true; +} diff --git a/toolkit/components/filepicker/content/filepicker.xul b/toolkit/components/filepicker/content/filepicker.xul new file mode 100644 index 000000000..4bf311230 --- /dev/null +++ b/toolkit/components/filepicker/content/filepicker.xul @@ -0,0 +1,80 @@ +<?xml version="1.0"?> <!-- -*- Mode: HTML -*- --> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="chrome://global/skin/filepicker.css" type="text/css"?> + +<!DOCTYPE dialog SYSTEM "chrome://global/locale/filepicker.dtd" > + +<dialog id="main-window" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:nc="http://home.netscape.com/NC-rdf#" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + onload="filepickerLoad();" + width="426" height="300" + ondialogaccept="return selectOnOK();" + ondialogcancel="return onCancel();" + persist="screenX screenY width height"> + +<stringbundle id="bundle_filepicker" src="chrome://global/locale/filepicker.properties"/> +<script type="application/javascript" src="chrome://global/content/filepicker.js"/> + +<hbox align="center"> + <label value="&lookInMenuList.label;" control="lookInMenuList" accesskey="&lookInMenuList.accesskey;"/> + <menulist id="lookInMenuList" flex="1" oncommand="onDirectoryChanged(event.target);" crop="start"> + <menupopup id="lookInMenu"/> + </menulist> + <button id="folderUpButton" class="up-button" tooltiptext="&folderUp.tooltiptext;" oncommand="goUp();"/> + <button id="homeButton" class="home-button" tooltiptext="&folderHome.tooltiptext;" oncommand="goHome();"/> + <button id="newDirButton" hidden="true" class="new-dir-button" tooltiptext="&folderNew.tooltiptext;" oncommand="newDir();"/> +</hbox> + +<hbox flex="1"> + <deck id="errorShower" flex="1"> + <tree id="directoryTree" flex="1" class="focusring" seltype="single" + onclick="onClick(event);" + ondblclick="onDblClick(event);" + onkeypress="onKeypress(event);" + onfocus="onTreeFocus(event);" + onselect="onSelect(event);"> + <treecols> + <treecol id="FilenameColumn" label="&name.label;" flex="1"/> + <splitter class="tree-splitter"/> + <treecol id="FileSizeColumn" label="&size.label;" flex="1"/> + <splitter class="tree-splitter"/> + <treecol id="LastModifiedColumn" label="&lastModified.label;" flex="1"/> + </treecols> + <treechildren/> + </tree> + <label>&noPermissionError.label;</label> + </deck> +</hbox> + +<grid style="margin-top: 5px"> + <columns> + <column/> + <column flex="1"/> + </columns> + + <rows> + <row align="center"> + <label value="&textInput.label;" id="textInputLabel" control="textInput" accesskey="&textInput.accesskey;"/> + <textbox id="textInput" flex="1" oninput="doEnabling()" + type="autocomplete" autocompletesearch="file" + onfocus="onTextFieldFocus();"/> + </row> + <row id="filterBox" hidden="true" align="center"> + <label value="&filterMenuList.label;" control="filterMenuList" accesskey="&filterMenuList.accesskey;"/> + <menulist id="filterMenuList" flex="1" oncommand="onFilterChanged(event.target);"/> + </row> + </rows> +</grid> +<hbox class="dialog-button-box" align="center"> + <checkbox label="&showHiddenFiles.label;" oncommand="toggleShowHidden();" + flex="1" accesskey="&showHiddenFiles.accesskey;"/> + <button dlgtype="cancel" icon="cancel" class="dialog-button"/> + <button dlgtype="accept" icon="open" class="dialog-button"/> +</hbox> +</dialog> |