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:
committed by
Armin Le Grand
parent
16bbd139d6
commit
edadfb564f
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user