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>