Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(398)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/CSSShadowEditor.js

Issue 2623743002: DevTools: extract modules (non-extensions) (Closed)
Patch Set: rebaseline Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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.
4 /**
5 * @unrestricted
6 */
7 UI.CSSShadowEditor = class extends UI.VBox {
8 constructor() {
9 super(true);
10 this.registerRequiredCSS('ui/cssShadowEditor.css');
11 this.contentElement.tabIndex = 0;
12 this.setDefaultFocusedElement(this.contentElement);
13
14 this._typeField = this.contentElement.createChild('div', 'shadow-editor-fiel d');
15 this._typeField.createChild('label', 'shadow-editor-label').textContent = Co mmon.UIString('Type');
16 this._outsetButton = this._typeField.createChild('button', 'shadow-editor-bu tton-left');
17 this._outsetButton.textContent = Common.UIString('Outset');
18 this._outsetButton.addEventListener('click', this._onButtonClick.bind(this), false);
19 this._insetButton = this._typeField.createChild('button', 'shadow-editor-but ton-right');
20 this._insetButton.textContent = Common.UIString('Inset');
21 this._insetButton.addEventListener('click', this._onButtonClick.bind(this), false);
22
23 var xField = this.contentElement.createChild('div', 'shadow-editor-field');
24 this._xInput = this._createTextInput(xField, Common.UIString('X offset'));
25 var yField = this.contentElement.createChild('div', 'shadow-editor-field');
26 this._yInput = this._createTextInput(yField, Common.UIString('Y offset'));
27 this._xySlider = xField.createChild('canvas', 'shadow-editor-2D-slider');
28 this._xySlider.width = UI.CSSShadowEditor.canvasSize;
29 this._xySlider.height = UI.CSSShadowEditor.canvasSize;
30 this._xySlider.tabIndex = -1;
31 this._halfCanvasSize = UI.CSSShadowEditor.canvasSize / 2;
32 this._innerCanvasSize = this._halfCanvasSize - UI.CSSShadowEditor.sliderThum bRadius;
33 UI.installDragHandle(this._xySlider, this._dragStart.bind(this), this._dragM ove.bind(this), null, 'default');
34 this._xySlider.addEventListener('keydown', this._onCanvasArrowKey.bind(this) , false);
35 this._xySlider.addEventListener('blur', this._onCanvasBlur.bind(this), false );
36
37 var blurField = this.contentElement.createChild('div', 'shadow-editor-blur-f ield');
38 this._blurInput = this._createTextInput(blurField, Common.UIString('Blur'));
39 this._blurSlider = this._createSlider(blurField);
40
41 this._spreadField = this.contentElement.createChild('div', 'shadow-editor-fi eld');
42 this._spreadInput = this._createTextInput(this._spreadField, Common.UIString ('Spread'));
43 this._spreadSlider = this._createSlider(this._spreadField);
44 }
45
46 /**
47 * @param {!Element} field
48 * @param {string} propertyName
49 * @return {!Element}
50 */
51 _createTextInput(field, propertyName) {
52 var label = field.createChild('label', 'shadow-editor-label');
53 label.textContent = propertyName;
54 label.setAttribute('for', propertyName);
55 var textInput = field.createChild('input', 'shadow-editor-text-input');
56 textInput.type = 'text';
57 textInput.id = propertyName;
58 textInput.addEventListener('keydown', this._handleValueModification.bind(thi s), false);
59 textInput.addEventListener('mousewheel', this._handleValueModification.bind( this), false);
60 textInput.addEventListener('input', this._onTextInput.bind(this), false);
61 textInput.addEventListener('blur', this._onTextBlur.bind(this), false);
62 return textInput;
63 }
64
65 /**
66 * @param {!Element} field
67 * @return {!Element}
68 */
69 _createSlider(field) {
70 var slider = UI.createSliderLabel(0, UI.CSSShadowEditor.maxRange, -1);
71 slider.addEventListener('input', this._onSliderInput.bind(this), false);
72 field.appendChild(slider);
73 return slider;
74 }
75
76 /**
77 * @override
78 */
79 wasShown() {
80 this._updateUI();
81 }
82
83 /**
84 * @param {!Common.CSSShadowModel} model
85 */
86 setModel(model) {
87 this._model = model;
88 this._typeField.hidden = !model.isBoxShadow();
89 this._spreadField.hidden = !model.isBoxShadow();
90 this._updateUI();
91 }
92
93 _updateUI() {
94 this._updateButtons();
95 this._xInput.value = this._model.offsetX().asCSSText();
96 this._yInput.value = this._model.offsetY().asCSSText();
97 this._blurInput.value = this._model.blurRadius().asCSSText();
98 this._spreadInput.value = this._model.spreadRadius().asCSSText();
99 this._blurSlider.value = this._model.blurRadius().amount;
100 this._spreadSlider.value = this._model.spreadRadius().amount;
101 this._updateCanvas(false);
102 }
103
104 _updateButtons() {
105 this._insetButton.classList.toggle('enabled', this._model.inset());
106 this._outsetButton.classList.toggle('enabled', !this._model.inset());
107 }
108
109 /**
110 * @param {boolean} drawFocus
111 */
112 _updateCanvas(drawFocus) {
113 var context = this._xySlider.getContext('2d');
114 context.clearRect(0, 0, this._xySlider.width, this._xySlider.height);
115
116 // Draw dashed axes.
117 context.save();
118 context.setLineDash([1, 1]);
119 context.strokeStyle = 'rgba(210, 210, 210, 0.8)';
120 context.beginPath();
121 context.moveTo(this._halfCanvasSize, 0);
122 context.lineTo(this._halfCanvasSize, UI.CSSShadowEditor.canvasSize);
123 context.moveTo(0, this._halfCanvasSize);
124 context.lineTo(UI.CSSShadowEditor.canvasSize, this._halfCanvasSize);
125 context.stroke();
126 context.restore();
127
128 var thumbPoint = this._sliderThumbPosition();
129 // Draw 2D slider line.
130 context.save();
131 context.translate(this._halfCanvasSize, this._halfCanvasSize);
132 context.lineWidth = 2;
133 context.strokeStyle = 'rgba(130, 130, 130, 0.75)';
134 context.beginPath();
135 context.moveTo(0, 0);
136 context.lineTo(thumbPoint.x, thumbPoint.y);
137 context.stroke();
138 // Draw 2D slider thumb.
139 if (drawFocus) {
140 context.beginPath();
141 context.fillStyle = 'rgba(66, 133, 244, 0.4)';
142 context.arc(thumbPoint.x, thumbPoint.y, UI.CSSShadowEditor.sliderThumbRadi us + 2, 0, 2 * Math.PI);
143 context.fill();
144 }
145 context.beginPath();
146 context.fillStyle = '#4285F4';
147 context.arc(thumbPoint.x, thumbPoint.y, UI.CSSShadowEditor.sliderThumbRadius , 0, 2 * Math.PI);
148 context.fill();
149 context.restore();
150 }
151
152 /**
153 * @param {!Event} event
154 */
155 _onButtonClick(event) {
156 var insetClicked = (event.currentTarget === this._insetButton);
157 if (insetClicked && this._model.inset() || !insetClicked && !this._model.ins et())
158 return;
159 this._model.setInset(insetClicked);
160 this._updateButtons();
161 this.dispatchEventToListeners(UI.CSSShadowEditor.Events.ShadowChanged, this. _model);
162 }
163
164 /**
165 * @param {!Event} event
166 */
167 _handleValueModification(event) {
168 var modifiedValue = UI.createReplacementString(event.currentTarget.value, ev ent, customNumberHandler);
169 if (!modifiedValue)
170 return;
171 var length = Common.CSSLength.parse(modifiedValue);
172 if (!length)
173 return;
174 if (event.currentTarget === this._blurInput && length.amount < 0)
175 length.amount = 0;
176 event.currentTarget.value = length.asCSSText();
177 event.currentTarget.selectionStart = 0;
178 event.currentTarget.selectionEnd = event.currentTarget.value.length;
179 this._onTextInput(event);
180 event.consume(true);
181
182 /**
183 * @param {string} prefix
184 * @param {number} number
185 * @param {string} suffix
186 * @return {string}
187 */
188 function customNumberHandler(prefix, number, suffix) {
189 if (!suffix.length)
190 suffix = UI.CSSShadowEditor.defaultUnit;
191 return prefix + number + suffix;
192 }
193 }
194
195 /**
196 * @param {!Event} event
197 */
198 _onTextInput(event) {
199 this._changedElement = event.currentTarget;
200 this._changedElement.classList.remove('invalid');
201 var length = Common.CSSLength.parse(event.currentTarget.value);
202 if (!length || event.currentTarget === this._blurInput && length.amount < 0)
203 return;
204 if (event.currentTarget === this._xInput) {
205 this._model.setOffsetX(length);
206 this._updateCanvas(false);
207 } else if (event.currentTarget === this._yInput) {
208 this._model.setOffsetY(length);
209 this._updateCanvas(false);
210 } else if (event.currentTarget === this._blurInput) {
211 this._model.setBlurRadius(length);
212 this._blurSlider.value = length.amount;
213 } else if (event.currentTarget === this._spreadInput) {
214 this._model.setSpreadRadius(length);
215 this._spreadSlider.value = length.amount;
216 }
217 this.dispatchEventToListeners(UI.CSSShadowEditor.Events.ShadowChanged, this. _model);
218 }
219
220 _onTextBlur() {
221 if (!this._changedElement)
222 return;
223 var length = !this._changedElement.value.trim() ? Common.CSSLength.zero() :
224 Common.CSSLength.parse(thi s._changedElement.value);
225 if (!length)
226 length = Common.CSSLength.parse(this._changedElement.value + UI.CSSShadowE ditor.defaultUnit);
227 if (!length) {
228 this._changedElement.classList.add('invalid');
229 this._changedElement = null;
230 return;
231 }
232 if (this._changedElement === this._xInput) {
233 this._model.setOffsetX(length);
234 this._xInput.value = length.asCSSText();
235 this._updateCanvas(false);
236 } else if (this._changedElement === this._yInput) {
237 this._model.setOffsetY(length);
238 this._yInput.value = length.asCSSText();
239 this._updateCanvas(false);
240 } else if (this._changedElement === this._blurInput) {
241 if (length.amount < 0)
242 length = Common.CSSLength.zero();
243 this._model.setBlurRadius(length);
244 this._blurInput.value = length.asCSSText();
245 this._blurSlider.value = length.amount;
246 } else if (this._changedElement === this._spreadInput) {
247 this._model.setSpreadRadius(length);
248 this._spreadInput.value = length.asCSSText();
249 this._spreadSlider.value = length.amount;
250 }
251 this._changedElement = null;
252 this.dispatchEventToListeners(UI.CSSShadowEditor.Events.ShadowChanged, this. _model);
253 }
254
255 /**
256 * @param {!Event} event
257 */
258 _onSliderInput(event) {
259 if (event.currentTarget === this._blurSlider) {
260 this._model.setBlurRadius(new Common.CSSLength(
261 this._blurSlider.value, this._model.blurRadius().unit || UI.CSSShadowE ditor.defaultUnit));
262 this._blurInput.value = this._model.blurRadius().asCSSText();
263 this._blurInput.classList.remove('invalid');
264 } else if (event.currentTarget === this._spreadSlider) {
265 this._model.setSpreadRadius(new Common.CSSLength(
266 this._spreadSlider.value, this._model.spreadRadius().unit || UI.CSSSha dowEditor.defaultUnit));
267 this._spreadInput.value = this._model.spreadRadius().asCSSText();
268 this._spreadInput.classList.remove('invalid');
269 }
270 this.dispatchEventToListeners(UI.CSSShadowEditor.Events.ShadowChanged, this. _model);
271 }
272
273 /**
274 * @param {!MouseEvent} event
275 * @return {boolean}
276 */
277 _dragStart(event) {
278 this._xySlider.focus();
279 this._updateCanvas(true);
280 this._canvasOrigin = new Common.Geometry.Point(
281 this._xySlider.totalOffsetLeft() + this._halfCanvasSize,
282 this._xySlider.totalOffsetTop() + this._halfCanvasSize);
283 var clickedPoint = new Common.Geometry.Point(event.x - this._canvasOrigin.x, event.y - this._canvasOrigin.y);
284 var thumbPoint = this._sliderThumbPosition();
285 if (clickedPoint.distanceTo(thumbPoint) >= UI.CSSShadowEditor.sliderThumbRad ius)
286 this._dragMove(event);
287 return true;
288 }
289
290 /**
291 * @param {!MouseEvent} event
292 */
293 _dragMove(event) {
294 var point = new Common.Geometry.Point(event.x - this._canvasOrigin.x, event. y - this._canvasOrigin.y);
295 if (event.shiftKey)
296 point = this._snapToClosestDirection(point);
297 var constrainedPoint = this._constrainPoint(point, this._innerCanvasSize);
298 var newX = Math.round((constrainedPoint.x / this._innerCanvasSize) * UI.CSSS hadowEditor.maxRange);
299 var newY = Math.round((constrainedPoint.y / this._innerCanvasSize) * UI.CSSS hadowEditor.maxRange);
300
301 if (event.shiftKey) {
302 this._model.setOffsetX(new Common.CSSLength(newX, this._model.offsetX().un it || UI.CSSShadowEditor.defaultUnit));
303 this._model.setOffsetY(new Common.CSSLength(newY, this._model.offsetY().un it || UI.CSSShadowEditor.defaultUnit));
304 } else {
305 if (!event.altKey) {
306 this._model.setOffsetX(
307 new Common.CSSLength(newX, this._model.offsetX().unit || UI.CSSShado wEditor.defaultUnit));
308 }
309 if (!UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
310 this._model.setOffsetY(
311 new Common.CSSLength(newY, this._model.offsetY().unit || UI.CSSShado wEditor.defaultUnit));
312 }
313 }
314 this._xInput.value = this._model.offsetX().asCSSText();
315 this._yInput.value = this._model.offsetY().asCSSText();
316 this._xInput.classList.remove('invalid');
317 this._yInput.classList.remove('invalid');
318 this._updateCanvas(true);
319 this.dispatchEventToListeners(UI.CSSShadowEditor.Events.ShadowChanged, this. _model);
320 }
321
322 _onCanvasBlur() {
323 this._updateCanvas(false);
324 }
325
326 /**
327 * @param {!Event} event
328 */
329 _onCanvasArrowKey(event) {
330 var shiftX = 0;
331 var shiftY = 0;
332 if (event.key === 'ArrowRight')
333 shiftX = 1;
334 else if (event.key === 'ArrowLeft')
335 shiftX = -1;
336 else if (event.key === 'ArrowUp')
337 shiftY = -1;
338 else if (event.key === 'ArrowDown')
339 shiftY = 1;
340
341 if (!shiftX && !shiftY)
342 return;
343 event.consume(true);
344
345 if (shiftX) {
346 var offsetX = this._model.offsetX();
347 var newAmount =
348 Number.constrain(offsetX.amount + shiftX, -UI.CSSShadowEditor.maxRange , UI.CSSShadowEditor.maxRange);
349 if (newAmount === offsetX.amount)
350 return;
351 this._model.setOffsetX(new Common.CSSLength(newAmount, offsetX.unit || UI. CSSShadowEditor.defaultUnit));
352 this._xInput.value = this._model.offsetX().asCSSText();
353 this._xInput.classList.remove('invalid');
354 }
355 if (shiftY) {
356 var offsetY = this._model.offsetY();
357 var newAmount =
358 Number.constrain(offsetY.amount + shiftY, -UI.CSSShadowEditor.maxRange , UI.CSSShadowEditor.maxRange);
359 if (newAmount === offsetY.amount)
360 return;
361 this._model.setOffsetY(new Common.CSSLength(newAmount, offsetY.unit || UI. CSSShadowEditor.defaultUnit));
362 this._yInput.value = this._model.offsetY().asCSSText();
363 this._yInput.classList.remove('invalid');
364 }
365 this._updateCanvas(true);
366 this.dispatchEventToListeners(UI.CSSShadowEditor.Events.ShadowChanged, this. _model);
367 }
368
369 /**
370 * @param {!Common.Geometry.Point} point
371 * @param {number} max
372 * @return {!Common.Geometry.Point}
373 */
374 _constrainPoint(point, max) {
375 if (Math.abs(point.x) <= max && Math.abs(point.y) <= max)
376 return new Common.Geometry.Point(point.x, point.y);
377 return point.scale(max / Math.max(Math.abs(point.x), Math.abs(point.y)));
378 }
379
380 /**
381 * @param {!Common.Geometry.Point} point
382 * @return {!Common.Geometry.Point}
383 */
384 _snapToClosestDirection(point) {
385 var minDistance = Number.MAX_VALUE;
386 var closestPoint = point;
387
388 var directions = [
389 new Common.Geometry.Point(0, -1), // North
390 new Common.Geometry.Point(1, -1), // Northeast
391 new Common.Geometry.Point(1, 0), // East
392 new Common.Geometry.Point(1, 1) // Southeast
393 ];
394
395 for (var direction of directions) {
396 var projection = point.projectOn(direction);
397 var distance = point.distanceTo(projection);
398 if (distance < minDistance) {
399 minDistance = distance;
400 closestPoint = projection;
401 }
402 }
403
404 return closestPoint;
405 }
406
407 /**
408 * @return {!Common.Geometry.Point}
409 */
410 _sliderThumbPosition() {
411 var x = (this._model.offsetX().amount / UI.CSSShadowEditor.maxRange) * this. _innerCanvasSize;
412 var y = (this._model.offsetY().amount / UI.CSSShadowEditor.maxRange) * this. _innerCanvasSize;
413 return this._constrainPoint(new Common.Geometry.Point(x, y), this._innerCanv asSize);
414 }
415 };
416
417 /** @enum {symbol} */
418 UI.CSSShadowEditor.Events = {
419 ShadowChanged: Symbol('ShadowChanged')
420 };
421
422 /** @type {number} */
423 UI.CSSShadowEditor.maxRange = 20;
424 /** @type {string} */
425 UI.CSSShadowEditor.defaultUnit = 'px';
426 /** @type {number} */
427 UI.CSSShadowEditor.sliderThumbRadius = 6;
428 /** @type {number} */
429 UI.CSSShadowEditor.canvasSize = 88;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698