wizards/source/scriptforge/SF_Exception.xba      |    4 
 wizards/source/scriptforge/SF_Root.xba           |   14 
 wizards/source/scriptforge/po/ScriptForge.pot    |   19 +
 wizards/source/scriptforge/po/en.po              |   19 +
 wizards/source/scriptforge/python/scriptforge.py |    4 
 wizards/source/sfdialogs/SF_Dialog.xba           |  381 ++++++++++++++++++++++-
 wizards/source/sfdialogs/SF_DialogListener.xba   |   92 +++++
 7 files changed, 523 insertions(+), 10 deletions(-)

New commits:
commit 55477bf4fd3baa99f8b5d5686091d7613a1022c3
Author:     Jean-Pierre Ledure <j...@ledure.be>
AuthorDate: Wed Oct 12 16:09:11 2022 +0200
Commit:     Jean-Pierre Ledure <j...@ledure.be>
CommitDate: Wed Oct 12 17:52:59 2022 +0200

    ScriptForge - (SF_Dialog) new SetPageManager method
    
    The SetPageManager() method
    
    Define how the dialog displays pages.
    The page manager is an alternative to the direct use
    of the Page property of the dialog and dialogcontrol objects.
    
    The arguments define which controls are involved
    in the orchestration of the displayed pages.
    Possible options:
        - select a value in a list- or combobox
        - select an item in a group of radio buttons
        - select a button linked to a page
          placed side-by-side the buttons can simulate a tabbed interface
        - press a NEXT or BACK button like in many wizards
    Those options may be combined.
    The control updates will be synchronized.
    The method will set the actual page number to 1.
    Afterwards the Page property may be used to display any other page
    
    The SetPageManager() method is to be run
    only once and before the Execute() statement.
    If invoked several times, subsequent calls will be ignored.
    The method will define new listeners
    on the concerned controls, addressing generic routines.
    The corresponding events will be fired during the dialog execution.
    Preset events (in the Basic IDE) will be preserved
    and executed immediately AFTER the page change.
    The listeners will be removed at dialog termination.
    
    The implementation has next parts:
    1. Store the arguments in the Dialog instance
    2. Set appropriate listeners on involved controls
    3. Page change synchronizes the values in the involved controls
       (be it by user code or by page manager)
    4. Events triggered by listeners change page number
    
    The method is available both in Basic and Python contexts.
    This commit require the Dialog help page to be updated.
    
    Change-Id: I00a0212414f283102c73de4ceb488aa1aeddf746
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141257
    Tested-by: Jean-Pierre Ledure <j...@ledure.be>
    Reviewed-by: Jean-Pierre Ledure <j...@ledure.be>
    Tested-by: Jenkins

diff --git a/wizards/source/scriptforge/SF_Exception.xba 
b/wizards/source/scriptforge/SF_Exception.xba
index 572b0fb950a6..f752e054f2b5 100644
--- a/wizards/source/scriptforge/SF_Exception.xba
+++ b/wizards/source/scriptforge/SF_Exception.xba
@@ -125,6 +125,7 @@ Const DIALOGNOTFOUNDERROR           =       
&quot;DIALOGNOTFOUNDERROR&quot;
 Const DIALOGDEADERROR                  =       &quot;DIALOGDEADERROR&quot;
 Const CONTROLTYPEERROR                 =       &quot;CONTROLTYPEERROR&quot;
 Const TEXTFIELDERROR                   =       &quot;TEXTFIELDERROR&quot;
+Const PAGEMANAGERERROR                 =       &quot;PAGEMANAGERERROR&quot;
 
 &apos; SF_Database
 Const DBREADONLYERROR                  =       &quot;DBREADONLYERROR&quot;
@@ -1020,6 +1021,9 @@ Try:
                        Case TEXTFIELDERROR     &apos;  
SF_DialogControl.WriteLine(ControlName, DialogName)
                                sMessage = sLocation _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;TEXTFIELD&quot;, pvArgs(0), pvArgs(1))
+                       Case PAGEMANAGERERROR   &apos;  
SF_Dialog.SetPageManager(PilotsList, TabsList, WizardsList)
+                               sMessage = sLocation _
+                                       &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;PAGEMANAGER&quot;, pvArgs(0), pvArgs(1), 
pvArgs(2), pvArgs(3), pvArgs(4), pvArgs(5))
                        Case DBREADONLYERROR    &apos;  SF_Database.RunSql()
                                sMessage = sLocation _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;DBREADONLY&quot;, vLocation(2))
diff --git a/wizards/source/scriptforge/SF_Root.xba 
b/wizards/source/scriptforge/SF_Root.xba
index 4db0efb42c1d..8c9a0dbcf6be 100644
--- a/wizards/source/scriptforge/SF_Root.xba
+++ b/wizards/source/scriptforge/SF_Root.xba
@@ -991,6 +991,20 @@ Try:
                                                                        &amp;   
&quot;%1: An identifier\n&quot; _
                                                                        &amp;   
&quot;%2: An identifier&quot; _
                                        )
+       &apos;  SF_Dialog.SetPageManager
+                       .AddText(       Context := &quot;PAGEMANAGER&quot; _
+                                               , MsgId := &quot;The Page 
Manager could not be setup due to inconsistent arguments.\n\n&quot; _
+                                                                       &amp; 
&quot; %1 : « %2 »\n&quot; _
+                                                                       &amp; 
&quot; %3 : « %4 »\n&quot; _
+                                                                       &amp; 
&quot; %5 : « %6 »&quot; _
+                                               , Comment :=    &quot;SF_Dialog 
Page Manager setting\n&quot; _
+                                                                       &amp;   
&quot;%1: An identifier\n&quot; _
+                                                                       &amp;   
&quot;%2: A list of names separated by commas\n&quot; _
+                                                                       &amp;   
&quot;%3: An identifier\n&quot; _
+                                                                       &amp;   
&quot;%4: A list of names separated by commas\n&quot; _
+                                                                       &amp;   
&quot;%5: An identifier\n&quot; _
+                                                                       &amp;   
&quot;%6: A list of names separated by commas&quot; _
+                                       )
        &apos;  SF_Database.RunSql
                        .AddText(       Context := &quot;DBREADONLY&quot; _
                                                , MsgId := &quot;The database 
has been opened in read-only mode.\n&quot; _
diff --git a/wizards/source/scriptforge/po/ScriptForge.pot 
b/wizards/source/scriptforge/po/ScriptForge.pot
index 248d800c017c..894b9da3bbe0 100644
--- a/wizards/source/scriptforge/po/ScriptForge.pot
+++ b/wizards/source/scriptforge/po/ScriptForge.pot
@@ -14,7 +14,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: 
https://bugs.libreoffice.org/enter_bug.cgi?product=LibreOffice&bug_status=UNCONFIRMED&component=UI\n";
-"POT-Creation-Date: 2022-05-04 18:07:20\n"
+"POT-Creation-Date: 2022-10-12 15:07:35\n"
 "PO-Revision-Date: YYYY-MM-DD HH:MM:SS\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
@@ -926,6 +926,23 @@ msgid  ""
 "The requested method could not be executed."
 msgstr ""
 
+#. SF_Dialog Page Manager setting
+#. %1: An identifier
+#. %2: A list of names separated by commas
+#. %3: An identifier
+#. %4: A list of names separated by commas
+#. %5: An identifier
+#. %6: A list of names separated by commas
+#, kde-format
+msgctxt "PAGEMANAGER"
+msgid  ""
+"The Page Manager could not be setup due to inconsistent arguments.\n"
+"\n"
+" %1 : « %2 »\n"
+" %3 : « %4 »\n"
+" %5 : « %6 »"
+msgstr ""
+
 #. SF_Database when running update SQL statement
 #. %1: The concerned method
 #, kde-format
diff --git a/wizards/source/scriptforge/po/en.po 
b/wizards/source/scriptforge/po/en.po
index 248d800c017c..894b9da3bbe0 100644
--- a/wizards/source/scriptforge/po/en.po
+++ b/wizards/source/scriptforge/po/en.po
@@ -14,7 +14,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: 
https://bugs.libreoffice.org/enter_bug.cgi?product=LibreOffice&bug_status=UNCONFIRMED&component=UI\n";
-"POT-Creation-Date: 2022-05-04 18:07:20\n"
+"POT-Creation-Date: 2022-10-12 15:07:35\n"
 "PO-Revision-Date: YYYY-MM-DD HH:MM:SS\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
@@ -926,6 +926,23 @@ msgid  ""
 "The requested method could not be executed."
 msgstr ""
 
+#. SF_Dialog Page Manager setting
+#. %1: An identifier
+#. %2: A list of names separated by commas
+#. %3: An identifier
+#. %4: A list of names separated by commas
+#. %5: An identifier
+#. %6: A list of names separated by commas
+#, kde-format
+msgctxt "PAGEMANAGER"
+msgid  ""
+"The Page Manager could not be setup due to inconsistent arguments.\n"
+"\n"
+" %1 : « %2 »\n"
+" %3 : « %4 »\n"
+" %5 : « %6 »"
+msgstr ""
+
 #. SF_Database when running update SQL statement
 #. %1: The concerned method
 #, kde-format
diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index 5535760445cd..11022984286b 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -1815,6 +1815,10 @@ class SFDialogs:
         def Resize(self, left = -1, top = -1, width = -1, height = -1):
             return self.ExecMethod(self.vbMethod + self.flgHardCode, 'Resize', 
left, top, width, height)
 
+        def SetPageManager(self, pilotcontrols = '', tabcontrols = '', 
wizardcontrols = '', lastpage = 0):
+            return self.ExecMethod(self.vbMethod, 'SetPageManager', 
pilotcontrols, tabcontrols, wizardcontrols,
+                                   lastpage)
+
         def Terminate(self):
             return self.ExecMethod(self.vbMethod, 'Terminate')
 
diff --git a/wizards/source/sfdialogs/SF_Dialog.xba 
b/wizards/source/sfdialogs/SF_Dialog.xba
index 4a6d1ae7a380..daf63354c0bb 100644
--- a/wizards/source/sfdialogs/SF_Dialog.xba
+++ b/wizards/source/sfdialogs/SF_Dialog.xba
@@ -50,6 +50,7 @@ Option Explicit
 REM ================================================================== 
EXCEPTIONS
 
 Private Const DIALOGDEADERROR          =       &quot;DIALOGDEADERROR&quot;
+Private Const PAGEMANAGERERROR         =       &quot;PAGEMANAGERERROR&quot;
 
 REM ============================================================= PRIVATE 
MEMBERS
 
@@ -79,13 +80,35 @@ Private _Top                                As Long
 Private _Width                         As Long
 Private _Height                                As Long
 
+&apos; Page management
+Type _PageManager
+       ControlName As String                                   &apos; 
Case-sensitive name of control involved in page management
+       PageMgtType As Integer                                  &apos; One of 
the PILOTCONTROL, TABCONTROL, NEXTCONTROL, BACKCONTROL constants
+       PageNumber As Long                                              &apos; 
When &gt; 0, the page to activate for tab controls
+       ListenerType As Integer                                 &apos; One of 
the ITEMSTATECHANGED, ACTIONPERFORMED constants
+End Type
+
+Private _PageManagement                As Variant              &apos; Array of 
_PageManager objects, one entry by involved control
+Private _ItemListener          As Object               &apos; 
com.sun.star.awt.XItemListener
+Private _ActionListener                As Object               &apos; 
com.sun.star.awt.XActionListener
+Private _LastPage                      As Long                 &apos; When 
&gt; 0, the last page in a tabbed dialog
+
 &apos; Persistent storage for controls
 Private _ControlCache          As Variant              &apos; Array of control 
objects sorted like ElementNames of the Dialog model
 
 REM ============================================================ MODULE 
CONSTANTS
 
-Private Const OKBUTTON         = 1
-Private Const CANCELBUTTON     = 0
+&apos; Dialog usual buttons
+Private Const OKBUTTON                 = 1
+Private Const CANCELBUTTON             = 0
+
+&apos; Page management
+Private Const PILOTCONTROL             = 1
+Private Const TABCONTROL               = 2
+Private Const BACKCONTROL              = 3
+Private Const NEXTCONTROL              = 4
+Private Const ITEMSTATECHANGED = 1
+Private Const ACTIONPERFORMED  = 2
 
 REM ====================================================== 
CONSTRUCTOR/DESTRUCTOR
 
@@ -108,6 +131,10 @@ Private Sub Class_Initialize()
        _Top = -1
        _Width = -1
        _Height = -1
+       _PageManagement = Array()
+       Set _ItemListener = Nothing
+       Set _ActionListener = Nothing
+       _LastPage = 0
        _ControlCache = Array()
 End Sub                &apos;  SFDialogs.SF_Dialog Constructor
 
@@ -223,10 +250,12 @@ End Property      &apos;  
SFDialogs.SF_Dialog.OnMouseReleased (get)
 
 REM 
-----------------------------------------------------------------------------
 Property Get Page() As Variant
-&apos;&apos;&apos;     A dialog may have several pages that can be traversed 
by the user step by step. The Page property of the Dialog object defines which 
page of the dialog is active.
+&apos;&apos;&apos;     A dialog may have several pages that can be traversed 
by the user step by step.
+&apos;&apos;&apos;     The Page property of the Dialog object defines which 
page of the dialog is active.
 &apos;&apos;&apos;     The Page property of a control defines the page of the 
dialog on which the control is visible.
 &apos;&apos;&apos;     For example, if a control has a page value of 1, it is 
only visible on page 1 of the dialog.
-&apos;&apos;&apos;     If the page value of the dialog is increased from 1 to 
2, then all controls with a page value of 1 disappear and all controls with a 
page value of 2 become visible.
+&apos;&apos;&apos;     If the page value of the dialog is increased from 1 to 
2, then all controls with a page value of 1 disappear
+&apos;&apos;&apos;     and all controls with a page value of 2 become visible.
        Page = _PropertyGet(&quot;Page&quot;)
 End Property   &apos;  SFDialogs.SF_Dialog.Page (get)
 
@@ -703,6 +732,7 @@ Public Function Methods() As Variant
                                        , &quot;Execute&quot; _
                                        , &quot;GetTextsFromL10N&quot; _
                                        , &quot;Resize&quot; _
+                                       , &quot;SetPageManager&quot; _
                                        , &quot;Terminate&quot; _
                                        )
 
@@ -808,6 +838,118 @@ Catch:
        GoTo Finally
 End Function   &apos;  SF_Documents.SF_Dialog.Resize
 
+REM 
-----------------------------------------------------------------------------
+Public Function SetPageManager(Optional ByVal PilotControls As Variant _
+                                                                       , 
Optional ByVal TabControls As Variant _
+                                                                       , 
Optional ByVal WizardControls As Variant _
+                                                                       , 
Optional ByVal LastPage As variant _
+                                                                       ) As 
Boolean
+&apos;&apos;&apos;     Define how the dialog displays pages. The page manager 
is an alternative to the
+&apos;&apos;&apos;     direct use of the Page property of the dialog and 
dialogcontrol objects.
+&apos;&apos;&apos;
+&apos;&apos;&apos;     A dialog may have several pages that can be traversed 
by the user step by step.
+&apos;&apos;&apos;     The Page property of the Dialog object defines which 
page of the dialog is active.
+&apos;&apos;&apos;     The Page property of a control defines the page of the 
dialog on which the control is visible.
+&apos;&apos;&apos;     For example, if a control has a page value of 1, it is 
only visible on page 1 of the dialog.
+&apos;&apos;&apos;     If the page value of the dialog is increased from 1 to 
2, then all controls with a page value of 1 disappear
+&apos;&apos;&apos;     and all controls with a page value of 2 become visible.
+&apos;&apos;&apos;
+&apos;&apos;&apos;     The arguments define which controls are involved in the 
orchestration of the displayed pages.
+&apos;&apos;&apos;     Possible options:
+&apos;&apos;&apos;             - select a value in a list- or combobox
+&apos;&apos;&apos;             - select an item in a group of radio buttons
+&apos;&apos;&apos;             - select a button linked to a page - placed 
side-by-side the buttons can simulate a tabbed interface
+&apos;&apos;&apos;             - press a NEXT or BACK button like in many 
wizards
+&apos;&apos;&apos;     Those options may be combined. The control updates will 
be synchronized.
+&apos;&apos;&apos;     The method will set the actual page number to 1. 
Afterwards the Page property may be used to display any other page
+&apos;&apos;&apos;     
+&apos;&apos;&apos;     The SetPageManager() method is to be run only once and 
before the Execute() statement.
+&apos;&apos;&apos;     If invoked several times, subsequent calls will be 
ignored.
+&apos;&apos;&apos;     The method will define new listeners on the concerned 
controls, addressing generic routines.
+&apos;&apos;&apos;     The corresponding events will be fired during the 
dialog execution.
+&apos;&apos;&apos;     Preset events (in the Basic IDE) will be preserved and 
executed immediately AFTER the page change.
+&apos;&apos;&apos;     The listeners will be removed at dialog termination.
+&apos;&apos;&apos;
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             PilotControls: a comma-separated list of 
listbox, combobox or radiobutton controls
+&apos;&apos;&apos;                     For radio buttons, provide the first in 
the group
+&apos;&apos;&apos;             TabControls: a comma-separated list of button 
controls in ascending order
+&apos;&apos;&apos;             WizardControls: a comma-separated list of 2 
controls, a BACK button and a NEXT button
+&apos;&apos;&apos;             LastPage: the index of the last available page. 
Recommended when use of WizardControls
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             dialog.SetPageManager(PilotControls := 
&quot;aListBox,aComboBox&quot;)  &apos;  2 controls may cause page changes
+
+Dim bManager As Boolean                                &apos;  Return value
+Dim vControls As Variant                       &apos;  Array of involved 
controls
+Dim oControl As Object                         &apos;  A DialogControl object
+Dim i As Long
+Const cstPrefix = &quot;_SFTAB_&quot;          &apos;  Prefix of Subs to 
trigger when involved controls are clicked
+Const cstComma = &quot;,&quot;
+
+Const cstThisSub = &quot;SFDialogs.Dialog.SetPageManager&quot;
+Const cstSubArgs = &quot;[PilotControls=&quot;&quot;&quot;&quot;], 
[TabControls=&quot;&quot;&quot;&quot;], 
[WizardControls=&quot;&quot;&quot;&quot;]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bManager = False
+
+Check:
+       If IsMissing(PilotControls) Or IsEmpty(PilotControls) Then 
PilotControls = &quot;&quot;
+       If IsMissing(TabControls) Or IsEmpty(TabControls) Then TabControls = 
&quot;&quot;
+       If IsMissing(WizardControls) Or IsEmpty(WizardControls) Then 
WizardControls = &quot;&quot;
+       If IsMissing(LastPage) Or IsEmpty(LastPage) Then LastPage = 0
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(PilotControls, 
&quot;PilotControls&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(TabControls, 
&quot;TabControls&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(WizardControls, 
&quot;WizardControls&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(LastPage, 
&quot;LastPage&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+       End If
+       &apos;  Ignore the call if already done before
+       If UBound(_PageManagement) &gt;= 0 Then GoTo Finally
+
+Try:
+       &apos;  Common listeners to all involved controls
+       Set _ItemListener = CreateUnoListener(cstPrefix, 
&quot;com.sun.star.awt.XItemListener&quot;)
+       Set _ActionListener     = CreateUnoListener(cstPrefix, 
&quot;com.sun.star.awt.XActionListener&quot;)
+
+       &apos;  Register the arguments in the _PageManagement array, control by 
control
+       &apos;  Pilot controls
+       If Len(PilotControls) &gt; 0 Then
+               vControls = Split(PilotControls, cstComma)
+               For i = 0 To UBound(vControls)
+                       If Not _RegisterPageListener(Trim(vControls(i)), 
&quot;ListBox,ComboBox,RadioButton&quot;, PILOTCONTROL, 0, ITEMSTATECHANGED) 
Then GoTo Catch
+               Next i
+       End If
+       &apos;  Tab controls
+       If Len(TabControls) &gt; 0 Then
+               vControls = Split(TabControls, cstComma)
+               For i = 0 To UBound(vControls)
+                       If Not _RegisterPageListener(Trim(vControls(i)), 
&quot;Button&quot;, TABCONTROL, i + 1, ACTIONPERFORMED) Then GoTo Catch
+               Next i
+       End If
+       &apos;  Wizard controls
+       If Len(WizardControls) &gt; 0 Then
+               vControls = Split(WizardControls, cstComma)
+               For i = 0 To UBound(vControls)
+                       If Not _RegisterPageListener(Trim(vControls(i)), 
&quot;Button&quot;, Iif(i = 0, BACKCONTROL, NEXTCONTROL), 0, ACTIONPERFORMED) 
Then GoTo Catch
+               Next i
+       End If
+
+       &apos;  Set the initial page to 1
+       Page = 1
+       _LastPage = LastPage
+
+Finally:
+       SetPageManager = bManager
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       ScriptForge.SF_Exception.RaiseFatal(PAGEMANAGERERROR, 
&quot;PilotControls&quot;, PilotControls, &quot;TabControls&quot;, TabControls _
+                               , &quot;WizardControls&quot;, WizardControls)
+       GoTo Finally
+End Function   &apos;  SFDialogs.SF_Dialog.SetPageManager
+
 REM 
-----------------------------------------------------------------------------
 Public Function SetProperty(Optional ByVal PropertyName As Variant _
                                                                , Optional 
ByRef Value As Variant _
@@ -867,7 +1009,9 @@ Check:
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive() Then GoTo Finally
        End If
+
 Try:
+       _RemovePageListeners()
        _DialogControl.dispose()
        Set _DialogControl = Nothing
        SF_Register._CleanCacheEntry(_CacheIndex)
@@ -886,6 +1030,72 @@ End Function      &apos;  SFDialogs.SF_Dialog.Terminate
 
 REM =========================================================== PRIVATE 
FUNCTIONS
 
+REM 
-----------------------------------------------------------------------------
+Private Function _FindRadioSiblings(ByVal psRadioButton As String) As String
+&apos;&apos;&apos;     Given the name of the first radio button of a group, 
return all the names of the group
+&apos;&apos;&apos;     For dialogs, radio buttons are considered of the same 
group
+&apos;&apos;&apos;     when their tab indexes are contiguous.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             psRadioButton: the exact name of the 1st radio 
button of the group
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A comma-separated list of the names of the 1st 
and the next radio buttons
+&apos;&apos;&apos;             belonging to the same group in their tabindex 
order.
+&apos;&apos;&apos;             The input argument when not a radio button
+
+
+Dim sList As String                            &apos;  Return value
+Dim oRadioControl As Object            &apos;  DialogControl instance 
corresponding with the argument
+Dim oControl As Object                 &apos;  DialogControl instance
+Dim vRadioList As Variant              &apos;  Array of all radio buttons 
having a tab index &gt; tab index of argument
+                                                               &apos;  1st 
column = name of radio button, 2nd = its tab index
+Dim iRadioTabIndex As Integer  &apos;  Tab index of the argument
+Dim iTabIndex As Integer               &apos;  Any tab index
+Dim vControlNames As Variant   &apos;  Array of control names
+Dim sControlName As String             &apos;  A single item in vControlNames()
+Dim i As Long
+Const cstComma = &quot;,&quot;
+
+Check:
+       On Local Error GoTo Catch
+       sList = psRadioButton
+       vRadioList = Array()
+
+Try:
+       Set oRadioControl = Controls(psRadioButton)
+       If oRadioControl.ControlType &lt;&gt; &quot;RadioButton&quot; Then GoTo 
Finally
+       iRadioTabIndex = oRadioControl._ControlModel.Tabindex
+       vRadioList = ScriptForge.SF_Array.AppendRow(vRadioList, 
Array(psRadioButton, iRadioTabIndex))
+
+       &apos;  Scan all controls. Store radio buttons having tab index &gt; 
1st radio button
+       vControlNames = Controls()
+       For Each sControlName In vControlNames
+               Set oControl = Controls(sControlName)
+               With oControl
+                       If .Name &lt;&gt; psRadioButton Then
+                               If .ControlType = &quot;RadioButton&quot; Then
+                                       iTabIndex = ._ControlModel.Tabindex
+                                       If iTabIndex &gt; iRadioTabIndex Then
+                                               vRadioList = 
ScriptForge.SF_Array.AppendRow(vRadioList, Array(.Name, iTabIndex))
+                                       End If
+                               End If
+                       End If
+               End With
+       Next sControlName
+
+       vRadioList = ScriptForge.SF_Array.SortRows(vRadioList, 1)
+       &apos;  Retain contiuous tav indexes
+       For i = 1 To UBound(vRadioList, 1)      &apos;  First row = argument
+               If vRadioList(i, 1) = iRadioTabIndex + i Then sList = sList 
&amp; cstComma &amp; vRadioList(i, 0)
+       Next i
+
+Finally:
+       _FindRadioSiblings = sList
+       Exit Function
+Catch:
+       sList = psRadioButton
+       GoTo Finally
+End Function   &apos;  SFDialogs.SF_Dialog._FindRadioSiblings
+
 REM 
-----------------------------------------------------------------------------
 Public Function _GetEventName(ByVal psProperty As String) As String
 &apos;&apos;&apos;     Return the LO internal event name derived from the SF 
property name
@@ -986,6 +1196,61 @@ Catch:
        GoTo Finally
 End Function   &apos;  SFDialogs.SF_Dialog._IsStillAlive
 
+REM 
-----------------------------------------------------------------------------
+Private Sub _JumpToPage(ByVal plPage As Long)
+&apos;&apos;&apos;     Called when the Page property is set to a new value
+&apos;&apos;&apos;     The rules defined in the _pageManagement array are 
applied here
+
+Dim oPageManager As Object             &apos;  A single entry in 
_PageManagement of type _PageManager
+Dim oControl As Object                 &apos;  DialogControl instance
+Dim lPage As Long                              &apos;  A dialog page number
+
+Check:
+       On Local Error GoTo Finally
+&apos; ControlName As String                                   &apos; 
Case-sensitive name of control involved in page management
+&apos; PageMgtType As Integer                                  &apos; One of 
the PILOTCONTROL, TABCONTROL, BACKCONTROL, NEXTCONTROL constants
+&apos; PageNumber As Long                                              &apos; 
When &gt; 0, the page to activate for tab controls
+&apos; ListenerType As Integer                                 &apos; One of 
the ITEMSTATECHANGED, ACTIONPERFORMED constants
+
+       If plPage &lt;= 0 Or (_LastPage &gt; 0 And plPage &gt; _LastPage) Then 
Exit Sub
+       If UBound(_PageManagement) &lt; 0 Then Exit Sub
+
+Try:
+       &apos;  Controls listed in the array must be synchronized with the page 
#
+       &apos;          Listboxes and comboboxes must be set to the 
corresponding value
+       &apos;          The right radio button must be selected
+       &apos;          One corresponding button must be dimmed, other must be 
enabled
+       &apos;          The Next button must be dimmed when last page othewide 
enabled
+       For Each oPageManager In _PageManagement
+               With oPageManager
+               lPage = .PageNumber
+               Set oControl = Controls(.ControlName)
+                       With oControl
+                               Select Case .ControlType
+                                       Case &quot;ListBox&quot;, 
&quot;ComboBox&quot;
+                                               If plPage &lt;= .ListCount Then 
.ListIndex = plPage - 1 &apos;  ListIndex is zero-based
+                                       Case &quot;RadioButton&quot;
+                                               .Value = ( plPage = lPage )
+                                       Case &quot;Button&quot;
+                                               Select Case 
oPageManager.PageMgtType
+                                                       Case TABCONTROL
+                                                               .Value = ( 
plPage = lPage )
+                                                       Case BACKCONTROL
+                                                               .Enabled = ( 
plPage &lt;&gt; 1 )
+                                                       Case NEXTCONTROL
+                                                               .Enabled = ( 
_LastPage = 0 Or plPage &lt; _LastPage )
+                                                       Case Else
+                                               End Select
+                                       Case Else
+                               End Select
+                       End With
+               End With
+       Next oPageManager
+
+Finally:
+       Exit Sub
+End Sub                        &apos;  SFDialogs.SF_Dialog._JumpToPage
+
 REM 
-----------------------------------------------------------------------------
 Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
 &apos;&apos;&apos;     Return the value of the named property
@@ -1079,7 +1344,11 @@ Const cstSubArgs = &quot;Value&quot;
                        If oSession.HasUNOProperty(_DialogModel, 
&quot;Height&quot;) Then _DialogModel.Height = pvValue
                Case UCase(&quot;Page&quot;)
                        If Not ScriptForge.SF_Utils._Validate(pvValue, 
&quot;Page&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
-                       If oSession.HasUNOProperty(_DialogModel, 
&quot;Step&quot;) Then _DialogModel.Step = CLng(pvValue)
+                       If oSession.HasUNOProperty(_DialogModel, 
&quot;Step&quot;) Then
+                               _DialogModel.Step = CLng(pvValue)
+                               &apos;  Execute the page manager instructions
+                               _JumpToPage(pvValue)
+                       End If
                Case UCase(&quot;Visible&quot;)
                        If Not ScriptForge.SF_Utils._Validate(pvValue, 
&quot;Visible&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
                        If oSession.HasUnoMethod(_DialogControl, 
&quot;setVisible&quot;) Then _DialogControl.setVisible(pvValue)
@@ -1098,6 +1367,108 @@ Catch:
        GoTo Finally
 End Function   &apos;  SFDialogs.SF_Dialog._PropertySet
 
+REM 
-----------------------------------------------------------------------------
+Private Function _RegisterPageListener(ByVal psControlName As String _
+                                                                               
        , ByVal psControlTypes As String _
+                                                                               
        , ByVal piMgtType As Integer _
+                                                                               
        , ByVal plPageNumber As Long _
+                                                                               
        , ByVal piListener As Integer _
+                                                                               
        ) As Boolean
+&apos;&apos;&apos;     Insert a new entry in the _PageManagemnt array when 1st 
argument is a listbox, a combobox or a button
+&apos;&apos;&apos;     or insert a new entry in the _PageManagemnt array by 
radio button in the same group as the 1st argument
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             psControlName: name of the involved control
+&apos;&apos;&apos;             psControlTypes: comma-separated list of allowad 
control types
+&apos;&apos;&apos;             piMgtType: one of the PILOTCONTROL, TABCONTROL, 
BACKCONTROL, NEXTCONTROL constants
+&apos;&apos;&apos;             plPageNumber: when &gt; 0 the page to jump to 
when control is clicked
+&apos;&apos;&apos;             piListener: one of the ACTIONPERFORMED, 
ITEMSTATECHANGED constants
+
+Dim bRegister As Boolean                       &apos;  Return value
+Dim oControl As Object                         &apos;  A DialogControl object
+Dim oControl2 As Object                                &apos;  An alternative 
DialogControl object for radio buttons
+Dim vControls As Variant                       &apos;  Array of involved 
controls - mostly 1 item, more when radio button
+Dim oPageManager As Object                     &apos;  Type _PageManager
+Dim bRadio As Boolean                          &apos;  True when argument is a 
radio button
+Dim sName As String                                    &apos;  Control name
+Dim i As Long
+
+Check:
+       On Local Error GoTo Catch
+       bRegister = False
+
+Try:
+       Set oControl = Controls(psControlName)
+       With oControl
+       &apos;  Check the type of control otherwise return False
+               If InStr(psControlTypes, .ControlType) = 0 Then GoTo Catch
+               &apos;  Are there siblings ? Siblings are returned as a 
comma-separated list of names
+               bRadio = ( .ControlType = &quot;RadioButton&quot;)
+               If bRadio Then vControls = Split(_FindRadioSiblings(.Name), 
&quot;,&quot;) Else vControls = Array(.Name)
+               &apos;  Several loops when radio buttons
+               For i = 0 To UBound(vControls)
+                       sName = vControls(i)
+                       &apos;  Prepare the next entry in the _PageManagement 
array
+                       Set oPageManager = New _PageManager
+                       With oPageManager
+                               .ControlName = sName
+                               .PageMgtType = piMgtType
+                               .PageNumber = Iif(bRadio, i + 1, plPageNumber)
+                               .ListenerType = piListener
+                       End With
+                       _PageManagement = 
ScriptForge.SF_Array.Append(_PageManagement, oPageManager)
+                       &apos;  Activate the listener
+                       &apos;  Use alternative control for radio buttons &gt; 
first
+                       If i = 0 Then Set oControl2 = oControl Else Set 
oControl2 = Controls(sName)
+                       With oControl2
+                               If piListener = ACTIONPERFORMED Then
+                                       
._ControlView.addActionListener(_ActionListener)
+                               ElseIf piListener = ITEMSTATECHANGED Then
+                                       
._ControlView.addItemListener(_ItemListener)
+                               End If
+                       End With
+               Next i
+       End With
+
+       bRegister = True
+                       
+Finally:
+       _RegisterPageListener = bRegister
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDialogs.SF_Dialog._RegisterPageListener
+
+REM 
-----------------------------------------------------------------------------
+Private Sub _RemovePageListeners()
+&apos;&apos;&apos;     Executed at dialog termination to drop at once all 
listeners set by the page manager
+
+Dim oPageManager As Object             &apos;  Item of _PageManagement array 
of _PageManager type
+Dim oControl As Object                 &apos;  DialogControl instance
+Dim i As Long
+
+       On Local Error GoTo Finally             &apos;  Never interrupt
+
+Try:
+       &apos;  Scan the _PageManagement array containing the actual settings 
of the page manager
+       For Each oPageManager In _PageManagement
+               With oPageManager
+                       If .ListenerType &gt; 0 Then
+                               Set oControl = Controls(.ControlName)
+                               If .ListenerType =  ACTIONPERFORMED Then
+                                       
oControl._ControlView.removeActionListener(_ActionListener)
+                               ElseIf .ListenerType = ITEMSTATECHANGED Then
+                                       
oControl._ControlView.addItemListener(_ItemListener)
+                               End If
+                       End If
+               End With
+       Next oPageManager
+
+       Set _ActionListener = Nothing
+       Set _ItemListener = Nothing
+
+Finally:
+       Exit Sub        
+End Sub                        &apos;  SFDialogs.SF_Dialog._RemovePageListeners
 REM 
-----------------------------------------------------------------------------
 Private Function _Repr() As String
 &apos;&apos;&apos;     Convert the Model instance to a readable string, 
typically for debugging purposes (DebugPrint ...)
diff --git a/wizards/source/sfdialogs/SF_DialogListener.xba 
b/wizards/source/sfdialogs/SF_DialogListener.xba
index 0f324b60963f..25634b3d7107 100644
--- a/wizards/source/sfdialogs/SF_DialogListener.xba
+++ b/wizards/source/sfdialogs/SF_DialogListener.xba
@@ -16,14 +16,20 @@ Option Explicit
 &apos;&apos;&apos;             which cannot be defined with the Basic IDE
 &apos;&apos;&apos;
 &apos;&apos;&apos;             Concerned events:
-&apos;&apos;&apos;                     TreeControl control type
+&apos;&apos;&apos;                     TreeControl control type, prefix = 
_SFEXP_
 &apos;&apos;&apos;                     -----------
 &apos;&apos;&apos;                             The OnNodeSelected event, 
triggered when a user selects a node
 &apos;&apos;&apos;                                     A typical action is to 
display additional info about the selected item elsewhere in the dialog
 &apos;&apos;&apos;                             The OnNodeExpanded event, 
triggered when a user clicks on the expansion symbol
 &apos;&apos;&apos;                                     A typical action is to 
create dynamically a subnode or a subtree below the expanded item
 &apos;&apos;&apos;
-&apos;&apos;&apos;             The described events are processed thru UNO 
listeners
+&apos;&apos;&apos;                     PageManager facility, prefix = _SFTAB_
+&apos;&apos;&apos;                     -----------
+&apos;&apos;&apos;                             Depending on the piloting 
control(s), next event types are implemented
+&apos;&apos;&apos;                                     XActionListener: for 
buttons
+&apos;&apos;&apos;                                     XItemListener: for 
listboxes, comboboxes and radio buttons
+&apos;&apos;&apos;                                     
+&apos;&apos;&apos;                     The described events are processed thru 
UNO listeners
 &apos;&apos;&apos;
 
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
 
@@ -31,7 +37,7 @@ REM 
================================================================= DEFINITION
 
 REM ================================================================== 
EXCEPTIONS
 
-REM ============================================================== PUBLIC 
METHODS
+REM ================================================ PUBLIC METHODS 
(TREECONTROL)
 
 REM 
-----------------------------------------------------------------------------
 Public Sub _SFEXP_requestChildNodes(Optional ByRef poEvent As Object)
@@ -107,6 +113,86 @@ End Sub
 Sub _SFSEL_disposing(ByRef poEvent As Object)
 End Sub
 
+REM ============================================ PUBLIC METHODS (PAGE 
MANAGEMENT)
+
+REM 
-----------------------------------------------------------------------------
+Public Sub _SFTAB_actionPerformed(Optional ByRef poEvent As Object)
+&apos;&apos;&apos;     Event triggered by a button configured through the 
dialog page manager
+&apos;&apos;&apos;     Buttons may be of type TABCONTROL, BACKCONTROL or 
NEXTCONTROL
+
+Dim oControl As Object                 &apos;  The DialogControl instance 
having caused the event
+Dim sName As String                            &apos;  Control name
+Dim oDialog As Object                  &apos;  The parent Dialog instance
+Dim oPageManager As Object             &apos;  An entry in 
dialog._PageManagement
+Const TABCONTROL               = 2
+Const BACKCONTROL              = 3
+Const NEXTCONTROL              = 4
+
+Check:
+       On Local Error GoTo Finally             &apos;  Never interrupt !!
+       Set oControl = CreateScriptService(&quot;DialogEvent&quot;, poEvent)
+       If IsNull(oControl) Then GoTo Finally
+
+Try:
+       Set oDialog = oControl.Parent
+       With oDialog
+               sName = oControl.Name
+               &apos;  Find entry in page manager settings
+               For Each oPageManager In ._PageManagement
+                       If oPageManager.ControlName = sName Then
+                               Select Case oPageManager.PageMgtType
+                                       Case TABCONTROL         :       .Page = 
oPageManager.PageNumber
+                                       Case BACKCONTROL        :       .Page = 
.Page - 1
+                                       Case NEXTCONTROL        :       .Page = 
.Page + 1
+                                       Case Else
+                               End Select
+                               Exit For
+                       End If
+               Next oPageManager
+       End With
+
+Finally:
+       Exit Sub
+End Sub
+
+REM 
-----------------------------------------------------------------------------
+Public Sub _SFTAB_itemStateChanged(Optional ByRef poEvent As Object)
+&apos;&apos;&apos;     Event triggered by a listbox, combobox or radiobutton 
configured through the dialog page manager
+&apos;&apos;&apos;     Buttons are of type PILOTCONTROL
+
+Dim oControl As Object                 &apos;  The DialogControl instance 
having caused the event
+Dim sName As String                            &apos;  Control name
+Dim oDialog As Object                  &apos;  The parent Dialog instance
+Dim oPageManager As Object             &apos;  An entry in 
dialog._PageManagement
+Dim lPage As Long                              &apos;  Actual page number
+
+Check:
+       On Local Error GoTo Finally             &apos;  Never interrupt !!
+       Set oControl = CreateScriptService(&quot;DialogEvent&quot;, poEvent)
+       If IsNull(oControl) Then GoTo Finally
+
+Try:
+       Set oDialog = oControl.Parent
+       With oDialog
+               sName = oControl.Name
+               &apos;  Find entry in page manager settings
+               For Each oPageManager In ._PageManagement
+                       If oPageManager.ControlName = sName Then
+                               lPage = oPageManager.PageNumber
+                               If lPage = 0 Then .Page = oControl.ListIndex + 
1 Else .Page = lPage
+                               Exit For
+                       End If
+               Next oPageManager
+       End With
+
+Finally:
+       Exit Sub
+End Sub
+
+REM 
-----------------------------------------------------------------------------
+Public Sub _SFTAB_disposing(Optional ByRef poEvent As Object)
+End Sub
+
 REM ============================================================= PRIVATE 
METHODS
 
 REM ============================================ END OF 
SFDIALOGS.SF_DIALOGLISTENER

Reply via email to