[Libreoffice-commits] core.git: Branch 'feature/msforms' - 7 commits - include/vcl sw/inc sw/Library_sw.mk sw/qa sw/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Fri Mar 8 16:02:25 UTC 2019
Rebased ref, commits from common ancestor:
commit 9011cded607e29eb07686535690f6c867bcf3035
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Thu Mar 7 12:37:00 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:46 2019 +0100
MSForms: UITest for drop-down form field's propertis dialog
Also changed the dialog's code a bit to work correctly with
the UI test too.
Change-Id: Idec85746f5ada979518d1fb0e09dc1c8e22ba7c1
diff --git a/sw/qa/uitest/writer_tests/data/drop_down_form_field.doc b/sw/qa/uitest/writer_tests/data/drop_down_form_field.doc
new file mode 100644
index 000000000000..cf94a1fdada1
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/drop_down_form_field.doc differ
diff --git a/sw/qa/uitest/writer_tests/data/drop_down_form_field.docx b/sw/qa/uitest/writer_tests/data/drop_down_form_field.docx
new file mode 100644
index 000000000000..d039cd2b60d3
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/drop_down_form_field.docx differ
diff --git a/sw/qa/uitest/writer_tests/data/drop_down_form_field.odt b/sw/qa/uitest/writer_tests/data/drop_down_form_field.odt
new file mode 100644
index 000000000000..f27b1157418c
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/drop_down_form_field.odt differ
diff --git a/sw/qa/uitest/writer_tests/data/empty_drop_down_form_field.odt b/sw/qa/uitest/writer_tests/data/empty_drop_down_form_field.odt
new file mode 100644
index 000000000000..bd85dc2a902d
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/empty_drop_down_form_field.odt differ
diff --git a/sw/qa/uitest/writer_tests5/DropDownFormFieldPropertiesDialog.py b/sw/qa/uitest/writer_tests5/DropDownFormFieldPropertiesDialog.py
new file mode 100644
index 000000000000..5628e83992e1
--- /dev/null
+++ b/sw/qa/uitest/writer_tests5/DropDownFormFieldPropertiesDialog.py
@@ -0,0 +1,266 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+from uitest.framework import UITestCase
+from uitest.uihelper.common import get_state_as_dict
+from libreoffice.uno.propertyvalue import mkPropertyValues
+import org.libreoffice.unotest
+import pathlib
+import time
+
+def get_url_for_data_file(file_name):
+ return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri()
+
+class dropDownFormFieldDialog(UITestCase):
+
+ def test_add_new_items(self):
+
+ # open a file with an empty form field
+ writer_doc = self.ui_test.load_file(get_url_for_data_file("empty_drop_down_form_field.odt"))
+ document = self.ui_test.get_component()
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+
+ # open the dialog (cursor is at the field)
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemEntry = xDialog.getChild("item_entry")
+ addButton = xDialog.getChild("add_button")
+ itemsList = xDialog.getChild("items_treeview")
+
+ # initial state
+ self.assertEqual(get_state_as_dict(itemEntry)["Text"], "")
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "false")
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "0")
+
+ # add some new items
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"1000"}))
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "true")
+ addButton.executeAction("CLICK", tuple())
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "false")
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"2000"}))
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"3000"}))
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"4000"}))
+ addButton.executeAction("CLICK", tuple())
+
+ # check whether the items are there in the list
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "2000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "4000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ # check whether items are the same after reopening
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemsList = xDialog.getChild("items_treeview")
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "2000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "4000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ self.ui_test.close_doc()
+
+ def test_remove_items(self):
+
+ # open a file with an empty form field
+ writer_doc = self.ui_test.load_file(get_url_for_data_file("empty_drop_down_form_field.odt"))
+ document = self.ui_test.get_component()
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+
+ # open the dialog (cursor is at the field)
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemEntry = xDialog.getChild("item_entry")
+ addButton = xDialog.getChild("add_button")
+ itemsList = xDialog.getChild("items_treeview")
+ removeButton = xDialog.getChild("remove_button")
+
+ # initial state
+ self.assertEqual(get_state_as_dict(itemEntry)["Text"], "")
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "false")
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "0")
+ self.assertEqual(get_state_as_dict(removeButton)["Enabled"], "false")
+
+ # add some new items
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"1000"}))
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "true")
+ addButton.executeAction("CLICK", tuple())
+ self.assertEqual(get_state_as_dict(removeButton)["Enabled"], "true")
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"2000"}))
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"3000"}))
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"4000"}))
+ addButton.executeAction("CLICK", tuple())
+
+ # check whether the items are there in the list
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "2000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "4000")
+
+ # select an item from the list and remove it
+ itemsList.getChild("1").executeAction("SELECT", tuple());
+ removeButton.executeAction("CLICK", tuple())
+
+ # check whether the right item was removed
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "3")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "4000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ # check whether items are the same after reopening
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemsList = xDialog.getChild("items_treeview")
+ removeButton = xDialog.getChild("remove_button")
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "3")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "4000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ self.ui_test.close_doc()
+
+ def test_move_items(self):
+
+ # open a file with an empty form field
+ writer_doc = self.ui_test.load_file(get_url_for_data_file("empty_drop_down_form_field.odt"))
+ document = self.ui_test.get_component()
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+
+ # open the dialog (cursor is at the field)
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemEntry = xDialog.getChild("item_entry")
+ addButton = xDialog.getChild("add_button")
+ itemsList = xDialog.getChild("items_treeview")
+ upButton = xDialog.getChild("up_button")
+ downButton = xDialog.getChild("down_button")
+
+ # initial state
+ self.assertEqual(get_state_as_dict(itemEntry)["Text"], "")
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "false")
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "0")
+ self.assertEqual(get_state_as_dict(upButton)["Enabled"], "false")
+ self.assertEqual(get_state_as_dict(downButton)["Enabled"], "false")
+
+ # add some new items
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"1000"}))
+ self.assertEqual(get_state_as_dict(addButton)["Enabled"], "true")
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"2000"}))
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"3000"}))
+ addButton.executeAction("CLICK", tuple())
+ itemEntry.executeAction("TYPE", mkPropertyValues({"TEXT":"4000"}))
+ addButton.executeAction("CLICK", tuple())
+
+ # check whether the items are there in the list
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "2000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "4000")
+
+ # select an item from the list and move it up
+ itemsList.getChild("1").executeAction("SELECT", tuple())
+ self.assertEqual(get_state_as_dict(upButton)["Enabled"], "true")
+ self.assertEqual(get_state_as_dict(downButton)["Enabled"], "true")
+ upButton.executeAction("CLICK", tuple())
+ self.assertEqual(get_state_as_dict(upButton)["Enabled"], "false")
+ self.assertEqual(get_state_as_dict(downButton)["Enabled"], "true")
+
+ # check whether the item was correctly moved
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "2000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "4000")
+
+ # move down the selected item
+ downButton.executeAction("CLICK", tuple())
+ downButton.executeAction("CLICK", tuple())
+ downButton.executeAction("CLICK", tuple())
+ self.assertEqual(get_state_as_dict(upButton)["Enabled"], "true")
+ self.assertEqual(get_state_as_dict(downButton)["Enabled"], "false")
+
+ # check whether the item was correctly moved
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "4000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "2000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ # check whether items are the same after reopening
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemsList = xDialog.getChild("items_treeview")
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "4000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "2000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ self.ui_test.close_doc()
+
+ def test_drop_down_after_import(self):
+
+ files = ["drop_down_form_field.odt", "drop_down_form_field.doc", "drop_down_form_field.docx"]
+ for file in files:
+ # open a file with a drop-down for field with items and selection
+ writer_doc = self.ui_test.load_file(get_url_for_data_file(file))
+ document = self.ui_test.get_component()
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+
+ # open the dialog (cursor is at the field)
+ self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+ xDialog = self.xUITest.getTopFocusWindow()
+
+ itemsList = xDialog.getChild("items_treeview")
+
+ # check whether the items are there in the list
+ self.assertEqual(get_state_as_dict(itemsList)["Children"], "4")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("0"))["Text"], "1000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("1"))["Text"], "2000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("2"))["Text"], "3000")
+ self.assertEqual(get_state_as_dict(itemsList.getChild("3"))["Text"], "4000")
+
+ self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "3000")
+
+ xOKBtn = xDialog.getChild("ok")
+ self.ui_test.close_dialog_through_button(xOKBtn)
+
+ self.ui_test.close_doc()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
index 3b30aaf9131a..ccd9829ce5f2 100644
--- a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
+++ b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
@@ -28,7 +28,7 @@ DropDownFormFieldDialog::DropDownFormFieldDialog(weld::Window* pParent,
, m_xListDownButton(m_xBuilder->weld_button("down_button"))
{
m_xListItemEntry->connect_key_press(LINK(this, DropDownFormFieldDialog, KeyPressedHdl));
- m_xListItemEntry->connect_key_release(LINK(this, DropDownFormFieldDialog, KeyReleasedHdl));
+ m_xListItemEntry->connect_changed(LINK(this, DropDownFormFieldDialog, EntryChangedHdl));
m_xListItemsTreeView->set_size_request(m_xListItemEntry->get_preferred_size().Width(),
m_xListItemEntry->get_preferred_size().Height() * 5);
@@ -57,10 +57,9 @@ IMPL_LINK(DropDownFormFieldDialog, KeyPressedHdl, const KeyEvent&, rEvent, bool)
return false;
}
-IMPL_LINK_NOARG(DropDownFormFieldDialog, KeyReleasedHdl, const KeyEvent&, bool)
+IMPL_LINK_NOARG(DropDownFormFieldDialog, EntryChangedHdl, weld::Entry&, void)
{
UpdateButtons();
- return false;
}
IMPL_LINK(DropDownFormFieldDialog, ButtonPushedHdl, weld::Button&, rButton, void)
diff --git a/sw/source/uibase/inc/DropDownFormFieldDialog.hxx b/sw/source/uibase/inc/DropDownFormFieldDialog.hxx
index 3fbb59db0ebc..aee5c5232845 100644
--- a/sw/source/uibase/inc/DropDownFormFieldDialog.hxx
+++ b/sw/source/uibase/inc/DropDownFormFieldDialog.hxx
@@ -41,7 +41,7 @@ private:
DECL_LINK(ListChangedHdl, weld::TreeView&, void);
DECL_LINK(KeyPressedHdl, const KeyEvent&, bool);
- DECL_LINK(KeyReleasedHdl, const KeyEvent&, bool);
+ DECL_LINK(EntryChangedHdl, weld::Entry&, void);
DECL_LINK(ButtonPushedHdl, weld::Button&, void);
void InitControls();
commit 0f0cf69fe3002fc31b84878f5e143f88c4f9e667
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Mar 6 16:58:17 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:46 2019 +0100
MSForms: Test insertion of form fields and undo / redo of this insertion.
Change-Id: I526faceab8eb1ce2f16d41ab1bed8cfb1bfcca24
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index dfd8d747f72f..697ec3533b59 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -30,6 +30,7 @@
#include <anchoredobject.hxx>
#include <swtypes.hxx>
#include <fmtornt.hxx>
+#include <xmloff/odffields.hxx>
namespace
{
@@ -89,6 +90,10 @@ public:
CPPUNIT_TEST(testTdf52391);
CPPUNIT_TEST(testTdf101873);
CPPUNIT_TEST(testTableWidth);
+ CPPUNIT_TEST(testTextFormFieldInsertion);
+ CPPUNIT_TEST(testCheckboxFormFieldInsertion);
+ CPPUNIT_TEST(testDropDownFormFieldInsertion);
+ CPPUNIT_TEST(testMixedFormFieldInsertion);
CPPUNIT_TEST_SUITE_END();
private:
@@ -937,6 +942,150 @@ void SwUiWriterTest2::testTableWidth()
getProperty<sal_Int16>(xTables->getByIndex(0), "RelativeWidth"));
}
+void SwUiWriterTest2::testTextFormFieldInsertion()
+{
+ load(DATA_DIRECTORY, "frame_size_export.docx");
+ SwDoc* pDoc = createDoc();
+ CPPUNIT_ASSERT(pDoc);
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT(pMarkAccess);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Insert a text form field
+ lcl_dispatchCommand(mxComponent, ".uno:TextFormField", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+ // Check whether the fieldmark is created
+ auto aIter = pMarkAccess->getAllMarksBegin();
+ CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+ CPPUNIT_ASSERT(pFieldmark);
+ CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMTEXT), pFieldmark->GetFieldname());
+
+ // The text form field has the placholder text in it
+ uno::Reference< text::XTextRange > xPara = getParagraph(1);
+ sal_Unicode vEnSpaces[5] = {8194, 8194, 8194, 8194, 8194};
+ CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
+
+ // Undo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+ xPara.set(getParagraph(1));
+ CPPUNIT_ASSERT(xPara->getString().isEmpty());
+
+ // Redo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ xPara.set(getParagraph(1));
+ CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
+}
+
+void SwUiWriterTest2::testCheckboxFormFieldInsertion()
+{
+ SwDoc* pDoc = createDoc();
+ CPPUNIT_ASSERT(pDoc);
+
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT(pMarkAccess);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Insert a checkbox form field
+ lcl_dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+ // Check whether the fieldmark is created
+ auto aIter = pMarkAccess->getAllMarksBegin();
+ CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+ CPPUNIT_ASSERT(pFieldmark);
+ CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
+ // The checkbox is not checked by default
+ ::sw::mark::ICheckboxFieldmark* pCheckBox = dynamic_cast< ::sw::mark::ICheckboxFieldmark* >(pFieldmark);
+ CPPUNIT_ASSERT(pCheckBox);
+ CPPUNIT_ASSERT(!pCheckBox->IsChecked());
+
+ // Undo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Redo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ aIter = pMarkAccess->getAllMarksBegin();
+ CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+ pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+ CPPUNIT_ASSERT(pFieldmark);
+ CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
+}
+
+void SwUiWriterTest2::testDropDownFormFieldInsertion()
+{
+ SwDoc* pDoc = createDoc();
+ CPPUNIT_ASSERT(pDoc);
+
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT(pMarkAccess);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Insert a drop-down form field
+ lcl_dispatchCommand(mxComponent, ".uno:DropDownFormField", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+ // Check whether the fieldmark is created
+ auto aIter = pMarkAccess->getAllMarksBegin();
+ CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+ CPPUNIT_ASSERT(pFieldmark);
+ CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
+ // Check drop down field's parameters. By default these params are not set
+ const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+ auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
+ CPPUNIT_ASSERT(pListEntries == pParameters->end());
+ auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
+ CPPUNIT_ASSERT(pResult == pParameters->end());
+
+ // Undo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Redo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+ aIter = pMarkAccess->getAllMarksBegin();
+ CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+ pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+ CPPUNIT_ASSERT(pFieldmark);
+ CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
+}
+
+void SwUiWriterTest2::testMixedFormFieldInsertion()
+{
+ SwDoc* pDoc = createDoc();
+ CPPUNIT_ASSERT(pDoc);
+
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT(pMarkAccess);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Insert fields
+ lcl_dispatchCommand(mxComponent, ".uno:TextFormField", {});
+ lcl_dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {});
+ lcl_dispatchCommand(mxComponent, ".uno:DropDownFormField", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
+
+ // Undo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+ lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+ lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+ // Redo insertion
+ lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+ lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+ lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2);
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit cadc78ba33b292e61bd34611a50bf2c823349b5f
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Mar 6 15:48:05 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:45 2019 +0100
MSForms: Add some extra comments for the new code
Change-Id: I4b70eb2164032623a12f9e703c660eca1d6768ec
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 68a97df6c3bc..fd55bc0dc747 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1225,7 +1225,7 @@ void Test::testDropDownFormField()
CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), vListEntries.getLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(-1), nSelection);
}
- else
+ else // The second one has list and also a selected item
{
CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), vListEntries.getLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), nSelection);
diff --git a/sw/source/core/inc/UndoBookmark.hxx b/sw/source/core/inc/UndoBookmark.hxx
index 7b9dd4fc68e5..3e2017d0721d 100644
--- a/sw/source/core/inc/UndoBookmark.hxx
+++ b/sw/source/core/inc/UndoBookmark.hxx
@@ -98,6 +98,7 @@ private:
virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
};
+/// Handling undo / redo of checkbox and drop-down form field insertion
class SwUndoInsNoTextFieldmark : public SwUndo
{
private:
@@ -110,6 +111,7 @@ public:
virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
};
+/// Handling undo / redo of text form field insertion
class SwUndoInsTextFieldmark : public SwUndo
{
private:
diff --git a/sw/source/core/inc/rolbck.hxx b/sw/source/core/inc/rolbck.hxx
index 3fde226b7acf..2feec7e6d973 100644
--- a/sw/source/core/inc/rolbck.hxx
+++ b/sw/source/core/inc/rolbck.hxx
@@ -262,6 +262,8 @@ class SwHistoryBookmark : public SwHistoryHint
std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
};
+/// History object containing all information used during undo / redo
+/// of checkbox and drop-down form field insertion.
class SwHistoryNoTextFieldmark : public SwHistoryHint
{
public:
@@ -275,6 +277,8 @@ class SwHistoryNoTextFieldmark : public SwHistoryHint
const sal_Int32 m_nContent;
};
+/// History object containing all information used during undo / redo
+/// of text form field insertion.
class SwHistoryTextFieldmark : public SwHistoryHint
{
public:
commit f2e0bb575ebbeca44050b1798ae120a36b54c812
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Tue Mar 5 21:07:32 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:45 2019 +0100
MSForms: Test legacy form field import / export for the supported formats.
Change-Id: Idbb80d097b21386e7d2673290a318d98b92125d5
diff --git a/sw/qa/extras/globalfilter/data/checkbox_form_field.odt b/sw/qa/extras/globalfilter/data/checkbox_form_field.odt
new file mode 100644
index 000000000000..14c931ed37da
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/checkbox_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/data/dropdown_form_field.odt b/sw/qa/extras/globalfilter/data/dropdown_form_field.odt
new file mode 100644
index 000000000000..caaa66acda8f
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/dropdown_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/data/text_form_field.odt b/sw/qa/extras/globalfilter/data/text_form_field.odt
new file mode 100644
index 000000000000..96af26f7708f
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/text_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index f9a6a60df823..68a97df6c3bc 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -25,6 +25,10 @@
#include <ndindex.hxx>
#include <pam.hxx>
#include <unotools/fltrcfg.hxx>
+#include <xmloff/odffields.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
class Test : public SwModelTestBase
{
@@ -45,6 +49,9 @@ public:
#endif
void testRedlineFlags();
void testBulletAsImage();
+ void testTextFormField();
+ void testCheckBoxFormField();
+ void testDropDownFormField();
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(testEmbeddedGraphicRoundtrip);
@@ -60,6 +67,9 @@ public:
#endif
CPPUNIT_TEST(testRedlineFlags);
CPPUNIT_TEST(testBulletAsImage);
+ CPPUNIT_TEST(testTextFormField);
+ CPPUNIT_TEST(testCheckBoxFormField);
+ CPPUNIT_TEST(testDropDownFormField);
CPPUNIT_TEST_SUITE_END();
};
@@ -1023,6 +1033,213 @@ void Test::testBulletAsImage()
}
}
+void Test::testTextFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ if (mxComponent.is())
+ mxComponent->dispose();
+ mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/text_form_field.odt"), "com.sun.star.text.TextDocument");
+
+ const OString sFailedMessage = OString("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= rFilterName;
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+ uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
+ xComponent->dispose();
+ mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
+
+ // Check the document after round trip
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ // We have two text form fields
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+ // Check whether all fieldmarks are text form fields
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMTEXT), pFieldmark->GetFieldname());
+ }
+
+ // In the first paragraph we have an empty text form field with the placeholder spaces
+ const uno::Reference< text::XTextRange > xPara = getParagraph(1);
+ sal_Unicode vEnSpaces[5] = {8194, 8194, 8194, 8194, 8194};
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), xPara->getString());
+
+ // In the second paragraph we have a set text
+ const uno::Reference< text::XTextRange > xPara2 = getParagraph(2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("xxxxx"), xPara2->getString());
+ }
+}
+
+void Test::testCheckBoxFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ if (mxComponent.is())
+ mxComponent->dispose();
+ mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/checkbox_form_field.odt"), "com.sun.star.text.TextDocument");
+
+ const OString sFailedMessage = OString("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= rFilterName;
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+ uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
+ xComponent->dispose();
+ mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
+
+ // Check the document after round trip
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ // We have two check box form fields
+ if(rFilterName == "Office Open XML Text")
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), pMarkAccess->getAllMarksCount());
+ else
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+ int nIndex = 0;
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+
+ if(rFilterName == "Office Open XML Text") // OOXML import also generates bookmarks
+ {
+ if(!pFieldmark)
+ continue;
+ }
+
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
+ ::sw::mark::ICheckboxFieldmark* pCheckBox = dynamic_cast< ::sw::mark::ICheckboxFieldmark* >(pFieldmark);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pCheckBox);
+
+ // The first one is unchecked, the other one is checked
+ if(nIndex == 0)
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !pCheckBox->IsChecked());
+ else
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pCheckBox->IsChecked());
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(2), nIndex);
+ }
+}
+
+void Test::testDropDownFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ if (mxComponent.is())
+ mxComponent->dispose();
+ mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/dropdown_form_field.odt"), "com.sun.star.text.TextDocument");
+
+ const OString sFailedMessage = OString("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= rFilterName;
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+ uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
+ xComponent->dispose();
+ mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
+
+ // Check the document after round trip
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+ int nIndex = 0;
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+
+ if(!pFieldmark)
+ continue;
+
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
+
+ // Check drop down field's parameters.
+ const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+ css::uno::Sequence<OUString> vListEntries;
+ sal_Int32 nSelection = -1;
+ auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
+ if (pListEntries != pParameters->end())
+ {
+ pListEntries->second >>= vListEntries;
+
+ if(vListEntries.getLength())
+ {
+ auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
+ if (pResult != pParameters->end())
+ {
+ pResult->second >>= nSelection;
+ }
+ }
+ }
+
+ // The first one is empty
+ if(nIndex == 0)
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), vListEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(-1), nSelection);
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), vListEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), nSelection);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("1000"), vListEntries[0]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2000"), vListEntries[1]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("3000"), vListEntries[2]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("4000"), vListEntries[3]);
+ }
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(2), nIndex);
+ }
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 2f248a996b7c..dfd8d747f72f 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -62,6 +62,10 @@ public:
void testTdf52391();
void testTdf101873();
void testTableWidth();
+ void testTextFormFieldInsertion();
+ void testCheckboxFormFieldInsertion();
+ void testDropDownFormFieldInsertion();
+ void testMixedFormFieldInsertion();
CPPUNIT_TEST_SUITE(SwUiWriterTest2);
CPPUNIT_TEST(testRedlineMoveInsertInDelete);
commit e309df9c8913eee8f6402a4a6d3e611704b8097c
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Tue Mar 5 19:40:08 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:44 2019 +0100
MSForms: Fix handling of drop-down form field after DOC import
In the properties dialog, code expected that the ODF_FORMDROPDOWN_RESULT
is not set in case of an empty list. This caused a crash.
The field popup window code expected that the list is not specified
when it is empty, but DOC import code sets ODF_FORMDROPDOWN_LISTENTRY
even if the list is empty.
Change-Id: If4c86fc5a08cdc578150afaa42ad7e86bdba9150
diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx
index d3a50b653dca..202622022fc1 100644
--- a/sw/source/core/crsr/DropDownFormFieldButton.cxx
+++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx
@@ -53,14 +53,15 @@ SwFieldDialog::SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, l
OUString sListKey = ODF_FORMDROPDOWN_LISTENTRY;
sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
= pParameters->find(sListKey);
+ css::uno::Sequence<OUString> vListEntries;
if (pListEntries != pParameters->end())
{
- css::uno::Sequence<OUString> vListEntries;
pListEntries->second >>= vListEntries;
for (OUString const& i : vListEntries)
aListBox->InsertEntry(i);
}
- else
+
+ if(vListEntries.getLength() == 0)
{
aListBox->InsertEntry(SwResId(STR_DROP_DOWN_EMPTY_LIST));
}
diff --git a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
index 09564999d321..3b30aaf9131a 100644
--- a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
+++ b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
@@ -119,7 +119,8 @@ void DropDownFormFieldDialog::InitControls()
{
sal_Int32 nSelection = -1;
pResult->second >>= nSelection;
- m_xListItemsTreeView->select_text(vListEntries[nSelection]);
+ if(vListEntries.getLength() > nSelection)
+ m_xListItemsTreeView->select_text(vListEntries[nSelection]);
}
}
}
commit 4d7287bb66b2e88a3d5d658b1820e0f1c7b02549
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Sat Mar 2 10:22:54 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:43 2019 +0100
MSForms: Open Control Properties dialog by double click for drop-down field
Change-Id: I66c0a7bad63d929ae346afe9d328d87dfa2c24ae
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 85d24b1d61c5..6ee65c5fdd7d 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -3364,6 +3364,21 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
// table.
rSh.SelTableBox();
}
+
+ SwContentAtPos aContentAtPos(IsAttrAtPos::FormControl);
+ if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
+ aContentAtPos.aFnd.pFieldmark != nullptr)
+ {
+ IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
+ if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN )
+ {
+ RstMBDownFlags();
+ rSh.getIDocumentMarkAccess()->ClearFieldActivation();
+ GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES);
+ return;
+ }
+ }
+
g_bHoldSelection = true;
return;
}
commit da80061c794d46f73de10d179d47c29d5ba514ab
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Mon Mar 4 20:52:38 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Mar 8 16:55:31 2019 +0100
MSForms: Add a drop-down button for drop-down form field
* Introduce a editing frame with a button for drop-down form field.
** The frame is mouse transparent.
** Pushing the button opens the popup window with the items of the field.
* The button is visible when the cursor is inside the field.
Change-Id: I5c7db138d14380899fee046c95a5afe14cfea213
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 4294c4f1e520..fff03ed1ffb5 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -598,7 +598,7 @@ protected:
SAL_DLLPRIVATE void ImplInvalidate( const vcl::Region* rRegion, InvalidateFlags nFlags );
- SAL_DLLPRIVATE WindowHitTest ImplHitTest( const Point& rFramePos );
+ virtual WindowHitTest ImplHitTest( const Point& rFramePos );
SAL_DLLPRIVATE void ImplSetMouseTransparent( bool bTransparent );
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index 939838d3dfc2..1cd8d8cb1613 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -150,6 +150,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
sw/source/core/crsr/crsrsh \
sw/source/core/crsr/crstrvl \
sw/source/core/crsr/crstrvl1 \
+ sw/source/core/crsr/DropDownFormFieldButton \
sw/source/core/crsr/findattr \
sw/source/core/crsr/findcoll \
sw/source/core/crsr/findfmt \
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index cbd523c012b1..d7111112612f 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -27,6 +27,7 @@
class SwPaM;
struct SwPosition;
class SwTextNode;
+class SwCursorShell;
namespace sw { namespace mark {
class SaveBookmark; // FIXME: Ugly: SaveBookmark is a core-internal class, and should not be used in the interface
@@ -258,6 +259,9 @@ class IDocumentMarkAccess
virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0;
virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0;
+ virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) = 0;
+ virtual void ClearFieldActivation() = 0;
+
// Annotation Marks
virtual const_iterator_t getAnnotationMarksBegin() const = 0;
virtual const_iterator_t getAnnotationMarksEnd() const = 0;
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index c8671f015e91..2093a2d8c14f 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -1328,6 +1328,9 @@
#define STR_MENU_UP NC_("STR_MENU_UP", "~Upwards")
#define STR_MENU_DOWN NC_("STR_MENU_DOWN", "Do~wnwards")
+
+#define STR_DROP_DOWN_EMPTY_LIST NC_("STR_DROP_DOWN_EMPTY_LIST", "No Item specified")
+
/*--------------------------------------------------------------------
Description: Classification strings
--------------------------------------------------------------------*/
diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index 66c61eef6dc5..d2fade9a1901 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -208,7 +208,6 @@ class SW_DLLPUBLIC SwView: public SfxViewShell
std::unique_ptr<SwPostItMgr> m_pPostItMgr;
SelectionType m_nSelectionType;
- VclPtr<FloatingWindow> m_pFieldPopup;
sal_uInt16 m_nPageCnt;
// current draw mode
@@ -265,8 +264,6 @@ class SW_DLLPUBLIC SwView: public SfxViewShell
DECL_DLLPRIVATE_LINK( TimeoutHdl, Timer*, void );
- DECL_DLLPRIVATE_LINK( FieldPopupModeEndHdl, FloatingWindow*, void );
-
inline long GetXScroll() const;
inline long GetYScroll() const;
SAL_DLLPRIVATE Point AlignToPixel(const Point& rPt) const;
@@ -423,7 +420,6 @@ public:
void SpellError(LanguageType eLang);
bool ExecSpellPopup( const Point& rPt );
- void ExecFieldPopup( const Point& rPt, sw::mark::IFieldmark *fieldBM );
void ExecSmartTagPopup( const Point& rPt );
DECL_LINK( OnlineSpellCallback, SpellCallbackInfo&, void );
diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx
new file mode 100644
index 000000000000..d3a50b653dca
--- /dev/null
+++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <DropDownFormFieldButton.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <edtwin.hxx>
+#include <basegfx/color/bcolortools.hxx>
+#include <viewopt.hxx>
+#include <bookmrk.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/event.hxx>
+#include <vcl/lstbox.hxx>
+#include <xmloff/odffields.hxx>
+#include <IMark.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <strings.hrc>
+
+/**
+ * Popup dialog for drop-down form field showing the list items of the field.
+ * The user can select the item using this popup while filling in a form.
+ */
+class SwFieldDialog : public FloatingWindow
+{
+private:
+ VclPtr<ListBox> aListBox;
+ sw::mark::IFieldmark* pFieldmark;
+
+ DECL_LINK(MyListBoxHandler, ListBox&, void);
+
+public:
+ SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, long nMinListWidth);
+ virtual ~SwFieldDialog() override;
+ virtual void dispose() override;
+};
+
+SwFieldDialog::SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, long nMinListWidth)
+ : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW)
+ , aListBox(VclPtr<ListBox>::Create(this))
+ , pFieldmark(fieldBM)
+{
+ if (fieldBM != nullptr)
+ {
+ const sw::mark::IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters();
+
+ OUString sListKey = ODF_FORMDROPDOWN_LISTENTRY;
+ sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
+ = pParameters->find(sListKey);
+ if (pListEntries != pParameters->end())
+ {
+ css::uno::Sequence<OUString> vListEntries;
+ pListEntries->second >>= vListEntries;
+ for (OUString const& i : vListEntries)
+ aListBox->InsertEntry(i);
+ }
+ else
+ {
+ aListBox->InsertEntry(SwResId(STR_DROP_DOWN_EMPTY_LIST));
+ }
+
+ // Select the current one
+ OUString sResultKey = ODF_FORMDROPDOWN_RESULT;
+ sw::mark::IFieldmark::parameter_map_t::const_iterator pResult
+ = pParameters->find(sResultKey);
+ if (pResult != pParameters->end())
+ {
+ sal_Int32 nSelection = -1;
+ pResult->second >>= nSelection;
+ aListBox->SelectEntryPos(nSelection);
+ }
+ }
+
+ Size lbSize(aListBox->GetOptimalSize());
+ lbSize.AdjustWidth(50);
+ lbSize.AdjustHeight(20);
+ lbSize.setWidth(std::max(lbSize.Width(), nMinListWidth));
+ aListBox->SetSizePixel(lbSize);
+ aListBox->SetSelectHdl(LINK(this, SwFieldDialog, MyListBoxHandler));
+ aListBox->Show();
+
+ SetSizePixel(lbSize);
+}
+
+SwFieldDialog::~SwFieldDialog() { disposeOnce(); }
+
+void SwFieldDialog::dispose()
+{
+ aListBox.disposeAndClear();
+ FloatingWindow::dispose();
+}
+
+IMPL_LINK(SwFieldDialog, MyListBoxHandler, ListBox&, rBox, void)
+{
+ if (!rBox.IsTravelSelect())
+ {
+ OUString sSelection = rBox.GetSelectedEntry();
+ if (sSelection == SwResId(STR_DROP_DOWN_EMPTY_LIST))
+ {
+ EndPopupMode();
+ return;
+ }
+
+ sal_Int32 nSelection = rBox.GetSelectedEntryPos();
+ if (nSelection >= 0)
+ {
+ OUString sKey = ODF_FORMDROPDOWN_RESULT;
+ (*pFieldmark->GetParameters())[sKey] <<= nSelection;
+ pFieldmark->Invalidate();
+ SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView();
+ rView.GetDocShell()->SetModified();
+ }
+
+ EndPopupMode();
+ }
+}
+
+DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin,
+ sw::mark::DropDownFieldmark& rFieldmark)
+ : MenuButton(pEditWin, WB_DIALOGCONTROL)
+ , m_rFieldmark(rFieldmark)
+{
+ assert(GetParent());
+ assert(dynamic_cast<SwEditWin*>(GetParent()));
+}
+
+DropDownFormFieldButton::~DropDownFormFieldButton() { disposeOnce(); }
+
+void DropDownFormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
+{
+ assert(GetParent());
+
+ Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos());
+ Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize());
+
+ // First calculate the size of the frame around the field
+ int nPadding = aBoxSize.Height() / 4;
+ aBoxPos.AdjustX(-nPadding);
+ aBoxPos.AdjustY(-nPadding);
+ aBoxSize.AdjustWidth(2 * nPadding);
+ aBoxSize.AdjustHeight(2 * nPadding);
+
+ m_aFieldFramePixel = tools::Rectangle(aBoxPos, aBoxSize);
+
+ // Then extend the size with the button area
+ aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
+
+ SetPosSizePixel(aBoxPos, aBoxSize);
+}
+
+void DropDownFormFieldButton::MouseButtonUp(const MouseEvent&)
+{
+ assert(GetParent());
+
+ Point aPixPos = GetPosPixel();
+ aPixPos.AdjustY(GetSizePixel().Height());
+
+ m_pFieldPopup = VclPtr<SwFieldDialog>::Create(static_cast<SwEditWin*>(GetParent()),
+ &m_rFieldmark, GetSizePixel().Width());
+ m_pFieldPopup->SetPopupModeEndHdl(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl));
+
+ tools::Rectangle aRect(GetParent()->OutputToScreenPixel(aPixPos), Size(0, 0));
+ m_pFieldPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus);
+ Invalidate();
+}
+
+IMPL_LINK_NOARG(DropDownFormFieldButton, FieldPopupModeEndHdl, FloatingWindow*, void)
+{
+ m_pFieldPopup.disposeAndClear();
+ m_rFieldmark.Invalidate();
+ Show(false); // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen
+ Invalidate();
+}
+
+basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor, double aLuminance)
+{
+ basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor);
+ aHslLine.setZ(aLuminance);
+ return basegfx::utils::hsl2rgb(aHslLine);
+}
+
+void DropDownFormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ SetMapMode(MapMode(MapUnit::MapPixel));
+
+ //const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
+ Color aLineColor = Color(COL_BLACK);
+ Color aFillColor
+ = Color(lcl_GetFillColor(aLineColor.getBColor(), (m_pFieldPopup ? 0.5 : 0.75)));
+
+ // Draw the frame around the field
+ // GTK3 backend cuts down the frame's top and left border, to avoid that add a padding around the frame
+ int nPadding = 1;
+ Point aPos (nPadding, nPadding);
+ Size aSize (m_aFieldFramePixel.GetSize().Width() - nPadding, m_aFieldFramePixel.GetSize().Height() - 2 * nPadding);
+ const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize));
+ rRenderContext.SetLineColor(aLineColor);
+ rRenderContext.SetFillColor(COL_TRANSPARENT);
+ rRenderContext.DrawRect(aFrameRect);
+
+ // Draw the button next to the frame
+ Point aButtonPos(aFrameRect.TopLeft());
+ aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - 1);
+ Size aButtonSize(aFrameRect.GetSize());
+ aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getWidth() - nPadding);
+ const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize));
+
+ // Background & border
+ rRenderContext.SetLineColor(aLineColor);
+ rRenderContext.SetFillColor(aFillColor);
+ rRenderContext.DrawRect(aButtonRect);
+
+ // the arrowhead
+ rRenderContext.SetLineColor(aLineColor);
+ rRenderContext.SetFillColor(aLineColor);
+
+ Point aCenter(aButtonPos.X() + (aButtonSize.Width() / 2),
+ aButtonPos.Y() + (aButtonSize.Height() / 2));
+ Size aArrowSize(aButtonSize.Width() / 4, aButtonSize.Height() / 10);
+
+ tools::Polygon aPoly(3);
+ aPoly.SetPoint(Point(aCenter.X() - aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 0);
+ aPoly.SetPoint(Point(aCenter.X() + aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 1);
+ aPoly.SetPoint(Point(aCenter.X(), aCenter.Y() + aArrowSize.Height()), 2);
+ rRenderContext.DrawPolygon(aPoly);
+}
+
+WindowHitTest DropDownFormFieldButton::ImplHitTest(const Point& rFramePos)
+{
+ // We need to check whether the position hits the button (the frame should be mouse transparent)
+ WindowHitTest aResult = MenuButton::ImplHitTest(rFramePos);
+ if (aResult != WindowHitTest::Inside)
+ return aResult;
+ else
+ {
+ return rFramePos.X() >= m_aFieldFramePixel.Right() ? WindowHitTest::Inside
+ : WindowHitTest::Transparent;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
index 4bb6d6780295..2e2a5417d0a0 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -37,6 +37,7 @@
#include <comphelper/random.hxx>
#include <comphelper/anytostring.hxx>
#include <sal/log.hxx>
+#include <edtwin.hxx>
using namespace ::sw::mark;
using namespace ::com::sun::star;
@@ -481,11 +482,13 @@ namespace sw { namespace mark
DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM)
: Fieldmark(rPaM)
+ , m_pButton(nullptr)
{
}
DropDownFieldmark::~DropDownFieldmark()
{
+ m_pButton.disposeAndClear();
}
void DropDownFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode const eMode)
@@ -511,6 +514,44 @@ namespace sw { namespace mark
lcl_RemoveFieldMarks(this, pDoc,
CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
}
+
+ void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea)
+ {
+ if(m_aPortionPaintArea == rPortionPaintArea &&
+ m_pButton && m_pButton->IsVisible())
+ return;
+
+ m_aPortionPaintArea = rPortionPaintArea;
+ if(m_pButton)
+ {
+ m_pButton->Show();
+ m_pButton->CalcPosAndSize(m_aPortionPaintArea);
+ m_pButton->Invalidate();
+ }
+ }
+
+ void DropDownFieldmark::ShowButton(SwEditWin* pEditWin)
+ {
+ if(pEditWin)
+ {
+ if(!m_pButton)
+ m_pButton = VclPtr<DropDownFormFieldButton>::Create(pEditWin, *this);
+ m_pButton->CalcPosAndSize(m_aPortionPaintArea);
+ m_pButton->Show();
+ }
+ }
+
+ void DropDownFieldmark::HideButton()
+ {
+ if(m_pButton)
+ m_pButton->Show(false);
+ }
+
+ void DropDownFieldmark::RemoveButton()
+ {
+ if(m_pButton)
+ m_pButton.disposeAndClear();
+ }
}}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index af7a56200564..f04c7a06e1f8 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2009,6 +2009,8 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
if( m_bSVCursorVis )
m_pVisibleCursor->Show(); // show again
+
+ getIDocumentMarkAccess()->NotifyCursorUpdate(*this);
}
void SwCursorShell::RefreshBlockCursor()
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 6014215f9e70..13b1926ee62f 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -54,6 +54,7 @@
#include <viscrs.hxx>
#include <edimp.hxx>
#include <tools/datetimeutils.hxx>
+#include <view.hxx>
using namespace ::sw::mark;
@@ -372,6 +373,7 @@ namespace sw { namespace mark
, m_vFieldmarks()
, m_vAnnotationMarks()
, m_pDoc(&rDoc)
+ , m_pLastActiveFieldmark(nullptr)
{ }
::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
@@ -956,6 +958,9 @@ namespace sw { namespace mark
IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
if ( ppFieldmark != m_vFieldmarks.end() )
{
+ if(m_pLastActiveFieldmark == ppFieldmark->get())
+ ClearFieldActivation();
+
m_vFieldmarks.erase(ppFieldmark);
ret.reset(new LazyFieldmarkDeleter(*ppMark, m_pDoc));
}
@@ -1031,6 +1036,7 @@ namespace sw { namespace mark
void MarkManager::clearAllMarks()
{
+ ClearFieldActivation();
m_vFieldmarks.clear();
m_vBookmarks.clear();
@@ -1117,10 +1123,61 @@ namespace sw { namespace mark
SwPaM aPaM = SwPaM(pFieldmark->GetMarkPos());
// Remove the old fieldmark and create a new one with the new type
- deleteFieldmarkAt(*aPaM.GetPoint());
- return makeNoTextFieldBookmark(aPaM, sName, rNewType);
+ if(aPaM.GetPoint()->nContent > 0)
+ {
+ --aPaM.GetPoint()->nContent;
+ SwPosition aNewPos (aPaM.GetPoint()->nNode, aPaM.GetPoint()->nContent);
+ deleteFieldmarkAt(aNewPos);
+ return makeNoTextFieldBookmark(aPaM, sName, rNewType);
+ }
+ return nullptr;
+ }
+
+ void MarkManager::NotifyCursorUpdate(const SwCursorShell& rCursorShell)
+ {
+ SwView* pSwView = dynamic_cast<SwView *>(rCursorShell.GetSfxViewShell());
+ if(!pSwView)
+ return;
+
+ SwEditWin& rEditWin = pSwView->GetEditWin();
+ SwPosition aPos(*rCursorShell.GetCursor()->GetPoint());
+ IFieldmark* pFieldBM = getFieldmarkFor(aPos);
+ DropDownFieldmark* pNewActiveFieldmark = nullptr;
+ if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMDROPDOWN)
+ && aPos.nContent.GetIndex() > 0 )
+ {
+ --aPos.nContent;
+ pFieldBM = getFieldmarkFor(aPos);
+ }
+
+ if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN )
+ {
+ if (m_pLastActiveFieldmark != pFieldBM)
+ {
+ DropDownFieldmark* pDropDownFm = dynamic_cast<DropDownFieldmark*>(pFieldBM);
+ pDropDownFm->ShowButton(&rEditWin);
+ pNewActiveFieldmark = pDropDownFm;
+ }
+ else
+ {
+ pNewActiveFieldmark = m_pLastActiveFieldmark;
+ }
+ }
+
+ if(pNewActiveFieldmark != m_pLastActiveFieldmark)
+ {
+ ClearFieldActivation();
+ m_pLastActiveFieldmark = pNewActiveFieldmark;
+ }
}
+ void MarkManager::ClearFieldActivation()
+ {
+ if(m_pLastActiveFieldmark)
+ m_pLastActiveFieldmark->RemoveButton();
+
+ m_pLastActiveFieldmark = nullptr;
+ }
IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const
{
diff --git a/sw/source/core/inc/DropDownFormFieldButton.hxx b/sw/source/core/inc/DropDownFormFieldButton.hxx
new file mode 100644
index 000000000000..abe159860d6f
--- /dev/null
+++ b/sw/source/core/inc/DropDownFormFieldButton.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX
+#define INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX
+
+#include <vcl/menubtn.hxx>
+#include <swrect.hxx>
+
+class SwFieldFormDropDownPortion;
+class SwEditWin;
+class FloatingWindow;
+namespace sw
+{
+namespace mark
+{
+class DropDownFieldmark;
+}
+}
+
+/**
+ * This button is shown when the cursor is in a drop-down form field.
+ * The user can select an item of the field using this button while filling in a form.
+ */
+class DropDownFormFieldButton : public MenuButton
+{
+public:
+ DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& rFieldMark);
+ virtual ~DropDownFormFieldButton() override;
+
+ void CalcPosAndSize(const SwRect& rPortionPaintArea);
+
+ virtual void MouseButtonUp(const MouseEvent& rMEvt) override;
+ DECL_DLLPRIVATE_LINK(FieldPopupModeEndHdl, FloatingWindow*, void);
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ virtual WindowHitTest ImplHitTest(const Point& rFramePos) override;
+
+private:
+ tools::Rectangle m_aFieldFramePixel;
+ sw::mark::DropDownFieldmark& m_rFieldmark;
+ VclPtr<FloatingWindow> m_pFieldPopup;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 71ad5c913d6c..11291f7b881a 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -24,11 +24,16 @@
#include <IDocumentMarkAccess.hxx>
#include <unordered_set>
#include <unordered_map>
+#include <memory>
+
+class SwCursorShell;
namespace sw {
namespace mark {
typedef std::unordered_map<OUString, sal_Int32> MarkBasenameMapUniqueOffset_t;
+ class DropDownFieldmark;
+
class MarkManager
: virtual public IDocumentMarkAccess
{
@@ -88,6 +93,9 @@ namespace sw {
virtual void deleteFieldmarkAt(const SwPosition& rPos) override;
virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override;
+ virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) override;
+ virtual void ClearFieldActivation() override;
+
void dumpAsXml(xmlTextWriterPtr pWriter) const;
// Annotation Marks
@@ -125,6 +133,8 @@ namespace sw {
container_t m_vAnnotationMarks;
SwDoc * const m_pDoc;
+
+ sw::mark::DropDownFieldmark* m_pLastActiveFieldmark;
};
} // namespace mark
}
diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx
index 29336abfcc90..eaa5b8bf8f4a 100644
--- a/sw/source/core/inc/bookmrk.hxx
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -29,6 +29,8 @@
#include <osl/diagnose.h>
#include <IMark.hxx>
#include <swserv.hxx>
+#include <swrect.hxx>
+#include "DropDownFormFieldButton.hxx"
namespace com {
namespace sun {
@@ -42,6 +44,7 @@ namespace com {
struct SwPosition; // fwd Decl. wg. UI
class SwDoc;
+class SwEditWin;
namespace sw {
namespace mark {
@@ -267,6 +270,17 @@ namespace sw {
virtual ~DropDownFieldmark();
virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override;
virtual void ReleaseDoc(SwDoc* const pDoc) override;
+
+ // This method should be called only by the portion so we can now the portion's painting area
+ void SetPortionPaintArea(const SwRect& rPortionPaintArea);
+
+ void ShowButton(SwEditWin* pEditWin);
+ void HideButton();
+ void RemoveButton();
+
+ private:
+ SwRect m_aPortionPaintArea;
+ VclPtr<DropDownFormFieldButton> m_pButton;
};
}
}
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 2697f3022639..fa56ada86eba 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -908,7 +908,7 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
}
else if (pBM->GetFieldname( ) == ODF_FORMDROPDOWN)
{
- pPor = new SwFieldFormDropDownPortion(sw::mark::ExpandFieldmark(pBM));
+ pPor = new SwFieldFormDropDownPortion(pBM, sw::mark::ExpandFieldmark(pBM));
}
/* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT.
* Otherwise file will crash on open.
diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
index e2a482e870dc..2a52f9b539c7 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -43,6 +43,7 @@
#include <accessibilityoptions.hxx>
#include <editeng/lrspitem.hxx>
#include <unicode/ubidi.h>
+#include <bookmrk.hxx>
using namespace ::com::sun::star;
@@ -1310,7 +1311,20 @@ sal_uInt16 SwCombinedPortion::GetViewWidth( const SwTextSizeInfo &rInf ) const
SwFieldPortion *SwFieldFormDropDownPortion::Clone(const OUString &rExpand) const
{
- return new SwFieldFormDropDownPortion(rExpand);
+ return new SwFieldFormDropDownPortion(m_pFieldMark, rExpand);
+}
+
+void SwFieldFormDropDownPortion::Paint( const SwTextPaintInfo &rInf ) const
+{
+ SwFieldPortion::Paint( rInf );
+
+ ::sw::mark::DropDownFieldmark* pDropDownField = dynamic_cast< ::sw::mark::DropDownFieldmark* >(m_pFieldMark);
+ if(pDropDownField)
+ {
+ SwRect aPaintArea;
+ rInf.CalcRect( *this, &aPaintArea );
+ pDropDownField->SetPortionPaintArea(aPaintArea);
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porfld.hxx b/sw/source/core/text/porfld.hxx
index 4434f1e8c577..069ab3798060 100644
--- a/sw/source/core/text/porfld.hxx
+++ b/sw/source/core/text/porfld.hxx
@@ -217,12 +217,18 @@ namespace sw { namespace mark {
class SwFieldFormDropDownPortion : public SwFieldPortion
{
public:
- explicit SwFieldFormDropDownPortion(const OUString &rExpand)
+ explicit SwFieldFormDropDownPortion(sw::mark::IFieldmark *pFieldMark, const OUString &rExpand)
: SwFieldPortion(rExpand)
+ , m_pFieldMark(pFieldMark)
{
}
// Field cloner for SplitGlue
virtual SwFieldPortion *Clone( const OUString &rExpand ) const override;
+
+ virtual void Paint( const SwTextPaintInfo &rInf ) const override;
+
+private:
+ sw::mark::IFieldmark* m_pFieldMark;
};
#endif
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 22458d77b710..85d24b1d61c5 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -4627,12 +4627,6 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
rCheckboxFm.Invalidate();
rSh.InvalidateWindows( m_rView.GetVisArea() );
- } else if ( fieldBM->GetFieldname() == ODF_FORMDROPDOWN ) {
- m_rView.ExecFieldPopup( aDocPt, fieldBM );
- fieldBM->Invalidate();
- rSh.InvalidateWindows( m_rView.GetVisArea() );
- } else {
- // unknown type..
}
}
}
diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
index 65484c32e748..c70e84156b97 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -120,6 +120,8 @@
#include <numrule.hxx>
#include <memory>
#include <xmloff/odffields.hxx>
+#include <swabstdlg.hxx>
+#include <bookmrk.hxx>
using namespace ::com::sun::star;
using namespace com::sun::star::beans;
@@ -1382,10 +1384,14 @@ void SwTextShell::Execute(SfxRequest &rReq)
{
SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDropDownFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM));
- pDlg->Execute();
- pFieldBM->Invalidate();
- rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() );
- rWrtSh.UpdateCursor(); // cursor position might be invalid
+ if (pDlg->Execute() == RET_OK)
+ {
+ pFieldBM->Invalidate();
+ rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() );
+ rWrtSh.UpdateCursor(); // cursor position might be invalid
+ // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen
+ dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldBM)->HideButton();
+ }
}
else
{
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
index 63febf29b44a..59fc540e0d35 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -1067,6 +1067,9 @@ SwView::~SwView()
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
+ // Need to remove activated field's button before disposing EditWin.
+ GetWrtShell().getIDocumentMarkAccess()->ClearFieldActivation();
+
GetViewFrame()->GetWindow().RemoveChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
m_pPostItMgr.reset();
diff --git a/sw/source/uibase/uiview/viewling.cxx b/sw/source/uibase/uiview/viewling.cxx
index 7d6aac2913d9..3ac2ebcadd3e 100644
--- a/sw/source/uibase/uiview/viewling.cxx
+++ b/sw/source/uibase/uiview/viewling.cxx
@@ -825,114 +825,4 @@ void SwView::ExecSmartTagPopup( const Point& rPt )
m_pWrtShell->LockView( bOldViewLock );
}
-class SwFieldDialog : public FloatingWindow
-{
-private:
- VclPtr<ListBox> aListBox;
- IFieldmark *pFieldmark;
-
- DECL_LINK( MyListBoxHandler, ListBox&, void );
-
-public:
- SwFieldDialog( SwEditWin* parent, IFieldmark *fieldBM );
- virtual ~SwFieldDialog() override;
- virtual void dispose() override;
-};
-
-SwFieldDialog::SwFieldDialog( SwEditWin* parent, IFieldmark *fieldBM ) :
- FloatingWindow( parent, WB_BORDER | WB_SYSTEMWINDOW ),
- aListBox(VclPtr<ListBox>::Create(this)),
- pFieldmark( fieldBM )
-{
- if ( fieldBM != nullptr )
- {
- const IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters();
-
- OUString sListKey = ODF_FORMDROPDOWN_LISTENTRY;
- IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find( sListKey );
- if(pListEntries != pParameters->end())
- {
- Sequence< OUString > vListEntries;
- pListEntries->second >>= vListEntries;
- for( OUString const & i : vListEntries)
- aListBox->InsertEntry(i);
- }
-
- // Select the current one
- OUString sResultKey = ODF_FORMDROPDOWN_RESULT;
- IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find( sResultKey );
- if ( pResult != pParameters->end() )
- {
- sal_Int32 nSelection = -1;
- pResult->second >>= nSelection;
- aListBox->SelectEntryPos( nSelection );
- }
- }
-
- Size lbSize(aListBox->GetOptimalSize());
- lbSize.AdjustWidth(50 );
- lbSize.AdjustHeight(20 );
- aListBox->SetSizePixel(lbSize);
- aListBox->SetSelectHdl( LINK( this, SwFieldDialog, MyListBoxHandler ) );
- aListBox->Show();
-
- SetSizePixel( lbSize );
-}
-
-SwFieldDialog::~SwFieldDialog()
-{
- disposeOnce();
-}
-
-void SwFieldDialog::dispose()
-{
- aListBox.disposeAndClear();
- FloatingWindow::dispose();
-}
-
-IMPL_LINK( SwFieldDialog, MyListBoxHandler, ListBox&, rBox, void )
-{
- if ( !rBox.IsTravelSelect() )
- {
- sal_Int32 selection = rBox.GetSelectedEntryPos();
- if ( selection >= 0 )
- {
- OUString sKey = ODF_FORMDROPDOWN_RESULT;
- (*pFieldmark->GetParameters())[ sKey ] <<= selection;
- pFieldmark->Invalidate();
- SwView& rView = static_cast<SwEditWin*>( GetParent() )->GetView();
- rView.GetDocShell()->SetModified();
- }
-
- EndPopupMode();
- }
-}
-
-IMPL_LINK_NOARG(SwView, FieldPopupModeEndHdl, FloatingWindow*, void)
-{
- m_pFieldPopup.disposeAndClear();
-}
-
-void SwView::ExecFieldPopup( const Point& rPt, IFieldmark *fieldBM )
-{
- // Don't show popup if there is no list item
- auto pListEntries = fieldBM->GetParameters()->find( ODF_FORMDROPDOWN_LISTENTRY );
- Sequence< OUString > vListEntries;
- if(pListEntries != fieldBM->GetParameters()->end())
- {
- pListEntries->second >>= vListEntries;
- }
-
- if(vListEntries.getLength() == 0)
- return;
-
- const Point aPixPos = GetEditWin().LogicToPixel( rPt );
-
- m_pFieldPopup = VclPtr<SwFieldDialog>::Create( m_pEditWin, fieldBM );
- m_pFieldPopup->SetPopupModeEndHdl( LINK( this, SwView, FieldPopupModeEndHdl ) );
-
- tools::Rectangle aRect( m_pEditWin->OutputToScreenPixel( aPixPos ), Size( 0, 0 ) );
- m_pFieldPopup->StartPopupMode( aRect, FloatWinPopupFlags::Down|FloatWinPopupFlags::GrabFocus );
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list