sw/qa/uitest/ui/misc/misc.py                |   12 +++
 sw/source/ui/misc/contentcontroldlg.cxx     |   36 +++++++++++
 sw/source/uibase/inc/contentcontroldlg.hxx  |    2 
 sw/uiconfig/swriter/ui/contentcontroldlg.ui |   85 +++++++++++++++++++++++++---
 4 files changed, 128 insertions(+), 7 deletions(-)

New commits:
commit 0d2a962c363632a890a994e7e143099c53ac4283
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Thu Feb 23 15:40:02 2023 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Feb 27 07:26:17 2023 +0000

    tdf#151548 sw content controls: add UI for Id and TabIndex
    
    This is my first go at adding anything to the UI.
    (I've done some fixing of other people's design,
    but never created anything new myself.)
    
    I took all my inspiration from Miklos'
    add110bad816fadeb96e7af0d4689389c04c263e.
    
    In the first iteration I did a fancy "same as id"
    scenario. But ID-as-unsigned, securing unique IDs,
    and English-only number recognition
    sadly made me decide to drop the fancy features.
    
    Now, both are simple, stand-alone spinbuttons
    that depend on tooltips to guide user input, not fancy comboboxes.
    
    It is important for the ID to display as unsigned,
    since that is how it is used as a "name" in VBA.
    It should be copy-pasteable for use in VBA programming.
    
    It is useful for the TABINDEX to display as signed,
    since it allows entering a -1 to disable tab navigation to the control.
    
    make UITest_sw_ui_misc
    
    Change-Id: Ia7c99888e60c33ac39616b24c7c1715604c3ec69
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147591
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/uitest/ui/misc/misc.py b/sw/qa/uitest/ui/misc/misc.py
index 2b6307cefb61..8af00054a5e6 100644
--- a/sw/qa/uitest/ui/misc/misc.py
+++ b/sw/qa/uitest/ui/misc/misc.py
@@ -26,6 +26,7 @@ class TestTmpdlg(UITestCase):
             contentControl = portion.ContentControl
             contentControl.Alias = "my alias"
             contentControl.Tag = "my tag"
+            contentControl.TabIndex = "1"
             listItems = contentControl.ListItems
             self.assertEqual(len(listItems), 1)
             self.assertEqual(listItems[0][0].Name, "DisplayText")
@@ -42,6 +43,15 @@ class TestTmpdlg(UITestCase):
                 self.assertEqual(get_state_as_dict(xTag)['Text'], "my tag")
                 type_text(xTag, "new tag ")
                 xAdd = xDialog.getChild("add")
+
+                xId = xDialog.getChild("idspinbutton")
+                self.assertEqual(get_state_as_dict(xId)['Text'], "0")
+                type_text(xId, "429496729") # added in front, making it 
4294967290
+
+                xTabIndex = xDialog.getChild("tabindexspinbutton")
+                self.assertEqual(get_state_as_dict(xTabIndex)['Text'], "1")
+                type_text(xTabIndex, "-") # add a minus in front, making it -1
+
                 with self.ui_test.execute_blocking_action(xAdd.executeAction, 
args=('CLICK', ())) as xSubDialog:
                     xDisplayName = xSubDialog.getChild("displayname")
                     type_text(xDisplayName, "Foo Bar")
@@ -57,6 +67,8 @@ class TestTmpdlg(UITestCase):
             self.assertEqual(listItems[1][1].Value, "foo-bar")
             self.assertEqual(contentControl.Alias, "new alias my alias")
             self.assertEqual(contentControl.Tag, "new tag my tag")
+            self.assertEqual(contentControl.Id, -6) # stored as signed, 
displays as unsigned
+            self.assertEqual(contentControl.TabIndex, 4294967295) # stored as 
unsigned, displays as signed
 
 
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/ui/misc/contentcontroldlg.cxx 
b/sw/source/ui/misc/contentcontroldlg.cxx
index 3aeeab3c6306..f318fa6a699e 100644
--- a/sw/source/ui/misc/contentcontroldlg.cxx
+++ b/sw/source/ui/misc/contentcontroldlg.cxx
@@ -40,6 +40,8 @@ SwContentControlDlg::SwContentControlDlg(weld::Window* 
pParent, SwWrtShell& rWrt
     , 
m_xShowingPlaceHolderCB(m_xBuilder->weld_check_button("showing_place_holder"))
     , m_xAlias(m_xBuilder->weld_entry("aliasentry"))
     , m_xTag(m_xBuilder->weld_entry("tagentry"))
+    , m_xId(m_xBuilder->weld_spin_button("idspinbutton"))
+    , m_xTabIndex(m_xBuilder->weld_spin_button("tabindexspinbutton"))
     , m_xCheckboxFrame(m_xBuilder->weld_frame("checkboxframe"))
     , m_xCheckedState(m_xBuilder->weld_entry("checkboxcheckedentry"))
     , m_xCheckedStateBtn(m_xBuilder->weld_button("btncheckboxchecked"))
@@ -108,6 +110,28 @@ SwContentControlDlg::SwContentControlDlg(weld::Window* 
pParent, SwWrtShell& rWrt
         m_xTag->save_value();
     }
 
+    // The ID is supposed to be a unique ID, but it isn't really used for much
+    // and in MS Word it (supposedly) is automatically made unique if it is a 
duplicate.
+    // The main purpose for having it here is lookup, not modification,
+    // since AFAIK the only use of the ID is for VBA macro name lookup.
+    // Since it is used as unsigned in VBA, make the UI display the unsigned 
values too.
+    m_xId->set_range(0, SAL_MAX_UINT32);
+    m_xId->set_increments(1, 10);
+    const sal_uInt32 nId = static_cast<sal_uInt32>(m_pContentControl->GetId());
+    m_xId->set_value(nId);
+    // a one-time chance to set the ID - only allow setting it when it is 
undefined.
+    if (nId)
+        m_xId->set_editable(false); // still available for copy/paste
+    m_xId->save_value();
+
+    // And on the contrary, the tabIndex is stored as unsigned,
+    // even though humanly speaking it is much nicer to use -1 to indicate a 
no tab stop. Oh well.
+    m_xTabIndex->set_range(SAL_MIN_INT32, SAL_MAX_INT32);
+    m_xTabIndex->set_increments(1, 10);
+    const sal_Int32 nTabIndex = 
static_cast<sal_Int32>(m_pContentControl->GetTabIndex());
+    m_xTabIndex->set_value(nTabIndex);
+    m_xTabIndex->save_value();
+
     if (m_pContentControl->GetCheckbox())
     {
         m_xCheckedState->set_text(m_pContentControl->GetCheckedState());
@@ -206,6 +230,18 @@ IMPL_LINK_NOARG(SwContentControlDlg, OkHdl, weld::Button&, 
void)
         bChanged = true;
     }
 
+    if (m_xId->get_value_changed_from_saved())
+    {
+        
m_pContentControl->SetId(o3tl::narrowing<sal_Int32>(m_xId->get_value()));
+        bChanged = true;
+    }
+
+    if (m_xTabIndex->get_value_changed_from_saved())
+    {
+        
m_pContentControl->SetTabIndex(o3tl::narrowing<sal_uInt32>(m_xTabIndex->get_value()));
+        bChanged = true;
+    }
+
     if (m_xCheckedState->get_value_changed_from_saved())
     {
         m_pContentControl->SetCheckedState(m_xCheckedState->get_text());
diff --git a/sw/source/uibase/inc/contentcontroldlg.hxx 
b/sw/source/uibase/inc/contentcontroldlg.hxx
index efeadbfa76b8..8fbc57d9ad47 100644
--- a/sw/source/uibase/inc/contentcontroldlg.hxx
+++ b/sw/source/uibase/inc/contentcontroldlg.hxx
@@ -40,6 +40,8 @@ class SwContentControlDlg final : public SfxDialogController
     std::unique_ptr<weld::CheckButton> m_xShowingPlaceHolderCB;
     std::unique_ptr<weld::Entry> m_xAlias;
     std::unique_ptr<weld::Entry> m_xTag;
+    std::unique_ptr<weld::SpinButton> m_xId;
+    std::unique_ptr<weld::SpinButton> m_xTabIndex;
     std::unique_ptr<weld::Frame> m_xCheckboxFrame;
     std::unique_ptr<weld::Entry> m_xCheckedState;
     std::unique_ptr<weld::Button> m_xCheckedStateBtn;
diff --git a/sw/uiconfig/swriter/ui/contentcontroldlg.ui 
b/sw/uiconfig/swriter/ui/contentcontroldlg.ui
index 8918a53a4a72..b4b403e833a3 100644
--- a/sw/uiconfig/swriter/ui/contentcontroldlg.ui
+++ b/sw/uiconfig/swriter/ui/contentcontroldlg.ui
@@ -91,7 +91,7 @@
           </packing>
         </child>
         <child>
-          <!-- n-columns=2 n-rows=3 -->
+          <!-- n-columns=4 n-rows=3 -->
           <object class="GtkGrid">
             <property name="visible">True</property>
             <property name="can-focus">False</property>
@@ -128,12 +128,25 @@
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="taglabel">
+              <object class="GtkEntry" id="aliasentry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="truncate-multiline">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="idlabel">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
-                <property name="label" translatable="yes" 
context="contentcontroldlg|taglabel">Tag:</property>
-                <property name="mnemonic-widget">tagentry</property>
+                <property name="label" translatable="yes" 
context="contentcontroldlg|idlabel">Id:</property>
                 <property name="xalign">0</property>
+                <accessibility>
+                  <relation type="label-for" target="idspinbutton"/>
+                </accessibility>
               </object>
               <packing>
                 <property name="left-attach">0</property>
@@ -141,13 +154,47 @@
               </packing>
             </child>
             <child>
-              <object class="GtkEntry" id="aliasentry">
+              <object class="GtkLabel" id="tabindexlabel">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="contentcontroldlg|tabindexlabel">Tab order:</property>
+                <accessibility>
+                  <relation type="label-for" target="tabindexspinbutton"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left-attach">2</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="idspinbutton">
                 <property name="visible">True</property>
                 <property name="can-focus">True</property>
-                <property name="truncate-multiline">True</property>
+                <property name="input-purpose">number</property>
+                <property name="input-hints">GTK_INPUT_HINT_NO_SPELLCHECK | 
GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE</property>
+                <property name="snap-to-ticks">True</property>
+                <property name="numeric">True</property>
+                <property name="wrap">True</property>
+                <accessibility>
+                  <relation type="labelled-by" target="idlabel"/>
+                </accessibility>
               </object>
               <packing>
                 <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="taglabel">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="contentcontroldlg|taglabel">Tag:</property>
+                <property name="mnemonic-widget">tagentry</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="left-attach">2</property>
                 <property name="top-attach">1</property>
               </packing>
             </child>
@@ -158,10 +205,34 @@
                 <property name="truncate-multiline">True</property>
               </object>
               <packing>
-                <property name="left-attach">1</property>
+                <property name="left-attach">3</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="tabindexspinbutton">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="primary-icon-tooltip-text" translatable="yes" 
context="contentcontroldlg:tabindexspinbutton">Keyboard tab navigation order: 
-1 to exclude from tab stop</property>
+                <property name="input-purpose">number</property>
+                <property name="input-hints">GTK_INPUT_HINT_NO_SPELLCHECK | 
GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE</property>
+                <property name="snap-to-ticks">True</property>
+                <property name="numeric">True</property>
+                <accessibility>
+                  <relation type="labelled-by" target="tabindexlabel"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left-attach">3</property>
                 <property name="top-attach">2</property>
               </packing>
             </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>

Reply via email to