gecko-dev/servo/etc/layout_viewer/viewer.html
Shing Lyu 72f401280b servo: Merge #14124 - Flexbox trace (from shinglyu:flexbox-trace); r=glennw
<!-- Please describe your changes on the following line: -->
This is a follow up for #13740, so r? @jdm

The first patch enables JSON serialization for flexbox flows, the second one fixed format incompatibilities for the layout viewer.

The 3rd and 4th patches are just layout viewer UI enhancements, we could split that to a spearate PR if you prefer.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #13846  (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because it's a trivial debug tool

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 58fec2f05a21eb69899c8ec21e4b95000cfed2f2
2016-12-28 00:33:31 -08:00

277 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Servo Layout Debugger</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Treeview -->
<link href="css/bootstrap-treeview.min.css" rel="stylesheet">
<!-- JSDiffPatch -->
<link href="css/formatters/html.css" rel="stylesheet">
<!-- Custom -->
<link href="css/main.css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container" role="main">
<div class="row">
<div class="col-sm-12">
<h1> Servo Layout Viewer </h1>
<p> Check the <a href="https://github.com/servo/servo/blob/master/etc/layout_viewer/README.md">README</a> for instructions.</p>
</div>
</div>
<div class="row">
<div class="col-sm-4">
<div class="row">
<div class="col-sm-12">
<div class="well">
<input type=file>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div id="trace-tree">
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<ul id="trace-list" class="list-group">
</ul>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="row">
<div class="col-sm-12">
<div class='panel panel-default'>
<div class='panel-heading'>Flow Tree</div>
<div class='panel-body' id="flow-tree"></div>
</div>
</div>
<div class="col-sm-12">
<div id="flow-diffs"></div>
</div>
</div>
</div>
</div>
<div id="toolbar">
<a href="#" id="prev_trace">< Prev step</a>
|
<a href="#" id="next_trace">Next step ></a>
<br>
<input type="checkbox" name="show_unchanged" id="show_unchanged" />
<label for="show_unchanged">Show unchanged code</label>
<br>
<a href="#top">Back to top</a>
</div>
</div>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Bootstrap -->
<script src="js/bootstrap.min.js"></script>
<!-- Treeview -->
<script src="js/bootstrap-treeview.min.js"></script>
<!-- JSDiffPatch -->
<script src="js/bundle.min.js"></script>
<script src="js/formatters.min.js"></script>
<script>
function get_base(trace_node) {
if (typeof(trace_node.data.base) == "undefined" && typeof(trace_node.data.block_flow) != "undefined") {
return trace_node.data.block_flow.base;
}
else {
return trace_node.data.base;
}
}
function create_flow_tree(trace_node) {
var base = get_base(trace_node);
var node = {
text: trace_node.class + " (" + base.id + ")",
id: base.id,
icon: "dummy",
href: "#diff-" + base.id
};
var children = [];
for (var i=0 ; i < base.children.length ; ++i) {
children.push(create_flow_tree(base.children[i]));
}
if (children.length > 0) {
node.nodes = children;
}
return node;
}
function create_flow_hash(trace_node, flow_hash) {
var base = get_base(trace_node);
flow_hash[base.id] = trace_node;
for (var i=0 ; i < base.children.length ; ++i) {
create_flow_hash(base.children[i], flow_hash);
}
delete base.children;
}
function flatten_trace(trace_node) {
var flow_tree = create_flow_tree(trace_node.children[0]);
var flow_hash = {};
create_flow_hash(trace_node.children[0], flow_hash);
return {
tree: flow_tree,
flows: flow_hash,
}
}
function create_tree_node(trace_node) {
var pre_trace = flatten_trace(trace_node.pre);
var post_trace = flatten_trace(trace_node.post);
var tree_node = {
text: trace_node.name,
icon: "dummy",
flow_tree: pre_trace.tree, // assume pre/post trace always have same tree!
pre: pre_trace.flows,
post: post_trace.flows,
};
var children = [];
for (var i=0 ; i < trace_node.children.length ; ++i) {
children.push(create_tree_node(trace_node.children[i]));
}
if (children.length > 0) {
tree_node.nodes = children;
}
return tree_node;
}
function update_flow_tree_bgcolor(flow_tree_node, node_color_hash) {
flow_tree_node.backColor = node_color_hash[flow_tree_node.id];
if (flow_tree_node.nodes !== undefined) {
for (var i=0 ; i < flow_tree_node.nodes.length ; ++i) {
update_flow_tree_bgcolor(flow_tree_node.nodes[i], node_color_hash)
}
}
}
function new_data_loaded(data) {
jsondiffpatch.formatters.html.hideUnchanged();
var node_color_hash = {};
var tree = [ create_tree_node(data) ];
$('#trace-tree').treeview({data: tree, levels: 3});
$('#trace-tree').on('nodeSelected', function(event, node) {
$("#flow-diffs").empty();
$('#trace-tree').treeview(true).revealNode(node);
for (var key in node.pre) {
var flow_left = node.pre[key];
var flow_right = node.post[key];
var delta = jsondiffpatch.create({
objectHash: function(obj) {
if (obj.data !== undefined && obj.data.base !== undefined) {
return obj.data.base.id;
}
if (obj.id !== undefined) {
return obj.id;
}
if (obj.index !== undefined) {
// FlexItem and FlexLine
return obj.index;
}
return JSON.stringify(obj);
}
}).diff(flow_left, flow_right);
if (delta !== undefined) {
var diff_id = "diff-" + key;
$("#flow-diffs").append(
"<div class='panel panel-default' id='" +
diff_id +
"'><div class='panel-heading'>" +
flow_left.class + " (" + key + ")" +
"</div><div class='panel-body'></div></div>");
document.getElementById(diff_id).getElementsByClassName('panel-body')[0].innerHTML =
jsondiffpatch.formatters.html.format(delta, flow_left);
node_color_hash[key] = "rgba(255, 0, 0, 0.7)";
} else {
node_color_hash[key] = "rgb(212, 248, 212)";
}
}
update_flow_tree_bgcolor(node.flow_tree, node_color_hash);
$('#flow-tree').treeview({data: [node.flow_tree], levels: 100, enableLinks: true, emptyIcon: "glyphicon glyphicon-unchecked hidden-glyphicon"});
});
$('#trace-tree').treeview(true).selectNode(0);
}
function register_toggle_unchanaged_code_handler() {
var show_unchange_box = document.getElementById("show_unchanged");
show_unchange_box.addEventListener("change", function(evt){
jsondiffpatch.formatters.html.showUnchanged(show_unchange_box.checked, null, 800);
});
}
function register_prev_next_trace_node() {
var prev_btn = document.getElementById("prev_trace");
var next_btn = document.getElementById("next_trace");
prev_btn.addEventListener("click", function(evt){
var node_id = $("#trace-tree").treeview(true).getSelected()[0].nodeId;
// We deliberatly choose to ignore the node_id out of bound case,
// since it won't break the UI usability
$("#trace-tree").treeview(true).selectNode(node_id - 1);
});
next_btn.addEventListener("click", function(evt){
var node_id = $("#trace-tree").treeview(true).getSelected()[0].nodeId;
$("#trace-tree").treeview(true).selectNode(node_id + 1);
});
}
$( document ).ready(function() {
var upload = document.getElementsByTagName('input')[0];
upload.onchange = function (e) {
e.preventDefault();
var file = upload.files[0],
reader = new FileReader();
reader.onload = function (event) {
new_data_loaded(JSON.parse(event.target.result));
};
reader.readAsText(file);
return false;
};
register_toggle_unchanaged_code_handler();
register_prev_next_trace_node();
});
</script>
</body>
</html>