Commit d2b96f1b authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[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: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58397}
parent cd5f5937
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment