[turbolizer] Keep tabs and info tab between loads
This is a first step towards support for opening more than one turbolizer json file at once. Change-Id: Id51ce47c59492ba63de03eceb0163fa1701ea500 Notry: true Bug: v8:7327 Reviewed-on: https://chromium-review.googlesource.com/c/1407057 Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#58790}
This commit is contained in:
parent
5b490eb2ee
commit
d7a989e3b8
@ -1,104 +1,114 @@
|
||||
|
||||
export class Tabs {
|
||||
container: HTMLElement;
|
||||
tabBar: HTMLElement;
|
||||
nextTabId: number;
|
||||
private container: HTMLElement;
|
||||
private tabBar: HTMLElement;
|
||||
private nextTabId: number;
|
||||
|
||||
mkTabBar(container: HTMLElement) {
|
||||
container.classList.add("nav-tabs-container");
|
||||
this.tabBar = document.createElement("ul");
|
||||
this.tabBar.id = `tab-bar-${container.id}`;
|
||||
this.tabBar.className = "nav-tabs";
|
||||
this.tabBar.ondrop = this.tabBarOnDrop.bind(this);
|
||||
this.tabBar.ondragover = this.tabBarOnDragover.bind(this);
|
||||
this.tabBar.onclick = this.tabBarOnClick.bind(this);
|
||||
private mkTabBar(container: HTMLElement) {
|
||||
container.classList.add("nav-tabs-container");
|
||||
this.tabBar = document.createElement("ul");
|
||||
this.tabBar.id = `tab-bar-${container.id}`;
|
||||
this.tabBar.className = "nav-tabs";
|
||||
this.tabBar.ondrop = this.tabBarOnDrop.bind(this);
|
||||
this.tabBar.ondragover = this.tabBarOnDragover.bind(this);
|
||||
this.tabBar.onclick = this.tabBarOnClick.bind(this);
|
||||
|
||||
const defaultDiv = document.createElement("div");
|
||||
defaultDiv.className = "tab-content tab-default";
|
||||
defaultDiv.id = `tab-content-${container.id}-default`;
|
||||
container.insertBefore(defaultDiv, container.firstChild);
|
||||
container.insertBefore(this.tabBar, container.firstChild);
|
||||
const defaultDiv = document.createElement("div");
|
||||
defaultDiv.className = "tab-content tab-default";
|
||||
defaultDiv.id = `tab-content-${container.id}-default`;
|
||||
container.insertBefore(defaultDiv, container.firstChild);
|
||||
container.insertBefore(this.tabBar, container.firstChild);
|
||||
}
|
||||
|
||||
constructor(container: HTMLElement) {
|
||||
this.container = container;
|
||||
this.nextTabId = 0;
|
||||
this.mkTabBar(container);
|
||||
}
|
||||
|
||||
activateTab(tab: HTMLLIElement) {
|
||||
if (typeof tab.dataset.divid !== "string") return;
|
||||
for (const li of this.tabBar.querySelectorAll<HTMLLIElement>("li.active")) {
|
||||
li.classList.remove("active");
|
||||
this.showTab(li, false);
|
||||
}
|
||||
tab.classList.add("active");
|
||||
this.showTab(tab, true);
|
||||
}
|
||||
|
||||
constructor(container: HTMLElement) {
|
||||
this.container = container;
|
||||
this.nextTabId = 0;
|
||||
this.mkTabBar(container);
|
||||
}
|
||||
|
||||
showTab(li: HTMLElement, show: boolean = true) {
|
||||
const tabDiv = document.getElementById(li.dataset.divid);
|
||||
tabDiv.style.display = show ? "block" : "none";
|
||||
}
|
||||
|
||||
activateTab(tab: HTMLLIElement) {
|
||||
if (typeof tab.dataset.divid !== "string") return;
|
||||
for (const li of this.tabBar.querySelectorAll<HTMLLIElement>("li.active")) {
|
||||
li.classList.remove("active");
|
||||
this.showTab(li, false);
|
||||
}
|
||||
tab.classList.add("active");
|
||||
this.showTab(tab, true);
|
||||
}
|
||||
|
||||
addTab(caption: string): HTMLLIElement {
|
||||
const newTab = document.createElement("li");
|
||||
newTab.innerHTML = caption;
|
||||
newTab.id = `tab-header-${this.container.id}-${this.nextTabId++}`;
|
||||
const lastTab = this.tabBar.querySelector("li.open-tab");
|
||||
this.tabBar.insertBefore(newTab, lastTab);
|
||||
return newTab;
|
||||
}
|
||||
|
||||
addTabAndContent(caption: string): [HTMLLIElement, HTMLDivElement] {
|
||||
const contentDiv = document.createElement("div");
|
||||
contentDiv.className = "tab-content tab-default";
|
||||
contentDiv.id = `tab-content-${this.container.id}-${this.nextTabId++}`;
|
||||
contentDiv.style.display = "none";
|
||||
this.container.appendChild(contentDiv);
|
||||
|
||||
const newTab = this.addTab(caption);
|
||||
newTab.dataset.divid = contentDiv.id;
|
||||
newTab.draggable = true;
|
||||
newTab.ondragstart = this.tabOnDragStart.bind(this);
|
||||
const lastTab = this.tabBar.querySelector("li.open-tab");
|
||||
this.tabBar.insertBefore(newTab, lastTab);
|
||||
return [newTab, contentDiv];
|
||||
}
|
||||
|
||||
moveTabDiv(tab: HTMLLIElement) {
|
||||
clearTabsAndContent() {
|
||||
for (const tab of this.tabBar.querySelectorAll(".nav-tabs > li")) {
|
||||
if (!(tab instanceof HTMLLIElement)) continue;
|
||||
if (tab.classList.contains("persistent-tab")) continue;
|
||||
const tabDiv = document.getElementById(tab.dataset.divid);
|
||||
tabDiv.style.display = "none";
|
||||
tab.classList.remove("active");
|
||||
this.tabBar.parentNode.appendChild(tabDiv);
|
||||
tabDiv.parentNode.removeChild(tabDiv);
|
||||
tab.parentNode.removeChild(tab);
|
||||
}
|
||||
}
|
||||
|
||||
tabBarOnDrop(e: DragEvent) {
|
||||
if (!(e.target instanceof HTMLElement)) return;
|
||||
e.preventDefault();
|
||||
const tabId = e.dataTransfer.getData("text");
|
||||
const tab = document.getElementById(tabId) as HTMLLIElement;
|
||||
if (tab.parentNode != this.tabBar) {
|
||||
this.moveTabDiv(tab);
|
||||
}
|
||||
const dropTab =
|
||||
e.target.parentNode == this.tabBar
|
||||
? e.target : this.tabBar.querySelector("li.open-tab");
|
||||
this.tabBar.insertBefore(tab, dropTab);
|
||||
this.activateTab(tab);
|
||||
}
|
||||
private showTab(li: HTMLElement, show: boolean = true) {
|
||||
const tabDiv = document.getElementById(li.dataset.divid);
|
||||
tabDiv.style.display = show ? "block" : "none";
|
||||
}
|
||||
|
||||
tabBarOnDragover(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
public addTab(caption: string): HTMLLIElement {
|
||||
const newTab = document.createElement("li");
|
||||
newTab.innerHTML = caption;
|
||||
newTab.id = `tab-header-${this.container.id}-${this.nextTabId++}`;
|
||||
const lastTab = this.tabBar.querySelector("li.last-tab");
|
||||
this.tabBar.insertBefore(newTab, lastTab);
|
||||
return newTab;
|
||||
}
|
||||
|
||||
tabOnDragStart(e: DragEvent) {
|
||||
if (!(e.target instanceof HTMLElement)) return;
|
||||
e.dataTransfer.setData("text", e.target.id);
|
||||
}
|
||||
public addTabAndContent(caption: string): [HTMLLIElement, HTMLDivElement] {
|
||||
const contentDiv = document.createElement("div");
|
||||
contentDiv.className = "tab-content tab-default";
|
||||
contentDiv.id = `tab-content-${this.container.id}-${this.nextTabId++}`;
|
||||
contentDiv.style.display = "none";
|
||||
this.container.appendChild(contentDiv);
|
||||
|
||||
tabBarOnClick(e: MouseEvent) {
|
||||
const li = e.target as HTMLLIElement;
|
||||
this.activateTab(li);
|
||||
const newTab = this.addTab(caption);
|
||||
newTab.dataset.divid = contentDiv.id;
|
||||
newTab.draggable = true;
|
||||
newTab.ondragstart = this.tabOnDragStart.bind(this);
|
||||
const lastTab = this.tabBar.querySelector("li.last-tab");
|
||||
this.tabBar.insertBefore(newTab, lastTab);
|
||||
return [newTab, contentDiv];
|
||||
}
|
||||
|
||||
private moveTabDiv(tab: HTMLLIElement) {
|
||||
const tabDiv = document.getElementById(tab.dataset.divid);
|
||||
tabDiv.style.display = "none";
|
||||
tab.classList.remove("active");
|
||||
this.tabBar.parentNode.appendChild(tabDiv);
|
||||
}
|
||||
|
||||
private tabBarOnDrop(e: DragEvent) {
|
||||
if (!(e.target instanceof HTMLElement)) return;
|
||||
e.preventDefault();
|
||||
const tabId = e.dataTransfer.getData("text");
|
||||
const tab = document.getElementById(tabId) as HTMLLIElement;
|
||||
if (tab.parentNode != this.tabBar) {
|
||||
this.moveTabDiv(tab);
|
||||
}
|
||||
const dropTab =
|
||||
e.target.parentNode == this.tabBar
|
||||
? e.target : this.tabBar.querySelector("li.last-tab");
|
||||
this.tabBar.insertBefore(tab, dropTab);
|
||||
this.activateTab(tab);
|
||||
}
|
||||
|
||||
private tabBarOnDragover(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
private tabOnDragStart(e: DragEvent) {
|
||||
if (!(e.target instanceof HTMLElement)) return;
|
||||
e.dataTransfer.setData("text", e.target.id);
|
||||
}
|
||||
|
||||
private tabBarOnClick(e: MouseEvent) {
|
||||
const li = e.target as HTMLLIElement;
|
||||
this.activateTab(li);
|
||||
}
|
||||
}
|
||||
|
@ -16,16 +16,29 @@ window.onload = function () {
|
||||
let multiview = null;
|
||||
let disassemblyView = null;
|
||||
let sourceViews = [];
|
||||
let infoView = null;
|
||||
let selectionBroker = null;
|
||||
let sourceResolver = null;
|
||||
const resizer = new Resizer(panesUpdatedCallback, 100);
|
||||
const sourceTabsContainer = document.getElementById(C.SOURCE_PANE_ID);
|
||||
const sourceTabs = new Tabs(sourceTabsContainer);
|
||||
sourceTabs.addTab("+").classList.add("last-tab", "persistent-tab");
|
||||
const disassemblyTabsContainer = document.getElementById(C.GENERATED_PANE_ID);
|
||||
const disassemblyTabs = new Tabs(disassemblyTabsContainer);
|
||||
disassemblyTabs.addTab("+").classList.add("last-tab", "persistent-tab");
|
||||
const [infoTab, infoContainer] = sourceTabs.addTabAndContent("Info");
|
||||
infoTab.classList.add("persistent-tab");
|
||||
infoContainer.classList.add("viewpane", "scrollable");
|
||||
const infoView = new InfoView(infoContainer);
|
||||
infoView.show(null, null);
|
||||
sourceTabs.activateTab(infoTab);
|
||||
|
||||
function panesUpdatedCallback() {
|
||||
if (multiview) multiview.onresize();
|
||||
}
|
||||
|
||||
function loadFile(txtRes: string) {
|
||||
sourceTabs.clearTabsAndContent();
|
||||
disassemblyTabs.clearTabsAndContent();
|
||||
// If the JSON isn't properly terminated, assume compiler crashed and
|
||||
// add best-guess empty termination
|
||||
if (txtRes[txtRes.length - 2] == ',') {
|
||||
@ -63,33 +76,22 @@ window.onload = function () {
|
||||
sourceResolver.setNodePositionMap(jsonObj.nodePositions);
|
||||
sourceResolver.parsePhases(jsonObj.phases);
|
||||
|
||||
const sourceTabsContainer = document.getElementById(C.SOURCE_PANE_ID);
|
||||
const sourceTabs = new Tabs(sourceTabsContainer);
|
||||
const [sourceTab, sourceContainer] = sourceTabs.addTabAndContent("Source");
|
||||
sourceContainer.classList.add("viewpane", "scrollable");
|
||||
sourceTabs.activateTab(sourceTab);
|
||||
sourceTabs.addTab("+").classList.add("open-tab");
|
||||
const sourceView = new CodeView(sourceContainer, selectionBroker, sourceResolver, fnc, CodeMode.MAIN_SOURCE);
|
||||
sourceView.show(null, null);
|
||||
sourceViews.push(sourceView);
|
||||
|
||||
const [, infoContainer] = sourceTabs.addTabAndContent("Info");
|
||||
infoContainer.classList.add("viewpane", "scrollable");
|
||||
infoView = new InfoView(infoContainer);
|
||||
infoView.show(null, null);
|
||||
|
||||
sourceResolver.forEachSource(source => {
|
||||
const sourceView = new CodeView(sourceContainer, selectionBroker, sourceResolver, source, CodeMode.INLINED_SOURCE);
|
||||
sourceView.show(null, null);
|
||||
sourceViews.push(sourceView);
|
||||
});
|
||||
|
||||
const disassemblyTabsContainer = document.getElementById(C.GENERATED_PANE_ID);
|
||||
const disassemblyTabs = new Tabs(disassemblyTabsContainer);
|
||||
const [disassemblyTab, disassemblyContainer] = disassemblyTabs.addTabAndContent("Disassembly");
|
||||
disassemblyContainer.classList.add("viewpane", "scrollable");
|
||||
disassemblyTabs.activateTab(disassemblyTab);
|
||||
disassemblyTabs.addTab("+").classList.add("open-tab");
|
||||
disassemblyView = new DisassemblyView(disassemblyContainer, selectionBroker);
|
||||
disassemblyView.initializeCode(fnc.sourceText);
|
||||
if (sourceResolver.disassemblyPhase) {
|
||||
|
Loading…
Reference in New Issue
Block a user