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 || WI.CollectionContentView.titleForCollection(collection);
37 this._contentViewConstructor = contentViewConstructor;
38 this._contentViewMap = new Map;
39 this._handleClickMap = new WeakMap;
40 this._selectedItem = null;
41 this._selectionEnabled = false;
44 static titleForCollection(collection)
46 switch (collection.typeVerifier) {
47 case WI.Collection.TypeVerifier.Frame:
48 return WI.UIString("Frames");
49 case WI.Collection.TypeVerifier.Resource:
50 return WI.UIString("Resources");
51 case WI.Collection.TypeVerifier.Script:
52 return WI.UIString("Scripts");
53 case WI.Collection.TypeVerifier.CSSStyleSheet:
54 return WI.UIString("Stylesheets");
55 case WI.Collection.TypeVerifier.Canvas:
56 return WI.UIString("Canvases");
57 case WI.Collection.TypeVerifier.ShaderProgram:
58 return WI.UIString("Shader Programs");
61 console.warn("No default title for Collection type verifier.", collection.typeVerifier);
62 return WI.UIString("Collection");
67 get supplementalRepresentedObjects()
69 if (this._selectedItem)
70 return [this._selectedItem];
74 get selectionEnabled()
76 return this._selectionEnabled;
79 set selectionEnabled(value)
81 if (this._selectionEnabled === value)
84 this._selectionEnabled = value;
85 if (!this._selectionEnabled)
86 this._selectItem(null);
91 console.assert(this._selectionEnabled, "Attempted to set selected item when selection is disabled.");
92 if (!this._selectionEnabled)
95 let contentView = this._contentViewMap.get(item);
96 console.assert(contentView, "Missing contet view for item.", item);
100 this._selectItem(item);
101 contentView.element.scrollIntoViewIfNeeded();
106 addContentViewForItem(item)
108 if (!this._contentViewConstructor)
111 if (this._contentViewMap.has(item)) {
112 console.assert(false, "Already added ContentView for item.", item);
116 this._hideContentPlaceholder();
118 let contentView = new this._contentViewConstructor(item);
119 console.assert(contentView instanceof WI.ContentView);
121 let handleClick = (event) => {
122 if (event.button !== 0 || event.ctrlKey)
125 if (this._selectionEnabled)
126 this._selectItem(item);
128 WI.showRepresentedObject(item);
131 this._contentViewMap.set(item, contentView);
132 this._handleClickMap.set(item, handleClick);
133 contentView.element.addEventListener("click", handleClick);
135 this.addSubview(contentView);
136 this.contentViewAdded(contentView);
141 removeContentViewForItem(item)
143 if (!this._contentViewConstructor)
146 let contentView = this._contentViewMap.get(item);
147 console.assert(contentView);
151 if (this._selectedItem === item)
152 this._selectItem(null);
154 this.removeSubview(contentView);
155 this._contentViewMap.delete(item);
156 this.contentViewRemoved(contentView);
158 contentView.hidden();
160 contentView.removeEventListener(null, null, this);
162 let handleClick = this._handleClickMap.get(item);
163 console.assert(handleClick);
166 contentView.element.removeEventListener("click", handleClick);
167 this._handleClickMap.delete(item);
170 if (!this.subviews.length)
171 this._showContentPlaceholder();
174 contentViewAdded(contentView)
176 // Implemented by subclasses.
179 contentViewRemoved(contentView)
181 // Implemented by subclasses.
186 let items = this.representedObject.items;
187 if (!items.size || !this._contentViewConstructor) {
188 this._showContentPlaceholder();
192 for (let item of items)
193 this.addContentViewForItem(item);
200 this.representedObject.addEventListener(WI.Collection.Event.ItemAdded, this._handleItemAdded, this);
201 this.representedObject.addEventListener(WI.Collection.Event.ItemRemoved, this._handleItemRemoved, this);
203 for (let item of this._contentViewMap.keys()) {
204 if (this.representedObject.items.has(item))
207 this.removeContentViewForItem(item);
208 if (this._selectedItem === item)
209 this._selectItem(null);
212 for (let item of this.representedObject.items) {
213 if (!this._contentViewMap.has(item))
214 this.addContentViewForItem(item);
220 this.representedObject.removeEventListener(null, null, this);
227 _handleItemAdded(event)
229 let item = event.data.item;
233 this.addContentViewForItem(item);
236 _handleItemRemoved(event)
238 let item = event.data.item;
242 this.removeContentViewForItem(item);
245 _handleContentError(event)
247 if (event && event.target)
248 this._removeContentViewForItem(event.target.representedObject);
253 if (this._selectedItem === item)
256 if (this._selectedItem) {
257 let contentView = this._contentViewMap.get(this._selectedItem);
258 console.assert(contentView, "Missing ContentView for deselected item.", this._selectedItem);
259 contentView.element.classList.remove("selected");
262 this._selectedItem = item;
264 if (this._selectedItem) {
265 let selectedContentView = this._contentViewMap.get(this._selectedItem);
266 console.assert(selectedContentView, "Missing ContentView for selected item.", this._selectedItem);
267 selectedContentView.element.classList.add("selected");
270 this.dispatchEventToListeners(WI.ContentView.Event.SupplementalRepresentedObjectsDidChange);
273 _showContentPlaceholder()
275 if (!this._contentPlaceholder)
276 this._contentPlaceholder = new WI.TitleView(this._contentPlaceholderText);
278 if (!this._contentPlaceholder.parentView)
279 this.debounce(250).addSubview(this._contentPlaceholder);
282 _hideContentPlaceholder()
284 this.addSubview.cancelDebounce();
286 if (this._contentPlaceholder && this._contentPlaceholder.parentView)
287 this.removeSubview(this._contentPlaceholder);