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

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

Issue 2771413006: Revert of [DevTools] Migrate SoftContextMenu to use GlassPane (Closed)
Patch Set: Created 3 years, 8 months 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) 2011 Google Inc. All Rights Reserved. 2 * Copyright (C) 2011 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 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 22 matching lines...) Expand all
33 * @param {!UI.SoftContextMenu=} parentMenu 33 * @param {!UI.SoftContextMenu=} parentMenu
34 */ 34 */
35 constructor(items, itemSelectedCallback, parentMenu) { 35 constructor(items, itemSelectedCallback, parentMenu) {
36 this._items = items; 36 this._items = items;
37 this._itemSelectedCallback = itemSelectedCallback; 37 this._itemSelectedCallback = itemSelectedCallback;
38 this._parentMenu = parentMenu; 38 this._parentMenu = parentMenu;
39 } 39 }
40 40
41 /** 41 /**
42 * @param {!Document} document 42 * @param {!Document} document
43 * @param {!AnchorBox} anchorBox 43 * @param {number} x
44 * @param {number} y
44 */ 45 */
45 show(document, anchorBox) { 46 show(document, x, y) {
46 if (!this._items.length) 47 if (!this._items.length)
47 return; 48 return;
48 49
49 this._document = document; 50 this._document = document;
51 this._x = x;
52 this._y = y;
53 this._time = new Date().getTime();
50 54
51 this._glassPane = new UI.GlassPane(); 55 // Create context menu.
52 this._glassPane.setBlockPointerEvents(!this._parentMenu); 56 this.element = createElementWithClass('div', 'soft-context-menu');
53 this._glassPane.setSetOutsideClickCallback(event => { 57 var root = UI.createShadowRootWithCoreStyles(this.element, 'ui/softContextMe nu.css');
54 this._discardMenu(true, event); 58 this._contextMenuElement = root.createChild('div');
55 event.consume(); 59 this.element.style.top = y + 'px';
56 }); 60 var subMenuOverlap = 3;
57 this._glassPane.registerRequiredCSS('ui/softContextMenu.css'); 61 this.element.style.left = (this._parentMenu ? x - subMenuOverlap : x) + 'px' ;
58 this._glassPane.setContentAnchorBox(anchorBox);
59 this._glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
60 this._glassPane.setMarginBehavior(UI.GlassPane.MarginBehavior.NoMargin);
61 this._glassPane.setAnchorBehavior(
62 this._parentMenu ? UI.GlassPane.AnchorBehavior.PreferRight : UI.GlassPan e.AnchorBehavior.PreferBottom);
63 62
64 this._contextMenuElement = this._glassPane.contentElement.createChild('div', 'soft-context-menu');
65 this._contextMenuElement.tabIndex = 0; 63 this._contextMenuElement.tabIndex = 0;
66 this._contextMenuElement.addEventListener('mouseup', e => e.consume(), false ); 64 this._contextMenuElement.addEventListener('mouseup', e => e.consume(), false );
67 this._contextMenuElement.addEventListener('keydown', this._menuKeyDown.bind( this), false); 65 this._contextMenuElement.addEventListener('keydown', this._menuKeyDown.bind( this), false);
68 66
69 for (var i = 0; i < this._items.length; ++i) 67 for (var i = 0; i < this._items.length; ++i)
70 this._contextMenuElement.appendChild(this._createMenuItem(this._items[i])) ; 68 this._contextMenuElement.appendChild(this._createMenuItem(this._items[i])) ;
71 69
72 this._glassPane.show(document); 70 // Install glass pane capturing events.
71 if (!this._parentMenu) {
72 this._glassPaneElement = createElementWithClass('div', 'soft-context-menu- glass-pane fill');
73 this._glassPaneElement.tabIndex = 0;
74 this._glassPaneElement.style.zIndex = '20000';
75 this._glassPaneElement.addEventListener('mouseup', this._glassPaneMouseUp. bind(this), false);
76 this._glassPaneElement.appendChild(this.element);
77 document.body.appendChild(this._glassPaneElement);
78 this._discardMenuOnResizeListener = this._discardMenu.bind(this, true);
79 document.defaultView.addEventListener('resize', this._discardMenuOnResizeL istener, false);
80 } else {
81 this._parentMenu._parentGlassPaneElement().appendChild(this.element);
82 }
83
84 // Re-position menu in case it does not fit.
85 var containerElement = UI.GlassPane.container(document);
86 var hostLeft = containerElement.totalOffsetLeft();
87 var hostRight = hostLeft + containerElement.offsetWidth;
88 if (hostRight < this.element.offsetLeft + this.element.offsetWidth) {
89 var left = this._parentMenu ? this._parentMenu.element.offsetLeft - this.e lement.offsetWidth + subMenuOverlap :
90 hostRight - this.element.offsetWidth;
91 this.element.style.left = Math.max(hostLeft, left) + 'px';
92 }
93
94 // Move submenus upwards if it does not fit.
95 if (this._parentMenu && document.body.offsetHeight < this.element.offsetTop + this.element.offsetHeight) {
96 y = Math.max(containerElement.totalOffsetTop(), document.body.offsetHeight - this.element.offsetHeight);
97 this.element.style.top = y + 'px';
98 }
99
100 var maxHeight = containerElement.offsetHeight;
101 maxHeight -= y - containerElement.totalOffsetTop();
102 this.element.style.maxHeight = maxHeight + 'px';
103
73 this._focus(); 104 this._focus();
74 } 105 }
75 106
76 discard() { 107 discard() {
77 this._discardMenu(true); 108 this._discardMenu(true);
78 } 109 }
79 110
111 _parentGlassPaneElement() {
112 if (this._glassPaneElement)
113 return this._glassPaneElement;
114 if (this._parentMenu)
115 return this._parentMenu._parentGlassPaneElement();
116 return null;
117 }
118
80 _createMenuItem(item) { 119 _createMenuItem(item) {
81 if (item.type === 'separator') 120 if (item.type === 'separator')
82 return this._createSeparator(); 121 return this._createSeparator();
83 122
84 if (item.type === 'subMenu') 123 if (item.type === 'subMenu')
85 return this._createSubMenu(item); 124 return this._createSubMenu(item);
86 125
87 var menuItemElement = createElementWithClass('div', 'soft-context-menu-item' ); 126 var menuItemElement = createElementWithClass('div', 'soft-context-menu-item' );
88 var checkMarkElement = UI.Icon.create('smallicon-checkmark', 'checkmark'); 127 var checkMarkElement = UI.Icon.create('smallicon-checkmark', 'checkmark');
89 menuItemElement.appendChild(checkMarkElement); 128 menuItemElement.appendChild(checkMarkElement);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 214
176 _showSubMenu(menuItemElement) { 215 _showSubMenu(menuItemElement) {
177 if (menuItemElement._subMenuTimer) { 216 if (menuItemElement._subMenuTimer) {
178 clearTimeout(menuItemElement._subMenuTimer); 217 clearTimeout(menuItemElement._subMenuTimer);
179 delete menuItemElement._subMenuTimer; 218 delete menuItemElement._subMenuTimer;
180 } 219 }
181 if (this._subMenu) 220 if (this._subMenu)
182 return; 221 return;
183 222
184 this._subMenu = new UI.SoftContextMenu(menuItemElement._subItems, this._item SelectedCallback, this); 223 this._subMenu = new UI.SoftContextMenu(menuItemElement._subItems, this._item SelectedCallback, this);
185 var anchorBox = menuItemElement.boxInWindow(); 224 var topPadding = 4;
186 // Adjust for padding. 225 this._subMenu.show(
187 anchorBox.y -= 5; 226 this._document, menuItemElement.totalOffsetLeft() + menuItemElement.offs etWidth,
188 anchorBox.x += 3; 227 menuItemElement.totalOffsetTop() - 1 - topPadding);
189 anchorBox.width -= 6;
190 anchorBox.height += 10;
191 this._subMenu.show(this._document, anchorBox);
192 } 228 }
193 229
194 _hideSubMenu() { 230 _hideSubMenu() {
195 if (!this._subMenu) 231 if (!this._subMenu)
196 return; 232 return;
197 this._subMenu._discardSubMenus(); 233 this._subMenu._discardSubMenus();
198 this._focus(); 234 this._focus();
199 } 235 }
200 236
201 _menuItemMouseOver(event) { 237 _menuItemMouseOver(event) {
202 this._highlightMenuItem(event.target, true); 238 this._highlightMenuItem(event.target, true);
203 } 239 }
204 240
205 _menuItemMouseLeave(event) { 241 _menuItemMouseLeave(event) {
206 if (!this._subMenu || !event.relatedTarget) { 242 if (!this._subMenu || !event.relatedTarget) {
207 this._highlightMenuItem(null, true); 243 this._highlightMenuItem(null, true);
208 return; 244 return;
209 } 245 }
210 246
211 var relatedTarget = event.relatedTarget; 247 var relatedTarget = event.relatedTarget;
212 if (relatedTarget === this._contextMenuElement) 248 if (relatedTarget.classList.contains('soft-context-menu-glass-pane'))
213 this._highlightMenuItem(null, true); 249 this._highlightMenuItem(null, true);
214 } 250 }
215 251
216 /** 252 /**
217 * @param {?Element} menuItemElement 253 * @param {?Element} menuItemElement
218 * @param {boolean} scheduleSubMenu 254 * @param {boolean} scheduleSubMenu
219 */ 255 */
220 _highlightMenuItem(menuItemElement, scheduleSubMenu) { 256 _highlightMenuItem(menuItemElement, scheduleSubMenu) {
221 if (this._highlightedMenuItemElement === menuItemElement) 257 if (this._highlightedMenuItemElement === menuItemElement)
222 return; 258 return;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 this._triggerAction(this._highlightedMenuItemElement, event); 332 this._triggerAction(this._highlightedMenuItemElement, event);
297 if (this._highlightedMenuItemElement._subItems) { 333 if (this._highlightedMenuItemElement._subItems) {
298 this._subMenu._focus(); 334 this._subMenu._focus();
299 this._subMenu._highlightNext(); 335 this._subMenu._highlightNext();
300 } 336 }
301 break; 337 break;
302 } 338 }
303 event.consume(true); 339 event.consume(true);
304 } 340 }
305 341
342 _glassPaneMouseUp(event) {
343 // Return if this is simple 'click', since dispatched on glass pane, can't u se 'click' event.
344 if (new Date().getTime() - this._time < 300)
345 return;
346 if (event.target === this.element)
347 return;
348 this._discardMenu(true, event);
349 event.consume();
350 }
351
306 /** 352 /**
307 * @param {boolean} closeParentMenus 353 * @param {boolean} closeParentMenus
308 * @param {!Event=} event 354 * @param {!Event=} event
309 */ 355 */
310 _discardMenu(closeParentMenus, event) { 356 _discardMenu(closeParentMenus, event) {
311 if (this._subMenu && !closeParentMenus) 357 if (this._subMenu && !closeParentMenus)
312 return; 358 return;
359 if (this._glassPaneElement) {
360 var glassPane = this._glassPaneElement;
361 delete this._glassPaneElement;
362 // This can re-enter discardMenu due to blur.
363 this._document.body.removeChild(glassPane);
364 if (this._parentMenu) {
365 delete this._parentMenu._subMenu;
366 if (closeParentMenus)
367 this._parentMenu._discardMenu(closeParentMenus, event);
368 else
369 this._parentMenu._focus();
370 }
313 371
314 this._discardSubMenus(); 372 if (event)
315 373 event.consume(true);
316 if (this._parentMenu) { 374 } else if (this._parentMenu && this._contextMenuElement.parentElementOrShado wHost()) {
375 this._discardSubMenus();
317 if (closeParentMenus) 376 if (closeParentMenus)
318 this._parentMenu._discardMenu(closeParentMenus, event); 377 this._parentMenu._discardMenu(closeParentMenus, event);
319 else 378 else
320 this._parentMenu._focus(); 379 this._parentMenu._focus();
380 if (event)
381 event.consume(true);
321 } 382 }
322 383 if (this._discardMenuOnResizeListener) {
323 if (event) 384 this._document.defaultView.removeEventListener('resize', this._discardMenu OnResizeListener, false);
324 event.consume(true); 385 delete this._discardMenuOnResizeListener;
386 }
325 } 387 }
326 388
327 _discardSubMenus() { 389 _discardSubMenus() {
328 if (this._subMenu) 390 if (this._subMenu)
329 this._subMenu._discardSubMenus(); 391 this._subMenu._discardSubMenus();
330 if (this._glassPane) { 392 if (this.element)
331 this._glassPane.hide(); 393 this.element.remove();
332 delete this._glassPane;
333 }
334 if (this._parentMenu) 394 if (this._parentMenu)
335 delete this._parentMenu._subMenu; 395 delete this._parentMenu._subMenu;
336 } 396 }
337 }; 397 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698