OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | |
31 /** | 30 /** |
32 * @constructor | 31 * @unrestricted |
33 * @extends {WebInspector.VBox} | |
34 */ | 32 */ |
35 WebInspector.RevisionHistoryView = function() | 33 WebInspector.RevisionHistoryView = class extends WebInspector.VBox { |
36 { | 34 constructor() { |
37 WebInspector.VBox.call(this); | 35 super(); |
38 this._uiSourceCodeItems = new Map(); | 36 this._uiSourceCodeItems = new Map(); |
39 | 37 |
40 this._treeOutline = new TreeOutlineInShadow(); | 38 this._treeOutline = new TreeOutlineInShadow(); |
41 this._treeOutline.registerRequiredCSS("sources/revisionHistory.css"); | 39 this._treeOutline.registerRequiredCSS('sources/revisionHistory.css'); |
42 this._treeOutline.makeDense(); | 40 this._treeOutline.makeDense(); |
43 this.element.appendChild(this._treeOutline.element); | 41 this.element.appendChild(this._treeOutline.element); |
44 | 42 |
45 /** | 43 /** |
46 * @param {!WebInspector.UISourceCode} uiSourceCode | 44 * @param {!WebInspector.UISourceCode} uiSourceCode |
47 * @this {WebInspector.RevisionHistoryView} | 45 * @this {WebInspector.RevisionHistoryView} |
48 */ | 46 */ |
49 function populateRevisions(uiSourceCode) | 47 function populateRevisions(uiSourceCode) { |
50 { | 48 if (uiSourceCode.history.length) |
51 if (uiSourceCode.history.length) | 49 this._createUISourceCodeItem(uiSourceCode); |
52 this._createUISourceCodeItem(uiSourceCode); | |
53 } | 50 } |
54 | 51 |
55 WebInspector.workspace.uiSourceCodes().forEach(populateRevisions.bind(this))
; | 52 WebInspector.workspace.uiSourceCodes().forEach(populateRevisions.bind(this))
; |
56 WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.Workin
gCopyCommittedByUser, this._revisionAdded, this); | 53 WebInspector.workspace.addEventListener( |
57 WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISour
ceCodeRemoved, this._uiSourceCodeRemoved, this); | 54 WebInspector.Workspace.Events.WorkingCopyCommittedByUser, this._revision
Added, this); |
| 55 WebInspector.workspace.addEventListener( |
| 56 WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRem
oved, this); |
58 WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.Projec
tRemoved, this._projectRemoved, this); | 57 WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.Projec
tRemoved, this._projectRemoved, this); |
| 58 } |
| 59 |
| 60 /** |
| 61 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 62 */ |
| 63 static showHistory(uiSourceCode) { |
| 64 WebInspector.viewManager.showView('sources.history'); |
| 65 var historyView = /** @type {!WebInspector.RevisionHistoryView} */ ( |
| 66 self.runtime.sharedInstance(WebInspector.RevisionHistoryView)); |
| 67 historyView._revealUISourceCode(uiSourceCode); |
| 68 } |
| 69 |
| 70 /** |
| 71 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 72 */ |
| 73 _createUISourceCodeItem(uiSourceCode) { |
| 74 var uiSourceCodeItem = new TreeElement(uiSourceCode.displayName(), true); |
| 75 uiSourceCodeItem.selectable = false; |
| 76 |
| 77 // Insert in sorted order |
| 78 var rootElement = this._treeOutline.rootElement(); |
| 79 for (var i = 0; i < rootElement.childCount(); ++i) { |
| 80 if (rootElement.childAt(i).title.localeCompare(uiSourceCode.displayName())
> 0) { |
| 81 rootElement.insertChild(uiSourceCodeItem, i); |
| 82 break; |
| 83 } |
| 84 } |
| 85 if (i === rootElement.childCount()) |
| 86 rootElement.appendChild(uiSourceCodeItem); |
| 87 |
| 88 this._uiSourceCodeItems.set(uiSourceCode, uiSourceCodeItem); |
| 89 |
| 90 var revisionCount = uiSourceCode.history.length; |
| 91 for (var i = revisionCount - 1; i >= 0; --i) { |
| 92 var revision = uiSourceCode.history[i]; |
| 93 var historyItem = |
| 94 new WebInspector.RevisionHistoryTreeElement(revision, uiSourceCode.his
tory[i - 1], i !== revisionCount - 1); |
| 95 uiSourceCodeItem.appendChild(historyItem); |
| 96 } |
| 97 |
| 98 var linkItem = new TreeElement(); |
| 99 linkItem.selectable = false; |
| 100 uiSourceCodeItem.appendChild(linkItem); |
| 101 |
| 102 var revertToOriginal = |
| 103 linkItem.listItemElement.createChild('span', 'revision-history-link revi
sion-history-link-row'); |
| 104 revertToOriginal.textContent = WebInspector.UIString('apply original content
'); |
| 105 revertToOriginal.addEventListener('click', this._revertToOriginal.bind(this,
uiSourceCode)); |
| 106 |
| 107 var clearHistoryElement = uiSourceCodeItem.listItemElement.createChild('span
', 'revision-history-link'); |
| 108 clearHistoryElement.textContent = WebInspector.UIString('revert'); |
| 109 clearHistoryElement.addEventListener('click', this._clearHistory.bind(this,
uiSourceCode)); |
| 110 return uiSourceCodeItem; |
| 111 } |
| 112 |
| 113 /** |
| 114 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 115 */ |
| 116 _revertToOriginal(uiSourceCode) { |
| 117 uiSourceCode.revertToOriginal(); |
| 118 } |
| 119 |
| 120 /** |
| 121 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 122 */ |
| 123 _clearHistory(uiSourceCode) { |
| 124 uiSourceCode.revertAndClearHistory(this._removeUISourceCode.bind(this)); |
| 125 } |
| 126 |
| 127 _revisionAdded(event) { |
| 128 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiS
ourceCode); |
| 129 var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode); |
| 130 if (!uiSourceCodeItem) { |
| 131 uiSourceCodeItem = this._createUISourceCodeItem(uiSourceCode); |
| 132 return; |
| 133 } |
| 134 |
| 135 var historyLength = uiSourceCode.history.length; |
| 136 var historyItem = new WebInspector.RevisionHistoryTreeElement( |
| 137 uiSourceCode.history[historyLength - 1], uiSourceCode.history[historyLen
gth - 2], false); |
| 138 if (uiSourceCodeItem.firstChild()) |
| 139 uiSourceCodeItem.firstChild().allowRevert(); |
| 140 uiSourceCodeItem.insertChild(historyItem, 0); |
| 141 } |
| 142 |
| 143 /** |
| 144 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 145 */ |
| 146 _revealUISourceCode(uiSourceCode) { |
| 147 var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode); |
| 148 if (uiSourceCodeItem) { |
| 149 uiSourceCodeItem.reveal(); |
| 150 uiSourceCodeItem.expand(); |
| 151 } |
| 152 } |
| 153 |
| 154 _uiSourceCodeRemoved(event) { |
| 155 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); |
| 156 this._removeUISourceCode(uiSourceCode); |
| 157 } |
| 158 |
| 159 /** |
| 160 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 161 */ |
| 162 _removeUISourceCode(uiSourceCode) { |
| 163 var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode); |
| 164 if (!uiSourceCodeItem) |
| 165 return; |
| 166 this._treeOutline.removeChild(uiSourceCodeItem); |
| 167 this._uiSourceCodeItems.remove(uiSourceCode); |
| 168 } |
| 169 |
| 170 _projectRemoved(event) { |
| 171 var project = event.data; |
| 172 project.uiSourceCodes().forEach(this._removeUISourceCode.bind(this)); |
| 173 } |
59 }; | 174 }; |
60 | 175 |
| 176 |
61 /** | 177 /** |
62 * @param {!WebInspector.UISourceCode} uiSourceCode | 178 * @unrestricted |
63 */ | 179 */ |
64 WebInspector.RevisionHistoryView.showHistory = function(uiSourceCode) | 180 WebInspector.RevisionHistoryTreeElement = class extends TreeElement { |
65 { | 181 /** |
66 WebInspector.viewManager.showView("sources.history"); | 182 * @param {!WebInspector.Revision} revision |
67 var historyView = /** @type {!WebInspector.RevisionHistoryView} */ (self.run
time.sharedInstance(WebInspector.RevisionHistoryView)); | 183 * @param {!WebInspector.Revision} baseRevision |
68 historyView._revealUISourceCode(uiSourceCode); | 184 * @param {boolean} allowRevert |
69 }; | 185 */ |
70 | 186 constructor(revision, baseRevision, allowRevert) { |
71 WebInspector.RevisionHistoryView.prototype = { | 187 super(revision.timestamp.toLocaleTimeString(), true); |
72 /** | |
73 * @param {!WebInspector.UISourceCode} uiSourceCode | |
74 */ | |
75 _createUISourceCodeItem: function(uiSourceCode) | |
76 { | |
77 var uiSourceCodeItem = new TreeElement(uiSourceCode.displayName(), true)
; | |
78 uiSourceCodeItem.selectable = false; | |
79 | |
80 // Insert in sorted order | |
81 var rootElement = this._treeOutline.rootElement(); | |
82 for (var i = 0; i < rootElement.childCount(); ++i) { | |
83 if (rootElement.childAt(i).title.localeCompare(uiSourceCode.displayN
ame()) > 0) { | |
84 rootElement.insertChild(uiSourceCodeItem, i); | |
85 break; | |
86 } | |
87 } | |
88 if (i === rootElement.childCount()) | |
89 rootElement.appendChild(uiSourceCodeItem); | |
90 | |
91 this._uiSourceCodeItems.set(uiSourceCode, uiSourceCodeItem); | |
92 | |
93 var revisionCount = uiSourceCode.history.length; | |
94 for (var i = revisionCount - 1; i >= 0; --i) { | |
95 var revision = uiSourceCode.history[i]; | |
96 var historyItem = new WebInspector.RevisionHistoryTreeElement(revisi
on, uiSourceCode.history[i - 1], i !== revisionCount - 1); | |
97 uiSourceCodeItem.appendChild(historyItem); | |
98 } | |
99 | |
100 var linkItem = new TreeElement(); | |
101 linkItem.selectable = false; | |
102 uiSourceCodeItem.appendChild(linkItem); | |
103 | |
104 var revertToOriginal = linkItem.listItemElement.createChild("span", "rev
ision-history-link revision-history-link-row"); | |
105 revertToOriginal.textContent = WebInspector.UIString("apply original con
tent"); | |
106 revertToOriginal.addEventListener("click", this._revertToOriginal.bind(t
his, uiSourceCode)); | |
107 | |
108 var clearHistoryElement = uiSourceCodeItem.listItemElement.createChild("
span", "revision-history-link"); | |
109 clearHistoryElement.textContent = WebInspector.UIString("revert"); | |
110 clearHistoryElement.addEventListener("click", this._clearHistory.bind(th
is, uiSourceCode)); | |
111 return uiSourceCodeItem; | |
112 }, | |
113 | |
114 /** | |
115 * @param {!WebInspector.UISourceCode} uiSourceCode | |
116 */ | |
117 _revertToOriginal: function(uiSourceCode) | |
118 { | |
119 uiSourceCode.revertToOriginal(); | |
120 }, | |
121 | |
122 /** | |
123 * @param {!WebInspector.UISourceCode} uiSourceCode | |
124 */ | |
125 _clearHistory: function(uiSourceCode) | |
126 { | |
127 uiSourceCode.revertAndClearHistory(this._removeUISourceCode.bind(this)); | |
128 }, | |
129 | |
130 _revisionAdded: function(event) | |
131 { | |
132 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data
.uiSourceCode); | |
133 var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode); | |
134 if (!uiSourceCodeItem) { | |
135 uiSourceCodeItem = this._createUISourceCodeItem(uiSourceCode); | |
136 return; | |
137 } | |
138 | |
139 var historyLength = uiSourceCode.history.length; | |
140 var historyItem = new WebInspector.RevisionHistoryTreeElement(uiSourceCo
de.history[historyLength - 1], uiSourceCode.history[historyLength - 2], false); | |
141 if (uiSourceCodeItem.firstChild()) | |
142 uiSourceCodeItem.firstChild().allowRevert(); | |
143 uiSourceCodeItem.insertChild(historyItem, 0); | |
144 }, | |
145 | |
146 /** | |
147 * @param {!WebInspector.UISourceCode} uiSourceCode | |
148 */ | |
149 _revealUISourceCode: function(uiSourceCode) | |
150 { | |
151 var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode); | |
152 if (uiSourceCodeItem) { | |
153 uiSourceCodeItem.reveal(); | |
154 uiSourceCodeItem.expand(); | |
155 } | |
156 }, | |
157 | |
158 _uiSourceCodeRemoved: function(event) | |
159 { | |
160 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data
); | |
161 this._removeUISourceCode(uiSourceCode); | |
162 }, | |
163 | |
164 /** | |
165 * @param {!WebInspector.UISourceCode} uiSourceCode | |
166 */ | |
167 _removeUISourceCode: function(uiSourceCode) | |
168 { | |
169 var uiSourceCodeItem = this._uiSourceCodeItems.get(uiSourceCode); | |
170 if (!uiSourceCodeItem) | |
171 return; | |
172 this._treeOutline.removeChild(uiSourceCodeItem); | |
173 this._uiSourceCodeItems.remove(uiSourceCode); | |
174 }, | |
175 | |
176 _projectRemoved: function(event) | |
177 { | |
178 var project = event.data; | |
179 project.uiSourceCodes().forEach(this._removeUISourceCode.bind(this)); | |
180 }, | |
181 | |
182 __proto__: WebInspector.VBox.prototype | |
183 }; | |
184 | |
185 /** | |
186 * @constructor | |
187 * @extends {TreeElement} | |
188 * @param {!WebInspector.Revision} revision | |
189 * @param {!WebInspector.Revision} baseRevision | |
190 * @param {boolean} allowRevert | |
191 */ | |
192 WebInspector.RevisionHistoryTreeElement = function(revision, baseRevision, allow
Revert) | |
193 { | |
194 TreeElement.call(this, revision.timestamp.toLocaleTimeString(), true); | |
195 this.selectable = false; | 188 this.selectable = false; |
196 | 189 |
197 this._revision = revision; | 190 this._revision = revision; |
198 this._baseRevision = baseRevision; | 191 this._baseRevision = baseRevision; |
199 | 192 |
200 this._revertElement = createElement("span"); | 193 this._revertElement = createElement('span'); |
201 this._revertElement.className = "revision-history-link"; | 194 this._revertElement.className = 'revision-history-link'; |
202 this._revertElement.textContent = WebInspector.UIString("apply revision cont
ent"); | 195 this._revertElement.textContent = WebInspector.UIString('apply revision cont
ent'); |
203 this._revertElement.addEventListener("click", event => {this._revision.rever
tToThis();}, false); | 196 this._revertElement.addEventListener('click', event => { |
| 197 this._revision.revertToThis(); |
| 198 }, false); |
204 if (!allowRevert) | 199 if (!allowRevert) |
205 this._revertElement.classList.add("hidden"); | 200 this._revertElement.classList.add('hidden'); |
| 201 } |
| 202 |
| 203 /** |
| 204 * @override |
| 205 */ |
| 206 onattach() { |
| 207 this.listItemElement.classList.add('revision-history-revision'); |
| 208 } |
| 209 |
| 210 /** |
| 211 * @override |
| 212 */ |
| 213 onpopulate() { |
| 214 this.listItemElement.appendChild(this._revertElement); |
| 215 |
| 216 this.childrenListElement.classList.add('source-code'); |
| 217 Promise |
| 218 .all([ |
| 219 this._baseRevision ? this._baseRevision.requestContent() : |
| 220 this._revision.uiSourceCode.requestOriginalConten
t(), |
| 221 this._revision.requestContent() |
| 222 ]) |
| 223 .spread(diff.bind(this)); |
| 224 |
| 225 /** |
| 226 * @param {?string} baseContent |
| 227 * @param {?string} newContent |
| 228 * @this {WebInspector.RevisionHistoryTreeElement} |
| 229 */ |
| 230 function diff(baseContent, newContent) { |
| 231 var baseLines = baseContent.split('\n'); |
| 232 var newLines = newContent.split('\n'); |
| 233 var opcodes = WebInspector.Diff.lineDiff(baseLines, newLines); |
| 234 var lastWasSeparator = false; |
| 235 |
| 236 var baseLineNumber = 0; |
| 237 var newLineNumber = 0; |
| 238 for (var idx = 0; idx < opcodes.length; idx++) { |
| 239 var code = opcodes[idx][0]; |
| 240 var rowCount = opcodes[idx][1].length; |
| 241 if (code === WebInspector.Diff.Operation.Equal) { |
| 242 baseLineNumber += rowCount; |
| 243 newLineNumber += rowCount; |
| 244 if (!lastWasSeparator) |
| 245 this._createLine(null, null, ' \u2026', 'separator'); |
| 246 lastWasSeparator = true; |
| 247 } else if (code === WebInspector.Diff.Operation.Delete) { |
| 248 lastWasSeparator = false; |
| 249 for (var i = 0; i < rowCount; ++i) |
| 250 this._createLine(baseLineNumber + i, null, baseLines[baseLineNumber
+ i], 'removed'); |
| 251 baseLineNumber += rowCount; |
| 252 } else if (code === WebInspector.Diff.Operation.Insert) { |
| 253 lastWasSeparator = false; |
| 254 for (var i = 0; i < rowCount; ++i) |
| 255 this._createLine(null, newLineNumber + i, newLines[newLineNumber + i
], 'added'); |
| 256 newLineNumber += rowCount; |
| 257 } |
| 258 } |
| 259 } |
| 260 } |
| 261 |
| 262 /** |
| 263 * @override |
| 264 */ |
| 265 oncollapse() { |
| 266 this._revertElement.remove(); |
| 267 } |
| 268 |
| 269 /** |
| 270 * @param {?number} baseLineNumber |
| 271 * @param {?number} newLineNumber |
| 272 * @param {string} lineContent |
| 273 * @param {string} changeType |
| 274 */ |
| 275 _createLine(baseLineNumber, newLineNumber, lineContent, changeType) { |
| 276 var child = new TreeElement(); |
| 277 child.selectable = false; |
| 278 this.appendChild(child); |
| 279 |
| 280 function appendLineNumber(lineNumber) { |
| 281 var numberString = lineNumber !== null ? numberToStringWithSpacesPadding(l
ineNumber + 1, 4) : spacesPadding(4); |
| 282 var lineNumberSpan = createElement('span'); |
| 283 lineNumberSpan.classList.add('webkit-line-number'); |
| 284 lineNumberSpan.textContent = numberString; |
| 285 child.listItemElement.appendChild(lineNumberSpan); |
| 286 } |
| 287 |
| 288 appendLineNumber(baseLineNumber); |
| 289 appendLineNumber(newLineNumber); |
| 290 |
| 291 var contentSpan = createElement('span'); |
| 292 contentSpan.textContent = lineContent; |
| 293 child.listItemElement.appendChild(contentSpan); |
| 294 child.listItemElement.classList.add('revision-history-line'); |
| 295 contentSpan.classList.add('revision-history-line-' + changeType); |
| 296 } |
| 297 |
| 298 allowRevert() { |
| 299 this._revertElement.classList.remove('hidden'); |
| 300 } |
206 }; | 301 }; |
207 | |
208 WebInspector.RevisionHistoryTreeElement.prototype = { | |
209 onattach: function() | |
210 { | |
211 this.listItemElement.classList.add("revision-history-revision"); | |
212 }, | |
213 | |
214 onpopulate: function() | |
215 { | |
216 this.listItemElement.appendChild(this._revertElement); | |
217 | |
218 this.childrenListElement.classList.add("source-code"); | |
219 Promise.all([ | |
220 this._baseRevision ? this._baseRevision.requestContent() : this._rev
ision.uiSourceCode.requestOriginalContent(), | |
221 this._revision.requestContent() | |
222 ]).spread(diff.bind(this)); | |
223 | |
224 /** | |
225 * @param {?string} baseContent | |
226 * @param {?string} newContent | |
227 * @this {WebInspector.RevisionHistoryTreeElement} | |
228 */ | |
229 function diff(baseContent, newContent) | |
230 { | |
231 var baseLines = baseContent.split("\n"); | |
232 var newLines = newContent.split("\n"); | |
233 var opcodes = WebInspector.Diff.lineDiff(baseLines, newLines); | |
234 var lastWasSeparator = false; | |
235 | |
236 var baseLineNumber = 0; | |
237 var newLineNumber = 0; | |
238 for (var idx = 0; idx < opcodes.length; idx++) { | |
239 var code = opcodes[idx][0]; | |
240 var rowCount = opcodes[idx][1].length; | |
241 if (code === WebInspector.Diff.Operation.Equal) { | |
242 baseLineNumber += rowCount; | |
243 newLineNumber += rowCount; | |
244 if (!lastWasSeparator) | |
245 this._createLine(null, null, " \u2026", "separator"); | |
246 lastWasSeparator = true; | |
247 } else if (code === WebInspector.Diff.Operation.Delete) { | |
248 lastWasSeparator = false; | |
249 for (var i = 0; i < rowCount; ++i) | |
250 this._createLine(baseLineNumber + i, null, baseLines[bas
eLineNumber + i], "removed"); | |
251 baseLineNumber += rowCount; | |
252 } else if (code === WebInspector.Diff.Operation.Insert) { | |
253 lastWasSeparator = false; | |
254 for (var i = 0; i < rowCount; ++i) | |
255 this._createLine(null, newLineNumber + i, newLines[newLi
neNumber + i], "added"); | |
256 newLineNumber += rowCount; | |
257 } | |
258 } | |
259 } | |
260 }, | |
261 | |
262 oncollapse: function() | |
263 { | |
264 this._revertElement.remove(); | |
265 }, | |
266 | |
267 /** | |
268 * @param {?number} baseLineNumber | |
269 * @param {?number} newLineNumber | |
270 * @param {string} lineContent | |
271 * @param {string} changeType | |
272 */ | |
273 _createLine: function(baseLineNumber, newLineNumber, lineContent, changeType
) | |
274 { | |
275 var child = new TreeElement(); | |
276 child.selectable = false; | |
277 this.appendChild(child); | |
278 | |
279 function appendLineNumber(lineNumber) | |
280 { | |
281 var numberString = lineNumber !== null ? numberToStringWithSpacesPad
ding(lineNumber + 1, 4) : spacesPadding(4); | |
282 var lineNumberSpan = createElement("span"); | |
283 lineNumberSpan.classList.add("webkit-line-number"); | |
284 lineNumberSpan.textContent = numberString; | |
285 child.listItemElement.appendChild(lineNumberSpan); | |
286 } | |
287 | |
288 appendLineNumber(baseLineNumber); | |
289 appendLineNumber(newLineNumber); | |
290 | |
291 var contentSpan = createElement("span"); | |
292 contentSpan.textContent = lineContent; | |
293 child.listItemElement.appendChild(contentSpan); | |
294 child.listItemElement.classList.add("revision-history-line"); | |
295 contentSpan.classList.add("revision-history-line-" + changeType); | |
296 }, | |
297 | |
298 allowRevert: function() | |
299 { | |
300 this._revertElement.classList.remove("hidden"); | |
301 }, | |
302 | |
303 __proto__: TreeElement.prototype | |
304 }; | |
OLD | NEW |