ada66697bdd2c36729dbb1297efc31b6a2edf4ce
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / VisualStyleColorPicker.js
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 WebInspector.VisualStyleColorPicker = class VisualStyleColorPicker extends WebInspector.VisualStylePropertyEditor
27 {
28     constructor(propertyNames, text, layoutReversed)
29     {
30         super(propertyNames, text, null, null, "input-color-picker", layoutReversed);
31
32         this._swatchElement = document.createElement("span");
33         this._swatchElement.classList.add("color-swatch");
34         this._swatchElement.title = WebInspector.UIString("Click to select a color. Shift-click to switch color formats.");
35         this._swatchElement.addEventListener("click", this._colorSwatchClicked.bind(this));
36
37         this._swatchInnerElement = document.createElement("span");
38         this._swatchElement.appendChild(this._swatchInnerElement);
39
40         this.contentElement.appendChild(this._swatchElement);
41
42         this._textInputElement = document.createElement("input");
43         this._textInputElement.spellcheck = false;
44         this._textInputElement.addEventListener("keydown", this._textInputKeyDown.bind(this));
45         this._textInputElement.addEventListener("keyup", this._textInputKeyUp.bind(this));
46         this._textInputElement.addEventListener("blur", this._hideCompletions.bind(this));
47         this.contentElement.appendChild(this._textInputElement);
48
49         this._completionController = new WebInspector.VisualStyleCompletionsController(this);
50         this._completionController.addEventListener(WebInspector.VisualStyleCompletionsController.Event.CompletionSelected, this._completionClicked, this);
51
52         this._formatChanged = false;
53         this._updateColorSwatch();
54         this._colorProperty = true;
55     }
56
57     // Public
58
59     get value()
60     {
61         return this._textInputElement.value;
62     }
63
64     set value(value)
65     {
66         if (value && value === this.value)
67             return;
68
69         this._textInputElement.value = this._hasMultipleConflictingValues() ? null : value;
70         this._updateColorSwatch();
71     }
72
73     get placeholder()
74     {
75         return this._textInputElement.getAttribute("placeholder");
76     }
77
78     set placeholder(text)
79     {
80         if (text && text === this.placeholder)
81             return;
82
83         if (this._hasMultipleConflictingValues())
84             text = this.specialPropertyPlaceholderElement.textContent;
85
86         this._textInputElement.setAttribute("placeholder", text || "transparent");
87     }
88
89     get synthesizedValue()
90     {
91         return this.value || null;
92     }
93
94     get hasCompletions()
95     {
96         return this._completionController.hasCompletions;
97     }
98
99     set completions(completions)
100     {
101         this._completionController.completions = completions;
102     }
103
104     // Private
105
106     _updateColorSwatch()
107     {
108         let value = this._textInputElement.value;
109         this._color = WebInspector.Color.fromString(value || "transparent");
110         this._swatchInnerElement.style.backgroundColor = this._color ? value : null;
111     }
112
113     _colorSwatchClicked(event)
114     {
115         let color = this._color;
116         if (event.shiftKey) {
117             let nextFormat = color.nextFormat();
118
119             console.assert(nextFormat);
120             if (!nextFormat)
121                 return;
122
123             color.format = nextFormat;
124             this.value = color.toString();
125
126             this._formatChanged = true;
127             this._valueDidChange();
128             return;
129         }
130
131         let bounds = WebInspector.Rect.rectFromClientRect(this._swatchElement.getBoundingClientRect());
132
133         let colorPicker = new WebInspector.ColorPicker;
134         colorPicker.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._colorPickerColorDidChange, this);
135
136         let popover = new WebInspector.Popover(this);
137         popover.content = colorPicker.element;
138         popover.present(bounds.pad(2), [WebInspector.RectEdge.MIN_X]);
139
140         colorPicker.color = color;
141     }
142
143     _colorPickerColorDidChange(event)
144     {
145         let format = !this._formatChanged ? WebInspector.Color.Format.HEX : null;
146         this.value = event.data.color.toString(format);
147         this._valueDidChange();
148     }
149
150     _completionClicked(event)
151     {
152         this.value = event.data.text;
153         this._valueDidChange();
154     }
155
156     _textInputKeyDown(event)
157     {
158         if (!this._completionController.visible)
159             return;
160
161         let keyCode = event.keyCode;
162         let enterKeyCode = WebInspector.KeyboardShortcut.Key.Enter.keyCode;
163         let tabKeyCode = WebInspector.KeyboardShortcut.Key.Tab.keyCode;
164         if (keyCode === enterKeyCode || keyCode === tabKeyCode) {
165             this.value = this._completionController.currentCompletion;
166             this._hideCompletions();
167             this._valueDidChange();
168             return;
169         }
170
171         let escapeKeyCode = WebInspector.KeyboardShortcut.Key.Escape.keyCode;
172         if (keyCode === escapeKeyCode) {
173             this._hideCompletions();
174             return;
175         }
176
177         let key = event.keyIdentifier;
178         if (key === "Up") {
179             this._completionController.previous();
180             return;
181         }
182
183         if (key === "Down") {
184             this._completionController.next();
185             return;
186         }
187     }
188
189     _textInputKeyUp()
190     {
191         this._showCompletionsIfAble();
192         this._updateColorSwatch();
193         this._valueDidChange();
194     }
195
196     _showCompletionsIfAble()
197     {
198         if (!this.hasCompletions)
199             return;
200
201         let result = this._valueDidChange();
202         if (!result)
203             return;
204
205         if (this._completionController.update(this.value)) {
206             let bounds = WebInspector.Rect.rectFromClientRect(this._textInputElement.getBoundingClientRect());
207             if (!bounds)
208                 return;
209
210             this._completionController.show(bounds, 2);
211         }
212     }
213
214     _hideCompletions()
215     {
216         this._completionController.hide();
217     }
218
219     _toggleTabbingOfSelectableElements(disabled)
220     {
221         this._textInputElement.tabIndex = disabled ? "-1" : null;
222     }
223 };