ScriptForge (Dialogs) add the TabPageContainer control

TabPageContainer-type controls are not supported
by the Basic IDE, while they are visually
attractive.

The current commit proposes the insertion
of such a control by code
  dialog.CreateTabPageContainer(..., tabheaders, ...)
where tabheaders is simply an array of strings.

The originality of the approach is here to make
the link with dialog pages very easy:
  OnTabSelected: define the script to trigger
                 when a tab is selected
  Value: get or set the actual tab

Additionally, the TabPageContainer control is
associated with the SetPageManager() method.

Example on
https://gitlab.com/LibreOfficiant/scriptforge/-/snippets/4823173

The function is available for Basic and Python user scripts.

The documentation will need to be updated accordingly.

Change-Id: I7a1644344cad5f3739055f7e1eec69310ffa019c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182697
Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Tested-by: Jenkins
This commit is contained in:
Jean-Pierre Ledure
2025-03-09 17:32:59 +01:00
parent cb42d9e8a5
commit 05d2701e3b
6 changed files with 308 additions and 51 deletions

View File

@@ -2139,6 +2139,9 @@ class SFDialogs:
return self.ExecMethod(self.vbMethod, 'CreateTableControl', controlname, place, border,
rowheaders, columnheaders, scrollbars, gridlines)
def CreateTabPageContainer(self, controlname, place, tabheaders, border = '3D'):
return self.ExecMethod(self.vbMethod, 'CreateTabPageContainer', controlname, place, tabheaders, border)
def CreateTextField(self, controlname, place, border = '3D', multiline = False,
maximumlength = 0, passwordcharacter = ''):
return self.ExecMethod(self.vbMethod, 'CreateTextField', controlname, place, border,
@@ -2226,14 +2229,14 @@ class SFDialogs:
OnFocusLost = 2, OnItemStateChanged = 2, OnKeyPressed = 2,
OnKeyReleased = 2, OnMouseDragged = 2, OnMouseEntered = 2,
OnMouseExited = 2, OnMouseMoved = 2, OnMousePressed = 2,
OnMouseReleased = 2, OnNodeExpanded = 2, OnNodeSelected = 2,
OnMouseReleased = 2, OnNodeExpanded = 2, OnNodeSelected = 2, OnTabSelected = 2,
OnTextChanged = 2, Page = 2, Parent = 0, Picture = 2,
RootNode = 0, RowSource = 2, TabIndex = 2, Text = 0, TipText = 2,
TripleState = 2, URL = 2, Value = 3, Visible = 2, Width = 2,
X = 2, Y = 2, XControlModel = 0, XControlView = 0,
XGridColumnModel = 0, XGridDataModel = 0, XTreeDataModel = 0)
# Root related properties do not start with X and, nevertheless, return a UNO object
# Root or node related properties do not start with X and, nevertheless, return a UNO object
@property
def CurrentNode(self):
return self.EXEC(self.objectreference, self.vbGet + self.flgUno, 'CurrentNode')

View File

@@ -3886,6 +3886,36 @@ class SFDialogs:
"""
...
def CreateTabPageContainer(self,
controlname: str,
place: Union[UNO, Tuple[int, int, int, int]],
tabheaders: Tuple[str, ...],
border: Literal["3D", "FLAT", "NONE"] = ...,
) -> Optional[DIALOGCONTROL]:
"""
Create a new control of type TabPageContainer in the actual dialog. Only one such creation is allowed
per dialog.
This type of control has no equivalent in the Basic IDE. The actual method may nevertheless be applied
to a dialog built in the IDE. It is recommended for control stacking reasons to define a tab
container control AFTER all or most other editable controls.
The creation request is ignored if the dialog is already displayed.
Args
``controlname``: the name of the new control. It must not exist yet.
``place``: the size and position expressed in "``APPFONT units``". Either:
- a tuple (X, Y, Width, Height).
- a ``com.sun.star.awt.Rectangle`` structure.
``tabheaders``: a tuple of strings to define the texts displayed in each respective tab.
``border``: "3D" (default), "FLAT" or "NONE".
Returns
A ``SFDialogs.SF_DialogControl`` instance or ``None``.
"""
...
def CreateTextField(self,
controlname: str,
place: Union[UNO, Tuple[int, int, int, int]],
@@ -4052,20 +4082,21 @@ class SFDialogs:
Defines which controls in a dialog are responsible for switching pages, making it easier
to orchestrate the ``Page`` property of a dialog and its controls.
Dialogs may have multiple pages and the currently visible page is defined by the ``Page``dialog property.
If the ``Page`` property is left unchanged, the default visible page is equal to ``0`` (zero), meaning
that no particular page is defined and all visible controls are displayed regardless of the value set in
their own ``Page`` property.
Dialogs may have multiple pages and the currently visible page is defined by the ``Page``dialog
property. If the ``Page`` property is left unchanged, the default visible page is equal to ``0`` (zero),
meaning that no particular page is defined and all visible controls are displayed regardless of
the value set in their own ``Page`` property.
When the ``Page`` property of a dialog is changed to some other value such as ``1``, ``2``, ``3``
and so forth, then only the controls whose ``Page`` property match the current dialog page will
be displayed.
By using the SetPageManager method it is possible to define four types of page managers:
By using the SetPageManager method it is possible to define five types of page managers:
- List box or combo box: in this case, each entry in the list box or combo box corresponds to a page. The first item refers to Page 1, the second items refers to Page 2 and so on.
- Group of radio buttons: defines a group of radio buttons that will control which page is visible.
- Sequence of buttons: defines a set of buttons, each of which corresponding to a dialog page. This can be used to emulate a tabbed interface by placing buttons side by side in the dialog.
- Previous/Next buttons: defines which buttons in the dialog that will be used to navigate to the Previous/Next page in the dialog.
- If the dialog contains a TabPageContainer control, the control always contributes implicitly to the page management.
This method is supposed to be called just once before calling the ``Execute()`` method.
Subsequent calls are ignored.
@@ -4079,14 +4110,15 @@ class SFDialogs:
they are associated with.
``wizardcontrols``: a comma-separated list with the names of two buttons that will be used
s the ``Previous/Next`` buttons.
as the ``Previous/Next`` buttons.
``lastpage``: the number of the last available page.
It is recommended to specify this value when using the ``Previous/Next`` page manager.
Returns
``True`` on success.
Tip
Note
It is possible to use more than one page management mechanism at the same time.
They will all be synchronized to point to the actual dialog page number.
"""
...
@@ -4178,6 +4210,10 @@ class SFDialogs:
""" Get/set the macro triggered by the ``Expansion button is pressed on a node in a tree control`` event. """
OnNodeSelected: SCRIPT_URI
""" Get/set the macro triggered by the ``Node in a tree control is selected`` event."""
OnTabSelected: SCRIPT_URI
""" Get/set the macro triggered by the ``Tab in a TabPageContainer control is selected`` event."""
OnTextChanged: SCRIPT_URI
""" Get/set the macro triggered by the ``Text modified`` event."""
Page: int
""" A dialog may have several pages that can be traversed by the user step by step.
@@ -4220,6 +4256,7 @@ class SFDialogs:
- ``RadioButton``: bool - Each button has its own name. They are linked together if their TAB positions are contiguous. If a radiobutton is set to ``True``, the other related buttons are automatically set to ``False``.
- ``ScrollBar``: int - Must be within the predefined bounds.
- ``TableControl``: List[Any] - The data of the currently selected row.
- ``TabPageContainer``: int, str - The index (starting from 1) of the selected tab.
- ``TextField``: str - The text appearing in the control.
- ``TimeField``: datetime.datetime.
Not applicable to ``FixedLine, FixedText, GroupBox, Hyperlink, ImageControl`` and ``TreeControl`` dialog controls.

View File

@@ -110,12 +110,15 @@ 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
ListenerType As Integer &apos; One of the ITEMSTATECHANGED, ACTIONPERFORMED or TABSELECTED constants
End Type
Private _PageManagement As Variant &apos; Array of _PageManager objects, one entry by involved control
Private _TabPageContainer As String &apos; The name of the unique tab page container control
Private _ItemListener As Object &apos; com.sun.star.awt.XItemListener
Private _ActionListener As Object &apos; com.sun.star.awt.XActionListener
Private _TabPageContainerListener As Object
&apos; com.sun.star.awt.tab.XTabPageContainerListener
Private _LastPage As Long &apos; When &gt; 0, the last page in a tabbed dialog
&apos; Updatable events
@@ -156,8 +159,10 @@ Private Const PILOTCONTROL = 1
Private Const TABCONTROL = 2
Private Const BACKCONTROL = 3
Private Const NEXTCONTROL = 4
Private Const TABPAGE = 5
Private Const ITEMSTATECHANGED = 1
Private Const ACTIONPERFORMED = 2
Private Const TABSELECTED = 3
REM ====================================================== CONSTRUCTOR/DESTRUCTOR
@@ -185,8 +190,10 @@ Private Sub Class_Initialize()
_Height = -1
_PageManagement = Array()
_TabPageContainer = &quot;&quot;
Set _ItemListener = Nothing
Set _ActionListener = Nothing
Set _TabPageContainerListener = Nothing
_LastPage = 0
Set _FocusListener = Nothing
@@ -1730,6 +1737,94 @@ Finally:
Exit Function
End Function &apos; SFDialogs.SF_Dialog.CreateTableControl
REM -----------------------------------------------------------------------------
Public Function CreateTabPageContainer(Optional ByVal ControlName As Variant _
, Optional ByRef Place As Variant _
, Optional ByRef TabHeaders As Variant _
, Optional ByVal Border As Variant _
) As Object
&apos;&apos;&apos; Create a new control of type TabPageContainer in the actual dialog.
&apos;&apos;&apos; Only one such creation is allowed per dialog.
&apos;&apos;&apos; A TabPageContainer control will be automatically coupled with a PageManager setup.
&apos;&apos;&apos;
&apos;&apos;&apos; This type of control has no equivalent in the Basic IDE. The actual method
&apos;&apos;&apos; may nevertheless be applied to a dialog built in the IDE.
&apos;&apos;&apos;
&apos;&apos;&apos; It is recommended for control stacking reasons to define a tab container
&apos;&apos;&apos; control AFTER all or most other editable controls.
&apos;&apos;&apos;
&apos;&apos;&apos; The creation request is ignored if the dialog is already displayed.
&apos;&apos;&apos;
&apos;&apos;&apos; Specific args:
&apos;&apos;&apos; TabHeaders: an array of strings to define the texts displayed in each individual tabs
1&apos;&apos;&apos; Border: &quot;3D&quot; (default) or &quot;FLAT&quot; or &quot;NONE&quot;
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; an instance of the SF_DialogControl class or Nothing
&apos;&apos;&apos; Example:
&apos;&apos;&apos; Set myTabContainer = dialog.CreateTabPageContainer(&quot;TabContainer1&quot;, Array(20, 20, 60, 15), _
&apos;&apos;&apos; TabHeaders := Array(&quot;Modules&quot;, &quot;Dialogs&quot;, &quot;Libraries&quot;))
Dim oControl As Object &apos; Return value
Dim iBorder As Integer &apos; Alias of border
Dim vPropNames As Variant &apos; Array of names of specific arguments
Dim vPropValues As Variant &apos; Array of values of specific arguments
Dim oTabPageModel As Object &apos; stardiv.Toolkit.UnoControlTabPageModel
Dim oToolkit As Object &apos; com.sun.star.awt.Toolkit
Dim iPage As Integer &apos; Actual page number
Dim i As Integer
Const cstThisSub = &quot;SFDialogs.Dialog.CreateTabContainer&quot;
Const cstSubArgs = &quot;ControlName, Place, TabHeaders, [Border=&quot;&quot;3D&quot;&quot;|&quot;&quot;FLAT&quot;&quot;|&quot;&quot;NONE&quot;&quot;]&quot;
Check:
Set oControl = Nothing
If Not _CheckNewControl(cstThisSub, cstSubArgs, ControlName, Place) Then GoTo Finally
If IsMissing(Border) Or IsEmpty(Border) Then Border = &quot;3D&quot;
If Not ScriptForge.SF_Utils._ValidateArray(TabHeaders, &quot;TabHeaders&quot;, 1, V_STRING, True) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(Border, &quot;Border&quot;, V_STRING, Array(&quot;3D&quot;, &quot;FLAT&quot;, &quot;NONE&quot;)) Then GoTo Finally
If _Displayed Then GoTo Finally &apos; Ignore the call when dialog is displayed to enable peer creation below
If Len(_TabPageContainer) &gt; 0 Then GoTo Finally &apos; A tab page container must be unique in a dialog
Try:
&apos; Handle specific arguments
iBorder = ScriptForge.SF_Array.IndexOf(Array(&quot;NONE&quot;, &quot;3D&quot;, &quot;FLAT&quot;), Border)
vPropNames = Array(&quot;Border&quot;)
vPropValues = Array(iBorder)
&apos; Create the control
Set oControl = _CreateNewControl(&quot;tab.UnoControlTabPageContainerModel&quot;, ControlName, Place, vPropNames, vPropValues)
&apos; Create the peer dialog window, preamble of the determination of the ActiveTabPageID
_DialogControl.setVisible(False) &apos; Differ the display of the dialog later than at createPeer()
Set oToolkit = CreateUnoService(&quot;com.sun.star.awt.Toolkit&quot;)
_DialogControl.createPeer(oToolkit, Null)
With oControl
&apos; Store the tab headers
._TabHeaders = TabHeaders
&apos; Insert the individual tab pages
For i = LBound(TabHeaders) To UBound(TabHeaders)
Set oTabPageModel = _DialogModel.createInstance(&quot;com.sun.star.awt.tab.UnoControlTabPageModel&quot;)
oTabPageModel.initialize (Array (i - LBound(TabHeaders) + 1)) &apos; TabPageID&apos;s start at 1
oTabPageModel.Title = TabHeaders(i)
._ControlModel.insertByIndex(i - LBound(TabHeaders), oTabPageModel)
Next i
&apos; Determine the default tab page
iPage = _DialogModel.Step
._ControlView.ActiveTabPageID = Iif(iPage = 0, 1, iPage)
End With
&apos; Register the unique tab page container
_TabPageContainer = ControlName
Finally:
Set CreateTabPageContainer = oControl
ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Function
End Function &apos; SFDialogs.SF_Dialog.CreateTabPageContainer
REM -----------------------------------------------------------------------------
Public Function CreateTextField(Optional ByVal ControlName As Variant _
, Optional ByRef Place As Variant _
@@ -2158,6 +2253,7 @@ Public Function Methods() As Variant
, &quot;CreateRadioButton&quot; _
, &quot;CreateScrollBar&quot; _
, &quot;CreateTableControl&quot; _
, &quot;CreateTabPageContainer&quot; _
, &quot;CreateTextField&quot; _
, &quot;CreateTimeField&quot; _
, &quot;CreateTreeControl&quot; _
@@ -2216,7 +2312,7 @@ Check:
End If
Try:
vWrongTypes = Array(&quot;FixedLine&quot;, &quot;GroupBox&quot;, &quot;ProgressBar&quot;)
vWrongTypes = Array(&quot;FixedLine&quot;, &quot;GroupBox&quot;, &quot;ProgressBar&quot;, &quot;TabPageContainer&quot;)
&apos; Remove all existing tabulations
vControlNames = _DialogModel.getElementNames()
@@ -2330,19 +2426,20 @@ Public Function SetPageManager(Optional ByVal PilotControls As Variant _
&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; If any, the predefined TabPageContainer control is implicitly part of the process.
&apos;&apos;&apos; Possible additional 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; Those options may be combined. The updates of all the involved controls 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; Predefined 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:
@@ -2355,6 +2452,9 @@ Public Function SetPageManager(Optional ByVal PilotControls As Variant _
&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
&apos;&apos;&apos; or
&apos;&apos;&apos; Set oTabs = dialog.CreateTabPageContainer(...)
&apos;&apos;&apos; dialog.SetPageManager() &apos; Only the TabPageContainer is involved
Dim bManager As Boolean &apos; Return value
Dim vControls As Variant &apos; Array of involved controls
@@ -2388,6 +2488,7 @@ 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;)
Set _TabPageContainerListener = CreateUnoListener(cstPrefix, &quot;com.sun.star.awt.tab.XTabPageContainerListener&quot;)
&apos; Register the arguments in the _PageManagement array, control by control
&apos; Pilot controls
@@ -2411,6 +2512,10 @@ Try:
If Not _RegisterPageListener(Trim(vControls(i)), &quot;Button&quot;, Iif(i = 0, BACKCONTROL, NEXTCONTROL), 0, ACTIONPERFORMED) Then GoTo Catch
Next i
End If
&apos; Tab page container
If Len(_TabPageContainer) &gt; 0 Then
If Not _RegisterPageListener(_TabPageContainer, &quot;TabPageContainer&quot;, TABPAGE, 0, TABSELECTED) Then GoTo Catch
End If
&apos; Set the initial page to 1
Page = 1
@@ -2836,8 +2941,8 @@ Try:
&apos; The Next button must be dimmed when last page otherwise enabled
For Each oPageManager In _PageManagement
With oPageManager
lPage = .PageNumber
Set oControl = Controls(.ControlName)
lPage = .PageNumber
Set oControl = Controls(.ControlName)
With oControl
Select Case .ControlType
Case &quot;ListBox&quot;, &quot;ComboBox&quot;
@@ -2854,6 +2959,8 @@ Try:
.Enabled = ( _LastPage = 0 Or plPage &lt; _LastPage )
Case Else
End Select
Case &quot;TabPageContainer&quot;
._ControlView.ActiveTabPageID = plPage
Case Else
End Select
End With
@@ -3020,14 +3127,15 @@ Private Function _RegisterPageListener(ByVal psControlName As String _
, ByVal plPageNumber As Long _
, ByVal piListener As Integer _
) As Boolean
&apos;&apos;&apos; Insert a new entry in the _PageManagement array when 1st argument is a listbox, a combobox or a button
&apos;&apos;&apos; Insert a new entry in the _PageManagement array when 1st argument is a listbox, a combobox,
&apos;&apos;&apos; a button or a tabpagecontainer.
&apos;&apos;&apos; or insert a new entry in the _PageManagement 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 allowed control types
&apos;&apos;&apos; piMgtType: one of the PILOTCONTROL, TABCONTROL, BACKCONTROL, NEXTCONTROL constants
&apos;&apos;&apos; piMgtType: one of the PILOTCONTROL, TABCONTROL, BACKCONTROL, NEXTCONTROL, TABPAGE 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
&apos;&apos;&apos; piListener: one of the ACTIONPERFORMED, ITEMSTATECHANGED, TABSELECTED constants
Dim bRegister As Boolean &apos; Return value
Dim oControl As Object &apos; A DialogControl object
@@ -3070,6 +3178,8 @@ Try:
._ControlView.addActionListener(_ActionListener)
ElseIf piListener = ITEMSTATECHANGED Then
._ControlView.addItemListener(_ItemListener)
ElseIf piListener = TABSELECTED Then
._ControlView.addTabPageContainerListener(_TabPageContainerListener)
End If
End With
Next i

View File

@@ -123,6 +123,10 @@ Private _OnMouseDragged As String &apos; Script to invoke when mouse is dragge
Private _OnMouseMoved As String &apos; Script to invoke when mouse is moved across the control
Private _MouseMotionCounter As Integer &apos; Counts the number of events set on the listener
&apos; ---
Private _TabPageContainerListener As Object &apos; com.sun.star.awt.XTabPageContainerListener
Private _OnTabSelected As String &apos; Script to invoke when a new tab is selected
Private _TabPageContainerCounter As Integer &apos; Counts the number of events set on the listener
&apos; ---
Private _TextListener As Object &apos; com.sun.star.awt.XTextListener
Private _OnTextChanged As String &apos; Script to invoke when textual content has changed
Private _TextCounter As Integer &apos; Counts the number of events set on the listener
@@ -130,30 +134,34 @@ Private _TextCounter As Integer &apos; Counts the number of events set on the
&apos; Table control attributes
Private _ColumnWidths As Variant &apos; Array of column widths
&apos; TabPageContainer attributes
Private _TabHeaders As Variant &apos; Array of tab page headers as strings
REM ============================================================ MODULE CONSTANTS
Private Const CTLBUTTON = &quot;Button&quot;
Private Const CTLCHECKBOX = &quot;CheckBox&quot;
Private Const CTLCOMBOBOX = &quot;ComboBox&quot;
Private Const CTLCURRENCYFIELD = &quot;CurrencyField&quot;
Private Const CTLDATEFIELD = &quot;DateField&quot;
Private Const CTLFILECONTROL = &quot;FileControl&quot;
Private Const CTLFIXEDLINE = &quot;FixedLine&quot;
Private Const CTLFIXEDTEXT = &quot;FixedText&quot;
Private Const CTLFORMATTEDFIELD = &quot;FormattedField&quot;
Private Const CTLGROUPBOX = &quot;GroupBox&quot;
Private Const CTLHYPERLINK = &quot;Hyperlink&quot;
Private Const CTLIMAGECONTROL = &quot;ImageControl&quot;
Private Const CTLLISTBOX = &quot;ListBox&quot;
Private Const CTLNUMERICFIELD = &quot;NumericField&quot;
Private Const CTLPATTERNFIELD = &quot;PatternField&quot;
Private Const CTLPROGRESSBAR = &quot;ProgressBar&quot;
Private Const CTLRADIOBUTTON = &quot;RadioButton&quot;
Private Const CTLSCROLLBAR = &quot;ScrollBar&quot;
Private Const CTLTABLECONTROL = &quot;TableControl&quot;
Private Const CTLTEXTFIELD = &quot;TextField&quot;
Private Const CTLTIMEFIELD = &quot;TimeField&quot;
Private Const CTLTREECONTROL = &quot;TreeControl&quot;
Private Const CTLBUTTON = &quot;Button&quot;
Private Const CTLCHECKBOX = &quot;CheckBox&quot;
Private Const CTLCOMBOBOX = &quot;ComboBox&quot;
Private Const CTLCURRENCYFIELD = &quot;CurrencyField&quot;
Private Const CTLDATEFIELD = &quot;DateField&quot;
Private Const CTLFILECONTROL = &quot;FileControl&quot;
Private Const CTLFIXEDLINE = &quot;FixedLine&quot;
Private Const CTLFIXEDTEXT = &quot;FixedText&quot;
Private Const CTLFORMATTEDFIELD = &quot;FormattedField&quot;
Private Const CTLGROUPBOX = &quot;GroupBox&quot;
Private Const CTLHYPERLINK = &quot;Hyperlink&quot;
Private Const CTLIMAGECONTROL = &quot;ImageControl&quot;
Private Const CTLLISTBOX = &quot;ListBox&quot;
Private Const CTLNUMERICFIELD = &quot;NumericField&quot;
Private Const CTLPATTERNFIELD = &quot;PatternField&quot;
Private Const CTLPROGRESSBAR = &quot;ProgressBar&quot;
Private Const CTLRADIOBUTTON = &quot;RadioButton&quot;
Private Const CTLSCROLLBAR = &quot;ScrollBar&quot;
Private Const CTLTABLECONTROL = &quot;TableControl&quot;
Private Const CTLTABPAGECONTAINER = &quot;TabPageContainer&quot;
Private Const CTLTEXTFIELD = &quot;TextField&quot;
Private Const CTLTIMEFIELD = &quot;TimeField&quot;
Private Const CTLTREECONTROL = &quot;TreeControl&quot;
REM ====================================================== CONSTRUCTOR/DESTRUCTOR
@@ -211,11 +219,15 @@ Private Sub Class_Initialize()
Set _ItemListener = Nothing
_OnItemStateChanged = &quot;&quot;
_ItemCounter = 0
Set _TabPageContainerListener = Nothing
_OnTabSelected = &quot;&quot;
_TabPageContainerCounter = 0
Set _TextListener = Nothing
_OnTextChanged = &quot;&quot;
_TextCounter = 0
_ColumnWidths = Array()
_TabHeaders = Array()
End Sub &apos; SFDialogs.SF_DialogControl Constructor
REM -----------------------------------------------------------------------------
@@ -564,6 +576,18 @@ Property Let OnNodeSelected(Optional ByVal pvOnNodeSelected As Variant)
_PropertySet(&quot;OnNodeSelected&quot;, pvOnNodeSelected)
End Property &apos; SFDialogs.SF_DialogControl.OnNodeSelected (let)
REM -----------------------------------------------------------------------------
Property Get OnTabSelected() As Variant
&apos;&apos;&apos; Get the script associated with the OnTabSelected event
OnTabSelected = _PropertyGet(&quot;OnTabSelected&quot;)
End Property &apos; SFDialogs.SF_DialogControl.OnTabSelected (get)
REM -----------------------------------------------------------------------------
Property Let OnTabSelected(Optional ByVal pvTextChanged As Variant)
&apos;&apos;&apos; Set the updatable property OnTabSelected
_PropertySet(&quot;OnTabSelected&quot;, pvTextChanged)
End Property &apos; SFDialogs.SF_DialogControl.OnTabSelected (let)
REM -----------------------------------------------------------------------------
Property Get OnTextChanged() As Variant
&apos;&apos;&apos; Get the script associated with the OnTextChanged event
@@ -1161,6 +1185,7 @@ Public Function Properties() As Variant
, &quot;OnMouseReleased&quot; _
, &quot;OnNodeExpanded&quot; _
, &quot;OnNodeSelected&quot; _
, &quot;OnTabSelected&quot; _
, &quot;OnTextChanged&quot; _
, &quot;Page&quot; _
, &quot;Parent&quot; _
@@ -1675,6 +1700,8 @@ Private Function _GetListener(ByVal psEventName As String) As String
_GetListener = &quot;XMouseMotionListener&quot;
Case UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;)
_GetListener = &quot;XMouseListener&quot;
Case UCase(&quot;OnTabSelected&quot;)
_GetListener = &quot;tab.XTabPageContainerListener&quot;
Case UCase(&quot;OnTextChanged&quot;)
_GetListener = &quot;XTextListener&quot;
Case Else
@@ -1714,6 +1741,8 @@ Try:
_ControlType = CTLTABLECONTROL
Set _GridColumnModel = _ControlModel.ColumnModel
Set _GridDataModel = _ControlModel.GridDataModel
Case &quot;UnoControlTabPageContainerModel&quot;
_ControlType = CTLTABPAGECONTAINER
Case Else : _ControlType = sType
End Select
@@ -1893,7 +1922,7 @@ Const cstSubArgs = &quot;&quot;
Case UCase(&quot;OnActionPerformed&quot;), UCase(&quot;OnAdjustmentValueChanged&quot;), UCase(&quot;OnFocusGained&quot;), UCase(&quot;OnFocusLost&quot;) _
, UCase(&quot;OnItemStateChanged&quot;), UCase(&quot;OnKeyPressed&quot;), UCase(&quot;OnKeyReleased&quot;) _
, UCase(&quot;OnMouseDragged&quot;), UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMouseMoved&quot;) _
, UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;), UCase(&quot;OnTextChanged&quot;)
, UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;), UCase(&quot;OnTabSelected&quot;), UCase(&quot;OnTextChanged&quot;)
Set oControlEvents = _ControlModel.getEvents()
sEventName = &quot;com.sun.star.awt.&quot; &amp; _GetListener(psProperty) &amp; &quot;::&quot; &amp; _GetEventName(psProperty)
If oControlEvents.hasByName(sEventName) Then
@@ -1914,6 +1943,7 @@ Const cstSubArgs = &quot;&quot;
Case UCase(&quot;OnMouseMoved&quot;) : _PropertyGet = _OnMouseMoved
Case UCase(&quot;OnMousePressed&quot;) : _PropertyGet = _OnMousePressed
Case UCase(&quot;OnMouseReleased&quot;) : _PropertyGet = _OnMouseReleased
Case UCase(&quot;OnTabSelected&quot;) : _PropertyGet = _OnTabSelected
Case UCase(&quot;OnTextChanged&quot;) : _PropertyGet = _OnTextChanged
Case Else : _PropertyGet = &quot;&quot;
End Select
@@ -2051,6 +2081,8 @@ Const cstSubArgs = &quot;&quot;
If lIndex &gt;= 0 Then vGet = _GridDataModel.getRowData(lIndex)
End If
End If
Case CTLTABPAGECONTAINER
If oSession.HasUnoProperty(_ControlView, &quot;ActiveTabPageID&quot;) Then vGet = _ControlView.ActiveTabPageID Else vGet = 0
Case CTLTIMEFIELD
vGet = CDate(0)
If oSession.HasUnoProperty(_ControlModel, &quot;Time&quot;) Then
@@ -2125,7 +2157,8 @@ Dim lFormatKey As Long &apos; Format index for formatted fields
Dim oLocale As Object &apos; com.sun.star.lang.Locale
Dim vSelection As Variant &apos; Alias of Model.SelectedItems
Dim vList As Variant &apos; Alias of Model.StringItemList
Dim lIndex As Long &apos; Index in StringItemList
Dim lIndex As Long &apos; Index in StringItemList or _TabHeaders
Dim vValue As Variant &apos; Alias of pvValue
Dim sItem As String &apos; A single item
Dim vCtlTypes As Variant &apos; Array of allowed control types
Dim i As Long
@@ -2276,7 +2309,7 @@ Const cstSubArgs = &quot;Value&quot;
Case UCase(&quot;OnActionPerformed&quot;), UCase(&quot;OnAdjustmentValueChanged&quot;), UCase(&quot;OnFocusGained&quot;), UCase(&quot;OnFocusLost&quot;) _
, UCase(&quot;OnItemStateChanged&quot;), UCase(&quot;OnKeyPressed&quot;), UCase(&quot;OnKeyReleased&quot;) _
, UCase(&quot;OnMouseDragged&quot;), UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMouseMoved&quot;) _
, UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;), UCase(&quot;OnTextChanged&quot;)
, UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;), UCase(&quot;OnTabSelected&quot;), UCase(&quot;OnTextChanged&quot;)
If Not ScriptForge.SF_Utils._Validate(pvValue, psProperty, V_STRING) Then GoTo Catch
&apos; Check control type for not universal event types
Select Case UCase(psProperty)
@@ -2287,6 +2320,8 @@ Const cstSubArgs = &quot;Value&quot;
End Select
Case UCase(&quot;OnAdjustmentValueChanged&quot;)
If _ControlType &lt;&gt; CTLSCROLLBAR Then GoTo CatchType
Case UCase(&quot;OnTabSelected&quot;)
If _ControlType &lt;&gt; CTLTABPAGECONTAINER Then GoTo CatchType
Case UCase(&quot;OnTextChanged&quot;)
Select Case _ControlType
Case CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFORMATTEDFIELD _
@@ -2460,6 +2495,17 @@ Const cstSubArgs = &quot;Value&quot;
If pvValue &gt; _ControlModel.ScrollValueMax Then pvValue = _ControlModel.ScrollValueMax
End If
If oSession.HasUnoProperty(_ControlModel, &quot;ScrollValue&quot;) Then _ControlModel.ScrollValue = pvValue
Case CTLTABPAGECONTAINER
If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, Array(V_STRING, ScriptForge.V_NUMERIC)) Then GoTo Finally
If oSession.HasUNOProperty(_ControlView, &quot;ActiveTabPageID&quot;) Then
If VarType(pvValue) = V_STRING Then
lIndex = ScriptForge.SF_Array.IndexOf(_TabHeaders, pvValue, CaseSensitive := True)
vValue = lIndex - LBound(_TabHeaders) + 1
Else
vValue = CInt(pvValue)
End If
If vValue &gt;= 1 And vValue &lt;= _ControlModel.Count Then _ControlView.ActiveTabPageID = vValue
End If
Case CTLTIMEFIELD
If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_DATE) Then GoTo Finally
If oSession.HasUnoProperty(_ControlModel, &quot;Time&quot;) Then

View File

@@ -32,7 +32,7 @@ Option Explicit
&apos;&apos;&apos; The described events are processed thru UNO listeners
&apos;&apos;&apos;
&apos;&apos;&apos; &quot;On&quot; events defined by code, prefix = _SFACTION_, _SFADJUST_, _SFFOCUS_, _SFKEY_, _SFMOUSE_,
&apos;&apos;&apos; ----------- _SFMOVE_, _SFITEM_, _SFADJUST_, _SFTEXT_
&apos;&apos;&apos; ----------- _SFMOVE_, _SFITEM_, _SFADJUST_, _SFSELTAB_, _SFTEXT_
&apos;&apos;&apos; All event types applicable on dialogs and control types &lt;&gt; TreeControl
&apos;&apos;&apos; The events MUST NOT be preset in the Basic IDE
&apos;&apos;&apos;
@@ -200,6 +200,37 @@ Finally:
Exit Sub
End Sub &apos; SFDialogs.SF_Dialoglistener._SFTAB_itemStateChanged
REM -----------------------------------------------------------------------------
Public Sub _SFTAB_tabPageActivated(Optional ByRef poEvent As Object)
&apos;&apos;&apos; Event triggered by a tab page container configured through the dialog page manager
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
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
.Page = poEvent.TabPageID
Exit For
End If
Next oPageManager
End With
Finally:
Exit Sub
End Sub &apos; SFDialogs.SF_Dialoglistener._SFTAB_actionPerformed
REM -----------------------------------------------------------------------------
Public Sub _SFTAB_disposing(Optional ByRef poEvent As Object)
End Sub
@@ -384,6 +415,21 @@ REM ----------------------------------------------------------------------------
Public Sub _SFMOVE_disposing()
End Sub
REM -----------------------------------------------------------------------------
Public Sub _SFSELTAB_tabPageActivated(Optional ByRef poEvent As Object)
&apos;&apos;&apos; Triggered by the OnTabSelected event in a dialog control
&apos;&apos;&apos; The event is triggered thru a com.sun.star.awt.tab.XTabPageContainerListener
&apos;&apos;&apos; The argument is passed to a user routine stored in the SF_DialogControl instance
&apos;&apos;&apos; as a scripting framework URI
_TriggerEvent(&quot;tabPageActivated&quot;, poEvent)
End Sub &apos; SFDialogs.SF_Dialoglistener._SFSELTAB_tabPageActivated
REM -----------------------------------------------------------------------------
Public Sub _SFSELTAB_disposing()
End Sub
REM -----------------------------------------------------------------------------
Public Sub _SFTEXT_textChanged(Optional ByRef poEvent As Object)
&apos;&apos;&apos; Triggered by the OnTextChanged event in a dialog control
@@ -393,7 +439,7 @@ Public Sub _SFTEXT_textChanged(Optional ByRef poEvent As Object)
_TriggerEvent(&quot;textChanged&quot;, poEvent)
End Sub &apos; SFDialogs.SF_Dialoglistener. _SFTEXT_textChanged
End Sub &apos; SFDialogs.SF_Dialoglistener._SFTEXT_textChanged
REM -----------------------------------------------------------------------------
Public Sub _SFTEXT_disposing()
@@ -544,6 +590,9 @@ Try:
Case UCase(&quot;OnMouseReleased&quot;)
sPrevious = ._OnMouseReleased
._OnMouseReleased = psScript
Case UCase(&quot;OnTabSelected&quot;)
sPrevious = ._OnTabSelected
._OnTabSelected = psScript
Case UCase(&quot;OnTextChanged&quot;)
sPrevious = ._OnTextChanged
._OnTextChanged = psScript
@@ -638,6 +687,17 @@ Try:
If Not IsNull(._MouseMotionListener) Then oView.removeMouseMotionListener(._MouseMotionListener)
._MouseMotionCounter = 0 &apos; Prevent negative values
End If
Case &quot;tab.XTabPageContainerListener&quot;
._TabPageContainerCounter = ._TabPageContainerCounter + iCounterIncrement
If ._TabPageContainerCounter = 1 Then
If IsNull(._TabPageContainerListener) Then
Set ._TabPageContainerListener = CreateUnoListener(&quot;SFDialogs.SF_DialogListener._SFSELTAB_&quot;, cstPrefix &amp; sListener)
End If
If iCounterIncrement = 1 Then oView.addTabPageContainerListener(._TabPageContainerListener)
ElseIf ._TabPageContainerCounter &lt;= 0 Then
If Not IsNull(._TabPageContainerListener) Then oView.removeTabPageContainerListener(._TabPageContainerListener)
._TabPageContainerCounter = 0 &apos; Prevent negative values
End If
Case &quot;XTextListener&quot;
._TextCounter = ._TextCounter + iCounterIncrement
If ._TextCounter = 1 Then
@@ -691,6 +751,7 @@ Try:
Case &quot;mouseMoved&quot; : sScript = .OnMouseMoved
Case &quot;mousePressed&quot; : sScript = .OnMousePressed
Case &quot;mouseReleased&quot; : sScript = .OnMouseReleased
Case &quot;tabPageActivated&quot; : sScript = .OnTabSelected
Case &quot;textChanged&quot; : sScript = .OnTextChanged
Case Else : sScript = &quot;&quot; &apos; Should not happen
End Select

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
<library:library xmlns:library="http://openoffice.org/2000/library" library:name="SFDialogs" library:readonly="false" library:passwordprotected="false">
<library:element library:name="SF_DialogUtils"/>
<library:element library:name="SF_DialogListener"/>
<library:element library:name="SF_DialogControl"/>
<library:element library:name="SF_Dialog"/>
<library:element library:name="SF_Register"/>
<library:element library:name="__License"/>
<library:element library:name="SF_Register"/>
<library:element library:name="SF_Dialog"/>
<library:element library:name="SF_DialogControl"/>
<library:element library:name="SF_DialogListener"/>
<library:element library:name="SF_DialogUtils"/>
</library:library>