1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * Data model for gallery.
8 * @param {!MetadataModel} metadataModel
9 * @param {!EntryListWatcher=} opt_watcher Entry list watcher.
11 * @extends {cr.ui.ArrayDataModel}
13 function GalleryDataModel(metadataModel, opt_watcher) {
14 cr.ui.ArrayDataModel.call(this, []);
17 * File system metadata.
18 * @private {!MetadataModel}
21 this.metadataModel_ = metadataModel;
24 * Directory where the image is saved if the image is located in a read-only
26 * @public {DirectoryEntry}
28 this.fallbackSaveDirectory = null;
30 // Start to watch file system entries.
31 var watcher = opt_watcher ? opt_watcher : new EntryListWatcher(this);
32 watcher.getEntry = function(item) { return item.getEntry(); };
36 * Maximum number of full size image cache.
41 GalleryDataModel.MAX_FULL_IMAGE_CACHE_ = 3;
44 * Maximum number of screen size image cache.
49 GalleryDataModel.MAX_SCREEN_IMAGE_CACHE_ = 5;
51 GalleryDataModel.prototype = {
52 __proto__: cr.ui.ArrayDataModel.prototype
58 * @param {!VolumeManager} volumeManager Volume manager instance.
59 * @param {!Gallery.Item} item Original gallery item.
60 * @param {!HTMLCanvasElement} canvas Canvas containing new image.
61 * @param {boolean} overwrite Whether to overwrite the image to the item or not.
62 * @return {!Promise} Promise to be fulfilled with when the operation completes.
64 GalleryDataModel.prototype.saveItem = function(
65 volumeManager, item, canvas, overwrite) {
66 var oldEntry = item.getEntry();
67 var oldLocationInfo = item.getLocationInfo();
68 return new Promise(function(fulfill, reject) {
72 this.fallbackSaveDirectory,
77 reject('Failed to save the image.');
81 // Current entry is updated.
83 var event = new Event('content');
85 event.oldEntry = oldEntry;
86 event.thumbnailChanged = true;
87 this.dispatchEvent(event);
89 if (!util.isSameEntry(oldEntry, item.getEntry())) {
91 this.metadataModel_.get(
92 [oldEntry], Gallery.PREFETCH_PROPERTY_NAMES),
93 new ThumbnailModel(this.metadataModel_).get([oldEntry])
94 ]).then(function(itemLists) {
95 // New entry is added and the item now tracks it.
96 // Add another item for the old entry.
97 var anotherItem = new Gallery.Item(
103 // The item must be added behind the existing item so that it does
104 // not change the index of the existing item.
105 // TODO(hirono): Update the item index of the selection model
107 this.splice(this.indexOf(item) + 1, 0, anotherItem);
108 }.bind(this)).then(fulfill, reject);
117 * Evicts image caches in the items.
119 GalleryDataModel.prototype.evictCache = function() {
120 // Sort the item by the last accessed date.
121 var sorted = this.slice().sort(function(a, b) {
122 return b.getLastAccessedDate() - a.getLastAccessedDate();
126 var contentCacheCount = 0;
127 var screenCacheCount = 0;
128 for (var i = 0; i < sorted.length; i++) {
129 if (sorted[i].contentImage) {
130 if (++contentCacheCount > GalleryDataModel.MAX_FULL_IMAGE_CACHE_) {
131 if (sorted[i].contentImage.parentNode) {
132 console.error('The content image has a parent node.');
134 // Force to free the buffer of the canvas by assigning zero size.
135 sorted[i].contentImage.width = 0;
136 sorted[i].contentImage.height = 0;
137 sorted[i].contentImage = null;
141 if (sorted[i].screenImage) {
142 if (++screenCacheCount > GalleryDataModel.MAX_SCREEN_IMAGE_CACHE_) {
143 if (sorted[i].screenImage.parentNode) {
144 console.error('The screen image has a parent node.');
146 // Force to free the buffer of the canvas by assigning zero size.
147 sorted[i].screenImage.width = 0;
148 sorted[i].screenImage.height = 0;
149 sorted[i].screenImage = null;