[turbolizer] Make instructions clickable in sequence view
This is work towards making instructions in the sequence view selectable. For now, they are clickable and will select the corresponding instructions in the disassembly view. Bug: v8:7327 Notry: true Change-Id: I8850efeec7f94487bd80c11a7ad250a959062393 Reviewed-on: https://chromium-review.googlesource.com/c/1386112 Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#58397}
This commit is contained in:
parent
cd5f5937cd
commit
d2b96f1b16
@ -6,6 +6,8 @@ import { PROF_COLS, UNICODE_BLOCK } from "../src/constants"
|
||||
import { SelectionBroker } from "../src/selection-broker"
|
||||
import { TextView } from "../src/text-view"
|
||||
import { SourceResolver } from "./source-resolver";
|
||||
import { MySelection } from "./selection";
|
||||
import { anyToString } from "./util";
|
||||
|
||||
export class DisassemblyView extends TextView {
|
||||
SOURCE_POSITION_HEADER_REGEX: any;
|
||||
@ -13,6 +15,8 @@ export class DisassemblyView extends TextView {
|
||||
total_event_counts: any;
|
||||
max_event_counts: any;
|
||||
pos_lines: Array<any>;
|
||||
instructionSelectionHandler: InstructionSelectionHandler;
|
||||
offsetSelection: MySelection;
|
||||
|
||||
createViewElement() {
|
||||
const pane = document.createElement('div');
|
||||
@ -144,6 +148,32 @@ export class DisassemblyView extends TextView {
|
||||
};
|
||||
}
|
||||
view.divNode.addEventListener('click', linkHandlerBlock);
|
||||
|
||||
this.offsetSelection = new MySelection(anyToString);
|
||||
const instructionSelectionHandler = {
|
||||
clear: function () {
|
||||
view.offsetSelection.clear();
|
||||
view.updateSelection();
|
||||
broker.broadcastClear(instructionSelectionHandler);
|
||||
},
|
||||
select: function (instructionIds, selected) {
|
||||
view.offsetSelection.select(instructionIds, selected);
|
||||
view.updateSelection();
|
||||
broker.broadcastBlockSelect(instructionSelectionHandler, instructionIds, selected);
|
||||
},
|
||||
brokeredInstructionSelect: function (instructionIds, selected) {
|
||||
const firstSelect = view.offsetSelection.isEmpty();
|
||||
const keyPcOffsets = view.sourceResolver.instructionsToKeyPcOffsets(instructionIds);
|
||||
view.offsetSelection.select(keyPcOffsets, selected);
|
||||
view.updateSelection(firstSelect);
|
||||
},
|
||||
brokeredClear: function () {
|
||||
view.offsetSelection.clear();
|
||||
view.updateSelection();
|
||||
}
|
||||
};
|
||||
this.instructionSelectionHandler = instructionSelectionHandler;
|
||||
broker.addInstructionHandler(instructionSelectionHandler);
|
||||
}
|
||||
|
||||
initializeCode(sourceText, sourcePosition) {
|
||||
|
@ -6,29 +6,47 @@ import {SourceResolver, sourcePositionValid} from "../src/source-resolver"
|
||||
|
||||
export class SelectionBroker {
|
||||
sourceResolver: SourceResolver;
|
||||
allHandlers: Array<ClearableHandler>;
|
||||
sourcePositionHandlers: Array<SelectionHandler>;
|
||||
nodeHandlers: Array<NodeSelectionHandler>;
|
||||
blockHandlers: Array<BlockSelectionHandler>;
|
||||
instructionHandlers: Array<InstructionSelectionHandler>;
|
||||
|
||||
constructor(sourceResolver) {
|
||||
this.allHandlers = [];
|
||||
this.sourcePositionHandlers = [];
|
||||
this.nodeHandlers = [];
|
||||
this.blockHandlers = [];
|
||||
this.instructionHandlers = [];
|
||||
this.sourceResolver = sourceResolver;
|
||||
};
|
||||
|
||||
addSourcePositionHandler(handler) {
|
||||
addSourcePositionHandler(handler: SelectionHandler&ClearableHandler) {
|
||||
this.allHandlers.push(handler);
|
||||
this.sourcePositionHandlers.push(handler);
|
||||
}
|
||||
|
||||
addNodeHandler(handler) {
|
||||
addNodeHandler(handler: NodeSelectionHandler&ClearableHandler) {
|
||||
this.allHandlers.push(handler);
|
||||
this.nodeHandlers.push(handler);
|
||||
}
|
||||
|
||||
addBlockHandler(handler) {
|
||||
addBlockHandler(handler: BlockSelectionHandler&ClearableHandler) {
|
||||
this.allHandlers.push(handler);
|
||||
this.blockHandlers.push(handler);
|
||||
}
|
||||
|
||||
addInstructionHandler(handler: InstructionSelectionHandler&ClearableHandler) {
|
||||
this.allHandlers.push(handler);
|
||||
this.instructionHandlers.push(handler);
|
||||
}
|
||||
|
||||
broadcastInstructionSelect(from, instructionOffsets, selected) {
|
||||
for (const b of this.instructionHandlers) {
|
||||
if (b != from) b.brokeredInstructionSelect(instructionOffsets, selected);
|
||||
}
|
||||
}
|
||||
|
||||
broadcastSourcePositionSelect(from, sourcePositions, selected) {
|
||||
let broker = this;
|
||||
sourcePositions = sourcePositions.filter((l) => {
|
||||
@ -66,13 +84,7 @@ export class SelectionBroker {
|
||||
}
|
||||
|
||||
broadcastClear(from) {
|
||||
this.sourcePositionHandlers.forEach(function (b) {
|
||||
if (b != from) b.brokeredClear();
|
||||
});
|
||||
this.nodeHandlers.forEach(function (b) {
|
||||
if (b != from) b.brokeredClear();
|
||||
});
|
||||
this.blockHandlers.forEach(function (b) {
|
||||
this.allHandlers.forEach(function (b) {
|
||||
if (b != from) b.brokeredClear();
|
||||
});
|
||||
}
|
||||
|
@ -2,23 +2,30 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
interface ClearableHandler {
|
||||
brokeredClear(): void;
|
||||
}
|
||||
|
||||
interface SelectionHandler {
|
||||
clear(): void;
|
||||
select(nodeIds: any, selected: any): void;
|
||||
brokeredClear(): void;
|
||||
brokeredSourcePositionSelect(sourcePositions: any, selected: any): void;
|
||||
};
|
||||
|
||||
interface NodeSelectionHandler {
|
||||
clear(): void;
|
||||
select(nodeIds: any, selected: any): void;
|
||||
brokeredClear(): void;
|
||||
brokeredNodeSelect(nodeIds: any, selected: any): void;
|
||||
};
|
||||
|
||||
interface BlockSelectionHandler {
|
||||
clear(): void;
|
||||
select(nodeIds: any, selected: any): void;
|
||||
brokeredClear(): void;
|
||||
brokeredBlockSelect(blockIds: any, selected: any): void;
|
||||
};
|
||||
|
||||
interface InstructionSelectionHandler {
|
||||
clear(): void;
|
||||
select(instructionIds: any, selected: any): void;
|
||||
brokeredInstructionSelect(instructionIds: any, selected: any): void;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ import {Sequence} from "../src/source-resolver"
|
||||
import {isIterable} from "../src/util"
|
||||
import {PhaseView} from "../src/view"
|
||||
import {TextView} from "../src/text-view"
|
||||
import { MySelection } from "./selection";
|
||||
|
||||
export class SequenceView extends TextView implements PhaseView {
|
||||
sequence: Sequence;
|
||||
@ -40,6 +41,13 @@ export class SequenceView extends TextView implements PhaseView {
|
||||
this.divNode.innerHTML = '';
|
||||
this.sequence = data.sequence;
|
||||
this.search_info = [];
|
||||
this.divNode.addEventListener('click', (e:MouseEvent) => {
|
||||
if (!(e.target instanceof HTMLElement)) return;
|
||||
const instructionId = e.target.dataset.instructionId;
|
||||
if (!instructionId) return;
|
||||
if (!e.shiftKey) this.broker.broadcastClear(null);
|
||||
this.broker.broadcastInstructionSelect(null, [instructionId], true);
|
||||
});
|
||||
this.addBlocks(this.sequence.blocks);
|
||||
this.attachSelection(rememberedSelection);
|
||||
}
|
||||
@ -91,6 +99,8 @@ export class SequenceView extends TextView implements PhaseView {
|
||||
const instNodeEl = createElement("div", "instruction-node");
|
||||
|
||||
const inst_id = createElement("div", "instruction-id", instruction.id);
|
||||
inst_id.classList.add("clickable");
|
||||
inst_id.dataset.instructionId = instruction.id;
|
||||
instNodeEl.appendChild(inst_id);
|
||||
|
||||
const instContentsEl = createElement("div", "instruction-contents");
|
||||
|
@ -372,6 +372,14 @@ export class SourceResolver {
|
||||
return this.instructionToPCOffset.slice(start, end);
|
||||
}
|
||||
|
||||
instructionsToKeyPcOffsets(instructionIds) {
|
||||
const keyPcOffsets = [];
|
||||
for (const instructionId of instructionIds) {
|
||||
keyPcOffsets.push(this.instructionToPCOffset[instructionId]);
|
||||
}
|
||||
return keyPcOffsets;
|
||||
}
|
||||
|
||||
nodesToKeyPcOffsets(nodes) {
|
||||
let offsets = [];
|
||||
for (const node of nodes) {
|
||||
|
@ -6,6 +6,7 @@ import { View } from "../src/view"
|
||||
import { anyToString, ViewElements, isIterable } from "../src/util"
|
||||
import { MySelection } from "../src/selection"
|
||||
import { SourceResolver } from "./source-resolver";
|
||||
import { SelectionBroker } from "./selection-broker";
|
||||
|
||||
export abstract class TextView extends View {
|
||||
selectionHandler: NodeSelectionHandler;
|
||||
@ -20,6 +21,7 @@ export abstract class TextView extends View {
|
||||
nodeIdToBlockId: Array<string>;
|
||||
patterns: any;
|
||||
sourceResolver: SourceResolver;
|
||||
broker: SelectionBroker;
|
||||
|
||||
constructor(id, broker, patterns) {
|
||||
super(id);
|
||||
@ -32,6 +34,7 @@ export abstract class TextView extends View {
|
||||
view.nodeIdToBlockId = [];
|
||||
view.selection = new MySelection(anyToString);
|
||||
view.blockSelection = new MySelection(anyToString);
|
||||
view.broker = broker;
|
||||
view.sourceResolver = broker.sourceResolver;
|
||||
const selectionHandler = {
|
||||
clear: function () {
|
||||
@ -136,7 +139,12 @@ export abstract class TextView extends View {
|
||||
for (const el of elementsToSelect) {
|
||||
el.classList.toggle("selected", false);
|
||||
}
|
||||
const keyPcOffsets = view.sourceResolver.nodesToKeyPcOffsets(view.selection.selectedKeys());
|
||||
let keyPcOffsets = view.sourceResolver.nodesToKeyPcOffsets(view.selection.selectedKeys());
|
||||
if (view.offsetSelection) {
|
||||
for (const key of view.offsetSelection.selectedKeys()) {
|
||||
keyPcOffsets.push(Number(key))
|
||||
}
|
||||
}
|
||||
for (const keyPcOffset of keyPcOffsets) {
|
||||
const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset='${keyPcOffset}']`)
|
||||
for (const el of elementsToSelect) {
|
||||
|
@ -289,11 +289,11 @@ input:hover, .collapse-pane:hover input {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span.linkable-text {
|
||||
.linkable-text {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span.linkable-text:hover {
|
||||
.linkable-text:hover {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user