sw/Library_sw.mk | 1 sw/inc/fesh.hxx | 3 sw/inc/strings.hrc | 2 sw/inc/swtypes.hxx | 3 sw/qa/extras/uiwriter/data/floating_table/small_floating_table.odt |binary sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.doc |binary sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.docx |binary sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.odt |binary sw/qa/extras/uiwriter/data/floating_table/unfloatable_small_floating_table.docx |binary sw/qa/extras/uiwriter/uiwriter2.cxx | 165 +++++++++ sw/source/core/frmedt/fefly1.cxx | 3 sw/source/core/frmedt/feshview.cxx | 11 sw/source/core/inc/flyfrm.hxx | 15 sw/source/core/inc/frame.hxx | 8 sw/source/core/inc/layfrm.hxx | 3 sw/source/core/inc/sortedobjs.hxx | 3 sw/source/core/inc/txtfrm.hxx | 2 sw/source/core/layout/findfrm.cxx | 13 sw/source/core/layout/fly.cxx | 107 ++++++ sw/source/core/layout/paintfrm.cxx | 12 sw/source/core/text/frmform.cxx | 12 sw/source/uibase/docvw/FloatingTableButton.cxx | 177 ++++++++++ sw/source/uibase/docvw/FrameControlsManager.cxx | 43 ++ sw/source/uibase/docvw/HeaderFooterWin.cxx | 79 ++-- sw/source/uibase/inc/FloatingTableButton.hxx | 37 ++ sw/source/uibase/inc/FrameControlsManager.hxx | 1 sw/source/uibase/inc/HeaderFooterWin.hxx | 10 27 files changed, 652 insertions(+), 58 deletions(-)
New commits: commit 38a7a61aa85e2b3a6eda53422cfcd9bc2e2f590c Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Fri Jan 4 11:23:59 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Unfloat: Test layout change of unfloat operation Change-Id: I75298a392de6a10861ac96e1bc58a30173cd2dd2 Reviewed-on: https://gerrit.libreoffice.org/65823 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit dd0b559d6aac5bf09566af735bd00b28c00fb2e4) Reviewed-on: https://gerrit.libreoffice.org/65874 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index f45272a771c7..14d0bd77ac49 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -32,8 +32,7 @@ #include <view.hxx> #include <sortedobjs.hxx> #include <anchoredobject.hxx> -#include <FrameControlsManager.hxx> -#include <FloatingTableButton.hxx> +#include <swtypes.hxx> namespace { @@ -65,6 +64,7 @@ public: void testUnfloatButtonSmallTable(); void testUnfloatButton(); void testUnfloatButtonReadOnlyMode(); + void testUnfloating(); CPPUNIT_TEST_SUITE(SwUiWriterTest2); CPPUNIT_TEST(testRedlineMoveInsertInDelete); @@ -87,6 +87,7 @@ public: CPPUNIT_TEST(testUnfloatButtonSmallTable); CPPUNIT_TEST(testUnfloatButton); CPPUNIT_TEST(testUnfloatButtonReadOnlyMode); + CPPUNIT_TEST(testUnfloating); CPPUNIT_TEST_SUITE_END(); private: @@ -879,6 +880,53 @@ void SwUiWriterTest2::testUnfloatButtonReadOnlyMode() CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); } +void SwUiWriterTest2::testUnfloating() +{ + // Test what happens when pushing the unfloat button + load(FLOATING_TABLE_DATA_DIRECTORY, "unfloatable_floating_table.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + + SwFlyFrame* pFlyFrame; + + // Before unfloating we have only one page with a fly frame + { + CPPUNIT_ASSERT_EQUAL(SwFrameType::Page, pWrtShell->GetLayout()->GetLower()->GetType()); + CPPUNIT_ASSERT(!pWrtShell->GetLayout()->GetLower()->GetNext()); + CPPUNIT_ASSERT_EQUAL(SwFrameType::Txt, + pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetType()); + const SwSortedObjs* pAnchored + = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); + CPPUNIT_ASSERT(pAnchored); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pAnchored->size()); + SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; + pFlyFrame = dynamic_cast<SwFlyFrame*>(pAnchoredObj); + CPPUNIT_ASSERT(pFlyFrame); + } + + // Select the floating table + SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); + CPPUNIT_ASSERT(pObj); + pWrtShell->SelectObj(Point(), 0, pObj); + CPPUNIT_ASSERT(pFlyFrame->IsShowUnfloatButton(pWrtShell)); + + // Push the unfloat button + pFlyFrame->ActiveUnfloatButton(pWrtShell); + + // After unfloating we have two pages with one tablre frame on each page + CPPUNIT_ASSERT(pWrtShell->GetLayout()->GetLower()->GetNext()); + CPPUNIT_ASSERT_EQUAL(SwFrameType::Page, + pWrtShell->GetLayout()->GetLower()->GetNext()->GetType()); + CPPUNIT_ASSERT(!pWrtShell->GetLayout()->GetLower()->GetNext()->GetNext()); + CPPUNIT_ASSERT_EQUAL(SwFrameType::Tab, + pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetType()); + CPPUNIT_ASSERT_EQUAL( + SwFrameType::Tab, + pWrtShell->GetLayout()->GetLower()->GetNext()->GetLower()->GetLower()->GetType()); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx index 5ee5eb152b9b..218fbe4a98ec 100644 --- a/sw/source/core/inc/flyfrm.hxx +++ b/sw/source/core/inc/flyfrm.hxx @@ -274,6 +274,9 @@ public: void SelectionHasChanged(SwFEShell* pShell); bool IsShowUnfloatButton(SwWrtShell* pWrtSh) const; + // For testing only (see uiwriter) + void ActiveUnfloatButton(SwWrtShell* pWrtSh); + private: void UpdateUnfloatButton(SwWrtShell* pWrtSh, bool bShow) const; void PaintDecorators() const; diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index e087f23430ad..fa47b1799b76 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -1849,6 +1849,17 @@ bool SwFlyFrame::IsShowUnfloatButton(SwWrtShell* pWrtSh) const return nBodyHeight < nTableHeight + nFrameOffset; } +void SwFlyFrame::ActiveUnfloatButton(SwWrtShell* pWrtSh) +{ + SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); + SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); + SwFrameControlPtr pControl = rMngr.GetControl(FloatingTable, this); + if (pControl.get() || pControl->GetWindow()) + { + pControl->GetWindow()->MouseButtonDown(MouseEvent()); + } +} + void SwFlyFrame::UpdateUnfloatButton(SwWrtShell* pWrtSh, bool bShow) const { if (pWrtSh == nullptr) commit ebea6821f35a746259d866114ee53d445530df31 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Wed Jan 2 18:06:37 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Unfloat: Disable undoing of unfloat operation I tested to use undo events for unfloat operations: moving a table outside of the text frame and removing the text frame, but sometimes it just crashed. So now we handle unfloating similar to the reverse operation (table is moved into a text frame(MakeFlyAndMove). Reviewed-on: https://gerrit.libreoffice.org/65822 Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> Tested-by: Tamás Zolnai <tamas.zol...@collabora.com> Tested-by: Jenkins (cherry picked from commit 9a115beac9a13ae320a9abf578be25bfbff1e02d) Reviewed-on: https://gerrit.libreoffice.org/65873 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> Change-Id: I4eaeda550ccc51252abd4abde6cee45c76a8483e diff --git a/sw/source/uibase/docvw/FloatingTableButton.cxx b/sw/source/uibase/docvw/FloatingTableButton.cxx index 905c647bb618..c2494945ba24 100644 --- a/sw/source/uibase/docvw/FloatingTableButton.cxx +++ b/sw/source/uibase/docvw/FloatingTableButton.cxx @@ -20,6 +20,8 @@ #include <txtfrm.hxx> #include <ndindex.hxx> #include <swtable.hxx> +#include <IDocumentState.hxx> +#include <IDocumentUndoRedo.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <drawinglayer/attribute/fontattribute.hxx> @@ -100,12 +102,23 @@ void FloatingTableButton::MouseButtonDown(const MouseEvent& /*rMEvt*/) if (pTableNode == nullptr) return; + SwDoc& rDoc = *pTextFrame->GetTextNodeFirst()->GetDoc(); + + // Move the table outside of the text frame SwNodeRange aRange(*pTableNode, 0, *pTableNode->EndOfSectionNode(), 1); - pTableNode->getIDocumentContentOperations().MoveNodeRange(aRange, aInsertPos, - SwMoveFlags::DEFAULT); + rDoc.getIDocumentContentOperations().MoveNodeRange(aRange, aInsertPos, SwMoveFlags::DEFAULT); // Remove the floating table's frame SwFrame::DestroyFrame(pFlyFrame); + + rDoc.getIDocumentState().SetModified(); + + // Undoing MoveNodeRange() is not working correctly in case of tables, it crashes some times + // So don't allow to undo after unfloating (similar to MakeFlyAndMove() method) + if (rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + rDoc.GetIDocumentUndoRedo().DelAllUndoObj(); + } } void FloatingTableButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) commit 9ff9378e076c25d6f81e5f8aaa310b1d13823504 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Fri Jan 4 21:10:27 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Unfloat: Implement unfloating of a floating table Triggered by the unfloat button. Reviewed-on: https://gerrit.libreoffice.org/65821 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit dcf70bb4188e019154d6201936bf1ee2e16149a3) Change-Id: I863f0ec481480343c184b0b5fa94b9ba1aa9276c Reviewed-on: https://gerrit.libreoffice.org/65872 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/source/uibase/docvw/FloatingTableButton.cxx b/sw/source/uibase/docvw/FloatingTableButton.cxx index 8f124f46f652..905c647bb618 100644 --- a/sw/source/uibase/docvw/FloatingTableButton.cxx +++ b/sw/source/uibase/docvw/FloatingTableButton.cxx @@ -14,6 +14,12 @@ #include <strings.hrc> #include <vcl/metric.hxx> #include <viewopt.hxx> +#include <frame.hxx> +#include <flyfrm.hxx> +#include <tabfrm.hxx> +#include <txtfrm.hxx> +#include <ndindex.hxx> +#include <swtable.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <drawinglayer/attribute/fontattribute.hxx> @@ -21,6 +27,7 @@ #include <basegfx/matrix/b2dhommatrixtools.hxx> #include <drawinglayer/processor2d/processorfromoutputdevice.hxx> #include <basegfx/vector/b2dvector.hxx> +#include <DocumentContentOperationsManager.hxx> #define TEXT_PADDING 3 #define BOX_DISTANCE 3 @@ -58,7 +65,47 @@ void FloatingTableButton::SetOffset(Point aBottomRightPixel) void FloatingTableButton::MouseButtonDown(const MouseEvent& /*rMEvt*/) { - // Move the table outside of the frame + assert(GetFrame()->IsFlyFrame()); + // const_cast is needed because of bad design of ISwFrameControl and derived classes + SwFlyFrame* pFlyFrame = const_cast<SwFlyFrame*>(static_cast<const SwFlyFrame*>(GetFrame())); + + // Find the table inside the text frame + SwTabFrame* pTableFrame = nullptr; + SwFrame* pLower = pFlyFrame->GetLower(); + while (pLower) + { + if (pLower->IsTabFrame()) + { + pTableFrame = static_cast<SwTabFrame*>(pLower); + break; + } + pLower = pLower->GetNext(); + } + + if (pTableFrame == nullptr) + return; + + // Insert the table at the position of the text node which has the frame anchored to + SwFrame* pAnchoreFrame = pFlyFrame->AnchorFrame(); + if (pAnchoreFrame == nullptr || !pAnchoreFrame->IsTextFrame()) + return; + + SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pAnchoreFrame); + if (pTextFrame->GetTextNodeFirst() == nullptr) + return; + + SwNodeIndex aInsertPos((*pTextFrame->GetTextNodeFirst())); + + SwTableNode* pTableNode = pTableFrame->GetTable()->GetTableNode(); + if (pTableNode == nullptr) + return; + + SwNodeRange aRange(*pTableNode, 0, *pTableNode->EndOfSectionNode(), 1); + pTableNode->getIDocumentContentOperations().MoveNodeRange(aRange, aInsertPos, + SwMoveFlags::DEFAULT); + + // Remove the floating table's frame + SwFrame::DestroyFrame(pFlyFrame); } void FloatingTableButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) @@ -114,4 +161,4 @@ bool FloatingTableButton::Contains(const Point& rDocPt) const void FloatingTableButton::SetReadonly(bool bReadonly) { ShowAll(!bReadonly); } -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ \ No newline at end of file +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ commit 67e31f715ff8bd6e5c09506c221bed099025e616 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Fri Jan 4 02:51:36 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Unfloat: Add some tests about the visibility of the unfloat button Reviewed-on: https://gerrit.libreoffice.org/65820 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 9c4a374baa4d18dec4066e547d76a40501b20d45) Change-Id: Id0bc6e5be5a55480233afeae44eccac24fa01434 Reviewed-on: https://gerrit.libreoffice.org/65871 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/uiwriter/data/floating_table/small_floating_table.odt b/sw/qa/extras/uiwriter/data/floating_table/small_floating_table.odt new file mode 100644 index 000000000000..6b77569f2583 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/floating_table/small_floating_table.odt differ diff --git a/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.doc b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.doc new file mode 100644 index 000000000000..e5247f1598c2 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.doc differ diff --git a/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.docx b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.docx new file mode 100644 index 000000000000..cef1f7bf685d Binary files /dev/null and b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.docx differ diff --git a/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.odt b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.odt new file mode 100644 index 000000000000..eb2534ba4c52 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_floating_table.odt differ diff --git a/sw/qa/extras/uiwriter/data/floating_table/unfloatable_small_floating_table.docx b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_small_floating_table.docx new file mode 100644 index 000000000000..d51056af1177 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/floating_table/unfloatable_small_floating_table.docx differ diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index d6410d60888b..f45272a771c7 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -26,11 +26,20 @@ #include <fmtfsize.hxx> #include <fmtornt.hxx> #include <com/sun/star/style/BreakType.hpp> +#include <flyfrms.hxx> +#include <UndoManager.hxx> +#include <edtwin.hxx> +#include <view.hxx> +#include <sortedobjs.hxx> +#include <anchoredobject.hxx> +#include <FrameControlsManager.hxx> +#include <FloatingTableButton.hxx> namespace { char const DATA_DIRECTORY[] = "/sw/qa/extras/uiwriter/data2/"; -} +char const FLOATING_TABLE_DATA_DIRECTORY[] = "/sw/qa/extras/uiwriter/data/floating_table/"; +} // namespace /// Second set of tests asserting the behavior of Writer user interface shells. class SwUiWriterTest2 : public SwModelTestBase @@ -53,6 +62,9 @@ public: void testDocxAttributeTableExport(); void testTdf125310(); void testTdf125310b(); + void testUnfloatButtonSmallTable(); + void testUnfloatButton(); + void testUnfloatButtonReadOnlyMode(); CPPUNIT_TEST_SUITE(SwUiWriterTest2); CPPUNIT_TEST(testRedlineMoveInsertInDelete); @@ -72,6 +84,9 @@ public: CPPUNIT_TEST(testDocxAttributeTableExport); CPPUNIT_TEST(testTdf125310); CPPUNIT_TEST(testTdf125310b); + CPPUNIT_TEST(testUnfloatButtonSmallTable); + CPPUNIT_TEST(testUnfloatButton); + CPPUNIT_TEST(testUnfloatButtonReadOnlyMode); CPPUNIT_TEST_SUITE_END(); private: @@ -764,6 +779,106 @@ void SwUiWriterTest2::testTdf125310b() CPPUNIT_ASSERT_EQUAL(1, getPages()); } +void SwUiWriterTest2::testUnfloatButtonSmallTable() +{ + // The floating table in the test document is too small, so we don't provide an unfloat button + load(FLOATING_TABLE_DATA_DIRECTORY, "small_floating_table.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + + const SwSortedObjs* pAnchored + = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); + CPPUNIT_ASSERT(pAnchored); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pAnchored->size()); + SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; + + SwFlyFrame* pFlyFrame = dynamic_cast<SwFlyFrame*>(pAnchoredObj); + CPPUNIT_ASSERT(pFlyFrame); + CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); + + SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); + CPPUNIT_ASSERT(pObj); + pWrtShell->SelectObj(Point(), 0, pObj); + CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); +} + +void SwUiWriterTest2::testUnfloatButton() +{ + // Different use cases where unfloat button should be visible + const std::vector<OUString> aTestFiles = { + "unfloatable_floating_table.odt", // Typical use case of multipage floating table + "unfloatable_floating_table.docx", // Need to test the DOCX import whether we detect the floating table correctly + "unfloatable_floating_table.doc", // Also the DOC import + "unfloatable_small_floating_table.docx" // Atypical use case, when the table is small, but because of it's position is it broken to two pages + }; + + for (const OUString& aTestFile : aTestFiles) + { + OString sTestFileName = OUStringToOString(aTestFile, RTL_TEXTENCODING_UTF8); + OString sFailureMessage = OString("Failure in the test file: ") + sTestFileName; + + load(FLOATING_TABLE_DATA_DIRECTORY, sTestFileName.getStr()); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pTextDoc); + SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pWrtShell); + + const SwSortedObjs* pAnchored; + if (sTestFileName == "unfloatable_small_floating_table.docx") + pAnchored = pWrtShell->GetLayout() + ->GetLower() + ->GetLower() + ->GetLower() + ->GetNext() + ->GetDrawObjs(); + else + pAnchored = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pAnchored); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailureMessage.getStr(), static_cast<size_t>(1), + pAnchored->size()); + SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; + + // The unfloat button is not visible until it gets selected + SwFlyFrame* pFlyFrame = dynamic_cast<SwFlyFrame*>(pAnchoredObj); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pFlyFrame); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), + !pFlyFrame->IsShowUnfloatButton(pWrtShell)); + + SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pObj); + pWrtShell->SelectObj(Point(), 0, pObj); + CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pFlyFrame->IsShowUnfloatButton(pWrtShell)); + } +} + +void SwUiWriterTest2::testUnfloatButtonReadOnlyMode() +{ + // In read only mode we don't show the unfloat button even if we have a multipage floating table + load(FLOATING_TABLE_DATA_DIRECTORY, "unfloatable_floating_table.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + pWrtShell->SetReadonlyOption(true); + + const SwSortedObjs* pAnchored + = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); + CPPUNIT_ASSERT(pAnchored); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pAnchored->size()); + SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; + + SwFlyFrame* pFlyFrame = dynamic_cast<SwFlyFrame*>(pAnchoredObj); + CPPUNIT_ASSERT(pFlyFrame); + CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); + + SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); + CPPUNIT_ASSERT(pObj); + pWrtShell->SelectObj(Point(), 0, pObj); + CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx index 6501ab592510..5ee5eb152b9b 100644 --- a/sw/source/core/inc/flyfrm.hxx +++ b/sw/source/core/inc/flyfrm.hxx @@ -24,6 +24,7 @@ #include <vector> #include <frmfmt.hxx> #include <anchoredobject.hxx> +#include <swdllapi.h> class SwFormatAnchor; class SwPageFrame; @@ -58,7 +59,7 @@ bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, bool bMove = true ); #i26791# - inherit also from <SwAnchoredFlyFrame> */ -class SwFlyFrame : public SwLayoutFrame, public SwAnchoredObject +class SW_DLLPUBLIC SwFlyFrame : public SwLayoutFrame, public SwAnchoredObject { // is allowed to lock, implemented in frmtool.cxx friend void AppendObj(SwFrame *const pFrame, SwPageFrame *const pPage, SwFrameFormat *const pFormat, const SwFormatAnchor & rAnch); @@ -271,9 +272,9 @@ public: void InvalidateContentPos(); void SelectionHasChanged(SwFEShell* pShell); + bool IsShowUnfloatButton(SwWrtShell* pWrtSh) const; private: - bool IsShowUnfloatButton(SwWrtShell* pWrtSh) const; void UpdateUnfloatButton(SwWrtShell* pWrtSh, bool bShow) const; void PaintDecorators() const; }; diff --git a/sw/source/core/inc/layfrm.hxx b/sw/source/core/inc/layfrm.hxx index 92fc189fba8a..8fd0e5f626aa 100644 --- a/sw/source/core/inc/layfrm.hxx +++ b/sw/source/core/inc/layfrm.hxx @@ -20,6 +20,7 @@ #define INCLUDED_SW_SOURCE_CORE_INC_LAYFRM_HXX #include "frame.hxx" +#include <swdllapi.h> class SwAnchoredObject; class SwContentFrame; @@ -31,7 +32,7 @@ class SwBorderAttrs; class SwFormatFrameSize; class SwCellFrame; -class SwLayoutFrame: public SwFrame +class SW_DLLPUBLIC SwLayoutFrame: public SwFrame { // The SwFrame in disguise friend class SwFlowFrame; diff --git a/sw/source/core/inc/sortedobjs.hxx b/sw/source/core/inc/sortedobjs.hxx index 0fd6a9cb9d71..5e5dcc45712f 100644 --- a/sw/source/core/inc/sortedobjs.hxx +++ b/sw/source/core/inc/sortedobjs.hxx @@ -21,6 +21,7 @@ #include <sal/types.h> #include <vector> +#include <swdllapi.h> class SwAnchoredObject; @@ -45,7 +46,7 @@ class SwAnchoredObject; If one of the sort criteria attributes of an anchored object changes, the sorting has to be updated - use method <Update(..)> */ -class SwSortedObjs +class SW_DLLPUBLIC SwSortedObjs { private: std::vector< SwAnchoredObject* > maSortedObjLst; commit 8dca18297479b334a153f3ad6b383d3f6157f0c6 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Wed Jan 2 17:57:22 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Unfloat: Handle unfloat button visibility We need to update the state of the button every time when the frame's layout changes or when the selection changes. Show the button if the text frame is selected and it's a floating table which would hang out of the actual page after unfloating. Reviewed-on: https://gerrit.libreoffice.org/65819 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 6e5c4001c7b5cab2b2cc6419072acbe5fa7cb04a) Change-Id: I6b64affb063f552921915a0735e80889e5fd8124 Reviewed-on: https://gerrit.libreoffice.org/65870 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx index d94ee5c8e6ad..65a19bc00487 100644 --- a/sw/source/core/frmedt/fefly1.cxx +++ b/sw/source/core/frmedt/fefly1.cxx @@ -266,6 +266,9 @@ void SwFEShell::SelectFlyFrame( SwFlyFrame& rFrame ) pImpl->GetDrawView()->MarkObj( rFrame.GetVirtDrawObj(), pImpl->GetPageView() ); + + rFrame.SelectionHasChanged(this); + KillPams(); ClearMark(); SelFlyGrabCursor(); diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx index 0d7a871c52c3..d3fa9b126e86 100644 --- a/sw/source/core/frmedt/feshview.cxx +++ b/sw/source/core/frmedt/feshview.cxx @@ -235,7 +235,11 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj ) } } if ( bUnmark ) + { pDView->UnmarkAll(); + if (pOldSelFly) + pOldSelFly->SelectionHasChanged(this); + } } else { @@ -275,6 +279,13 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj ) } } + if ( rMrkList.GetMarkCount() == 1 ) + { + SwFlyFrame *pSelFly = ::GetFlyFromMarked( &rMrkList, this ); + if (pSelFly) + pSelFly->SelectionHasChanged(this); + } + if (!(nFlag & SW_ALLOW_TEXTBOX)) { // If the fly frame is a textbox of a shape, then select the shape instead. diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx index c28dcd98b882..6501ab592510 100644 --- a/sw/source/core/inc/flyfrm.hxx +++ b/sw/source/core/inc/flyfrm.hxx @@ -37,6 +37,8 @@ namespace tools { class PolyPolygon; } class SwFlyDrawContact; class SwFormat; class SwViewShell; +class SwFEShell; +class SwWrtShell; /** search an anchor for paragraph bound frames starting from pOldAnch @@ -267,6 +269,13 @@ public: Point& ContentPos() { return m_aContentPos; } void InvalidateContentPos(); + + void SelectionHasChanged(SwFEShell* pShell); + +private: + bool IsShowUnfloatButton(SwWrtShell* pWrtSh) const; + void UpdateUnfloatButton(SwWrtShell* pWrtSh, bool bShow) const; + void PaintDecorators() const; }; #endif diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index f81a62266a5e..e087f23430ad 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -68,6 +68,12 @@ #include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <bodyfrm.hxx> +#include <FrameControlsManager.hxx> + using namespace ::com::sun::star; static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame ); @@ -279,6 +285,9 @@ void SwFlyFrame::DestroyImpl() FinitDrawObj(); SwLayoutFrame::DestroyImpl(); + + SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(getRootFrame()->GetCurrShell()); + UpdateUnfloatButton(pWrtSh, false); } SwFlyFrame::~SwFlyFrame() @@ -1764,6 +1773,93 @@ void SwFlyFrame::InvalidateContentPos() Invalidate_(); } +void SwFlyFrame::SelectionHasChanged(SwFEShell* pShell) +{ + SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >(pShell); + if (pWrtSh == nullptr) + return; + + UpdateUnfloatButton(pWrtSh, IsShowUnfloatButton(pWrtSh)); +} + +bool SwFlyFrame::IsShowUnfloatButton(SwWrtShell* pWrtSh) const +{ + if (pWrtSh == nullptr) + return false; + + // In read only mode we don't allow unfloat operation + if (pWrtSh->GetViewOptions()->IsReadonly()) + return false; + + const SdrObject *pObj = GetFrameFormat().FindRealSdrObject(); + if (pObj == nullptr) + return false; + + // SwFlyFrame itself can mean images, ole objects, etc, but we interested in actual text frames + if (SwFEShell::GetObjCntType(*pObj) != OBJCNT_FLY) + return false; + + // We show the button only for the selected text frame + SwDrawView *pView = pWrtSh->Imp()->GetDrawView(); + if (pView == nullptr) + return false; + + // Fly frame can be selected only alone + if (pView->GetMarkedObjectList().GetMarkCount() != 1) + return false; + + if(!pView->IsObjMarked(pObj)) + return false; + + // A frame is a floating table if there is only one table (and maybe some whitespaces) inside it + int nTableCount = 0; + const SwFrame* pLower = GetLower(); + const SwTabFrame* pTable = nullptr; + while (pLower) + { + if (pLower->IsTabFrame()) + { + pTable = static_cast<const SwTabFrame*>(pLower); + ++nTableCount; + if (nTableCount > 1 || pTable == nullptr) + return false; + } + + if (pLower->IsTextFrame()) + { + const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(pLower); + if (!pTextFrame->GetText().trim().isEmpty()) + return false; + } + pLower = pLower->GetNext(); + } + + if (nTableCount != 1 || pTable == nullptr) + return false; + + // Show the unfold button only for multipage tables + const SwBodyFrame *pBody = GetAnchorFrame()->FindBodyFrame(); + if (pBody == nullptr) + return false; + + long nBodyHeight = pBody->getFrameArea().Height(); + long nTableHeight = pTable->getFrameArea().Height(); + long nFrameOffset = std::abs(GetAnchorFrame()->getFrameArea().Top() - pBody->getFrameArea().Top()); + + return nBodyHeight < nTableHeight + nFrameOffset; +} + +void SwFlyFrame::UpdateUnfloatButton(SwWrtShell* pWrtSh, bool bShow) const +{ + if (pWrtSh == nullptr) + return; + + SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); + SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); + Point aBottomRightPixel = rEditWin.LogicToPixel( getFrameArea().BottomRight() ); + rMngr.SetFloatingTableButton(this, bShow, aBottomRightPixel); +} + SwTwips SwFlyFrame::Grow_( SwTwips nDist, bool bTst ) { SwRectFnSet aRectFnSet(this); diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 0a9338f462b6..f116678d0b59 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -4094,12 +4094,24 @@ void SwFlyFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& // have to paint frame borders added in heaven layer here... ProcessPrimitives(gProp.pBLines->GetBorderLines_Clear()); + PaintDecorators(); + rRenderContext.Pop(); if ( gProp.pSProgress && pNoText ) SfxProgress::Reschedule(); } +void SwFlyFrame::PaintDecorators() const +{ + // Show the un-float button + SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell ); + if ( pWrtSh ) + { + UpdateUnfloatButton(pWrtSh, IsShowUnfloatButton(pWrtSh)); + } +} + void SwTabFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const { const SwViewOption* pViewOption = gProp.pSGlobalShell->GetViewOptions(); commit 5224950508e484adcfe03d7815cbc3f29eaa8de7 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Fri Jan 4 20:16:12 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Unfloat: Introduce Unfloat table button as a frame control Use the same button style and color what LO uses for header/footer button. Later it might be a good idea to have a separate configurable color for this button, but for now it's seems unneeded to introduce a new configure option for this. Reviewed-on: https://gerrit.libreoffice.org/65818 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 021c3a0ee1c95a1b0b8e7c72f9d8e81718862a62) Change-Id: Idf86aaa44e29846a2ee211a81fe5376b4335bb05 Reviewed-on: https://gerrit.libreoffice.org/65869 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index f69c69adc337..2751a24a4b00 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -608,6 +608,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\ sw/source/uibase/docvw/AnnotationWin2 \ sw/source/uibase/docvw/DashedLine \ sw/source/uibase/docvw/FrameControlsManager \ + sw/source/uibase/docvw/FloatingTableButton \ sw/source/uibase/docvw/PageBreakWin \ sw/source/uibase/docvw/OverlayRanges \ sw/source/uibase/docvw/PostItMgr \ diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx index 5d45fa3e6621..e5e3275bcbec 100644 --- a/sw/inc/fesh.hxx +++ b/sw/inc/fesh.hxx @@ -227,8 +227,6 @@ private: SAL_DLLPRIVATE bool ImpEndCreate(); - SAL_DLLPRIVATE static ObjCntType GetObjCntType( const SdrObject& rObj ); - /// Methods for copying of draw objects. SAL_DLLPRIVATE bool CopyDrawSel( SwFEShell* pDestShell, const Point& rSttPt, const Point& rInsPt, bool bIsMove, @@ -311,6 +309,7 @@ public: * drag&drop of controls into header */ bool IsSelContainsControl() const; + static ObjCntType GetObjCntType( const SdrObject& rObj ); ObjCntType GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const; ObjCntType GetObjCntTypeOfSelection() const; diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc index f0a07cd6e1b0..1b3153dab176 100644 --- a/sw/inc/strings.hrc +++ b/sw/inc/strings.hrc @@ -1204,6 +1204,8 @@ #define STR_DELETE_FOOTER NC_("STR_DELETE_FOOTER", "Delete Footer...") #define STR_FORMAT_FOOTER NC_("STR_FORMAT_FOOTER", "Format Footer...") +#define STR_UNFLOAT_TABLE NC_("STR_UNFLOAT_TABLE", "Un-float Table") + #define STR_GRFILTER_OPENERROR NC_("STR_GRFILTER_OPENERROR", "Image file cannot be opened") #define STR_GRFILTER_IOERROR NC_("STR_GRFILTER_IOERROR", "Image file cannot be read") #define STR_GRFILTER_FORMATERROR NC_("STR_GRFILTER_FORMATERROR", "Unknown image format") diff --git a/sw/inc/swtypes.hxx b/sw/inc/swtypes.hxx index a89413ccfa7d..41ce4e820e8f 100644 --- a/sw/inc/swtypes.hxx +++ b/sw/inc/swtypes.hxx @@ -248,7 +248,8 @@ enum FrameControlType { PageBreak, Header, - Footer + Footer, + FloatingTable }; #endif diff --git a/sw/source/uibase/docvw/FloatingTableButton.cxx b/sw/source/uibase/docvw/FloatingTableButton.cxx new file mode 100644 index 000000000000..8f124f46f652 --- /dev/null +++ b/sw/source/uibase/docvw/FloatingTableButton.cxx @@ -0,0 +1,117 @@ +/* -*- 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 <FloatingTableButton.hxx> +#include <HeaderFooterWin.hxx> + +#include <edtwin.hxx> +#include <strings.hrc> +#include <vcl/metric.hxx> +#include <viewopt.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/attribute/fontattribute.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> +#include <basegfx/vector/b2dvector.hxx> + +#define TEXT_PADDING 3 +#define BOX_DISTANCE 3 +#define BUTTON_WIDTH 12 + +FloatingTableButton::FloatingTableButton(SwEditWin* pEditWin, const SwFrame* pFrame) + : SwFrameMenuButtonBase(pEditWin, pFrame) + , m_sLabel(SwResId(STR_UNFLOAT_TABLE)) +{ +} + +FloatingTableButton::~FloatingTableButton() { disposeOnce(); } + +void FloatingTableButton::SetOffset(Point aBottomRightPixel) +{ + // Compute the text size and get the box position & size from it + tools::Rectangle aTextRect; + GetTextBoundRect(aTextRect, m_sLabel); + tools::Rectangle aTextPxRect = LogicToPixel(aTextRect); + FontMetric aFontMetric = GetFontMetric(GetFont()); + Size aBoxSize(aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2, + aFontMetric.GetLineHeight() + TEXT_PADDING * 2); + + Point aBoxPos(aBottomRightPixel.X() - aBoxSize.Width() - BOX_DISTANCE, + aBottomRightPixel.Y() - aBoxSize.Height()); + + if (AllSettings::GetLayoutRTL()) + { + aBoxPos.setX(aBottomRightPixel.X() + BOX_DISTANCE); + } + + // Set the position & Size of the window + SetPosSizePixel(aBoxPos, aBoxSize); +} + +void FloatingTableButton::MouseButtonDown(const MouseEvent& /*rMEvt*/) +{ + // Move the table outside of the frame +} + +void FloatingTableButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + SetMapMode(MapMode(MapUnit::MapPixel)); + drawinglayer::primitive2d::Primitive2DContainer aSeq; + const ::tools::Rectangle aRect( + ::tools::Rectangle(Point(0, 0), rRenderContext.PixelToLogic(GetSizePixel()))); + + // Create button + SwFrameButtonPainter::PaintButton(aSeq, aRect, false); + + // Create the text primitive + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); + basegfx::B2DVector aFontSize; + drawinglayer::attribute::FontAttribute aFontAttr + = drawinglayer::primitive2d::getFontAttributeFromVclFont( + aFontSize, rRenderContext.GetFont(), false, false); + + FontMetric aFontMetric = rRenderContext.GetFontMetric(rRenderContext.GetFont()); + double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING; + double nTextOffsetX = std::abs(aRect.GetWidth() - rRenderContext.GetTextWidth(m_sLabel)) / 2.0; + Point aTextPos(nTextOffsetX, nTextOffsetY); + + basegfx::B2DHomMatrix aTextMatrix(basegfx::utils::createScaleTranslateB2DHomMatrix( + aFontSize.getX(), aFontSize.getY(), static_cast<double>(aTextPos.X()), + static_cast<double>(aTextPos.Y()))); + + aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(), aFontAttr, + css::lang::Locale(), aLineColor))); + + // Create the processor and process the primitives + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor( + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, + aNewViewInfos)); + + pProcessor->process(aSeq); +} + +void FloatingTableButton::ShowAll(bool bShow) { Show(bShow); } + +bool FloatingTableButton::Contains(const Point& rDocPt) const +{ + ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel()); + if (aRect.IsInside(rDocPt)) + return true; + + return false; +} + +void FloatingTableButton::SetReadonly(bool bReadonly) { ShowAll(!bReadonly); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ \ No newline at end of file diff --git a/sw/source/uibase/docvw/FrameControlsManager.cxx b/sw/source/uibase/docvw/FrameControlsManager.cxx index e0c09639d09b..6bad9e5dd3af 100644 --- a/sw/source/uibase/docvw/FrameControlsManager.cxx +++ b/sw/source/uibase/docvw/FrameControlsManager.cxx @@ -11,7 +11,9 @@ #include <FrameControlsManager.hxx> #include <HeaderFooterWin.hxx> #include <PageBreakWin.hxx> +#include <FloatingTableButton.hxx> #include <pagefrm.hxx> +#include <flyfrm.hxx> #include <viewopt.hxx> #include <view.hxx> #include <wrtsh.hxx> @@ -137,6 +139,39 @@ void SwFrameControlsManager::SetPageBreakControl( const SwPageFrame* pPageFrame pControl->ShowAll( true ); } +void SwFrameControlsManager::SetFloatingTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aBottomRightPixel ) +{ + if(pFlyFrame == nullptr) + return; + + // Check if we already have the control + SwFrameControlPtr pControl; + + SwFrameControlPtrMap& rControls = m_aControls[FloatingTable]; + + SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pFlyFrame); + if (lb != rControls.end() && !(rControls.key_comp()(pFlyFrame, lb->first))) + pControl = lb->second; + else if (!bShow) // Do not create the control when it's not shown + return; + else + { + SwFrameControlPtr pNewControl( new SwFrameControl( + VclPtr<FloatingTableButton>::Create( m_pEditWin, pFlyFrame ).get() ) ); + const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions(); + pNewControl->SetReadonly( pViewOpt->IsReadonly() ); + + rControls.insert(lb, make_pair(pFlyFrame, pNewControl)); + + pControl.swap( pNewControl ); + } + + FloatingTableButton* pButton = dynamic_cast<FloatingTableButton*>(pControl->GetWindow()); + assert(pButton != nullptr); + pButton->SetOffset(aBottomRightPixel); + pControl->ShowAll( bShow ); +} + SwFrameMenuButtonBase::SwFrameMenuButtonBase( SwEditWin* pEditWin, const SwFrame* pFrame ) : MenuButton( pEditWin, WB_DIALOGCONTROL ), m_pEditWin( pEditWin ), @@ -146,7 +181,13 @@ SwFrameMenuButtonBase::SwFrameMenuButtonBase( SwEditWin* pEditWin, const SwFrame const SwPageFrame* SwFrameMenuButtonBase::GetPageFrame() { - return static_cast< const SwPageFrame * >( m_pFrame ); + if (m_pFrame->IsPageFrame()) + return static_cast<const SwPageFrame*>( m_pFrame ); + + if (m_pFrame->IsFlyFrame()) + return static_cast<const SwFlyFrame*>(m_pFrame)->GetAnchorFrame()->FindPageFrame(); + + return m_pFrame->FindPageFrame(); } void SwFrameMenuButtonBase::dispose() diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx b/sw/source/uibase/docvw/HeaderFooterWin.cxx index 9e66daab2a24..411c1f3c87d2 100644 --- a/sw/source/uibase/docvw/HeaderFooterWin.cxx +++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx @@ -80,7 +80,7 @@ namespace return basegfx::utils::hsl2rgb( aHslDark ); } - B2DPolygon lcl_GetPolygon( const ::tools::Rectangle& rRect, bool bHeader ) + B2DPolygon lcl_GetPolygon( const ::tools::Rectangle& rRect, bool bOnTop ) { const double nRadius = 3; const double nKappa((M_SQRT2 - 1.0) * 4.0 / 3.0); @@ -112,7 +112,7 @@ namespace aPolygon.append( B2DPoint( rRect.Right(), rRect.Top() ) ); - if ( !bHeader ) + if ( !bOnTop ) { B2DRectangle aBRect( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ); B2DHomMatrix aRotation = createRotateAroundPoint( @@ -124,6 +124,42 @@ namespace } } +void SwFrameButtonPainter::PaintButton(drawinglayer::primitive2d::Primitive2DContainer& rSeq, + const tools::Rectangle& rRect, bool bOnTop) +{ + rSeq.clear(); + B2DPolygon aPolygon = lcl_GetPolygon(rRect, bOnTop); + + // Colors + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); + basegfx::BColor aFillColor = lcl_GetFillColor(aLineColor); + basegfx::BColor aLighterColor = lcl_GetLighterGradientColor(aFillColor); + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + if (rSettings.GetHighContrastMode()) + { + aFillColor = rSettings.GetDialogColor().getBColor(); + aLineColor = rSettings.GetDialogTextColor().getBColor(); + + rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aFillColor))); + } + else + { + B2DRectangle aGradientRect(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom()); + double nAngle = M_PI; + if (bOnTop) + nAngle = 0; + FillGradientAttribute aFillAttrs(drawinglayer::attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, nAngle, aLighterColor, aFillColor, 10); + rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::FillGradientPrimitive2D(aGradientRect, aFillAttrs))); + } + + // Create the border lines primitive + rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aPolygon, aLineColor))); +} + SwHeaderFooterWin::SwHeaderFooterWin( SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader ) : SwFrameMenuButtonBase( pEditWin, pFrame ), m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/headerfootermenu.ui", ""), @@ -255,42 +291,13 @@ void SwHeaderFooterWin::Paint(vcl::RenderContext& rRenderContext, const ::tools: { // Use pixels for the rest of the drawing SetMapMode(MapMode(MapUnit::MapPixel)); - + drawinglayer::primitive2d::Primitive2DContainer aSeq; const ::tools::Rectangle aRect(::tools::Rectangle(Point(0, 0), rRenderContext.PixelToLogic(GetSizePixel()))); - drawinglayer::primitive2d::Primitive2DContainer aSeq(3); - - B2DPolygon aPolygon = lcl_GetPolygon(aRect, m_bIsHeader); - - // Colors - basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); - basegfx::BColor aFillColor = lcl_GetFillColor(aLineColor); - basegfx::BColor aLighterColor = lcl_GetLighterGradientColor(aFillColor); - const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); - if (rSettings.GetHighContrastMode()) - { - aFillColor = rSettings.GetDialogColor().getBColor(); - aLineColor = rSettings.GetDialogTextColor().getBColor(); - - aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( - new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aFillColor)); - } - else - { - B2DRectangle aGradientRect(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); - double nAngle = M_PI; - if (m_bIsHeader) - nAngle = 0; - FillGradientAttribute aFillAttrs(drawinglayer::attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, nAngle, aLighterColor, aFillColor, 10); - aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( - new drawinglayer::primitive2d::FillGradientPrimitive2D(aGradientRect, aFillAttrs)); - } - - // Create the border lines primitive - aSeq[1] = drawinglayer::primitive2d::Primitive2DReference( - new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aPolygon, aLineColor)); + SwFrameButtonPainter::PaintButton(aSeq, aRect, m_bIsHeader); // Create the text primitive + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); B2DVector aFontSize; FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, rRenderContext.GetFont(), false, false); @@ -302,10 +309,10 @@ void SwHeaderFooterWin::Paint(vcl::RenderContext& rRenderContext, const ::tools: aFontSize.getX(), aFontSize.getY(), double(aTextPos.X()), double(aTextPos.Y()))); - aSeq[2] = drawinglayer::primitive2d::Primitive2DReference( + aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), - std::vector<double>(), aFontAttr, css::lang::Locale(), aLineColor)); + std::vector<double>(), aFontAttr, css::lang::Locale(), aLineColor))); // Create the 'plus' or 'arrow' primitive B2DRectangle aSignArea(B2DPoint(aRect.Right() - BUTTON_WIDTH, 0.0), diff --git a/sw/source/uibase/inc/FloatingTableButton.hxx b/sw/source/uibase/inc/FloatingTableButton.hxx new file mode 100644 index 000000000000..b64ddfe07912 --- /dev/null +++ b/sw/source/uibase/inc/FloatingTableButton.hxx @@ -0,0 +1,37 @@ +/* -*- 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_UIBASE_DOCVW_FLOATINGTABLEBUTTON_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_FLOATINGTABLEBUTTON_HXX + +#include "FrameControl.hxx" +#include <vcl/menubtn.hxx> + +class FloatingTableButton : public SwFrameMenuButtonBase +{ + OUString m_sLabel; + +public: + FloatingTableButton(SwEditWin* pEditWin, const SwFrame* pFrame); + virtual ~FloatingTableButton() override; + + void SetOffset(Point aBottomRightPixel); + + virtual void MouseButtonDown(const MouseEvent& rMEvt) override; + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + + virtual void ShowAll(bool bShow) override; + virtual bool Contains(const Point& rDocPt) const override; + + virtual void SetReadonly(bool bReadonly) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ \ No newline at end of file diff --git a/sw/source/uibase/inc/FrameControlsManager.hxx b/sw/source/uibase/inc/FrameControlsManager.hxx index df449922d755..096e61376b8c 100644 --- a/sw/source/uibase/inc/FrameControlsManager.hxx +++ b/sw/source/uibase/inc/FrameControlsManager.hxx @@ -47,6 +47,7 @@ class SwFrameControlsManager // Helper methods void SetHeaderFooterControl( const SwPageFrame* pPageFrame, FrameControlType eType, Point aOffset ); void SetPageBreakControl( const SwPageFrame* pPageFrame ); + void SetFloatingTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aTopLeftPixel = Point() ); }; #endif diff --git a/sw/source/uibase/inc/HeaderFooterWin.hxx b/sw/source/uibase/inc/HeaderFooterWin.hxx index 47853074eec9..33a49c2d52e3 100644 --- a/sw/source/uibase/inc/HeaderFooterWin.hxx +++ b/sw/source/uibase/inc/HeaderFooterWin.hxx @@ -12,6 +12,16 @@ #include "FrameControl.hxx" #include <vcl/builder.hxx> #include <vcl/menubtn.hxx> +#include <vcl/timer.hxx> +#include <drawinglayer/primitive2d/baseprimitive2d.hxx> + +class SwFrameButtonPainter +{ +public: + + static void PaintButton(drawinglayer::primitive2d::Primitive2DContainer& rSeq, + const tools::Rectangle& rRect, bool bOnTop); +}; /** Class for the header and footer separator control window. commit 1efbc847abd8cfeb7335045340691a351dae6e3c Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Thu Jan 3 12:23:18 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jun 19 14:28:17 2019 +0200 Move FindBodyFrame from SwTextFrame to SwFrame So we can call it on other type of frames too. Reviewed-on: https://gerrit.libreoffice.org/65817 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 484867ec5e716a1828a41b2535f7a1e10e8f3fe7) Reviewed-on: https://gerrit.libreoffice.org/65868 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 641f8a1370d6b57fc35778a833b601de7fb14954) Change-Id: I74e80eb831ba1fc00abb8db1ffa3728758e68376 diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index 920bd621fff4..0a9a1ea823c0 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -38,6 +38,7 @@ class SwLayoutFrame; class SwRootFrame; class SwPageFrame; +class SwBodyFrame; class SwFlyFrame; class SwSectionFrame; class SwFootnoteFrame; @@ -661,6 +662,7 @@ public: SwFootnoteFrame *ImplFindFootnoteFrame(); SwFlyFrame *ImplFindFlyFrame(); SwSectionFrame *ImplFindSctFrame(); + const SwBodyFrame *ImplFindBodyFrame() const; SwFrame *FindFooterOrHeader(); SwFrame *GetLower(); const SwFrame *GetNext() const { return mpNext; } @@ -683,6 +685,7 @@ public: inline const SwFootnoteFrame *FindFootnoteFrame() const; inline const SwFlyFrame *FindFlyFrame() const; inline const SwSectionFrame *FindSctFrame() const; + inline const SwBodyFrame *FindBodyFrame() const; inline const SwFrame *FindNext() const; // #i27138# - add parameter <_bInSameFootnote> const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const; @@ -1085,6 +1088,11 @@ inline SwSectionFrame *SwFrame::FindSctFrame() return IsInSct() ? ImplFindSctFrame() : nullptr; } +inline const SwBodyFrame *SwFrame::FindBodyFrame() const +{ + return IsInDocBody() ? ImplFindBodyFrame() : nullptr; +} + inline const SwTabFrame *SwFrame::FindTabFrame() const { return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr; diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index bf4c0ad8a316..86882201fbfd 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -591,8 +591,6 @@ public: /// Respect the Follows inline bool IsInside(TextFrameIndex nPos) const; - const SwBodyFrame *FindBodyFrame() const; - /// DropCaps and selections bool GetDropRect( SwRect &rRect ) const { return HasPara() && GetDropRect_( rRect ); } diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx index a38f9f989529..5bdb1de12702 100644 --- a/sw/source/core/layout/findfrm.cxx +++ b/sw/source/core/layout/findfrm.cxx @@ -31,6 +31,7 @@ #include <fmtftn.hxx> #include <fmtpdsc.hxx> #include <txtfrm.hxx> +#include <bodyfrm.hxx> #include <calbck.hxx> #include <viewopt.hxx> #include <sal/log.hxx> @@ -486,6 +487,18 @@ SwSectionFrame* SwFrame::ImplFindSctFrame() return static_cast<SwSectionFrame*>(pRet); } +const SwBodyFrame* SwFrame::ImplFindBodyFrame() const +{ + const SwFrame *pRet = this; + while ( !pRet->IsBodyFrame() ) + { + pRet = pRet->GetUpper(); + if ( !pRet ) + return nullptr; + } + return static_cast<const SwBodyFrame*>(pRet); +} + SwFootnoteFrame *SwFrame::ImplFindFootnoteFrame() { SwFrame *pRet = this; diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx index dad1b9a47109..a513fde52629 100644 --- a/sw/source/core/text/frmform.cxx +++ b/sw/source/core/text/frmform.cxx @@ -172,18 +172,6 @@ bool SwTextFrame::GetDropRect_( SwRect &rRect ) const return false; } -const SwBodyFrame *SwTextFrame::FindBodyFrame() const -{ - if ( IsInDocBody() ) - { - const SwFrame *pFrame = GetUpper(); - while( pFrame && !pFrame->IsBodyFrame() ) - pFrame = pFrame->GetUpper(); - return static_cast<const SwBodyFrame*>(pFrame); - } - return nullptr; -} - bool SwTextFrame::CalcFollow(TextFrameIndex const nTextOfst) { vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut(); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits