OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Setting the src of an img to an empty string can crash the browser, so we | 5 // Setting the src of an img to an empty string can crash the browser, so we |
6 // use an empty 1x1 gif instead. | 6 // use an empty 1x1 gif instead. |
7 | 7 |
8 /** | 8 /** |
9 * FileManager constructor. | 9 * FileManager constructor. |
10 * | 10 * |
(...skipping 18 matching lines...) Expand all Loading... |
29 this.selection = null; | 29 this.selection = null; |
30 | 30 |
31 this.butterTimer_ = null; | 31 this.butterTimer_ = null; |
32 this.currentButter_ = null; | 32 this.currentButter_ = null; |
33 this.butterLastShowTime_ = 0; | 33 this.butterLastShowTime_ = 0; |
34 | 34 |
35 this.watchedDirectoryUrl_ = null; | 35 this.watchedDirectoryUrl_ = null; |
36 | 36 |
37 this.commands_ = {}; | 37 this.commands_ = {}; |
38 | 38 |
| 39 this.thumbnailUrlCache_ = {}; |
| 40 |
39 this.document_ = dialogDom.ownerDocument; | 41 this.document_ = dialogDom.ownerDocument; |
40 this.dialogType_ = this.params_.type || FileManager.DialogType.FULL_PAGE; | 42 this.dialogType_ = this.params_.type || FileManager.DialogType.FULL_PAGE; |
41 | 43 |
42 metrics.recordEnum('Create', this.dialogType_, | 44 metrics.recordEnum('Create', this.dialogType_, |
43 [FileManager.DialogType.SELECT_FOLDER, | 45 [FileManager.DialogType.SELECT_FOLDER, |
44 FileManager.DialogType.SELECT_SAVEAS_FILE, | 46 FileManager.DialogType.SELECT_SAVEAS_FILE, |
45 FileManager.DialogType.SELECT_OPEN_FILE, | 47 FileManager.DialogType.SELECT_OPEN_FILE, |
46 FileManager.DialogType.SELECT_OPEN_MULTI_FILE, | 48 FileManager.DialogType.SELECT_OPEN_MULTI_FILE, |
47 FileManager.DialogType.FULL_PAGE]); | 49 FileManager.DialogType.FULL_PAGE]); |
48 | 50 |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 | 643 |
642 this.downloadsWarning_ = | 644 this.downloadsWarning_ = |
643 this.dialogDom_.querySelector('.downloads-warning'); | 645 this.dialogDom_.querySelector('.downloads-warning'); |
644 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); | 646 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); |
645 this.downloadsWarning_.lastElementChild.innerHTML = html; | 647 this.downloadsWarning_.lastElementChild.innerHTML = html; |
646 var link = this.downloadsWarning_.querySelector('a'); | 648 var link = this.downloadsWarning_.querySelector('a'); |
647 link.addEventListener('click', this.onDownloadsWarningClick_.bind(this)); | 649 link.addEventListener('click', this.onDownloadsWarningClick_.bind(this)); |
648 | 650 |
649 this.document_.addEventListener('keydown', this.onKeyDown_.bind(this)); | 651 this.document_.addEventListener('keydown', this.onKeyDown_.bind(this)); |
650 this.document_.addEventListener('copy', | 652 this.document_.addEventListener('copy', |
651 this.copySelectionToClipboard_.bind(this)); | 653 this.onCopy_.bind(this)); |
652 // Disable the default browser context menu. | 654 // Disable the default browser context menu. |
653 this.document_.addEventListener('contextmenu', | 655 this.document_.addEventListener('contextmenu', |
654 function (e) { e.preventDefault() }); | 656 function (e) { e.preventDefault() }); |
655 | 657 |
656 // We need to store a reference to the function returned by bind. Later, in | 658 // We need to store a reference to the function returned by bind. Later, in |
657 // canPaste function, we need to temporarily remove this event handler and | 659 // canPaste function, we need to temporarily remove this event handler and |
658 // use another 'paste' event handler to check the state of system clipboard. | 660 // use another 'paste' event handler to check the state of system clipboard. |
659 this.pasteFromClipboardBind_ = this.pasteFromClipboard_.bind(this); | 661 this.onPasteBound_ = this.onPaste_.bind(this); |
660 this.document_.addEventListener('paste', this.pasteFromClipboardBind_); | 662 this.document_.addEventListener('paste', this.onPasteBound_); |
661 | 663 |
662 // In pasteFromClipboard function, we need to reset system clipboard after | 664 // In pasteFromClipboard function, we need to reset system clipboard after |
663 // 'cut' and 'paste' command sequence. The clipboardData.clearData doesn't | 665 // 'cut' and 'paste' command sequence. The clipboardData.clearData doesn't |
664 // seem to work. We reset the system clipboard in another 'cut' event | 666 // seem to work. We reset the system clipboard in another 'cut' event |
665 // handler as a workaround. This reference is used to temporarily remove | 667 // handler as a workaround. This reference is used to temporarily remove |
666 // 'cut' event handler as well. | 668 // 'cut' event handler as well. |
667 this.cutFromClipboardBind_ = this.cutSelectionToClipboard_.bind(this); | 669 this.onCutBound_ = this.onCut_.bind(this); |
668 this.document_.addEventListener('cut', this.cutFromClipboardBind_); | 670 this.document_.addEventListener('cut', this.onCutBound_); |
669 | 671 |
670 this.renameInput_ = this.document_.createElement('input'); | 672 this.renameInput_ = this.document_.createElement('input'); |
671 this.renameInput_.className = 'rename'; | 673 this.renameInput_.className = 'rename'; |
672 | 674 |
673 this.renameInput_.addEventListener( | 675 this.renameInput_.addEventListener( |
674 'keydown', this.onRenameInputKeyDown_.bind(this)); | 676 'keydown', this.onRenameInputKeyDown_.bind(this)); |
675 this.renameInput_.addEventListener( | 677 this.renameInput_.addEventListener( |
676 'blur', this.onRenameInputBlur_.bind(this)); | 678 'blur', this.onRenameInputBlur_.bind(this)); |
677 | 679 |
678 this.filenameInput_.addEventListener( | 680 this.filenameInput_.addEventListener( |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 var clipboardCanPaste = function(event) { | 1109 var clipboardCanPaste = function(event) { |
1108 event.preventDefault(); | 1110 event.preventDefault(); |
1109 // Here we need to use lower case as clipboardData.types return lower | 1111 // Here we need to use lower case as clipboardData.types return lower |
1110 // case DomStringList. | 1112 // case DomStringList. |
1111 if (event.clipboardData && | 1113 if (event.clipboardData && |
1112 event.clipboardData.types && | 1114 event.clipboardData.types && |
1113 event.clipboardData.types.indexOf('fs/iscut') != -1) | 1115 event.clipboardData.types.indexOf('fs/iscut') != -1) |
1114 canPaste = true; | 1116 canPaste = true; |
1115 }; | 1117 }; |
1116 | 1118 |
1117 this.document_.removeEventListener('paste', this.pasteFromClipboardBind_); | 1119 this.document_.removeEventListener('paste', this.onPasteBound_); |
1118 this.document_.addEventListener('paste', clipboardCanPaste); | 1120 this.document_.addEventListener('paste', clipboardCanPaste); |
1119 this.document_.execCommand('paste'); | 1121 this.document_.execCommand('paste'); |
1120 this.document_.removeEventListener('paste', clipboardCanPaste); | 1122 this.document_.removeEventListener('paste', clipboardCanPaste); |
1121 this.document_.addEventListener('paste', this.pasteFromClipboardBind_); | 1123 this.document_.addEventListener('paste', this.onPasteBound_); |
1122 return canPaste && !readonly; | 1124 return canPaste && !readonly; |
1123 }; | 1125 }; |
1124 | 1126 |
1125 /** | 1127 /** |
1126 * @param {string} commandId Command identifier. | 1128 * @param {string} commandId Command identifier. |
1127 * @return {boolean} True if the command can be executed for current | 1129 * @return {boolean} True if the command can be executed for current |
1128 * selection. | 1130 * selection. |
1129 */ | 1131 */ |
1130 FileManager.prototype.canExecute_ = function(commandId) { | 1132 FileManager.prototype.canExecute_ = function(commandId) { |
1131 var readonly = this.directoryModel_.readonly; | 1133 var readonly = this.directoryModel_.readonly; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 */ | 1247 */ |
1246 FileManager.prototype.initGrid_ = function() { | 1248 FileManager.prototype.initGrid_ = function() { |
1247 var self = this; | 1249 var self = this; |
1248 this.grid_.itemConstructor = GridItem.bind(null, this); | 1250 this.grid_.itemConstructor = GridItem.bind(null, this); |
1249 | 1251 |
1250 this.grid_.addEventListener( | 1252 this.grid_.addEventListener( |
1251 'dblclick', this.onDetailDoubleClick_.bind(this)); | 1253 'dblclick', this.onDetailDoubleClick_.bind(this)); |
1252 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_); | 1254 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_); |
1253 this.grid_.addEventListener('mousedown', | 1255 this.grid_.addEventListener('mousedown', |
1254 this.onGridOrTableMouseDown_.bind(this)); | 1256 this.onGridOrTableMouseDown_.bind(this)); |
| 1257 this.setupDragAndDrop_(this.grid_); |
1255 }; | 1258 }; |
1256 | 1259 |
1257 /** | 1260 /** |
1258 * Initialize the file list table. | 1261 * Initialize the file list table. |
1259 */ | 1262 */ |
1260 FileManager.prototype.initTable_ = function() { | 1263 FileManager.prototype.initTable_ = function() { |
1261 var columns = [ | 1264 var columns = [ |
1262 new cr.ui.table.TableColumn('name', str('NAME_COLUMN_LABEL'), | 1265 new cr.ui.table.TableColumn('name', str('NAME_COLUMN_LABEL'), |
1263 64), | 1266 64), |
1264 new cr.ui.table.TableColumn('cachedSize_', | 1267 new cr.ui.table.TableColumn('cachedSize_', |
(...skipping 24 matching lines...) Expand all Loading... |
1289 | 1292 |
1290 // Don't pay attention to double clicks on the table header. | 1293 // Don't pay attention to double clicks on the table header. |
1291 this.table_.querySelector('.list').addEventListener( | 1294 this.table_.querySelector('.list').addEventListener( |
1292 'dblclick', this.onDetailDoubleClick_.bind(this)); | 1295 'dblclick', this.onDetailDoubleClick_.bind(this)); |
1293 | 1296 |
1294 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'), | 1297 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'), |
1295 this.fileContextMenu_); | 1298 this.fileContextMenu_); |
1296 | 1299 |
1297 this.table_.addEventListener('mousedown', | 1300 this.table_.addEventListener('mousedown', |
1298 this.onGridOrTableMouseDown_.bind(this)); | 1301 this.onGridOrTableMouseDown_.bind(this)); |
| 1302 this.setupDragAndDrop_(this.table_.list); |
| 1303 }; |
| 1304 |
| 1305 FileManager.prototype.setupDragAndDrop_ = function(list) { |
| 1306 list.addEventListener('dragstart', this.onDragStart_.bind(this)); |
| 1307 }; |
| 1308 |
| 1309 FileManager.prototype.onDragStart_ = function(event) { |
| 1310 var dt = event.dataTransfer; |
| 1311 var container = this.document_.querySelector('#drag-image-container'); |
| 1312 container.textContent = ''; |
| 1313 for (var i = 0; i < this.selection.dragNodes.length; i++) { |
| 1314 var listItem = this.selection.dragNodes[i]; |
| 1315 listItem.selected = true; |
| 1316 container.appendChild(listItem); |
| 1317 } |
| 1318 |
| 1319 this.cutOrCopyToClipboard_(dt, false); |
| 1320 |
| 1321 dt.setDragImage(container, 0, 0); |
| 1322 dt.effectAllowed = 'copyMove'; |
1299 }; | 1323 }; |
1300 | 1324 |
1301 FileManager.prototype.initButter_ = function() { | 1325 FileManager.prototype.initButter_ = function() { |
1302 var self = this; | 1326 var self = this; |
1303 var progress = this.copyManager_.getProgress(); | 1327 var progress = this.copyManager_.getProgress(); |
1304 | 1328 |
1305 var options = {progress: progress.percentage, actions:{}}; | 1329 var options = {progress: progress.percentage, actions:{}}; |
1306 options.actions[str('CANCEL_LABEL')] = function cancelPaste() { | 1330 options.actions[str('CANCEL_LABEL')] = function cancelPaste() { |
1307 self.copyManager_.requestCancel(); | 1331 self.copyManager_.requestCancel(); |
1308 }; | 1332 }; |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1722 * the image has been loaded before inserting | 1746 * the image has been loaded before inserting |
1723 * it into the DOM. | 1747 * it into the DOM. |
1724 * @return {HTMLDivElement} | 1748 * @return {HTMLDivElement} |
1725 */ | 1749 */ |
1726 FileManager.prototype.renderThumbnailBox_ = function(entry, fill, | 1750 FileManager.prototype.renderThumbnailBox_ = function(entry, fill, |
1727 opt_imageLoadCallback) { | 1751 opt_imageLoadCallback) { |
1728 var box = this.document_.createElement('div'); | 1752 var box = this.document_.createElement('div'); |
1729 box.className = 'img-container'; | 1753 box.className = 'img-container'; |
1730 var img = this.document_.createElement('img'); | 1754 var img = this.document_.createElement('img'); |
1731 var self = this; | 1755 var self = this; |
1732 this.getThumbnailURL(entry, function(iconType, url, transform) { | 1756 |
| 1757 function onThumbnailURL(iconType, url, transform) { |
| 1758 self.thumbnailUrlCache_[entry.fullPath] = { |
| 1759 iconType: iconType, |
| 1760 url: url, |
| 1761 transform: transform |
| 1762 }; |
1733 img.onload = function() { | 1763 img.onload = function() { |
1734 self.centerImage_(img.style, img.width, img.height, fill); | 1764 self.centerImage_(img.style, img.width, img.height, fill); |
1735 if (opt_imageLoadCallback) | 1765 if (opt_imageLoadCallback) |
1736 opt_imageLoadCallback(img, transform); | 1766 opt_imageLoadCallback(img, transform); |
1737 box.appendChild(img); | 1767 box.appendChild(img); |
1738 }; | 1768 }; |
1739 img.src = url; | 1769 img.src = url; |
1740 self.applyImageTransformation_(box, transform); | 1770 self.applyImageTransformation_(box, transform); |
1741 }); | 1771 } |
| 1772 |
| 1773 var cached = this.thumbnailUrlCache_[entry.fullPath]; |
| 1774 if (cached) |
| 1775 onThumbnailURL(cached.iconType, cached.url, cached.transform); |
| 1776 else |
| 1777 this.getThumbnailURL(entry, onThumbnailURL); |
| 1778 |
1742 return box; | 1779 return box; |
1743 }; | 1780 }; |
1744 | 1781 |
1745 FileManager.prototype.decorateThumbnail_ = function(li, entry) { | 1782 FileManager.prototype.decorateThumbnail_ = function(li, entry) { |
1746 li.className = 'thumbnail-item'; | 1783 li.className = 'thumbnail-item'; |
1747 | 1784 |
1748 if (this.showCheckboxes_) | 1785 if (this.showCheckboxes_) |
1749 li.appendChild(this.renderCheckbox_(entry)); | 1786 li.appendChild(this.renderCheckbox_(entry)); |
1750 | 1787 |
1751 li.appendChild(this.renderThumbnailBox_(entry, false)); | 1788 li.appendChild(this.renderThumbnailBox_(entry, false)); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 */ | 2106 */ |
2070 FileManager.prototype.summarizeSelection_ = function() { | 2107 FileManager.prototype.summarizeSelection_ = function() { |
2071 var selection = this.selection = { | 2108 var selection = this.selection = { |
2072 entries: [], | 2109 entries: [], |
2073 urls: [], | 2110 urls: [], |
2074 totalCount: 0, | 2111 totalCount: 0, |
2075 fileCount: 0, | 2112 fileCount: 0, |
2076 directoryCount: 0, | 2113 directoryCount: 0, |
2077 bytes: 0, | 2114 bytes: 0, |
2078 iconType: null, | 2115 iconType: null, |
2079 indexes: this.currentList_.selectionModel.selectedIndexes | 2116 indexes: this.currentList_.selectionModel.selectedIndexes, |
| 2117 files: [], |
| 2118 dragNodes: [] |
2080 }; | 2119 }; |
2081 | 2120 |
2082 if (!selection.indexes.length) { | 2121 if (!selection.indexes.length) { |
2083 this.updateCommonActionButtons_(); | 2122 this.updateCommonActionButtons_(); |
2084 this.updatePreviewPanelVisibility_(); | 2123 this.updatePreviewPanelVisibility_(); |
2085 cr.dispatchSimpleEvent(this, 'selection-summarized'); | 2124 cr.dispatchSimpleEvent(this, 'selection-summarized'); |
2086 return; | 2125 return; |
2087 } | 2126 } |
2088 | 2127 |
2089 this.previewSummary_.textContent = str('COMPUTING_SELECTION'); | 2128 this.previewSummary_.textContent = str('COMPUTING_SELECTION'); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 var thumbnail = this.renderThumbnailBox_(entry, true, imageLoadCalback); | 2161 var thumbnail = this.renderThumbnailBox_(entry, true, imageLoadCalback); |
2123 box.appendChild(thumbnail); | 2162 box.appendChild(thumbnail); |
2124 box.style.zIndex = MAX_PREVIEW_THUMBAIL_COUNT + 1 - i; | 2163 box.style.zIndex = MAX_PREVIEW_THUMBAIL_COUNT + 1 - i; |
2125 box.addEventListener('click', | 2164 box.addEventListener('click', |
2126 this.dispatchDefaultTask_.bind(this, selection)); | 2165 this.dispatchDefaultTask_.bind(this, selection)); |
2127 | 2166 |
2128 this.previewThumbnails_.appendChild(box); | 2167 this.previewThumbnails_.appendChild(box); |
2129 thumbnailCount++; | 2168 thumbnailCount++; |
2130 } | 2169 } |
2131 | 2170 |
| 2171 // Items to drag are created in advance. Images must be loaded |
| 2172 // at the time the 'dragstart' event comes. Otherwise draggable |
| 2173 // image will be rendered without IMG tags. |
| 2174 if (selection.dragNodes.length < MAX_PREVIEW_THUMBAIL_COUNT) |
| 2175 selection.dragNodes.push(new GridItem(this, entry)); |
| 2176 |
2132 selection.totalCount++; | 2177 selection.totalCount++; |
2133 | 2178 |
2134 if (entry.isFile) { | 2179 if (entry.isFile) { |
2135 selection.fileCount += 1; | 2180 selection.fileCount += 1; |
2136 if (!('cachedSize_' in entry)) { | 2181 if (!('cachedSize_' in entry)) { |
2137 // Any file that hasn't been rendered may be missing its cachedSize_ | 2182 // Any file that hasn't been rendered may be missing its cachedSize_ |
2138 // property. For example, visit a large file list, and press ctrl-a | 2183 // property. For example, visit a large file list, and press ctrl-a |
2139 // to select all. In this case, we need to asynchronously get the | 2184 // to select all. In this case, we need to asynchronously get the |
2140 // sizes for these files before telling the world the selection has | 2185 // sizes for these files before telling the world the selection has |
2141 // been summarized. See the 'computeNextFile' logic below. | 2186 // been summarized. See the 'computeNextFile' logic below. |
2142 pendingFiles.push(entry); | 2187 pendingFiles.push(entry); |
2143 continue; | 2188 continue; |
2144 } else { | 2189 } else { |
2145 selection.bytes += entry.cachedSize_; | 2190 selection.bytes += entry.cachedSize_; |
2146 } | 2191 } |
| 2192 // File object must be prepeared in advance for clipboard operations |
| 2193 // (copy, paste and drag). Clipboard object closes for write after |
| 2194 // returning control from that handlers so they may not have |
| 2195 // asynchronous operations. |
| 2196 // TODO(serya): Put file objects into the clipboard. |
| 2197 if (!this.isOnGData()) { |
| 2198 entry.file(function(f) { |
| 2199 selection.files.push(f); |
| 2200 }); |
| 2201 } |
2147 } else { | 2202 } else { |
2148 selection.directoryCount += 1; | 2203 selection.directoryCount += 1; |
2149 } | 2204 } |
2150 } | 2205 } |
2151 | 2206 |
2152 // Now this.selection is complete. Update buttons. | 2207 // Now this.selection is complete. Update buttons. |
2153 this.updateCommonActionButtons_(); | 2208 this.updateCommonActionButtons_(); |
2154 this.updatePreviewPanelVisibility_(); | 2209 this.updatePreviewPanelVisibility_(); |
2155 | 2210 |
2156 var self = this; | 2211 var self = this; |
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3054 var listItem = self.currentList_.getListItemByIndex(selectedIndex); | 3109 var listItem = self.currentList_.getListItemByIndex(selectedIndex); |
3055 if (listItem) | 3110 if (listItem) |
3056 listItem.classList.remove('blink'); | 3111 listItem.classList.remove('blink'); |
3057 } | 3112 } |
3058 }, 100); | 3113 }, 100); |
3059 }; | 3114 }; |
3060 | 3115 |
3061 /** | 3116 /** |
3062 * Write the current selection to system clipboard. | 3117 * Write the current selection to system clipboard. |
3063 * | 3118 * |
3064 * @param {Event} event Cut or Copy event. | 3119 * @param {Clipboard} clipboard Clipboard from the event. |
3065 * @param {boolean} isCut True if the current command is cut. | 3120 * @param {boolean} isCut True if the current command is cut. |
3066 */ | 3121 */ |
3067 FileManager.prototype.cutOrCopyToClipboard_ = function(event, isCut) { | 3122 FileManager.prototype.cutOrCopyToClipboard_ = function(clipboard, isCut) { |
3068 event.preventDefault(); | 3123 var directories = ''; |
| 3124 var files = ''; |
| 3125 for(var i = 0, entry; i < this.selection.entries.length; i++) { |
| 3126 entry = this.selection.entries[i]; |
| 3127 if (entry.isDirectory) |
| 3128 directories += entry.fullPath + '\n'; |
| 3129 else |
| 3130 files += entry.fullPath + '\n'; |
| 3131 } |
3069 | 3132 |
3070 var directories = ''; | 3133 clipboard.setData('fs/isCut', isCut.toString()); |
3071 var files = ''; | 3134 clipboard.setData('fs/sourceDir', |
3072 for(var i = 0, entry; i < this.selection.entries.length; i++) { | |
3073 entry = this.selection.entries[i]; | |
3074 if (entry.isDirectory) | |
3075 directories += entry.fullPath + '\n'; | |
3076 else | |
3077 files += entry.fullPath + '\n'; | |
3078 } | |
3079 | |
3080 event.clipboardData.setData('fs/isCut', isCut.toString()); | |
3081 event.clipboardData.setData('fs/isOnGData', | |
3082 this.isOnGData().toString()); | |
3083 event.clipboardData.setData('fs/sourceDir', | |
3084 this.directoryModel_.currentEntry.fullPath); | 3135 this.directoryModel_.currentEntry.fullPath); |
3085 event.clipboardData.setData('fs/directories', directories); | 3136 clipboard.setData('fs/sourceOnGData', this.isOnGData()); |
3086 event.clipboardData.setData('fs/files', files); | 3137 clipboard.setData('fs/directories', directories); |
| 3138 clipboard.setData('fs/files', files); |
3087 } | 3139 } |
3088 | 3140 |
3089 FileManager.prototype.copySelectionToClipboard_ = function(event) { | 3141 FileManager.prototype.onCopy_ = function(event) { |
3090 if (!this.selection || this.selection.totalCount == 0) | 3142 if (!this.selection || this.selection.totalCount == 0) |
3091 return; | 3143 return; |
3092 | 3144 |
3093 this.cutOrCopyToClipboard_(event, false); | 3145 event.preventDefault(); |
| 3146 this.cutOrCopyToClipboard_(event.clipboardData, false); |
3094 | 3147 |
3095 this.blinkSelection(); | 3148 this.blinkSelection(); |
3096 }; | 3149 }; |
3097 | 3150 |
3098 FileManager.prototype.cutSelectionToClipboard_ = function(event) { | 3151 FileManager.prototype.onCut_ = function(event) { |
3099 if (!this.selection || this.selection.totalCount == 0 || | 3152 if (!this.selection || this.selection.totalCount == 0 || |
3100 this.commands_['cut'].disabled) | 3153 this.commands_['cut'].disabled) |
3101 return; | 3154 return; |
3102 | 3155 |
3103 this.cutOrCopyToClipboard_(event, true); | 3156 event.preventDefault(); |
| 3157 this.cutOrCopyToClipboard_(event.clipboardData, true); |
3104 | 3158 |
3105 this.blinkSelection(); | 3159 this.blinkSelection(); |
3106 }; | 3160 }; |
3107 | 3161 |
| 3162 FileManager.prototype.onPaste_ = function(event) { |
| 3163 event.preventDefault(); |
| 3164 this.pasteFromClipboard_(event.clipboardData); |
| 3165 }; |
| 3166 |
3108 /** | 3167 /** |
3109 * Queue up a file copy operation based on the current system clipboard. | 3168 * Queue up a file copy operation based on the current system clipboard. |
3110 */ | 3169 */ |
3111 FileManager.prototype.pasteFromClipboard_ = function(event) { | 3170 FileManager.prototype.pasteFromClipboard_ = function(clipboard) { |
3112 event.preventDefault(); | |
3113 | |
3114 if (!event.clipboardData.getData('fs/isCut')) | 3171 if (!event.clipboardData.getData('fs/isCut')) |
3115 return; | 3172 return; |
3116 | 3173 |
3117 var clipboard = { | 3174 var operationInfo = { |
3118 isCut: event.clipboardData.getData('fs/isCut'), | 3175 isCut: clipboard.getData('fs/isCut'), |
3119 isOnGData: event.clipboardData.getData('fs/isOnGData'), | 3176 sourceDir: clipboard.getData('fs/sourceDir'), |
3120 sourceDir: event.clipboardData.getData('fs/sourceDir'), | 3177 sourceOnGData: clipboard.getData('fs/sourceOnGData'), |
3121 directories: event.clipboardData.getData('fs/directories'), | 3178 directories: clipboard.getData('fs/directories'), |
3122 files: event.clipboardData.getData('fs/files') | 3179 files: clipboard.getData('fs/files') |
3123 }; | 3180 }; |
3124 | 3181 |
3125 this.copyManager_.paste(clipboard, | 3182 // If both source and target are on GData, FileCopyManager uses |
| 3183 // FileEntry.copyTo() / FileEntry.moveTo() to copy / move files. |
| 3184 var sourceAndTargetOnGData = operationInfo.sourceOnGData && |
| 3185 this.isOnGData(); |
| 3186 this.copyManager_.paste(operationInfo, |
3126 this.directoryModel_.currentEntry, | 3187 this.directoryModel_.currentEntry, |
3127 this.isOnGData(), | 3188 this.isOnGData(), |
3128 this.filesystem_.root); | 3189 this.filesystem_.root); |
3129 | 3190 |
3130 var clearClipboard = function (event) { | 3191 var clearClipboard = function (event) { |
3131 event.preventDefault(); | 3192 event.preventDefault(); |
3132 event.clipboardData.setData('fs/clear', ''); | 3193 event.clipboardData.setData('fs/clear', ''); |
3133 } | 3194 } |
3134 | 3195 |
3135 // On cut, we clear the clipboard after the file is pasted/moved so we don't | 3196 // On cut, we clear the clipboard after the file is pasted/moved so we don't |
3136 // try to move/delete the original file again. | 3197 // try to move/delete the original file again. |
3137 if (clipboard.isCut == 'true') { | 3198 if (operationInfo.isCut == 'true') { |
3138 this.document_.removeEventListener('cut', this.cutFromClipboardBind_); | 3199 this.document_.removeEventListener('cut', this.onCutBound_); |
3139 this.document_.addEventListener('cut', clearClipboard); | 3200 this.document_.addEventListener('cut', clearClipboard); |
3140 this.document_.execCommand('cut'); | 3201 this.document_.execCommand('cut'); |
3141 this.document_.removeEventListener('cut', clearClipboard); | 3202 this.document_.removeEventListener('cut', clearClipboard); |
3142 this.document_.addEventListener('cut', this.cutFromClipboardBind_); | 3203 this.document_.addEventListener('cut', this.onCutBound_); |
3143 } | 3204 } |
3144 }; | 3205 }; |
3145 | 3206 |
3146 /** | 3207 /** |
3147 * Update the selection summary UI when the selection summarization completes. | 3208 * Update the selection summary UI when the selection summarization completes. |
3148 */ | 3209 */ |
3149 FileManager.prototype.onSelectionSummarized_ = function() { | 3210 FileManager.prototype.onSelectionSummarized_ = function() { |
3150 var selection = this.selection; | 3211 var selection = this.selection; |
3151 var bytes = util.bytesToSi(selection.bytes); | 3212 var bytes = util.bytesToSi(selection.bytes); |
3152 var text = ''; | 3213 var text = ''; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3258 if (this.selection && | 3319 if (this.selection && |
3259 this.selection.totalCount == 1 && | 3320 this.selection.totalCount == 1 && |
3260 this.selection.entries[0].isFile && | 3321 this.selection.entries[0].isFile && |
3261 this.filenameInput_.value != this.selection.entries[0].name) { | 3322 this.filenameInput_.value != this.selection.entries[0].name) { |
3262 this.filenameInput_.value = this.selection.entries[0].name; | 3323 this.filenameInput_.value = this.selection.entries[0].name; |
3263 } | 3324 } |
3264 } | 3325 } |
3265 | 3326 |
3266 this.updateOkButton_(); | 3327 this.updateOkButton_(); |
3267 | 3328 |
3268 var self = this; | 3329 var newThumbnailUrlCache = {}; |
3269 setTimeout(function() { self.onSelectionChangeComplete_(event) }, 0); | 3330 if (this.selection) { |
| 3331 const entries = this.selection.entries; |
| 3332 for (var i = 0; i < entries.length; i++) { |
| 3333 var path = entries[i].fullPath; |
| 3334 if (path in this.thumbnailUrlCache_) |
| 3335 newThumbnailUrlCache[path] = this.thumbnailUrlCache_[path]; |
| 3336 } |
| 3337 } |
| 3338 this.thumbnailUrlCache_ = newThumbnailUrlCache; |
| 3339 |
| 3340 setTimeout(this.onSelectionChangeComplete_.bind(this, event), 0); |
3270 }; | 3341 }; |
3271 | 3342 |
3272 /** | 3343 /** |
3273 * Handle selection change related tasks that won't run properly during | 3344 * Handle selection change related tasks that won't run properly during |
3274 * the actual selection change event. | 3345 * the actual selection change event. |
3275 */ | 3346 */ |
3276 FileManager.prototype.onSelectionChangeComplete_ = function(event) { | 3347 FileManager.prototype.onSelectionChangeComplete_ = function(event) { |
3277 // Inform tests it's OK to click buttons now. | 3348 // Inform tests it's OK to click buttons now. |
3278 chrome.test.sendMessage('selection-change-complete'); | 3349 chrome.test.sendMessage('selection-change-complete'); |
3279 | 3350 |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3512 if (metadata && dm.rootEntry == rootEntry) | 3583 if (metadata && dm.rootEntry == rootEntry) |
3513 dm.readonly = metadata.isReadOnly; | 3584 dm.readonly = metadata.isReadOnly; |
3514 }); | 3585 }); |
3515 }; | 3586 }; |
3516 | 3587 |
3517 FileManager.prototype.findListItemForEvent_ = function(event) { | 3588 FileManager.prototype.findListItemForEvent_ = function(event) { |
3518 return this.findListItemForNode_(event.srcElement); | 3589 return this.findListItemForNode_(event.srcElement); |
3519 }; | 3590 }; |
3520 | 3591 |
3521 FileManager.prototype.findListItemForNode_ = function(node) { | 3592 FileManager.prototype.findListItemForNode_ = function(node) { |
3522 var list = this.currentList_; | 3593 var item = this.currentList_.getListItemAncestor(node); |
3523 // Assume list items are direct children of the list. | 3594 // TODO(serya): list should check that. |
3524 if (node == list) | 3595 return item && this.currentList_.isItem(item) ? item : null; |
3525 return null; | |
3526 while (node) { | |
3527 var parent = node.parentNode; | |
3528 if (parent == list && node instanceof cr.ui.ListItem) | |
3529 return node; | |
3530 node = parent; | |
3531 } | |
3532 return null; | |
3533 }; | 3596 }; |
3534 | 3597 |
3535 FileManager.prototype.onGridOrTableMouseDown_ = function(event) { | 3598 FileManager.prototype.onGridOrTableMouseDown_ = function(event) { |
3536 var item = this.findListItemForEvent_(event); | 3599 var item = this.findListItemForEvent_(event); |
3537 if (!item) | 3600 if (!item) |
3538 return; | 3601 return; |
3539 | 3602 |
3540 if (this.allowRenameClick_(event, item)) { | 3603 if (this.allowRenameClick_(event, item)) { |
3541 event.preventDefault(); | 3604 event.preventDefault(); |
3542 this.directoryModel_.fileListSelection.selectedIndex = item.listIndex; | 3605 this.directoryModel_.fileListSelection.selectedIndex = item.listIndex; |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4279 }); | 4342 }); |
4280 }, onError); | 4343 }, onError); |
4281 | 4344 |
4282 function onError(err) { | 4345 function onError(err) { |
4283 console.log('Error while checking free space: ' + err); | 4346 console.log('Error while checking free space: ' + err); |
4284 setTimeout(doCheck, 1000 * 60); | 4347 setTimeout(doCheck, 1000 * 60); |
4285 } | 4348 } |
4286 } | 4349 } |
4287 } | 4350 } |
4288 })(); | 4351 })(); |
OLD | NEW |