diff --git a/package.json b/package.json index 2c449f0e..8da469c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@spcl/sdfv", - "version": "1.2.1", + "version": "1.2.2", "description": "A standalone viewer for SDFGs", "homepage": "https://github.com/spcl/dace-webclient", "main": "out/index.js", diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 1c4ff3a8..2fdefa9f 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -594,7 +594,8 @@ export class SDFGRenderer extends EventEmitter { }).appendTo(this.toolbar).append(overlayDropdown); const addOverlayToMenu = ( - txt: string, ol: typeof GenericSdfgOverlay, default_state: boolean + txt: string, ol: typeof GenericSdfgOverlay, + default_state: boolean ) => { const olItem = $('
  • ', { css: { @@ -626,8 +627,12 @@ export class SDFGRenderer extends EventEmitter { addOverlayToMenu('Logical groups', LogicalGroupOverlay, true); // Add overlays that are turned off by default. - addOverlayToMenu('Storage locations', MemoryLocationOverlay, false); - addOverlayToMenu('Logical data movement volume', MemoryVolumeOverlay, false); + addOverlayToMenu( + 'Storage locations', MemoryLocationOverlay, false + ); + addOverlayToMenu( + 'Logical data movement volume', MemoryVolumeOverlay, false + ); } // Zoom to fit. @@ -906,8 +911,8 @@ export class SDFGRenderer extends EventEmitter { this.updateCFGList(); // Create the initial SDFG layout - // Loading animation already started in the file_read_complete function in sdfv.ts - // to also include the JSON parsing step. + // Loading animation already started in the file_read_complete function + // in sdfv.ts to also include the JSON parsing step. this.relayout(); // Set mouse event handlers @@ -2680,7 +2685,6 @@ export class SDFGRenderer extends EventEmitter { // Toggles collapsed state of foreground_elem if applicable. // Returns true if re-layout occured and re-draw is necessary. public toggle_element_collapse(foreground_elem: any): boolean { - const sdfg = (foreground_elem ? foreground_elem.sdfg : null); let sdfg_elem = null; if (foreground_elem instanceof State) { @@ -2971,9 +2975,8 @@ export class SDFGRenderer extends EventEmitter { return false; } } else if (evtype === 'wheel') { - if (SDFVSettings.useVerticalScrollNavigation && !event.ctrlKey - || !SDFVSettings.useVerticalScrollNavigation && event.ctrlKey - ) { + if (SDFVSettings.useVerticalScrollNavigation && !event.ctrlKey || + !SDFVSettings.useVerticalScrollNavigation && event.ctrlKey) { // If vertical scroll navigation is turned on, use this to // move the viewport up and down. If the control key is held // down while scrolling, treat it as a typical zoom operation. @@ -3095,7 +3098,7 @@ export class SDFGRenderer extends EventEmitter { highlighting_changed = true; hover_changed = true; } - + // Highlight all edges of the memlet tree if (obj instanceof Edge && obj.parent_id !== null) { if (obj.hovered && hover_changed) { @@ -3152,37 +3155,55 @@ export class SDFGRenderer extends EventEmitter { } if (obj instanceof Connector) { - // Highlight the incoming/outgoing Edge const parent_node = obj.linkedElem; - if (obj.hovered && (hover_changed || (!parent_node?.hovered))) { + if (obj.hovered && + (hover_changed || (!parent_node?.hovered))) { const state = obj.linkedElem?.parentElem; - if (state && state instanceof State && state.data) { + if (state && state instanceof State && + state.data) { const state_json = state.data.state; const state_graph = state.data.graph; - state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { - if (edge.src_connector === obj.data.name || edge.dst_connector === obj.data.name) { - const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge) { - gedge.highlighted = true; + state_json.edges.forEach( + (edge: JsonSDFGEdge, id: number) => { + if (edge.src_connector === + obj.data.name || + edge.dst_connector === + obj.data.name) { + const gedge = state_graph.edge( + edge.src, edge.dst, + id.toString() + ) as Memlet; + if (gedge) + gedge.highlighted = true; } } - }); + ); } } if (!obj.hovered && hover_changed) { - // Prevent de-highlighting of edge if parent is already hovered (to show all edges) + // Prevent de-highlighting of edge if parent is + // already hovered (to show all edges). if (parent_node && !parent_node.hovered) { const state = obj.linkedElem?.parentElem; - if (state && state instanceof State && state.data) { + if (state && state instanceof State && + state.data) { const state_json = state.data.state; const state_graph = state.data.graph; - state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { - if (edge.src_connector === obj.data.name || edge.dst_connector === obj.data.name) { - const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge) { + state_json.edges.forEach(( + edge: JsonSDFGEdge, + id: number + ) => { + if (edge.src_connector === + obj.data.name || + edge.dst_connector === + obj.data.name) { + const gedge = state_graph.edge( + edge.src, edge.dst, + id.toString() + ) as Memlet; + if (gedge) gedge.highlighted = false; - } } }); } @@ -3190,8 +3211,8 @@ export class SDFGRenderer extends EventEmitter { } - // Highlight all access nodes with the same name as the - // hovered connector in the nested sdfg + // Highlight all access nodes with the same name as + // the hovered connector in the nested sdfg. if (obj.hovered && hover_changed) { const nGraph = obj.parentElem?.data.graph; if (nGraph) { @@ -3268,40 +3289,49 @@ export class SDFGRenderer extends EventEmitter { } } } - - // Make all edges of a node visible and remove the edge summary symbol + + // Make all edges of a node visible and remove the edge + // summary symbol. if (obj.hovered && hover_changed) { - // Setting these to false will cause the summary symbol - // not to be drawn in renderer_elements.ts + // Setting these to false will cause the summary + // symbol not to be drawn in renderer_elements.ts obj.summarize_in_edges = false; obj.summarize_out_edges = false; const state = obj.parentElem; if (state && state instanceof State && state.data) { const state_json = state.data.state; const state_graph = state.data.graph; - state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { - if (edge.src === obj.id.toString() || edge.dst === obj.id.toString()) { - const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge) { - gedge.highlighted = true; + state_json.edges.forEach( + (edge: JsonSDFGEdge, id: number) => { + if (edge.src === obj.id.toString() || + edge.dst === obj.id.toString()) { + const gedge = state_graph.edge( + edge.src, edge.dst, + id.toString() + ) as Memlet; + if (gedge) + gedge.highlighted = true; } } - }); + ); } - } - else if (!obj.hovered && hover_changed) { + } else if (!obj.hovered && hover_changed) { obj.summarize_in_edges = true; obj.summarize_out_edges = true; const state = obj.parentElem; if (state && state instanceof State && state.data) { const state_json = state.data.state; const state_graph = state.data.graph; - state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { - if (edge.src === obj.id.toString() || edge.dst === obj.id.toString()) { - const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge) { + state_json.edges.forEach(( + edge: JsonSDFGEdge, id: number + ) => { + if (edge.src === obj.id.toString() || + edge.dst === obj.id.toString()) { + const gedge = state_graph.edge( + edge.src, edge.dst, id.toString() + ) as Memlet; + if (gedge) gedge.highlighted = false; - } } }); } @@ -3328,7 +3358,9 @@ export class SDFGRenderer extends EventEmitter { } if (evtype === 'dblclick') { - const relayout_happened = this.toggle_element_collapse(foreground_elem); + const relayout_happened = this.toggle_element_collapse( + foreground_elem + ); if (relayout_happened) { dirty = true; element_focus_changed = true; @@ -3603,12 +3635,12 @@ export class SDFGRenderer extends EventEmitter { // Cancel add mode if (this.panmode_btn?.onclick) this.panmode_btn?.onclick(event); - } - else if (this.mouse_mode === 'pan') { - + } else if (this.mouse_mode === 'pan') { // Shift + Rightclick to toggle expand/collapse if (event.shiftKey) { - const relayout_happened = this.toggle_element_collapse(foreground_elem); + const relayout_happened = this.toggle_element_collapse( + foreground_elem + ); if (relayout_happened) { dirty = true; element_focus_changed = true; @@ -4516,7 +4548,6 @@ function relayoutSDFGState( } }); - // Re-order in_connectors for the edges to not intertwine state.nodes.forEach((node: JsonSDFGNode, id: number) => { const gnode: any = g.node(id.toString()); @@ -4524,56 +4555,62 @@ function relayoutSDFGState( // Ignore nodes that should not be drawn. return; } - - // Summarize edges for NestedSDFGs and ScopeNodes - if (gnode instanceof NestedSDFG || gnode instanceof ScopeNode) { - const n_of_in_connectors = gnode.in_connectors.length; - const n_of_out_connectors = gnode.out_connectors.length; - if (n_of_in_connectors > 10) { - gnode.summarize_in_edges = true; - gnode.in_summary_has_effect = true; - } - if (n_of_out_connectors > 10) { - gnode.summarize_out_edges = true; - gnode.out_summary_has_effect = true; + // Summarize edges for NestedSDFGs and ScopeNodes + if (SDFVSettings.summarizeLargeNumbersOfEdges) { + if (gnode instanceof NestedSDFG || gnode instanceof ScopeNode) { + const n_of_in_connectors = gnode.in_connectors.length; + const n_of_out_connectors = gnode.out_connectors.length; + + if (n_of_in_connectors > 10) { + gnode.summarize_in_edges = true; + gnode.in_summary_has_effect = true; + } + if (n_of_out_connectors > 10) { + gnode.summarize_out_edges = true; + gnode.out_summary_has_effect = true; + } } } - const SPACING = SDFV.LINEHEIGHT; const iConnLength = (SDFV.LINEHEIGHT + SPACING) * Object.keys( node.attributes.layout.in_connectors ).length - SPACING; let iConnX = gnode.x - iConnLength / 2.0 + SDFV.LINEHEIGHT / 2.0; - // Dictionary that saves the x coordinates of each connector's source node or source connector. - // This is later used to reorder the in_connectors based on the sources' x coordinates. - let sources_x_coordinates: { [key: string]: number } = {}; - - // For each in_connector, find the x coordinate of the source node connector + // Dictionary that saves the x coordinates of each connector's source + // node or source connector. This is later used to reorder the + // in_connectors based on the sources' x coordinates. + const sources_x_coordinates: { [key: string]: number } = {}; + + // For each in_connector, find the x coordinate of the source node + // connector. for (const c of gnode.in_connectors) { state.edges.forEach((edge: JsonSDFGEdge, id: number) => { - if (edge.dst === gnode.id.toString() && edge.dst_connector === c.data.name) { - + if (edge.dst === gnode.id.toString() && + edge.dst_connector === c.data.name) { // If in-edges are to be summarized, set Memlet.summarized - const gedge = g.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge && gnode.summarize_in_edges) { + const gedge = g.edge( + edge.src, edge.dst, id.toString() + ) as Memlet; + if (gedge && gnode.summarize_in_edges) gedge.summarized = true; - } const source_node: SDFGNode = g.node(edge.src); if (source_node) { - // If source node doesn't have out_connectors, take // the source node's own x coordinate if (source_node.out_connectors.length === 0) { sources_x_coordinates[c.data.name] = source_node.x; - } - else { - // Find the corresponding out_connector and take its x coordinate - for (let i = 0; i < source_node.out_connectors.length; ++i) { - if (source_node.out_connectors[i].data.name === edge.src_connector) { - sources_x_coordinates[c.data.name] = source_node.out_connectors[i].x; + } else { + // Find the corresponding out_connector and take its + // x coordinate. + const nOutConn = source_node.out_connectors.length; + for (let i = 0; i < nOutConn; ++i) { + if (source_node.out_connectors[i].data.name === + edge.src_connector) { + sources_x_coordinates[c.data.name] = + source_node.out_connectors[i].x; break; } } @@ -4581,14 +4618,16 @@ function relayoutSDFGState( } } }); - } - + // Sort the dictionary by x coordinate values - let sources_x_coordinates_sorted = Object.entries(sources_x_coordinates); + const sources_x_coordinates_sorted = Object.entries( + sources_x_coordinates + ); sources_x_coordinates_sorted.sort((a, b) => a[1] - b[1]); - // In the order of the sorted source x coordinates, set the x coordinates of the in_connectors + // In the order of the sorted source x coordinates, set the x + // coordinates of the in_connectors. for (const element of sources_x_coordinates_sorted) { for (const c of gnode.in_connectors) { if (c.data.name === element[0]) { @@ -4598,16 +4637,18 @@ function relayoutSDFGState( } } } - + // For out_connectors set Memlet.summarized for all out-edges if needed if (gnode.summarize_out_edges) { for (const c of gnode.out_connectors) { state.edges.forEach((edge: JsonSDFGEdge, id: number) => { - if (edge.src === gnode.id.toString() && edge.src_connector === c.data.name) { - const gedge = g.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge) { + if (edge.src === gnode.id.toString() && + edge.src_connector === c.data.name) { + const gedge = g.edge( + edge.src, edge.dst, id.toString() + ) as Memlet; + if (gedge) gedge.summarized = true; - } } }); } diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 1784eb44..b37909db 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -46,6 +46,71 @@ export enum SDFGElementType { LoopRegion = 'LoopRegion', } +function draw_summary_symbol( + ctx: CanvasRenderingContext2D, + min_connector_x: number, max_connector_x: number, + horizontal_line_level: number, draw_arrows_above_line: boolean +): void { + // Draw left arrow + const middle_of_line = (min_connector_x + max_connector_x) / 2; + const left_arrow_x = middle_of_line - 10; + const righ_arrow_x = middle_of_line + 10; + let arrow_start_y = horizontal_line_level + 2; + let arrow_end_y = horizontal_line_level + 8; + if (draw_arrows_above_line) { + arrow_start_y = horizontal_line_level - 10; + arrow_end_y = horizontal_line_level - 4; + } + const dot_height = (arrow_start_y + arrow_end_y) / 2; + // Arrow line + ctx.beginPath(); + ctx.moveTo(left_arrow_x, arrow_start_y); + ctx.lineTo(left_arrow_x, arrow_end_y); + ctx.closePath(); + ctx.stroke(); + // Arrow head + ctx.beginPath(); + ctx.moveTo(left_arrow_x, arrow_end_y + 2); + ctx.lineTo(left_arrow_x - 2, arrow_end_y); + ctx.lineTo(left_arrow_x + 2, arrow_end_y); + ctx.lineTo(left_arrow_x, arrow_end_y + 2); + ctx.closePath(); + ctx.fill(); + + // 3 dots + ctx.beginPath(); + ctx.moveTo(middle_of_line - 5, dot_height); + ctx.lineTo(middle_of_line - 4, dot_height); + ctx.closePath(); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(middle_of_line - 0.5, dot_height); + ctx.lineTo(middle_of_line + 0.5, dot_height); + ctx.closePath(); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(middle_of_line + 4, dot_height); + ctx.lineTo(middle_of_line + 5, dot_height); + ctx.closePath(); + ctx.stroke(); + + // Draw right arrow + // Arrow line + ctx.beginPath(); + ctx.moveTo(righ_arrow_x, arrow_start_y); + ctx.lineTo(righ_arrow_x, arrow_end_y); + ctx.closePath(); + ctx.stroke(); + // Arrow head + ctx.beginPath(); + ctx.moveTo(righ_arrow_x, arrow_end_y + 2); + ctx.lineTo(righ_arrow_x - 2, arrow_end_y); + ctx.lineTo(righ_arrow_x + 2, arrow_end_y); + ctx.lineTo(righ_arrow_x, arrow_end_y + 2); + ctx.closePath(); + ctx.fill(); +} + export class SDFGElement { public get COLLAPSIBLE(): boolean { @@ -59,17 +124,18 @@ export class SDFGElement { public selected: boolean = false; public highlighted: boolean = false; public hovered: boolean = false; - + // Used to draw edge summary instead of all edges separately. - // Helps with rendering performance when too many edges would be drawn on the screen. - // These two fields get set in the layouter, depending on the number of in/out_connectors - // of a node. They also get toggled in the mousehandler when the hover status changes. - // Currently only used for NestedSDFGs and ScopeNodes. + // Helps with rendering performance when too many edges would be drawn on + // the screen. These two fields get set in the layouter, depending on the + // number of in/out_connectors of a node. They also get toggled in the + // mousehandler when the hover status changes. Currently only used for + // NestedSDFGs and ScopeNodes. public summarize_in_edges: boolean = false; public summarize_out_edges: boolean = false; - // Used in draw_edge_summary to decide if edge summary is applicable. Set in the layouter - // only for NestedSDFGs and ScopeNodes. This prevents the summary to get toggled on - // by the mousehandler when it is not applicable. + // Used in draw_edge_summary to decide if edge summary is applicable. Set + // in the layouter only for NestedSDFGs and ScopeNodes. This prevents the + // summary to get toggled on by the mousehandler when it is not applicable. public in_summary_has_effect: boolean = false; public out_summary_has_effect: boolean = false; @@ -226,11 +292,10 @@ export class SDFGElement { ): string { return renderer.getCssProperty(propertyName); } - + public draw_edge_summary( renderer: SDFGRenderer, ctx: CanvasRenderingContext2D ): void { - // Only draw if close enough const canvas_manager = renderer.get_canvas_manager(); const ppp = canvas_manager?.points_per_pixel(); @@ -238,97 +303,24 @@ export class SDFGElement { const topleft = this.topleft(); ctx.strokeStyle = this.strokeStyle(renderer); ctx.fillStyle = ctx.strokeStyle; - - function draw_summary_symbol(ctx: CanvasRenderingContext2D, - min_connector_x: number, max_connector_x: number, - horizontal_line_level: number, draw_arrows_above_line: boolean - ): void { - - // Draw horizontal line (looks better without) - // ctx.beginPath(); - // ctx.moveTo(min_connector_x, horizontal_line_level); - // ctx.lineTo(max_connector_x, horizontal_line_level); - // ctx.closePath(); - // ctx.stroke(); - - // Draw left arrow - const middle_of_line = (min_connector_x + max_connector_x) / 2; - const left_arrow_x = middle_of_line - 10; - const righ_arrow_x = middle_of_line + 10; - let arrow_start_y = horizontal_line_level + 2; - let arrow_end_y = horizontal_line_level + 8; - if (draw_arrows_above_line) { - arrow_start_y = horizontal_line_level - 10; - arrow_end_y = horizontal_line_level - 4; - } - const dot_height = (arrow_start_y + arrow_end_y) / 2; - // Arrow line - ctx.beginPath(); - ctx.moveTo(left_arrow_x, arrow_start_y); - ctx.lineTo(left_arrow_x, arrow_end_y); - ctx.closePath(); - ctx.stroke(); - // Arrow head - ctx.beginPath(); - ctx.moveTo(left_arrow_x, arrow_end_y + 2); - ctx.lineTo(left_arrow_x - 2, arrow_end_y); - ctx.lineTo(left_arrow_x + 2, arrow_end_y); - ctx.lineTo(left_arrow_x, arrow_end_y + 2); - ctx.closePath(); - ctx.fill(); - - // 3 dots - ctx.beginPath(); - ctx.moveTo(middle_of_line - 5, dot_height) - ctx.lineTo(middle_of_line - 4, dot_height) - ctx.closePath(); - ctx.stroke(); - ctx.beginPath(); - ctx.moveTo(middle_of_line - 0.5, dot_height) - ctx.lineTo(middle_of_line + 0.5, dot_height) - ctx.closePath(); - ctx.stroke(); - ctx.beginPath(); - ctx.moveTo(middle_of_line + 4, dot_height) - ctx.lineTo(middle_of_line + 5, dot_height) - ctx.closePath(); - ctx.stroke(); - - // Draw right arrow - // Arrow line - ctx.beginPath(); - ctx.moveTo(righ_arrow_x, arrow_start_y); - ctx.lineTo(righ_arrow_x, arrow_end_y); - ctx.closePath(); - ctx.stroke(); - // Arrow head - ctx.beginPath(); - ctx.moveTo(righ_arrow_x, arrow_end_y + 2); - ctx.lineTo(righ_arrow_x - 2, arrow_end_y); - ctx.lineTo(righ_arrow_x + 2, arrow_end_y); - ctx.lineTo(righ_arrow_x, arrow_end_y + 2); - ctx.closePath(); - ctx.fill(); - } - + if (this.summarize_in_edges && this.in_summary_has_effect) { // Find the left most and right most connector coordinates if (this.in_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; let max_connector_x = Number.MIN_SAFE_INTEGER; this.in_connectors.forEach((c: Connector) => { - if (c.x < min_connector_x) { + if (c.x < min_connector_x) min_connector_x = c.x; - } - if (c.x > max_connector_x) { + if (c.x > max_connector_x) max_connector_x = c.x; - } }); // Draw the summary symbol above the node - draw_summary_symbol(ctx, - min_connector_x, max_connector_x, - topleft.y - 8, true); + draw_summary_symbol( + ctx, min_connector_x, max_connector_x, + topleft.y - 8, true + ); } } if (this.summarize_out_edges && this.out_summary_has_effect) { @@ -337,22 +329,22 @@ export class SDFGElement { let min_connector_x = Number.MAX_SAFE_INTEGER; let max_connector_x = Number.MIN_SAFE_INTEGER; this.out_connectors.forEach((c: Connector) => { - if (c.x < min_connector_x) { + if (c.x < min_connector_x) min_connector_x = c.x; - } - if (c.x > max_connector_x) { + if (c.x > max_connector_x) max_connector_x = c.x; - } }); - + // Draw the summary symbol below the node - draw_summary_symbol(ctx, - min_connector_x, max_connector_x, - topleft.y + this.height + 8, false); + draw_summary_symbol( + ctx, min_connector_x, max_connector_x, + topleft.y + this.height + 8, false + ); } } } } + } // SDFG as an element (to support properties) @@ -1254,7 +1246,7 @@ export abstract class Edge extends SDFGElement { } -export class Memlet extends Edge { +export class Memlet extends Edge { // Currently used for Memlets to decide if they need to be drawn or not. // Set in the layouter. @@ -1895,9 +1887,8 @@ export class ScopeNode extends SDFGNode { renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, _mousepos?: Point2D ): void { - this.draw_edge_summary(renderer, ctx); - + let draw_shape; if (this.data.node.attributes.is_collapsed) { draw_shape = () => { @@ -2484,9 +2475,8 @@ export class NestedSDFG extends SDFGNode { renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, mousepos?: Point2D ): void { - this.draw_edge_summary(renderer, ctx); - + if (this.data.node.attributes.is_collapsed) { const topleft = this.topleft(); drawOctagon(ctx, topleft, this.width, this.height); @@ -2752,9 +2742,8 @@ function batchedDrawEdges( if (edge.selected || edge.hovered || edge.highlighted) { deferredEdges.push(edge); return; - } - // Dont draw if Memlet is summarized - else if (edge instanceof Memlet && edge.summarized) { + } else if (edge instanceof Memlet && edge.summarized) { + // Don't draw if Memlet is summarized return; } @@ -2823,7 +2812,8 @@ export function drawStateContents( continue; // Simple draw for non-collapsed NestedSDFGs - if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + if (node instanceof NestedSDFG && + !node.data.node.attributes.is_collapsed) { const nodeppp = Math.sqrt(node.width * node.height) / ppp; if (lod && nodeppp < SDFV.STATE_LOD) { node.simple_draw(renderer, ctx, mousePos); diff --git a/src/utils/sdfv_settings.ts b/src/utils/sdfv_settings.ts index 5600a44b..e5f5695f 100644 --- a/src/utils/sdfv_settings.ts +++ b/src/utils/sdfv_settings.ts @@ -30,6 +30,7 @@ export class SDFVSettings { 'showStateNames': true, 'showMapSchedules': true, 'showDataDescriptorSizes': false, + 'summarizeLargeNumbersOfEdges': false, 'inclusiveRanges': false, 'useVerticalStateMachineLayout': false, 'useVerticalScrollNavigation': false, @@ -103,6 +104,12 @@ export class SDFVSettings { '(hides data container names)', 'showDataDescriptorSizes', true ); + this.addToggle( + root, + 'Hide / summarize edges for nodes where a large number of ' + + 'edges are connected', + 'summarizeLargeNumbersOfEdges', true + ); this.addToggle(root, 'Use inclusive ranges', 'inclusiveRanges', true); this.addToggle( root, 'Use vertical state machine layout', @@ -305,6 +312,12 @@ export class SDFVSettings { ] as boolean; } + public static get summarizeLargeNumbersOfEdges(): boolean { + return SDFVSettings.getInstance().settingsDict[ + 'summarizeLargeNumbersOfEdges' + ] as boolean; + } + public static get useVerticalStateMachineLayout(): boolean { return this.getInstance().settingsDict[ 'useVerticalStateMachineLayout'