Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / ui / ContextMenu.js
1 /*
2  * Copyright (C) 2009 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29  */
30
31 /**
32  * @constructor
33  * @param {!WebInspector.ContextMenu} topLevelMenu
34  * @param {string} type
35  * @param {string=} label
36  * @param {boolean=} disabled
37  * @param {boolean=} checked
38  */
39 WebInspector.ContextMenuItem = function(topLevelMenu, type, label, disabled, checked)
40 {
41     this._type = type;
42     this._label = label;
43     this._disabled = disabled;
44     this._checked = checked;
45     this._contextMenu = topLevelMenu;
46     if (type === "item" || type === "checkbox")
47         this._id = topLevelMenu.nextId();
48 }
49
50 WebInspector.ContextMenuItem.prototype = {
51     /**
52      * @return {number}
53      */
54     id: function()
55     {
56         return this._id;
57     },
58
59     /**
60      * @return {string}
61      */
62     type: function()
63     {
64         return this._type;
65     },
66
67     /**
68      * @return {boolean}
69      */
70     isEnabled: function()
71     {
72         return !this._disabled;
73     },
74
75     /**
76      * @param {boolean} enabled
77      */
78     setEnabled: function(enabled)
79     {
80         this._disabled = !enabled;
81     },
82
83     _buildDescriptor: function()
84     {
85         switch (this._type) {
86         case "item":
87             return { type: "item", id: this._id, label: this._label, enabled: !this._disabled };
88         case "separator":
89             return { type: "separator" };
90         case "checkbox":
91             return { type: "checkbox", id: this._id, label: this._label, checked: !!this._checked, enabled: !this._disabled };
92         }
93     }
94 }
95
96 /**
97  * @constructor
98  * @extends {WebInspector.ContextMenuItem}
99  * @param {!WebInspector.ContextMenu} topLevelMenu
100  * @param {string=} label
101  * @param {boolean=} disabled
102  */
103 WebInspector.ContextSubMenuItem = function(topLevelMenu, label, disabled)
104 {
105     WebInspector.ContextMenuItem.call(this, topLevelMenu, "subMenu", label, disabled);
106     /** @type {!Array.<!WebInspector.ContextMenuItem>} */
107     this._items = [];
108 }
109
110 WebInspector.ContextSubMenuItem.prototype = {
111     /**
112      * @param {string} label
113      * @param {function(?)} handler
114      * @param {boolean=} disabled
115      * @return {!WebInspector.ContextMenuItem}
116      */
117     appendItem: function(label, handler, disabled)
118     {
119         var item = new WebInspector.ContextMenuItem(this._contextMenu, "item", label, disabled);
120         this._pushItem(item);
121         this._contextMenu._setHandler(item.id(), handler);
122         return item;
123     },
124
125     /**
126      * @param {string} label
127      * @param {boolean=} disabled
128      * @return {!WebInspector.ContextSubMenuItem}
129      */
130     appendSubMenuItem: function(label, disabled)
131     {
132         var item = new WebInspector.ContextSubMenuItem(this._contextMenu, label, disabled);
133         this._pushItem(item);
134         return item;
135     },
136
137     /**
138      * @param {string} label
139      * @param {function()} handler
140      * @param {boolean=} checked
141      * @param {boolean=} disabled
142      * @return {!WebInspector.ContextMenuItem}
143      */
144     appendCheckboxItem: function(label, handler, checked, disabled)
145     {
146         var item = new WebInspector.ContextMenuItem(this._contextMenu, "checkbox", label, disabled, checked);
147         this._pushItem(item);
148         this._contextMenu._setHandler(item.id(), handler);
149         return item;
150     },
151
152     appendSeparator: function()
153     {
154         if (this._items.length)
155             this._pendingSeparator = true;
156     },
157
158     /**
159      * @param {!WebInspector.ContextMenuItem} item
160      */
161     _pushItem: function(item)
162     {
163         if (this._pendingSeparator) {
164             this._items.push(new WebInspector.ContextMenuItem(this._contextMenu, "separator"));
165             delete this._pendingSeparator;
166         }
167         this._items.push(item);
168     },
169
170     /**
171      * @return {boolean}
172      */
173     isEmpty: function()
174     {
175         return !this._items.length;
176     },
177
178     _buildDescriptor: function()
179     {
180         var result = { type: "subMenu", label: this._label, enabled: !this._disabled, subItems: [] };
181         for (var i = 0; i < this._items.length; ++i)
182             result.subItems.push(this._items[i]._buildDescriptor());
183         return result;
184     },
185
186     __proto__: WebInspector.ContextMenuItem.prototype
187 }
188
189 /**
190  * @constructor
191  * @extends {WebInspector.ContextSubMenuItem}
192  * @param {?Event} event
193  */
194 WebInspector.ContextMenu = function(event)
195 {
196     WebInspector.ContextSubMenuItem.call(this, this, "");
197     this._event = /** @type {!Event} */ (event);
198     this._handlers = {};
199     this._id = 0;
200 }
201
202 /**
203  * @param {boolean} useSoftMenu
204  */
205 WebInspector.ContextMenu.setUseSoftMenu = function(useSoftMenu)
206 {
207     WebInspector.ContextMenu._useSoftMenu = useSoftMenu;
208 }
209
210 WebInspector.ContextMenu.prototype = {
211     /**
212      * @return {number}
213      */
214     nextId: function()
215     {
216         return this._id++;
217     },
218
219     show: function()
220     {
221         var menuObject = this._buildDescriptor();
222
223         if (menuObject.length) {
224             WebInspector._contextMenu = this;
225             if (WebInspector.ContextMenu._useSoftMenu) {
226                 var softMenu = new WebInspector.SoftContextMenu(menuObject);
227                 softMenu.show(this._event);
228             } else {
229                 InspectorFrontendHost.showContextMenu(this._event, menuObject);
230             }
231             this._event.consume(true);
232         }
233     },
234
235     /**
236      * @param {number} id
237      * @param {function(?)} handler
238      */
239     _setHandler: function(id, handler)
240     {
241         if (handler)
242             this._handlers[id] = handler;
243     },
244
245     _buildDescriptor: function()
246     {
247         var result = [];
248         for (var i = 0; i < this._items.length; ++i)
249             result.push(this._items[i]._buildDescriptor());
250         return result;
251     },
252
253     _itemSelected: function(id)
254     {
255         if (this._handlers[id])
256             this._handlers[id].call(this);
257     },
258
259     /**
260      * @param {!Object} target
261      */
262     appendApplicableItems: function(target)
263     {
264         WebInspector.moduleManager.extensions(WebInspector.ContextMenu.Provider, target).forEach(processProviders.bind(this));
265
266         /**
267          * @param {!WebInspector.ModuleManager.Extension} extension
268          * @this {WebInspector.ContextMenu}
269          */
270         function processProviders(extension)
271         {
272             var provider = /** @type {!WebInspector.ContextMenu.Provider} */ (extension.instance());
273             this.appendSeparator();
274             provider.appendApplicableItems(this._event, this, target);
275             this.appendSeparator();
276         }
277     },
278
279     __proto__: WebInspector.ContextSubMenuItem.prototype
280 }
281
282 /**
283  * @interface
284  */
285 WebInspector.ContextMenu.Provider = function() {
286 }
287
288 WebInspector.ContextMenu.Provider.prototype = {
289     /**
290      * @param {!Event} event
291      * @param {!WebInspector.ContextMenu} contextMenu
292      * @param {!Object} target
293      */
294     appendApplicableItems: function(event, contextMenu, target) { }
295 }
296
297 WebInspector.contextMenuItemSelected = function(id)
298 {
299     if (WebInspector._contextMenu)
300         WebInspector._contextMenu._itemSelected(id);
301 }
302
303 WebInspector.contextMenuCleared = function()
304 {
305     // FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected
306     // so we can't delete last menu object from WebInspector. Fix the contract.
307 }