Bug 1081245 - Make the call tree text select and copy-able. r=nfitzgerald

This commit is contained in:
Hernan Rodriguez Colmeiro 2015-10-30 02:57:00 -03:00
parent d5b596dbaa
commit 493cf700f9
10 changed files with 97 additions and 68 deletions

View File

@ -235,7 +235,8 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
cell.className = "plain call-tree-cell";
cell.setAttribute("type", type);
cell.setAttribute("crop", "end");
cell.setAttribute("value", value);
// Add a tabulation to the cell text in case it's is selected and copied.
cell.textContent = value + "\t";
return cell;
},
@ -261,7 +262,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
nameNode.className = "plain call-tree-name";
nameNode.setAttribute("flex", "1");
nameNode.setAttribute("crop", "end");
nameNode.setAttribute("value", frameName);
nameNode.textContent = frameName;
cell.appendChild(nameNode);
}
@ -276,6 +277,17 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
arrowNode.setAttribute("invisible", "");
}
// Add a line break to the last description of the row in case it's selected
// and copied.
let lastDescription = cell.querySelector('description:last-of-type');
lastDescription.textContent = lastDescription.textContent + "\n";
// Add spaces as frameLevel indicators in case the row is selected and
// copied. These spaces won't be displayed in the cell content.
let firstDescription = cell.querySelector('description:first-of-type');
let levelIndicator = frameLevel > 0 ? " ".repeat(frameLevel) : "";
firstDescription.textContent = levelIndicator + firstDescription.textContent;
return cell;
},
@ -285,7 +297,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
urlNode.className = "plain call-tree-url";
urlNode.setAttribute("flex", "1");
urlNode.setAttribute("crop", "end");
urlNode.setAttribute("value", frameInfo.fileName);
urlNode.textContent = frameInfo.fileName;
urlNode.setAttribute("tooltiptext", URL_LABEL_TOOLTIP + " → " + frameInfo.url);
urlNode.addEventListener("mousedown", this._onUrlClick);
cell.appendChild(urlNode);
@ -294,21 +306,21 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
if (frameInfo.line) {
let lineNode = doc.createElement("description");
lineNode.className = "plain call-tree-line";
lineNode.setAttribute("value", ":" + frameInfo.line);
lineNode.textContent = ":" + frameInfo.line;
cell.appendChild(lineNode);
}
if (frameInfo.column) {
let columnNode = doc.createElement("description");
columnNode.className = "plain call-tree-column";
columnNode.setAttribute("value", ":" + frameInfo.column);
columnNode.textContent = ":" + frameInfo.column;
cell.appendChild(columnNode);
}
if (frameInfo.host) {
let hostNode = doc.createElement("description");
hostNode.className = "plain call-tree-host";
hostNode.setAttribute("value", frameInfo.host);
hostNode.textContent = frameInfo.host;
cell.appendChild(hostNode);
}
@ -320,7 +332,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
let categoryNode = doc.createElement("description");
categoryNode.className = "plain call-tree-category";
categoryNode.style.color = frameInfo.categoryData.color;
categoryNode.setAttribute("value", frameInfo.categoryData.label);
categoryNode.textContent = frameInfo.categoryData.label;
cell.appendChild(categoryNode);
}
},

View File

@ -7,7 +7,7 @@
*/
function* spawnTest() {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, $, DetailsView, JsCallTreeView } = panel.panelWin;
let { EVENTS, $, $$, DetailsView, JsCallTreeView } = panel.panelWin;
// Enable platform data to show the categories.
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, true);
@ -22,17 +22,26 @@ function* spawnTest() {
is($(".call-tree-cells-container").hasAttribute("categories-hidden"), false,
"The call tree cells container should show the categories now.");
ok($(".call-tree-category[value=Gecko]"),
"A category node with the label `Gecko` is displayed in the tree.");
ok(geckoCategoryPresent($$),
"A category node with the text `Gecko` is displayed in the tree.");
// Disable platform data to show the categories.
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, false);
is($(".call-tree-cells-container").getAttribute("categories-hidden"), "",
"The call tree cells container should hide the categories now.");
ok(!$(".call-tree-category[value=Gecko]"),
"A category node with the label `Gecko` doesn't exist in the tree anymore.");
ok(!geckoCategoryPresent($$),
"A category node with the text `Gecko` doesn't exist in the tree anymore.");
yield teardown(panel);
finish();
}
function geckoCategoryPresent($$) {
for (let elem of $$('.call-tree-category')) {
if (elem.textContent.trim() == 'Gecko') {
return true
}
}
return false
}

View File

@ -31,27 +31,27 @@ function test() {
is(container.childNodes[0].childNodes[0].getAttribute("type"), "duration",
"The root node in the tree has a duration cell.");
is(container.childNodes[0].childNodes[0].getAttribute("value"), "20 ms",
is(container.childNodes[0].childNodes[0].textContent.trim(), "20 ms",
"The root node in the tree has the correct duration cell value.");
is(container.childNodes[0].childNodes[1].getAttribute("type"), "percentage",
"The root node in the tree has a percentage cell.");
is(container.childNodes[0].childNodes[1].getAttribute("value"), "100%",
is(container.childNodes[0].childNodes[1].textContent.trim(), "100%",
"The root node in the tree has the correct percentage cell value.");
is(container.childNodes[0].childNodes[2].getAttribute("type"), "self-duration",
"The root node in the tree has a self-duration cell.");
is(container.childNodes[0].childNodes[2].getAttribute("value"), "0 ms",
is(container.childNodes[0].childNodes[2].textContent.trim(), "0 ms",
"The root node in the tree has the correct self-duration cell value.");
is(container.childNodes[0].childNodes[3].getAttribute("type"), "self-percentage",
"The root node in the tree has a self-percentage cell.");
is(container.childNodes[0].childNodes[3].getAttribute("value"), "0%",
is(container.childNodes[0].childNodes[3].textContent.trim(), "0%",
"The root node in the tree has the correct self-percentage cell value.");
is(container.childNodes[0].childNodes[4].getAttribute("type"), "samples",
"The root node in the tree has an samples cell.");
is(container.childNodes[0].childNodes[4].getAttribute("value"), "0",
is(container.childNodes[0].childNodes[4].textContent.trim(), "0",
"The root node in the tree has the correct samples cell value.");
is(container.childNodes[0].childNodes[5].getAttribute("type"), "function",

View File

@ -33,13 +33,13 @@ function test() {
is(container.childNodes[0].className, "call-tree-item",
"The root node in the tree has the correct class name.");
is($$dur(0).getAttribute("value"), "20 ms",
is($$dur(0).textContent.trim(), "20 ms",
"The root's duration cell displays the correct value.");
is($$perc(0).getAttribute("value"), "100%",
is($$perc(0).textContent.trim(), "100%",
"The root's percentage cell displays the correct value.");
is($$sampl(0).getAttribute("value"), "0",
is($$sampl(0).textContent.trim(), "0",
"The root's samples cell displays the correct value.");
is($$fun(".call-tree-name")[0].getAttribute("value"), "(root)",
is($$fun(".call-tree-name")[0].textContent.trim(), "(root)",
"The root's function cell displays the correct name.");
is($$fun(".call-tree-url")[0], null,
"The root's function cell displays no url.");
@ -59,23 +59,23 @@ function test() {
is(container.childNodes[1].className, "call-tree-item",
"The .A node in the tree has the correct class name.");
is($$dur(1).getAttribute("value"), "20 ms",
is($$dur(1).textContent.trim(), "20 ms",
"The .A node's duration cell displays the correct value.");
is($$perc(1).getAttribute("value"), "100%",
is($$perc(1).textContent.trim(), "100%",
"The .A node's percentage cell displays the correct value.");
is($$sampl(1).getAttribute("value"), "0",
is($$sampl(1).textContent.trim(), "0",
"The .A node's samples cell displays the correct value.");
is($fun(".call-tree-name", $$(".call-tree-item")[1]).getAttribute("value"), "A",
is($fun(".call-tree-name", $$(".call-tree-item")[1]).textContent.trim(), "A",
"The .A node's function cell displays the correct name.");
is($fun(".call-tree-url", $$(".call-tree-item")[1]).getAttribute("value"), "baz",
is($fun(".call-tree-url", $$(".call-tree-item")[1]).textContent.trim(), "baz",
"The .A node's function cell displays the correct url.");
ok($fun(".call-tree-url", $$(".call-tree-item")[1]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
"The .A node's function cell displays the correct url tooltiptext.");
is($fun(".call-tree-line", $$(".call-tree-item")[1]).getAttribute("value"), ":12",
is($fun(".call-tree-line", $$(".call-tree-item")[1]).textContent.trim(), ":12",
"The .A node's function cell displays the correct line.");
is($fun(".call-tree-host", $$(".call-tree-item")[1]).getAttribute("value"), "foo",
is($fun(".call-tree-host", $$(".call-tree-item")[1]).textContent.trim(), "foo",
"The .A node's function cell displays the correct host.");
is($fun(".call-tree-category", $$(".call-tree-item")[1]).getAttribute("value"), "Gecko",
is($fun(".call-tree-category", $$(".call-tree-item")[1]).textContent.trim(), "Gecko",
"The .A node's function cell displays the correct category.");
let A = treeRoot.getChild();
@ -88,42 +88,42 @@ function test() {
is(container.childNodes[3].className, "call-tree-item",
"The .E node in the tree has the correct class name.");
is($$dur(2).getAttribute("value"), "15 ms",
is($$dur(2).textContent.trim(), "15 ms",
"The .A.B node's duration cell displays the correct value.");
is($$perc(2).getAttribute("value"), "75%",
is($$perc(2).textContent.trim(), "75%",
"The .A.B node's percentage cell displays the correct value.");
is($$sampl(2).getAttribute("value"), "0",
is($$sampl(2).textContent.trim(), "0",
"The .A.B node's samples cell displays the correct value.");
is($fun(".call-tree-name", $$(".call-tree-item")[2]).getAttribute("value"), "B",
is($fun(".call-tree-name", $$(".call-tree-item")[2]).textContent.trim(), "B",
"The .A.B node's function cell displays the correct name.");
is($fun(".call-tree-url", $$(".call-tree-item")[2]).getAttribute("value"), "baz",
is($fun(".call-tree-url", $$(".call-tree-item")[2]).textContent.trim(), "baz",
"The .A.B node's function cell displays the correct url.");
ok($fun(".call-tree-url", $$(".call-tree-item")[2]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
"The .A.B node's function cell displays the correct url tooltiptext.");
is($fun(".call-tree-line", $$(".call-tree-item")[2]).getAttribute("value"), ":34",
is($fun(".call-tree-line", $$(".call-tree-item")[2]).textContent.trim(), ":34",
"The .A.B node's function cell displays the correct line.");
is($fun(".call-tree-host", $$(".call-tree-item")[2]).getAttribute("value"), "foo",
is($fun(".call-tree-host", $$(".call-tree-item")[2]).textContent.trim(), "foo",
"The .A.B node's function cell displays the correct host.");
is($fun(".call-tree-category", $$(".call-tree-item")[2]).getAttribute("value"), "Styles",
is($fun(".call-tree-category", $$(".call-tree-item")[2]).textContent.trim(), "Styles",
"The .A.B node's function cell displays the correct category.");
is($$dur(3).getAttribute("value"), "5 ms",
is($$dur(3).textContent.trim(), "5 ms",
"The .A.E node's duration cell displays the correct value.");
is($$perc(3).getAttribute("value"), "25%",
is($$perc(3).textContent.trim(), "25%",
"The .A.E node's percentage cell displays the correct value.");
is($$sampl(3).getAttribute("value"), "0",
is($$sampl(3).textContent.trim(), "0",
"The .A.E node's samples cell displays the correct value.");
is($fun(".call-tree-name", $$(".call-tree-item")[3]).getAttribute("value"), "E",
is($fun(".call-tree-name", $$(".call-tree-item")[3]).textContent.trim(), "E",
"The .A.E node's function cell displays the correct name.");
is($fun(".call-tree-url", $$(".call-tree-item")[3]).getAttribute("value"), "baz",
is($fun(".call-tree-url", $$(".call-tree-item")[3]).textContent.trim(), "baz",
"The .A.E node's function cell displays the correct url.");
ok($fun(".call-tree-url", $$(".call-tree-item")[3]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
"The .A.E node's function cell displays the correct url tooltiptext.");
is($fun(".call-tree-line", $$(".call-tree-item")[3]).getAttribute("value"), ":90",
is($fun(".call-tree-line", $$(".call-tree-item")[3]).textContent.trim(), ":90",
"The .A.E node's function cell displays the correct line.");
is($fun(".call-tree-host", $$(".call-tree-item")[3]).getAttribute("value"), "foo",
is($fun(".call-tree-host", $$(".call-tree-item")[3]).textContent.trim(), "foo",
"The .A.E node's function cell displays the correct host.");
is($fun(".call-tree-category", $$(".call-tree-item")[3]).getAttribute("value"), "GC",
is($fun(".call-tree-category", $$(".call-tree-item")[3]).textContent.trim(), "GC",
"The .A.E node's function cell displays the correct category.");
finish();

View File

@ -42,34 +42,34 @@ function test() {
is($$fun(6).style.MozMarginStart, "48px",
"The .A.E.F node's function cell has the correct indentation.");
is($$name(0).getAttribute("value"), "(root)",
is($$name(0).textContent.trim(), "(root)",
"The root node's function cell displays the correct name.");
is($$name(1).getAttribute("value"), "A",
is($$name(1).textContent.trim(), "A",
"The .A node's function cell displays the correct name.");
is($$name(2).getAttribute("value"), "B",
is($$name(2).textContent.trim(), "B",
"The .A.B node's function cell displays the correct name.");
is($$name(3).getAttribute("value"), "D",
is($$name(3).textContent.trim(), "D",
"The .A.B.D node's function cell displays the correct name.");
is($$name(4).getAttribute("value"), "C",
is($$name(4).textContent.trim(), "C",
"The .A.B.C node's function cell displays the correct name.");
is($$name(5).getAttribute("value"), "E",
is($$name(5).textContent.trim(), "E",
"The .A.E node's function cell displays the correct name.");
is($$name(6).getAttribute("value"), "F",
is($$name(6).textContent.trim(), "F",
"The .A.E.F node's function cell displays the correct name.");
is($$duration(0).getAttribute("value"), "20 ms",
is($$duration(0).textContent.trim(), "20 ms",
"The root node's function cell displays the correct duration.");
is($$duration(1).getAttribute("value"), "20 ms",
is($$duration(1).textContent.trim(), "20 ms",
"The .A node's function cell displays the correct duration.");
is($$duration(2).getAttribute("value"), "15 ms",
is($$duration(2).textContent.trim(), "15 ms",
"The .A.B node's function cell displays the correct duration.");
is($$duration(3).getAttribute("value"), "10 ms",
is($$duration(3).textContent.trim(), "10 ms",
"The .A.B.D node's function cell displays the correct duration.");
is($$duration(4).getAttribute("value"), "5 ms",
is($$duration(4).textContent.trim(), "5 ms",
"The .A.B.C node's function cell displays the correct duration.");
is($$duration(5).getAttribute("value"), "5 ms",
is($$duration(5).textContent.trim(), "5 ms",
"The .A.E node's function cell displays the correct duration.");
is($$duration(6).getAttribute("value"), "5 ms",
is($$duration(6).textContent.trim(), "5 ms",
"The .A.E.F node's function cell displays the correct duration.");
finish();
@ -108,4 +108,3 @@ var gThread = synthesizeProfileForTest([{
{ category: 256, location: "F (http://foo/bar/baz:99)" }
]
}]);

View File

@ -43,21 +43,21 @@ function test() {
"Generalized JS node has correct category");
is(JS.target.getAttribute("tooltiptext"), "JIT",
"Generalized JS node has correct category");
is(JS.target.querySelector(".call-tree-name").getAttribute("value"), "JIT",
is(JS.target.querySelector(".call-tree-name").textContent.trim(), "JIT",
"Generalized JS node has correct display value as just the category name.");
is(JS2.target.getAttribute("category"), "js",
"Generalized second JS node has correct category");
is(JS2.target.getAttribute("tooltiptext"), "JIT",
"Generalized second JS node has correct category");
is(JS2.target.querySelector(".call-tree-name").getAttribute("value"), "JIT",
is(JS2.target.querySelector(".call-tree-name").textContent.trim(), "JIT",
"Generalized second JS node has correct display value as just the category name.");
is(GC.target.getAttribute("category"), "gc",
"Generalized GC node has correct category");
is(GC.target.getAttribute("tooltiptext"), "GC",
"Generalized GC node has correct category");
is(GC.target.querySelector(".call-tree-name").getAttribute("value"), "GC",
is(GC.target.querySelector(".call-tree-name").textContent.trim(), "GC",
"Generalized GC node has correct display value as just the category name.");
finish();

View File

@ -63,9 +63,9 @@ function test() {
let [total, self, name] = def;
name = name.trim();
is($$name(i).getAttribute("value"), name, `${name} has correct name.`);
is($$percentage(i).getAttribute("value"), `${total}%`, `${name} has correct total percent.`);
is($$selfpercentage(i).getAttribute("value"), `${self}%`, `${name} has correct self percent.`);
is($$name(i).textContent.trim(), name, `${name} has correct name.`);
is($$percentage(i).textContent.trim(), `${total}%`, `${name} has correct total percent.`);
is($$selfpercentage(i).textContent.trim(), `${self}%`, `${name} has correct self percent.`);
});
finish();

View File

@ -31,7 +31,7 @@ function* spawnTest() {
let rows = $$("#js-calltree-view .call-tree-item");
is(rows.length, 4, "4 call tree rows exist");
for (let row of rows) {
let name = $(".call-tree-name", row).value;
let name = $(".call-tree-name", row).textContent.trim();
switch (name) {
case "A":
ok($(".opt-icon", row), "found an opt icon on a leaf node with opt data");

View File

@ -522,7 +522,6 @@ AbstractTreeItem.prototype = {
* Handler for the "click" event on the element displaying this tree item.
*/
_onClick: function(e) {
e.preventDefault();
e.stopPropagation();
this.focus();
},

View File

@ -269,6 +269,16 @@
background-color: var(--theme-tab-toolbar-background);
}
.call-tree-item .call-tree-cell,
.call-tree-item .call-tree-cell[type=function] description {
-moz-user-select: text;
}
.call-tree-item .call-tree-cell::-moz-selection,
.call-tree-item .call-tree-cell[type=function] description::-moz-selection {
background-color: var(--theme-highlight-orange);
}
.call-tree-item:last-child {
border-bottom: 1px solid var(--cell-border-color);
}