diff options
author | Justin Luth <justin_luth@sil.org> | 2019-07-03 15:33:35 +0300 |
---|---|---|
committer | Justin Luth <justin_luth@sil.org> | 2019-07-22 06:07:29 +0200 |
commit | 82c3e68642de445064313e353812b54df76c7fe9 (patch) | |
tree | affbde4996b940f506cd40409fc077d095b11f01 /svx/source | |
parent | 382aceb80d3c0f420d51762e1f88eee2334ff11b (diff) |
tdf#118370 Draw: add option to consolidate multiple textObjs
This gives the user a tool to consolidate multiple textboxes
into a single textbox. First the user selects a group of
textframes, and then runs the consolidate text function.
This will REPLACE the marked textframes with a single textbox
combining all of the text. The function inspects the text
fragments to see if they end in sentence-ending punctuation.
If not, then the next textbox's content is appended to it
instead of starting a new pargraph. It is the user's responsibility
to afterwards fix up paragraphing, and set paragraph properties.
The rational for this patch is to simplify making major text
changes on PDFs imported into Draw, since each paragraph is
currently broken into tiny character-property textbox fragments.
Copy/paste from the PDF itself doesn't keep character attributes,
so it is hard for a user to re-create the text.
This is related to tdf#32249, but as a comment says, a better
solution would be to write an entire text-focused PDF import,
rather than just pick up the pieces. And I agree, but considering
this simple patch took me a couple of weeks of frustration,
I'm obviously not the person to do that. And since the bug
has been open for 9 years, likely no one else will either.
Thus, this pick-up-the-pieces tool to help the end user.
This initial patch works only with textFrames, but can
easily be adjusted to consolidate other HasText() SdrObjects.
However, that tended to produce unexpected results, so everything
other than OBJ_TEXT is explicitly excluded.
(Thus general shapes with text, callouts, text-along-path etc
are ignored.)
Change-Id: I68a9a5b187bf320a8e671414c5cb22b07725fd52
Reviewed-on: https://gerrit.libreoffice.org/75043
Tested-by: Jenkins
Reviewed-by: Justin Luth <justin_luth@sil.org>
Diffstat (limited to 'svx/source')
-rw-r--r-- | svx/source/svdraw/svdedtv2.cxx | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx index 47dd34025de2..5a7bf23d64f4 100644 --- a/svx/source/svdraw/svdedtv2.cxx +++ b/svx/source/svdraw/svdedtv2.cxx @@ -21,6 +21,7 @@ #include <editeng/outliner.hxx> #include <svx/svdundo.hxx> #include <svx/svdogrp.hxx> +#include <svx/svdoutl.hxx> #include <svx/svdovirt.hxx> #include <svx/svdopath.hxx> #include <svx/svdpage.hxx> @@ -33,6 +34,7 @@ #include <svx/sdshitm.hxx> #include <svx/xfillit0.hxx> #include <svx/xlineit0.hxx> +#include <svx/xtextit0.hxx> #include "svdfmtf.hxx" #include "svdpdf.hxx" #include <svx/svdetc.hxx> @@ -45,6 +47,7 @@ #include <svx/strings.hrc> #include <svx/svdoashp.hxx> #include <basegfx/polygon/b2dpolypolygoncutter.hxx> +#include <i18nutil/unicode.hxx> #include <sal/log.hxx> #include <tools/debug.hxx> #include <memory> @@ -1213,6 +1216,70 @@ void SdrEditView::EqualizeMarkedObjects(bool bWidth) EndUndo(); } +void SdrEditView::CombineMarkedTextObjects() +{ + SdrPageView* pPageView = GetSdrPageView(); + if ( !pPageView || pPageView->IsLayerLocked( GetActiveLayer() ) ) + return; + + bool bUndo = IsUndoEnabled(); + + // Undo-String will be set later + if ( bUndo ) + BegUndo(); + + SdrOutliner& rDrawOutliner = getSdrModelFromSdrView().GetDrawOutliner(); + + SdrObjListIter aIter( GetMarkedObjectList(), SdrIterMode::Flat); + while ( aIter.IsMore() ) + { + SdrObject* pObj = aIter.Next(); + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( pObj ); + const OutlinerParaObject* pOPO = pTextObj ? pTextObj->GetOutlinerParaObject() : nullptr; + if ( pOPO && pTextObj->IsTextFrame() + && pTextObj->GetObjIdentifier() == OBJ_TEXT // not callouts (OBJ_CAPTION) + && !pTextObj->IsOutlText() // not impress presentation objects + && pTextObj->GetMergedItem(XATTR_FORMTXTSTYLE).GetValue() == XFormTextStyle::NONE // not Fontwork + ) + { + // if the last paragraph does not end in paragraph-end punctuation (ignoring whitespace), + // assume this text should be added to the end of the last paragraph, instead of starting a new paragraph. + const sal_Int32 nPara = rDrawOutliner.GetParagraphCount(); + const OUString sLastPara = nPara ? rDrawOutliner.GetText( rDrawOutliner.GetParagraph( nPara - 1 ) ) : ""; + sal_Int32 n = sLastPara.getLength(); + while ( n && unicode::isWhiteSpace( sLastPara[--n] ) ) + ; + //TODO: find way to use Locale to identify sentence final punctuation. Copied IsSentenceAtEnd() from autofmt.cxx + const bool bAppend = !n || ( sLastPara[n] != '.' && sLastPara[n] != '?' && sLastPara[n] != '!' ); + rDrawOutliner.AddText( *pOPO, bAppend ); + } + else + { + // Unmark non-textboxes, because all marked objects are deleted at the end. AdjustMarkHdl later. + MarkObj(pObj, pPageView, /*bUnmark=*/true, /*bImpNoSetMarkHdl=*/true); + } + } + + MarkListHasChanged(); + AdjustMarkHdl(); + + if ( GetMarkedObjectCount() > 1 ) + { + SdrRectObj* pReplacement = new SdrRectObj( getSdrModelFromSdrView(), OBJ_TEXT ); + pReplacement->SetOutlinerParaObject( rDrawOutliner.CreateParaObject() ); + pReplacement->SetSnapRect( GetMarkedObjRect() ); + + const SdrInsertFlags nFlags = SdrInsertFlags::DONTMARK | SdrInsertFlags::SETDEFLAYER; + if ( InsertObjectAtView( pReplacement, *pPageView, nFlags ) ) + DeleteMarkedObj(); + } + + if ( bUndo ) + EndUndo(); + + return; +} + void SdrEditView::CombineMarkedObjects(bool bNoPolyPoly) { // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would |