99import type { Block } from '../core/block.js' ;
1010import type { BlockSvg } from '../core/block_svg.js' ;
1111import type { BlockDefinition } from '../core/blocks.js' ;
12- import * as common from '../core/common.js' ;
1312import { defineBlocks } from '../core/common.js' ;
1413import { config } from '../core/config.js' ;
1514import type { Connection } from '../core/connection.js' ;
@@ -27,15 +26,19 @@ import {FieldCheckbox} from '../core/field_checkbox.js';
2726import { FieldLabel } from '../core/field_label.js' ;
2827import * as fieldRegistry from '../core/field_registry.js' ;
2928import { FieldTextInput } from '../core/field_textinput.js' ;
29+ import { getFocusManager } from '../core/focus_manager.js' ;
3030import '../core/icons/comment_icon.js' ;
3131import { MutatorIcon as Mutator } from '../core/icons/mutator_icon.js' ;
3232import '../core/icons/warning_icon.js' ;
3333import { Align } from '../core/inputs/align.js' ;
34+ import type {
35+ IVariableModel ,
36+ IVariableState ,
37+ } from '../core/interfaces/i_variable_model.js' ;
3438import { Msg } from '../core/msg.js' ;
3539import { Names } from '../core/names.js' ;
3640import * as Procedures from '../core/procedures.js' ;
3741import * as xmlUtils from '../core/utils/xml.js' ;
38- import type { VariableModel } from '../core/variable_model.js' ;
3942import * as Variables from '../core/variables.js' ;
4043import type { Workspace } from '../core/workspace.js' ;
4144import type { WorkspaceSvg } from '../core/workspace_svg.js' ;
@@ -48,7 +51,7 @@ export const blocks: {[key: string]: BlockDefinition} = {};
4851type ProcedureBlock = Block & ProcedureMixin ;
4952interface ProcedureMixin extends ProcedureMixinType {
5053 arguments_ : string [ ] ;
51- argumentVarModels_ : VariableModel [ ] ;
54+ argumentVarModels_ : IVariableModel < IVariableState > [ ] ;
5255 callType_ : string ;
5356 paramIds_ : string [ ] ;
5457 hasStatements_ : boolean ;
@@ -128,7 +131,7 @@ const PROCEDURE_DEF_COMMON = {
128131 for ( let i = 0 ; i < this . argumentVarModels_ . length ; i ++ ) {
129132 const parameter = xmlUtils . createElement ( 'arg' ) ;
130133 const argModel = this . argumentVarModels_ [ i ] ;
131- parameter . setAttribute ( 'name' , argModel . name ) ;
134+ parameter . setAttribute ( 'name' , argModel . getName ( ) ) ;
132135 parameter . setAttribute ( 'varid' , argModel . getId ( ) ) ;
133136 if ( opt_paramIds && this . paramIds_ ) {
134137 parameter . setAttribute ( 'paramId' , this . paramIds_ [ i ] ) ;
@@ -196,7 +199,7 @@ const PROCEDURE_DEF_COMMON = {
196199 state [ 'params' ] . push ( {
197200 // We don't need to serialize the name, but just in case we decide
198201 // to separate params from variables.
199- 'name' : this . argumentVarModels_ [ i ] . name ,
202+ 'name' : this . argumentVarModels_ [ i ] . getName ( ) ,
200203 'id' : this . argumentVarModels_ [ i ] . getId ( ) ,
201204 } ) ;
202205 }
@@ -224,7 +227,7 @@ const PROCEDURE_DEF_COMMON = {
224227 param [ 'name' ] ,
225228 '' ,
226229 ) ;
227- this . arguments_ . push ( variable . name ) ;
230+ this . arguments_ . push ( variable . getName ( ) ) ;
228231 this . argumentVarModels_ . push ( variable ) ;
229232 }
230233 }
@@ -352,7 +355,9 @@ const PROCEDURE_DEF_COMMON = {
352355 *
353356 * @returns List of variable models.
354357 */
355- getVarModels : function ( this : ProcedureBlock ) : VariableModel [ ] {
358+ getVarModels : function (
359+ this : ProcedureBlock ,
360+ ) : IVariableModel < IVariableState > [ ] {
356361 return this . argumentVarModels_ ;
357362 } ,
358363 /**
@@ -370,23 +375,23 @@ const PROCEDURE_DEF_COMMON = {
370375 newId : string ,
371376 ) {
372377 const oldVariable = this . workspace . getVariableById ( oldId ) ! ;
373- if ( oldVariable . type !== '' ) {
378+ if ( oldVariable . getType ( ) !== '' ) {
374379 // Procedure arguments always have the empty type.
375380 return ;
376381 }
377- const oldName = oldVariable . name ;
382+ const oldName = oldVariable . getName ( ) ;
378383 const newVar = this . workspace . getVariableById ( newId ) ! ;
379384
380385 let change = false ;
381386 for ( let i = 0 ; i < this . argumentVarModels_ . length ; i ++ ) {
382387 if ( this . argumentVarModels_ [ i ] . getId ( ) === oldId ) {
383- this . arguments_ [ i ] = newVar . name ;
388+ this . arguments_ [ i ] = newVar . getName ( ) ;
384389 this . argumentVarModels_ [ i ] = newVar ;
385390 change = true ;
386391 }
387392 }
388393 if ( change ) {
389- this . displayRenamedVar_ ( oldName , newVar . name ) ;
394+ this . displayRenamedVar_ ( oldName , newVar . getName ( ) ) ;
390395 Procedures . mutateCallers ( this ) ;
391396 }
392397 } ,
@@ -398,9 +403,9 @@ const PROCEDURE_DEF_COMMON = {
398403 */
399404 updateVarName : function (
400405 this : ProcedureBlock & BlockSvg ,
401- variable : VariableModel ,
406+ variable : IVariableModel < IVariableState > ,
402407 ) {
403- const newName = variable . name ;
408+ const newName = variable . getName ( ) ;
404409 let change = false ;
405410 let oldName ;
406411 for ( let i = 0 ; i < this . argumentVarModels_ . length ; i ++ ) {
@@ -473,12 +478,16 @@ const PROCEDURE_DEF_COMMON = {
473478 const getVarBlockState = {
474479 type : 'variables_get' ,
475480 fields : {
476- VAR : { name : argVar . name , id : argVar . getId ( ) , type : argVar . type } ,
481+ VAR : {
482+ name : argVar . getName ( ) ,
483+ id : argVar . getId ( ) ,
484+ type : argVar . getType ( ) ,
485+ } ,
477486 } ,
478487 } ;
479488 options . push ( {
480489 enabled : true ,
481- text : Msg [ 'VARIABLES_SET_CREATE_GET' ] . replace ( '%1' , argVar . name ) ,
490+ text : Msg [ 'VARIABLES_SET_CREATE_GET' ] . replace ( '%1' , argVar . getName ( ) ) ,
482491 callback : ContextMenu . callbackFactory ( this , getVarBlockState ) ,
483492 } ) ;
484493 }
@@ -620,30 +629,49 @@ type ArgumentBlock = Block & ArgumentMixin;
620629interface ArgumentMixin extends ArgumentMixinType { }
621630type ArgumentMixinType = typeof PROCEDURES_MUTATORARGUMENT ;
622631
623- // TODO(#6920): This is kludgy.
624- type FieldTextInputForArgument = FieldTextInput & {
625- oldShowEditorFn_ ( _e ?: Event , quietInput ?: boolean ) : void ;
626- createdVariables_ : VariableModel [ ] ;
627- } ;
632+ /**
633+ * Field responsible for editing procedure argument names.
634+ */
635+ class ProcedureArgumentField extends FieldTextInput {
636+ /**
637+ * Whether or not this field is currently being edited interactively.
638+ */
639+ editingInteractively = false ;
640+
641+ /**
642+ * The procedure argument variable whose name is being interactively edited.
643+ */
644+ editingVariable ?: IVariableModel < IVariableState > ;
645+
646+ /**
647+ * Displays the field editor.
648+ *
649+ * @param e The event that triggered display of the field editor.
650+ */
651+ protected override showEditor_ ( e ?: Event ) {
652+ super . showEditor_ ( e ) ;
653+ this . editingInteractively = true ;
654+ this . editingVariable = undefined ;
655+ }
656+
657+ /**
658+ * Handles cleanup when the field editor is dismissed.
659+ */
660+ override onFinishEditing_ ( value : string ) {
661+ super . onFinishEditing_ ( value ) ;
662+ this . editingInteractively = false ;
663+ }
664+ }
628665
629666const PROCEDURES_MUTATORARGUMENT = {
630667 /**
631668 * Mutator block for procedure argument.
632669 */
633670 init : function ( this : ArgumentBlock ) {
634- const field = fieldRegistry . fromJson ( {
635- type : 'field_input' ,
636- text : Procedures . DEFAULT_ARG ,
637- } ) as FieldTextInputForArgument ;
638- field . setValidator ( this . validator_ ) ;
639- // Hack: override showEditor to do just a little bit more work.
640- // We don't have a good place to hook into the start of a text edit.
641- field . oldShowEditorFn_ = ( field as AnyDuringMigration ) . showEditor_ ;
642- const newShowEditorFn = function ( this : typeof field ) {
643- this . createdVariables_ = [ ] ;
644- this . oldShowEditorFn_ ( ) ;
645- } ;
646- ( field as AnyDuringMigration ) . showEditor_ = newShowEditorFn ;
671+ const field = new ProcedureArgumentField (
672+ Procedures . DEFAULT_ARG ,
673+ this . validator_ ,
674+ ) ;
647675
648676 this . appendDummyInput ( )
649677 . appendField ( Msg [ 'PROCEDURES_MUTATORARG_TITLE' ] )
@@ -653,14 +681,6 @@ const PROCEDURES_MUTATORARGUMENT = {
653681 this . setStyle ( 'procedure_blocks' ) ;
654682 this . setTooltip ( Msg [ 'PROCEDURES_MUTATORARG_TOOLTIP' ] ) ;
655683 this . contextMenu = false ;
656-
657- // Create the default variable when we drag the block in from the flyout.
658- // Have to do this after installing the field on the block.
659- field . onFinishEditing_ = this . deleteIntermediateVars_ ;
660- // Create an empty list so onFinishEditing_ has something to look at, even
661- // though the editor was never opened.
662- field . createdVariables_ = [ ] ;
663- field . onFinishEditing_ ( 'x' ) ;
664684 } ,
665685
666686 /**
@@ -674,11 +694,11 @@ const PROCEDURES_MUTATORARGUMENT = {
674694 * @returns Valid name, or null if a name was not specified.
675695 */
676696 validator_ : function (
677- this : FieldTextInputForArgument ,
697+ this : ProcedureArgumentField ,
678698 varName : string ,
679699 ) : string | null {
680700 const sourceBlock = this . getSourceBlock ( ) ! ;
681- const outerWs = sourceBlock ! . workspace . getRootWorkspace ( ) ! ;
701+ const outerWs = sourceBlock . workspace . getRootWorkspace ( ) ! ;
682702 varName = varName . replace ( / [ \s \xa0 ] + / g, ' ' ) . replace ( / ^ | $ / g, '' ) ;
683703 if ( ! varName ) {
684704 return null ;
@@ -707,50 +727,31 @@ const PROCEDURES_MUTATORARGUMENT = {
707727 return varName ;
708728 }
709729
710- let model = outerWs . getVariable ( varName , '' ) ;
711- if ( model && model . name !== varName ) {
730+ const model = outerWs . getVariable ( varName , '' ) ;
731+ if ( model && model . getName ( ) !== varName ) {
712732 // Rename the variable (case change)
713733 outerWs . renameVariableById ( model . getId ( ) , varName ) ;
714734 }
715735 if ( ! model ) {
716- model = outerWs . createVariable ( varName , '' ) ;
717- if ( model && this . createdVariables_ ) {
718- this . createdVariables_ . push ( model ) ;
736+ if ( this . editingInteractively ) {
737+ if ( ! this . editingVariable ) {
738+ this . editingVariable = outerWs . createVariable ( varName , '' ) ;
739+ } else {
740+ outerWs . renameVariableById ( this . editingVariable . getId ( ) , varName ) ;
741+ }
742+ } else {
743+ outerWs . createVariable ( varName , '' ) ;
719744 }
720745 }
721746 return varName ;
722747 } ,
723-
724- /**
725- * Called when focusing away from the text field.
726- * Deletes all variables that were created as the user typed their intended
727- * variable name.
728- *
729- * @internal
730- * @param newText The new variable name.
731- */
732- deleteIntermediateVars_ : function (
733- this : FieldTextInputForArgument ,
734- newText : string ,
735- ) {
736- const outerWs = this . getSourceBlock ( ) ! . workspace . getRootWorkspace ( ) ;
737- if ( ! outerWs ) {
738- return ;
739- }
740- for ( let i = 0 ; i < this . createdVariables_ . length ; i ++ ) {
741- const model = this . createdVariables_ [ i ] ;
742- if ( model . name !== newText ) {
743- outerWs . deleteVariableById ( model . getId ( ) ) ;
744- }
745- }
746- } ,
747748} ;
748749blocks [ 'procedures_mutatorarg' ] = PROCEDURES_MUTATORARGUMENT ;
749750
750751/** Type of a block using the PROCEDURE_CALL_COMMON mixin. */
751752type CallBlock = Block & CallMixin ;
752753interface CallMixin extends CallMixinType {
753- argumentVarModels_ : VariableModel [ ] ;
754+ argumentVarModels_ : IVariableModel < IVariableState > [ ] ;
754755 arguments_ : string [ ] ;
755756 defType_ : string ;
756757 quarkIds_ : string [ ] | null ;
@@ -1029,7 +1030,7 @@ const PROCEDURE_CALL_COMMON = {
10291030 *
10301031 * @returns List of variable models.
10311032 */
1032- getVarModels : function ( this : CallBlock ) : VariableModel [ ] {
1033+ getVarModels : function ( this : CallBlock ) : IVariableModel < IVariableState > [ ] {
10331034 return this . argumentVarModels_ ;
10341035 } ,
10351036 /**
@@ -1177,7 +1178,7 @@ const PROCEDURE_CALL_COMMON = {
11771178 const def = Procedures . getDefinition ( name , workspace ) ;
11781179 if ( def ) {
11791180 ( workspace as WorkspaceSvg ) . centerOnBlock ( def . id ) ;
1180- common . setSelected ( def as BlockSvg ) ;
1181+ getFocusManager ( ) . focusNode ( def as BlockSvg ) ;
11811182 }
11821183 } ,
11831184 } ) ;
0 commit comments