@@ -24,10 +24,13 @@ import {
2424 SetDirtyStateAction ,
2525 SetMarkersAction ,
2626 SetModelAction ,
27+ StatusAction ,
2728 UpdateModelAction
2829} from '@eclipse-glsp/protocol' ;
30+ import { DebouncedFunc , debounce } from 'lodash' ;
2931
3032import { inject , injectable , optional } from 'inversify' ;
33+ import { ActionDispatcher } from '../../actions/action-dispatcher' ;
3134import { CommandStack } from '../../command/command-stack' ;
3235import { DiagramConfiguration , ServerLayoutKind } from '../../diagram/diagram-configuration' ;
3336import { LayoutEngine } from '../layout/layout-engine' ;
@@ -70,8 +73,14 @@ export class ModelSubmissionHandler {
7073 @optional ( )
7174 protected validator ?: ModelValidator ;
7275
76+ @inject ( ActionDispatcher )
77+ protected actionDispatcher : ActionDispatcher ;
78+
7379 protected requestModelAction ?: RequestModelAction ;
7480
81+ liveValidationDelay = 100 ;
82+ protected debouncedLiveValidation ?: DebouncedFunc < ( validator : ModelValidator ) => void > ;
83+
7584 /**
7685 * Returns a list of actions to submit the initial revision of the client-side model, based on the injected
7786 * {@link ModelState}. Typically this method is invoked by the {@link RequestModelActionHandler} when the diagram
@@ -149,12 +158,33 @@ export class ModelSubmissionHandler {
149158 result . push ( SetDirtyStateAction . create ( this . commandStack . isDirty , { reason } ) ) ;
150159 }
151160 if ( this . validator ) {
152- const markers = await this . validator . validate ( [ this . modelState . root ] , MarkersReason . LIVE ) ;
153- result . push ( SetMarkersAction . create ( markers , { reason : MarkersReason . LIVE } ) ) ;
161+ const validationActions = await this . validateModel ( this . validator ) ;
162+ result . push ( ... validationActions ) ;
154163 }
155164 return result ;
156165 }
157166
167+ protected validateModel ( validator : ModelValidator ) : MaybePromise < Action [ ] > {
168+ this . scheduleLiveValidation ( validator ) ;
169+ // we are using async, debounced live validation so there are no actions to return for the model submission
170+ return [ ] ;
171+ }
172+
173+ protected scheduleLiveValidation ( validator : ModelValidator ) : void {
174+ this . debouncedLiveValidation ?. cancel ( ) ;
175+ this . debouncedLiveValidation = debounce ( validator => this . performLiveValidation ( validator ) , this . liveValidationDelay ) ;
176+ this . debouncedLiveValidation ( validator ) ;
177+ }
178+
179+ protected async performLiveValidation ( validator : ModelValidator ) : Promise < void > {
180+ this . actionDispatcher . dispatch ( StatusAction . create ( 'Validate Model...' ) ) ;
181+ const markers = await validator . validate ( [ this . modelState . root ] , MarkersReason . LIVE ) ;
182+ return this . actionDispatcher . dispatchAll (
183+ SetMarkersAction . create ( markers , { reason : MarkersReason . LIVE } ) ,
184+ StatusAction . create ( '' , { severity : 'NONE' } )
185+ ) ;
186+ }
187+
158188 protected createSetModeAction ( newRoot : GModelRootSchema ) : SetModelAction {
159189 const responseId = this . requestModelAction ?. requestId ?? '' ;
160190 const response = SetModelAction . create ( newRoot , { responseId } ) ;
0 commit comments