@@ -33,6 +33,7 @@ import {
3333 getProcessPath ,
3434 createPowerSystemRelationPrivate ,
3535 getSldSvgs ,
36+ eTr6100Ns ,
3637} from './util.js' ;
3738import { FunctionsLayer } from './components/functions-layer/functions-layer.js' ;
3839import { CreateFunctionDialog } from './components/create-function-dialog/create-function-dialog.js' ;
@@ -100,6 +101,12 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
100101 @state ( )
101102 highlight : { id : string ; style : HighlightStyle } [ ] = [ ] ;
102103
104+ @state ( )
105+ functionHoverHighlight : { id : string ; style : HighlightStyle } [ ] = [ ] ;
106+
107+ @state ( )
108+ private hoveredSubstation ?: Element ;
109+
103110 @state ( )
104111 selectedElement ?: Element ;
105112
@@ -139,6 +146,9 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
139146 private handleKeydown = ( event : KeyboardEvent ) => {
140147 if ( event . key === 'Escape' && this . inAction ) {
141148 event . preventDefault ( ) ;
149+ if ( this . addingFunction ) {
150+ this . showFunctions = false ;
151+ }
142152 this . reset ( ) ;
143153 }
144154 } ;
@@ -149,6 +159,63 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
149159 this . functionsInAction = true ;
150160 } ;
151161
162+ handleFunctionHover = ( funcElement : Element | null ) => {
163+ if ( ! funcElement ) {
164+ this . functionHoverHighlight = [ ] ;
165+ this . hoveredSubstation = undefined ;
166+ return ;
167+ }
168+
169+ // If the Function has a PowerSystemRelation Private, resolve the referenced
170+ // element and highlight that instead of the DOM parent.
171+ const psrRelationEl = funcElement . getElementsByTagNameNS (
172+ eTr6100Ns ,
173+ 'PowerSystemRelation'
174+ ) [ 0 ] ;
175+ const relation = psrRelationEl ?. getAttribute ( 'relation' ) ;
176+ const target = relation
177+ ? this . getElementFromProcessPath ( relation )
178+ : funcElement . parentElement ;
179+
180+ if ( ! target ) {
181+ this . functionHoverHighlight = [ ] ;
182+ this . hoveredSubstation = undefined ;
183+ return ;
184+ }
185+
186+ if ( target . tagName === 'Substation' ) {
187+ this . functionHoverHighlight = [ ] ;
188+ this . hoveredSubstation = target ;
189+ return ;
190+ }
191+
192+ this . hoveredSubstation = undefined ;
193+ this . functionHoverHighlight = [
194+ {
195+ id : identity ( target ) . toString ( ) ,
196+ style : SELECTED_PSR_HIGHLIGHT_STYLE ,
197+ } ,
198+ ] ;
199+ } ;
200+
201+ private getElementFromProcessPath ( path : string ) : Element | null {
202+ if ( ! this . doc ) return null ;
203+ const parts = path . split ( '/' ) ;
204+ if ( ! parts . length || ! parts [ 0 ] ) return null ;
205+
206+ let current : Element | null = this . doc . querySelector (
207+ `:root > Substation[name="${ parts [ 0 ] } "]`
208+ ) ;
209+ for ( let i = 1 ; i < parts . length && current ; i += 1 ) {
210+ const name = parts [ i ] ;
211+ current =
212+ Array . from ( current . children ) . find (
213+ child => child . getAttribute ( 'name' ) === name
214+ ) ?? null ;
215+ }
216+ return current ;
217+ }
218+
152219 get inAction ( ) : boolean {
153220 return (
154221 this . sldEditorInAction || this . functionsInAction || this . addingFunction
@@ -517,33 +584,53 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
517584 }
518585
519586 private renderSubstationHighlight ( ) {
520- if ( ! this . addingFunction || ! this . doc ) return nothing ;
587+ if ( ! this . doc ) return nothing ;
521588 const substations = Array . from (
522589 this . doc . querySelectorAll ( ':root > Substation' )
523590 ) ;
524591 if ( ! substations . length ) return nothing ;
525- return substations . map ( ( substation , i ) => {
592+
593+ const result = [ ] ;
594+
595+ if ( this . addingFunction ) {
596+ result . push (
597+ ...substations . map ( ( substation , i ) => {
598+ const b = this . sldBounds [ i ] ;
599+ const style = b
600+ ? `top:${ b . top } px;left:${ b . left } px;width:${ b . width } px;height:${ b . height } px`
601+ : 'inset:0' ;
602+ return html `
603+ <div class= "substation-highlight" style = "${ style } ">
604+ <butto n
605+ class= "substation-chip"
606+ title = "Select Substation ${ substation . getAttribute ( 'name' ) } "
607+ @click = ${ ( ) =>
608+ this . handleSldSelected (
609+ new CustomEvent ( 'oscd-sld-selected' , {
610+ detail : { element : substation } ,
611+ } )
612+ ) }
613+ >
614+ ${ substation . getAttribute ( 'name' ) }
615+ </ butto n>
616+ </ div>
617+ ` ;
618+ } )
619+ ) ;
620+ }
621+
622+ if ( this . hoveredSubstation ) {
623+ const i = substations . indexOf ( this . hoveredSubstation ) ;
526624 const b = this . sldBounds [ i ] ;
527625 const style = b
528- ? `top:${ b . top } px;left:${ b . left } px;width:${ b . width } px;height:${ b . height } px`
626+ ? `top:${ b . top } px;left:${ b . left } px;width:${ b . width } px;height:${ b . height } px;z-index:1;background:rgba(210,185,236,0.5); `
529627 : 'inset:0' ;
530- return html `
531- <div class= "substation-highlight" style = "${ style } ">
532- <butto n
533- class= "substation-chip"
534- title = "Select Substation ${ substation . getAttribute ( 'name' ) } "
535- @click = ${ ( ) =>
536- this . handleSldSelected (
537- new CustomEvent ( 'oscd-sld-selected' , {
538- detail : { element : substation } ,
539- } )
540- ) }
541- >
542- ${ substation . getAttribute ( 'name' ) }
543- </ butto n>
544- </ div>
545- ` ;
546- } ) ;
628+ result . push (
629+ html `<div class= "substation-highlight" style = "${ style } "> </ div> `
630+ ) ;
631+ }
632+
633+ return result ;
547634 }
548635
549636 private renderFunctionButtons ( ) {
@@ -578,6 +665,7 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
578665 style : PSR_HIGHLIGHT_STYLE ,
579666 } ) ) ;
580667 this . addingFunction = true ;
668+ this . showFunctions = true ;
581669 } }
582670 >
583671 ${ functionAddIcon }
@@ -614,7 +702,12 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
614702 ? html `<oscd- icon- butto n
615703 label= "Cancel"
616704 title = "Cancel"
617- @click = ${ ( ) => this . reset ( ) }
705+ @click = ${ ( ) => {
706+ if ( this . addingFunction ) {
707+ this . showFunctions = false ;
708+ }
709+ this . reset ( ) ;
710+ } }
618711 >
619712 <oscd- icon> close </ oscd- icon>
620713 </ oscd- icon- butto n> `
@@ -699,14 +792,13 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
699792 > ${ this . renderTransformerButtons ( ) } ${ this . renderFunctionButtons ( ) }
700793 </ nav>
701794 <div class= "editor-container" >
702- ${ this . renderSubstationHighlight ( ) }
703795 <sld- edito r
704796 .doc = ${ this . doc }
705797 .docVersion = ${ this . editCount }
706798 .gridSize = ${ this . gridSize }
707799 .showLabels = ${ this . showLabels }
708800 .disabled = ${ this . addingFunction || this . showFunctions }
709- .highlight = ${ this . highlight }
801+ .highlight = ${ [ ... this . highlight , ... this . functionHoverHighlight ] }
710802 .selectable = ${ this . addingFunction
711803 ? this . highlight . map ( h => h . id )
712804 : [ ] }
@@ -715,6 +807,7 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
715807 } }
716808 @oscd-sld-selected = ${ this . handleSldSelected }
717809 > </ sld- edito r>
810+ ${ this . renderSubstationHighlight ( ) }
718811 ${ this . showFunctions
719812 ? Array . from ( this . doc . querySelectorAll ( ':root > Substation' ) ) . map (
720813 substation => html `<functions- layer
@@ -726,6 +819,7 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
726819 .placing = ${ this . placingFunction }
727820 .placingOffset = ${ this . placingFunctionOffset }
728821 .onStartPlaceFunction = ${ this . handleStartPlaceFunction }
822+ .onHoverFunction = ${ this . handleFunctionHover }
729823 > </ functions- layer> `
730824 )
731825 : nothing }
@@ -767,7 +861,7 @@ export default class BayTemplatePlugin extends ScopedElementsMixin(LitElement) {
767861 display : flex;
768862 gap : 4px ;
769863 flex-wrap : wrap;
770- z-index : 2 ;
864+ z-index : 3 ;
771865 }
772866 # bay-button {
773867 --md-filled-icon-button-container-color : # 12579b ;
0 commit comments