wizards/source/scriptforge/python/scriptforge.py | 7 - wizards/source/scriptforge/python/scriptforge.pyi | 51 +++++++- wizards/source/sfdialogs/SF_Dialog.xba | 130 ++++++++++++++++++++-- wizards/source/sfdialogs/SF_DialogControl.xba | 96 ++++++++++++---- wizards/source/sfdialogs/SF_DialogListener.xba | 65 ++++++++++- wizards/source/sfdialogs/script.xlb | 10 - 6 files changed, 308 insertions(+), 51 deletions(-)
New commits: commit 05d2701e3bba4c36752d5dbc144e103667ce1681 Author: Jean-Pierre Ledure <j...@ledure.be> AuthorDate: Sun Mar 9 17:32:59 2025 +0100 Commit: Jean-Pierre Ledure <j...@ledure.be> CommitDate: Mon Mar 10 11:07:23 2025 +0100 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 <j...@ledure.be> Tested-by: Jenkins diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index 00fddb2209ee..8d04f2a07b64 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -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') diff --git a/wizards/source/scriptforge/python/scriptforge.pyi b/wizards/source/scriptforge/python/scriptforge.pyi index fcbd957a6882..ff3d59e8472d 100644 --- a/wizards/source/scriptforge/python/scriptforge.pyi +++ b/wizards/source/scriptforge/python/scriptforge.pyi @@ -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. diff --git a/wizards/source/sfdialogs/SF_Dialog.xba b/wizards/source/sfdialogs/SF_Dialog.xba index 96035e277009..819f4c291d20 100644 --- a/wizards/source/sfdialogs/SF_Dialog.xba +++ b/wizards/source/sfdialogs/SF_Dialog.xba @@ -110,12 +110,15 @@ Type _PageManager ControlName As String ' Case-sensitive name of control involved in page management PageMgtType As Integer ' One of the PILOTCONTROL, TABCONTROL, NEXTCONTROL, BACKCONTROL constants PageNumber As Long ' When > 0, the page to activate for tab controls - ListenerType As Integer ' One of the ITEMSTATECHANGED, ACTIONPERFORMED constants + ListenerType As Integer ' One of the ITEMSTATECHANGED, ACTIONPERFORMED or TABSELECTED constants End Type Private _PageManagement As Variant ' Array of _PageManager objects, one entry by involved control +Private _TabPageContainer As String ' The name of the unique tab page container control Private _ItemListener As Object ' com.sun.star.awt.XItemListener Private _ActionListener As Object ' com.sun.star.awt.XActionListener +Private _TabPageContainerListener As Object + ' com.sun.star.awt.tab.XTabPageContainerListener Private _LastPage As Long ' When > 0, the last page in a tabbed dialog ' 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 = "" Set _ItemListener = Nothing Set _ActionListener = Nothing + Set _TabPageContainerListener = Nothing _LastPage = 0 Set _FocusListener = Nothing @@ -1730,6 +1737,94 @@ Finally: Exit Function End Function ' 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 +''' Create a new control of type TabPageContainer in the actual dialog. +''' Only one such creation is allowed per dialog. +''' A TabPageContainer control will be automatically coupled with a PageManager setup. +''' +''' 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. +''' +''' Specific args: +''' TabHeaders: an array of strings to define the texts displayed in each individual tabs +1''' Border: "3D" (default) or "FLAT" or "NONE" +''' Returns: +''' an instance of the SF_DialogControl class or Nothing +''' Example: +''' Set myTabContainer = dialog.CreateTabPageContainer("TabContainer1", Array(20, 20, 60, 15), _ +''' TabHeaders := Array("Modules", "Dialogs", "Libraries")) + +Dim oControl As Object ' Return value +Dim iBorder As Integer ' Alias of border +Dim vPropNames As Variant ' Array of names of specific arguments +Dim vPropValues As Variant ' Array of values of specific arguments +Dim oTabPageModel As Object ' stardiv.Toolkit.UnoControlTabPageModel +Dim oToolkit As Object ' com.sun.star.awt.Toolkit +Dim iPage As Integer ' Actual page number +Dim i As Integer + +Const cstThisSub = "SFDialogs.Dialog.CreateTabContainer" +Const cstSubArgs = "ControlName, Place, TabHeaders, [Border=""3D""|""FLAT""|""NONE""]" + +Check: + Set oControl = Nothing + If Not _CheckNewControl(cstThisSub, cstSubArgs, ControlName, Place) Then GoTo Finally + + If IsMissing(Border) Or IsEmpty(Border) Then Border = "3D" + If Not ScriptForge.SF_Utils._ValidateArray(TabHeaders, "TabHeaders", 1, V_STRING, True) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(Border, "Border", V_STRING, Array("3D", "FLAT", "NONE")) Then GoTo Finally + + If _Displayed Then GoTo Finally ' Ignore the call when dialog is displayed to enable peer creation below + If Len(_TabPageContainer) > 0 Then GoTo Finally ' A tab page container must be unique in a dialog + +Try: + ' Handle specific arguments + iBorder = ScriptForge.SF_Array.IndexOf(Array("NONE", "3D", "FLAT"), Border) + vPropNames = Array("Border") + vPropValues = Array(iBorder) + + ' Create the control + Set oControl = _CreateNewControl("tab.UnoControlTabPageContainerModel", ControlName, Place, vPropNames, vPropValues) + + ' Create the peer dialog window, preamble of the determination of the ActiveTabPageID + _DialogControl.setVisible(False) ' Differ the display of the dialog later than at createPeer() + Set oToolkit = CreateUnoService("com.sun.star.awt.Toolkit") + _DialogControl.createPeer(oToolkit, Null) + + With oControl + ' Store the tab headers + ._TabHeaders = TabHeaders + ' Insert the individual tab pages + For i = LBound(TabHeaders) To UBound(TabHeaders) + Set oTabPageModel = _DialogModel.createInstance("com.sun.star.awt.tab.UnoControlTabPageModel") + oTabPageModel.initialize (Array (i - LBound(TabHeaders) + 1)) ' TabPageID's start at 1 + oTabPageModel.Title = TabHeaders(i) + ._ControlModel.insertByIndex(i - LBound(TabHeaders), oTabPageModel) + Next i + ' Determine the default tab page + iPage = _DialogModel.Step + ._ControlView.ActiveTabPageID = Iif(iPage = 0, 1, iPage) + End With + + ' Register the unique tab page container + _TabPageContainer = ControlName + +Finally: + Set CreateTabPageContainer = oControl + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +End Function ' 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 , "CreateRadioButton" _ , "CreateScrollBar" _ , "CreateTableControl" _ + , "CreateTabPageContainer" _ , "CreateTextField" _ , "CreateTimeField" _ , "CreateTreeControl" _ @@ -2216,7 +2312,7 @@ Check: End If Try: - vWrongTypes = Array("FixedLine", "GroupBox", "ProgressBar") + vWrongTypes = Array("FixedLine", "GroupBox", "ProgressBar", "TabPageContainer") ' Remove all existing tabulations vControlNames = _DialogModel.getElementNames() @@ -2330,19 +2426,20 @@ Public Function SetPageManager(Optional ByVal PilotControls As Variant _ ''' and all controls with a page value of 2 become visible. ''' ''' The arguments define which controls are involved in the orchestration of the displayed pages. -''' Possible options: +''' If any, the predefined TabPageContainer control is implicitly part of the process. +''' Possible additional 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. +''' Those options may be combined. The updates of all the involved controls 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. +''' Predefined events (in the Basic IDE) will be preserved and executed immediately AFTER the page change. ''' The listeners will be removed at dialog termination. ''' ''' Args: @@ -2355,6 +2452,9 @@ Public Function SetPageManager(Optional ByVal PilotControls As Variant _ ''' True when successful ''' Examples: ''' dialog.SetPageManager(PilotControls := "aListBox,aComboBox") ' 2 controls may cause page changes +''' or +''' Set oTabs = dialog.CreateTabPageContainer(...) +''' dialog.SetPageManager() ' Only the TabPageContainer is involved Dim bManager As Boolean ' Return value Dim vControls As Variant ' Array of involved controls @@ -2388,6 +2488,7 @@ Try: ' Common listeners to all involved controls Set _ItemListener = CreateUnoListener(cstPrefix, "com.sun.star.awt.XItemListener") Set _ActionListener = CreateUnoListener(cstPrefix, "com.sun.star.awt.XActionListener") + Set _TabPageContainerListener = CreateUnoListener(cstPrefix, "com.sun.star.awt.tab.XTabPageContainerListener") ' Register the arguments in the _PageManagement array, control by control ' Pilot controls @@ -2411,6 +2512,10 @@ Try: If Not _RegisterPageListener(Trim(vControls(i)), "Button", Iif(i = 0, BACKCONTROL, NEXTCONTROL), 0, ACTIONPERFORMED) Then GoTo Catch Next i End If + ' Tab page container + If Len(_TabPageContainer) > 0 Then + If Not _RegisterPageListener(_TabPageContainer, "TabPageContainer", TABPAGE, 0, TABSELECTED) Then GoTo Catch + End If ' Set the initial page to 1 Page = 1 @@ -2836,8 +2941,8 @@ Try: ' 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 "ListBox", "ComboBox" @@ -2854,6 +2959,8 @@ Try: .Enabled = ( _LastPage = 0 Or plPage < _LastPage ) Case Else End Select + Case "TabPageContainer" + ._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 -''' Insert a new entry in the _PageManagement array when 1st argument is a listbox, a combobox or a button +''' Insert a new entry in the _PageManagement array when 1st argument is a listbox, a combobox, +''' a button or a tabpagecontainer. ''' or insert a new entry in the _PageManagement array by radio button in the same group as the 1st argument ''' Args: ''' psControlName: name of the involved control ''' psControlTypes: comma-separated list of allowed control types -''' piMgtType: one of the PILOTCONTROL, TABCONTROL, BACKCONTROL, NEXTCONTROL constants +''' piMgtType: one of the PILOTCONTROL, TABCONTROL, BACKCONTROL, NEXTCONTROL, TABPAGE constants ''' plPageNumber: when > 0 the page to jump to when control is clicked -''' piListener: one of the ACTIONPERFORMED, ITEMSTATECHANGED constants +''' piListener: one of the ACTIONPERFORMED, ITEMSTATECHANGED, TABSELECTED constants Dim bRegister As Boolean ' Return value Dim oControl As Object ' 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 diff --git a/wizards/source/sfdialogs/SF_DialogControl.xba b/wizards/source/sfdialogs/SF_DialogControl.xba index 4ddc9e0e0608..4c15444e2fa8 100644 --- a/wizards/source/sfdialogs/SF_DialogControl.xba +++ b/wizards/source/sfdialogs/SF_DialogControl.xba @@ -123,6 +123,10 @@ Private _OnMouseDragged As String ' Script to invoke when mouse is dragge Private _OnMouseMoved As String ' Script to invoke when mouse is moved across the control Private _MouseMotionCounter As Integer ' Counts the number of events set on the listener ' --- +Private _TabPageContainerListener As Object ' com.sun.star.awt.XTabPageContainerListener +Private _OnTabSelected As String ' Script to invoke when a new tab is selected +Private _TabPageContainerCounter As Integer ' Counts the number of events set on the listener +' --- Private _TextListener As Object ' com.sun.star.awt.XTextListener Private _OnTextChanged As String ' Script to invoke when textual content has changed Private _TextCounter As Integer ' Counts the number of events set on the listener @@ -130,30 +134,34 @@ Private _TextCounter As Integer ' Counts the number of events set on the ' Table control attributes Private _ColumnWidths As Variant ' Array of column widths +' TabPageContainer attributes +Private _TabHeaders As Variant ' Array of tab page headers as strings + REM ============================================================ MODULE CONSTANTS -Private Const CTLBUTTON = "Button" -Private Const CTLCHECKBOX = "CheckBox" -Private Const CTLCOMBOBOX = "ComboBox" -Private Const CTLCURRENCYFIELD = "CurrencyField" -Private Const CTLDATEFIELD = "DateField" -Private Const CTLFILECONTROL = "FileControl" -Private Const CTLFIXEDLINE = "FixedLine" -Private Const CTLFIXEDTEXT = "FixedText" -Private Const CTLFORMATTEDFIELD = "FormattedField" -Private Const CTLGROUPBOX = "GroupBox" -Private Const CTLHYPERLINK = "Hyperlink" -Private Const CTLIMAGECONTROL = "ImageControl" -Private Const CTLLISTBOX = "ListBox" -Private Const CTLNUMERICFIELD = "NumericField" -Private Const CTLPATTERNFIELD = "PatternField" -Private Const CTLPROGRESSBAR = "ProgressBar" -Private Const CTLRADIOBUTTON = "RadioButton" -Private Const CTLSCROLLBAR = "ScrollBar" -Private Const CTLTABLECONTROL = "TableControl" -Private Const CTLTEXTFIELD = "TextField" -Private Const CTLTIMEFIELD = "TimeField" -Private Const CTLTREECONTROL = "TreeControl" +Private Const CTLBUTTON = "Button" +Private Const CTLCHECKBOX = "CheckBox" +Private Const CTLCOMBOBOX = "ComboBox" +Private Const CTLCURRENCYFIELD = "CurrencyField" +Private Const CTLDATEFIELD = "DateField" +Private Const CTLFILECONTROL = "FileControl" +Private Const CTLFIXEDLINE = "FixedLine" +Private Const CTLFIXEDTEXT = "FixedText" +Private Const CTLFORMATTEDFIELD = "FormattedField" +Private Const CTLGROUPBOX = "GroupBox" +Private Const CTLHYPERLINK = "Hyperlink" +Private Const CTLIMAGECONTROL = "ImageControl" +Private Const CTLLISTBOX = "ListBox" +Private Const CTLNUMERICFIELD = "NumericField" +Private Const CTLPATTERNFIELD = "PatternField" +Private Const CTLPROGRESSBAR = "ProgressBar" +Private Const CTLRADIOBUTTON = "RadioButton" +Private Const CTLSCROLLBAR = "ScrollBar" +Private Const CTLTABLECONTROL = "TableControl" +Private Const CTLTABPAGECONTAINER = "TabPageContainer" +Private Const CTLTEXTFIELD = "TextField" +Private Const CTLTIMEFIELD = "TimeField" +Private Const CTLTREECONTROL = "TreeControl" REM ====================================================== CONSTRUCTOR/DESTRUCTOR @@ -211,11 +219,15 @@ Private Sub Class_Initialize() Set _ItemListener = Nothing _OnItemStateChanged = "" _ItemCounter = 0 + Set _TabPageContainerListener = Nothing + _OnTabSelected = "" + _TabPageContainerCounter = 0 Set _TextListener = Nothing _OnTextChanged = "" _TextCounter = 0 _ColumnWidths = Array() + _TabHeaders = Array() End Sub ' SFDialogs.SF_DialogControl Constructor REM ----------------------------------------------------------------------------- @@ -564,6 +576,18 @@ Property Let OnNodeSelected(Optional ByVal pvOnNodeSelected As Variant) _PropertySet("OnNodeSelected", pvOnNodeSelected) End Property ' SFDialogs.SF_DialogControl.OnNodeSelected (let) +REM ----------------------------------------------------------------------------- +Property Get OnTabSelected() As Variant +''' Get the script associated with the OnTabSelected event + OnTabSelected = _PropertyGet("OnTabSelected") +End Property ' SFDialogs.SF_DialogControl.OnTabSelected (get) + +REM ----------------------------------------------------------------------------- +Property Let OnTabSelected(Optional ByVal pvTextChanged As Variant) +''' Set the updatable property OnTabSelected + _PropertySet("OnTabSelected", pvTextChanged) +End Property ' SFDialogs.SF_DialogControl.OnTabSelected (let) + REM ----------------------------------------------------------------------------- Property Get OnTextChanged() As Variant ''' Get the script associated with the OnTextChanged event @@ -1161,6 +1185,7 @@ Public Function Properties() As Variant , "OnMouseReleased" _ , "OnNodeExpanded" _ , "OnNodeSelected" _ + , "OnTabSelected" _ , "OnTextChanged" _ , "Page" _ , "Parent" _ @@ -1675,6 +1700,8 @@ Private Function _GetListener(ByVal psEventName As String) As String _GetListener = "XMouseMotionListener" Case UCase("OnMouseEntered"), UCase("OnMouseExited"), UCase("OnMousePressed"), UCase("OnMouseReleased") _GetListener = "XMouseListener" + Case UCase("OnTabSelected") + _GetListener = "tab.XTabPageContainerListener" Case UCase("OnTextChanged") _GetListener = "XTextListener" Case Else @@ -1714,6 +1741,8 @@ Try: _ControlType = CTLTABLECONTROL Set _GridColumnModel = _ControlModel.ColumnModel Set _GridDataModel = _ControlModel.GridDataModel + Case "UnoControlTabPageContainerModel" + _ControlType = CTLTABPAGECONTAINER Case Else : _ControlType = sType End Select @@ -1893,7 +1922,7 @@ Const cstSubArgs = "" Case UCase("OnActionPerformed"), UCase("OnAdjustmentValueChanged"), UCase("OnFocusGained"), UCase("OnFocusLost") _ , UCase("OnItemStateChanged"), UCase("OnKeyPressed"), UCase("OnKeyReleased") _ , UCase("OnMouseDragged"), UCase("OnMouseEntered"), UCase("OnMouseExited"), UCase("OnMouseMoved") _ - , UCase("OnMousePressed"), UCase("OnMouseReleased"), UCase("OnTextChanged") + , UCase("OnMousePressed"), UCase("OnMouseReleased"), UCase("OnTabSelected"), UCase("OnTextChanged") Set oControlEvents = _ControlModel.getEvents() sEventName = "com.sun.star.awt." & _GetListener(psProperty) & "::" & _GetEventName(psProperty) If oControlEvents.hasByName(sEventName) Then @@ -1914,6 +1943,7 @@ Const cstSubArgs = "" Case UCase("OnMouseMoved") : _PropertyGet = _OnMouseMoved Case UCase("OnMousePressed") : _PropertyGet = _OnMousePressed Case UCase("OnMouseReleased") : _PropertyGet = _OnMouseReleased + Case UCase("OnTabSelected") : _PropertyGet = _OnTabSelected Case UCase("OnTextChanged") : _PropertyGet = _OnTextChanged Case Else : _PropertyGet = "" End Select @@ -2051,6 +2081,8 @@ Const cstSubArgs = "" If lIndex >= 0 Then vGet = _GridDataModel.getRowData(lIndex) End If End If + Case CTLTABPAGECONTAINER + If oSession.HasUnoProperty(_ControlView, "ActiveTabPageID") Then vGet = _ControlView.ActiveTabPageID Else vGet = 0 Case CTLTIMEFIELD vGet = CDate(0) If oSession.HasUnoProperty(_ControlModel, "Time") Then @@ -2125,7 +2157,8 @@ Dim lFormatKey As Long ' Format index for formatted fields Dim oLocale As Object ' com.sun.star.lang.Locale Dim vSelection As Variant ' Alias of Model.SelectedItems Dim vList As Variant ' Alias of Model.StringItemList -Dim lIndex As Long ' Index in StringItemList +Dim lIndex As Long ' Index in StringItemList or _TabHeaders +Dim vValue As Variant ' Alias of pvValue Dim sItem As String ' A single item Dim vCtlTypes As Variant ' Array of allowed control types Dim i As Long @@ -2276,7 +2309,7 @@ Const cstSubArgs = "Value" Case UCase("OnActionPerformed"), UCase("OnAdjustmentValueChanged"), UCase("OnFocusGained"), UCase("OnFocusLost") _ , UCase("OnItemStateChanged"), UCase("OnKeyPressed"), UCase("OnKeyReleased") _ , UCase("OnMouseDragged"), UCase("OnMouseEntered"), UCase("OnMouseExited"), UCase("OnMouseMoved") _ - , UCase("OnMousePressed"), UCase("OnMouseReleased"), UCase("OnTextChanged") + , UCase("OnMousePressed"), UCase("OnMouseReleased"), UCase("OnTabSelected"), UCase("OnTextChanged") If Not ScriptForge.SF_Utils._Validate(pvValue, psProperty, V_STRING) Then GoTo Catch ' Check control type for not universal event types Select Case UCase(psProperty) @@ -2287,6 +2320,8 @@ Const cstSubArgs = "Value" End Select Case UCase("OnAdjustmentValueChanged") If _ControlType <> CTLSCROLLBAR Then GoTo CatchType + Case UCase("OnTabSelected") + If _ControlType <> CTLTABPAGECONTAINER Then GoTo CatchType Case UCase("OnTextChanged") Select Case _ControlType Case CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFORMATTEDFIELD _ @@ -2460,6 +2495,17 @@ Const cstSubArgs = "Value" If pvValue > _ControlModel.ScrollValueMax Then pvValue = _ControlModel.ScrollValueMax End If If oSession.HasUnoProperty(_ControlModel, "ScrollValue") Then _ControlModel.ScrollValue = pvValue + Case CTLTABPAGECONTAINER + If Not ScriptForge.SF_Utils._Validate(pvValue, "Value", Array(V_STRING, ScriptForge.V_NUMERIC)) Then GoTo Finally + If oSession.HasUNOProperty(_ControlView, "ActiveTabPageID") 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 >= 1 And vValue <= _ControlModel.Count Then _ControlView.ActiveTabPageID = vValue + End If Case CTLTIMEFIELD If Not ScriptForge.SF_Utils._Validate(pvValue, "Value", V_DATE) Then GoTo Finally If oSession.HasUnoProperty(_ControlModel, "Time") Then diff --git a/wizards/source/sfdialogs/SF_DialogListener.xba b/wizards/source/sfdialogs/SF_DialogListener.xba index 8975c2d8257a..9281e9b69b53 100644 --- a/wizards/source/sfdialogs/SF_DialogListener.xba +++ b/wizards/source/sfdialogs/SF_DialogListener.xba @@ -32,7 +32,7 @@ Option Explicit ''' The described events are processed thru UNO listeners ''' ''' "On" events defined by code, prefix = _SFACTION_, _SFADJUST_, _SFFOCUS_, _SFKEY_, _SFMOUSE_, -''' ----------- _SFMOVE_, _SFITEM_, _SFADJUST_, _SFTEXT_ +''' ----------- _SFMOVE_, _SFITEM_, _SFADJUST_, _SFSELTAB_, _SFTEXT_ ''' All event types applicable on dialogs and control types <> TreeControl ''' The events MUST NOT be preset in the Basic IDE ''' @@ -200,6 +200,37 @@ Finally: Exit Sub End Sub ' SFDialogs.SF_Dialoglistener._SFTAB_itemStateChanged +REM ----------------------------------------------------------------------------- +Public Sub _SFTAB_tabPageActivated(Optional ByRef poEvent As Object) +''' Event triggered by a tab page container configured through the dialog page manager + +Dim oControl As Object ' The DialogControl instance having caused the event +Dim sName As String ' Control name +Dim oDialog As Object ' The parent Dialog instance +Dim oPageManager As Object ' An entry in dialog._PageManagement + +Check: + On Local Error GoTo Finally ' Never interrupt !! + Set oControl = CreateScriptService("DialogEvent", poEvent) + If IsNull(oControl) Then GoTo Finally + +Try: + Set oDialog = oControl.Parent + With oDialog + sName = oControl.Name + ' 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 ' 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) +''' Triggered by the OnTabSelected event in a dialog control +''' The event is triggered thru a com.sun.star.awt.tab.XTabPageContainerListener +''' The argument is passed to a user routine stored in the SF_DialogControl instance +''' as a scripting framework URI + + _TriggerEvent("tabPageActivated", poEvent) + +End Sub ' SFDialogs.SF_Dialoglistener._SFSELTAB_tabPageActivated + +REM ----------------------------------------------------------------------------- +Public Sub _SFSELTAB_disposing() +End Sub + REM ----------------------------------------------------------------------------- Public Sub _SFTEXT_textChanged(Optional ByRef poEvent As Object) ''' Triggered by the OnTextChanged event in a dialog control @@ -393,7 +439,7 @@ Public Sub _SFTEXT_textChanged(Optional ByRef poEvent As Object) _TriggerEvent("textChanged", poEvent) -End Sub ' SFDialogs.SF_Dialoglistener. _SFTEXT_textChanged +End Sub ' SFDialogs.SF_Dialoglistener._SFTEXT_textChanged REM ----------------------------------------------------------------------------- Public Sub _SFTEXT_disposing() @@ -544,6 +590,9 @@ Try: Case UCase("OnMouseReleased") sPrevious = ._OnMouseReleased ._OnMouseReleased = psScript + Case UCase("OnTabSelected") + sPrevious = ._OnTabSelected + ._OnTabSelected = psScript Case UCase("OnTextChanged") sPrevious = ._OnTextChanged ._OnTextChanged = psScript @@ -638,6 +687,17 @@ Try: If Not IsNull(._MouseMotionListener) Then oView.removeMouseMotionListener(._MouseMotionListener) ._MouseMotionCounter = 0 ' Prevent negative values End If + Case "tab.XTabPageContainerListener" + ._TabPageContainerCounter = ._TabPageContainerCounter + iCounterIncrement + If ._TabPageContainerCounter = 1 Then + If IsNull(._TabPageContainerListener) Then + Set ._TabPageContainerListener = CreateUnoListener("SFDialogs.SF_DialogListener._SFSELTAB_", cstPrefix & sListener) + End If + If iCounterIncrement = 1 Then oView.addTabPageContainerListener(._TabPageContainerListener) + ElseIf ._TabPageContainerCounter <= 0 Then + If Not IsNull(._TabPageContainerListener) Then oView.removeTabPageContainerListener(._TabPageContainerListener) + ._TabPageContainerCounter = 0 ' Prevent negative values + End If Case "XTextListener" ._TextCounter = ._TextCounter + iCounterIncrement If ._TextCounter = 1 Then @@ -691,6 +751,7 @@ Try: Case "mouseMoved" : sScript = .OnMouseMoved Case "mousePressed" : sScript = .OnMousePressed Case "mouseReleased" : sScript = .OnMouseReleased + Case "tabPageActivated" : sScript = .OnTabSelected Case "textChanged" : sScript = .OnTextChanged Case Else : sScript = "" ' Should not happen End Select diff --git a/wizards/source/sfdialogs/script.xlb b/wizards/source/sfdialogs/script.xlb index 199ba3621c19..59263472b3a1 100644 --- a/wizards/source/sfdialogs/script.xlb +++ b/wizards/source/sfdialogs/script.xlb @@ -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> \ No newline at end of file