officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu | 8 + sw/inc/cmdid.h | 1 sw/qa/uibase/wrtsh/wrtsh.cxx | 22 ++++ sw/sdi/_textsh.sdi | 6 + sw/sdi/swriter.sdi | 17 +++ sw/source/uibase/dochdl/swdtflvr.cxx | 10 - sw/source/uibase/inc/wrtsh.hxx | 2 sw/source/uibase/shells/basesh.cxx | 2 sw/source/uibase/shells/textsh.cxx | 5 sw/source/uibase/uiview/view.cxx | 4 sw/source/uibase/uiview/view2.cxx | 4 sw/source/uibase/wrtsh/wrtsh1.cxx | 52 +++++++++- sw/uiconfig/swriter/menubar/menubar.xml | 1 sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml | 1 14 files changed, 120 insertions(+), 15 deletions(-)
New commits: commit 73ed5e36047b6f46b3777bf6f36591ec4babb1f9 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri May 20 13:31:45 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri May 20 16:55:16 2022 +0200 sw content controls, picture: add insert UI - handle the picture case in SwWrtShell::InsertContentControl(): insert a placeholder bitmap & create content control around the as-char image - expose this as a new .uno:InsertPictureContentControl command - add the new uno command to the default & MS-compatible menus - rename the SwWrtShell::Insert() overload taking a Graphic to make this a bit more readable Change-Id: I289d6b6a9cd622c585b6cf0ec0c91d6b51ad81ac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134681 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 1dad35cc2190..2ca80032ed48 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu @@ -651,6 +651,14 @@ <value>1</value> </prop> </node> + <node oor:name=".uno:InsertPictureContentControl" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Insert Picture Content Control</value> + </prop> + <prop oor:name="Properties" oor:type="xs:int"> + <value>1</value> + </prop> + </node> <node oor:name=".uno:InsertObjectDialog" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Insert Other Objects</value> diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index 0e1691d7ec2d..8b102cae3bf1 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -223,6 +223,7 @@ class SwUINumRuleItem; #define FN_INSERT_PAGEBREAK (FN_INSERT + 23) /* Page break*/ #define FN_INSERT_DROPDOWN_CONTENT_CONTROL (FN_INSERT + 24) /* Dropdown content control */ #define FN_CONTENT_CONTROL_PROPERTIES (FN_INSERT + 25) /* Content control properties */ +#define FN_INSERT_PICTURE_CONTENT_CONTROL (FN_INSERT + 26) /* Picture content control */ #define FN_POSTIT (FN_INSERT + 29) /* Insert/edit PostIt */ #define FN_INSERT_TABLE (FN_INSERT + 30) /* Insert Table */ #define FN_INSERT_STRING (FN_INSERT+31) diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx index 297e7a2d1ebd..3fd708bf2a48 100644 --- a/sw/qa/uibase/wrtsh/wrtsh.cxx +++ b/sw/qa/uibase/wrtsh/wrtsh.cxx @@ -285,6 +285,28 @@ CPPUNIT_TEST_FIXTURE(Test, testReplacePictureContentControl) // killed the image selection. CPPUNIT_ASSERT(pWrtShell->IsFrameSelected()); } + +CPPUNIT_TEST_FIXTURE(Test, testInsertPictureContentControl) +{ + // Given an empty document: + SwDoc* pDoc = createSwDoc(); + + // When inserting a content control: + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->InsertContentControl(SwContentControlType::PICTURE); + + // Then make sure that the matching text attribute is added to the document model: + SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode(); + SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, RES_TXTATR_CONTENTCONTROL); + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + auto& rFormatContentControl + = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr()); + std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl(); + // Without the accompanying fix in place, this test would have failed, there was no special + // handling for picture content control, no placeholder fly content was inserted. + CPPUNIT_ASSERT(pContentControl->GetPicture()); + CPPUNIT_ASSERT(pTextNode->GetTextAttrForCharAt(1, RES_TXTATR_FLYCNT)); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi index 4c4e042e45a5..6f6ad01a1536 100644 --- a/sw/sdi/_textsh.sdi +++ b/sw/sdi/_textsh.sdi @@ -290,6 +290,12 @@ interface BaseText StateMethod = NoState ; DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; ] + FN_INSERT_PICTURE_CONTENT_CONTROL // status(final|play) + [ + ExecMethod = ExecInsert ; + StateMethod = NoState ; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] FN_CONTENT_CONTROL_PROPERTIES // status(final|play) [ ExecMethod = ExecInsert ; diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi index 4bd53a1557d9..285f1fdfa7e4 100644 --- a/sw/sdi/swriter.sdi +++ b/sw/sdi/swriter.sdi @@ -3083,6 +3083,23 @@ SfxVoidItem InsertDropdownContentControl FN_INSERT_DROPDOWN_CONTENT_CONTROL GroupId = SfxGroupId::Insert; ] +SfxVoidItem InsertPictureContentControl FN_INSERT_PICTURE_CONTENT_CONTROL +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Insert; +] + SfxVoidItem ContentControlProperties FN_CONTENT_CONTROL_PROPERTIES () [ diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx index 2e81d7495a43..7768414cb4ba 100644 --- a/sw/source/uibase/dochdl/swdtflvr.cxx +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -2499,7 +2499,7 @@ bool SwTransferable::PasteTargetURL( const TransferableDataHelper& rData, { case SwPasteSdr::Insert: SwTransferable::SetSelInShell( rSh, false, pPt ); - rSh.Insert(sURL, OUString(), aGraphic); + rSh.InsertGraphic(sURL, OUString(), aGraphic); break; case SwPasteSdr::Replace: @@ -2521,7 +2521,7 @@ bool SwTransferable::PasteTargetURL( const TransferableDataHelper& rData, else { SwTransferable::SetSelInShell( rSh, false, pPt ); - rSh.Insert(sURL, OUString(), aGraphic); + rSh.InsertGraphic(sURL, OUString(), aGraphic); } break; default: @@ -2627,7 +2627,7 @@ bool SwTransferable::PasteDDE( const TransferableDataHelper& rData, if ( bReReadGrf ) rWrtShell.ReRead( aCmd, sLnkTyp, &aGrf ); else - rWrtShell.Insert( aCmd, sLnkTyp, aGrf ); + rWrtShell.InsertGraphic( aCmd, sLnkTyp, aGrf ); } return bRet; } @@ -2922,7 +2922,7 @@ bool SwTransferable::PasteGrf( const TransferableDataHelper& rData, SwWrtShell& case SwPasteSdr::Insert: { SwTransferable::SetSelInShell( rSh, false, pPt ); - rSh.Insert(sURL, OUString(), aGraphic, nullptr, nAnchorType); + rSh.InsertGraphic(sURL, OUString(), aGraphic, nullptr, nAnchorType); break; } @@ -2976,7 +2976,7 @@ bool SwTransferable::PasteGrf( const TransferableDataHelper& rData, SwWrtShell& else { SwTransferable::SetSelInShell( rSh, false, pPt ); - rSh.Insert(aBkmk.GetURL(), OUString(), aGraphic); + rSh.InsertGraphic(aBkmk.GetURL(), OUString(), aGraphic); } break; } diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index a80f42c8315a..91cb72146fc0 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -309,7 +309,7 @@ typedef bool (SwWrtShell::*FNSimpleMove)(); bool InsertField2(SwField const &, SwPaM* pAnnotationRange = nullptr); void Insert(const OUString &); // graphic - void Insert( const OUString &rPath, const OUString &rFilter, + void InsertGraphic( const OUString &rPath, const OUString &rFilter, const Graphic &, SwFlyFrameAttrMgr * = nullptr, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA); diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index c5b46d42d90d..e63384824b43 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -919,7 +919,7 @@ void SwBaseShell::Execute(SfxRequest &rReq) if ( nSelType & SelectionType::Graphic ) rSh.ReRead( aGrfName, aFltName, &aGrf ); else - rSh.Insert( aGrfName, aFltName, aGrf ); + rSh.InsertGraphic( aGrfName, aFltName, aGrf ); GetView().GetEditWin().GrabFocus(); } diff --git a/sw/source/uibase/shells/textsh.cxx b/sw/source/uibase/shells/textsh.cxx index bd624db80afe..ded35969ff39 100644 --- a/sw/source/uibase/shells/textsh.cxx +++ b/sw/source/uibase/shells/textsh.cxx @@ -234,6 +234,11 @@ void SwTextShell::ExecInsert(SfxRequest &rReq) rReq.Done(); break; + case FN_INSERT_PICTURE_CONTENT_CONTROL: + rSh.InsertContentControl(SwContentControlType::PICTURE); + rReq.Done(); + break; + case FN_CONTENT_CONTROL_PROPERTIES: { SwWrtShell& rWrtSh = GetShell(); diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx index 9bec819807ee..359e1b27fa49 100644 --- a/sw/source/uibase/uiview/view.cxx +++ b/sw/source/uibase/uiview/view.cxx @@ -593,7 +593,7 @@ void SwView::CheckReadonlyState() FN_INSERT_HARDHYPHEN, FN_INSERT_HARD_SPACE, FN_INSERT_NNBSP, FN_INSERT_BREAK, FN_INSERT_LINEBREAK, FN_INSERT_COLUMN_BREAK, FN_INSERT_BREAK_DLG, FN_INSERT_CONTENT_CONTROL, FN_INSERT_CHECKBOX_CONTENT_CONTROL, - FN_INSERT_DROPDOWN_CONTENT_CONTROL, + FN_INSERT_DROPDOWN_CONTENT_CONTROL, FN_INSERT_PICTURE_CONTENT_CONTROL, FN_DELETE_SENT, FN_DELETE_BACK_SENT, FN_DELETE_WORD, FN_DELETE_BACK_WORD, FN_DELETE_LINE, FN_DELETE_BACK_LINE, FN_DELETE_PARA, FN_DELETE_BACK_PARA, FN_DELETE_WHOLE_LINE, @@ -1797,7 +1797,7 @@ void SwView::ScannerEventHdl() if( !aScanBmp.IsEmpty() ) { Graphic aGrf(aScanBmp); - m_pWrtShell->Insert( OUString(), OUString(), aGrf ); + m_pWrtShell->InsertGraphic( OUString(), OUString(), aGrf ); } } } diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx index 75219fcbab07..e716c96b31f6 100644 --- a/sw/source/uibase/uiview/view2.cxx +++ b/sw/source/uibase/uiview/view2.cxx @@ -287,11 +287,11 @@ ErrCode SwView::InsertGraphic( const OUString &rPath, const OUString &rFilter, OUString sURL = URIHelper::SmartRel2Abs( aTemp, rPath, URIHelper::GetMaybeFileHdl() ); aGraphic.setOriginURL(sURL); - rShell.Insert( sURL, rFilter, aGraphic, &aFrameManager ); + rShell.InsertGraphic( sURL, rFilter, aGraphic, &aFrameManager ); } else { - rShell.Insert( OUString(), OUString(), aGraphic, &aFrameManager ); + rShell.InsertGraphic( OUString(), OUString(), aGraphic, &aFrameManager ); } // it is too late after "EndAction" because the Shell can already be destroyed. diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index 965a0e309cb5..ea022fc85b31 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -103,6 +103,7 @@ #include <svx/postattr.hxx> #include <comphelper/lok.hxx> #include <comphelper/propertyvalue.hxx> +#include <svtools/optionsdrawinglayer.hxx> #include <memory> #include <frmtool.hxx> @@ -267,9 +268,9 @@ void SwWrtShell::Insert( const OUString &rStr ) // Maximum height limit not possible, because the maximum height // of the current frame can not be obtained. -void SwWrtShell::Insert( const OUString &rPath, const OUString &rFilter, - const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr, - RndStdIds nAnchorType ) +void SwWrtShell::InsertGraphic( const OUString &rPath, const OUString &rFilter, + const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr, + RndStdIds nAnchorType ) { ResetCursorStack(); if ( !CanInsert() ) @@ -1030,7 +1031,6 @@ void SwWrtShell::InsertContentControl(SwContentControlType eType) switch (eType) { case SwContentControlType::RICH_TEXT: - case SwContentControlType::PICTURE: { pContentControl->SetShowingPlaceHolder(true); if (!HasSelection()) @@ -1061,6 +1061,50 @@ void SwWrtShell::InsertContentControl(SwContentControlType eType) pContentControl->SetListItems({ aListItem }); break; } + case SwContentControlType::PICTURE: + { + // Set up the picture content control. + pContentControl->SetShowingPlaceHolder(true); + pContentControl->SetPicture(true); + + // Create the placeholder bitmap. + BitmapEx aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP); + Color aColor = SvtOptionsDrawinglayer::getHilightColor(); + aColor.IncreaseLuminance(255 * 0.75); + aBitmap.Erase(aColor); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME)); + StartUndo(SwUndoId::INSERT, &aRewriter); + LockPaint(); + StartAction(); + InsertGraphic(OUString(), OUString(), aBitmap, nullptr, RndStdIds::FLY_AS_CHAR); + + // Set properties on the bitmap. + SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE> aSet(GetDoc()->GetAttrPool()); + GetFlyFrameAttr(aSet); + SwFormatFrameSize aSize(SwFrameSize::Fixed, 3000, 3000); + aSet.Put(aSize); + SetFlyFrameAttr(aSet); + SwFrameFormat* pFrameFormat = GetFlyFrameFormat(); + EndAction(); + UnlockPaint(); + EndUndo(); + + // Go after the anchor position. + UnSelectFrame(); + LeaveSelFrameMode(); + { + SwCursor* pCursor = getShellCursor(true); + pCursor->DeleteMark(); + const SwPosition* pAnchor = pFrameFormat->GetAnchor().GetContentAnchor(); + pCursor->GetPoint()->nContent = pAnchor->nContent; + ++pCursor->GetPoint()->nContent; + } + + // Select before the anchor position. + Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); + break; + } } if (aPlaceholder.getLength()) { diff --git a/sw/uiconfig/swriter/menubar/menubar.xml b/sw/uiconfig/swriter/menubar/menubar.xml index dda9338ce381..9ed30d1bf492 100644 --- a/sw/uiconfig/swriter/menubar/menubar.xml +++ b/sw/uiconfig/swriter/menubar/menubar.xml @@ -713,6 +713,7 @@ <menu:menu menu:id=".uno:ContentControlsMenu"> <menu:menupopup> <menu:menuitem menu:id=".uno:InsertContentControl"/> + <menu:menuitem menu:id=".uno:InsertPictureContentControl"/> <menu:menuitem menu:id=".uno:InsertCheckboxContentControl"/> <menu:menuitem menu:id=".uno:InsertDropdownContentControl"/> <menu:menuitem menu:id=".uno:ContentControlProperties"/> diff --git a/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml b/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml index 147b4dd03d6e..cc4483cda320 100644 --- a/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml +++ b/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml @@ -16,6 +16,7 @@ <menu:menu menu:id=".uno:MSCompatContentControls"> <menu:menupopup> <menu:menuitem menu:id=".uno:InsertContentControl"/> + <menu:menuitem menu:id=".uno:InsertPictureContentControl"/> <menu:menuitem menu:id=".uno:InsertCheckboxContentControl"/> <menu:menuitem menu:id=".uno:InsertDropdownContentControl"/> <menu:menuitem menu:id=".uno:DatePickerFormField"/>