Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer 11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the 12 * in the documentation and/or other materials provided with the
13 * distribution. 13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its 14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from 15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission. 16 * this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30
31 /** 30 /**
32 * @constructor 31 * @unrestricted
33 * @param {?WebInspector.ContextMenu} topLevelMenu 32 */
34 * @param {string} type 33 WebInspector.ContextMenuItem = class {
35 * @param {string=} label 34 /**
36 * @param {boolean=} disabled 35 * @param {?WebInspector.ContextMenu} topLevelMenu
37 * @param {boolean=} checked 36 * @param {string} type
38 */ 37 * @param {string=} label
39 WebInspector.ContextMenuItem = function(topLevelMenu, type, label, disabled, che cked) 38 * @param {boolean=} disabled
40 { 39 * @param {boolean=} checked
40 */
41 constructor(topLevelMenu, type, label, disabled, checked) {
41 this._type = type; 42 this._type = type;
42 this._label = label; 43 this._label = label;
43 this._disabled = disabled; 44 this._disabled = disabled;
44 this._checked = checked; 45 this._checked = checked;
45 this._contextMenu = topLevelMenu; 46 this._contextMenu = topLevelMenu;
46 if (type === "item" || type === "checkbox") 47 if (type === 'item' || type === 'checkbox')
47 this._id = topLevelMenu ? topLevelMenu._nextId() : 0; 48 this._id = topLevelMenu ? topLevelMenu._nextId() : 0;
49 }
50
51 /**
52 * @return {number}
53 */
54 id() {
55 return this._id;
56 }
57
58 /**
59 * @return {string}
60 */
61 type() {
62 return this._type;
63 }
64
65 /**
66 * @return {boolean}
67 */
68 isEnabled() {
69 return !this._disabled;
70 }
71
72 /**
73 * @param {boolean} enabled
74 */
75 setEnabled(enabled) {
76 this._disabled = !enabled;
77 }
78
79 /**
80 * @return {!InspectorFrontendHostAPI.ContextMenuDescriptor}
81 */
82 _buildDescriptor() {
83 switch (this._type) {
84 case 'item':
85 var result = {type: 'item', id: this._id, label: this._label, enabled: ! this._disabled};
86 if (this._customElement)
87 result.element = this._customElement;
88 if (this._shortcut)
89 result.shortcut = this._shortcut;
90 return result;
91 case 'separator':
92 return {type: 'separator'};
93 case 'checkbox':
94 return {type: 'checkbox', id: this._id, label: this._label, checked: !!t his._checked, enabled: !this._disabled};
95 }
96 throw new Error('Invalid item type:' + this._type);
97 }
98
99 /**
100 * @param {string} shortcut
101 */
102 setShortcut(shortcut) {
103 this._shortcut = shortcut;
104 }
48 }; 105 };
49 106
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 /**
84 * @return {!InspectorFrontendHostAPI.ContextMenuDescriptor}
85 */
86 _buildDescriptor: function()
87 {
88 switch (this._type) {
89 case "item":
90 var result = { type: "item", id: this._id, label: this._label, enabl ed: !this._disabled };
91 if (this._customElement)
92 result.element = this._customElement;
93 if (this._shortcut)
94 result.shortcut = this._shortcut;
95 return result;
96 case "separator":
97 return { type: "separator" };
98 case "checkbox":
99 return { type: "checkbox", id: this._id, label: this._label, checked : !!this._checked, enabled: !this._disabled };
100 }
101 throw new Error("Invalid item type:" + this._type);
102 },
103
104 /**
105 * @param {string} shortcut
106 */
107 setShortcut: function(shortcut)
108 {
109 this._shortcut = shortcut;
110 }
111 };
112
113 /** 107 /**
114 * @constructor 108 * @unrestricted
115 * @extends {WebInspector.ContextMenuItem} 109 */
116 * @param {?WebInspector.ContextMenu} topLevelMenu 110 WebInspector.ContextSubMenuItem = class extends WebInspector.ContextMenuItem {
117 * @param {string=} label 111 /**
118 * @param {boolean=} disabled 112 * @param {?WebInspector.ContextMenu} topLevelMenu
119 */ 113 * @param {string=} label
120 WebInspector.ContextSubMenuItem = function(topLevelMenu, label, disabled) 114 * @param {boolean=} disabled
121 { 115 */
122 WebInspector.ContextMenuItem.call(this, topLevelMenu, "subMenu", label, disa bled); 116 constructor(topLevelMenu, label, disabled) {
117 super(topLevelMenu, 'subMenu', label, disabled);
123 /** @type {!Array.<!WebInspector.ContextMenuItem>} */ 118 /** @type {!Array.<!WebInspector.ContextMenuItem>} */
124 this._items = []; 119 this._items = [];
120 }
121
122 /**
123 * @param {string} label
124 * @param {function(?)} handler
125 * @param {boolean=} disabled
126 * @return {!WebInspector.ContextMenuItem}
127 */
128 appendItem(label, handler, disabled) {
129 var item = new WebInspector.ContextMenuItem(this._contextMenu, 'item', label , disabled);
130 this._pushItem(item);
131 this._contextMenu._setHandler(item.id(), handler);
132 return item;
133 }
134
135 /**
136 * @param {!Element} element
137 * @return {!WebInspector.ContextMenuItem}
138 */
139 appendCustomItem(element) {
140 var item = new WebInspector.ContextMenuItem(this._contextMenu, 'item', '<cus tom>');
141 item._customElement = element;
142 this._pushItem(item);
143 return item;
144 }
145
146 /**
147 * @param {string} actionId
148 * @param {string=} label
149 * @return {!WebInspector.ContextMenuItem}
150 */
151 appendAction(actionId, label) {
152 var action = WebInspector.actionRegistry.action(actionId);
153 if (!label)
154 label = action.title();
155 var result = this.appendItem(label, action.execute.bind(action));
156 var shortcut = WebInspector.shortcutRegistry.shortcutTitleForAction(actionId );
157 if (shortcut)
158 result.setShortcut(shortcut);
159 return result;
160 }
161
162 /**
163 * @param {string} label
164 * @param {boolean=} disabled
165 * @param {string=} subMenuId
166 * @return {!WebInspector.ContextSubMenuItem}
167 */
168 appendSubMenuItem(label, disabled, subMenuId) {
169 var item = new WebInspector.ContextSubMenuItem(this._contextMenu, label, dis abled);
170 if (subMenuId)
171 this._contextMenu._namedSubMenus.set(subMenuId, item);
172 this._pushItem(item);
173 return item;
174 }
175
176 /**
177 * @param {string} label
178 * @param {function()} handler
179 * @param {boolean=} checked
180 * @param {boolean=} disabled
181 * @return {!WebInspector.ContextMenuItem}
182 */
183 appendCheckboxItem(label, handler, checked, disabled) {
184 var item = new WebInspector.ContextMenuItem(this._contextMenu, 'checkbox', l abel, disabled, checked);
185 this._pushItem(item);
186 this._contextMenu._setHandler(item.id(), handler);
187 return item;
188 }
189
190 appendSeparator() {
191 if (this._items.length)
192 this._pendingSeparator = true;
193 }
194
195 /**
196 * @param {!WebInspector.ContextMenuItem} item
197 */
198 _pushItem(item) {
199 if (this._pendingSeparator) {
200 this._items.push(new WebInspector.ContextMenuItem(this._contextMenu, 'sepa rator'));
201 delete this._pendingSeparator;
202 }
203 this._items.push(item);
204 }
205
206 /**
207 * @return {boolean}
208 */
209 isEmpty() {
210 return !this._items.length;
211 }
212
213 /**
214 * @override
215 * @return {!InspectorFrontendHostAPI.ContextMenuDescriptor}
216 */
217 _buildDescriptor() {
218 var result = {type: 'subMenu', label: this._label, enabled: !this._disabled, subItems: []};
219 for (var i = 0; i < this._items.length; ++i)
220 result.subItems.push(this._items[i]._buildDescriptor());
221 return result;
222 }
223
224 /**
225 * @param {string} location
226 */
227 appendItemsAtLocation(location) {
228 /**
229 * @param {!WebInspector.ContextSubMenuItem} menu
230 * @param {!Runtime.Extension} extension
231 */
232 function appendExtension(menu, extension) {
233 var subMenuId = extension.descriptor()['subMenuId'];
234 if (subMenuId) {
235 var subMenuItem = menu.appendSubMenuItem(extension.title(), false, subMe nuId);
236 subMenuItem.appendItemsAtLocation(subMenuId);
237 } else {
238 menu.appendAction(extension.descriptor()['actionId']);
239 }
240 }
241
242 // Hard-coded named groups for elements to maintain generic order.
243 var groupWeights = ['new', 'open', 'clipboard', 'navigate', 'footer'];
244
245 /** @type {!Map.<string, !Array.<!Runtime.Extension>>} */
246 var groups = new Map();
247 var extensions = self.runtime.extensions('context-menu-item');
248 for (var extension of extensions) {
249 var itemLocation = extension.descriptor()['location'] || '';
250 if (!itemLocation.startsWith(location + '/'))
251 continue;
252
253 var itemGroup = itemLocation.substr(location.length + 1);
254 if (!itemGroup || itemGroup.includes('/'))
255 continue;
256 var group = groups.get(itemGroup);
257 if (!group) {
258 group = [];
259 groups.set(itemGroup, group);
260 if (groupWeights.indexOf(itemGroup) === -1)
261 groupWeights.splice(4, 0, itemGroup);
262 }
263 group.push(extension);
264 }
265 for (var groupName of groupWeights) {
266 var group = groups.get(groupName);
267 if (!group)
268 continue;
269 group.forEach(appendExtension.bind(null, this));
270 this.appendSeparator();
271 }
272 }
125 }; 273 };
126 274
127 WebInspector.ContextSubMenuItem.prototype = {
128 /**
129 * @param {string} label
130 * @param {function(?)} handler
131 * @param {boolean=} disabled
132 * @return {!WebInspector.ContextMenuItem}
133 */
134 appendItem: function(label, handler, disabled)
135 {
136 var item = new WebInspector.ContextMenuItem(this._contextMenu, "item", l abel, disabled);
137 this._pushItem(item);
138 this._contextMenu._setHandler(item.id(), handler);
139 return item;
140 },
141
142 /**
143 * @param {!Element} element
144 * @return {!WebInspector.ContextMenuItem}
145 */
146 appendCustomItem: function(element)
147 {
148 var item = new WebInspector.ContextMenuItem(this._contextMenu, "item", " <custom>");
149 item._customElement = element;
150 this._pushItem(item);
151 return item;
152 },
153
154 /**
155 * @param {string} actionId
156 * @param {string=} label
157 * @return {!WebInspector.ContextMenuItem}
158 */
159 appendAction: function(actionId, label)
160 {
161 var action = WebInspector.actionRegistry.action(actionId);
162 if (!label)
163 label = action.title();
164 var result = this.appendItem(label, action.execute.bind(action));
165 var shortcut = WebInspector.shortcutRegistry.shortcutTitleForAction(acti onId);
166 if (shortcut)
167 result.setShortcut(shortcut);
168 return result;
169 },
170
171 /**
172 * @param {string} label
173 * @param {boolean=} disabled
174 * @param {string=} subMenuId
175 * @return {!WebInspector.ContextSubMenuItem}
176 */
177 appendSubMenuItem: function(label, disabled, subMenuId)
178 {
179 var item = new WebInspector.ContextSubMenuItem(this._contextMenu, label, disabled);
180 if (subMenuId)
181 this._contextMenu._namedSubMenus.set(subMenuId, item);
182 this._pushItem(item);
183 return item;
184 },
185
186 /**
187 * @param {string} label
188 * @param {function()} handler
189 * @param {boolean=} checked
190 * @param {boolean=} disabled
191 * @return {!WebInspector.ContextMenuItem}
192 */
193 appendCheckboxItem: function(label, handler, checked, disabled)
194 {
195 var item = new WebInspector.ContextMenuItem(this._contextMenu, "checkbox ", label, disabled, checked);
196 this._pushItem(item);
197 this._contextMenu._setHandler(item.id(), handler);
198 return item;
199 },
200
201 appendSeparator: function()
202 {
203 if (this._items.length)
204 this._pendingSeparator = true;
205 },
206
207 /**
208 * @param {!WebInspector.ContextMenuItem} item
209 */
210 _pushItem: function(item)
211 {
212 if (this._pendingSeparator) {
213 this._items.push(new WebInspector.ContextMenuItem(this._contextMenu, "separator"));
214 delete this._pendingSeparator;
215 }
216 this._items.push(item);
217 },
218
219 /**
220 * @return {boolean}
221 */
222 isEmpty: function()
223 {
224 return !this._items.length;
225 },
226
227 /**
228 * @override
229 * @return {!InspectorFrontendHostAPI.ContextMenuDescriptor}
230 */
231 _buildDescriptor: function()
232 {
233 var result = { type: "subMenu", label: this._label, enabled: !this._disa bled, subItems: [] };
234 for (var i = 0; i < this._items.length; ++i)
235 result.subItems.push(this._items[i]._buildDescriptor());
236 return result;
237 },
238
239 /**
240 * @param {string} location
241 */
242 appendItemsAtLocation: function(location)
243 {
244 /**
245 * @param {!WebInspector.ContextSubMenuItem} menu
246 * @param {!Runtime.Extension} extension
247 */
248 function appendExtension(menu, extension)
249 {
250 var subMenuId = extension.descriptor()["subMenuId"];
251 if (subMenuId) {
252 var subMenuItem = menu.appendSubMenuItem(extension.title(), fals e, subMenuId);
253 subMenuItem.appendItemsAtLocation(subMenuId);
254 } else {
255 menu.appendAction(extension.descriptor()["actionId"]);
256 }
257 }
258
259 // Hard-coded named groups for elements to maintain generic order.
260 var groupWeights = ["new", "open", "clipboard", "navigate", "footer"];
261
262 /** @type {!Map.<string, !Array.<!Runtime.Extension>>} */
263 var groups = new Map();
264 var extensions = self.runtime.extensions("context-menu-item");
265 for (var extension of extensions) {
266 var itemLocation = extension.descriptor()["location"] || "";
267 if (!itemLocation.startsWith(location + "/"))
268 continue;
269
270 var itemGroup = itemLocation.substr(location.length + 1);
271 if (!itemGroup || itemGroup.includes("/"))
272 continue;
273 var group = groups.get(itemGroup);
274 if (!group) {
275 group = [];
276 groups.set(itemGroup, group);
277 if (groupWeights.indexOf(itemGroup) === -1)
278 groupWeights.splice(4, 0, itemGroup);
279 }
280 group.push(extension);
281 }
282 for (var groupName of groupWeights) {
283 var group = groups.get(groupName);
284 if (!group)
285 continue;
286 group.forEach(appendExtension.bind(null, this));
287 this.appendSeparator();
288 }
289 },
290
291 __proto__: WebInspector.ContextMenuItem.prototype
292 };
293
294 /** 275 /**
295 * @constructor 276 * @unrestricted
296 * @extends {WebInspector.ContextSubMenuItem} 277 */
297 * @param {!Event} event 278 WebInspector.ContextMenu = class extends WebInspector.ContextSubMenuItem {
298 * @param {boolean=} useSoftMenu 279 /**
299 * @param {number=} x 280 * @param {!Event} event
300 * @param {number=} y 281 * @param {boolean=} useSoftMenu
301 */ 282 * @param {number=} x
302 WebInspector.ContextMenu = function(event, useSoftMenu, x, y) 283 * @param {number=} y
303 { 284 */
304 WebInspector.ContextSubMenuItem.call(this, null, ""); 285 constructor(event, useSoftMenu, x, y) {
286 super(null, '');
305 this._contextMenu = this; 287 this._contextMenu = this;
306 /** @type {!Array.<!Promise.<!Array.<!WebInspector.ContextMenu.Provider>>>} */ 288 /** @type {!Array.<!Promise.<!Array.<!WebInspector.ContextMenu.Provider>>>} */
307 this._pendingPromises = []; 289 this._pendingPromises = [];
308 /** @type {!Array<!Object>} */ 290 /** @type {!Array<!Object>} */
309 this._pendingTargets = []; 291 this._pendingTargets = [];
310 this._event = event; 292 this._event = event;
311 this._useSoftMenu = !!useSoftMenu; 293 this._useSoftMenu = !!useSoftMenu;
312 this._x = x === undefined ? event.x : x; 294 this._x = x === undefined ? event.x : x;
313 this._y = y === undefined ? event.y : y; 295 this._y = y === undefined ? event.y : y;
314 this._handlers = {}; 296 this._handlers = {};
315 this._id = 0; 297 this._id = 0;
316 /** @type {!Map<string, !WebInspector.ContextSubMenuItem>} */ 298 /** @type {!Map<string, !WebInspector.ContextSubMenuItem>} */
317 this._namedSubMenus = new Map(); 299 this._namedSubMenus = new Map();
318 }; 300 }
319 301
320 WebInspector.ContextMenu.initialize = function() 302 static initialize() {
321 {
322 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event s.SetUseSoftMenu, setUseSoftMenu); 303 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event s.SetUseSoftMenu, setUseSoftMenu);
323 /** 304 /**
324 * @param {!WebInspector.Event} event 305 * @param {!WebInspector.Event} event
325 */ 306 */
326 function setUseSoftMenu(event) 307 function setUseSoftMenu(event) {
327 { 308 WebInspector.ContextMenu._useSoftMenu = /** @type {boolean} */ (event.data );
328 WebInspector.ContextMenu._useSoftMenu = /** @type {boolean} */ (event.da ta);
329 } 309 }
330 }; 310 }
331 311
332 /** 312 /**
333 * @param {!Document} doc 313 * @param {!Document} doc
334 */ 314 */
335 WebInspector.ContextMenu.installHandler = function(doc) 315 static installHandler(doc) {
336 { 316 doc.body.addEventListener('contextmenu', handler, false);
337 doc.body.addEventListener("contextmenu", handler, false);
338 317
339 /** 318 /**
340 * @param {!Event} event 319 * @param {!Event} event
341 */ 320 */
342 function handler(event) 321 function handler(event) {
343 { 322 var contextMenu = new WebInspector.ContextMenu(event);
344 var contextMenu = new WebInspector.ContextMenu(event); 323 contextMenu.appendApplicableItems(/** @type {!Object} */ (event.deepElemen tFromPoint()));
345 contextMenu.appendApplicableItems(/** @type {!Object} */ (event.deepElem entFromPoint())); 324 contextMenu.show();
346 contextMenu.show();
347 } 325 }
326 }
327
328 /**
329 * @return {number}
330 */
331 _nextId() {
332 return this._id++;
333 }
334
335 /**
336 * @param {function()} callback
337 */
338 beforeShow(callback) {
339 this._beforeShow = callback;
340 }
341
342 show() {
343 Promise.all(this._pendingPromises).then(populate.bind(this)).then(this._inne rShow.bind(this));
344 WebInspector.ContextMenu._pendingMenu = this;
345
346 /**
347 * @param {!Array.<!Array.<!WebInspector.ContextMenu.Provider>>} appendCallR esults
348 * @this {WebInspector.ContextMenu}
349 */
350 function populate(appendCallResults) {
351 if (WebInspector.ContextMenu._pendingMenu !== this)
352 return;
353 delete WebInspector.ContextMenu._pendingMenu;
354
355 for (var i = 0; i < appendCallResults.length; ++i) {
356 var providers = appendCallResults[i];
357 var target = this._pendingTargets[i];
358
359 for (var j = 0; j < providers.length; ++j) {
360 var provider = /** @type {!WebInspector.ContextMenu.Provider} */ (prov iders[j]);
361 this.appendSeparator();
362 provider.appendApplicableItems(this._event, this, target);
363 this.appendSeparator();
364 }
365 }
366
367 this._pendingPromises = [];
368 this._pendingTargets = [];
369 }
370
371 this._event.consume(true);
372 }
373
374 discard() {
375 if (this._softMenu)
376 this._softMenu.discard();
377 }
378
379 _innerShow() {
380 if (typeof this._beforeShow === 'function') {
381 this._beforeShow();
382 delete this._beforeShow;
383 }
384
385 var menuObject = this._buildDescriptors();
386
387 WebInspector._contextMenu = this;
388 if (this._useSoftMenu || WebInspector.ContextMenu._useSoftMenu || InspectorF rontendHost.isHostedMode()) {
389 this._softMenu = new WebInspector.SoftContextMenu(menuObject, this._itemSe lected.bind(this));
390 this._softMenu.show(this._event.target.ownerDocument, this._x, this._y);
391 } else {
392 InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuObject, this._event.target.ownerDocument);
393
394 /**
395 * @this {WebInspector.ContextMenu}
396 */
397 function listenToEvents() {
398 InspectorFrontendHost.events.addEventListener(
399 InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleare d, this);
400 InspectorFrontendHost.events.addEventListener(
401 InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onIte mSelected, this);
402 }
403
404 // showContextMenuAtPoint call above synchronously issues a clear event fo r previous context menu (if any),
405 // so we skip it before subscribing to the clear event.
406 setImmediate(listenToEvents.bind(this));
407 }
408 }
409
410 /**
411 * @param {number} id
412 * @param {function(?)} handler
413 */
414 _setHandler(id, handler) {
415 if (handler)
416 this._handlers[id] = handler;
417 }
418
419 /**
420 * @return {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>}
421 */
422 _buildDescriptors() {
423 var result = [];
424 for (var i = 0; i < this._items.length; ++i)
425 result.push(this._items[i]._buildDescriptor());
426 return result;
427 }
428
429 /**
430 * @param {!WebInspector.Event} event
431 */
432 _onItemSelected(event) {
433 this._itemSelected(/** @type {string} */ (event.data));
434 }
435
436 /**
437 * @param {string} id
438 */
439 _itemSelected(id) {
440 if (this._handlers[id])
441 this._handlers[id].call(this);
442 this._menuCleared();
443 }
444
445 _menuCleared() {
446 InspectorFrontendHost.events.removeEventListener(
447 InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, t his);
448 InspectorFrontendHost.events.removeEventListener(
449 InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSel ected, this);
450 }
451
452 /**
453 * @param {!Object} target
454 */
455 appendApplicableItems(target) {
456 this._pendingPromises.push(self.runtime.allInstances(WebInspector.ContextMen u.Provider, target));
457 this._pendingTargets.push(target);
458 }
459
460 /**
461 * @param {string} name
462 * @return {?WebInspector.ContextSubMenuItem}
463 */
464 namedSubMenu(name) {
465 return this._namedSubMenus.get(name) || null;
466 }
348 }; 467 };
349 468
350 WebInspector.ContextMenu.prototype = {
351 /**
352 * @return {number}
353 */
354 _nextId: function()
355 {
356 return this._id++;
357 },
358
359 /**
360 * @param {function()} callback
361 */
362 beforeShow: function(callback)
363 {
364 this._beforeShow = callback;
365 },
366
367 show: function()
368 {
369 Promise.all(this._pendingPromises).then(populate.bind(this)).then(this._ innerShow.bind(this));
370 WebInspector.ContextMenu._pendingMenu = this;
371
372 /**
373 * @param {!Array.<!Array.<!WebInspector.ContextMenu.Provider>>} appendC allResults
374 * @this {WebInspector.ContextMenu}
375 */
376 function populate(appendCallResults)
377 {
378 if (WebInspector.ContextMenu._pendingMenu !== this)
379 return;
380 delete WebInspector.ContextMenu._pendingMenu;
381
382 for (var i = 0; i < appendCallResults.length; ++i) {
383 var providers = appendCallResults[i];
384 var target = this._pendingTargets[i];
385
386 for (var j = 0; j < providers.length; ++j) {
387 var provider = /** @type {!WebInspector.ContextMenu.Provider } */ (providers[j]);
388 this.appendSeparator();
389 provider.appendApplicableItems(this._event, this, target);
390 this.appendSeparator();
391 }
392 }
393
394 this._pendingPromises = [];
395 this._pendingTargets = [];
396 }
397
398 this._event.consume(true);
399 },
400
401 discard: function()
402 {
403 if (this._softMenu)
404 this._softMenu.discard();
405 },
406
407 _innerShow: function()
408 {
409 if (typeof this._beforeShow === "function") {
410 this._beforeShow();
411 delete this._beforeShow;
412 }
413
414 var menuObject = this._buildDescriptors();
415
416 WebInspector._contextMenu = this;
417 if (this._useSoftMenu || WebInspector.ContextMenu._useSoftMenu || Inspec torFrontendHost.isHostedMode()) {
418 this._softMenu = new WebInspector.SoftContextMenu(menuObject, this._ itemSelected.bind(this));
419 this._softMenu.show(this._event.target.ownerDocument, this._x, this. _y);
420 } else {
421 InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuO bject, this._event.target.ownerDocument);
422
423 /**
424 * @this {WebInspector.ContextMenu}
425 */
426 function listenToEvents()
427 {
428 InspectorFrontendHost.events.addEventListener(InspectorFrontendH ostAPI.Events.ContextMenuCleared, this._menuCleared, this);
429 InspectorFrontendHost.events.addEventListener(InspectorFrontendH ostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this);
430 }
431
432 // showContextMenuAtPoint call above synchronously issues a clear ev ent for previous context menu (if any),
433 // so we skip it before subscribing to the clear event.
434 setImmediate(listenToEvents.bind(this));
435 }
436 },
437
438 /**
439 * @param {number} id
440 * @param {function(?)} handler
441 */
442 _setHandler: function(id, handler)
443 {
444 if (handler)
445 this._handlers[id] = handler;
446 },
447
448 /**
449 * @return {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>}
450 */
451 _buildDescriptors: function()
452 {
453 var result = [];
454 for (var i = 0; i < this._items.length; ++i)
455 result.push(this._items[i]._buildDescriptor());
456 return result;
457 },
458
459 /**
460 * @param {!WebInspector.Event} event
461 */
462 _onItemSelected: function(event)
463 {
464 this._itemSelected(/** @type {string} */ (event.data));
465 },
466
467 /**
468 * @param {string} id
469 */
470 _itemSelected: function(id)
471 {
472 if (this._handlers[id])
473 this._handlers[id].call(this);
474 this._menuCleared();
475 },
476
477 _menuCleared: function()
478 {
479 InspectorFrontendHost.events.removeEventListener(InspectorFrontendHostAP I.Events.ContextMenuCleared, this._menuCleared, this);
480 InspectorFrontendHost.events.removeEventListener(InspectorFrontendHostAP I.Events.ContextMenuItemSelected, this._onItemSelected, this);
481 },
482
483 /**
484 * @param {!Object} target
485 */
486 appendApplicableItems: function(target)
487 {
488 this._pendingPromises.push(self.runtime.allInstances(WebInspector.Contex tMenu.Provider, target));
489 this._pendingTargets.push(target);
490 },
491
492 /**
493 * @param {string} name
494 * @return {?WebInspector.ContextSubMenuItem}
495 */
496 namedSubMenu: function(name)
497 {
498 return this._namedSubMenus.get(name) || null;
499 },
500
501 __proto__: WebInspector.ContextSubMenuItem.prototype
502 };
503 469
504 /** 470 /**
505 * @interface 471 * @interface
506 */ 472 */
507 WebInspector.ContextMenu.Provider = function() { 473 WebInspector.ContextMenu.Provider = function() {};
508 };
509 474
510 WebInspector.ContextMenu.Provider.prototype = { 475 WebInspector.ContextMenu.Provider.prototype = {
511 /** 476 /**
512 * @param {!Event} event 477 * @param {!Event} event
513 * @param {!WebInspector.ContextMenu} contextMenu 478 * @param {!WebInspector.ContextMenu} contextMenu
514 * @param {!Object} target 479 * @param {!Object} target
515 */ 480 */
516 appendApplicableItems: function(event, contextMenu, target) { } 481 appendApplicableItems: function(event, contextMenu, target) {}
517 }; 482 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698