Index: Source/devtools/front_end/elements/ElementsTreeOutline.js |
diff --git a/Source/devtools/front_end/elements/ElementsTreeOutline.js b/Source/devtools/front_end/elements/ElementsTreeOutline.js |
index 9cc824b7538c809813e0b79de20e8689cc68ab22..7d1c1876f991bee0436a090ce98a0b0b0bb09839 100644 |
--- a/Source/devtools/front_end/elements/ElementsTreeOutline.js |
+++ b/Source/devtools/front_end/elements/ElementsTreeOutline.js |
@@ -71,6 +71,9 @@ WebInspector.ElementsTreeOutline = function(target, omitRootDOMNode, selectEnabl |
this._createNodeDecorators(); |
} |
+/** @typedef {{node: !WebInspector.DOMNode, isCut: boolean}} */ |
+WebInspector.ElementsTreeOutline.ClipboardData; |
+ |
/** |
* @enum {string} |
*/ |
@@ -144,6 +147,153 @@ WebInspector.ElementsTreeOutline.prototype = { |
if (this._elementsTreeUpdater) |
this._elementsTreeUpdater.dispose(); |
}, |
+ |
+ /** |
+ * @param {?WebInspector.ElementsTreeOutline.ClipboardData} data |
+ */ |
+ _setClipboardData: function(data) |
+ { |
+ if (this._clipboardNodeData) { |
+ var treeElement = this.findTreeElement(this._clipboardNodeData.node); |
+ if (treeElement) |
+ treeElement.setInClipboard(false); |
+ delete this._clipboardNodeData; |
+ } |
+ |
+ if (data) { |
+ var treeElement = this.findTreeElement(data.node); |
+ if (treeElement) |
+ treeElement.setInClipboard(true); |
+ this._clipboardNodeData = data; |
+ } |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.DOMNode} node |
+ */ |
+ _cutNode: function(node) |
aandrey
2014/07/25 15:44:27
remove this in favor of .bind(..., true)?
apavlov
2014/07/25 16:09:56
Done.
|
+ { |
+ this._performCopyOrCut(true, node); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.DOMNode} node |
+ */ |
+ _copyNode: function(node) |
aandrey
2014/07/25 15:44:27
ditto
apavlov
2014/07/25 16:09:56
Done.
|
+ { |
+ this._performCopyOrCut(false, node); |
+ }, |
+ |
+ /** |
+ * @param {boolean} isCut |
+ * @param {!Event} event |
+ */ |
+ handleCopyOrCutKeyboardEvent: function(isCut, event) |
+ { |
+ this._setClipboardData(null); |
aandrey
2014/07/25 15:44:26
should it be after all the returns?
apavlov
2014/07/25 16:09:57
Nope. We don't want users to go dizzy about having
|
+ |
+ // Do not interfere with text editing. |
+ var currentFocusElement = WebInspector.currentFocusElement(); |
+ if (currentFocusElement && WebInspector.isBeingEdited(currentFocusElement)) |
+ return; |
+ |
+ var targetNode = this.selectedDOMNode(); |
+ if (!targetNode) |
+ return; |
+ |
+ if (isCut && (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot())) |
+ return; |
+ |
+ event.clipboardData.clearData(); |
+ event.preventDefault(); |
+ this._performCopyOrCut(isCut, targetNode); |
+ }, |
+ |
+ /** |
+ * @param {boolean} isCut |
+ * @param {?WebInspector.DOMNode} node |
+ */ |
+ _performCopyOrCut: function(isCut, node) |
+ { |
+ node.copyNode(); |
+ this._setClipboardData({node: node, isCut: isCut}); |
aandrey
2014/07/25 15:44:27
nit: spaces after { and before }
apavlov
2014/07/25 16:09:57
Done.
|
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.DOMNode} targetNode |
+ * @return {boolean} |
+ */ |
+ _canPaste: function(targetNode) |
+ { |
+ if (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot()) |
+ return false; |
+ |
+ if (!this._clipboardNodeData) |
+ return false; |
+ |
+ var node = this._clipboardNodeData.node; |
+ if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode))) |
+ return false; |
+ |
+ if (targetNode.target() !== node.target()) |
+ return false; |
+ return true; |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.DOMNode} targetNode |
+ */ |
+ _pasteNode: function(targetNode) |
aandrey
2014/07/25 15:44:26
remove this (looks like the code would be a lot si
apavlov
2014/07/25 16:09:57
Done.
|
+ { |
+ this._performPaste(targetNode); |
+ }, |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ handlePasteKeyboardEvent: function(event) |
+ { |
+ // Do not interfere with text editing. |
+ var currentFocusElement = WebInspector.currentFocusElement(); |
+ if (currentFocusElement && WebInspector.isBeingEdited(currentFocusElement)) |
+ return; |
+ |
+ var targetNode = this.selectedDOMNode(); |
+ if (!targetNode || !this._canPaste(targetNode)) |
+ return; |
+ |
+ event.preventDefault(); |
aandrey
2014/07/25 15:44:27
maybe event.consume(false); ?
apavlov
2014/07/25 16:09:57
true, since we need to preventDefault(). Done.
|
+ this._performPaste(targetNode); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.DOMNode} targetNode |
+ */ |
+ _performPaste: function(targetNode) |
+ { |
+ if (this._clipboardNodeData.isCut) { |
+ this._clipboardNodeData.node.moveTo(targetNode, null, expandCallback.bind(this)); |
+ this._setClipboardData(null); |
+ } else { |
+ this._clipboardNodeData.node.copyTo(targetNode, null, expandCallback.bind(this)); |
+ } |
+ |
+ /** |
+ * @param {?Protocol.Error} error |
+ * @param {!DOMAgent.NodeId} nodeId |
+ * @this {WebInspector.ElementsTreeOutline} |
+ */ |
+ function expandCallback(error, nodeId) |
+ { |
+ if (error) |
+ return; |
+ var pastedNode = this._domModel.nodeForId(nodeId); |
+ if (!pastedNode) |
+ return; |
+ this.selectDOMNode(pastedNode); |
+ } |
+ }, |
+ |
/** |
* @param {boolean} visible |
*/ |
@@ -350,6 +500,8 @@ WebInspector.ElementsTreeOutline.prototype = { |
if (this._suppressRevealAndSelect) |
return; |
+ this._updateModifiedNodes(); |
+ |
if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode) |
node = this.rootDOMNode.firstChild; |
if (!node) |
@@ -613,7 +765,7 @@ WebInspector.ElementsTreeOutline.prototype = { |
treeElement._populateTagContextMenu(contextMenu, event); |
} else if (commentNode) { |
contextMenu.appendSeparator(); |
- treeElement._populateNodeContextMenu(contextMenu, textNode); |
+ treeElement._populateNodeContextMenu(contextMenu); |
} else if (isPseudoElement) { |
treeElement._populateScrollIntoView(contextMenu); |
} else if (treeElement._node.isShadowRoot()) { |
@@ -920,6 +1072,17 @@ WebInspector.ElementsTreeElement.prototype = { |
} |
}, |
+ /** |
+ * @param {boolean} inClipboard |
+ */ |
+ setInClipboard: function(inClipboard) |
+ { |
+ if (this._inClipboard === inClipboard) |
+ return; |
+ this._inClipboard = inClipboard; |
+ this.listItemElement.classList.toggle("in-clipboard", inClipboard); |
+ }, |
+ |
get hovered() |
{ |
return this._hovered; |
@@ -1453,14 +1616,19 @@ WebInspector.ElementsTreeElement.prototype = { |
if (isEditable && !this._editing) |
contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), openTagElement._editAsHTML.bind(openTagElement)); |
var isShadowRoot = this.representedObject.isShadowRoot(); |
- if (!isShadowRoot) |
- contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this)); |
// Place it here so that all "Copy"-ing items stick together. |
if (this.representedObject.nodeType() === Node.ELEMENT_NODE) |
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy CSS path" : "Copy CSS Path"), this._copyCSSPath.bind(this)); |
if (!isShadowRoot) |
contextMenu.appendItem(WebInspector.UIString("Copy XPath"), this._copyXPath.bind(this)); |
+ if (!isShadowRoot) { |
+ var treeOutline = this.treeOutline; |
+ contextMenu.appendItem(WebInspector.UIString("Copy"), treeOutline._copyNode.bind(treeOutline, this.representedObject)); |
+ contextMenu.appendItem(WebInspector.UIString("Cut"), treeOutline._cutNode.bind(treeOutline, this.representedObject), !this.hasEditableNode()); |
+ contextMenu.appendItem(WebInspector.UIString("Paste"), treeOutline._pasteNode.bind(treeOutline, this.representedObject), !treeOutline._canPaste(this.representedObject)); |
+ } |
+ |
if (isEditable) |
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete node" : "Delete Node"), this.remove.bind(this)); |
}, |
@@ -2347,11 +2515,6 @@ WebInspector.ElementsTreeElement.prototype = { |
node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange)); |
}, |
- _copyHTML: function() |
- { |
- this._node.copyNode(); |
- }, |
- |
_copyCSSPath: function() |
{ |
InspectorFrontendHost.copyText(WebInspector.DOMPresentationUtils.cssPath(this._node, true)); |
@@ -2635,6 +2798,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
this._treeOutline.selectDOMNode(null, false); |
this._domModel.hideDOMNodeHighlight(); |
this._recentlyModifiedNodes.clear(); |
+ delete this._treeOutline._clipboardNodeData; |
} |
} |