@@ -127,7 +127,7 @@ angular
127127 //---------------------------------------------
128128 write ( value ) {
129129 //-- Write the value to the DOM
130- $ ( `#form${ this . formId } ` ) . val ( value ) ;
130+ $ ( `#form${ this . formId } ` ) . val ( value ) . trigger ( 'input' ) ;
131131 }
132132
133133 //------------------------------------------------
@@ -738,6 +738,7 @@ angular
738738 this . tableId = `table${ formId } ` ;
739739 this . table = null ;
740740 this . className = className ;
741+ this . onEnter = null ;
741742
742743 //-- Html template for building the grid
743744 this . htmlTemplate = `
@@ -766,6 +767,12 @@ angular
766767 allowManualInsertRow : false ,
767768 tableOverflow : true ,
768769 tableHeight : '200px' ,
770+ contextMenu : false ,
771+ onchange : ( ) => {
772+ if ( typeof this . onEnter === 'function' ) {
773+ this . onEnter ( this ) ;
774+ }
775+ } ,
769776 } ) ;
770777 }
771778
@@ -776,6 +783,20 @@ angular
776783 read ( ) {
777784 return this . table . getData ( ) ;
778785 }
786+
787+ allowEnter ( ) {
788+ const editor = document . querySelector (
789+ `#${ this . tableId } .editor input`
790+ ) ;
791+ if ( editor ) {
792+ editor . blur ( ) ;
793+ if ( typeof this . onEnter === 'function' ) {
794+ this . onEnter ( this ) ;
795+ }
796+ return false ;
797+ }
798+ return true ;
799+ }
779800 }
780801
781802 class Form {
@@ -1023,7 +1044,37 @@ angular
10231044 dialog . setContent ( html ) ;
10241045
10251046 //-- Set the callback for the OK button
1026- dialog . set ( 'onok' , callback ) ;
1047+ dialog . set ( 'onok' , function ( evt ) {
1048+ let allow = true ;
1049+
1050+ if ( Array . isArray ( self . fields ) ) {
1051+ self . fields . forEach ( ( field ) => {
1052+ if (
1053+ typeof field . allowEnter === 'function' &&
1054+ ! field . allowEnter ( )
1055+ ) {
1056+ allow = false ;
1057+ }
1058+ } ) ;
1059+ } else {
1060+ Object . keys ( self . fields ) . forEach ( ( tab ) => {
1061+ self . fields [ tab ] . forEach ( ( field ) => {
1062+ if (
1063+ typeof field . allowEnter === 'function' &&
1064+ ! field . allowEnter ( )
1065+ ) {
1066+ allow = false ;
1067+ }
1068+ } ) ;
1069+ } ) ;
1070+ }
1071+
1072+ if ( allow ) {
1073+ callback ( evt ) ;
1074+ } else {
1075+ evt . cancel = true ;
1076+ }
1077+ } ) ;
10271078
10281079 //-- Set the callback for the Cancel button:
10291080 //-- Do nothing...
@@ -1954,21 +2005,22 @@ angular
19542005 ] ;
19552006
19562007 const columns = [
1957- { type : 'text' , title : 'Name' , width : 150 } ,
2008+ { type : 'text' , title : 'Name' , width : 140 } ,
19582009 {
19592010 type : 'dropdown' ,
19602011 title : 'Type' ,
1961- width : 70 ,
2012+ width : 80 ,
19622013 source : [ 'IN' , 'OUT' , 'BIDI' ] ,
19632014 } ,
19642015 { type : 'numeric' , title : 'Bus width' , width : 80 } ,
19652016 { type : 'checkbox' , title : 'Signed' , width : 55 } ,
19662017 { type : 'checkbox' , title : 'Registered' , width : 80 } ,
19672018 { type : 'checkbox' , title : 'Enable' , width : 60 } ,
19682019 ] ;
1969- const data = [ [ '' , 'IN' , 0 , false , false , true ] ] ;
2020+ const data = [ [ '' , 'IN' , 1 , false , false , true ] ] ;
19702021
19712022 let field7 = new GridField ( 7 , 'ports-table' , columns , data ) ;
2023+ field7 . onEnter = onEnterIOPortsTable ;
19722024 this . addField ( field7 , modulePortsLabel ) ;
19732025
19742026 field0 . onChange ( ( value ) => {
@@ -2832,13 +2884,104 @@ angular
28322884 //------------------------------------------------------------------------
28332885 //-- Private functions
28342886 //------------------------------------------------------------------------
2887+ function onEnterIOPortsTable ( self ) {
2888+ const grouped = {
2889+ IN : [ ] ,
2890+ OUT : [ ] ,
2891+ BIDI : [ ] ,
2892+ } ;
2893+
2894+ self . table . getData ( ) . forEach ( ( row ) => {
2895+ const enabled = row [ 5 ] !== false ;
2896+ if ( ! enabled ) {
2897+ return ;
2898+ }
2899+ let name = row [ 0 ] ?. trim ( ) ;
2900+ const type = row [ 1 ] ?. toUpperCase ( ) ;
2901+ const busWidth = parseInt ( row [ 2 ] , 10 ) ;
2902+ const signed = row [ 3 ] === true ;
2903+
2904+ if ( ! name || ! type ) {
2905+ return ;
2906+ }
2907+
2908+ if ( ! isNaN ( busWidth ) && busWidth > 1 ) {
2909+ name += `[${ busWidth - 1 } :0]` ;
2910+ }
2911+
2912+ if ( signed ) {
2913+ name = `@${ name } ` ;
2914+ }
2915+
2916+ if ( grouped [ type ] ) {
2917+ grouped [ type ] . push ( name ) ;
2918+ }
2919+ } ) ;
2920+
2921+ const inInput = document . querySelector ( '#form0' ) ;
2922+ const outInput = document . querySelector ( '#form1' ) ;
2923+ const bidiInput1 = document . querySelector ( '#form3' ) ;
2924+ const bidiInput2 = document . querySelector ( '#form4' ) ;
2925+
2926+ inInput . value = grouped . IN . join ( ', ' ) ;
2927+ outInput . value = grouped . OUT . join ( ', ' ) ;
2928+ bidiInput1 . value = grouped . BIDI . join ( ', ' ) ;
2929+ bidiInput2 . value = grouped . BIDI . join ( ', ' ) ;
2930+
2931+ const coords = self . table . selectedCell || [ ] ;
2932+ const row = coords [ 1 ] || 0 ;
2933+ const data = self . table . getData ( ) ;
2934+ const rowData = self . table . getRowData ( row ) ;
2935+ const name = rowData [ 0 ] ;
2936+ const totalRows = data . length ;
2937+
2938+ const isEmpty = ! name ;
2939+ const defaultRow = [ '' , 'IN' , 1 , false , false , true ] ;
2940+
2941+ if ( isEmpty ) {
2942+ const otherEmptyRowExists = data . some ( ( r , i ) => ! r [ 0 ] && i !== row ) ;
2943+
2944+ if ( otherEmptyRowExists || totalRows > 1 ) {
2945+ self . table . deleteRow ( row ) ;
2946+
2947+ const stillHasEmptyRow = self . table . getData ( ) . some ( ( r ) => ! r [ 0 ] ) ;
2948+ if ( ! stillHasEmptyRow ) {
2949+ self . table . insertRow ( [ ...defaultRow ] ) ;
2950+ }
2951+ }
2952+ } else {
2953+ const hasEmptyRow = data . some ( ( r ) => ! r [ 0 ] ) ;
2954+ if ( ! hasEmptyRow ) {
2955+ self . table . insertRow ( [ ...defaultRow ] ) ;
2956+ }
2957+ }
2958+ }
2959+
28352960 function updateIOPortsTable ( instance , textList , type ) {
2836- const newNames = textList
2961+ const parsedNames = textList
28372962 . split ( ',' )
2838- . map ( ( n ) => n . trim ( ) )
2839- . filter ( ( n ) => n !== '' ) ;
2963+ . map ( ( n ) => {
2964+ let trimmed = n . trim ( ) ;
2965+ let signed = false ;
2966+
2967+ if ( trimmed . startsWith ( '@' ) ) {
2968+ signed = true ;
2969+ trimmed = trimmed . slice ( 1 ) ;
2970+ }
28402971
2841- const defaultRow = [ '' , 'IN' , 0 , false , false , true ] ;
2972+ const match = trimmed . match ( / ^ ( \w + ) \[ ( \d + ) : ( \d + ) \] $ / ) ;
2973+ if ( match ) {
2974+ const name = match [ 1 ] ;
2975+ const msb = parseInt ( match [ 2 ] , 10 ) ;
2976+ const lsb = parseInt ( match [ 3 ] , 10 ) ;
2977+ const busWidth = Math . abs ( msb - lsb ) + 1 ;
2978+ return { name, busWidth, signed } ;
2979+ }
2980+ return { name : trimmed , busWidth : 1 , signed } ;
2981+ } )
2982+ . filter ( ( { name } ) => name !== '' ) ;
2983+
2984+ const defaultRow = [ '' , 'IN' , 1 , false , false , true ] ;
28422985 const data = instance . getData ( ) ;
28432986
28442987 const nameToRowIndex = new Map ( ) ;
@@ -2851,13 +2994,18 @@ angular
28512994 }
28522995 } ) ;
28532996
2854- newNames . forEach ( ( name ) => {
2997+ const newNames = parsedNames . map ( ( p ) => p . name ) ;
2998+ parsedNames . forEach ( ( { name, busWidth, signed } ) => {
28552999 if ( nameToRowIndex . has ( name ) ) {
28563000 const i = nameToRowIndex . get ( name ) ;
28573001 const row = instance . getData ( ) [ i ] ;
28583002 if ( row [ 1 ] !== type ) {
28593003 instance . setValueFromCoords ( 1 , i , type ) ;
28603004 }
3005+ if ( row [ 2 ] !== busWidth ) {
3006+ instance . setValueFromCoords ( 2 , i , busWidth ) ;
3007+ }
3008+ instance . setValueFromCoords ( 3 , i , signed ) ;
28613009 usedIndexes . add ( i ) ;
28623010 } else {
28633011 let reused = false ;
@@ -2870,13 +3018,15 @@ angular
28703018 existingName
28713019 ) {
28723020 instance . setValueFromCoords ( 0 , i , name ) ;
3021+ instance . setValueFromCoords ( 2 , i , busWidth ) ;
3022+ instance . setValueFromCoords ( 3 , i , signed ) ;
28733023 usedIndexes . add ( i ) ;
28743024 reused = true ;
28753025 break ;
28763026 }
28773027 }
28783028 if ( ! reused ) {
2879- instance . insertRow ( [ name , type , 0 , false , false , true ] ) ;
3029+ instance . insertRow ( [ name , type , busWidth , signed , false , true ] ) ;
28803030 }
28813031 }
28823032 } ) ;
@@ -2889,13 +3039,20 @@ angular
28893039 }
28903040
28913041 const updated = instance . getData ( ) ;
3042+ let hasEmptyRow = false ;
3043+
28923044 for ( let i = updated . length - 1 ; i >= 0 ; i -- ) {
2893- if ( ! updated [ i ] [ 0 ] ) {
3045+ const length = instance . getData ( ) . length ;
3046+ if ( ! updated [ i ] [ 0 ] && length > 1 ) {
28943047 instance . deleteRow ( i ) ;
3048+ } else if ( ! updated [ i ] [ 0 ] ) {
3049+ hasEmptyRow = true ;
28953050 }
28963051 }
28973052
2898- instance . insertRow ( [ ...defaultRow ] ) ;
3053+ if ( ! hasEmptyRow ) {
3054+ instance . insertRow ( [ ...defaultRow ] ) ;
3055+ }
28993056 }
29003057 }
29013058 ) ;
0 commit comments