Archive: .onNextPage / forcing selection


.onNextPage / forcing selection
  below is my hack to warn a user and select all components (there are 4) if they unselect them all and attempt to install.

is this the right way to do it? it works, but i can tell by doing a mb_ok that it's doing this literally EVERY NEXT PAGE.

i also observed when i would print the values of $0/$1/$2/$3 if the components were selected they would yield 3/5/5/1 respectively. what is with the different values?

while my solution works, it is not elegant in the fact that it warns the user, they click ok, and then their screen shows all their options unselected - but they're actually all forcefully selected. going back a screen and returning will show this. right now a developer install has all 4 components selected. if they unselect all 4 and attempt to install, it warns them, then puts them back at the component selection screen - with all the checkboxes visibly unchecked and 'custom' selected as the install type.

so...

what's with the numbers?
is this the right way to do this?
if this is the right way to do this, how do i 'refresh' the screen to show the components have all been forcefully selected?


onNextPage

SectionGetFlags 1$0
SectionGetFlags 2$1
SectionGetFlags 3$2
SectionGetFlags 4$3
IntCmp 0$0 end unselected1 end
unselected1:
IntCmp 0 $1 end unselected2 end
unselected2:
IntCmp 0 $2 end unselected3 end
unselected3:
IntCmp 0 $3 end unselected4 end
unselected4:
MessageBox MB_OK|MB_ICONSTOP "You must select at least 1 component!"
SectionSetFlags 1 0x80000000
SectionSetFlags 2 0x80000000
SectionSetFlags 3 0x80000000
SectionSetFlags 4 0x80000000
abort 0
end:
>FunctionEnd
>

The right way to do it is using .onSelChange. There is an example in the archive: http://nsis.sourceforge.net/archive/...instances=0,11.

As for the numbers, do you have more then one installation type (InstType)? If you do then the section flags in NSIS 1.98 are composed from install types too. Every install type gets a bit and it's on if the section is in that install type.


i had actually transplanted the info using http://forums.winamp.com/showthread....586#post582586 and http://nsis.sourceforge.net/archive/...instances=0,11

unfortunately, i lack the aptitude to figure out how to modify your initial post to suit my needs. i am not a programmer, and i have no mathematics background. the intop & and intop | are totally lost on me, but i suspect that even if i did understand the operations the rest of it wouldn't make sense.

while a handout would be nice, i'm not expecting one, and my solution does 'work' for now. it is a situation that will only arise when somebody actually unselects everything and attempts to proceed.


The problem with your code is that you didn't check that .onNextPage is called after the components page (needs to be counted, example in Contrib\InstallOptions\test.nsi) and that you change the selection and then abort the page moving. NSIS 1.98 doesn't support the latter as you have noticed, if you just warn and not set it should be OK.


i was reticent about switching to 2.0 simply because of the issue documented at http://forums.winamp.com/showthread....047#post827047 , but that now appears to be resolved.

after disabling enabledbitmap/disabledbitmap and enabled xpstyle everything looks nice and works the same (minus the .onnextpage, which appears to have been deprecated). i'll try mucking around with it.


The Pages section in the docs should you you replace .onNextPage.
Before you ask, there is no way to abort the moving to another page currently. It will be implemented sometime before the final version of NSIS 2.


ok, so i SHOULDN'T switch to nsis2 then?


If you want to display a message box if the user selected non of them, then no. You can always use a variant of the one-section example to force the user to select a minimum of one section if you do want to use 2.


by simply importing the nsis2 'must choose one' code, it's complaining that the sec* variables are undefined
when i try to compile: "unknown variable "{sec1}" detected, ignoring

below is my main body nsi. the copied stuff is included via static.nsi

!include defaults.nsi
!include static.nsi
!include functions.nsi

Section -
Call ExtractHelpers
Call CheckForPreviousInstallation
Call CheckForValidOS
Call EvalSilentInstall
Call DeleteHelpers
SectionEnd

Section "Hivemind Service" sec1
SectionIn 1 2
Call ExtractHelpers
!insertmacro ExtractServices
Call InstallServices
Call TestServices
Call AskStartHiveNow
Call UpdateRuntime
Call AddToPath
Call DeleteHelpers
SectionEnd

Section "Administration Utilities" sec2
SectionIn 1 3
!insertmacro ExtractUtils
SectionEnd

Section "Documentation" sec3
SectionIn 1 3
!insertmacro ExtractDocs
SectionEnd

Section "Software Development Kit" sec4
SectionIn 1
!insertmacro ExtractSDK
SectionEnd

Section ""
Call CreateUninstaller
Call RebootIfNeeded
SectionEnd

Section Uninstall
Call un.InstallWarning
Call un.ExtractHelpers
Call un.InstallServices
Call un.InstallAll
Call un.DeleteHelpers
SectionEnd


As sec1, sec2, etc. are defines, you can't use them before they are defined in the Section statement. Therefore the section control code must come after the sections code.


sorry about all this hassle...

okay, so i put the stuff in stuff.nsi and i included it at the bottom of my main nsi

everything compiles fine now, but it doesn't appear to work.

i put a messagebox $1 in onselchange before sectiongetflags $1 $0, and it yields '1' every time.

isn't the sectiongetflags pulling from section $1, which is defined in oninit's initial strcpy? how is it passing the value of $1 from one function to another? i thought these were independent to the functions.

at any rate, $1 is constantly 1 in my situation.


Please attach the script (don't copy it to the thread, it's getting too big) and I will have a look at it when I get back tomorrow.


attached. thanks!


I should have probably told you that the section flags values have changed too... The new ones are:


define SF_SELECTED   1

>!define SF_SUBSEC 2
>!define SF_SUBSECEND 4
>!define SF_BOLD 8
>!define SF_RO 16
>!define SF_EXPAND 32

>!define SECTION_OFF 0xFFFFFFFE
>

indeed, that makes quite a difference

almost there, but not quite...

the installer now starts the component page with sec1 (XXX service) unchecked and the default install mode as 'custom' - the rest are checked. i can toggle sec2/sec3/sec4 but clicking on sec1 yields nothing.

judging by the size estimate, sec1 is PERMANENTLY unselected. any ideas? while i'm using the example that had one required section and 4 toggles, i only have those 4 toggles, named appropriately. i would think the absence of the required section wouldn't cause anything.


OK, as you are not the first to ask this I have added this to the example:

This example demonstrates how to control section selection It allows only one of the four optional section to be selected at any given time.

Please note that the initial value will not be what you expect it to be if you are are using InstType because InstType is taken into consideration after the .onInit, where the initial state is set, executes.
To use this code with InstType you will either have to specify you first InstType to match the initial value you set in .onInit (only StrCpy $1 ${sec1} is important in this case because the other set the section and that will be done by InstType), or set the initial section selection from .onSelChange when it is called for the first time.