Archive: Mutually Exclusive Options problem.


Mutually Exclusive Options problem.
  Almost done with my Installer, but have been stuck on one problem which I've been unable to solve.

I have 3 option groups with 2 mutually exclusive options each. Now this is where it gets confusing.

If the Top option in each group is selected (Sec2, Sec4, Sec6) by the user, then the user can change between options in any other of the 3 groups by single clicking between each selection, as one would expect. However, if the bottom option in any group is selected (Sec1, Sec3, Sec5) then the user has to unselect the selected option before selecting another, as it locks and wont allow it to change. So it works one way, but not the other.



onSelChange

Push$0

>;OptionGroup1
StrCmp $R9${Sec1} check_Sec1
SectionGetFlags${Sec1} $0
IntOp$0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 OptionGroup1Done OptionGroup1Done
StrCpy $R9${Sec1}
SectionGetFlags ${Sec2} $0
IntOp$0 $0 & ${SECTION_OFF}
SectionSetFlags ${Sec2} $0

Goto OptionGroup1Done

check_Sec1:

SectionGetFlags ${Sec2} $0
IntOp$0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 OptionGroup1Done OptionGroup1Done
StrCpy $R9${Sec2}
SectionGetFlags ${Sec1} $0
IntOp$0 $0 & ${SECTION_OFF}
SectionSetFlags ${Sec1} $0

OptionGroup1Done:

;OptionGroup2
StrCmp $R9${Sec3} check_Sec3
SectionGetFlags${Sec3} $0
IntOp$0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 OptionGroup2Done OptionGroup2Done
StrCpy $R9${Sec3}
SectionGetFlags ${Sec4} $0
IntOp$0 $0 & ${SECTION_OFF}
SectionSetFlags ${Sec4} $0

Goto OptionGroup2Done

check_Sec3:

SectionGetFlags ${Sec4} $0
IntOp$0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 OptionGroup2Done OptionGroup2Done
StrCpy $R9${Sec4}
SectionGetFlags ${Sec3} $0
IntOp$0 $0 & ${SECTION_OFF}
SectionSetFlags ${Sec3} $0

OptionGroup2Done:

;OptionGroup3
StrCmp $R9${Sec5} check_Sec5
SectionGetFlags${Sec5} $0
IntOp$0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 OptionGroup3Done OptionGroup3Done
StrCpy $R9${Sec5}
SectionGetFlags ${Sec6} $0
IntOp$0 $0 & ${SECTION_OFF}
SectionSetFlags ${Sec6} $0

Goto OptionGroup3Done

check_Sec5:

SectionGetFlags ${Sec6} $0
IntOp$0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 OptionGroup3Done OptionGroup3Done
StrCpy $R9${Sec6}
SectionGetFlags ${Sec5} $0
IntOp$0 $0 & ${SECTION_OFF}
SectionSetFlags ${Sec5} $0

OptionGroup3Done:

Pop $0
FunctionEnd
>

There are a couple critical pieces missing from this:
http://nsis.sourceforge.net/Mutually_Exclusive_Sections

First, in .oninit you have to memorize current selections. I personally would use a user var instead of register R9.

Second, you use that in selection onchange. You are missing this line from the example at the beginning of .onSelChange:

  StrCmp $R9 ${sec1} check_sec1


You might want to consider using the RadioButtons macros, as it might make this a lot easier, especially if you get more than 2 items in a group:
http://nsis.sourceforge.net/RadioButtons

Anyway, I just tested this code:

Name "Example1"

; The file to write
OutFile "example1.exe"

!include "Sections.nsh"
!include "LogicLib.nsh"

; The default installation directory
InstallDir $DESKTOP\Example1

Page components
Page instfiles

Section "1" Sec1

SectionEnd ; end the section
Section /o "2" Sec2

SectionEnd ; end the section
Section "3" Sec3

SectionEnd ; end the section
Section /o "4" Sec4

SectionEnd ; end the section
Section "5" Sec5

SectionEnd ; end the section
Section /o "6" Sec6

SectionEnd ; end the section



Var /GLOBAL WasSelectedGrpA
Var /GLOBAL WasSelectedGrpB
Var /GLOBAL WasSelectedGrpC
Function .oninit
;this is the critical piece you were missing, you have to memorize who is initial selected for each
;mutually exclusive group, otherwise when you get to .onSelChange, you will have 2 selected sections
;and won't know which one to deselect because you don't know which is the newly selected

StrCpy $WasSelectedGrpA ${Sec1}
StrCpy $WasSelectedGrpB ${Sec3}
StrCpy $WasSelectedGrpC ${Sec5}
FunctionEnd

Function .onSelChange

;If both items are selected, then one of them must be deselected
${If} ${SectionIsSelected} ${Sec1}
${AndIf} ${SectionIsSelected} ${Sec2}
;unselect old selection
!insertmacro UnselectSection $WasSelectedGrpA
${EndIf}

;memorize current selection
${If} ${SectionIsSelected} ${Sec1}
StrCpy $WasSelectedGrpA ${Sec1}
${ElseIf} ${SectionIsSelected} ${Sec2}
StrCpy $WasSelectedGrpA ${Sec2}
${EndIf}

${If} ${SectionIsSelected} ${Sec3}
${AndIf} ${SectionIsSelected} ${Sec4}
!insertmacro UnselectSection $WasSelectedGrpB
${EndIf}
${If} ${SectionIsSelected} ${Sec3}
StrCpy $WasSelectedGrpB ${Sec3}
${ElseIf} ${SectionIsSelected} ${Sec4}
StrCpy $WasSelectedGrpB ${Sec4}
${EndIf}


${If} ${SectionIsSelected} ${Sec5}
${AndIf} ${SectionIsSelected} ${Sec6}
!insertmacro UnselectSection $WasSelectedGrpC
${EndIf}
${If} ${SectionIsSelected} ${Sec5}
StrCpy $WasSelectedGrpC ${Sec5}
${ElseIf} ${SectionIsSelected} ${Sec6}
StrCpy $WasSelectedGrpC ${Sec6}
${EndIf}


FunctionEnd

Thankyou again for dumbing it down for me :P

Again that makes it much easier and works perfectly. I'm sure the users will be happy to get this next week :)

I appreciate the help.