Source/WebInspectorUI/ChangeLog

 12018-03-14 Devin Rousso <webkit@devinrousso.com>
 2
 3 Web Inspector: Canvas tab: create icons for recordings/shaders in the preview tile
 4 https://bugs.webkit.org/show_bug.cgi?id=183650
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * Localizations/en.lproj/localizedStrings.js:
 9
 10 * UserInterface/Views/CanvasContentView.js:
 11 (WI.CanvasContentView):
 12 (WI.CanvasContentView.prototype.initialLayout):
 13 (WI.CanvasContentView.prototype.attached):
 14 (WI.CanvasContentView.prototype._recordingStopped):
 15 (WI.CanvasContentView.prototype._shaderProgramAdded):
 16 (WI.CanvasContentView.prototype._shaderProgramRemoved):
 17 (WI.CanvasContentView.prototype._updateViewRelated):
 18 (WI.CanvasContentView.prototype._handleViewShaderButtonClicked):
 19 (WI.CanvasContentView.prototype._handleViewRecordingButtonClicked):
 20 (WI.CanvasContentView.prototype._addRecording): Deleted.
 21 (WI.CanvasContentView.prototype._handleRecordingSelectElementChange): Deleted.
 22 * UserInterface/Views/CanvasOverviewContentView.css:
 23 (.content-view.canvas-overview .content-view.canvas > footer > .view-related):
 24 (.content-view.canvas-overview .content-view.canvas > footer > .view-related > :matches(.view-shader, .view-recording)):
 25 (.content-view.canvas-overview .content-view.canvas > footer > .view-related > img + img):
 26 (.content-view.canvas-overview .content-view.canvas > footer > .view-related > .view-shader):
 27 (.content-view.canvas-overview .content-view.canvas > footer > .view-related > .view-recording):
 28 (.content-view.canvas-overview .content-view.canvas > footer > .recordings): Deleted.
 29 (.content-view.canvas-overview .content-view.canvas > footer > .recordings::before): Deleted.
 30 (.content-view.canvas-overview .content-view.canvas > footer > .recordings > select): Deleted.
 31 (.content-view.canvas-overview .content-view.canvas > footer .recordings > select:focus): Deleted.
 32 Create two image buttons in the bottom left corner of each canvas tile that appear when the
 33 canvas has associated shaders and/or recordings. Clicking each image button will function
 34 similar to path components, in that if there is only one shader/recording, it is immediately
 35 selected, whereas if there are multiple a dropdown is shown.
 36
1372018-03-14 Devin Rousso <webkit@devinrousso.com>
238
339 Web Inspector: Canvas: a recording initiated by the user should be shown immediately on completion

Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

@@localizedStrings["Vertex"] = "Vertex";
10311031localizedStrings["Vertex Shader"] = "Vertex Shader";
10321032localizedStrings["Vertical"] = "Vertical";
10331033localizedStrings["View Image"] = "View Image";
1034 localizedStrings["View Recordings... (%d)"] = "View Recordings... (%d)";
 1034localizedStrings["View Recording"] = "View Recording";
 1035localizedStrings["View Shader"] = "View Shader";
10351036localizedStrings["View variable value"] = "View variable value";
10361037localizedStrings["Visibility"] = "Visibility";
10371038localizedStrings["Visible"] = "Visible";

Source/WebInspectorUI/UserInterface/Views/CanvasContentView.js

@@WI.CanvasContentView = class CanvasContentView extends WI.ContentView
4242 this._pixelSize = null;
4343 this._pixelSizeElement = null;
4444 this._canvasNode = null;
45  this._recordingOptionElementMap = new WeakMap;
4645
4746 if (this.representedObject.contextType === WI.Canvas.ContextType.Canvas2D || this.representedObject.contextType === WI.Canvas.ContextType.WebGL) {
4847 const toolTip = WI.UIString("Start recording canvas actions.\nShift-click to record a single frame.");

@@WI.CanvasContentView = class CanvasContentView extends WI.ContentView
127126 let footer = this.element.appendChild(document.createElement("footer"));
128127 footer.addEventListener("click", (event) => { event.stopPropagation(); });
129128
130  this._recordingSelectContainer = footer.appendChild(document.createElement("div"));
131  this._recordingSelectContainer.classList.add("recordings", "hidden");
 129 this._viewRelatedContainer = footer.appendChild(document.createElement("div"));
 130 this._viewRelatedContainer.classList.add("view-related");
132131
133  this._recordingSelectText = this._recordingSelectContainer.appendChild(document.createElement("span"));
 132 this._viewShaderButton = document.createElement("img");
 133 this._viewShaderButton.classList.add("view-shader");
 134 this._viewShaderButton.title = WI.UIString("View Shader");
 135 this._viewShaderButton.addEventListener("click", this._handleViewShaderButtonClicked.bind(this));
134136
135  this._recordingSelectElement = this._recordingSelectContainer.appendChild(document.createElement("select"));
136  this._recordingSelectElement.addEventListener("change", this._handleRecordingSelectElementChange.bind(this));
 137 this._viewRecordingButton = document.createElement("img");
 138 this._viewRecordingButton.classList.add("view-recording");
 139 this._viewRecordingButton.title = WI.UIString("View Recording");
 140 this._viewRecordingButton.addEventListener("click", this._handleViewRecordingButtonClicked.bind(this));
137141
138  for (let recording of this.representedObject.recordingCollection.items)
139  this._addRecording(recording);
 142 this._updateViewRelated();
140143
141144 let flexibleSpaceElement = footer.appendChild(document.createElement("div"));
142145 flexibleSpaceElement.className = "flexible-space";

@@WI.CanvasContentView = class CanvasContentView extends WI.ContentView
206209 WI.canvasManager.addEventListener(WI.CanvasManager.Event.RecordingStarted, this._recordingStarted, this);
207210 WI.canvasManager.addEventListener(WI.CanvasManager.Event.RecordingProgress, this._recordingProgress, this);
208211 WI.canvasManager.addEventListener(WI.CanvasManager.Event.RecordingStopped, this._recordingStopped, this);
 212 WI.canvasManager.addEventListener(WI.CanvasManager.Event.ShaderProgramAdded, this._shaderProgramAdded, this);
 213 WI.canvasManager.addEventListener(WI.CanvasManager.Event.ShaderProgramRemoved, this._shaderProgramRemoved, this);
209214
210215 WI.settings.showImageGrid.addEventListener(WI.Setting.Event.Changed, this._updateImageGrid, this);
211 
212  if (this.didInitialLayout)
213  this._recordingSelectElement.selectedIndex = -1;
214216 }
215217
216218 detached()

@@WI.CanvasContentView = class CanvasContentView extends WI.ContentView
242244 this._previewContainerElement.appendChild(this._errorElement);
243245 }
244246
245  _addRecording(recording)
246  {
247  let optionElement = this._recordingSelectElement.appendChild(document.createElement("option"));
248  optionElement.textContent = recording.displayName;
249 
250  this._recordingOptionElementMap.set(optionElement, recording);
251 
252  let recordingCount = this._recordingSelectElement.options.length;
253  this._recordingSelectText.textContent = WI.UIString("View Recordings... (%d)").format(recordingCount);
254  this._recordingSelectContainer.classList.remove("hidden");
255 
256  this._recordingSelectElement.selectedIndex = -1;
257  }
258 
259247 _toggleRecording(event)
260248 {
261249 if (this.representedObject.isRecording)

@@WI.CanvasContentView = class CanvasContentView extends WI.ContentView
285273 {
286274 this._updateRecordNavigationItem();
287275
288  let {canvas, recording} = event.data;
 276 let {canvas} = event.data;
289277 if (canvas !== this.representedObject)
290278 return;
291279
292280 this._updateProgressView();
293281
294  if (recording)
295  this._addRecording(recording);
 282 this._updateViewRelated();
296283 }
297284
298  _handleRecordingSelectElementChange(event)
 285 _shaderProgramAdded(event)
299286 {
300  let selectedOption = this._recordingSelectElement.options[this._recordingSelectElement.selectedIndex];
301  console.assert(selectedOption, "An option should have been selected.");
302  if (!selectedOption)
 287 let {shaderProgram} = event.data;
 288 if (!shaderProgram || shaderProgram.canvas !== this.representedObject)
303289 return;
304290
305  let representedObject = this._recordingOptionElementMap.get(selectedOption);
306  console.assert(representedObject, "Missing map entry for option.");
307  if (!representedObject)
 291 this._updateViewRelated();
 292 }
 293
 294 _shaderProgramRemoved(event)
 295 {
 296 let {shaderProgram} = event.data;
 297 if (!shaderProgram || shaderProgram.canvas !== this.representedObject)
308298 return;
309299
310  WI.showRepresentedObject(representedObject);
 300 this._updateViewRelated();
311301 }
312302
313303 _refreshPixelSize()

@@WI.CanvasContentView = class CanvasContentView extends WI.ContentView
425415 this._progressView.title = title;
426416 this._progressView.subtitle = bufferUsed ? Number.bytesToString(bufferUsed) : "";
427417 }
 418
 419 _updateViewRelated()
 420 {
 421 this._viewRelatedContainer.removeChildren();
 422
 423 if (this.representedObject.shaderProgramCollection.items.size)
 424 this._viewRelatedContainer.appendChild(this._viewShaderButton);
 425
 426 if (this.representedObject.recordingCollection.items.size)
 427 this._viewRelatedContainer.appendChild(this._viewRecordingButton);
 428 }
 429
 430 _handleViewShaderButtonClicked(event)
 431 {
 432 let shaderPrograms = Array.from(this.representedObject.shaderProgramCollection.items);
 433 console.assert(shaderPrograms.length);
 434 if (!shaderPrograms.length)
 435 return;
 436
 437 if (shaderPrograms.length === 1) {
 438 WI.showRepresentedObject(shaderPrograms[0]);
 439 return;
 440 }
 441
 442 let contextMenu = WI.ContextMenu.createFromEvent(event);
 443
 444 for (let shaderProgram of shaderPrograms) {
 445 contextMenu.appendItem(shaderProgram.displayName, (event) => {
 446 WI.showRepresentedObject(shaderProgram);
 447 });
 448 }
 449
 450 contextMenu.show();
 451 }
 452
 453 _handleViewRecordingButtonClicked(event)
 454 {
 455 let recordings = Array.from(this.representedObject.recordingCollection.items);
 456 console.assert(recordings.length);
 457 if (!recordings.length)
 458 return;
 459
 460 if (recordings.length === 1) {
 461 WI.showRepresentedObject(recordings[0]);
 462 return;
 463 }
 464
 465 let contextMenu = WI.ContextMenu.createFromEvent(event);
 466
 467 for (let recording of recordings) {
 468 contextMenu.appendItem(recording.displayName, (event) => {
 469 WI.showRepresentedObject(recording);
 470 });
 471 }
 472
 473 contextMenu.show();
 474 }
428475};

Source/WebInspectorUI/UserInterface/Views/CanvasOverviewContentView.css

143143 border-top: none;
144144}
145145
146 .content-view.canvas-overview .content-view.canvas > footer > .recordings {
147  position: absolute;
 146.content-view.canvas-overview .content-view.canvas > footer > .view-related {
148147 display: flex;
149148 align-items: center;
150149}
151150
152 .content-view.canvas-overview .content-view.canvas > footer > .recordings::before {
153  display: inline-block;
 151.content-view.canvas-overview .content-view.canvas > footer > .view-related > :matches(.view-shader, .view-recording) {
154152 width: 16px;
155  margin-top: 3px;
156  -webkit-padding-end: 4px;
157  content: url(../Images/Recording.svg);
 153 height: 16px;
158154}
159155
160 .content-view.canvas-overview .content-view.canvas > footer > .recordings > select {
161  position: absolute;
162  top: 0;
163  right: 0;
164  bottom: 0;
165  left: 0;
166  margin: 0;
167  padding: 0;
168  border: none;
169  opacity: 0;
170  -webkit-appearance: none;
 156.content-view.canvas-overview .content-view.canvas > footer > .view-related > img + img {
 157 -webkit-margin-start: 4px;
171158}
172159
173 .content-view.canvas-overview .content-view.canvas > footer .recordings > select:focus {
174  -webkit-margin-start: 11px;
 160.content-view.canvas-overview .content-view.canvas > footer > .view-related > .view-shader {
 161 content: image-set(url(../Images/DocumentGL.png) 1x, url(../Images/DocumentGL@2x.png) 2x);
 162}
 163
 164.content-view.canvas-overview .content-view.canvas > footer > .view-related > .view-recording {
 165 content: url(../Images/Recording.svg);
175166}
176167
177168.content-view.canvas-overview .content-view.canvas > footer > .flexible-space {