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..da0e35fe3c09ecad6e84fca93f78225ef5ebac92 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,132 @@ 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; |
+ } |
+ }, |
+ |
+ _cutNode: function() |
+ { |
+ this.handleCopyOrCutEvent(true); |
+ }, |
+ |
+ _copyNode: function() |
+ { |
+ this.handleCopyOrCutEvent(false); |
+ }, |
+ |
+ _pasteNode: function() |
+ { |
+ this.handlePasteEvent(); |
+ }, |
+ |
+ /** |
+ * @param {boolean} isCut |
+ * @param {!Event=} event |
+ */ |
+ handleCopyOrCutEvent: function(isCut, event) |
+ { |
+ this._setClipboardData(null); |
+ var currentFocusElement = WebInspector.currentFocusElement(); |
+ if (currentFocusElement && WebInspector.isBeingEdited(currentFocusElement)) |
+ return; |
+ |
+ // Don't prevent the normal copy if the user has a selection. |
+ if (!window.getSelection().isCollapsed) |
+ return; |
+ |
+ var selectedNode = this.selectedDOMNode(); |
+ if (!selectedNode) |
+ return; |
+ |
+ if (event) { |
+ event.clipboardData.clearData(); |
+ event.preventDefault(); |
+ } |
+ selectedNode.copyNode(); |
+ this._setClipboardData({node: selectedNode, isCut: isCut}); |
+ }, |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ _canPaste: function() |
+ { |
+ if (!this._clipboardNodeData) |
+ return false; |
+ |
+ // Don't prevent the normal copy if the user has a selection. |
+ if (!window.getSelection().isCollapsed) |
+ return false; |
+ |
+ var currentFocusElement = WebInspector.currentFocusElement(); |
+ if (currentFocusElement && WebInspector.isBeingEdited(currentFocusElement)) |
+ return false; |
+ |
+ var targetNode = this.selectedDOMNode(); |
+ if (!targetNode) |
+ return false; |
+ |
+ var node = this._clipboardNodeData.node; |
+ if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode))) |
aandrey
2014/07/25 13:32:54
node.isSelfOrAncestor(targetNode)
apavlov
2014/07/25 15:04:47
This works for ordinary DOM Node's, not our WI.DOM
|
+ return false; |
+ |
+ if (targetNode.target() !== node.target()) |
+ return false; |
+ return true; |
+ }, |
+ |
+ /** |
+ * @param {!Event=} event |
+ */ |
+ handlePasteEvent: function(event) |
+ { |
+ if (!this._canPaste()) |
+ return; |
+ |
+ if (this._clipboardNodeData.isCut) { |
+ this._clipboardNodeData.node.moveTo(this.selectedDOMNode(), null, expandCallback.bind(this)); |
+ this._setClipboardData(null); |
+ } else { |
+ this._clipboardNodeData.node.copyTo(this.selectedDOMNode(), null, expandCallback.bind(this)); |
+ } |
+ |
+ if (event) |
+ event.preventDefault(); |
+ |
+ /** |
+ * @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 +479,8 @@ WebInspector.ElementsTreeOutline.prototype = { |
if (this._suppressRevealAndSelect) |
return; |
+ this._updateModifiedNodes(); |
+ |
if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode) |
node = this.rootDOMNode.firstChild; |
if (!node) |
@@ -920,6 +1051,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 +1595,20 @@ 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)); |
aandrey
2014/07/25 13:32:54
This callbacks should always work regardless of th
apavlov
2014/07/25 15:04:47
Done
|
+ contextMenu.appendItem(WebInspector.UIString("Cut"), treeOutline._cutNode.bind(treeOutline)); |
+ if (treeOutline._canPaste()) |
+ contextMenu.appendItem(WebInspector.UIString("Paste"), treeOutline._pasteNode.bind(treeOutline)); |
aandrey
2014/07/25 13:32:54
maybe always append this option, but make disabled
apavlov
2014/07/25 15:04:47
Done.
|
+ } |
+ |
if (isEditable) |
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete node" : "Delete Node"), this.remove.bind(this)); |
}, |
@@ -2347,11 +2495,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 +2778,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
this._treeOutline.selectDOMNode(null, false); |
this._domModel.hideDOMNodeHighlight(); |
this._recentlyModifiedNodes.clear(); |
+ delete this._treeOutline._clipboardNodeData; |
} |
} |