2 * Copyright (C) 2016 Devin Rousso <webkit@devinrousso.com>. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 WI.CollectionContentView = class CollectionContentView extends WI.ContentView
28 constructor(collection, contentViewConstructor, contentPlaceholderText)
30 console.assert(collection instanceof WI.Collection);
34 this.element.classList.add("collection");
36 this._contentPlaceholderText = contentPlaceholderText || collection.displayName;
37 this._contentViewConstructor = contentViewConstructor;
38 this._contentViewMap = new Map;
39 this._handleClickMap = new WeakMap;
40 this._selectedItem = null;
41 this._selectionEnabled = false;
46 get supplementalRepresentedObjects()
48 if (this._selectedItem)
49 return [this._selectedItem];
53 get selectionEnabled()
55 return this._selectionEnabled;
58 set selectionEnabled(value)
60 if (this._selectionEnabled === value)
63 this._selectionEnabled = value;
64 if (!this._selectionEnabled)
65 this._selectItem(null);
70 console.assert(this._selectionEnabled, "Attempted to set selected item when selection is disabled.");
71 if (!this._selectionEnabled)
74 let contentView = this._contentViewMap.get(item);
75 console.assert(contentView, "Missing contet view for item.", item);
79 this._selectItem(item);
80 contentView.element.scrollIntoViewIfNeeded();
85 addContentViewForItem(item)
87 if (!this._contentViewConstructor)
90 if (this._contentViewMap.has(item)) {
91 console.assert(false, "Already added ContentView for item.", item);
95 this._hideContentPlaceholder();
97 let contentView = new this._contentViewConstructor(item);
98 console.assert(contentView instanceof WI.ContentView);
100 let handleClick = (event) => {
101 if (event.button !== 0 || event.ctrlKey)
104 if (this._selectionEnabled)
105 this._selectItem(item);
107 WI.showRepresentedObject(item);
110 this._contentViewMap.set(item, contentView);
111 this._handleClickMap.set(item, handleClick);
112 contentView.element.addEventListener("click", handleClick);
114 this.addSubview(contentView);
115 this.contentViewAdded(contentView);
120 removeContentViewForItem(item)
122 if (!this._contentViewConstructor)
125 let contentView = this._contentViewMap.get(item);
126 console.assert(contentView);
130 if (this._selectedItem === item)
131 this._selectItem(null);
133 this.removeSubview(contentView);
134 this._contentViewMap.delete(item);
135 this.contentViewRemoved(contentView);
137 contentView.hidden();
139 contentView.removeEventListener(null, null, this);
141 let handleClick = this._handleClickMap.get(item);
142 console.assert(handleClick);
145 contentView.element.removeEventListener("click", handleClick);
146 this._handleClickMap.delete(item);
149 if (!this.subviews.length)
150 this._showContentPlaceholder();
153 contentViewAdded(contentView)
155 // Implemented by subclasses.
158 contentViewRemoved(contentView)
160 // Implemented by subclasses.
165 let items = this.representedObject.items;
166 if (!items.size || !this._contentViewConstructor) {
167 this._showContentPlaceholder();
176 this.representedObject.addEventListener(WI.Collection.Event.ItemAdded, this._handleItemAdded, this);
177 this.representedObject.addEventListener(WI.Collection.Event.ItemRemoved, this._handleItemRemoved, this);
179 for (let item of this._contentViewMap.keys()) {
180 if (this.representedObject.items.has(item))
183 this.removeContentViewForItem(item);
184 if (this._selectedItem === item)
185 this._selectItem(null);
188 for (let item of this.representedObject.items) {
189 if (!this._contentViewMap.has(item))
190 this.addContentViewForItem(item);
196 this.representedObject.removeEventListener(null, null, this);
203 _handleItemAdded(event)
205 let item = event.data.item;
209 this.addContentViewForItem(item);
212 _handleItemRemoved(event)
214 let item = event.data.item;
218 this.removeContentViewForItem(item);
221 _handleContentError(event)
223 if (event && event.target)
224 this._removeContentViewForItem(event.target.representedObject);
229 if (this._selectedItem === item)
232 if (this._selectedItem) {
233 let contentView = this._contentViewMap.get(this._selectedItem);
234 console.assert(contentView, "Missing ContentView for deselected item.", this._selectedItem);
235 contentView.element.classList.remove("selected");
238 this._selectedItem = item;
240 if (this._selectedItem) {
241 let selectedContentView = this._contentViewMap.get(this._selectedItem);
242 console.assert(selectedContentView, "Missing ContentView for selected item.", this._selectedItem);
243 selectedContentView.element.classList.add("selected");
246 this.dispatchEventToListeners(WI.ContentView.Event.SupplementalRepresentedObjectsDidChange);
249 _showContentPlaceholder()
251 if (!this._contentPlaceholder)
252 this._contentPlaceholder = new WI.TitleView(this._contentPlaceholderText);
254 if (!this._contentPlaceholder.parentView)
255 this.addSubview(this._contentPlaceholder);
258 _hideContentPlaceholder()
260 this.addSubview.cancelDebounce();
262 if (this._contentPlaceholder && this._contentPlaceholder.parentView)
263 this.removeSubview(this._contentPlaceholder);