Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: chrome/browser/resources/file_manager/js/file_manager.js

Issue 10392155: Fixing race condition in prepearing thumbnails for the bottom panel. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /** 5 /**
6 * FileManager constructor. 6 * FileManager constructor.
7 * 7 *
8 * FileManager objects encapsulate the functionality of the file selector 8 * FileManager objects encapsulate the functionality of the file selector
9 * dialogs, as well as the full screen file manager application (though the 9 * dialogs, as well as the full screen file manager application (though the
10 * latter is not yet implemented). 10 * latter is not yet implemented).
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 48
49 // TODO(dgozman): This will be changed to LocaleInfo. 49 // TODO(dgozman): This will be changed to LocaleInfo.
50 this.locale_ = new v8Locale(navigator.language); 50 this.locale_ = new v8Locale(navigator.language);
51 51
52 this.initFileSystem_(); 52 this.initFileSystem_();
53 this.initDom_(); 53 this.initDom_();
54 this.initDialogType_(); 54 this.initDialogType_();
55 this.dialogDom_.style.opacity = '1'; 55 this.dialogDom_.style.opacity = '1';
56 } 56 }
57 57
58 /**
59 * Maximum delay in milliseconds for updating thumbnails in the bottom panel
60 * to mitigate flickering. If images load faster then the delay they replace
61 * old images smoothly. On the other hand we don't want to keep old images
62 * too long.
63 */
64 FileManager.THUMBNAIL_SHOW_DELAY = 100;
65
58 FileManager.prototype = { 66 FileManager.prototype = {
59 __proto__: cr.EventTarget.prototype 67 __proto__: cr.EventTarget.prototype
60 }; 68 };
61 69
62 // Anonymous "namespace". 70 // Anonymous "namespace".
63 (function() { 71 (function() {
64 72
65 // Private variables and helper functions. 73 // Private variables and helper functions.
66 74
67 /** 75 /**
(...skipping 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after
2088 }; 2096 };
2089 2097
2090 if (!selection.indexes.length) { 2098 if (!selection.indexes.length) {
2091 this.updateCommonActionButtons_(); 2099 this.updateCommonActionButtons_();
2092 this.updatePreviewPanelVisibility_(); 2100 this.updatePreviewPanelVisibility_();
2093 cr.dispatchSimpleEvent(this, 'selection-summarized'); 2101 cr.dispatchSimpleEvent(this, 'selection-summarized');
2094 return; 2102 return;
2095 } 2103 }
2096 2104
2097 this.previewSummary_.textContent = str('COMPUTING_SELECTION'); 2105 this.previewSummary_.textContent = str('COMPUTING_SELECTION');
2098 var thumbnails = this.document_.createDocumentFragment(); 2106 var thumbnails = [];
2099 2107
2100 var pendingFiles = []; 2108 var pendingFiles = [];
2101 var thumbnailCount = 0; 2109 var thumbnailCount = 0;
2102 var thumbnailLoaded = -1; 2110 var thumbnailLoaded = -1;
2103 var forcedShowTimeout = null; 2111 var forcedShowTimeout = null;
2104 var self = this; 2112 var self = this;
2105 2113
2106 function showThumbnails() { 2114 function showThumbnails() {
2107 if (forcedShowTimeout === null) 2115 if (forcedShowTimeout === null)
2108 return; 2116 return;
2109 clearTimeout(forcedShowTimeout); 2117 clearTimeout(forcedShowTimeout);
2110 forcedShowTimeout = null; 2118 forcedShowTimeout = null;
2111 2119
2112 // Selection could change while images are loading. 2120 // Selection could change while images are loading.
2113 if (self.selection == selection) { 2121 if (self.selection == selection) {
2114 removeChildren(self.previewThumbnails_); 2122 removeChildren(self.previewThumbnails_);
2115 self.previewThumbnails_.appendChild(thumbnails); 2123 for (var i = 0; i < thumbnails.length; i++)
2124 self.previewThumbnails_.appendChild(thumbnails[i]);
2116 } 2125 }
2117 } 2126 }
2118 2127
2119 function onThumbnailLoaded() { 2128 function onThumbnailLoaded() {
2120 thumbnailLoaded++; 2129 thumbnailLoaded++;
2121 if (thumbnailLoaded == thumbnailCount) 2130 if (thumbnailLoaded == thumbnailCount)
2122 showThumbnails(); 2131 showThumbnails();
2123 } 2132 }
2124 2133
2125 for (var i = 0; i < selection.indexes.length; i++) { 2134 for (var i = 0; i < selection.indexes.length; i++) {
2126 var entry = this.directoryModel_.getFileList().item(selection.indexes[i]); 2135 var entry = this.directoryModel_.getFileList().item(selection.indexes[i]);
2127 if (!entry) 2136 if (!entry)
2128 continue; 2137 continue;
2129 2138
2130 selection.entries.push(entry); 2139 selection.entries.push(entry);
2131 selection.urls.push(entry.toURL()); 2140 selection.urls.push(entry.toURL());
2132 2141
2133 if (thumbnailCount < MAX_PREVIEW_THUMBAIL_COUNT) { 2142 if (thumbnailCount < MAX_PREVIEW_THUMBAIL_COUNT) {
2134 var box = this.document_.createElement('div'); 2143 var box = this.document_.createElement('div');
2135 box.className = 'thumbnail'; 2144 box.className = 'thumbnail';
2136 function imageLoadCalback(index, box, img, transform) { 2145 if (thumbnailCount == 0) {
2137 if (index == 0) 2146 var zoomed = this.document_.createElement('div');
2138 thumbnails.insertBefore(self.renderThumbnailZoom_(img, transform), 2147 zoomed.hidden = true;
2139 thumbnails.firstChild); 2148 thumbnails.push(zoomed);
2140 onThumbnailLoaded(); 2149 function onFirstThumbnailLoaded(img, transform) {
2150 self.decorateThumbnailZoom_(zoomed, img, transform);
2151 zoomed.hidden = false;
2152 onThumbnailLoaded();
2153 }
2154 var thumbnail = this.renderThumbnailBox_(entry, true,
2155 onFirstThumbnailLoaded);
2156 } else {
2157 var thumbnail = this.renderThumbnailBox_(entry, true,
2158 onThumbnailLoaded);
2141 } 2159 }
2142 var thumbnail = this.renderThumbnailBox_(entry, true,
2143 imageLoadCalback.bind(null, thumbnailCount, box));
2144 thumbnailCount++; 2160 thumbnailCount++;
2145 box.appendChild(thumbnail); 2161 box.appendChild(thumbnail);
2146 box.style.zIndex = MAX_PREVIEW_THUMBAIL_COUNT + 1 - i; 2162 box.style.zIndex = MAX_PREVIEW_THUMBAIL_COUNT + 1 - i;
2147 box.addEventListener('click', 2163 box.addEventListener('click',
2148 this.dispatchDefaultTask_.bind(this, selection)); 2164 this.dispatchDefaultTask_.bind(this, selection));
2149 2165
2150 thumbnails.appendChild(box); 2166 thumbnails.push(box);
2151 } 2167 }
2152 2168
2153 if (selection.iconType == null) { 2169 if (selection.iconType == null) {
2154 selection.iconType = FileType.getIcon(entry); 2170 selection.iconType = FileType.getIcon(entry);
2155 } else if (selection.iconType != 'unknown') { 2171 } else if (selection.iconType != 'unknown') {
2156 var iconType = FileType.getIcon(entry); 2172 var iconType = FileType.getIcon(entry);
2157 if (selection.iconType != iconType) 2173 if (selection.iconType != iconType)
2158 selection.iconType = 'unknown'; 2174 selection.iconType = 'unknown';
2159 } 2175 }
2160 2176
2161 if (entry.isFile) { 2177 if (entry.isFile) {
2162 selection.fileCount += 1; 2178 selection.fileCount += 1;
2163 selection.showBytes |= !FileType.isHosted(entry); 2179 selection.showBytes |= !FileType.isHosted(entry);
2164 } else { 2180 } else {
2165 selection.directoryCount += 1; 2181 selection.directoryCount += 1;
2166 } 2182 }
2167 selection.totalCount++; 2183 selection.totalCount++;
2168 } 2184 }
2169 2185
2170 // Now this.selection is complete. Update buttons. 2186 // Now this.selection is complete. Update buttons.
2171 this.updateCommonActionButtons_(); 2187 this.updateCommonActionButtons_();
2172 this.updatePreviewPanelVisibility_(); 2188 this.updatePreviewPanelVisibility_();
2173 forcedShowTimeout = setTimeout(showThumbnails, 100); 2189 forcedShowTimeout = setTimeout(showThumbnails,
2190 FileManager.THUMBNAIL_SHOW_DELAY);
2174 onThumbnailLoaded(); 2191 onThumbnailLoaded();
2175 2192
2176 if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) { 2193 if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) {
2177 // Some internal tasks cannot be defined in terms of file patterns, 2194 // Some internal tasks cannot be defined in terms of file patterns,
2178 // so we pass selection to check for them manually. 2195 // so we pass selection to check for them manually.
2179 if (selection.directoryCount == 0 && selection.fileCount > 0) { 2196 if (selection.directoryCount == 0 && selection.fileCount > 0) {
2180 // Only files, not directories, are supported for external tasks. 2197 // Only files, not directories, are supported for external tasks.
2181 chrome.fileBrowserPrivate.getFileTasks( 2198 chrome.fileBrowserPrivate.getFileTasks(
2182 selection.urls, 2199 selection.urls,
2183 this.onTasksFound_.bind(this, selection)); 2200 this.onTasksFound_.bind(this, selection));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 FileManager.prototype.isSelectionAvailable = function() { 2235 FileManager.prototype.isSelectionAvailable = function() {
2219 return !this.isOnGData() || 2236 return !this.isOnGData() ||
2220 !this.isOffline() || 2237 !this.isOffline() ||
2221 this.selection.allGDataFilesPresent; 2238 this.selection.allGDataFilesPresent;
2222 }; 2239 };
2223 2240
2224 /** 2241 /**
2225 * Creates enlarged image for a bottom pannel thumbnail. 2242 * Creates enlarged image for a bottom pannel thumbnail.
2226 * Image's assumed to be just loaded and not inserted into the DOM. 2243 * Image's assumed to be just loaded and not inserted into the DOM.
2227 * 2244 *
2245 * @param {HTMLElement} largeImageBox DIV element to decorate.
2228 * @param {HTMLElement} img Loaded image. 2246 * @param {HTMLElement} img Loaded image.
2229 * @param {Object} transform Image transformation description. 2247 * @param {Object} transform Image transformation description.
2230 * @return {Element} Created element.
2231 */ 2248 */
2232 FileManager.prototype.renderThumbnailZoom_ = function(img, transform) { 2249 FileManager.prototype.decorateThumbnailZoom_ = function(largeImageBox,
2250 img, transform) {
2233 var width = img.width; 2251 var width = img.width;
2234 var height = img.height; 2252 var height = img.height;
2235 var THUMBNAIL_SIZE = 45; 2253 var THUMBNAIL_SIZE = 45;
2236 2254
2237 if (width < THUMBNAIL_SIZE * 2 && height < THUMBNAIL_SIZE * 2) 2255 if (width < THUMBNAIL_SIZE * 2 && height < THUMBNAIL_SIZE * 2)
2238 return; 2256 return;
Vladislav Kaznacheev 2012/05/18 06:58:57 if we return here the the DIV will be empty. Will
SeRya 2012/05/18 09:19:37 It doesn't show up. However thumbnails used to hid
2239 2257
2240 var scale = Math.min(1, 2258 var scale = Math.min(1,
2241 IMAGE_HOVER_PREVIEW_SIZE / Math.max(width, height)); 2259 IMAGE_HOVER_PREVIEW_SIZE / Math.max(width, height));
2242 2260
2243 var imageWidth = Math.round(width * scale); 2261 var imageWidth = Math.round(width * scale);
2244 var imageHeight = Math.round(height * scale); 2262 var imageHeight = Math.round(height * scale);
2245 2263
2246 var largeImage = this.document_.createElement('img'); 2264 var largeImage = this.document_.createElement('img');
2247 if (scale < 0.3) { 2265 if (scale < 0.3) {
2248 // Scaling large images kills animation. Downscale it in advance. 2266 // Scaling large images kills animation. Downscale it in advance.
2249 2267
2250 // Canvas scales images with liner interpolation. Make a larger 2268 // Canvas scales images with liner interpolation. Make a larger
2251 // image (but small enough to not kill animation) and let IMG 2269 // image (but small enough to not kill animation) and let IMG
2252 // scale it smoothly. 2270 // scale it smoothly.
2253 var INTERMEDIATE_SCALE = 3; 2271 var INTERMEDIATE_SCALE = 3;
2254 var canvas = this.document_.createElement('canvas'); 2272 var canvas = this.document_.createElement('canvas');
2255 canvas.width = imageWidth * INTERMEDIATE_SCALE; 2273 canvas.width = imageWidth * INTERMEDIATE_SCALE;
2256 canvas.height = imageHeight * INTERMEDIATE_SCALE; 2274 canvas.height = imageHeight * INTERMEDIATE_SCALE;
2257 var ctx = canvas.getContext('2d'); 2275 var ctx = canvas.getContext('2d');
2258 ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 2276 ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
2259 // Using bigger than default compression reduces image size by 2277 // Using bigger than default compression reduces image size by
2260 // several times. Quality degradation compensated by greater resolution. 2278 // several times. Quality degradation compensated by greater resolution.
2261 largeImage.src = canvas.toDataURL('image/jpeg', 0.6); 2279 largeImage.src = canvas.toDataURL('image/jpeg', 0.6);
2262 } else { 2280 } else {
2263 largeImage.src = img.src; 2281 largeImage.src = img.src;
2264 } 2282 }
2265 var largeImageBox = this.document_.createElement('div');
2266 largeImageBox.className = 'popup'; 2283 largeImageBox.className = 'popup';
2267 2284
2268 var boxWidth = Math.max(THUMBNAIL_SIZE, imageWidth); 2285 var boxWidth = Math.max(THUMBNAIL_SIZE, imageWidth);
2269 var boxHeight = Math.max(THUMBNAIL_SIZE, imageHeight); 2286 var boxHeight = Math.max(THUMBNAIL_SIZE, imageHeight);
2270 2287
2271 if (transform && transform.rotate90 % 2 == 1) { 2288 if (transform && transform.rotate90 % 2 == 1) {
2272 var t = boxWidth; 2289 var t = boxWidth;
2273 boxWidth = boxHeight; 2290 boxWidth = boxHeight;
2274 boxHeight = t; 2291 boxHeight = t;
2275 } 2292 }
2276 2293
2277 var style = largeImageBox.style; 2294 var style = largeImageBox.style;
2278 style.width = boxWidth + 'px'; 2295 style.width = boxWidth + 'px';
2279 style.height = boxHeight + 'px'; 2296 style.height = boxHeight + 'px';
2280 style.top = (-boxHeight + THUMBNAIL_SIZE) + 'px'; 2297 style.top = (-boxHeight + THUMBNAIL_SIZE) + 'px';
2281 2298
2282 var style = largeImage.style; 2299 var style = largeImage.style;
2283 style.width = imageWidth + 'px'; 2300 style.width = imageWidth + 'px';
2284 style.height = imageHeight + 'px'; 2301 style.height = imageHeight + 'px';
2285 style.left = (boxWidth - imageWidth) / 2 + 'px'; 2302 style.left = (boxWidth - imageWidth) / 2 + 'px';
2286 style.top = (boxHeight - imageHeight) / 2 + 'px'; 2303 style.top = (boxHeight - imageHeight) / 2 + 'px';
2287 style.position = 'relative'; 2304 style.position = 'relative';
2288 2305
2289 util.applyTransform(largeImage, transform); 2306 util.applyTransform(largeImage, transform);
2290 2307
2291 largeImageBox.appendChild(largeImage); 2308 largeImageBox.appendChild(largeImage);
2292 largeImageBox.style.zIndex = 1000; 2309 largeImageBox.style.zIndex = 1000;
2293 return largeImageBox; 2310 return largeImageBox;
Vladislav Kaznacheev 2012/05/18 06:59:35 return is not required anymore
SeRya 2012/05/18 09:19:37 Done.
2294 }; 2311 };
2295 2312
2296 FileManager.prototype.updatePreviewPanelVisibility_ = function() { 2313 FileManager.prototype.updatePreviewPanelVisibility_ = function() {
2297 var panel = this.previewPanel_; 2314 var panel = this.previewPanel_;
2298 var state = panel.getAttribute('visibility'); 2315 var state = panel.getAttribute('visibility');
2299 var mustBeVisible = (this.selection.totalCount > 0); 2316 var mustBeVisible = (this.selection.totalCount > 0);
2300 var self = this; 2317 var self = this;
2301 2318
2302 switch (state) { 2319 switch (state) {
2303 case 'visible': 2320 case 'visible':
(...skipping 2322 matching lines...) Expand 10 before | Expand all | Expand 10 after
4626 4643
4627 function closeBanner() { 4644 function closeBanner() {
4628 self.cleanupGDataWelcome_(); 4645 self.cleanupGDataWelcome_();
4629 // Stop showing the welcome banner. 4646 // Stop showing the welcome banner.
4630 localStorage[WELCOME_HEADER_COUNTER_KEY] = WELCOME_HEADER_COUNTER_LIMIT; 4647 localStorage[WELCOME_HEADER_COUNTER_KEY] = WELCOME_HEADER_COUNTER_LIMIT;
4631 } 4648 }
4632 4649
4633 return maybeShowBanner; 4650 return maybeShowBanner;
4634 }; 4651 };
4635 })(); 4652 })();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698