svcabre
svcabre

Reputation: 303

NSIS - How to implement three Mutually Exclusive Sections within a SubSection

I have a simple NSIS script based on the following source code I found on: NSIS Mutually Exclusive Sections. The problem I'm facing is that I'm not able to implement three mutually exclusive sections instead of one.

Section 0 is independent.

For Section 1, 2 and 3 I need to have them mutually exclusive. Being able to select none of them or just one selected at same time.

If you test the example it seems it works well when you select:

The problem starts when you continue selecting options after having section 3 selected and then you go to select section 2 and section 1. Or if you try to doing random selections the selections are messed up.

I'm not able to implement this mutually exclusive between three sections within a SubSection. Can anyone give me some light on this?

Much appreciated.

Thanks,

Here's the script that I have modified so far:

# Example to control section selection.
# It allows only one of three sections to be selected at any
# given time, but unlike one-section, it allows non of them 
# to be selected as well.
#

!include Sections.nsh
!include LogicLib.nsh

Name example
OutFile "mutually exclusive.exe"

ComponentText "please choose zero or one but the default"

SubSection /e "Test" SSEC00
    Section /o "Test Sec 0" sec0
    SectionEnd

    Section /o "#2 and #3 unselected" sec1
    SectionEnd

    Section /o "#1 and #3 unselected" sec2
    SectionEnd

    Section /o "#1 and #2 unselected" sec3
    SectionEnd
SubSectionEnd

Function .onInit
  Push $0

  SectionGetFlags ${sec1} $0
  IntOp $0 $0 & ${SECTION_OFF}
  SectionSetFlags ${sec1} $0

  SectionGetFlags ${sec2} $0
  IntOp $0 $0 & ${SECTION_OFF}
  SectionSetFlags ${sec2} $0

  SectionGetFlags ${sec3} $0
  IntOp $0 $0 & ${SECTION_OFF}
  SectionSetFlags ${sec3} $0

  Pop $0
FunctionEnd

Function .onSelChange
    Push $0

    ${If} ${SectionIsSelected} ${sec1}
    ${OrIf} ${SectionIsSelected} ${sec2}
    ${OrIf} ${SectionIsSelected} ${sec3}

        StrCmp $R9 ${sec1} check_sec2  # If last selection was sec1 goto check_sec2
        StrCmp $R9 ${sec2} check_sec3  # If last selection was sec2 goto check_sec3
        StrCmp $R9 ${sec3} check_sec1

        check_sec1:

        SectionGetFlags ${sec1} $0
        IntOp $0 $0 & ${SF_SELECTED}
        IntCmp $0 ${SF_SELECTED} 0 Seldone Seldone

        StrCpy $R9 ${sec1}
        SectionGetFlags ${sec2} $0
        IntOp $0 $0 & ${SECTION_OFF}
        SectionSetFlags ${sec2} $0

        SectionGetFlags ${sec3} $0
        IntOp $0 $0 & ${SECTION_OFF}
        SectionSetFlags ${sec3} $0
        Goto Seldone

        check_sec2:

        SectionGetFlags ${sec2} $0
        IntOp $0 $0 & ${SF_SELECTED}
        IntCmp $0 ${SF_SELECTED} 0 Seldone Seldone

        StrCpy $R9 ${sec2}
        SectionGetFlags ${sec1} $0
        IntOp $0 $0 & ${SECTION_OFF}
        SectionSetFlags ${sec1} $0

        SectionGetFlags ${sec3} $0
        IntOp $0 $0 & ${SECTION_OFF}
        SectionSetFlags ${sec3} $0

        check_sec3:

        SectionGetFlags ${sec3} $0
        IntOp $0 $0 & ${SF_SELECTED}
        IntCmp $0 ${SF_SELECTED} 0 Seldone Seldone

        StrCpy $R9 ${sec3}
          SectionGetFlags ${sec1} $0
          IntOp $0 $0 & ${SECTION_OFF}
          SectionSetFlags ${sec2} $0

          SectionGetFlags ${sec2} $0
          IntOp $0 $0 & ${SECTION_OFF}
          SectionSetFlags ${sec2} $0

        Goto check_sec1

        Seldone:

    ${EndIf}

    Pop $0
FunctionEnd

Upvotes: 0

Views: 778

Answers (1)

Anders
Anders

Reputation: 101666

In NSIS v3+ the section id of the changed section is stored in $0 when .onSelChange is called, this makes it easier to get the logic correct:

!include Sections.nsh
!include LogicLib.nsh

ComponentText "please choose zero or one but the default"

SubSection /e "Test" SSEC00
    Section /o "Test Sec 0" sec0
    SectionEnd

    Section /o "#2 and #3 unselected" sec1
    SectionEnd

    Section /o "#1 and #3 unselected" sec2
    SectionEnd

    Section /o "#1 and #2 unselected" sec3
    SectionEnd
SubSectionEnd

Page Components
Page InstFiles

Function .onSelChange
${IfThen} $0 = -1 ${|} Return ${|} ; I don't care about InstType changes
${If} $0 < ${sec1}
${OrIf} $0 > ${sec3}
    Return ; I don't care about other sections
${EndIf}

!macro SelectOnlyMe sid
${IfThen} $0 <> ${sid} ${|} !insertmacro UnselectSection ${sid} ${|}
!macroend

!insertmacro SelectOnlyMe ${sec1}
!insertmacro SelectOnlyMe ${sec2}
!insertmacro SelectOnlyMe ${sec3}
FunctionEnd

(If you need multiple groups of mutually exclusive sections you could make the "if/orif" range check part of the helper macro instead)

Upvotes: 1

Related Questions