summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/inc/crsrsh.hxx3
-rw-r--r--sw/inc/docsh.hxx3
-rw-r--r--sw/qa/extras/uiwriter/uiwriter3.cxx44
-rw-r--r--sw/source/core/crsr/crsrsh.cxx39
-rw-r--r--sw/source/uibase/app/docst.cxx78
5 files changed, 166 insertions, 1 deletions
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 02a08289a889..806b1b7d2472 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -552,6 +552,9 @@ public:
// Check if selection is within one paragraph.
bool IsSelOnePara() const;
+ // Check if selection starts a paragraph.
+ bool IsSelStartPara() const;
+
/*
* Returns SRectangle, at which the cursor is located.
*/
diff --git a/sw/inc/docsh.hxx b/sw/inc/docsh.hxx
index f29c4ed78134..858c778ac784 100644
--- a/sw/inc/docsh.hxx
+++ b/sw/inc/docsh.hxx
@@ -54,6 +54,7 @@ class SwDrawModel;
class SwViewShell;
class SwDocStyleSheetPool;
class SwXTextDocument;
+class SwTextFormatColl;
namespace svt
{
class EmbeddedObjectRef;
@@ -143,6 +144,8 @@ class SW_DLLPUBLIC SwDocShell
SAL_DLLPRIVATE void Delete(const OUString &rName, SfxStyleFamily nFamily);
SAL_DLLPRIVATE void Hide(const OUString &rName, SfxStyleFamily nFamily, bool bHidden);
+ SAL_DLLPRIVATE bool MakeInlineHeading(SwWrtShell *pSh, SwTextFormatColl* pColl,
+ const sal_uInt16 nMode);
SAL_DLLPRIVATE SfxStyleFamily ApplyStyles(const OUString &rName,
const SfxStyleFamily nFamily,
SwWrtShell* pShell,
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx
index f7c31f4e76d8..cbd860f0aabf 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -1315,6 +1315,50 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf147206)
u"HyperLinkURL"_ustr));
}
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf48459)
+{
+ createSwDoc();
+ SwDoc* pDoc = getSwDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+ // insert paragraph text
+ pWrtShell->Insert(u"Heading and normal text"_ustr);
+
+ // select the first word (proposed for inline heading)
+ pWrtShell->SttEndDoc(/*bStart=*/true);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 7, /*bBasicCall=*/false);
+
+ // apply styles only on the selected word -> create inline heading
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
+ { "Style", uno::Any(u"Heading 1"_ustr) },
+ { "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
+ });
+ dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
+
+ uno::Reference<frame::XFrames> xFrames = mxDesktop->getFrames();
+
+ // inline heading frame
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xFrames->getCount());
+
+ pWrtShell->EndOfSection(false);
+
+ // insert table of contents to check ToC content (containing only the inline heading)
+ SwTOXMgr mgr(pWrtShell);
+ SwTOXDescription desc{ TOX_CONTENT };
+ mgr.UpdateOrInsertTOX(desc, nullptr, nullptr);
+
+ CPPUNIT_ASSERT_EQUAL(int(3), getParagraphs());
+
+ // first paragraph: selected text moved to the inline heading frame
+ CPPUNIT_ASSERT_EQUAL(u" and normal text"_ustr, getParagraph(1)->getString());
+
+ // ToC title
+ CPPUNIT_ASSERT_EQUAL(u"Table of Contents"_ustr, getParagraph(2)->getString());
+
+ // ToC contains only the inline heading
+ CPPUNIT_ASSERT_EQUAL(u"Heading\t1"_ustr, getParagraph(3)->getString());
+}
+
CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf144840)
{
createSwDoc("tdf144840.odt");
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index fce43323b19b..6386b8673856 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1394,6 +1394,45 @@ bool SwCursorShell::IsSelOnePara() const
return false;
}
+bool SwCursorShell::IsSelStartPara() const
+{
+ if (m_pCurrentCursor->IsMultiSelection())
+ {
+ return false;
+ }
+ if (m_pCurrentCursor->GetPoint()->GetContentIndex() == 0 ||
+ m_pCurrentCursor->GetMark()->GetContentIndex() == 0)
+ {
+ return true;
+ }
+ if (GetLayout()->HasMergedParas())
+ {
+ SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode());
+ if (pNode)
+ {
+ SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
+ pNode->getLayoutFrame(GetLayout())));
+ if (pFrame)
+ {
+ return pFrame->MapModelToViewPos(*m_pCurrentCursor->GetPoint())
+ == TextFrameIndex(0);
+ }
+ }
+ SwTextNode const*const pNode2(m_pCurrentCursor->GetMark()->GetNode().GetTextNode());
+ if (pNode2)
+ {
+ SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
+ pNode2->getLayoutFrame(GetLayout())));
+ if (pFrame)
+ {
+ return pFrame->MapModelToViewPos(*m_pCurrentCursor->GetMark())
+ == TextFrameIndex(0);
+ }
+ }
+ }
+ return false;
+}
+
bool SwCursorShell::IsSttPara() const
{
if (GetLayout()->HasMergedParas())
diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx
index d6be439d4259..e81ccb9aff8d 100644
--- a/sw/source/uibase/app/docst.cxx
+++ b/sw/source/uibase/app/docst.cxx
@@ -85,6 +85,10 @@
#include <docmodel/theme/Theme.hxx>
#include <svx/svdpage.hxx>
#include <officecfg/Office/Common.hxx>
+#include <fmtfsize.hxx>
+#include <svl/ptitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/ulspitem.hxx>
using namespace ::com::sun::star;
@@ -1170,6 +1174,71 @@ void SwDocShell::Hide(const OUString &rName, SfxStyleFamily nFamily, bool bHidde
}
}
+#define MAX_CHAR_IN_INLINE_HEADING 75
+bool SwDocShell::MakeInlineHeading(SwWrtShell *pSh, SwTextFormatColl* pColl, const sal_uInt16 nMode)
+{
+ // insert an inline heading frame, if only MAX_CHAR_IN_INLINE_HEADING or less
+ // characters are selected beginning of a single paragraph, but not the full paragraph
+ // TODO extend it for multiple selections
+ if ( pSh->IsSelOnePara() && !pSh->IsSelFullPara() && pSh->IsSelStartPara() &&
+ GetView()->GetSelectionText().getLength() < MAX_CHAR_IN_INLINE_HEADING &&
+ 0 < GetView()->GetSelectionText().getLength() )
+ {
+ SwTextFormatColl *pLocal = pColl? pColl: (*GetDoc()->GetTextFormatColls())[0];
+
+ // put inside a single Undo
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, pLocal->GetName());
+ GetWrtShell()->StartUndo(SwUndoId::SETFMTCOLL, &aRewriter);
+
+ // anchor as character
+ SfxUInt16Item aAnchor(FN_INSERT_FRAME, static_cast<sal_uInt16>(1));
+ SvxSizeItem aSizeItem(FN_PARAM_2, Size(1, 1));
+ GetView()->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_FRAME,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD, { &aAnchor, &aSizeItem });
+ if ( pSh->IsFrameSelected() )
+ {
+ // use the borderless frame style "Formula"
+ // TODO add a new frame style "Inline Heading"
+ SwDocStyleSheet* pStyle2 = static_cast<SwDocStyleSheet*>(
+ m_xBasePool->Find( "Formula", SfxStyleFamily::Frame));
+ pSh->SetFrameFormat( pStyle2->GetFrameFormat() );
+
+ // set variable width frame to extend for the width of the text content
+ SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aSet(pSh->GetAttrPool());
+ pSh->GetFlyFrameAttr( aSet );
+ SwTwips nMinWidth = 100;
+ SwFormatFrameSize aSize(SwFrameSize::Variable, nMinWidth, nMinWidth);
+ aSize.SetWidthSizeType(SwFrameSize::Variable);
+ aSet.Put(aSize);
+ pSh->SetFlyFrameAttr( aSet );
+
+ // select the text content of the frame, and apply the paragraph style
+ pSh->UnSelectFrame();
+ pSh->LeaveSelFrameMode();
+ pSh->MoveSection( GoCurrSection, fnSectionEnd );
+ pSh->SelAll();
+
+ pSh->SetTextFormatColl( pColl, true, (nMode & KEY_MOD1) ? SetAttrMode::REMOVE_ALL_ATTR : SetAttrMode::DEFAULT);
+
+ // zero the upper and lower margins of the paragraph (also an interoperability issue)
+ SfxItemSetFixed<RES_UL_SPACE, RES_UL_SPACE> aSet2(pSh->GetAttrPool());
+ pSh->GetCurAttr( aSet2 );
+ SvxULSpaceItem aUL( 0, 0, RES_UL_SPACE );
+ pSh->SetAttrItem( aUL );
+
+ // leave the inline heading frame
+ GetView()->GetViewFrame().GetDispatcher()->Execute(FN_ESCAPE, SfxCallMode::ASYNCHRON);
+ GetView()->GetViewFrame().GetDispatcher()->Execute(FN_ESCAPE, SfxCallMode::ASYNCHRON);
+ GetView()->GetViewFrame().GetDispatcher()->Execute(FN_ESCAPE, SfxCallMode::SYNCHRON);
+
+ GetWrtShell()->EndUndo();
+ return true;
+ }
+ }
+ return false;
+}
+
// apply template
SfxStyleFamily SwDocShell::ApplyStyles(const OUString &rName, SfxStyleFamily nFamily,
SwWrtShell* pShell, const sal_uInt16 nMode )
@@ -1211,10 +1280,17 @@ SfxStyleFamily SwDocShell::ApplyStyles(const OUString &rName, SfxStyleFamily nFa
// outline node become folded content of the previous outline node if the previous
// outline node's content is folded.
MakeAllOutlineContentTemporarilyVisible a(GetDoc());
+
+ // if the first 75 or less characters are selected, but not the full paragraph,
+ // create an inline heading from the selected text
+ SwTextFormatColl* pColl = pStyle->GetCollection();
+ if ( MakeInlineHeading( pSh, pColl, nMode ) )
+ break;
+
// #i62675#
// clear also list attributes at affected text nodes, if paragraph
// style has the list style attribute set.
- pSh->SetTextFormatColl( pStyle->GetCollection(), true, (nMode & KEY_MOD1) ? SetAttrMode::REMOVE_ALL_ATTR : SetAttrMode::DEFAULT);
+ pSh->SetTextFormatColl( pColl, true, (nMode & KEY_MOD1) ? SetAttrMode::REMOVE_ALL_ATTR : SetAttrMode::DEFAULT);
}
break;
}