Advanced Diagram support: Secure properties at Diagram ModelData

Additionally to the Text/Attributes already saved/secured after
Diagram import, secure more data that is part of the Diagram
ModelData. This is about attributes (e.g. FillStyle/LineStyle,
TextAttributes, ...) in UNO API formt that will be secured/
attached to the Diagram ModelData in it's
svx::diagram::Point structure.
This is done for all those entries for which a XShape will/
would be incarnated, thus associated to entries that will
get a visualization, including the BackgroundObject.
From that data, at re-creation time, the attributes can be
re-applied to the re-created XShape(s), also after changes
to the Diagram Model Data (e.g. Add/Remove).
This is - besides the already added securing of the Style/
Theme - a 2nd method for lossless re-creation. For the
BackgroundObject - if it has FillStyles - it is even the
only method to secure that data and thus necessary for that
case. The selection of atributes that gets secured is minimal
for now and may/need to be extended for existing cases
accordingly.

Change-Id: Ie9b72b9b9135113cf858d57fe6cd8622d736c4a4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132976
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
This commit is contained in:
Armin Le Grand (Allotropia)
2022-04-14 11:02:19 +02:00
committed by Armin Le Grand
parent 16bbd139d6
commit edadfb564f
6 changed files with 270 additions and 24 deletions
+16 -2
View File
@@ -29,8 +29,8 @@
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/xml/dom/XDocument.hpp>
#include <com/sun/star/drawing/XShape.hpp>
namespace svx::diagram {
@@ -83,11 +83,21 @@ struct SVXCORE_DLLPUBLIC TextBody
OUString msText;
// attributes from TextBody::getTextProperties()
css::uno::Sequence< css::beans::PropertyValue > maTextProps;
std::vector< std::pair< OUString, css::uno::Any >> maTextProps;
};
typedef std::shared_ptr< TextBody > TextBodyPtr;
/** Styles for a Point (FillStyle/LineStyle/...)
*/
struct SVXCORE_DLLPUBLIC PointStyle
{
// attributes (LineStyle/FillStyle/...)
std::vector< std::pair< OUString, css::uno::Any >> maProperties;
};
typedef std::shared_ptr< PointStyle > PointStylePtr;
/** A point
*/
struct SVXCORE_DLLPUBLIC Point
@@ -95,6 +105,7 @@ struct SVXCORE_DLLPUBLIC Point
Point();
TextBodyPtr msTextBody;
PointStylePtr msPointStylePtr;
OUString msCnxId;
OUString msModelId;
@@ -136,6 +147,9 @@ struct SVXCORE_DLLPUBLIC Point
bool mbCustomVerticalFlip;
bool mbCustomText;
bool mbIsPlaceholder;
void securePropertiesFromXShape(const css::uno::Reference< css::drawing::XShape >& rXShape);
void restorePropertiesToXShape(const css::uno::Reference< css::drawing::XShape >& rXShape) const;
};
typedef std::vector< Point > Points;
+9 -4
View File
@@ -68,15 +68,15 @@ void DiagramData::restoreDataFromModelToShapeAfterReCreation(const svx::diagram:
pTextRun->getText() = rPoint.msTextBody->msText;
aNewTextBody->addParagraph().addRun(pTextRun);
if(rPoint.msTextBody->maTextProps.hasElements())
if(!rPoint.msTextBody->maTextProps.empty())
{
oox::PropertyMap& rTargetMap(aNewTextBody->getTextProperties().maPropertyMap);
for (auto const& prop : rPoint.msTextBody->maTextProps)
{
sal_Int32 nPropId(oox::PropertyMap::getPropertyId(prop.Name));
const sal_Int32 nPropId(oox::PropertyMap::getPropertyId(prop.first));
if(nPropId > 0)
rTargetMap.setAnyProperty(nPropId, prop.Value);
rTargetMap.setAnyProperty(nPropId, prop.second);
}
}
}
@@ -99,7 +99,12 @@ void DiagramData::secureDataFromShapeToModelAfterDiagramImport()
{
point.msTextBody = std::make_shared<svx::diagram::TextBody>();
point.msTextBody->msText = pShapeCandidate->getTextBody()->toString();
point.msTextBody->maTextProps = pShapeCandidate->getTextBody()->getTextProperties().maPropertyMap.makePropertyValueSequence();
const uno::Sequence< beans::PropertyValue > aTextProps(
pShapeCandidate->getTextBody()->getTextProperties().maPropertyMap.makePropertyValueSequence());
for (auto const& prop : aTextProps)
point.msTextBody->maTextProps.push_back(std::pair(prop.Name, prop.Value));
}
// At this place a mechanism to find missing data should be added:
+34 -5
View File
@@ -103,6 +103,40 @@ static void removeUnneededGroupShapes(const ShapePtr& pShape)
}
}
void DiagramLayout::secureDataFromXShapeToModelAfterDiagramImport()
{
// maPresPointShapeMap types: < const svx::diagram::Point*, ShapePtr >
for (const auto& pEntry : maPresPointShapeMap)
{
if(nullptr != pEntry.first && pEntry.second)
{
const css::uno::Reference< css::drawing::XShape >& rXShape(pEntry.second->getXShape());
if(rXShape)
{
const_cast<svx::diagram::Point*>(pEntry.first)->securePropertiesFromXShape(rXShape);
}
}
}
}
void DiagramLayout::restoreDataFromModelToXShapeAfterDiagramReCreate()
{
// maPresPointShapeMap types: < const svx::diagram::Point*, ShapePtr >
for (const auto& pEntry : maPresPointShapeMap)
{
if(nullptr != pEntry.first && pEntry.second)
{
const css::uno::Reference< css::drawing::XShape >& rXShape(pEntry.second->getXShape());
if(rXShape)
{
pEntry.first->restorePropertiesToXShape(rXShape);
}
}
}
}
void Diagram::addTo( const ShapePtr & pParentShape )
{
if (pParentShape->getSize().Width == 0 || pParentShape->getSize().Height == 0)
@@ -403,11 +437,6 @@ void loadDiagram( ShapePtr const & pShape,
}
}
// After Diagram import, parts of the Diagram ModelData is at the
// oox::drawingml::Shape. Since these objects are temporary helpers,
// secure that data at the Diagram ModelData by copying.
pData->secureDataFromShapeToModelAfterDiagramImport();
// collect data, init maps
// for Diagram import, do - for now - NOT clear all oox::drawingml::Shape
pData->buildDiagramDataModel(false);
+4
View File
@@ -79,6 +79,10 @@ public:
PresPointShapeMap & getPresPointShapeMap()
{ return maPresPointShapeMap; }
// get/set data between Diagram DataModel and oox::drawingml::Shape
void secureDataFromXShapeToModelAfterDiagramImport();
void restoreDataFromModelToXShapeAfterDiagramReCreate();
private:
Diagram& mrDgm;
OUString msDefStyle;
+41 -8
View File
@@ -103,7 +103,9 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget)
// set oox::Theme at Filter. All LineStyle/FillStyle/Colors/Attributes
// will be taken from there
xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter));
static bool bUseDiagramThemeData(false);
if(bUseDiagramThemeData)
xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter));
css::uno::Reference< css::lang::XComponent > aComponentModel( rUnoModel, uno::UNO_QUERY );
xFilter->setTargetDocument(aComponentModel);
@@ -126,11 +128,16 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget)
pShapePtr->getFillProperties());
}
// Re-apply remembered geometry
rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon);
// sync FontHeights
mpDiagramPtr->syncDiagramFontHeights();
// re-apply secured data from ModelData
static bool bUseDiagramModelData(true);
if(bUseDiagramModelData)
mpDiagramPtr->getLayout()->restoreDataFromModelToXShapeAfterDiagramReCreate();
// Re-apply remembered geometry
rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon);
}
OUString AdvancedDiagramHelper::getString() const
@@ -155,22 +162,42 @@ std::vector<std::pair<OUString, OUString>> AdvancedDiagramHelper::getChildren(co
OUString AdvancedDiagramHelper::addNode(const OUString& rText)
{
OUString aRetval;
if(hasDiagramData())
{
return mpDiagramPtr->getData()->addNode(rText);
aRetval = mpDiagramPtr->getData()->addNode(rText);
// reset temporary buffered ModelData association lists & rebuild them
// and the Diagram DataModel
mpDiagramPtr->getData()->buildDiagramDataModel(true);
// also reset temporary buffered layout data - that might
// still refer to changed oox::Shape data
mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
}
return OUString();
return aRetval;
}
bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId)
{
bool bRetval(false);
if(hasDiagramData())
{
return mpDiagramPtr->getData()->removeNode(rNodeId);
bRetval = mpDiagramPtr->getData()->removeNode(rNodeId);
// reset temporary buffered ModelData association lists & rebuild them
// and the Diagram DataModel
mpDiagramPtr->getData()->buildDiagramDataModel(true);
// also reset temporary buffered layout data - that might
// still refer to changed oox::Shape data
mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
}
return false;
return bRetval;
}
void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget)
@@ -182,6 +209,12 @@ void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget)
mpDiagramPtr->syncDiagramFontHeights();
// After Diagram import, parts of the Diagram ModelData is at the
// oox::drawingml::Shape. Since these objects are temporary helpers,
// secure that data at the Diagram ModelData by copying.
mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport();
mpDiagramPtr->getLayout()->secureDataFromXShapeToModelAfterDiagramImport();
anchorToSdrObjGroup(rTarget);
}
+166 -5
View File
@@ -23,6 +23,15 @@
#include <svx/diagram/datamodel.hxx>
#include <comphelper/xmltools.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/text/XText.hpp>
#include <editeng/unoprnms.hxx>
#include <sal/log.hxx>
namespace svx::diagram {
@@ -63,6 +72,163 @@ Point::Point()
{
}
static void addProperty(const OUString& rName,
const css::uno::Reference< css::beans::XPropertySetInfo >& xInfo,
std::vector< std::pair< OUString, css::uno::Any >>& rTarget,
const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
{
if(xInfo->hasPropertyByName(rName))
rTarget.push_back(std::pair(OUString(rName), xPropSet->getPropertyValue(rName)));
}
void Point::securePropertiesFromXShape(const css::uno::Reference< css::drawing::XShape >& rXShape)
{
if(!rXShape)
return;
#ifdef DBG_UTIL
// to easier decide which additional properties may/should be preserved,
// create a full list of set properties to browse/decide (in debugger)
const css::uno::Reference< css::beans::XPropertyState > xAllPropStates(rXShape, css::uno::UNO_QUERY);
const css::uno::Reference< css::beans::XPropertySet > xAllPropSet( rXShape, css::uno::UNO_QUERY );
const css::uno::Sequence< css::beans::Property > allSequence(xAllPropSet->getPropertySetInfo()->getProperties());
std::vector< std::pair< OUString, css::uno::Any >> allSetProps;
for (auto& rProp : allSequence)
{
try
{
if (xAllPropStates->getPropertyState(rProp.Name) == css::beans::PropertyState::PropertyState_DIRECT_VALUE)
{
css::uno::Any aValue(xAllPropSet->getPropertyValue(rProp.Name));
if(aValue.hasValue())
allSetProps.push_back(std::pair(rProp.Name, aValue));
}
}
catch (...)
{
}
}
#endif
const css::uno::Reference< css::beans::XPropertySet > xPropSet( rXShape, css::uno::UNO_QUERY );
if(!xPropSet)
return;
const css::uno::Reference< css::lang::XServiceInfo > xServiceInfo( rXShape, css::uno::UNO_QUERY );
if(!xServiceInfo)
return;
const css::uno::Reference< css::beans::XPropertySetInfo > xInfo(xPropSet->getPropertySetInfo());
if (!xInfo.is())
return;
if(!msPointStylePtr)
msPointStylePtr = std::make_shared< svx::diagram::PointStyle >();
// shortcut to target
std::vector< std::pair< OUString, css::uno::Any >>& rTarget(msPointStylePtr->maProperties);
// Note: The Text may also be secured here, so it may also be possible to
// secure/store it at PointStyle instead of at TextBody, same maybe evaluated
// for the text attributes - where when securing here the attributes would be
// in our UNO API format already.
// if(xServiceInfo->supportsService("com.sun.star.drawing.Text"))
// {
// css::uno::Reference< css::text::XText > xText(rXShape, css::uno::UNO_QUERY);
// const OUString aText(xText->getString());
//
// if(!aText.isEmpty())
// {
// }
// }
// Add all kinds of properties that are needed to re-create the XShape.
// For now this is a minimal example-selection, it will need to be extended
// over time for all kind of cases/properties
// text properties
if(xServiceInfo->supportsService("com.sun.star.drawing.TextProperties"))
{
addProperty(UNO_NAME_CHAR_COLOR, xInfo, rTarget, xPropSet);
addProperty(UNO_NAME_CHAR_HEIGHT, xInfo, rTarget, xPropSet);
addProperty(UNO_NAME_CHAR_SHADOWED, xInfo, rTarget, xPropSet);
addProperty(UNO_NAME_CHAR_WEIGHT, xInfo, rTarget, xPropSet);
}
// fill properties
if(xServiceInfo->supportsService("com.sun.star.drawing.FillProperties"))
{
css::drawing::FillStyle eFillStyle(css::drawing::FillStyle_NONE);
if (xInfo->hasPropertyByName(UNO_NAME_FILLSTYLE))
xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= eFillStyle;
if(css::drawing::FillStyle_NONE != eFillStyle)
{
addProperty(UNO_NAME_FILLSTYLE, xInfo, rTarget, xPropSet);
switch(eFillStyle)
{
case css::drawing::FillStyle_SOLID:
{
addProperty(UNO_NAME_FILLCOLOR, xInfo, rTarget, xPropSet);
break;
}
default:
case css::drawing::FillStyle_NONE:
case css::drawing::FillStyle_GRADIENT:
case css::drawing::FillStyle_HATCH:
case css::drawing::FillStyle_BITMAP:
break;
}
}
}
// line properties
if(xServiceInfo->supportsService("com.sun.star.drawing.LineProperties"))
{
css::drawing::LineStyle eLineStyle(css::drawing::LineStyle_NONE);
if (xInfo->hasPropertyByName(UNO_NAME_LINESTYLE))
xPropSet->getPropertyValue(UNO_NAME_LINESTYLE) >>= eLineStyle;
if(css::drawing::LineStyle_NONE != eLineStyle)
{
addProperty(UNO_NAME_LINESTYLE, xInfo, rTarget, xPropSet);
addProperty(UNO_NAME_LINECOLOR, xInfo, rTarget, xPropSet);
addProperty(UNO_NAME_LINEWIDTH, xInfo, rTarget, xPropSet);
switch(eLineStyle)
{
case css::drawing::LineStyle_SOLID:
break;
default:
case css::drawing::LineStyle_NONE:
case css::drawing::LineStyle_DASH:
break;
}
}
}
}
void Point::restorePropertiesToXShape(const css::uno::Reference< css::drawing::XShape >& rXShape) const
{
if(!msPointStylePtr)
return;
if(!rXShape)
return;
css::uno::Reference<css::beans::XPropertySet> xPropSet(rXShape, css::uno::UNO_QUERY);
if(!xPropSet)
return;
std::vector< std::pair< OUString, css::uno::Any >>& rSource(msPointStylePtr->maProperties);
for (auto const& prop : rSource)
{
xPropSet->setPropertyValue(prop.first, prop.second);
}
}
DiagramData::DiagramData()
{
}
@@ -136,9 +302,6 @@ bool DiagramData::removeNode(const OUString& rNodeId)
maPoints.end());
// TODO: fix source/dest order
buildDiagramDataModel(true);
return true;
}
@@ -254,8 +417,6 @@ OUString DiagramData::addNode(const OUString& rText)
maPoints.push_back(aDataPoint);
maPoints.push_back(aPresPoint);
buildDiagramDataModel(true);
return sNewNodeId;
}