• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. Use for loop to create dynamic field in hiCreateAppForm

Stats

  • Locked Locked
  • Replies 11
  • Subscribers 143
  • Views 17845
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Use for loop to create dynamic field in hiCreateAppForm

mantang
mantang over 5 years ago

Hi 

I use for loop to generate same two fields 10 times, so I could change # of two fields easily in the future. Since nameHandle "symmetry1" and "group_instance" or symbol "'instances" and "'symmetry1" are same for two fields (10 times), how could I access the value of 20 fields (10 x 2 fields) in the form callback procedure ? Is it the correct approach ?

I could create 20 fields one by one using different symbol and nameHandle manually, but I don't think it is a good approach for code maintenance. Any suggestion ?  

I saw an article about dynamic field https://community.cadence.com/cadence_technology_forums/f/custom-ic-skill/35948/accessing-dynamic-form-fields  , but I do not know how to use the code in hiCreateAppForm and nameHandle is the same for different symbol name of hiCreateRadioButton.

 

group_instance = hiCreateStringField(
?name 'instances
?prompt "Group instances"
)
symmetry1 = hiCreateRadioField(
?name 'symmetry1
?prompt "Device symmetry"
?choices list("Y" "N")
?value "Y"
?callback "symmetry1CB(hiGetCurrentForm())"
)


allList = nil
startx = 0
starty = 210
width = 600
height = 30

for(i 0 9
finalx = startx
finaly = 210 + (i*height)
finalx_f2 = finalx
finaly_f2 = finaly + height
flist = list(list(group_instance finalx:finaly width:height) list(symmetry1 finalx_f2:finaly_f2 width:height))
allList = append(allList, flist)
)

hiCreateAppForm(
?name 'ExampleForm
?formTitle "example form"
?callback 'ExampleFormCB
?fields allList

..

)

Thanks,

ManChak

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 5 years ago
    let((group_instance symmetry allList startx starty width height)
    
        allList = nil
        startx = 0
        starty = 210
        width = 600
        height = 30
    
        for(i 0 9
            ; use concat to give each field a unique name
            group_instance = hiCreateStringField(
                ?name concat('instances i)
                ?prompt "Group instances"
            )
            symmetry = hiCreateRadioField(
                ?name concat('symmetry i)
                ?prompt "Device symmetry"
                ?choices list("Y" "N")
                ?value "Y"
            ; commented callback out for now as this needs to be a list
            ;    ?callback "symmetry1CB(hiGetCurrentForm())"
            )
            finalx = startx
            ; add a *2 to stop the fields overlapping
            finaly = 210 + (i*height*2)
            finalx_f2 = finalx
            finaly_f2 = finaly + height
            ; added prompt widths
            flist = list(
                list(group_instance finalx:finaly width:height 120) 
                list(symmetry finalx_f2:finaly_f2 width:height 120)
            )
            ; should really consider whether append is the right approach
            ; if there are many fields (lists are sequential). Maybe lconc or
            ; build list using cons and then reverse() at the end?
            allList = append(allList flist)
        )
    
        hiCreateAppForm(
            ?name 'ExampleForm
            ?formTitle "example form"
            ?callback 'ExampleFormCB
            ?fields allList
        )
    )
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • mantang
    mantang over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thank you for your code. It clarifies my SKILL concept.  How do I pass a list of callback procedures in "?callback argument" inside for loop in this case since each radio field has its own callback procedure? 

    ?callback list("symmetryCB(hiGetCurrentForm())")    ?

    symmetry = hiCreateRadioField(
    ?name concat('symmetry i)
    ?prompt "Device symmetry"
    ?choices list("Y" "N")
    ?value "Y"
    ; commented callback out for now as this needs to be a list
    ; ?callback "symmetry1CB(hiGetCurrentForm())"
    )

    Thanks,

    ManChak

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to mantang

    Hi ManChak,

    In this example, I use a common callback function, but pass in the field names to the callback so that the common callback can retrieve the associated fields. The other approach would be to construct the callback function name using sprintf in a similar fashion (so it could be symmetry%dCB for example).

    Andrew.

    procedure(symmetryCB(form symmetry instances)
        printf("symmetry is %s\n" get(form symmetry)->value)
        printf("instances is %s\n" get(form instances)->value)
    )
    
    let((group_instance symmetry allList startx starty width height)
    
        allList = nil
        startx = 0
        starty = 210
        width = 600
        height = 30
    
        for(i 0 9
            ; use concat to give each field a unique name
            group_instance = hiCreateStringField(
                ?name concat('instances i)
                ?prompt "Group instances"
            )
            symmetry = hiCreateRadioField(
                ?name concat('symmetry i)
                ?prompt "Device symmetry"
                ?choices list("Y" "N")
                ?value "Y"
                ?callback list(
                    sprintf(nil 
                        "symmetryCB(hiGetCurrentForm() 'symmetry%d 'instances%d)"
                        i i
                    )
                )
            )
            finalx = startx
            ; add a *2 to stop the fields overlapping
            finaly = 210 + (i*height*2)
            finalx_f2 = finalx
            finaly_f2 = finaly + height
            ; added prompt widths
            flist = list(
                list(group_instance finalx:finaly width:height 120) 
                list(symmetry finalx_f2:finaly_f2 width:height 120)
            )
            ; should really consider whether append is the right approach
            ; if there are many fields (lists are sequential). Maybe lconc or
            ; build list using cons and then reverse() at the end?
            allList = append(allList flist)
        )
    
        hiCreateAppForm(
            ?name 'ExampleForm
            ?formTitle "example form"
            ?callback 'ExampleFormCB
            ?fields allList
        )
    )
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • mantang
    mantang over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thank you for your help. I will try the code.

    ManChak

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • mantang
    mantang over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    I use your code above to create "allList". I get syntax syntax if I use the following code for  hiCreateAppForm.

    I know item1 solution should work, but I prefer item2 solution if possible. I just want "allList" contains fields defined in the for loop.

    1) Do I need to add templateField, templateLoad, templateSave, sep1, libName to allList ?

    OR 

    2) ?fields argument could accept multiple list ?

    hiCreateAppForm(
       ?name 'ExampleForm
       ?formTitle "example form"
       ?callback 'ExampleFormCB
       ?fields
       list(
          list(templateFile 0:0 600:30 200)
          list(templateLoad 100:5 45:20)
          list(templateSave 150:5 45:20)
          list(sep1 0:35 600:0)
          list(libName 0:40 600:30 200)
          allList
      ) )

    *WARNING* promptWidth attribute must be a positive integer:
    *WARNING* ((stringStruct@0x2ed5fcb0 (0 210) (600 30) 120) (radioStruct@0x2ed5fcc8 (0 240) (600 30) 120) (stringStruct@0x2ed5fce0 (0 270) (600 30) 120) (radioStruct@0x2ed5fcf8 (0 300) (600 30) 120) (stringStruct@0x2ed5fd10 (0 330) (600 30) 120) (radioStruct@0x2ed5fd28 (0 360) (600 30) 120) (stringStruct@0x2ed5fd40 (0 390) (600 30) 120) (radioStruct@0x2ed5fd58 (0 420) (600 30) 120) (stringStruct@0x2ed5fd70 (0 450) (600 30) 120) (radioStruct@0x2ed5fd88 (0 480) (600 30) 120) (stringStruct@0x2ed5fda0 (0 510) (600 30) 120
    *Error* hiCreateAppForm: not all fields have 2D attributes specified,
    and/or illegal attribute values

    Thanks,

    ManChak

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to mantang

    It fails because the list would be the wrong structure - you'd have the allList within the list with the other fields. You'd need to do (and I didn't test this because I don't have your other fields defined, but it should work):

    hiCreateAppForm(
       ?name 'ExampleForm
       ?formTitle "example form"
       ?callback 'ExampleFormCB
       ?fields
       append(
         list(
            list(templateFile 0:0 600:30 200)
            list(templateLoad 100:5 45:20)
            list(templateSave 150:5 45:20)
            list(sep1 0:35 600:0)
            list(libName 0:40 600:30 200)
         )
         allList
       )
    )

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • mantang
    mantang over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    1. Thank you for your help. It works,

    2. I have one question about your suggestion in the previous response. I tried lconc and cons in my code. According to SKILL manual, one argument of cons is item instead of list. 

    Unlike append command,  "lconc" merges two lists together. How could I replace "append" command with either cons or lconc command to build allList ?

        x = tconc(nil 1) ; x is initialized ((1) 1)
    lconc(x '(2 3 4)) ; x is now ((1 2 3 4) 4)
    lconc(x nil) ; Nothing is added to x.
    lconc(x '(5)) ; x is now ((1 2 3 4 5) 5)
       x = car( x ) ; x is now (1 2 3 4 5)

    flist = list(
    list(group_instance finalx:finaly width:height 120)
    list(symmetry finalx_f2:finaly_f2 width:height 120)
    )
    ; should really consider whether append is the right approach
    ; if there are many fields (lists are sequential). Maybe lconc or
    ; build list using cons and then reverse() at the end?

    allList = append(allList flist)

    Thanks,

    ManChak

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to mantang

    ManChak,

    Here's the first version, using lconc:

    procedure(symmetryCB(form symmetry instances)
        printf("symmetry is %s\n" get(form symmetry)->value)
        printf("instances is %s\n" get(form instances)->value)
    )
    
    let((group_instance symmetry allList startx starty width height
            templateFile templateLoad templateSave sep1 libName)
    
        templateFile = hiCreateStringField(
            ?name 'templateFile
            ?prompt "Template File"
        )
        templateLoad = hiCreateButton(
            ?name 'templateLoad
            ?buttonText "Load"
        )
        templateSave = hiCreateButton(
            ?name 'templateSave
            ?buttonText "Save"
        )
        sep1 = hiCreateSeparatorField(
            ?name 'sep1
        )
        libName = hiCreateStringField(
            ?name 'libName
            ?prompt "Library Name"
        )
    
        allList = nil
        startx = 0
        starty = 210
        width = 600
        height = 30
    
        for(i 0 9
            ; use concat to give each field a unique name
            group_instance = hiCreateStringField(
                ?name concat('instances i)
                ?prompt "Group instances"
            )
            symmetry = hiCreateRadioField(
                ?name concat('symmetry i)
                ?prompt "Device symmetry"
                ?choices list("Y" "N")
                ?value "Y"
                ?callback list(
                    sprintf(nil 
                        "symmetryCB(hiGetCurrentForm() 'symmetry%d 'instances%d)"
                        i i
                    )
                )
            )
            finalx = startx
            ; add a *2 to stop the fields overlapping
            finaly = 210 + (i*height*2)
            finalx_f2 = finalx
            finaly_f2 = finaly + height
            ; added prompt widths
            flist = list(
                list(group_instance finalx:finaly width:height 120) 
                list(symmetry finalx_f2:finaly_f2 width:height 120)
            )
    	; Example using lconc
    	; was using append here
            allList = lconc(allList flist)
        )
        allList=car(allList)
    
        hiCreateAppForm(
            ?name 'ExampleForm
            ?formTitle "example form"
            ?callback 'ExampleFormCB
            ?fields 
                append(
                    list(
                        list(templateFile 0:0 600:30 200)
                        list(templateLoad 100:5 45:20)
                        list(templateSave 150:5 45:20)
                        list(sep1 0:35 600:0)
                        list(libName 0:40 600:30 200)
                    )
                    allList
                )
        )
    )

    Here's using cons and reverse:

    procedure(symmetryCB(form symmetry instances)
        printf("symmetry is %s\n" get(form symmetry)->value)
        printf("instances is %s\n" get(form instances)->value)
    )
    
    let((group_instance symmetry allList startx starty width height
            templateFile templateLoad templateSave sep1 libName)
    
        templateFile = hiCreateStringField(
            ?name 'templateFile
            ?prompt "Template File"
        )
        templateLoad = hiCreateButton(
            ?name 'templateLoad
            ?buttonText "Load"
        )
        templateSave = hiCreateButton(
            ?name 'templateSave
            ?buttonText "Save"
        )
        sep1 = hiCreateSeparatorField(
            ?name 'sep1
        )
        libName = hiCreateStringField(
            ?name 'libName
            ?prompt "Library Name"
        )
    
        allList = nil
        startx = 0
        starty = 210
        width = 600
        height = 30
    
        for(i 0 9
            ; use concat to give each field a unique name
            group_instance = hiCreateStringField(
                ?name concat('instances i)
                ?prompt "Group instances"
            )
            symmetry = hiCreateRadioField(
                ?name concat('symmetry i)
                ?prompt "Device symmetry"
                ?choices list("Y" "N")
                ?value "Y"
                ?callback list(
                    sprintf(nil 
                        "symmetryCB(hiGetCurrentForm() 'symmetry%d 'instances%d)"
                        i i
                    )
                )
            )
            finalx = startx
            ; add a *2 to stop the fields overlapping
            finaly = 210 + (i*height*2)
            finalx_f2 = finalx
            finaly_f2 = finaly + height
            ; added prompt widths
    	; now using cons to construct the list - more efficient since
    	; it adds to the beginning
    	allList=cons(list(group_instance finalx:finaly width:height 120) allList)
    	allList=cons(list(symmetry finalx_f2:finaly_f2 width:height 120) allList)
        )
        ; the fields all appear OK even if you don't reverse, but if
        ; you use tab to move through the fields, they are in the wrong order
        ; unless you reverse the list to be from top to bottom
        allList=reverse(allList)
    
        hiCreateAppForm(
            ?name 'ExampleForm
            ?formTitle "example form"
            ?callback 'ExampleFormCB
            ?fields 
                append(
                    list(
                        list(templateFile 0:0 600:30 200)
                        list(templateLoad 100:5 45:20)
                        list(templateSave 150:5 45:20)
                        list(sep1 0:35 600:0)
                        list(libName 0:40 600:30 200)
                    )
                    allList
                )
        )
    )

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to mantang

    ManChak,

    Here's the first version, using lconc:

    procedure(symmetryCB(form symmetry instances)
        printf("symmetry is %s\n" get(form symmetry)->value)
        printf("instances is %s\n" get(form instances)->value)
    )
    
    let((group_instance symmetry allList startx starty width height
            templateFile templateLoad templateSave sep1 libName)
    
        templateFile = hiCreateStringField(
            ?name 'templateFile
            ?prompt "Template File"
        )
        templateLoad = hiCreateButton(
            ?name 'templateLoad
            ?buttonText "Load"
        )
        templateSave = hiCreateButton(
            ?name 'templateSave
            ?buttonText "Save"
        )
        sep1 = hiCreateSeparatorField(
            ?name 'sep1
        )
        libName = hiCreateStringField(
            ?name 'libName
            ?prompt "Library Name"
        )
    
        allList = nil
        startx = 0
        starty = 210
        width = 600
        height = 30
    
        for(i 0 9
            ; use concat to give each field a unique name
            group_instance = hiCreateStringField(
                ?name concat('instances i)
                ?prompt "Group instances"
            )
            symmetry = hiCreateRadioField(
                ?name concat('symmetry i)
                ?prompt "Device symmetry"
                ?choices list("Y" "N")
                ?value "Y"
                ?callback list(
                    sprintf(nil 
                        "symmetryCB(hiGetCurrentForm() 'symmetry%d 'instances%d)"
                        i i
                    )
                )
            )
            finalx = startx
            ; add a *2 to stop the fields overlapping
            finaly = 210 + (i*height*2)
            finalx_f2 = finalx
            finaly_f2 = finaly + height
            ; added prompt widths
            flist = list(
                list(group_instance finalx:finaly width:height 120) 
                list(symmetry finalx_f2:finaly_f2 width:height 120)
            )
    	; Example using lconc
    	; was using append here
            allList = lconc(allList flist)
        )
        allList=car(allList)
    
        hiCreateAppForm(
            ?name 'ExampleForm
            ?formTitle "example form"
            ?callback 'ExampleFormCB
            ?fields 
                append(
                    list(
                        list(templateFile 0:0 600:30 200)
                        list(templateLoad 100:5 45:20)
                        list(templateSave 150:5 45:20)
                        list(sep1 0:35 600:0)
                        list(libName 0:40 600:30 200)
                    )
                    allList
                )
        )
    )

    Here's using cons and reverse:

    procedure(symmetryCB(form symmetry instances)
        printf("symmetry is %s\n" get(form symmetry)->value)
        printf("instances is %s\n" get(form instances)->value)
    )
    
    let((group_instance symmetry allList startx starty width height
            templateFile templateLoad templateSave sep1 libName)
    
        templateFile = hiCreateStringField(
            ?name 'templateFile
            ?prompt "Template File"
        )
        templateLoad = hiCreateButton(
            ?name 'templateLoad
            ?buttonText "Load"
        )
        templateSave = hiCreateButton(
            ?name 'templateSave
            ?buttonText "Save"
        )
        sep1 = hiCreateSeparatorField(
            ?name 'sep1
        )
        libName = hiCreateStringField(
            ?name 'libName
            ?prompt "Library Name"
        )
    
        allList = nil
        startx = 0
        starty = 210
        width = 600
        height = 30
    
        for(i 0 9
            ; use concat to give each field a unique name
            group_instance = hiCreateStringField(
                ?name concat('instances i)
                ?prompt "Group instances"
            )
            symmetry = hiCreateRadioField(
                ?name concat('symmetry i)
                ?prompt "Device symmetry"
                ?choices list("Y" "N")
                ?value "Y"
                ?callback list(
                    sprintf(nil 
                        "symmetryCB(hiGetCurrentForm() 'symmetry%d 'instances%d)"
                        i i
                    )
                )
            )
            finalx = startx
            ; add a *2 to stop the fields overlapping
            finaly = 210 + (i*height*2)
            finalx_f2 = finalx
            finaly_f2 = finaly + height
            ; added prompt widths
    	; now using cons to construct the list - more efficient since
    	; it adds to the beginning
    	allList=cons(list(group_instance finalx:finaly width:height 120) allList)
    	allList=cons(list(symmetry finalx_f2:finaly_f2 width:height 120) allList)
        )
        ; the fields all appear OK even if you don't reverse, but if
        ; you use tab to move through the fields, they are in the wrong order
        ; unless you reverse the list to be from top to bottom
        allList=reverse(allList)
    
        hiCreateAppForm(
            ?name 'ExampleForm
            ?formTitle "example form"
            ?callback 'ExampleFormCB
            ?fields 
                append(
                    list(
                        list(templateFile 0:0 600:30 200)
                        list(templateLoad 100:5 45:20)
                        list(templateSave 150:5 45:20)
                        list(sep1 0:35 600:0)
                        list(libName 0:40 600:30 200)
                    )
                    allList
                )
        )
    )

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • mantang
    mantang over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thank you for your examples. It is very useful to me.

    Thanks,

    ManChak

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information