officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu |    8 +
 sw/inc/cmdid.h                                                      |    1 
 sw/inc/fesh.hxx                                                     |    2 
 sw/qa/core/frmedt/frmedt.cxx                                        |   41 
++++++++++
 sw/sdi/_frmsh.sdi                                                   |    7 +
 sw/sdi/swriter.sdi                                                  |   17 ++++
 sw/source/core/frmedt/fefly1.cxx                                    |   40 
+++++++++
 sw/source/uibase/docvw/UnfloatTableButton.cxx                       |   16 ---
 sw/source/uibase/shells/frmsh.cxx                                   |    6 +
 sw/uiconfig/swriter/popupmenu/frame.xml                             |    1 
 10 files changed, 125 insertions(+), 14 deletions(-)

New commits:
commit 871ca5dd73b34086fad1e57d4697f43a6739a11d
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Nov 17 08:31:41 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Nov 17 10:13:58 2023 +0100

    sw floattable, delete UI: add an uno command to unfloat frame from context 
menu
    
    Word has an easy UI to turn floating tables into inline ones. Writer had
    a similar button, but that had a few shortcomings:
    
    1) It was only visible if a non-split frame was too large to fit the
       page.
    
    2) It was a separate VCL widget, so invisible to LOK clients.
    
    3) It only worked for frames which had a single table in them.
    
    Researching the problem, it's interesting how deleting a frame always
    deletes its content as well, but e.g. deleting a section just removes
    the container but leaves the content in the body text.
    
    Fix the problem by adding a new menu item in the context menu that
    always allows converting the frame to inline content at the anchor
    point. This can share a bit of code with the old unfloat button.
    
    The undo/redo still needs fixing, in a follow-up change.
    
    Change-Id: I8ce05c9f958b08cb599fd5d2a27e770182f28cc7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159550
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git 
a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index dc4d4dbdb399..247f94688255 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -827,6 +827,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:UnfloatFrame" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Unfloat Frame Content</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:InsertIndexesEntry" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Insert Index Entry</value>
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 74ab5cf8c554..165b6aa60a30 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -242,6 +242,7 @@ class SwUINumRuleItem;
 
 #define FN_INSERT_IDX_ENTRY_DLG (FN_INSERT + 35)    /* insert index entry */
 #define FN_INSERT_FRAME_INTERACT_NOCOL (FN_INSERT + 36) /*insert interactive 
non column frame*/
+#define FN_UNFLOAT_FRAME TypedWhichId<SfxUInt16Item>(FN_INSERT + 37) /* 
Unfloat Frame */
 
 #define FN_TOOL_ANCHOR_PAGE     (FN_INSERT + 50)    /* anchor Draw object to 
page */
 #define FN_TOOL_ANCHOR_PARAGRAPH (FN_INSERT + 51)   /* anchor Draw object to 
paragraph */
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index ce1cdc79f3fd..a0a3a64176d7 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -268,6 +268,8 @@ public:
 
     void SelectFlyFrame( SwFlyFrame& rFrame );
 
+    void UnfloatFlyFrame();
+
     /// Is selected frame within another frame?
     const SwFrameFormat* IsFlyInFly();
 
diff --git a/sw/qa/core/frmedt/frmedt.cxx b/sw/qa/core/frmedt/frmedt.cxx
index f5a12e9392f1..55c6c7b9d01f 100644
--- a/sw/qa/core/frmedt/frmedt.cxx
+++ b/sw/qa/core/frmedt/frmedt.cxx
@@ -26,6 +26,8 @@
 #include <caption.hxx>
 #include <view.hxx>
 #include <formatflysplit.hxx>
+#include <itabenum.hxx>
+#include <frmmgr.hxx>
 
 /// Covers sw/source/core/frmedt/ fixes.
 class SwCoreFrmedtTest : public SwModelTestBase
@@ -196,6 +198,45 @@ CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, 
testSplitFlyInsertCaption)
     CPPUNIT_ASSERT(!pFly->GetAttrSet().GetFlySplit().GetValue());
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, testSplitFlyUnfloat)
+{
+    // Given a document with a floating table:
+    createSwDoc();
+    SwDoc* pDoc = getSwDocShell()->GetDoc();
+    sw::FrameFormats<sw::SpzFrameFormat*>& rFlyFormats = 
*pDoc->GetSpzFrameFormats();
+    CPPUNIT_ASSERT(rFlyFormats.empty());
+    // Insert a table:
+    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+    SwInsertTableOptions aTableOptions(SwInsertTableFlags::DefaultBorder, 0);
+    pWrtShell->InsertTable(aTableOptions, /*nRows=*/2, /*nCols=*/1);
+    pWrtShell->MoveTable(GotoPrevTable, fnTableStart);
+    pWrtShell->GoPrevCell();
+    pWrtShell->Insert("A1");
+    pWrtShell->GoNextCell();
+    pWrtShell->Insert("A2");
+    // Select cell:
+    pWrtShell->SelAll();
+    // Select table:
+    pWrtShell->SelAll();
+    // Wrap the table in a text frame:
+    SwFlyFrameAttrMgr aMgr(true, pWrtShell, Frmmgr_Type::TEXT, nullptr);
+    pWrtShell->StartAllAction();
+    aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PARA, aMgr.GetPos(), aMgr.GetSize());
+    pWrtShell->EndAllAction();
+    CPPUNIT_ASSERT(!rFlyFormats.empty());
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
pDoc->GetTableFrameFormatCount(/*bUsed=*/true));
+
+    // When marking that frame and unfloating it:
+    selectShape(1);
+    pWrtShell->UnfloatFlyFrame();
+
+    // Then make sure the frame is removed, but the table is still part of the 
document:
+    // Without the accompanying fix in place (empty 
SwFEShell::UnfloatFlyFrame()), this test would
+    // have failed, the frame was not removed.
+    CPPUNIT_ASSERT(rFlyFormats.empty());
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
pDoc->GetTableFrameFormatCount(/*bUsed=*/true));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/sdi/_frmsh.sdi b/sw/sdi/_frmsh.sdi
index 24ad2f94aa10..0768c01739b9 100644
--- a/sw/sdi/_frmsh.sdi
+++ b/sw/sdi/_frmsh.sdi
@@ -371,6 +371,13 @@ interface BaseTextFrame
         DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
     ]
 
+    FN_UNFLOAT_FRAME
+    [
+        ExecMethod = Execute ;
+        StateMethod = GetState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
+
     SID_ATTR_BORDER // status()
     [
         ExecMethod = ExecFrameStyle ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index 7608b22bac26..74cbeff51b7d 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -3098,6 +3098,23 @@ SfxUInt16Item InsertFrame FN_INSERT_FRAME
     GroupId = SfxGroupId::Insert;
 ]
 
+SfxUInt16Item UnfloatFrame FN_UNFLOAT_FRAME
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Edit;
+]
+
 SfxUInt16Item InsertFrameInteract FN_INSERT_FRAME_INTERACT
 (SfxUInt16Item Columns SID_ATTR_COLUMNS, SfxUInt16Item Modifier SID_MODIFIER)
 [
diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx
index 425db6ed1b27..d9a620122b07 100644
--- a/sw/source/core/frmedt/fefly1.cxx
+++ b/sw/source/core/frmedt/fefly1.cxx
@@ -273,6 +273,46 @@ void SwFEShell::SelectFlyFrame( SwFlyFrame& rFrame )
     SelFlyGrabCursor();
 }
 
+void SwFEShell::UnfloatFlyFrame()
+{
+    SwFlyFrame* pFly = GetSelectedFlyFrame();
+    if (!pFly)
+    {
+        return;
+    }
+
+    SwFrameFormat& rFlyFormat = pFly->GetFrameFormat();
+    const SwFormatContent& rContent = rFlyFormat.GetContent();
+    const SwNodeIndex* pFlyStart = rContent.GetContentIdx();
+    if (!pFlyStart)
+    {
+        return;
+    }
+
+    const SwEndNode* pFlyEnd = pFlyStart->GetNode().EndOfSectionNode();
+    if (!pFlyEnd)
+    {
+        return;
+    }
+
+    SwNodeRange aRange(pFlyStart->GetNode(), SwNodeOffset(1), *pFlyEnd, 
SwNodeOffset(0));
+    const SwFormatAnchor& rAnchor = rFlyFormat.GetAnchor();
+    SwNode* pAnchor = rAnchor.GetAnchorNode();
+    if (!pAnchor)
+    {
+        return;
+    }
+
+    // Move the content outside of the text frame.
+    SwNodeIndex aInsertPos(*pAnchor);
+    IDocumentContentOperations& rIDCO = 
rFlyFormat.GetDoc()->getIDocumentContentOperations();
+    rIDCO.MoveNodeRange(aRange, aInsertPos.GetNode(), 
SwMoveFlags::CREATEUNDOOBJ);
+
+    // Remove the fly frame frame.
+    IDocumentLayoutAccess& rIDLA = rFlyFormat.getIDocumentLayoutAccess();
+    rIDLA.DelLayoutFormat(&rFlyFormat);
+}
+
 // Get selected fly
 SwFlyFrame* SwFEShell::GetSelectedFlyFrame() const
 {
diff --git a/sw/source/uibase/docvw/UnfloatTableButton.cxx 
b/sw/source/uibase/docvw/UnfloatTableButton.cxx
index 30d1d97aaacc..4e8449383ecd 100644
--- a/sw/source/uibase/docvw/UnfloatTableButton.cxx
+++ b/sw/source/uibase/docvw/UnfloatTableButton.cxx
@@ -123,8 +123,6 @@ IMPL_LINK_NOARG(UnfloatTableButton, ClickHdl, 
weld::Button&, void)
     if (pTextFrame->GetTextNodeFirst() == nullptr)
         return;
 
-    SwNodeIndex aInsertPos(*pTextFrame->GetTextNodeFirst());
-
     SwTableNode* pTableNode = pTableFrame->GetTable()->GetTableNode();
     if (pTableNode == nullptr)
         return;
@@ -173,18 +171,8 @@ IMPL_LINK_NOARG(UnfloatTableButton, ClickHdl, 
weld::Button&, void)
         }
     }
 
-    // Move the table outside of the text frame
-    SwNodeRange aRange(*pTableNode, SwNodeOffset(0), 
*pTableNode->EndOfSectionNode(),
-                       SwNodeOffset(1));
-    rDoc.getIDocumentContentOperations().MoveNodeRange(aRange, 
aInsertPos.GetNode(),
-                                                       SwMoveFlags::DEFAULT);
-
-    // Remove the floating table's frame
-    SwFlyFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
-    if (pFrameFormat)
-    {
-        rDoc.getIDocumentLayoutAccess().DelLayoutFormat(pFrameFormat);
-    }
+    SwWrtShell& rWrtShell = GetEditWin()->GetView().GetWrtShell();
+    rWrtShell.UnfloatFlyFrame();
 
     rDoc.getIDocumentState().SetModified();
 
diff --git a/sw/source/uibase/shells/frmsh.cxx 
b/sw/source/uibase/shells/frmsh.cxx
index 0976b6cb42c0..ac5ee0d80835 100644
--- a/sw/source/uibase/shells/frmsh.cxx
+++ b/sw/source/uibase/shells/frmsh.cxx
@@ -269,6 +269,12 @@ void SwFrameShell::Execute(SfxRequest &rReq)
             GetView().UpdateWordCount(this, nSlot);
             break;
         }
+        case FN_UNFLOAT_FRAME:
+        {
+            rSh.UnfloatFlyFrame();
+            rReq.Done();
+            break;
+        }
         default: bMore = true;
     }
 
diff --git a/sw/uiconfig/swriter/popupmenu/frame.xml 
b/sw/uiconfig/swriter/popupmenu/frame.xml
index 959f8df4b173..7a3bfcb22915 100644
--- a/sw/uiconfig/swriter/popupmenu/frame.xml
+++ b/sw/uiconfig/swriter/popupmenu/frame.xml
@@ -50,5 +50,6 @@
   </menu:menu>
   <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:InsertCaptionDialog"/>
+  <menu:menuitem menu:id=".uno:UnfloatFrame"/>
   <menu:menuitem menu:id=".uno:FrameDialog"/>
 </menu:menupopup>

Reply via email to