Web Inspector: Elements: Styles: add icons for various CSS rule types
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / TypeTokenView.js
1 /*
2  * Copyright (C) 2014-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 WI.TypeTokenView = class TypeTokenView extends WI.Object
27 {
28     constructor(tokenAnnotator, shouldHaveRightMargin, shouldHaveLeftMargin, titleType, functionOrVariableName)
29     {
30         console.assert(titleType === WI.TypeTokenView.TitleType.Variable || titleType === WI.TypeTokenView.TitleType.ReturnStatement);
31
32         super();
33
34         var span = document.createElement("span");
35         span.classList.add("type-token");
36         if (shouldHaveRightMargin)
37             span.classList.add("type-token-right-spacing");
38         if (shouldHaveLeftMargin)
39             span.classList.add("type-token-left-spacing");
40
41         this.element = span;
42         this._tokenAnnotator = tokenAnnotator;
43
44         this._typeDescription = null;
45
46         this._colorClass = null;
47
48         this._popoverTitle = WI.TypeTokenView.titleForPopover(titleType, functionOrVariableName);
49
50         this._setUpMouseoverHandlers();
51     }
52
53     // Static
54
55     static titleForPopover(titleType, functionOrVariableName)
56     {
57         if (titleType === WI.TypeTokenView.TitleType.Variable)
58             return WI.UIString("Type information for variable: %s").format(functionOrVariableName);
59
60         if (functionOrVariableName)
61             return WI.UIString("Return type for function: %s").format(functionOrVariableName);
62
63         return WI.UIString("Return type for anonymous function");
64     }
65
66     // Public
67
68     update(typeDescription)
69     {
70         console.assert(typeDescription instanceof WI.TypeDescription);
71
72         this._typeDescription = typeDescription;
73
74         var title = this._displayTypeName();
75         if (title === this.element.textContent)
76             return;
77
78         this.element.textContent = title;
79         var hashString = title[title.length - 1] === "?" ? title.slice(0, title.length - 1) : title;
80
81         if (this._colorClass)
82             this.element.classList.remove(this._colorClass);
83
84         this._colorClass = WI.TypeTokenView.ColorClassForType[hashString] || "type-token-default";
85         this.element.classList.add(this._colorClass);
86     }
87
88     // Private
89
90     _setUpMouseoverHandlers()
91     {
92         var timeoutID = null;
93
94         this.element.addEventListener("mouseover", function() {
95             function showPopoverAfterDelay()
96             {
97                 timeoutID = null;
98
99                 var domRect = this.element.getBoundingClientRect();
100                 var bounds = new WI.Rect(domRect.left, domRect.top, domRect.width, domRect.height);
101                 this._tokenAnnotator.sourceCodeTextEditor.showPopoverForTypes(this._typeDescription, bounds, this._popoverTitle);
102             }
103
104             if (this._shouldShowPopover())
105                 timeoutID = setTimeout(showPopoverAfterDelay.bind(this), WI.TypeTokenView.DelayHoverTime);
106         }.bind(this));
107
108         this.element.addEventListener("mouseout", function() {
109             if (timeoutID)
110                 clearTimeout(timeoutID);
111         });
112     }
113
114     _shouldShowPopover()
115     {
116         if (!this._typeDescription.valid)
117             return false;
118
119         if (this._typeDescription.typeSet.primitiveTypeNames.length > 1)
120             return true;
121
122         if (this._typeDescription.structures && this._typeDescription.structures.length)
123             return true;
124
125         return false;
126     }
127
128     _displayTypeName()
129     {
130         if (!this._typeDescription.valid)
131             return "";
132
133         var typeSet = this._typeDescription.typeSet;
134
135         if (this._typeDescription.leastCommonAncestor) {
136             if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object))
137                 return this._typeDescription.leastCommonAncestor;
138             if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object | WI.TypeSet.NullOrUndefinedTypeBits))
139                 return this._typeDescription.leastCommonAncestor + "?";
140         }
141
142         // The order of these checks are important.
143         // For example, if a value is only a function, it is contained in TypeFunction, but it is also contained in (TypeFunction | TypeNull).
144         // Therefore, more specific types must be checked first.
145
146         // The strings returned here should match those in TypeTokenView.ColorClassForType
147         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Function))
148             return "Function";
149         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Undefined))
150             return "Undefined";
151         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Null))
152             return "Null";
153         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Boolean))
154             return "Boolean";
155         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Integer))
156             return "Integer";
157         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Number | WI.TypeSet.TypeBit.Integer))
158             return "Number";
159         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.String))
160             return "String";
161         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Symbol))
162             return "Symbol";
163
164         if (typeSet.isContainedIn(WI.TypeSet.NullOrUndefinedTypeBits))
165             return "(?)";
166
167         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Function | WI.TypeSet.NullOrUndefinedTypeBits))
168             return "Function?";
169         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Boolean | WI.TypeSet.NullOrUndefinedTypeBits))
170             return "Boolean?";
171         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Integer | WI.TypeSet.NullOrUndefinedTypeBits))
172             return "Integer?";
173         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Number | WI.TypeSet.TypeBit.Integer | WI.TypeSet.NullOrUndefinedTypeBits))
174             return "Number?";
175         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.String | WI.TypeSet.NullOrUndefinedTypeBits))
176             return "String?";
177         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Symbol | WI.TypeSet.NullOrUndefinedTypeBits))
178             return "Symbol?";
179
180         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object | WI.TypeSet.TypeBit.Function | WI.TypeSet.TypeBit.String))
181             return "Object";
182         if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object | WI.TypeSet.TypeBit.Function | WI.TypeSet.TypeBit.String | WI.TypeSet.NullOrUndefinedTypeBits))
183             return "Object?";
184
185         return WI.UIString("(many)");
186     }
187 };
188
189 WI.TypeTokenView.TitleType = {
190     Variable: Symbol("title-type-variable"),
191     ReturnStatement: Symbol("title-type-return-statement")
192 };
193
194 WI.TypeTokenView.ColorClassForType = {
195     "String": "type-token-string",
196     "Symbol": "type-token-symbol",
197     "Function": "type-token-function",
198     "Number": "type-token-number",
199     "Integer": "type-token-number",
200     "Undefined": "type-token-empty",
201     "Null": "type-token-empty",
202     "(?)": "type-token-empty",
203     "Boolean": "type-token-boolean",
204     "(many)": "type-token-many"
205 };
206
207 WI.TypeTokenView.DelayHoverTime = 350;