SmartArt: Add posssibility to edit (simple) text
A loaded SmartArt allows to start TextEdit when one of the included nodes gets klicked. TextEdit seems to work, but the object degrades from a SmartArt to a GroupObject with content. I try to add the preconditions here which are needed to be able to do change at a SmartArt in the future. Basic problem is that the ModelData for SmartArt are 'attached' to the GroupObject that is used for representation, but no ways exist to support edit/change and promote that to that seperated model. One of the main hindrances is that the needed IDs that create the associations between that model and the Shapes is missing, added that. This needs to be added for two scenarios (what makes it complicated): - loaded replacement visualization - re-created SmartArt (add/rmove used) To test this I added a simple text edit that does a first change at that SmartArt model data. For now just simple text, of course TextAttributes need to follow, as do changes when Attributes get changed (Line/Fill/style/...) Thus it's a 1st step and needed quite some experimenting. As long as this is not further progressed (which I try to make happen) the default will stay to have SmartArt as GroupObject with content - as it is today. Unified connect/disconnect, added slot and commands for disconnect, adapted test to use that. Needed to adapt UnitTest testTextEditEmptyGrabBag, it needs to work with a *real* SmartArt/Diagram. The former test created a 'fake' one and checked if on TextEdit the GrabBag gets deleted. The updated SmartArt text edit *tries* to keep the Data (in IDiagramHelper attached to SdrObjGroup). It clears the GrabBag, but only if a 'real' SmartArt exists. Thus I added a bugdoc for that task which contains a 'real' SmartArt to test if GrabBag gets cleared on change of the model data. Also added a modified state to the SmartArt model data (which is in IDiagramHelper). This is needed to decide what shall be done at export time. As long as we have no SmartArt model data export, the fallback to conversion to SdrObjGroup has to be used (as before). Change-Id: Ie6ef3f3a8bbc5da99984d85f79f89e5df308e3c9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195097 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
This commit is contained in:
committed by
Armin Le Grand
parent
ea37a0ab8f
commit
3ad22de97d
@@ -83,8 +83,13 @@ private:
|
||||
// and the layouting stuff
|
||||
bool mbSelfCreated;
|
||||
|
||||
// set to true if the model contained here for the Diagram was
|
||||
// modified
|
||||
bool mbModified; // false
|
||||
|
||||
protected:
|
||||
void anchorToSdrObjGroup(SdrObjGroup& rTarget);
|
||||
// remember associated SdrObjGroup
|
||||
SdrObjGroup* mpAssociatedSdrObjGroup;
|
||||
|
||||
public:
|
||||
IDiagramHelper(bool bSelfCreated);
|
||||
@@ -118,6 +123,18 @@ public:
|
||||
bool isSelfCreated() const { return mbSelfCreated; }
|
||||
void setSelfCreated() { mbSelfCreated = true; }
|
||||
|
||||
// connect/disconnect to/from Group
|
||||
void connectToSdrObjGroup(SdrObjGroup& rTarget);
|
||||
void disconnectFromSdrObjGroup();
|
||||
|
||||
// modified state of this local model. Needs to be set to know
|
||||
// how to do correct export
|
||||
bool isModified() const { return mbModified; }
|
||||
void setModified() { mbModified = true; }
|
||||
|
||||
// react on changes to objects identified by DiagramDataModelID, returns true if a change was done
|
||||
virtual void TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) = 0;
|
||||
|
||||
static void AddAdditionalVisualization(const SdrObjGroup& rTarget, SdrHdlList& rHdlList);
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <com/sun/star/drawing/XShape.hpp>
|
||||
#include <oox/token/tokens.hxx>
|
||||
|
||||
class Outliner;
|
||||
|
||||
namespace svx::diagram {
|
||||
|
||||
enum TypeConstant {
|
||||
@@ -230,6 +232,9 @@ public:
|
||||
DiagramDataStatePtr extractDiagramDataState() const;
|
||||
void applyDiagramDataState(const DiagramDataStatePtr& rState);
|
||||
|
||||
// react on changes to objects identified by DiagramDataModelID, returns true if a change was done
|
||||
bool TextInformationChange(const OUString& rDiagramDataModelID, Outliner& rOutl);
|
||||
|
||||
protected:
|
||||
// helpers
|
||||
void getChildrenString(OUStringBuffer& rBuf, const Point* pPoint, sal_Int32 nLevel) const;
|
||||
|
||||
@@ -227,8 +227,11 @@ class SVXCORE_DLLPUBLIC SdrObject : public SfxListener, public cppu::OWeakObject
|
||||
{
|
||||
public:
|
||||
// Basic DiagramHelper support
|
||||
virtual bool isDiagram() const;
|
||||
virtual const std::shared_ptr< svx::diagram::IDiagramHelper >& getDiagramHelper() const;
|
||||
bool isDiagram() const { return bool(getDiagramHelper()); }
|
||||
const std::shared_ptr< svx::diagram::IDiagramHelper >& getDiagramHelperFromDiagramOrMember() const;
|
||||
void setDiagramDataModelID(const OUString& rID) { msDiagramDataModelID = rID; }
|
||||
const OUString& getDiagramDataModelID() const { return msDiagramDataModelID; }
|
||||
|
||||
private:
|
||||
friend class SdrObjListIter;
|
||||
@@ -984,9 +987,13 @@ private:
|
||||
// HACK: Do not automatically insert newly created object into a page.
|
||||
// The user needs to do it manually later.
|
||||
bool mbDoNotInsertIntoPageAutomatically;
|
||||
|
||||
// Hyperlink for the whole shape
|
||||
OUString msHyperlink;
|
||||
|
||||
// if this object is a representation of Diagram Sub-Data, hold the DataModelID
|
||||
OUString msDiagramDataModelID;
|
||||
|
||||
// only for internal use!
|
||||
SvxShape* getSvxShape();
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ class SVXCORE_DLLPUBLIC SdrObjGroup final : public SdrObject, public SdrObjList
|
||||
{
|
||||
public:
|
||||
// Basic DiagramHelper support
|
||||
virtual bool isDiagram() const override;
|
||||
virtual const std::shared_ptr< svx::diagram::IDiagramHelper >& getDiagramHelper() const override;
|
||||
|
||||
private:
|
||||
@@ -66,7 +67,6 @@ public:
|
||||
virtual void handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage) override;
|
||||
|
||||
virtual SdrObjList* GetSubList() const override;
|
||||
virtual void SetGrabBagItem(const css::uno::Any& rVal) override;
|
||||
|
||||
virtual const tools::Rectangle& GetCurrentBoundRect() const override;
|
||||
virtual const tools::Rectangle& GetSnapRect() const override;
|
||||
|
||||
@@ -385,6 +385,7 @@ class XFillGradientItem;
|
||||
|
||||
// CAUTION! Range <250 .. 250> used by EditEngine (!)
|
||||
|
||||
#define SID_DIAGRAM_TO_GROUP ( SID_SVX_START + 252 )
|
||||
#define SID_DRAW_TEXT ( SID_SVX_START + 253 )
|
||||
#define SID_DRAW_CAPTION ( SID_SVX_START + 254 )
|
||||
#define SID_DRAW_SELECT ( SID_SVX_START + 255 )
|
||||
|
||||
@@ -7915,6 +7915,11 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8
|
||||
<value xml:lang="en-US">Regenerate Diagram</value>
|
||||
</prop>
|
||||
</node>
|
||||
<node oor:name=".uno:DiagramToGroup" oor:op="replace">
|
||||
<prop oor:name="Label" oor:type="xs:string">
|
||||
<value xml:lang="en-US">Convert Diagram to Group Object</value>
|
||||
</prop>
|
||||
</node>
|
||||
<node oor:name=".uno:EditDiagram" oor:op="replace">
|
||||
<prop oor:name="Label" oor:type="xs:string">
|
||||
<value xml:lang="en-US">Edit Diagram</value>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <oox/ppt/pptimport.hxx>
|
||||
#include <drawingml/fillproperties.hxx>
|
||||
#include <svx/svdmodel.hxx>
|
||||
#include <svx/svdoutl.hxx>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <oox/drawingml/themefragmenthandler.hxx>
|
||||
#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
|
||||
@@ -233,6 +234,26 @@ void AdvancedDiagramHelper::applyDiagramDataState(const svx::diagram::DiagramDat
|
||||
mpDiagramPtr->getData()->applyDiagramDataState(rState);
|
||||
}
|
||||
|
||||
void AdvancedDiagramHelper::TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl)
|
||||
{
|
||||
if(!mpDiagramPtr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// try text change for model part in DiagramData
|
||||
const bool bChanged(mpDiagramPtr->getData()->TextInformationChange(rDiagramDataModelID, rOutl));
|
||||
|
||||
if(bChanged && nullptr != mpAssociatedSdrObjGroup)
|
||||
{
|
||||
// if change was done, reset GrabBagItem to delete buffered DiagramData which is no longer valid
|
||||
mpAssociatedSdrObjGroup->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>()));
|
||||
|
||||
// also set self to modified to get correct exports
|
||||
setModified();
|
||||
}
|
||||
}
|
||||
|
||||
void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape)
|
||||
{
|
||||
if(!mpDiagramPtr)
|
||||
@@ -247,7 +268,8 @@ void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Sha
|
||||
// secure that data at the Diagram ModelData by copying.
|
||||
mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport(rRootShape);
|
||||
|
||||
anchorToSdrObjGroup(rTarget);
|
||||
// initialize connection to GroupObject
|
||||
connectToSdrObjGroup(rTarget);
|
||||
}
|
||||
|
||||
const std::shared_ptr< ::oox::drawingml::Theme >& AdvancedDiagramHelper::getOrCreateThemePtr(
|
||||
|
||||
@@ -82,6 +82,9 @@ public:
|
||||
void doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape);
|
||||
const std::shared_ptr< ::oox::drawingml::Theme >& getOrCreateThemePtr(
|
||||
const rtl::Reference< oox::shape::ShapeFilterBase>& rxFilter ) const;
|
||||
|
||||
// react on changes to objects identified by DiagramDataModelID, returns true if a change was done
|
||||
virtual void TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1435,6 +1435,24 @@ Reference< XShape > const & Shape::createAndInsert(
|
||||
|
||||
ActionLockGuard const alg(mxShape);
|
||||
|
||||
if (!getDiagramDataModelID().isEmpty())
|
||||
{
|
||||
SdrObject* pShape(SdrObject::getSdrObjectFromXShape(mxShape));
|
||||
|
||||
if (nullptr != pShape)
|
||||
{
|
||||
// check if we have a DiagramHelper
|
||||
std::shared_ptr< svx::diagram::IDiagramHelper > pIDiagramHelper(
|
||||
pShape->getDiagramHelperFromDiagramOrMember());
|
||||
|
||||
if (pIDiagramHelper)
|
||||
{
|
||||
// only needed when DiagramHelper exists
|
||||
pShape->setDiagramDataModelID(getDiagramDataModelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape
|
||||
if ( bClearText )
|
||||
{
|
||||
|
||||
@@ -112,7 +112,14 @@ ContextHandlerRef PPTShapeGroupContext::onCreateContext( sal_Int32 aElementToken
|
||||
{
|
||||
pShape->getFillProperties().moFillType = XML_noFill;
|
||||
}
|
||||
pShape->setModelId(rAttribs.getStringDefaulted( XML_modelId ));
|
||||
const OUString aModelID(rAttribs.getStringDefaulted( XML_modelId ));
|
||||
pShape->setModelId(aModelID);
|
||||
|
||||
// also set DataModelID to have these also available for the imported
|
||||
// replacement visualization. This is key to allow changes to
|
||||
// DiagramHelper model changes
|
||||
pShape->setDiagramDataModelID(aModelID);
|
||||
|
||||
return new PPTShapeContext( *this, mpSlidePersistPtr, mpGroupShapePtr, pShape );
|
||||
}
|
||||
case PPT_TOKEN( pic ): // CT_Picture
|
||||
|
||||
+3
-2
@@ -136,8 +136,9 @@ interface TableDraw
|
||||
SID_UNGROUP [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState; ]
|
||||
SID_ENTER_GROUP [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState; ]
|
||||
SID_LEAVE_GROUP [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState; ]
|
||||
SID_REGENERATE_DIAGRAM [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState ]
|
||||
SID_EDIT_DIAGRAM [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState ]
|
||||
SID_REGENERATE_DIAGRAM [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState; ]
|
||||
SID_DIAGRAM_TO_GROUP [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState; ]
|
||||
SID_EDIT_DIAGRAM [ ExecMethod = ExecDrawFunc; StateMethod = GetDrawFuncState; ]
|
||||
// !!! special
|
||||
SID_DELETE [ExecMethod = ExecDrawFunc ;StateMethod = GetDrawFuncState; ]
|
||||
|
||||
|
||||
@@ -284,6 +284,7 @@ void ScDrawShell::GetDrawFuncState( SfxItemSet& rSet ) // disable functions
|
||||
if (!pObj->isDiagram())
|
||||
{
|
||||
rSet.DisableItem( SID_REGENERATE_DIAGRAM );
|
||||
rSet.DisableItem( SID_DIAGRAM_TO_GROUP );
|
||||
rSet.DisableItem( SID_EDIT_DIAGRAM );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +276,7 @@ void ScDrawShell::ExecDrawFunc( SfxRequest& rReq )
|
||||
break;
|
||||
|
||||
case SID_REGENERATE_DIAGRAM:
|
||||
case SID_DIAGRAM_TO_GROUP:
|
||||
case SID_EDIT_DIAGRAM:
|
||||
{
|
||||
const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
|
||||
@@ -293,7 +294,7 @@ void ScDrawShell::ExecDrawFunc( SfxRequest& rReq )
|
||||
pObj->getDiagramHelper()->reLayout(*static_cast<SdrObjGroup*>(pObj));
|
||||
pView->MarkObj(pObj, pView->GetSdrPageView());
|
||||
}
|
||||
else // SID_EDIT_DIAGRAM
|
||||
else if (SID_EDIT_DIAGRAM == nSlotId)
|
||||
{
|
||||
VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
|
||||
vcl::Window* pWin = rViewData.GetActiveWin();
|
||||
@@ -307,6 +308,12 @@ void ScDrawShell::ExecDrawFunc( SfxRequest& rReq )
|
||||
}
|
||||
);
|
||||
}
|
||||
else // SID_DIAGRAM_TO_GROUP
|
||||
{
|
||||
pView->UnmarkAll();
|
||||
pObj->getDiagramHelper()->disconnectFromSdrObjGroup();
|
||||
pView->MarkObj(pObj, pView->GetSdrPageView());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <svx/svdomedia.hxx>
|
||||
#include <svx/svdotable.hxx>
|
||||
#include <svx/svdpage.hxx>
|
||||
#include <svx/svdogrp.hxx>
|
||||
#include <svx/diagram/IDiagramHelper.hxx>
|
||||
#include <docmodel/uno/UnoGradientTools.hxx>
|
||||
|
||||
#include <com/sun/star/animations/TransitionType.hpp>
|
||||
@@ -1595,12 +1597,13 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testSmartartRotation2)
|
||||
createSdImpressDoc("pptx/smartart-rotation2.pptx");
|
||||
|
||||
// clear SmartArt data to check how group shapes with double-rotated children are exported, not smartart
|
||||
// NOTE: Resetting the GrabBag data is a *very* indirect way to reset the SmartArt functionality.
|
||||
// Since this worked before and there is not (yet?) a better way to do it using UNO API, I added
|
||||
// code to support this for now
|
||||
uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
|
||||
uno::Sequence<beans::PropertyValue> aInteropGrabBag;
|
||||
xShape->setPropertyValue(u"InteropGrabBag"_ustr, uno::Any(aInteropGrabBag));
|
||||
// NOTE: Now we have a slot (comphelper::dispatchCommand(u".uno:DiagramToGroup"_ustr, {})) and method
|
||||
// at IDiagramHelper to do that, adapted removal of Diagram/SmartArt functionality
|
||||
uno::Reference<drawing::XDrawPage> xPage(getPage(0));
|
||||
uno::Reference<drawing::XShape> xShape(xPage->getByIndex(0), uno::UNO_QUERY);
|
||||
SdrObjGroup* pSdrObjGroup
|
||||
= dynamic_cast<SdrObjGroup*>(SdrObject::getSdrObjectFromXShape(xShape));
|
||||
pSdrObjGroup->getDiagramHelper()->disconnectFromSdrObjGroup();
|
||||
|
||||
save(TestFilter::PPTX);
|
||||
|
||||
|
||||
@@ -2928,6 +2928,11 @@ interface DrawView
|
||||
ExecMethod = ExecCtrl ;
|
||||
StateMethod = GetMenuState ;
|
||||
]
|
||||
SID_DIAGRAM_TO_GROUP
|
||||
[
|
||||
ExecMethod = ExecCtrl ;
|
||||
StateMethod = GetMenuState ;
|
||||
]
|
||||
SID_EDIT_DIAGRAM
|
||||
[
|
||||
ExecMethod = ExecCtrl ;
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
#include <svx/unoapi.hxx>
|
||||
#include <svx/svdogrp.hxx>
|
||||
#include <svx/ColorSets.hxx>
|
||||
#include <svx/diagram/IDiagramHelper.hxx>
|
||||
#include <sdmod.hxx>
|
||||
#include <sdpage.hxx>
|
||||
#include <unomodel.hxx>
|
||||
@@ -2348,7 +2349,12 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType
|
||||
{
|
||||
SAL_INFO("sd.eppt", "mType: " << mType);
|
||||
const SdrObjGroup* pDiagramCandidate(dynamic_cast<const SdrObjGroup*>(SdrObject::getSdrObjectFromXShape(mXShape)));
|
||||
const bool bIsDiagram(nullptr != pDiagramCandidate && pDiagramCandidate->isDiagram());
|
||||
bool bIsDiagram(nullptr != pDiagramCandidate && pDiagramCandidate->isDiagram());
|
||||
|
||||
// check if it was modified. For now, since we have no ppt export for Diagram,
|
||||
// do not export as Diagram, that would be empty if the GrabBag was deleted
|
||||
if (bIsDiagram && pDiagramCandidate->getDiagramHelper()->isModified())
|
||||
bIsDiagram = false;
|
||||
|
||||
if (bIsDiagram)
|
||||
WriteDiagram(pFS, aDML, mXShape, mnDiagramId++);
|
||||
|
||||
@@ -488,6 +488,7 @@ void DrawViewShell::ExecCtrl(SfxRequest& rReq)
|
||||
break;
|
||||
|
||||
case SID_REGENERATE_DIAGRAM:
|
||||
case SID_DIAGRAM_TO_GROUP:
|
||||
case SID_EDIT_DIAGRAM:
|
||||
{
|
||||
if (1 == rMarkList.GetMarkCount())
|
||||
@@ -497,13 +498,13 @@ void DrawViewShell::ExecCtrl(SfxRequest& rReq)
|
||||
// Support advanced DiagramHelper
|
||||
if(nullptr != pObj && pObj->isDiagram())
|
||||
{
|
||||
if(SID_REGENERATE_DIAGRAM == nSlot)
|
||||
if (SID_REGENERATE_DIAGRAM == nSlot)
|
||||
{
|
||||
mpDrawView->UnmarkAll();
|
||||
pObj->getDiagramHelper()->reLayout(*static_cast<SdrObjGroup*>(pObj));
|
||||
mpDrawView->MarkObj(pObj, mpDrawView->GetSdrPageView());
|
||||
}
|
||||
else // SID_EDIT_DIAGRAM
|
||||
else if (SID_EDIT_DIAGRAM == nSlot)
|
||||
{
|
||||
VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
|
||||
VclPtr<VclAbstractDialog> pDlg = pFact->CreateDiagramDialog(
|
||||
@@ -516,6 +517,12 @@ void DrawViewShell::ExecCtrl(SfxRequest& rReq)
|
||||
}
|
||||
);
|
||||
}
|
||||
else // SID_DIAGRAM_TO_GROUP
|
||||
{
|
||||
mpDrawView->UnmarkAll();
|
||||
pObj->getDiagramHelper()->disconnectFromSdrObjGroup();
|
||||
mpDrawView->MarkObj(pObj, mpDrawView->GetSdrPageView());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@ void DrawViewShell::GetMenuStateSel( SfxItemSet &rSet )
|
||||
if(!pSdrObjGroup || !pSdrObjGroup->isDiagram())
|
||||
{
|
||||
rSet.DisableItem( SID_REGENERATE_DIAGRAM );
|
||||
rSet.DisableItem( SID_DIAGRAM_TO_GROUP );
|
||||
rSet.DisableItem( SID_EDIT_DIAGRAM );
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
+30
-27
@@ -237,46 +237,49 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testHandlePathObjScale)
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(SvdrawTest, testTextEditEmptyGrabBag)
|
||||
{
|
||||
// Given a document with a groupshape, which has 2 children.
|
||||
loadFromURL(u"private:factory/sdraw"_ustr);
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<drawing::XShape> xRect1(
|
||||
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr), uno::UNO_QUERY);
|
||||
xRect1->setPosition(awt::Point(1000, 1000));
|
||||
xRect1->setSize(awt::Size(10000, 10000));
|
||||
uno::Reference<drawing::XShape> xRect2(
|
||||
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr), uno::UNO_QUERY);
|
||||
xRect2->setPosition(awt::Point(1000, 1000));
|
||||
xRect2->setSize(awt::Size(10000, 10000));
|
||||
uno::Reference<drawing::XShapes> xGroup(
|
||||
xFactory->createInstance(u"com.sun.star.drawing.GroupShape"_ustr), uno::UNO_QUERY);
|
||||
// Adapted this test to work with a *real* SmartArt/Diagram (SA). The former
|
||||
// test created a 'fake' one and checked if on TextEdit The GrabBag gets deleted.
|
||||
// The updated SA text edit *tries* to keep the SA Data (in IDiagramHelper
|
||||
// attached to SdrObjGroup). It clears the GrabBag, but only if a 'real' SA
|
||||
// exists.
|
||||
// Thus I added a bugdoc for that task which contains a 'real' SA to test
|
||||
// if GrabBag gets cleared on change of the SA model data.
|
||||
|
||||
// load document
|
||||
loadFromFile(u"tdf132368.pptx");
|
||||
|
||||
// get DrawPage
|
||||
uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
|
||||
uno::UNO_QUERY);
|
||||
uno::Reference<drawing::XShape> xGroupShape(xGroup, uno::UNO_QUERY);
|
||||
xDrawPage->add(xGroupShape);
|
||||
xGroup->add(xRect1);
|
||||
xGroup->add(xRect2);
|
||||
uno::Reference<text::XTextRange> xRect2Text(xRect2, uno::UNO_QUERY);
|
||||
xRect2Text->setString(u"x"_ustr);
|
||||
uno::Sequence<beans::PropertyValue> aGrabBag = {
|
||||
comphelper::makePropertyValue(u"OOXLayout"_ustr, true),
|
||||
};
|
||||
uno::Reference<beans::XPropertySet> xGroupProps(xGroup, uno::UNO_QUERY);
|
||||
xGroupProps->setPropertyValue(u"InteropGrabBag"_ustr, uno::Any(aGrabBag));
|
||||
|
||||
// When editing the shape text of the 2nd rectangle (insert a char at the start).
|
||||
// get 1st object, this is the SA. Get as GroupObject
|
||||
uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
|
||||
uno::Reference<drawing::XShapes> xGroupShape(xShape, uno::UNO_QUERY);
|
||||
|
||||
// get the GrabBag. After import is *has* to be set, check that
|
||||
uno::Sequence<beans::PropertyValue> aGrabBag;
|
||||
uno::Reference<beans::XPropertySet> xGroupProps(xGroupShape, uno::UNO_QUERY);
|
||||
xGroupProps->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag;
|
||||
CPPUNIT_ASSERT(aGrabBag.hasElements());
|
||||
|
||||
// get the 1st text shape (containing 'A'). There is a BGShape and an Arrow
|
||||
// in indices before
|
||||
uno::Reference<drawing::XShape> xShapeA(xGroupShape->getByIndex(2), uno::UNO_QUERY);
|
||||
|
||||
// TextEdit: insert a char at the start
|
||||
SfxViewShell* pViewShell = SfxViewShell::Current();
|
||||
CPPUNIT_ASSERT(pViewShell);
|
||||
SdrView* pSdrView = pViewShell->GetDrawView();
|
||||
SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xRect2);
|
||||
SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xShapeA);
|
||||
pSdrView->SdrBeginTextEdit(pObject);
|
||||
EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
|
||||
rEditView.InsertText(u"y"_ustr);
|
||||
rEditView.InsertText(u"X"_ustr);
|
||||
pSdrView->SdrEndTextEdit();
|
||||
|
||||
// Then make sure that grab-bag is empty to avoid losing the new text.
|
||||
xGroupProps->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag;
|
||||
|
||||
// Without the accompanying fix in place, this test would have failed with:
|
||||
// assertion failed
|
||||
// - Expression: !aGrabBag.hasElements()
|
||||
|
||||
@@ -2660,6 +2660,23 @@ SfxVoidItem RegenerateDiagram SID_REGENERATE_DIAGRAM
|
||||
GroupId = SfxGroupId::Modify;
|
||||
]
|
||||
|
||||
SfxVoidItem DiagramToGroup SID_DIAGRAM_TO_GROUP
|
||||
()
|
||||
[
|
||||
AutoUpdate = FALSE,
|
||||
FastCall = FALSE,
|
||||
ReadOnlyDoc = FALSE,
|
||||
Toggle = FALSE,
|
||||
Container = FALSE,
|
||||
RecordAbsolute = FALSE,
|
||||
RecordPerSet;
|
||||
|
||||
AccelConfig = TRUE,
|
||||
MenuConfig = TRUE,
|
||||
ToolBoxConfig = TRUE,
|
||||
GroupId = SfxGroupId::Modify;
|
||||
]
|
||||
|
||||
SfxVoidItem EditDiagram SID_EDIT_DIAGRAM
|
||||
()
|
||||
[
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <svx/strings.hrc>
|
||||
#include <svx/dialmgr.hxx>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace {
|
||||
|
||||
// helper to create the geometry for a rounded polygon, maybe
|
||||
@@ -408,13 +410,35 @@ IDiagramHelper::IDiagramHelper(bool bSelfCreated)
|
||||
, mbUseDiagramModelData(true)
|
||||
, mbForceThemePtrRecreation(false)
|
||||
, mbSelfCreated(bSelfCreated)
|
||||
, mbModified(false)
|
||||
, mpAssociatedSdrObjGroup(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
IDiagramHelper::~IDiagramHelper() {}
|
||||
|
||||
void IDiagramHelper::anchorToSdrObjGroup(SdrObjGroup& rTarget)
|
||||
void IDiagramHelper::disconnectFromSdrObjGroup()
|
||||
{
|
||||
if (nullptr != mpAssociatedSdrObjGroup)
|
||||
{
|
||||
// if change was done, reset GrabBagItem to delete buffered DiagramData which is no longer valid
|
||||
mpAssociatedSdrObjGroup->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>()));
|
||||
mpAssociatedSdrObjGroup->mp_DiagramHelper.reset();
|
||||
mpAssociatedSdrObjGroup = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void IDiagramHelper::connectToSdrObjGroup(SdrObjGroup& rTarget)
|
||||
{
|
||||
if (mpAssociatedSdrObjGroup == &rTarget && rTarget.mp_DiagramHelper.get() == this)
|
||||
// connection already established
|
||||
return;
|
||||
|
||||
// ensure unconnect if already connected
|
||||
disconnectFromSdrObjGroup();
|
||||
|
||||
// connect to target
|
||||
mpAssociatedSdrObjGroup = &rTarget;
|
||||
rTarget.mp_DiagramHelper.reset(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <fstream>
|
||||
|
||||
#include <svx/diagram/datamodel.hxx>
|
||||
#include <svx/svdoutl.hxx>
|
||||
#include <comphelper/xmltools.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <utility>
|
||||
@@ -493,6 +494,52 @@ void DiagramData::buildDiagramDataModel(bool /*bClearOoxShapes*/)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DiagramData::TextInformationChange(const OUString& rDiagramDataModelID, Outliner& rOutl)
|
||||
{
|
||||
// try to get the Point fo rthe associated ID
|
||||
const auto pDataNode = maPointNameMap.find(rDiagramDataModelID);
|
||||
if (pDataNode == maPointNameMap.end())
|
||||
return false;
|
||||
|
||||
// use PresentationAssociationId to get to the text containing Point
|
||||
const OUString& rPresentationAssociationId(pDataNode->second->msPresentationAssociationId);
|
||||
if (rPresentationAssociationId.isEmpty())
|
||||
return false;
|
||||
|
||||
// try to get the text-associated Point
|
||||
const auto pTextNode = maPointNameMap.find(rPresentationAssociationId);
|
||||
if (pTextNode == maPointNameMap.end())
|
||||
return false;
|
||||
|
||||
// check if it has a text node - it should
|
||||
if (!pTextNode->second->msTextBody)
|
||||
return false;
|
||||
|
||||
// access TextBody
|
||||
TextBodyPtr pTextBody(pTextNode->second->msTextBody);
|
||||
|
||||
// now for outliner/source: Do we have data at all?
|
||||
if(0 == rOutl.GetParagraphCount())
|
||||
return false;
|
||||
|
||||
// if yes, use 1st paragraph (for now)
|
||||
const Paragraph* pPara(rOutl.GetParagraph(0));
|
||||
if (nullptr == pPara)
|
||||
return false;
|
||||
|
||||
// extract 1st para as text
|
||||
const OUString aCurrentText(rOutl.GetText(pPara));
|
||||
|
||||
// check if text differs at all
|
||||
if (aCurrentText == pTextBody->msText)
|
||||
return false;
|
||||
|
||||
// do change and return true (change was done)
|
||||
// NOTE: for now only rough text change, attributes are missing and will need to be added
|
||||
pTextBody->msText = aCurrentText;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#include <svx/sdsxyitm.hxx>
|
||||
#include <svx/sdtmfitm.hxx>
|
||||
#include <svx/sdasitm.hxx>
|
||||
#include <svx/diagram/IDiagramHelper.hxx>
|
||||
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||
@@ -2608,8 +2609,20 @@ void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, tools
|
||||
if (pPaperMax!=nullptr) *pPaperMax=aPaperMax;
|
||||
if (pViewInit!=nullptr) *pViewInit=aViewInit;
|
||||
}
|
||||
|
||||
void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl )
|
||||
{
|
||||
if (!getDiagramDataModelID().isEmpty())
|
||||
{
|
||||
std::shared_ptr< svx::diagram::IDiagramHelper > pIDiagramHelper(getDiagramHelperFromDiagramOrMember());
|
||||
|
||||
if (pIDiagramHelper)
|
||||
{
|
||||
// try to do the needed changes at the associated DiagramData model
|
||||
pIDiagramHelper->TextInformationChange(getDiagramDataModelID(), rOutl);
|
||||
}
|
||||
}
|
||||
|
||||
SdrTextObj::EndTextEdit( rOutl );
|
||||
InvalidateRenderGeometry();
|
||||
}
|
||||
|
||||
@@ -201,12 +201,31 @@ struct SdrObject::Impl
|
||||
meRelativeHeightRelation(text::RelOrientation::PAGE_FRAME) {}
|
||||
};
|
||||
|
||||
bool SdrObject::isDiagram() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::shared_ptr< svx::diagram::IDiagramHelper >& SdrObject::getDiagramHelper() const
|
||||
{
|
||||
static std::shared_ptr< svx::diagram::IDiagramHelper > aEmpty;
|
||||
return aEmpty;
|
||||
}
|
||||
|
||||
const std::shared_ptr< svx::diagram::IDiagramHelper >& SdrObject::getDiagramHelperFromDiagramOrMember() const
|
||||
{
|
||||
SdrObject* pCurrent(const_cast<SdrObject*>(this));
|
||||
|
||||
while (pCurrent)
|
||||
{
|
||||
if (pCurrent->isDiagram())
|
||||
return pCurrent->getDiagramHelper();
|
||||
pCurrent = pCurrent->getParentSdrObjectFromSdrObject();
|
||||
}
|
||||
|
||||
return getDiagramHelper();
|
||||
}
|
||||
|
||||
// BaseProperties section
|
||||
|
||||
sdr::properties::BaseProperties& SdrObject::GetProperties() const
|
||||
@@ -347,6 +366,8 @@ SdrObject::SdrObject(SdrModel& rSdrModel)
|
||||
, mnLayerID(0)
|
||||
, mpSvxShape( nullptr )
|
||||
, mbDoNotInsertIntoPageAutomatically(false)
|
||||
, msHyperlink()
|
||||
, msDiagramDataModelID()
|
||||
{
|
||||
m_bVirtObj =false;
|
||||
m_bSnapRectDirty =true;
|
||||
@@ -383,6 +404,8 @@ SdrObject::SdrObject(SdrModel& rSdrModel, SdrObject const & rSource)
|
||||
, mnLayerID(0)
|
||||
, mpSvxShape( nullptr )
|
||||
, mbDoNotInsertIntoPageAutomatically(false)
|
||||
, msHyperlink()
|
||||
, msDiagramDataModelID()
|
||||
{
|
||||
m_bVirtObj =false;
|
||||
m_bSnapRectDirty =true;
|
||||
@@ -1855,19 +1878,6 @@ void SdrObject::SetOutlinerParaObject(std::optional<OutlinerParaObject> pTextObj
|
||||
if (GetCurrentBoundRect()!=aBoundRect0) {
|
||||
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
|
||||
}
|
||||
|
||||
if (!getSdrModelFromSdrObject().IsUndoEnabled())
|
||||
return;
|
||||
|
||||
// Don't do this during import.
|
||||
if (SdrObject* pTopGroupObj = getParentSdrObjectFromSdrObject())
|
||||
{
|
||||
while (SdrObject* pParent = pTopGroupObj->getParentSdrObjectFromSdrObject())
|
||||
pTopGroupObj = pParent;
|
||||
// A shape was modified, which is in a group shape. Empty the group shape's grab-bag,
|
||||
// which potentially contains the old text of the shapes in case of diagrams.
|
||||
pTopGroupObj->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>()));
|
||||
}
|
||||
}
|
||||
|
||||
void SdrObject::NbcSetOutlinerParaObject(std::optional<OutlinerParaObject> /*pTextObject*/, bool /*bAdjustTextFrameWidthAndHeight = true*/)
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
#include <vcl/canvastools.hxx>
|
||||
#include <svx/diagram/IDiagramHelper.hxx>
|
||||
|
||||
bool SdrObjGroup::isDiagram() const
|
||||
{
|
||||
return bool(mp_DiagramHelper);
|
||||
}
|
||||
|
||||
const std::shared_ptr< svx::diagram::IDiagramHelper >& SdrObjGroup::getDiagramHelper() const
|
||||
{
|
||||
return mp_DiagramHelper;
|
||||
@@ -204,39 +209,6 @@ SdrObjList* SdrObjGroup::GetSubList() const
|
||||
{
|
||||
return const_cast< SdrObjGroup* >(this);
|
||||
}
|
||||
|
||||
static bool containsOOXData(const css::uno::Any& rVal)
|
||||
{
|
||||
const css::uno::Sequence<css::beans::PropertyValue> propList(rVal.get< css::uno::Sequence<css::beans::PropertyValue> >());
|
||||
for (const auto& rProp : propList)
|
||||
{
|
||||
if(rProp.Name.startsWith("OOX"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SdrObjGroup::SetGrabBagItem(const css::uno::Any& rVal)
|
||||
{
|
||||
// detect if the intention is to disable Diagram functionality
|
||||
if(isDiagram() && !containsOOXData(rVal))
|
||||
{
|
||||
css::uno::Any aOld;
|
||||
GetGrabBagItem(aOld);
|
||||
|
||||
if(containsOOXData(aOld))
|
||||
{
|
||||
mp_DiagramHelper.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// call parent
|
||||
SdrObject::SetGrabBagItem(rVal);
|
||||
}
|
||||
|
||||
const tools::Rectangle& SdrObjGroup::GetCurrentBoundRect() const
|
||||
{
|
||||
// <aOutRect> has to contain the bounding rectangle
|
||||
|
||||
@@ -67,6 +67,13 @@ interface BaseTextDrawBase
|
||||
StateMethod = GetState ;
|
||||
]
|
||||
|
||||
SID_DIAGRAM_TO_GROUP
|
||||
[
|
||||
AutoUpdate = TRUE ,
|
||||
ExecMethod = Execute ;
|
||||
StateMethod = GetState ;
|
||||
]
|
||||
|
||||
SID_EDIT_DIAGRAM
|
||||
[
|
||||
AutoUpdate = TRUE ,
|
||||
|
||||
@@ -460,6 +460,7 @@ void SwDrawBaseShell::Execute(SfxRequest& rReq)
|
||||
break;
|
||||
|
||||
case SID_REGENERATE_DIAGRAM:
|
||||
case SID_DIAGRAM_TO_GROUP:
|
||||
case SID_EDIT_DIAGRAM:
|
||||
{
|
||||
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
||||
@@ -471,13 +472,13 @@ void SwDrawBaseShell::Execute(SfxRequest& rReq)
|
||||
// Support advanced DiagramHelper
|
||||
if(nullptr != pObj && pObj->isDiagram())
|
||||
{
|
||||
if(SID_REGENERATE_DIAGRAM == nSlotId)
|
||||
if (SID_REGENERATE_DIAGRAM == nSlotId)
|
||||
{
|
||||
pSdrView->UnmarkAll();
|
||||
pObj->getDiagramHelper()->reLayout(*static_cast<SdrObjGroup*>(pObj));
|
||||
pSdrView->MarkObj(pObj, pSdrView->GetSdrPageView());
|
||||
}
|
||||
else // SID_EDIT_DIAGRAM
|
||||
else if(SID_EDIT_DIAGRAM == nSlotId)
|
||||
{
|
||||
VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
|
||||
VclPtr<VclAbstractDialog> pDlg = pFact->CreateDiagramDialog(
|
||||
@@ -490,6 +491,12 @@ void SwDrawBaseShell::Execute(SfxRequest& rReq)
|
||||
}
|
||||
);
|
||||
}
|
||||
else // SID_DIAGRAM_TO_GROUP
|
||||
{
|
||||
pSdrView->UnmarkAll();
|
||||
pObj->getDiagramHelper()->disconnectFromSdrObjGroup();
|
||||
pSdrView->MarkObj(pObj, pSdrView->GetSdrPageView());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user