diff options
Diffstat (limited to 'oox/source/drawingml/diagram/diagramhelper.cxx')
-rw-r--r-- | oox/source/drawingml/diagram/diagramhelper.cxx | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/oox/source/drawingml/diagram/diagramhelper.cxx b/oox/source/drawingml/diagram/diagramhelper.cxx new file mode 100644 index 000000000..7b746e067 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramhelper.cxx @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "diagramhelper.hxx" +#include "diagram.hxx" + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <oox/shape/ShapeFilterBase.hxx> +#include <oox/ppt/pptimport.hxx> +#include <drawingml/fillproperties.hxx> +#include <svx/svdmodel.hxx> +#include <comphelper/processfactory.hxx> +#include <oox/drawingml/themefragmenthandler.hxx> +#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> + +using namespace ::com::sun::star; + +namespace oox::drawingml { + +bool AdvancedDiagramHelper::hasDiagramData() const +{ + return mpDiagramPtr && mpDiagramPtr->getData(); +} + +AdvancedDiagramHelper::AdvancedDiagramHelper( + const std::shared_ptr< Diagram >& rDiagramPtr, + const std::shared_ptr<::oox::drawingml::Theme>& rTheme, + css::awt::Size aImportSize) +: svx::diagram::IDiagramHelper() +, mpDiagramPtr(rDiagramPtr) +, mpThemePtr(rTheme) +, maImportSize(aImportSize) +{ +} + +AdvancedDiagramHelper::~AdvancedDiagramHelper() +{ +} + +void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget) +{ + if(!mpDiagramPtr) + { + return; + } + + // Rescue/remember geometric transformation of existing Diagram + basegfx::B2DHomMatrix aTransformation; + basegfx::B2DPolyPolygon aPolyPolygon; + rTarget.TRGetBaseGeometry(aTransformation, aPolyPolygon); + + // create temporary oox::Shape as target. No longer needed is to keep/remember + // the original oox::Shape to do that. Use original Size and Pos from initial import + // to get the same layout(s) + oox::drawingml::ShapePtr pShapePtr = std::make_shared<Shape>( "com.sun.star.drawing.GroupShape" ); + pShapePtr->setDiagramType(); + pShapePtr->setSize(maImportSize); + + // Re-create the oox::Shapes for the diagram content + mpDiagramPtr->addTo(pShapePtr); + + // Delete all existing shapes in that group to prepare re-creation + rTarget.getChildrenOfSdrObject()->ClearSdrObjList(); + + // For re-creation we need to use ::addShape functionality from the + // oox import filter since currently Shape import is very tightly + // coupled to Shape creation. It converts a oox::Shape representation + // combined with an oox::Theme to incarnated XShapes representing the + // Diagram. + // To use that functionality, we have to create a temporary filter + // (based on ShapeFilterBase). Problems are that this needs to know + // the oox:Theme and a ComponentModel from TargetDocument. + // The DiagramHelper holds/delivers the oox::Theme to use, so + // it does not need to be re-imported from oox repeatedly. + // The ComponentModel can be derived from the existing XShape/GroupShape + // when knowing where to get it from, making it independent from app. + // + // NOTE: Using another (buffered) oox::Theme would allow to re-create + // using another theming in the future. + // NOTE: The incarnation of import filter (ShapeFilterBase) is only + // used for XShape creation, no xml snippets/data gets imported + // here. XShape creation may be isolated in the future. + SdrModel& rModel(rTarget.getSdrModelFromSdrObject()); + uno::Reference< uno::XInterface > const & rUnoModel(rModel.getUnoModel()); + css::uno::Reference<css::uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + rtl::Reference<oox::shape::ShapeFilterBase> xFilter(new oox::shape::ShapeFilterBase(xContext)); + + // set oox::Theme at Filter. All LineStyle/FillStyle/Colors/Attributes + // will be taken from there + if(UseDiagramThemeData()) + xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter)); + + css::uno::Reference< css::lang::XComponent > aComponentModel( rUnoModel, uno::UNO_QUERY ); + xFilter->setTargetDocument(aComponentModel); + + // set DiagramFontHeights + xFilter->setDiagramFontHeights(&mpDiagramPtr->getDiagramFontHeights()); + + // Prepare the target for the to-be-created XShapes + uno::Reference<drawing::XShapes> xShapes(rTarget.getUnoShape(), uno::UNO_QUERY_THROW); + + for (auto const& child : pShapePtr->getChildren()) + { + // Create all sub-shapes. This will recursively create needed geometry using + // filter-internal ::createShapes + child->addShape( + *xFilter, + xFilter->getCurrentTheme(), + xShapes, + aTransformation, + pShapePtr->getFillProperties()); + } + + // sync FontHeights + mpDiagramPtr->syncDiagramFontHeights(); + + // re-apply secured data from ModelData + if(UseDiagramModelData()) + mpDiagramPtr->getData()->restoreDataFromShapeToModelAfterDiagramImport(*pShapePtr); + + // Re-apply remembered geometry + rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon); +} + +OUString AdvancedDiagramHelper::getString() const +{ + if(hasDiagramData()) + { + return mpDiagramPtr->getData()->getString(); + } + + return OUString(); +} + +std::vector<std::pair<OUString, OUString>> AdvancedDiagramHelper::getChildren(const OUString& rParentId) const +{ + if(hasDiagramData()) + { + return mpDiagramPtr->getData()->getChildren(rParentId); + } + + return std::vector<std::pair<OUString, OUString>>(); +} + +OUString AdvancedDiagramHelper::addNode(const OUString& rText) +{ + OUString aRetval; + + if(hasDiagramData()) + { + 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 aRetval; +} + +bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId) +{ + bool bRetval(false); + + if(hasDiagramData()) + { + 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 bRetval; +} + +svx::diagram::DiagramDataStatePtr AdvancedDiagramHelper::extractDiagramDataState() const +{ + if(!mpDiagramPtr) + { + return svx::diagram::DiagramDataStatePtr(); + } + + return mpDiagramPtr->getData()->extractDiagramDataState(); +} + +void AdvancedDiagramHelper::applyDiagramDataState(const svx::diagram::DiagramDataStatePtr& rState) +{ + if(!mpDiagramPtr) + { + return; + } + + mpDiagramPtr->getData()->applyDiagramDataState(rState); +} + +void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape) +{ + if(!mpDiagramPtr) + { + return; + } + + 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(rRootShape); + + anchorToSdrObjGroup(rTarget); +} + +std::shared_ptr< ::oox::drawingml::Theme > AdvancedDiagramHelper::getOrCreateThemePtr( + rtl::Reference< oox::shape::ShapeFilterBase >& rxFilter) const +{ + // (Re-)Use already existing Theme if existing/imported if possible. + // If not, re-import Theme if data is available and thus possible + if(hasDiagramData() && (ForceThemePtrRecreation() || !mpThemePtr)) + { + // get the originally imported dom::XDocument + const uno::Reference< css::xml::dom::XDocument >& xThemeDocument(mpDiagramPtr->getData()->getThemeDocument()); + + if(xThemeDocument) + { + // reset local Theme ModelData *always* to get rid of former data that would + // else be added additionally + const_cast<AdvancedDiagramHelper*>(this)->mpThemePtr = std::make_shared<oox::drawingml::Theme>(); + + // import Theme ModelData + rxFilter->importFragment( + new ThemeFragmentHandler( + *rxFilter, OUString(), *mpThemePtr ), + uno::Reference< css::xml::sax::XFastSAXSerializable >( + xThemeDocument, + uno::UNO_QUERY_THROW)); + } + } + + return mpThemePtr; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |