3496e462f0fa0f9b8613a7c0f270f25e4ef450ee
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / TypeTokenView.js
1 /*
2  * Copyright (C) 2014 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.TypeTokenView = function(tokenAnnotator, shouldHaveRightMargin, shouldHaveLeftMargin, titleType, functionOrVariableName)
27 {
28     console.assert(titleType === WebInspector.TypeTokenView.TitleType.Variable  || titleType === WebInspector.TypeTokenView.TitleType.ReturnStatement);
29
30     WebInspector.Object.call(this);
31
32     var span = document.createElement("span");
33     span.classList.add("type-token");
34     if (shouldHaveRightMargin)
35         span.classList.add("type-token-right-spacing");
36     if (shouldHaveLeftMargin)
37         span.classList.add("type-token-left-spacing");
38
39     this.element = span;
40     this._tokenAnnotator = tokenAnnotator;
41     this._types = null;
42     this._colorClass = null;
43
44     this._popoverTitle = WebInspector.TypeTokenView.titleForPopover(titleType, functionOrVariableName);
45
46     this._setUpMouseoverHandlers();
47 };
48
49 WebInspector.TypeTokenView.titleForPopover = function(titleType, functionOrVariableName)
50 {
51     var titleString = null;
52     if (titleType === WebInspector.TypeTokenView.TitleType.Variable)
53         titleString = WebInspector.UIString("Type information for variable: %s").format(functionOrVariableName);
54     else {
55         if (functionOrVariableName)
56             titleString = WebInspector.UIString("Return type for function: %s").format(functionOrVariableName);
57         else
58             titleString = WebInspector.UIString("Return type for anonymous function");
59     }
60
61     return titleString;
62 };
63
64 WebInspector.TypeTokenView.TitleType = {
65     Variable: "title-type-variable",
66     ReturnStatement: "title-type-return-statement"
67 };
68
69 // These type strings should be kept in sync with type information in JavaScriptCore/runtime/TypeSet.cpp
70 WebInspector.TypeTokenView.ColorClassForType = {
71     "String": "type-token-string",
72     "Function": "type-token-function",
73     "Number": "type-token-number",
74     "Integer": "type-token-number",
75     "Undefined": "type-token-empty",
76     "Null": "type-token-empty",
77     "(?)": "type-token-empty",
78     "Boolean": "type-token-boolean",
79     "(many)": "type-token-many"
80 };
81
82 WebInspector.TypeTokenView.DelayHoverTime = 350;
83
84 WebInspector.TypeTokenView.prototype = {
85     constructor: WebInspector.TypeTokenView,
86     __proto__: WebInspector.Object.prototype,
87
88     // Public
89
90     update: function(types)
91     {
92         var title = types.displayTypeName;
93         this.element.textContent = title;
94         this._types = types;
95         var hashString = title[title.length - 1] === "?" ? title.slice(0, title.length - 1) : title;
96
97         if (this._colorClass)
98             this.element.classList.remove(this._colorClass);
99
100         this._colorClass = WebInspector.TypeTokenView.ColorClassForType[hashString] || "type-token-default";
101         this.element.classList.add(this._colorClass);
102     },
103
104     // Private
105
106     _setUpMouseoverHandlers: function()
107     {
108         var timeoutID = null;
109
110         this.element.addEventListener("mouseover", function() {
111             function showPopoverAfterDelay()
112             {
113                 timeoutID = null;
114
115                 var domRect = this.element.getBoundingClientRect();
116                 var bounds = new WebInspector.Rect(domRect.left, domRect.top, domRect.width, domRect.height);
117                 this._tokenAnnotator.sourceCodeTextEditor.showPopoverForTypes(this._types, bounds, this._popoverTitle);
118             }
119
120             if (this._shouldShowPopover())
121                 timeoutID = setTimeout(showPopoverAfterDelay.bind(this), WebInspector.TypeTokenView.DelayHoverTime);
122         }.bind(this));
123
124         this.element.addEventListener("mouseout", function() {
125             if (timeoutID)
126                 clearTimeout(timeoutID);
127         }.bind(this));
128     },
129
130     _shouldShowPopover: function()
131     {
132         if ((this._types.globalPrimitiveTypeNames && this._types.globalPrimitiveTypeNames.length > 1) || (this._types.localPrimitiveTypeNames && this._types.localPrimitiveTypeNames.length > 1))
133             return true;
134
135         if ((this._types.globalStructures && this._types.globalStructures.length) || (this._types.localStructures && this._types.localStructures.length))
136             return true;
137
138         return false;
139     }
140 };