Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / 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.ContextSubMenuItem} 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 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.ContextMenuItem}
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 {boolean=} disabled
139      * @return {!WebInspector.ContextMenuItem}
140      */
141     appendCheckboxItem: function(label, handler, checked, disabled)
142     {
143         var item = new WebInspector.ContextMenuItem(this._contextMenu, "checkbox", label, disabled, checked);
144         this._pushItem(item);
145         this._contextMenu._setHandler(item.id(), handler);
146         return item;
147     },
148
149     appendSeparator: function()
150     {
151         if (this._items.length)
152             this._pendingSeparator = true;
153     },
154
155     /**
156      * @param {!WebInspector.ContextMenuItem} item
157      */
158     _pushItem: function(item)
159     {
160         if (this._pendingSeparator) {
161             this._items.push(new WebInspector.ContextMenuItem(this._contextMenu, "separator"));
162             delete this._pendingSeparator;
163         }
164         this._items.push(item);
165     },
166
167     /**
168      * @return {boolean}
169      */
170     isEmpty: function()
171     {
172         return !this._items.length;
173     },
174
175     _buildDescriptor: function()
176     {
177         var result = { type: "subMenu", label: this._label, enabled: !this._disabled, subItems: [] };
178         for (var i = 0; i < this._items.length; ++i)
179             result.subItems.push(this._items[i]._buildDescriptor());
180         return result;
181     },
182
183     __proto__: WebInspector.ContextMenuItem.prototype
184 }
185
186 /**
187  * @constructor
188  * @extends {WebInspector.ContextSubMenuItem}
189  */
190 WebInspector.ContextMenu = function(event) {
191     WebInspector.ContextSubMenuItem.call(this, this, "");
192     this._event = event;
193     this._handlers = {};
194     this._id = 0;
195 }
196
197 /**
198  * @param {boolean} useSoftMenu
199  */
200 WebInspector.ContextMenu.setUseSoftMenu = function(useSoftMenu)
201 {
202     WebInspector.ContextMenu._useSoftMenu = useSoftMenu;
203 }
204
205 WebInspector.ContextMenu.prototype = {
206     /**
207      * @return {number}
208      */
209     nextId: function()
210     {
211         return this._id++;
212     },
213
214     show: function()
215     {
216         var menuObject = this._buildDescriptor();
217
218         if (menuObject.length) {
219             WebInspector._contextMenu = this;
220             if (WebInspector.ContextMenu._useSoftMenu) {
221                 var softMenu = new WebInspector.SoftContextMenu(menuObject);
222                 softMenu.show(this._event);
223             } else {
224                 InspectorFrontendHost.showContextMenu(this._event, menuObject);
225             }
226             this._event.consume();
227         }
228     },
229
230     _setHandler: function(id, handler)
231     {
232         if (handler)
233             this._handlers[id] = handler;
234     },
235
236     _buildDescriptor: function()
237     {
238         var result = [];
239         for (var i = 0; i < this._items.length; ++i)
240             result.push(this._items[i]._buildDescriptor());
241         return result;
242     },
243
244     _itemSelected: function(id)
245     {
246         if (this._handlers[id])
247             this._handlers[id].call(this);
248     },
249
250     /**
251      * @param {!Object} target
252      */
253     appendApplicableItems: function(target)
254     {
255         WebInspector.moduleManager.extensions(WebInspector.ContextMenu.Provider, target).forEach(processProviders.bind(this));
256
257         /**
258          * @param {!WebInspector.ModuleManager.Extension} extension
259          * @this {WebInspector.ContextMenu}
260          */
261         function processProviders(extension)
262         {
263             var provider = /** @type {!WebInspector.ContextMenu.Provider} */ (extension.instance());
264             this.appendSeparator();
265             provider.appendApplicableItems(this._event, this, target);
266             this.appendSeparator();
267         }
268     },
269
270     __proto__: WebInspector.ContextSubMenuItem.prototype
271 }
272
273 /**
274  * @interface
275  */
276 WebInspector.ContextMenu.Provider = function() { 
277 }
278
279 WebInspector.ContextMenu.Provider.prototype = {
280     /** 
281      * @param {!WebInspector.ContextMenu} contextMenu
282      * @param {!Object} target
283      */
284     appendApplicableItems: function(event, contextMenu, target) { }
285 }
286
287 WebInspector.contextMenuItemSelected = function(id)
288 {
289     if (WebInspector._contextMenu)
290         WebInspector._contextMenu._itemSelected(id);
291 }
292
293 WebInspector.contextMenuCleared = function()
294 {
295     // FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected
296     // so we can't delete last menu object from WebInspector. Fix the contract.
297 }