[turbolizer] Display live ranges in portrait mode
Allow live ranges to be displayed beside the instruction sequence in turbolizer. Bug: v8:7327 Change-Id: Idec5130655ccc9365dd32ec6927d8615a3e5c570 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3585960 Commit-Queue: George Wort <george.wort@arm.com> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/main@{#80226}
This commit is contained in:
parent
750b5f37fb
commit
d67a14b2fc
@ -25,8 +25,10 @@ code is governed by a BSD-style license that can be found in the LICENSE file.
|
|||||||
<div id="resizer-ranges" class="resizer" style="visibility:hidden;"></div>
|
<div id="resizer-ranges" class="resizer" style="visibility:hidden;"></div>
|
||||||
<div id="ranges" class="content" style="visibility:hidden;"></div>
|
<div id="ranges" class="content" style="visibility:hidden;"></div>
|
||||||
<div id="show-hide-ranges" class="show-hide-pane" style="visibility: hidden">
|
<div id="show-hide-ranges" class="show-hide-pane" style="visibility: hidden">
|
||||||
<input id="ranges-expand" type="image" title="show ranges" src="up-arrow.png" class="button-input invisible">
|
<input id="ranges-expand-vert" type="image" title="show ranges" src="up-arrow.png" class="button-input invisible">
|
||||||
<input id="ranges-shrink" type="image" title="hide ranges" src="down-arrow.png" class="button-input">
|
<input id="ranges-shrink-vert" type="image" title="hide ranges" src="down-arrow.png" class="button-input">
|
||||||
|
<input id="ranges-expand-hor" type="image" title="show ranges" src="left-arrow.png" class="button-input invisible">
|
||||||
|
<input id="ranges-shrink-hor" type="image" title="hide ranges" src="right-arrow.png" class="button-input invisible">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="resizer-right" class="resizer"></div>
|
<div id="resizer-right" class="resizer"></div>
|
||||||
|
@ -15,8 +15,10 @@ export const DISASSEMBLY_PANE_ID = 'disassembly';
|
|||||||
export const DISASSEMBLY_COLLAPSE_ID = 'disassembly-shrink';
|
export const DISASSEMBLY_COLLAPSE_ID = 'disassembly-shrink';
|
||||||
export const DISASSEMBLY_EXPAND_ID = 'disassembly-expand';
|
export const DISASSEMBLY_EXPAND_ID = 'disassembly-expand';
|
||||||
export const RANGES_PANE_ID = "ranges";
|
export const RANGES_PANE_ID = "ranges";
|
||||||
export const RANGES_COLLAPSE_ID = "ranges-shrink";
|
export const RANGES_COLLAPSE_VERT_ID = "ranges-shrink-vert";
|
||||||
export const RANGES_EXPAND_ID = "ranges-expand";
|
export const RANGES_EXPAND_VERT_ID = "ranges-expand-vert";
|
||||||
|
export const RANGES_COLLAPSE_HOR_ID = "ranges-shrink-hor";
|
||||||
|
export const RANGES_EXPAND_HOR_ID = "ranges-expand-hor";
|
||||||
export const UNICODE_BLOCK = '▋';
|
export const UNICODE_BLOCK = '▋';
|
||||||
export const PROF_COLS = [
|
export const PROF_COLS = [
|
||||||
{ perc: 0, col: { r: 255, g: 255, b: 255 } },
|
{ perc: 0, col: { r: 255, g: 255, b: 255 } },
|
||||||
|
@ -40,6 +40,7 @@ export class GraphMultiView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
|
this.container.className = "";
|
||||||
this.hideCurrentPhase();
|
this.hideCurrentPhase();
|
||||||
super.hide();
|
super.hide();
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,75 @@ class CSSVariables {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserSettingsObject {
|
||||||
|
value: boolean;
|
||||||
|
resetFunction: (boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manages the user's setting options regarding how the grid is displayed.
|
||||||
|
class UserSettings {
|
||||||
|
static readonly SESSION_STORAGE_PREFIX = "ranges-setting-";
|
||||||
|
settings: Map<string, UserSettingsObject>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.settings = new Map<string, UserSettingsObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
addSetting(settingName: string, value: boolean, resetFunction: (boolean) => void) {
|
||||||
|
this.settings.set(settingName, {value, resetFunction});
|
||||||
|
}
|
||||||
|
|
||||||
|
getToggleElement(settingName: string, settingLabel: string) {
|
||||||
|
const toggleEl = createElement("label", "range-toggle-setting", settingLabel);
|
||||||
|
const toggleInput = createElement("input", "range-toggle-setting") as HTMLInputElement;
|
||||||
|
toggleInput.id = "range-toggle-" + settingName;
|
||||||
|
toggleInput.setAttribute("type", "checkbox");
|
||||||
|
toggleInput.oninput = () => {
|
||||||
|
toggleInput.disabled = true;
|
||||||
|
this.set(settingName, toggleInput.checked);
|
||||||
|
this.reset(settingName);
|
||||||
|
toggleInput.disabled = false;
|
||||||
|
};
|
||||||
|
toggleEl.insertBefore(toggleInput, toggleEl.firstChild);
|
||||||
|
return toggleEl;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(settingName: string) {
|
||||||
|
const settingObject = this.settings.get(settingName);
|
||||||
|
window.sessionStorage.setItem(UserSettings.SESSION_STORAGE_PREFIX + settingName,
|
||||||
|
settingObject.value.toString());
|
||||||
|
settingObject.resetFunction(settingObject.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(settingName: string) {
|
||||||
|
return this.settings.get(settingName).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(settingName: string, value: boolean) {
|
||||||
|
this.settings.get(settingName).value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetFromSessionStorage() {
|
||||||
|
this.settings.forEach((settingObject: UserSettingsObject,
|
||||||
|
settingName: string) => {
|
||||||
|
const storedString =
|
||||||
|
window.sessionStorage.getItem(UserSettings.SESSION_STORAGE_PREFIX + settingName);
|
||||||
|
if (storedString) {
|
||||||
|
const storedValue = storedString == "true" ? true : false;
|
||||||
|
this.set(settingName, storedValue);
|
||||||
|
if (storedValue) {
|
||||||
|
const toggle =
|
||||||
|
(document.getElementById("range-toggle-" + settingName) as HTMLInputElement);
|
||||||
|
if (!toggle.checked) {
|
||||||
|
toggle.checked = storedValue;
|
||||||
|
settingObject.resetFunction(storedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Store the required data from the blocks JSON.
|
// Store the required data from the blocks JSON.
|
||||||
class BlocksData {
|
class BlocksData {
|
||||||
blockBorders: Set<number>;
|
blockBorders: Set<number>;
|
||||||
@ -185,13 +254,13 @@ class Divs {
|
|||||||
yAxis: HTMLElement;
|
yAxis: HTMLElement;
|
||||||
grid: HTMLElement;
|
grid: HTMLElement;
|
||||||
|
|
||||||
constructor() {
|
constructor(userSettings: UserSettings) {
|
||||||
this.container = document.getElementById("ranges");
|
this.container = document.getElementById("ranges");
|
||||||
this.resizerBar = document.getElementById("resizer-ranges");
|
this.resizerBar = document.getElementById("resizer-ranges");
|
||||||
this.snapper = document.getElementById("show-hide-ranges");
|
this.snapper = document.getElementById("show-hide-ranges");
|
||||||
|
|
||||||
this.content = document.createElement("div");
|
this.content = document.createElement("div");
|
||||||
this.content.appendChild(this.elementForTitle());
|
this.content.appendChild(this.elementForTitle(userSettings));
|
||||||
|
|
||||||
this.showOnLoad = document.createElement("div");
|
this.showOnLoad = document.createElement("div");
|
||||||
this.showOnLoad.style.visibility = "hidden";
|
this.showOnLoad.style.visibility = "hidden";
|
||||||
@ -209,7 +278,7 @@ class Divs {
|
|||||||
this.registerHeaders.appendChild(this.registers);
|
this.registerHeaders.appendChild(this.registers);
|
||||||
}
|
}
|
||||||
|
|
||||||
elementForTitle() {
|
elementForTitle(userSettings: UserSettings) {
|
||||||
const titleEl = createElement("div", "range-title-div");
|
const titleEl = createElement("div", "range-title-div");
|
||||||
const titleBar = createElement("div", "range-title");
|
const titleBar = createElement("div", "range-title");
|
||||||
titleBar.appendChild(createElement("div", "", "Live Ranges"));
|
titleBar.appendChild(createElement("div", "", "Live Ranges"));
|
||||||
@ -220,6 +289,7 @@ class Divs {
|
|||||||
+ "\nand j, the index of the interval within the LiveRange, to give i:j.";
|
+ "\nand j, the index of the interval within the LiveRange, to give i:j.";
|
||||||
titleEl.appendChild(titleBar);
|
titleEl.appendChild(titleBar);
|
||||||
titleEl.appendChild(titleHelp);
|
titleEl.appendChild(titleHelp);
|
||||||
|
titleEl.appendChild(userSettings.getToggleElement("landscapeMode", "Landscape Mode"));
|
||||||
return titleEl;
|
return titleEl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -862,6 +932,7 @@ export class RangeView {
|
|||||||
isShown: boolean;
|
isShown: boolean;
|
||||||
numPositions: number;
|
numPositions: number;
|
||||||
cssVariables: CSSVariables;
|
cssVariables: CSSVariables;
|
||||||
|
userSettings: UserSettings;
|
||||||
divs: Divs;
|
divs: Divs;
|
||||||
rowConstructor: RowConstructor;
|
rowConstructor: RowConstructor;
|
||||||
phaseChangeHandler: PhaseChangeHandler;
|
phaseChangeHandler: PhaseChangeHandler;
|
||||||
@ -881,8 +952,11 @@ export class RangeView {
|
|||||||
this.gridAccessor = new GridAccessor(this.sequenceView);
|
this.gridAccessor = new GridAccessor(this.sequenceView);
|
||||||
this.intervalsAccessor = new IntervalElementsAccessor(this.sequenceView);
|
this.intervalsAccessor = new IntervalElementsAccessor(this.sequenceView);
|
||||||
this.cssVariables = new CSSVariables();
|
this.cssVariables = new CSSVariables();
|
||||||
|
this.userSettings = new UserSettings();
|
||||||
|
// Indicates whether the RangeView is displayed beside or below the SequenceView.
|
||||||
|
this.userSettings.addSetting("landscapeMode", false, this.resetLandscapeMode.bind(this));
|
||||||
this.blocksData = new BlocksData(blocks);
|
this.blocksData = new BlocksData(blocks);
|
||||||
this.divs = new Divs();
|
this.divs = new Divs(this.userSettings);
|
||||||
this.scrollHandler = new ScrollHandler(this.divs);
|
this.scrollHandler = new ScrollHandler(this.divs);
|
||||||
this.numPositions = this.sequenceView.numInstructions * Constants.POSITIONS_PER_INSTRUCTION;
|
this.numPositions = this.sequenceView.numInstructions * Constants.POSITIONS_PER_INSTRUCTION;
|
||||||
this.rowConstructor = new RowConstructor(this);
|
this.rowConstructor = new RowConstructor(this);
|
||||||
@ -909,6 +983,7 @@ export class RangeView {
|
|||||||
window.dispatchEvent(new Event('resize'));
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
this.userSettings.resetFromSessionStorage();
|
||||||
this.scrollHandler.restoreScroll();
|
this.scrollHandler.restoreScroll();
|
||||||
this.scrollHandler.syncHidden();
|
this.scrollHandler.syncHidden();
|
||||||
this.divs.showOnLoad.style.visibility = "visible";
|
this.divs.showOnLoad.style.visibility = "visible";
|
||||||
@ -935,4 +1010,15 @@ export class RangeView {
|
|||||||
onresize() {
|
onresize() {
|
||||||
if (this.isShown) this.scrollHandler.syncHidden();
|
if (this.isShown) this.scrollHandler.syncHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetLandscapeMode(isInLandscapeMode: boolean) {
|
||||||
|
// Used to communicate the setting to Resizer.
|
||||||
|
this.divs.container.dataset.landscapeMode = isInLandscapeMode.toString();
|
||||||
|
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
// Required to adjust scrollbar spacing.
|
||||||
|
setTimeout(() => {
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,12 @@ class Snapper {
|
|||||||
sourceCollapse: HTMLElement;
|
sourceCollapse: HTMLElement;
|
||||||
disassemblyExpand: HTMLElement;
|
disassemblyExpand: HTMLElement;
|
||||||
disassemblyCollapse: HTMLElement;
|
disassemblyCollapse: HTMLElement;
|
||||||
rangesExpand: HTMLElement;
|
|
||||||
rangesCollapse: HTMLElement;
|
rangesShowHide: HTMLElement;
|
||||||
|
rangesExpandVert: HTMLElement;
|
||||||
|
rangesCollapseVert: HTMLElement;
|
||||||
|
rangesExpandHor: HTMLElement;
|
||||||
|
rangesCollapseHor: HTMLElement;
|
||||||
|
|
||||||
constructor(resizer: Resizer) {
|
constructor(resizer: Resizer) {
|
||||||
this.resizer = resizer;
|
this.resizer = resizer;
|
||||||
@ -20,8 +24,11 @@ class Snapper {
|
|||||||
this.sourceCollapse = document.getElementById(C.SOURCE_COLLAPSE_ID);
|
this.sourceCollapse = document.getElementById(C.SOURCE_COLLAPSE_ID);
|
||||||
this.disassemblyExpand = document.getElementById(C.DISASSEMBLY_EXPAND_ID);
|
this.disassemblyExpand = document.getElementById(C.DISASSEMBLY_EXPAND_ID);
|
||||||
this.disassemblyCollapse = document.getElementById(C.DISASSEMBLY_COLLAPSE_ID);
|
this.disassemblyCollapse = document.getElementById(C.DISASSEMBLY_COLLAPSE_ID);
|
||||||
this.rangesExpand = document.getElementById(C.RANGES_EXPAND_ID);
|
this.rangesShowHide = document.getElementById("show-hide-ranges");
|
||||||
this.rangesCollapse = document.getElementById(C.RANGES_COLLAPSE_ID);
|
this.rangesExpandVert = document.getElementById(C.RANGES_EXPAND_VERT_ID);
|
||||||
|
this.rangesCollapseVert = document.getElementById(C.RANGES_COLLAPSE_VERT_ID);
|
||||||
|
this.rangesExpandHor = document.getElementById(C.RANGES_EXPAND_HOR_ID);
|
||||||
|
this.rangesCollapseHor = document.getElementById(C.RANGES_COLLAPSE_HOR_ID);
|
||||||
|
|
||||||
document.getElementById("show-hide-source").addEventListener("click", () => {
|
document.getElementById("show-hide-source").addEventListener("click", () => {
|
||||||
this.resizer.resizerLeft.classed("snapped", !this.resizer.resizerLeft.classed("snapped"));
|
this.resizer.resizerLeft.classed("snapped", !this.resizer.resizerLeft.classed("snapped"));
|
||||||
@ -33,9 +40,10 @@ class Snapper {
|
|||||||
this.setDisassemblyExpanded(!this.disassemblyExpand.classList.contains("invisible"));
|
this.setDisassemblyExpanded(!this.disassemblyExpand.classList.contains("invisible"));
|
||||||
this.resizer.updatePanes();
|
this.resizer.updatePanes();
|
||||||
});
|
});
|
||||||
document.getElementById("show-hide-ranges").addEventListener("click", () => {
|
this.rangesShowHide.dataset.expanded = "1";
|
||||||
|
this.rangesShowHide.addEventListener("click", () => {
|
||||||
this.resizer.resizerRanges.classed("snapped", !this.resizer.resizerRanges.classed("snapped"));
|
this.resizer.resizerRanges.classed("snapped", !this.resizer.resizerRanges.classed("snapped"));
|
||||||
this.setRangesExpanded(!this.rangesExpand.classList.contains("invisible"));
|
this.setRangesExpanded(this.rangesShowHide.dataset.expanded != "1");
|
||||||
this.resizer.updatePanes();
|
this.resizer.updatePanes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -59,7 +67,6 @@ class Snapper {
|
|||||||
window.sessionStorage.setItem("expandedState-source", `${isSourceExpanded}`);
|
window.sessionStorage.setItem("expandedState-source", `${isSourceExpanded}`);
|
||||||
this.sourceExpand.classList.toggle("invisible", isSourceExpanded);
|
this.sourceExpand.classList.toggle("invisible", isSourceExpanded);
|
||||||
this.sourceCollapse.classList.toggle("invisible", !isSourceExpanded);
|
this.sourceCollapse.classList.toggle("invisible", !isSourceExpanded);
|
||||||
document.getElementById("show-hide-ranges").style.marginLeft = isSourceExpanded ? null : "40px";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSourceExpanded(isSourceExpanded: boolean): void {
|
setSourceExpanded(isSourceExpanded: boolean): void {
|
||||||
@ -76,12 +83,35 @@ class Snapper {
|
|||||||
setDisassemblyExpanded(isDisassemblyExpanded: boolean): void {
|
setDisassemblyExpanded(isDisassemblyExpanded: boolean): void {
|
||||||
this.disassemblyUpdate(isDisassemblyExpanded);
|
this.disassemblyUpdate(isDisassemblyExpanded);
|
||||||
this.resizer.updateRightWidth();
|
this.resizer.updateRightWidth();
|
||||||
|
this.resizer.updateRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
rangesUpdate(isRangesExpanded: boolean): void {
|
rangesUpdate(isRangesExpanded: boolean): void {
|
||||||
window.sessionStorage.setItem("expandedState-ranges", `${isRangesExpanded}`);
|
window.sessionStorage.setItem("expandedState-ranges", `${isRangesExpanded}`);
|
||||||
this.rangesExpand.classList.toggle("invisible", isRangesExpanded);
|
this.rangesShowHide.dataset.expanded = isRangesExpanded ? "1" : "0";
|
||||||
this.rangesCollapse.classList.toggle("invisible", !isRangesExpanded);
|
const landscapeMode = this.resizer.isRangesInLandscapeMode();
|
||||||
|
this.rangesExpandVert.classList.toggle("invisible", !landscapeMode || isRangesExpanded);
|
||||||
|
this.rangesCollapseVert.classList.toggle("invisible", !landscapeMode || !isRangesExpanded);
|
||||||
|
this.rangesExpandHor.classList.toggle("invisible", landscapeMode || isRangesExpanded);
|
||||||
|
this.rangesCollapseHor.classList.toggle("invisible", landscapeMode || !isRangesExpanded);
|
||||||
|
let left: number;
|
||||||
|
if (landscapeMode) {
|
||||||
|
left = this.resizer.sepLeft + this.resizer.RESIZER_SIZE;
|
||||||
|
} else {
|
||||||
|
left = isRangesExpanded ? this.resizer.sepRangesX + this.resizer.RESIZER_SIZE
|
||||||
|
: (this.resizer.sepRangesX - this.rangesShowHide.clientWidth
|
||||||
|
- (2 * this.resizer.RESIZER_SIZE));
|
||||||
|
}
|
||||||
|
const marginLeft = parseInt(window.getComputedStyle(this.rangesShowHide, null)
|
||||||
|
.getPropertyValue('margin-left').slice(0, -2), 10);
|
||||||
|
const marginRight = parseInt(window.getComputedStyle(this.rangesShowHide, null)
|
||||||
|
.getPropertyValue('margin-right').slice(0, -2), 10);
|
||||||
|
const width = this.rangesShowHide.clientWidth + marginLeft + marginRight;
|
||||||
|
// The left value is bounded on both sides by another show/hide button of the same width. The
|
||||||
|
// max value must also account for its own width. marginRight is subtracted from both sides to
|
||||||
|
// reduce the separation between buttons.
|
||||||
|
const maxLeft = document.body.getBoundingClientRect().width - (2 * width) + marginRight;
|
||||||
|
this.rangesShowHide.style.left = Math.max(width - marginRight, Math.min(left, maxLeft)) + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
setRangesExpanded(isRangesExpanded: boolean): void {
|
setRangesExpanded(isRangesExpanded: boolean): void {
|
||||||
@ -100,7 +130,9 @@ export class Resizer {
|
|||||||
middle: HTMLElement;
|
middle: HTMLElement;
|
||||||
sepLeft: number;
|
sepLeft: number;
|
||||||
sepRight: number;
|
sepRight: number;
|
||||||
|
sepRangesX: number;
|
||||||
sepRangesHeight: number;
|
sepRangesHeight: number;
|
||||||
|
rangesInLandscapeMode: boolean;
|
||||||
panesUpdatedCallback: () => void;
|
panesUpdatedCallback: () => void;
|
||||||
resizerRight: d3.Selection<HTMLDivElement, any, any, any>;
|
resizerRight: d3.Selection<HTMLDivElement, any, any, any>;
|
||||||
resizerLeft: d3.Selection<HTMLDivElement, any, any, any>;
|
resizerLeft: d3.Selection<HTMLDivElement, any, any, any>;
|
||||||
@ -109,8 +141,9 @@ export class Resizer {
|
|||||||
private readonly SOURCE_PANE_DEFAULT_PERCENT = 1 / 4;
|
private readonly SOURCE_PANE_DEFAULT_PERCENT = 1 / 4;
|
||||||
private readonly DISASSEMBLY_PANE_DEFAULT_PERCENT = 3 / 4;
|
private readonly DISASSEMBLY_PANE_DEFAULT_PERCENT = 3 / 4;
|
||||||
private readonly RANGES_PANE_HEIGHT_DEFAULT_PERCENT = 3 / 4;
|
private readonly RANGES_PANE_HEIGHT_DEFAULT_PERCENT = 3 / 4;
|
||||||
|
private readonly RANGES_PANE_WIDTH_DEFAULT_PERCENT = 1 / 2;
|
||||||
private readonly RESIZER_RANGES_HEIGHT_BUFFER_PERCENTAGE = 5;
|
private readonly RESIZER_RANGES_HEIGHT_BUFFER_PERCENTAGE = 5;
|
||||||
private readonly RESIZER_SIZE = document.getElementById("resizer-ranges").offsetHeight;
|
readonly RESIZER_SIZE = document.getElementById("resizer-ranges").offsetHeight;
|
||||||
|
|
||||||
constructor(panesUpdatedCallback: () => void, deadWidth: number, deadHeight: number) {
|
constructor(panesUpdatedCallback: () => void, deadWidth: number, deadHeight: number) {
|
||||||
const resizer = this;
|
const resizer = this;
|
||||||
@ -134,22 +167,29 @@ export class Resizer {
|
|||||||
if (window.sessionStorage.getItem("ranges-pane-height-percent") === null) {
|
if (window.sessionStorage.getItem("ranges-pane-height-percent") === null) {
|
||||||
window.sessionStorage.setItem("ranges-pane-height-percent", `${this.RANGES_PANE_HEIGHT_DEFAULT_PERCENT}`);
|
window.sessionStorage.setItem("ranges-pane-height-percent", `${this.RANGES_PANE_HEIGHT_DEFAULT_PERCENT}`);
|
||||||
}
|
}
|
||||||
|
if (window.sessionStorage.getItem("ranges-pane-width-percent") === null) {
|
||||||
|
window.sessionStorage.setItem("ranges-pane-width-percent", `${this.RANGES_PANE_WIDTH_DEFAULT_PERCENT}`);
|
||||||
|
}
|
||||||
|
|
||||||
this.updateSizes();
|
this.updateSizes();
|
||||||
|
|
||||||
const dragResizeLeft = d3.drag()
|
const dragResizeLeft = d3.drag()
|
||||||
.on('drag', function () {
|
.on('drag', function () {
|
||||||
const x = d3.mouse(this.parentElement)[0];
|
const x = d3.mouse(document.body)[0];
|
||||||
resizer.sepLeft = Math.min(Math.max(0, x), resizer.sepRight);
|
resizer.sepLeft = Math.min(Math.max(0, x), resizer.sepRight);
|
||||||
|
if (resizer.sepLeft > resizer.sepRangesX) {
|
||||||
|
resizer.sepRangesX = resizer.sepLeft;
|
||||||
|
}
|
||||||
resizer.updatePanes();
|
resizer.updatePanes();
|
||||||
})
|
})
|
||||||
.on('start', function () {
|
.on('start', function () {
|
||||||
|
resizer.rangesInLandscapeMode = resizer.isRangesInLandscapeMode();
|
||||||
resizer.resizerLeft.classed("dragged", true);
|
resizer.resizerLeft.classed("dragged", true);
|
||||||
})
|
})
|
||||||
.on('end', function () {
|
.on('end', function () {
|
||||||
// If the panel is close enough to the left, treat it as if it was pulled all the way to the lefg.
|
// If the panel is close enough to the left, treat it as if it was pulled all the way to the left.
|
||||||
const x = d3.mouse(this.parentElement)[0];
|
const coords = d3.mouse(document.body);
|
||||||
if (x <= deadWidth) {
|
if (coords[0] <= deadWidth) {
|
||||||
resizer.sepLeft = 0;
|
resizer.sepLeft = 0;
|
||||||
resizer.updatePanes();
|
resizer.updatePanes();
|
||||||
}
|
}
|
||||||
@ -160,23 +200,30 @@ export class Resizer {
|
|||||||
}
|
}
|
||||||
resizer.snapper.setSourceExpanded(!resizer.isLeftSnapped());
|
resizer.snapper.setSourceExpanded(!resizer.isLeftSnapped());
|
||||||
resizer.resizerLeft.classed("dragged", false);
|
resizer.resizerLeft.classed("dragged", false);
|
||||||
|
if (!resizer.rangesInLandscapeMode) {
|
||||||
|
resizer.dragRangesEnd(coords, resizer.sepRangesX >= resizer.sepRight - deadWidth);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
resizer.resizerLeft.call(dragResizeLeft);
|
resizer.resizerLeft.call(dragResizeLeft);
|
||||||
|
|
||||||
const dragResizeRight = d3.drag()
|
const dragResizeRight = d3.drag()
|
||||||
.on('drag', function () {
|
.on('drag', function () {
|
||||||
const x = d3.mouse(this.parentElement)[0];
|
const x = d3.mouse(document.body)[0];
|
||||||
resizer.sepRight = Math.max(resizer.sepLeft, Math.min(x, document.body.getBoundingClientRect().width));
|
resizer.sepRight = Math.max(resizer.sepLeft, Math.min(x, document.body.getBoundingClientRect().width));
|
||||||
|
if (resizer.sepRight < resizer.sepRangesX || resizer.isRangesSnapped()) {
|
||||||
|
resizer.sepRangesX = resizer.sepRight;
|
||||||
|
}
|
||||||
resizer.updatePanes();
|
resizer.updatePanes();
|
||||||
})
|
})
|
||||||
.on('start', function () {
|
.on('start', function () {
|
||||||
|
resizer.rangesInLandscapeMode = resizer.isRangesInLandscapeMode();
|
||||||
resizer.resizerRight.classed("dragged", true);
|
resizer.resizerRight.classed("dragged", true);
|
||||||
})
|
})
|
||||||
.on('end', function () {
|
.on('end', function () {
|
||||||
// If the panel is close enough to the right, treat it as if it was pulled all the way to the right.
|
// If the panel is close enough to the right, treat it as if it was pulled all the way to the right.
|
||||||
const x = d3.mouse(this.parentElement)[0];
|
const coords = d3.mouse(document.body);
|
||||||
const clientWidth = document.body.getBoundingClientRect().width;
|
const clientWidth = document.body.getBoundingClientRect().width;
|
||||||
if (x >= (clientWidth - deadWidth)) {
|
if (coords[0] >= (clientWidth - deadWidth)) {
|
||||||
resizer.sepRight = clientWidth - 1;
|
resizer.sepRight = clientWidth - 1;
|
||||||
resizer.updatePanes();
|
resizer.updatePanes();
|
||||||
}
|
}
|
||||||
@ -187,32 +234,28 @@ export class Resizer {
|
|||||||
}
|
}
|
||||||
resizer.snapper.setDisassemblyExpanded(!resizer.isRightSnapped());
|
resizer.snapper.setDisassemblyExpanded(!resizer.isRightSnapped());
|
||||||
resizer.resizerRight.classed("dragged", false);
|
resizer.resizerRight.classed("dragged", false);
|
||||||
|
if (!resizer.rangesInLandscapeMode) {
|
||||||
|
resizer.dragRangesEnd(coords, resizer.sepRangesX >= resizer.sepRight - deadWidth);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
resizer.resizerRight.call(dragResizeRight);
|
resizer.resizerRight.call(dragResizeRight);
|
||||||
|
|
||||||
const dragResizeRanges = d3.drag()
|
const dragResizeRanges = d3.drag()
|
||||||
.on('drag', function () {
|
.on('drag', function () {
|
||||||
const y = d3.mouse(this.parentElement)[1];
|
const coords = d3.mouse(document.body);
|
||||||
resizer.sepRangesHeight = Math.max(100, Math.min(y, window.innerHeight) - resizer.RESIZER_RANGES_HEIGHT_BUFFER_PERCENTAGE);
|
resizer.sepRangesX = Math.max(resizer.sepLeft, Math.min(coords[0], resizer.sepRight));
|
||||||
|
resizer.sepRangesHeight = Math.max(100, Math.min(coords[1], window.innerHeight)
|
||||||
|
- resizer.RESIZER_RANGES_HEIGHT_BUFFER_PERCENTAGE);
|
||||||
resizer.updatePanes();
|
resizer.updatePanes();
|
||||||
})
|
})
|
||||||
.on('start', function () {
|
.on('start', function () {
|
||||||
|
resizer.rangesInLandscapeMode = resizer.isRangesInLandscapeMode();
|
||||||
resizer.resizerRanges.classed("dragged", true);
|
resizer.resizerRanges.classed("dragged", true);
|
||||||
})
|
})
|
||||||
.on('end', function () {
|
.on('end', function () {
|
||||||
// If the panel is close enough to the bottom, treat it as if it was pulled all the way to the bottom.
|
const coords = d3.mouse(document.body);
|
||||||
const y = d3.mouse(this.parentElement)[1];
|
const isSnappedX = !resizer.rangesInLandscapeMode && (coords[0] >= (resizer.sepRight - deadWidth));
|
||||||
if (y >= (window.innerHeight - deadHeight)) {
|
resizer.dragRangesEnd(coords, isSnappedX);
|
||||||
resizer.sepRangesHeight = window.innerHeight;
|
|
||||||
resizer.updatePanes();
|
|
||||||
}
|
|
||||||
// Snap if dragged all the way to the bottom.
|
|
||||||
resizer.resizerRanges.classed("snapped", resizer.sepRangesHeight >= window.innerHeight - 1);
|
|
||||||
if (!resizer.isRangesSnapped()) {
|
|
||||||
window.sessionStorage.setItem("ranges-pane-height-percent", `${resizer.sepRangesHeight / window.innerHeight}`);
|
|
||||||
}
|
|
||||||
resizer.snapper.setRangesExpanded(!resizer.isRangesSnapped());
|
|
||||||
resizer.resizerRanges.classed("dragged", false);
|
|
||||||
});
|
});
|
||||||
resizer.resizerRanges.call(dragResizeRanges);
|
resizer.resizerRanges.call(dragResizeRanges);
|
||||||
|
|
||||||
@ -236,23 +279,66 @@ export class Resizer {
|
|||||||
return this.resizerRanges.classed("snapped");
|
return this.resizerRanges.classed("snapped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isRangesInLandscapeMode() {
|
||||||
|
return this.ranges.dataset.landscapeMode == "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
dragRangesEnd(coords: [number, number], isSnappedX: boolean) {
|
||||||
|
// If the panel is close enough to the bottom, treat it as if it was pulled all the way to the
|
||||||
|
// bottom.
|
||||||
|
const isSnappedY = this.rangesInLandscapeMode
|
||||||
|
&& (coords[1] >= (window.innerHeight - this.deadHeight));
|
||||||
|
if (isSnappedX || isSnappedY) {
|
||||||
|
if (isSnappedX) {
|
||||||
|
this.sepRangesX = this.sepRight;
|
||||||
|
}
|
||||||
|
if (isSnappedY) {
|
||||||
|
this.sepRangesHeight = window.innerHeight;
|
||||||
|
}
|
||||||
|
this.updatePanes();
|
||||||
|
}
|
||||||
|
// Snap if dragged all the way to the bottom.
|
||||||
|
this.resizerRanges.classed("snapped", (!this.rangesInLandscapeMode && (this.sepRangesX >= this.sepRight - 1))
|
||||||
|
|| (this.rangesInLandscapeMode
|
||||||
|
&& (this.sepRangesHeight >= window.innerHeight - 1)));
|
||||||
|
if (!this.isRangesSnapped()) {
|
||||||
|
if (this.rangesInLandscapeMode) {
|
||||||
|
window.sessionStorage.setItem("ranges-pane-height-percent",
|
||||||
|
`${this.sepRangesHeight / window.innerHeight}`);
|
||||||
|
} else {
|
||||||
|
window.sessionStorage.setItem("ranges-pane-width-percent",
|
||||||
|
`${(this.sepRangesX - this.sepLeft) / (this.sepRight - this.sepLeft)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.snapper.setRangesExpanded(!this.isRangesSnapped());
|
||||||
|
this.resizerRanges.classed("dragged", false);
|
||||||
|
}
|
||||||
|
|
||||||
updateRangesPane() {
|
updateRangesPane() {
|
||||||
const clientHeight = window.innerHeight;
|
const clientHeight = window.innerHeight;
|
||||||
const rangesIsHidden = this.ranges.style.visibility == "hidden";
|
const rangesIsHidden = this.ranges.style.visibility == "hidden";
|
||||||
let resizerSize = this.RESIZER_SIZE;
|
const resizerSize = rangesIsHidden ? 0 : this.RESIZER_SIZE;
|
||||||
if (rangesIsHidden) {
|
const sepRangesHeight = rangesIsHidden ? clientHeight : this.sepRangesHeight;
|
||||||
resizerSize = 0;
|
const sepRangesX = rangesIsHidden ? this.sepRight : this.sepRangesX;
|
||||||
this.sepRangesHeight = clientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rangeHeight = clientHeight - this.sepRangesHeight;
|
this.snapper.rangesUpdate(this.snapper.rangesShowHide.dataset.expanded == "1");
|
||||||
|
|
||||||
|
const inLandscapeMode = this.isRangesInLandscapeMode();
|
||||||
|
const rangeHeight = inLandscapeMode ? clientHeight - sepRangesHeight : clientHeight;
|
||||||
this.ranges.style.height = rangeHeight + 'px';
|
this.ranges.style.height = rangeHeight + 'px';
|
||||||
const panelWidth = this.sepRight - this.sepLeft - (2 * resizerSize);
|
const panelWidth = this.sepRight - this.sepLeft - (2 * resizerSize);
|
||||||
this.ranges.style.width = panelWidth + 'px';
|
const rangeWidth = inLandscapeMode ? panelWidth : this.sepRight - sepRangesX;
|
||||||
|
this.ranges.style.width = rangeWidth + 'px';
|
||||||
const multiview = document.getElementById("multiview");
|
const multiview = document.getElementById("multiview");
|
||||||
if (multiview && multiview.style) {
|
if (multiview && multiview.style) {
|
||||||
multiview.style.height = (this.sepRangesHeight - resizerSize) + 'px';
|
multiview.style.height = (inLandscapeMode ? sepRangesHeight - resizerSize : clientHeight) + 'px';
|
||||||
multiview.style.width = panelWidth + 'px';
|
const midWidth = inLandscapeMode ? panelWidth : sepRangesX - this.sepLeft - (3 * resizerSize);
|
||||||
|
multiview.style.width = midWidth + 'px';
|
||||||
|
if (inLandscapeMode) {
|
||||||
|
this.middle.classList.remove("display-inline-flex");
|
||||||
|
} else {
|
||||||
|
this.middle.classList.add("display-inline-flex");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the range grid and labels.
|
// Resize the range grid and labels.
|
||||||
@ -261,12 +347,12 @@ export class Resizer {
|
|||||||
const yAxis = (this.ranges.getElementsByClassName("range-y-axis")[0] as HTMLElement);
|
const yAxis = (this.ranges.getElementsByClassName("range-y-axis")[0] as HTMLElement);
|
||||||
const rangeHeader = (this.ranges.getElementsByClassName("range-header")[0] as HTMLElement);
|
const rangeHeader = (this.ranges.getElementsByClassName("range-header")[0] as HTMLElement);
|
||||||
|
|
||||||
const gridWidth = panelWidth - yAxis.clientWidth;
|
const gridWidth = rangeWidth - yAxis.clientWidth;
|
||||||
rangeGrid.style.width = Math.floor(gridWidth - 1) + 'px';
|
rangeGrid.style.width = Math.floor(gridWidth - 1) + 'px';
|
||||||
// Take live ranges' right scrollbar into account.
|
// Take live ranges' right scrollbar into account.
|
||||||
rangeHeader.style.width = (gridWidth - rangeGrid.offsetWidth + rangeGrid.clientWidth - 1) + 'px';
|
rangeHeader.style.width = (gridWidth - rangeGrid.offsetWidth + rangeGrid.clientWidth - 1) + 'px';
|
||||||
// Set resizer to horizontal.
|
this.resizerRanges.style('width', inLandscapeMode ? rangeWidth + 'px' : resizerSize + 'px');
|
||||||
this.resizerRanges.style('width', panelWidth + 'px');
|
this.resizerRanges.style('height', inLandscapeMode ? resizerSize + 'px' : clientHeight + 'px');
|
||||||
|
|
||||||
const rangeTitle = (this.ranges.getElementsByClassName("range-title-div")[0] as HTMLElement);
|
const rangeTitle = (this.ranges.getElementsByClassName("range-title-div")[0] as HTMLElement);
|
||||||
const rangeHeaderLabel = (this.ranges.getElementsByClassName("range-header-label-x")[0] as HTMLElement);
|
const rangeHeaderLabel = (this.ranges.getElementsByClassName("range-header-label-x")[0] as HTMLElement);
|
||||||
@ -274,6 +360,9 @@ export class Resizer {
|
|||||||
rangeGrid.style.height = gridHeight + 'px';
|
rangeGrid.style.height = gridHeight + 'px';
|
||||||
// Take live ranges' bottom scrollbar into account.
|
// Take live ranges' bottom scrollbar into account.
|
||||||
yAxis.style.height = (gridHeight - rangeGrid.offsetHeight + rangeGrid.clientHeight) + 'px';
|
yAxis.style.height = (gridHeight - rangeGrid.offsetHeight + rangeGrid.clientHeight) + 'px';
|
||||||
|
} else {
|
||||||
|
this.resizerRanges.style('width', '0px');
|
||||||
|
this.resizerRanges.style('height', '0px');
|
||||||
}
|
}
|
||||||
this.resizerRanges.style('ranges', this.ranges.style.height);
|
this.resizerRanges.style('ranges', this.ranges.style.height);
|
||||||
}
|
}
|
||||||
@ -290,9 +379,12 @@ export class Resizer {
|
|||||||
updateRanges() {
|
updateRanges() {
|
||||||
if (this.isRangesSnapped()) {
|
if (this.isRangesSnapped()) {
|
||||||
this.sepRangesHeight = window.innerHeight;
|
this.sepRangesHeight = window.innerHeight;
|
||||||
|
this.sepRangesX = this.sepRight;
|
||||||
} else {
|
} else {
|
||||||
const sepRangesHeight = window.sessionStorage.getItem("ranges-pane-height-percent");
|
const sepRangesHeight = window.sessionStorage.getItem("ranges-pane-height-percent");
|
||||||
this.sepRangesHeight = window.innerHeight * Number.parseFloat(sepRangesHeight);
|
this.sepRangesHeight = window.innerHeight * Number.parseFloat(sepRangesHeight);
|
||||||
|
const sepRangesWidth = window.sessionStorage.getItem("ranges-pane-width-percent");
|
||||||
|
this.sepRangesX = this.sepLeft + ((this.sepRight - this.sepLeft) * Number.parseFloat(sepRangesWidth));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,13 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.range-toggle-show {
|
label.range-toggle-setting {
|
||||||
|
text-align: right;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.range-toggle-show,
|
||||||
|
input.range-toggle-setting {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user