diff --git a/scripts/interface/Interface.js b/scripts/interface/Interface.js index be87d4c..84abbe3 100644 --- a/scripts/interface/Interface.js +++ b/scripts/interface/Interface.js @@ -165,6 +165,11 @@ define([ registerListeners() { this.code.on('change', () => this.update(false)); + this.code.on('cursorActivity', () => { + const from = this.code.getCursor('from').line; + const to = this.code.getCursor('to').line; + this.renderer.setHighlight(Math.min(from, to)); + }); this.renderer.addEventListener('mouseover', (element) => { if(this.marker) { diff --git a/scripts/sequence/Renderer.js b/scripts/sequence/Renderer.js index d624e74..cd34955 100644 --- a/scripts/sequence/Renderer.js +++ b/scripts/sequence/Renderer.js @@ -129,6 +129,8 @@ define([ this.components = components; this.SVGTextBlockClass = SVGTextBlockClass; this.knownDefs = new Set(); + this.highlights = new Map(); + this.currentHighlight = -1; this.buildStaticElements(); this.components.forEach((component) => { component.makeState(this.state); @@ -406,6 +408,15 @@ define([ this.markAgentRange([left, right], this.currentY); } + addHighlightObject(line, o) { + let list = this.highlights.get(line); + if(!list) { + list = []; + this.highlights.set(line, list); + } + list.push(o); + } + renderStages(stages) { this.agentInfos.forEach((agentInfo) => { const rad = agentInfo.currentRad; @@ -477,6 +488,8 @@ define([ if(!o) { o = svg.make('g'); } + this.addHighlightObject(stage.ln, o); + o.setAttribute('class', 'region'); o.addEventListener('mouseenter', eventOver); o.addEventListener('mouseleave', eventOut); o.addEventListener('click', eventClick); @@ -585,6 +598,8 @@ define([ _reset() { this.knownDefs.clear(); + this.highlights.clear(); + this.currentHighlight = -1; svg.empty(this.defs); svg.empty(this.mask); svg.empty(this.agentLines); @@ -599,7 +614,28 @@ define([ }); } + setHighlight(line = null) { + if(line === null || !this.highlights.has(line)) { + line = -1; + } + if(this.currentHighlight === line) { + return; + } + if(this.currentHighlight !== -1) { + this.highlights.get(this.currentHighlight).forEach((o) => { + o.setAttribute('class', 'region'); + }); + } + if(line !== -1) { + this.highlights.get(line).forEach((o) => { + o.setAttribute('class', 'region focus'); + }); + } + this.currentHighlight = line; + } + render(sequence) { + const prevHighlight = this.currentHighlight; this._reset(); const themeName = sequence.meta.theme; @@ -626,6 +662,7 @@ define([ this.sizer.resetCache(); this.sizer.detach(); + this.setHighlight(prevHighlight); } getThemeNames() { diff --git a/scripts/sequence/components/Connect.js b/scripts/sequence/components/Connect.js index a6c7639..dd45fd6 100644 --- a/scripts/sequence/components/Connect.js +++ b/scripts/sequence/components/Connect.js @@ -142,11 +142,11 @@ define([ const lArrow = ARROWHEADS[options.left]; const rArrow = ARROWHEADS[options.right]; - const height = ( + const height = label ? ( env.textSizer.measureHeight(config.label.attrs, label) + config.label.margin.top + config.label.margin.bottom - ); + ) : 0; const lineX = from.x + from.currentMaxRad; const y0 = env.primaryY; @@ -193,13 +193,14 @@ define([ lArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y0, dir: 1}); rArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y1, dir: 1}); + const raise = Math.max(height, lArrow.height(env.theme) / 2); const arrowDip = rArrow.height(env.theme) / 2; clickable.insertBefore(svg.make('rect', { 'x': lineX, - 'y': y0 - height, + 'y': y0 - raise, 'width': x1 + r - lineX, - 'height': height + r * 2 + arrowDip, + 'height': raise + r * 2 + arrowDip, 'fill': 'transparent', }), clickable.firstChild); @@ -250,20 +251,20 @@ define([ lArrow.render(env.shapeLayer, env.theme, {x: x0, y, dir}); rArrow.render(env.shapeLayer, env.theme, {x: x1, y, dir: -dir}); - const arrowDip = Math.max( + const arrowSpread = Math.max( lArrow.height(env.theme), rArrow.height(env.theme) ) / 2; clickable.insertBefore(svg.make('rect', { 'x': Math.min(x0, x1), - 'y': y - height, + 'y': y - Math.max(height, arrowSpread), 'width': Math.abs(x1 - x0), - 'height': height + arrowDip, + 'height': Math.max(height, arrowSpread) + arrowSpread, 'fill': 'transparent', }), clickable.firstChild); - return y + arrowDip + env.theme.actionMargin; + return y + arrowSpread + env.theme.actionMargin; } renderPre({label, agentNames, options}, env) { diff --git a/styles/main.css b/styles/main.css index 179b6f3..d175f44 100644 --- a/styles/main.css +++ b/styles/main.css @@ -71,6 +71,21 @@ html, body { height: 100%; } +.pane-view .region:hover rect { + stroke-width: 5px; + stroke: rgba(255, 255, 0, 0.5); +} + +.pane-view .region.focus rect { + stroke-width: 5px; + stroke: rgba(255, 128, 0, 0.5); +} + +.pane-view .region.focus:hover rect { + stroke-width: 5px; + stroke: rgba(255, 192, 0, 0.5); +} + .pane-library { position: absolute; left: 0;