From cd53a8515ad28dab64f3d594aee5a257fb7046fe Mon Sep 17 00:00:00 2001 From: dingge2016 Date: Thu, 25 Mar 2021 16:39:15 -0700 Subject: [PATCH 1/6] Add a message post for hovering nodes and implement the framework of relative interaction Implement a new interaction: When user hover a node on graph, highlight the node's line on the editor --- cyberbrain-vsc/src/interactions.ts | 20 ++++++++++++++++++++ cyberbrain-vsc/src/rpc_server.ts | 15 +++++++++++++-- cyberbrain-vsc/src/trace_graph.js | 11 +++++++++++ cyberbrain-vsc/src/webview.ts | 2 +- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 cyberbrain-vsc/src/interactions.ts diff --git a/cyberbrain-vsc/src/interactions.ts b/cyberbrain-vsc/src/interactions.ts new file mode 100644 index 00000000..ff40dc9d --- /dev/null +++ b/cyberbrain-vsc/src/interactions.ts @@ -0,0 +1,20 @@ +import { window, workspace} from 'vscode' + +export class Interactions { + //let currentHightlightLineno = null; + highlightLineOnEditor(lineno: Number) { + // TODO: Implement line highlight function on Editor + } + + + execute(context: { interactionType: String, info?: any }) { + switch (context.interactionType) { + case "Hover": + if (context.info?.hasOwnProperty("lineno")) + this.highlightLineOnEditor(context.info["lineno"]); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/cyberbrain-vsc/src/rpc_server.ts b/cyberbrain-vsc/src/rpc_server.ts index d50af7f9..c8e68b01 100644 --- a/cyberbrain-vsc/src/rpc_server.ts +++ b/cyberbrain-vsc/src/rpc_server.ts @@ -4,6 +4,7 @@ import * as bodyParser from "body-parser"; import { openTraceGraph } from "./webview"; import { isTestMode } from "./utils"; import { decode } from "@msgpack/msgpack"; +import { Interactions } from "./interactions"; let cl = console.log; @@ -14,11 +15,16 @@ export class RpcServer { private server: express.Express; private readonly context: vscode.ExtensionContext; private readonly listeningPort = 1989; // TODO: Make it configurable. +<<<<<<< HEAD +======= + private interactions: Interactions; +>>>>>>> Add a message post for hovering nodes and implement the framework of relative interaction constructor(context: vscode.ExtensionContext) { this.context = context; this.server = express(); this.server.use(bodyParser.raw({ limit: "10GB" })); + this.interactions = new Interactions(); this.server.post("/frame", (req, res) => { cl("get message"); @@ -28,8 +34,8 @@ export class RpcServer { // Sends data to the trace graph in webview. let webviewPanel = openTraceGraph(this.context); webviewPanel.webview.onDidReceiveMessage( - (message: string) => { - if (message === "Webview ready") { + (message: { command: string, context?: { interactionType: string, info?: any } }) => { + if (message.command === "Webview ready") { webviewPanel.webview.postMessage(decode(req.body)); // If under test, don't open the devtools window because it will cover the trace graph. @@ -39,6 +45,11 @@ export class RpcServer { ); } } + if (message.command === "Interaction behaivor") { + if (message.context) { + this.interactions.execute(message.context); + } + } }, undefined, this.context.subscriptions diff --git a/cyberbrain-vsc/src/trace_graph.js b/cyberbrain-vsc/src/trace_graph.js index 9aea88c4..e60a777d 100644 --- a/cyberbrain-vsc/src/trace_graph.js +++ b/cyberbrain-vsc/src/trace_graph.js @@ -294,6 +294,17 @@ class TraceGraph { return; } this.hoveredNodeId = node.id; + + // highlight the current hoverd node's line on the editor + // TODO: post interaction behavior "UnHover" to cancel the highlight when unhovering the node + vscode.postMessage({ + command: "Interaction behaivor", + context: { + interactionType: "Hover", + info: { lineno: node.lineno } + } + }); + // TODO: show values of all local variables at this point. displayValueInConsole(node); }); diff --git a/cyberbrain-vsc/src/webview.ts b/cyberbrain-vsc/src/webview.ts index 86c84b5d..8158a223 100644 --- a/cyberbrain-vsc/src/webview.ts +++ b/cyberbrain-vsc/src/webview.ts @@ -103,7 +103,7 @@ export function openTraceGraph(
`; From df7c9968f7513f84772487b4b38a9e365edf6cf4 Mon Sep 17 00:00:00 2001 From: dingge2016 Date: Thu, 25 Mar 2021 22:44:29 -0700 Subject: [PATCH 2/6] Implement line highlight function on Editor --- cyberbrain-vsc/src/interactions.ts | 27 ++++++++++++++++++++------- cyberbrain-vsc/src/trace_graph.js | 3 ++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/cyberbrain-vsc/src/interactions.ts b/cyberbrain-vsc/src/interactions.ts index ff40dc9d..0b5ff237 100644 --- a/cyberbrain-vsc/src/interactions.ts +++ b/cyberbrain-vsc/src/interactions.ts @@ -1,17 +1,30 @@ -import { window, workspace} from 'vscode' +import { window, Range, Position, workspace } from 'vscode' -export class Interactions { - //let currentHightlightLineno = null; - highlightLineOnEditor(lineno: Number) { - // TODO: Implement line highlight function on Editor +export class Interactions { + + // TODO: beautify the highlight UI + private decorationType = window.createTextEditorDecorationType({ + backgroundColor: 'yellow', + border: '2px solid white', + }) + + highlightLineOnEditor(lineno: number, relativePath: string) { + + const nodeEditor = window.visibleTextEditors.filter( + editor => editor.document.uri.fsPath.indexOf(relativePath) !== -1)[0] + if (nodeEditor) { + //TODO: The Range offset seems doesn't work. Whatever the range is, whole text part on the line will be highlighted. + // Maybe only highlight the variable? or use other way? Will improve it later. + let lineRange = [{ range: new Range(new Position(lineno, 0), new Position(lineno, 100)) }] + nodeEditor.setDecorations(this.decorationType, lineRange) + } } - execute(context: { interactionType: String, info?: any }) { switch (context.interactionType) { case "Hover": if (context.info?.hasOwnProperty("lineno")) - this.highlightLineOnEditor(context.info["lineno"]); + this.highlightLineOnEditor(context.info["lineno"], context.info["relativePath"]); break; default: break; diff --git a/cyberbrain-vsc/src/trace_graph.js b/cyberbrain-vsc/src/trace_graph.js index e60a777d..88dbc2ec 100644 --- a/cyberbrain-vsc/src/trace_graph.js +++ b/cyberbrain-vsc/src/trace_graph.js @@ -301,7 +301,7 @@ class TraceGraph { command: "Interaction behaivor", context: { interactionType: "Hover", - info: { lineno: node.lineno } + info: { lineno: node.lineno, relativePath: node.filename } } }); @@ -349,6 +349,7 @@ class TraceGraph { level: this.traceData.linenoMapping.get(event.lineno), lineno: event.lineno, label: buildLabelText(event), + filename: this.traceData.frameMetadata.filename, target: event.target, // "value" is a reserved property, use "runtimeValue" instead. runtimeValue: event.value, From 863a9e4f5c2b9c8d8746c77efec4ffda14d488bd Mon Sep 17 00:00:00 2001 From: dingge2016 Date: Tue, 30 Mar 2021 23:19:39 -0700 Subject: [PATCH 3/6] beautify the highlight UI 1. add an overview ruler on the right side of the editor. 2. use different color to highlight the line in different themes. --- cyberbrain-vsc/src/interactions.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/cyberbrain-vsc/src/interactions.ts b/cyberbrain-vsc/src/interactions.ts index 0b5ff237..aa219505 100644 --- a/cyberbrain-vsc/src/interactions.ts +++ b/cyberbrain-vsc/src/interactions.ts @@ -1,20 +1,26 @@ -import { window, Range, Position, workspace } from 'vscode' +import { window, Range, Position, workspace, TextEditor, OverviewRulerLane } from 'vscode' export class Interactions { - // TODO: beautify the highlight UI private decorationType = window.createTextEditorDecorationType({ - backgroundColor: 'yellow', - border: '2px solid white', - }) + isWholeLine: true, + overviewRulerColor: 'blue', + overviewRulerLane: OverviewRulerLane.Right, + light: { + // this color will be used in light color themes + backgroundColor: 'lightblue' + }, + dark: { + // this color will be used in dark color themes + backgroundColor: 'darkblue' + } + }); highlightLineOnEditor(lineno: number, relativePath: string) { const nodeEditor = window.visibleTextEditors.filter( editor => editor.document.uri.fsPath.indexOf(relativePath) !== -1)[0] if (nodeEditor) { - //TODO: The Range offset seems doesn't work. Whatever the range is, whole text part on the line will be highlighted. - // Maybe only highlight the variable? or use other way? Will improve it later. let lineRange = [{ range: new Range(new Position(lineno, 0), new Position(lineno, 100)) }] nodeEditor.setDecorations(this.decorationType, lineRange) } From 4117bc0fe2f96891e1fb15eae93128ab6170e241 Mon Sep 17 00:00:00 2001 From: dingge2016 Date: Wed, 31 Mar 2021 00:08:43 -0700 Subject: [PATCH 4/6] unhighlight the line when unhovering nodes --- cyberbrain-vsc/src/interactions.ts | 20 +++++++++++++++----- cyberbrain-vsc/src/trace_graph.js | 8 ++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cyberbrain-vsc/src/interactions.ts b/cyberbrain-vsc/src/interactions.ts index aa219505..1d751942 100644 --- a/cyberbrain-vsc/src/interactions.ts +++ b/cyberbrain-vsc/src/interactions.ts @@ -1,11 +1,13 @@ -import { window, Range, Position, workspace, TextEditor, OverviewRulerLane } from 'vscode' +import { window, Range, Position, workspace, TextEditor, OverviewRulerLane, TextEditorDecorationType } from 'vscode' export class Interactions { - private decorationType = window.createTextEditorDecorationType({ + private decorateType: TextEditorDecorationType | undefined; + getDecorationType = function () { + return window.createTextEditorDecorationType({ isWholeLine: true, overviewRulerColor: 'blue', - overviewRulerLane: OverviewRulerLane.Right, + overviewRulerLane: OverviewRulerLane.Right, light: { // this color will be used in light color themes backgroundColor: 'lightblue' @@ -15,14 +17,17 @@ export class Interactions { backgroundColor: 'darkblue' } }); + } highlightLineOnEditor(lineno: number, relativePath: string) { const nodeEditor = window.visibleTextEditors.filter( editor => editor.document.uri.fsPath.indexOf(relativePath) !== -1)[0] if (nodeEditor) { - let lineRange = [{ range: new Range(new Position(lineno, 0), new Position(lineno, 100)) }] - nodeEditor.setDecorations(this.decorationType, lineRange) + // create a decoration type everytime since it will be disposed when unhovering the node + this.decorateType = this.getDecorationType(); + let lineRange = [{ range: new Range(new Position(lineno - 1, 0), new Position(lineno - 1, 100)) }] + nodeEditor.setDecorations(this.decorateType, lineRange) } } @@ -32,6 +37,11 @@ export class Interactions { if (context.info?.hasOwnProperty("lineno")) this.highlightLineOnEditor(context.info["lineno"], context.info["relativePath"]); break; + case "Unhover": + if (this.decorateType) { + this.decorateType.dispose(); + } + break; default: break; } diff --git a/cyberbrain-vsc/src/trace_graph.js b/cyberbrain-vsc/src/trace_graph.js index 88dbc2ec..d3d74361 100644 --- a/cyberbrain-vsc/src/trace_graph.js +++ b/cyberbrain-vsc/src/trace_graph.js @@ -310,6 +310,14 @@ class TraceGraph { }); this.network.on("blurNode", event => { + // unhighlight the current hoverd node's line on the editor + vscode.postMessage({ + command: "Interaction behaivor", + context: { + interactionType: "Unhover", + } + }); + this.hoveredNodeId = undefined; }); From 040c4491f2ca050aec689ea3c67f3f01b9b5946e Mon Sep 17 00:00:00 2001 From: dingge2016 Date: Thu, 22 Apr 2021 15:09:38 -0700 Subject: [PATCH 5/6] Change the highlight color and deal with some reviews. --- cyberbrain-vsc/src/interactions.ts | 117 +++++++++++++++++++---------- cyberbrain-vsc/src/rpc_server.ts | 20 +++-- cyberbrain-vsc/src/trace_graph.js | 9 +-- 3 files changed, 93 insertions(+), 53 deletions(-) diff --git a/cyberbrain-vsc/src/interactions.ts b/cyberbrain-vsc/src/interactions.ts index 1d751942..c58e27bb 100644 --- a/cyberbrain-vsc/src/interactions.ts +++ b/cyberbrain-vsc/src/interactions.ts @@ -1,49 +1,86 @@ -import { window, Range, Position, workspace, TextEditor, OverviewRulerLane, TextEditorDecorationType } from 'vscode' +import { + window, + Range, + Position, + workspace, + TextEditor, + OverviewRulerLane, + TextEditorDecorationType +} from "vscode"; -export class Interactions { +enum Behaviors { + Hover = "Hover", + Unhover = "Unhover" +} - private decorateType: TextEditorDecorationType | undefined; - getDecorationType = function () { - return window.createTextEditorDecorationType({ - isWholeLine: true, - overviewRulerColor: 'blue', - overviewRulerLane: OverviewRulerLane.Right, - light: { - // this color will be used in light color themes - backgroundColor: 'lightblue' - }, - dark: { - // this color will be used in dark color themes - backgroundColor: 'darkblue' - } - }); - } +/** + * `Interactions` is used to realize and manage the interaction behaviors from users when they iteract with the cyberbrain webpage. + * To design a interation, post message to Vscode when a User's interaction behavior is detected, parse the message with rpc server, + * define relative interactions logic in the `Interactions`, and then call `Interactions.excute` to excute it. + * Current Interaction Behaviors includes: + * 1. Highlight the line of the node in the editor when hovering the mouse on any node. Cancel the highlight when the node is unhovered. + **/ +export class Interactions { + private decorateType: TextEditorDecorationType | undefined; - highlightLineOnEditor(lineno: number, relativePath: string) { + getDecorationType(): TextEditorDecorationType { + return window.createTextEditorDecorationType({ + isWholeLine: true, + overviewRulerLane: OverviewRulerLane.Right, + light: { + // this color will be used in light color themes + backgroundColor: "#fcf29f", + overviewRulerColor: "#fcf29f" + }, + dark: { + // this color will be used in dark color themes + backgroundColor: "#264F78", + overviewRulerColor: "#264F78" + } + }); + } - const nodeEditor = window.visibleTextEditors.filter( - editor => editor.document.uri.fsPath.indexOf(relativePath) !== -1)[0] - if (nodeEditor) { - // create a decoration type everytime since it will be disposed when unhovering the node - this.decorateType = this.getDecorationType(); - let lineRange = [{ range: new Range(new Position(lineno - 1, 0), new Position(lineno - 1, 100)) }] - nodeEditor.setDecorations(this.decorateType, lineRange) + /** + * Highlight the given line on the Editor + * @param lineno the highlighted line's number. + * @param relativePath the relative file path of the highlighted line + */ + highlightLineOnEditor(lineno: number, relativePath: string) { + const nodeEditor = window.visibleTextEditors.filter( + editor => editor.document.uri.fsPath.indexOf(relativePath) !== -1 + )[0]; + if (nodeEditor) { + // create a decoration type everytime since it will be disposed when unhovering the node + this.decorateType = this.getDecorationType(); + let lineRange = [ + { + range: new Range( + new Position(lineno - 1, 0), + new Position(lineno - 1, 100) + ) } + ]; + nodeEditor.setDecorations(this.decorateType, lineRange); } + } - execute(context: { interactionType: String, info?: any }) { - switch (context.interactionType) { - case "Hover": - if (context.info?.hasOwnProperty("lineno")) - this.highlightLineOnEditor(context.info["lineno"], context.info["relativePath"]); - break; - case "Unhover": - if (this.decorateType) { - this.decorateType.dispose(); - } - break; - default: - break; + execute(context: { interactionType: String; info?: any }) { + switch (context.interactionType) { + case Behaviors.Hover: + if (context.info?.hasOwnProperty("lineno")) { + this.highlightLineOnEditor( + context.info["lineno"], + context.info["relativePath"] + ); + } + break; + case Behaviors.Unhover: + if (this.decorateType) { + this.decorateType.dispose(); } + break; + default: + break; } -} \ No newline at end of file + } +} diff --git a/cyberbrain-vsc/src/rpc_server.ts b/cyberbrain-vsc/src/rpc_server.ts index c8e68b01..a3b2fde4 100644 --- a/cyberbrain-vsc/src/rpc_server.ts +++ b/cyberbrain-vsc/src/rpc_server.ts @@ -15,11 +15,8 @@ export class RpcServer { private server: express.Express; private readonly context: vscode.ExtensionContext; private readonly listeningPort = 1989; // TODO: Make it configurable. -<<<<<<< HEAD - -======= private interactions: Interactions; ->>>>>>> Add a message post for hovering nodes and implement the framework of relative interaction + constructor(context: vscode.ExtensionContext) { this.context = context; this.server = express(); @@ -34,7 +31,10 @@ export class RpcServer { // Sends data to the trace graph in webview. let webviewPanel = openTraceGraph(this.context); webviewPanel.webview.onDidReceiveMessage( - (message: { command: string, context?: { interactionType: string, info?: any } }) => { + (message: { + command: string; + context?: { interactionType: string; info?: any }; + }) => { if (message.command === "Webview ready") { webviewPanel.webview.postMessage(decode(req.body)); @@ -45,9 +45,13 @@ export class RpcServer { ); } } - if (message.command === "Interaction behaivor") { - if (message.context) { - this.interactions.execute(message.context); + if (message.command === "Interaction behavior") { + try { + if (message.context) { + this.interactions.execute(message.context); + } + } catch (error) { + cl("Failed to execute the interation behavior: ", error); } } }, diff --git a/cyberbrain-vsc/src/trace_graph.js b/cyberbrain-vsc/src/trace_graph.js index d3d74361..8b605d4d 100644 --- a/cyberbrain-vsc/src/trace_graph.js +++ b/cyberbrain-vsc/src/trace_graph.js @@ -296,9 +296,8 @@ class TraceGraph { this.hoveredNodeId = node.id; // highlight the current hoverd node's line on the editor - // TODO: post interaction behavior "UnHover" to cancel the highlight when unhovering the node vscode.postMessage({ - command: "Interaction behaivor", + command: "Interaction behavior", context: { interactionType: "Hover", info: { lineno: node.lineno, relativePath: node.filename } @@ -312,12 +311,12 @@ class TraceGraph { this.network.on("blurNode", event => { // unhighlight the current hoverd node's line on the editor vscode.postMessage({ - command: "Interaction behaivor", + command: "Interaction behavior", context: { - interactionType: "Unhover", + interactionType: "Unhover" } }); - + this.hoveredNodeId = undefined; }); From e026b1a6d819662182e9ee777631abe221c3be93 Mon Sep 17 00:00:00 2001 From: dingge2016 Date: Thu, 22 Apr 2021 16:15:12 -0700 Subject: [PATCH 6/6] rename `context` to avoid confusing and fix typo --- cyberbrain-vsc/src/interactions.ts | 24 ++++++++++++------------ cyberbrain-vsc/src/rpc_server.ts | 6 +++--- cyberbrain-vsc/src/trace_graph.js | 8 ++++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cyberbrain-vsc/src/interactions.ts b/cyberbrain-vsc/src/interactions.ts index c58e27bb..cc8d7243 100644 --- a/cyberbrain-vsc/src/interactions.ts +++ b/cyberbrain-vsc/src/interactions.ts @@ -8,14 +8,14 @@ import { TextEditorDecorationType } from "vscode"; -enum Behaviors { +enum Behavior { Hover = "Hover", Unhover = "Unhover" } /** - * `Interactions` is used to realize and manage the interaction behaviors from users when they iteract with the cyberbrain webpage. - * To design a interation, post message to Vscode when a User's interaction behavior is detected, parse the message with rpc server, + * `Interactions` is used to implement the interaction behaviors from users when they interact with cyberbrain webpages. + * To add an interation, post message to Vscode when a user's interaction behavior is detected, parse the message with rpc server, * define relative interactions logic in the `Interactions`, and then call `Interactions.excute` to excute it. * Current Interaction Behaviors includes: * 1. Highlight the line of the node in the editor when hovering the mouse on any node. Cancel the highlight when the node is unhovered. @@ -41,9 +41,9 @@ export class Interactions { } /** - * Highlight the given line on the Editor + * Highlight the given line on the Editor. * @param lineno the highlighted line's number. - * @param relativePath the relative file path of the highlighted line + * @param relativePath the relative path of the file which the highlighted line belongs to. */ highlightLineOnEditor(lineno: number, relativePath: string) { const nodeEditor = window.visibleTextEditors.filter( @@ -64,17 +64,17 @@ export class Interactions { } } - execute(context: { interactionType: String; info?: any }) { - switch (context.interactionType) { - case Behaviors.Hover: - if (context.info?.hasOwnProperty("lineno")) { + execute(interactionConfig: { type: String; info?: any }) { + switch (interactionConfig.type) { + case Behavior.Hover: + if (interactionConfig.info?.hasOwnProperty("lineno")) { this.highlightLineOnEditor( - context.info["lineno"], - context.info["relativePath"] + interactionConfig.info["lineno"], + interactionConfig.info["relativePath"] ); } break; - case Behaviors.Unhover: + case Behavior.Unhover: if (this.decorateType) { this.decorateType.dispose(); } diff --git a/cyberbrain-vsc/src/rpc_server.ts b/cyberbrain-vsc/src/rpc_server.ts index a3b2fde4..b19ee0f6 100644 --- a/cyberbrain-vsc/src/rpc_server.ts +++ b/cyberbrain-vsc/src/rpc_server.ts @@ -33,7 +33,7 @@ export class RpcServer { webviewPanel.webview.onDidReceiveMessage( (message: { command: string; - context?: { interactionType: string; info?: any }; + interactionConfig?: { type: string; info?: any }; }) => { if (message.command === "Webview ready") { webviewPanel.webview.postMessage(decode(req.body)); @@ -47,8 +47,8 @@ export class RpcServer { } if (message.command === "Interaction behavior") { try { - if (message.context) { - this.interactions.execute(message.context); + if (message.interactionConfig) { + this.interactions.execute(message.interactionConfig); } } catch (error) { cl("Failed to execute the interation behavior: ", error); diff --git a/cyberbrain-vsc/src/trace_graph.js b/cyberbrain-vsc/src/trace_graph.js index 8b605d4d..938e98c7 100644 --- a/cyberbrain-vsc/src/trace_graph.js +++ b/cyberbrain-vsc/src/trace_graph.js @@ -298,8 +298,8 @@ class TraceGraph { // highlight the current hoverd node's line on the editor vscode.postMessage({ command: "Interaction behavior", - context: { - interactionType: "Hover", + interactionConfig: { + type: "Hover", info: { lineno: node.lineno, relativePath: node.filename } } }); @@ -312,8 +312,8 @@ class TraceGraph { // unhighlight the current hoverd node's line on the editor vscode.postMessage({ command: "Interaction behavior", - context: { - interactionType: "Unhover" + interactionConfig: { + type: "Unhover" } });