diff --git a/scss/color_schemes/default.scss b/scss/color_schemes/default.scss new file mode 100644 index 00000000..4544831e --- /dev/null +++ b/scss/color_schemes/default.scss @@ -0,0 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +$sdfv-diff-added: rgba(93, 186, 76, 0.5); +$sdfv-diff-removed: rgba(255, 109, 69, 0.5); +$sdfv-diff-changed: rgba(255, 204, 84, 0.5); diff --git a/scss/sdfv.scss b/scss/sdfv.scss index 777aed18..806ecb0d 100644 --- a/scss/sdfv.scss +++ b/scss/sdfv.scss @@ -8,6 +8,8 @@ $material-symbols-font-path: "~material-symbols/"; @import "~material-symbols"; +@import "./color_schemes/default"; + .sdfv { @import "~bootstrap/scss/bootstrap"; } @@ -245,26 +247,26 @@ body.sdfv { color: rgba(20, 20, 20, 1.0); &.removed { - background-color: rgba(255, 109, 69, 0.5); + background-color: $sdfv-diff-removed; &:hover { - background-color: darken(rgba(212, 92, 59, 0.5), 5%); + background-color: darken($sdfv-diff-removed, 5%); } } &.added { - background-color: rgba(93, 186, 76, 0.5); + background-color: $sdfv-diff-added; &:hover { - background-color: darken(rgba(93, 186, 76, 0.8), 5%); + background-color: darken($sdfv-diff-added, 5%); } } &.changed { - background-color: rgba(255, 204, 84, 0.5); + background-color: $sdfv-diff-changed; &:hover { - background-color: darken(rgba(255, 192, 43, 0.5), 5%); + background-color: darken($sdfv-diff-changed, 5%); } } @@ -400,6 +402,10 @@ body.sdfv { --local-view-edge-overlay-width: 10; --local-view-edge-overlay-arrowhead-length: 30; --local-view-edge-overlay-fontsize: 20; + + --color-diff-added: #{$sdfv-diff-added}; + --color-diff-removed: #{$sdfv-diff-removed}; + --color-diff-changed: #{$sdfv-diff-changed}; } #access-pattern-button-box .button { diff --git a/src/index.ts b/src/index.ts index 17fba632..9f9fa8fe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,6 +27,7 @@ export * from './utils/sanitization'; export * from './utils/utils'; export * from './overlay_manager'; export * from './sdfv'; +export * from './sdfv_ui'; export type SymbolMap = { [symbol: string]: number | undefined, diff --git a/src/overlays/diff_overlay.ts b/src/overlays/diff_overlay.ts index d78957a9..e91b2027 100644 --- a/src/overlays/diff_overlay.ts +++ b/src/overlays/diff_overlay.ts @@ -19,7 +19,7 @@ import { SDFGElementType, Edge, } from '../renderer/renderer_elements'; -import { DiffMap } from '../sdfg_diff_viewr'; +import { DiffMap } from '../sdfg_diff_viewer'; import { GenericSdfgOverlay, OverlayType } from './generic_sdfg_overlay'; export class DiffOverlay extends GenericSdfgOverlay { @@ -47,12 +47,19 @@ export class DiffOverlay extends GenericSdfgOverlay { public shadeElem( elem: Edge | SDFGNode, ctx: CanvasRenderingContext2D ): void { - if (this.diffMap?.addedKeys.has(elem.attributes().guid)) - elem.shade(this.renderer, ctx, this.ADDED_COLOR); - else if (this.diffMap?.removedKeys.has(elem.attributes().guid)) - elem.shade(this.renderer, ctx, this.REMOVED_COLOR); - else if (this.diffMap?.changedKeys.has(elem.attributes().guid)) - elem.shade(this.renderer, ctx, this.CHANGED_COLOR); + if (this.diffMap?.addedKeys.has(elem.guid())) { + elem.shade(this.renderer, ctx, this.renderer.getCssProperty( + '--color-diff-added' + ), 1); + } else if (this.diffMap?.removedKeys.has(elem.guid())) { + elem.shade(this.renderer, ctx, this.renderer.getCssProperty( + '--color-diff-removed' + ), 1); + } else if (this.diffMap?.changedKeys.has(elem.guid())) { + elem.shade(this.renderer, ctx, this.renderer.getCssProperty( + '--color-diff-changed' + ), 1); + } } public recursivelyShadeCFG( diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index cca8afa8..b5575dab 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -209,8 +209,10 @@ export class SDFGElement { } public guid(): string { + if (this.attributes().guid) + return this.attributes().guid; // If GUID does not exist, fall back to element ID - return this.cfg?.cfg_list_id + '/' + ( + return (this.cfg?.cfg_list_id ?? 0) + '/' + ( this.parent_id ?? -1) + '/' + this.id; } diff --git a/src/sdfg_diff_viewr.ts b/src/sdfg_diff_viewer.ts similarity index 97% rename from src/sdfg_diff_viewr.ts rename to src/sdfg_diff_viewer.ts index 1d9c2604..cb57dc14 100644 --- a/src/sdfg_diff_viewr.ts +++ b/src/sdfg_diff_viewer.ts @@ -180,25 +180,25 @@ export abstract class SDFGDiffViewer implements ISDFV { const addedIDs: Map = new Map(); const mergedResults: string[] = []; for (const res of lResults) { - const existing = addedIDs.get(res.attributes().guid); + const existing = addedIDs.get(res.guid()); if (existing) { existing.push([res, this.leftRenderer]); } else { const newEntry: [any, SDFGRenderer][] = [[res, this.leftRenderer]]; - addedIDs.set(res.attributes().guid, newEntry); - mergedResults.push(res.attributes().guid); + addedIDs.set(res.guid(), newEntry); + mergedResults.push(res.guid()); } } for (const res of rResults) { - const existing = addedIDs.get(res.attributes().guid); + const existing = addedIDs.get(res.guid()); if (existing) { existing.push([res, this.rightRenderer]); } else { const newEntry: [any, SDFGRenderer][] = [[res, this.rightRenderer]]; - addedIDs.set(res.attributes().guid, newEntry); - mergedResults.push(res.attributes().guid); + addedIDs.set(res.guid(), newEntry); + mergedResults.push(res.guid()); } } @@ -212,7 +212,7 @@ export abstract class SDFGDiffViewer implements ISDFV { continue; let status: ChangeState = 'nodiff'; - const guid = res[0][0].attributes().guid; + const guid = res[0][0].guid(); if (this.diffMap?.changedKeys.has(guid)) status = 'changed'; else if (this.diffMap?.removedKeys.has(guid)) @@ -392,6 +392,8 @@ export class WebSDFGDiffViewer extends SDFGDiffViewer { rendererSelectionChange(rightRenderer); }); + console.log(leftRenderer.get_graph()); + console.log(rightRenderer.get_graph()); SDFGDiffViewer.diff(graphA, graphB).then(diff => { viewer.diffMap = diff; const leftOverlay = new DiffOverlay(leftRenderer, diff); @@ -412,7 +414,7 @@ export class WebSDFGDiffViewer extends SDFGDiffViewer { ): (localGraphDiffStackEntry | null)[] { const elemClass = (elem: SDFGElement | JsonSDFG): ChangeState => { const guid = elem instanceof SDFGElement ? - elem.attributes().guid : elem.attributes.guid; + elem.guid() : elem.attributes.guid; if (this.diffMap?.addedKeys.has(guid)) return 'added'; else if (this.diffMap?.removedKeys.has(guid)) @@ -456,7 +458,7 @@ export class WebSDFGDiffViewer extends SDFGDiffViewer { // Create element const elemEntry = { - guid: node.attributes().guid, + guid: node.guid(), htmlLabel: htmlSanitize` ${node_type} ${node.label()}${is_collapsed ? ' (collapsed)' : ''} `, diff --git a/src/sdfv.ts b/src/sdfv.ts index e84e312d..8e4858ce 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -12,7 +12,6 @@ import { GenericSdfgOverlay, JsonSDFG, ModeButtons, - sdfg_property_to_string, showErrorModal, traverseSDFGScopes, } from './index'; @@ -23,7 +22,7 @@ import { import { OverlayManager } from './overlay_manager'; import { SDFGRenderer } from './renderer/renderer'; import { - AccessNode, Edge, Memlet, NestedSDFG, SDFG, + SDFG, SDFGElement, SDFGNode, } from './renderer/renderer_elements'; @@ -34,245 +33,11 @@ import { stringify_sdfg, } from './utils/sdfg/json_serializer'; import { SDFVSettings } from './utils/sdfv_settings'; -import { WebSDFGDiffViewer } from './sdfg_diff_viewr'; +import { WebSDFGDiffViewer } from './sdfg_diff_viewer'; +import { ISDFVUserInterface, SDFVWebUI } from './sdfv_ui'; declare const vscode: any; -export interface ISDFVUserInterface { - get infoContentContainer(): JQuery; - init(): void; - infoClear(): void; - infoShow(): void; - infoSetTitle(title: string): void; - disableInfoClear(): void; - enableInfoClear(): void; - showElementInfo( - elem: SDFGElement | DagreGraph | null, renderer: SDFGRenderer - ): void; -} - -export class SDFVWebUI implements ISDFVUserInterface { - - private static readonly INSTANCE: SDFVWebUI = new SDFVWebUI(); - - private constructor() { - } - - public static getInstance(): SDFVWebUI { - return this.INSTANCE; - } - - public get infoContentContainer(): JQuery { - return $('#sidebar-contents'); - } - - private initInfo(): void { - const right = document.getElementById('sidebar'); - const bar = document.getElementById('dragbar'); - - const drag = (e: MouseEvent) => { - if ((document as any).selection) - (document as any).selection.empty(); - else - window.getSelection()?.removeAllRanges(); - - if (right) { - right.style.width = Math.max( - ((e.view ? e.view.innerWidth - e.pageX : 0)), 20 - ) + 'px'; - } - }; - - if (bar) { - bar.addEventListener('mousedown', () => { - document.addEventListener('mousemove', drag); - document.addEventListener('mouseup', () => { - document.removeEventListener('mousemove', drag); - }); - }); - } - } - - public init(): void { - $(document).on( - 'click.sdfv-webui', '#menuclose', this.infoClear.bind(this) - ); - - this.initInfo(); - - // Set up any external interaction mode buttons that may override the - // renderer. - const pan_btn = document.getElementById('pan-btn'); - const move_btn = document.getElementById('move-btn'); - const select_btn = document.getElementById('select-btn'); - const add_btns: HTMLElement[] = []; - add_btns.push(document.getElementById('elem_map')!); - add_btns.push(document.getElementById('elem_consume')!); - add_btns.push(document.getElementById('elem_tasklet')!); - add_btns.push(document.getElementById('elem_nested_sdfg')!); - add_btns.push(document.getElementById('elem_access_node')!); - add_btns.push(document.getElementById('elem_stream')!); - add_btns.push(document.getElementById('elem_state')!); - if (pan_btn) { - WebSDFV.getInstance().setModeButtons({ - pan: pan_btn, - move: move_btn, - select: select_btn, - add_btns: add_btns, - }); - } - } - - public infoClear(): void { - this.infoContentContainer.html(''); - $('#sidebar').css('display', 'none'); - } - - public infoShow(): void { - // Open sidebar if closed - $('#sidebar').css('display', 'flex'); - } - - public infoSetTitle(title: string): void { - $('#sidebar-header')?.text(title); - } - - public disableInfoClear(): void { - $('#menuclose').hide(); - } - - public enableInfoClear(): void { - $('#menuclose').show(); - } - - public showElementInfo( - elem: SDFGElement | DagreGraph | null, renderer: SDFGRenderer - ): void { - const contentsRaw = SDFVWebUI.getInstance().infoContentContainer; - if (!contentsRaw || !elem || !(elem instanceof SDFGElement)) - return; - this.infoSetTitle(elem.type() + ' ' + elem.label()); - - const contents = $(contentsRaw); - contents.html(''); - - if (elem instanceof Memlet) { - contents.append($('

', { - html: 'Connectors: ' + elem.src_connector + ' → ' + - elem.dst_connector, - })); - } - contents.append($('


')); - - if (elem instanceof Edge) { - const btnContainer = $('
', { - class: 'd-flex', - }); - btnContainer.append($('