moved to root
This commit is contained in:
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2009 Google Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
WI.ContextMenuItem = class ContextMenuItem extends WI.Object
|
||||
{
|
||||
constructor(topLevelMenu, type, label, disabled, checked)
|
||||
{
|
||||
super();
|
||||
|
||||
this._type = type;
|
||||
this._label = label;
|
||||
this._disabled = disabled;
|
||||
this._checked = checked;
|
||||
this._contextMenu = topLevelMenu || this;
|
||||
|
||||
if (type === "item" || type === "checkbox")
|
||||
this._id = topLevelMenu.nextId();
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
id()
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
type()
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
|
||||
isEnabled()
|
||||
{
|
||||
return !this._disabled;
|
||||
}
|
||||
|
||||
setEnabled(enabled)
|
||||
{
|
||||
this._disabled = !enabled;
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_buildDescriptor()
|
||||
{
|
||||
switch (this._type) {
|
||||
case "item":
|
||||
return {type: "item", id: this._id, label: this._label, enabled: !this._disabled};
|
||||
case "separator":
|
||||
return {type: "separator"};
|
||||
case "checkbox":
|
||||
return {type: "checkbox", id: this._id, label: this._label, checked: !!this._checked, enabled: !this._disabled};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
WI.ContextSubMenuItem = class ContextSubMenuItem extends WI.ContextMenuItem
|
||||
{
|
||||
constructor(topLevelMenu, label, disabled)
|
||||
{
|
||||
super(topLevelMenu, "subMenu", label, disabled);
|
||||
|
||||
this._items = [];
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
appendItem(label, handler, disabled)
|
||||
{
|
||||
let item = new WI.ContextMenuItem(this._contextMenu, "item", label, disabled);
|
||||
this.pushItem(item);
|
||||
this._contextMenu._setHandler(item.id(), handler);
|
||||
return item;
|
||||
}
|
||||
|
||||
appendSubMenuItem(label, disabled)
|
||||
{
|
||||
let item = new WI.ContextSubMenuItem(this._contextMenu, label, disabled);
|
||||
this.pushItem(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
appendCheckboxItem(label, handler, checked, disabled)
|
||||
{
|
||||
let item = new WI.ContextMenuItem(this._contextMenu, "checkbox", label, disabled, checked);
|
||||
this.pushItem(item);
|
||||
this._contextMenu._setHandler(item.id(), handler);
|
||||
return item;
|
||||
}
|
||||
|
||||
appendHeader(label)
|
||||
{
|
||||
return this.appendItem(label, () => {
|
||||
console.assert(false, "not reached");
|
||||
}, true);
|
||||
}
|
||||
|
||||
appendSeparator()
|
||||
{
|
||||
if (this._items.length)
|
||||
this._pendingSeparator = true;
|
||||
}
|
||||
|
||||
pushItem(item)
|
||||
{
|
||||
if (this._pendingSeparator) {
|
||||
this._items.push(new WI.ContextMenuItem(this._contextMenu, "separator"));
|
||||
this._pendingSeparator = null;
|
||||
}
|
||||
this._items.push(item);
|
||||
}
|
||||
|
||||
isEmpty()
|
||||
{
|
||||
return !this._items.length;
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_buildDescriptor()
|
||||
{
|
||||
if (this.isEmpty())
|
||||
return null;
|
||||
|
||||
let subItems = this._items.map((item) => item._buildDescriptor()).filter((item) => !!item);
|
||||
return {type: "subMenu", label: this._label, enabled: !this._disabled, subItems};
|
||||
}
|
||||
};
|
||||
|
||||
WI.ContextMenu = class ContextMenu extends WI.ContextSubMenuItem
|
||||
{
|
||||
constructor(event)
|
||||
{
|
||||
super(null, "");
|
||||
|
||||
this._event = event;
|
||||
this._handlers = {};
|
||||
this._id = 0;
|
||||
|
||||
this._beforeShowCallbacks = [];
|
||||
}
|
||||
|
||||
// Static
|
||||
|
||||
static createFromEvent(event, onlyExisting = false)
|
||||
{
|
||||
if (!event[WI.ContextMenu.ProposedMenuSymbol] && !onlyExisting)
|
||||
event[WI.ContextMenu.ProposedMenuSymbol] = new WI.ContextMenu(event);
|
||||
|
||||
return event[WI.ContextMenu.ProposedMenuSymbol] || null;
|
||||
}
|
||||
|
||||
static contextMenuItemSelected(id)
|
||||
{
|
||||
if (WI.ContextMenu._lastContextMenu)
|
||||
WI.ContextMenu._lastContextMenu._itemSelected(id);
|
||||
}
|
||||
|
||||
static contextMenuCleared()
|
||||
{
|
||||
// FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected
|
||||
// so we can't delete last menu object from WI. Fix the contract.
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
nextId()
|
||||
{
|
||||
return this._id++;
|
||||
}
|
||||
|
||||
show()
|
||||
{
|
||||
console.assert(this._event instanceof MouseEvent);
|
||||
|
||||
let menuObject = this._buildDescriptor();
|
||||
if (menuObject.length) {
|
||||
WI.ContextMenu._lastContextMenu = this;
|
||||
|
||||
if (this._event.type !== "contextmenu" && typeof InspectorFrontendHost.dispatchEventAsContextMenuEvent === "function") {
|
||||
console.assert(event.type !== "mousedown" || this._beforeShowCallbacks.length > 0, "Calling show() in a mousedown handler should have a before show callback to enable quick selection.");
|
||||
|
||||
this._menuObject = menuObject;
|
||||
this._event.target.addEventListener("contextmenu", this, true);
|
||||
InspectorFrontendHost.dispatchEventAsContextMenuEvent(this._event);
|
||||
} else
|
||||
this._showSoftContextMenu(this._event, menuObject);
|
||||
}
|
||||
|
||||
if (this._event)
|
||||
this._event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
addBeforeShowCallback(callback)
|
||||
{
|
||||
this._beforeShowCallbacks.push(callback);
|
||||
}
|
||||
|
||||
// Protected
|
||||
|
||||
handleEvent(event)
|
||||
{
|
||||
console.assert(event.type === "contextmenu");
|
||||
|
||||
for (let callback of this._beforeShowCallbacks)
|
||||
callback(this);
|
||||
|
||||
this._event.target.removeEventListener("contextmenu", this, true);
|
||||
this._showSoftContextMenu(event, this._menuObject);
|
||||
this._menuObject = null;
|
||||
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_setHandler(id, handler)
|
||||
{
|
||||
if (handler)
|
||||
this._handlers[id] = handler;
|
||||
}
|
||||
|
||||
_buildDescriptor()
|
||||
{
|
||||
return this._items.map((item) => item._buildDescriptor()).filter((item) => !!item);
|
||||
}
|
||||
|
||||
_itemSelected(id)
|
||||
{
|
||||
try {
|
||||
if (this._handlers[id])
|
||||
this._handlers[id].call(this);
|
||||
} catch (e) {
|
||||
WI.reportInternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
_showSoftContextMenu(event, menuObject)
|
||||
{
|
||||
new WI.SoftContextMenu(menuObject).show(event);
|
||||
}
|
||||
};
|
||||
|
||||
WI.ContextMenu.ProposedMenuSymbol = Symbol("context-menu-proposed-menu");
|
||||
Reference in New Issue
Block a user