summaryrefslogtreecommitdiffstats
path: root/reportdesign/source/core/sdr
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /reportdesign/source/core/sdr
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'reportdesign/source/core/sdr')
-rw-r--r--reportdesign/source/core/sdr/PropertyForward.cxx180
-rw-r--r--reportdesign/source/core/sdr/ReportDrawPage.cxx149
-rw-r--r--reportdesign/source/core/sdr/ReportUndoFactory.cxx157
-rw-r--r--reportdesign/source/core/sdr/RptModel.cxx187
-rw-r--r--reportdesign/source/core/sdr/RptObject.cxx1219
-rw-r--r--reportdesign/source/core/sdr/RptObjectListener.cxx69
-rw-r--r--reportdesign/source/core/sdr/RptPage.cxx192
-rw-r--r--reportdesign/source/core/sdr/UndoActions.cxx407
-rw-r--r--reportdesign/source/core/sdr/UndoEnv.cxx619
-rw-r--r--reportdesign/source/core/sdr/formatnormalizer.cxx258
-rw-r--r--reportdesign/source/core/sdr/formatnormalizer.hxx86
11 files changed, 3523 insertions, 0 deletions
diff --git a/reportdesign/source/core/sdr/PropertyForward.cxx b/reportdesign/source/core/sdr/PropertyForward.cxx
new file mode 100644
index 000000000..394edfc12
--- /dev/null
+++ b/reportdesign/source/core/sdr/PropertyForward.cxx
@@ -0,0 +1,180 @@
+/* -*- 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 <PropertyForward.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <comphelper/property.hxx>
+#include <tools/diagnose_ex.h>
+#include <strings.hxx>
+
+namespace rptui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+
+OPropertyMediator::OPropertyMediator(const Reference< XPropertySet>& _xSource
+ ,const Reference< XPropertySet>& _xDest
+ ,TPropertyNamePair&& _aNameMap
+ ,bool _bReverse)
+ : OPropertyForward_Base(m_aMutex)
+ ,m_aNameMap(std::move(_aNameMap))
+ ,m_xSource(_xSource)
+ ,m_xDest(_xDest)
+ ,m_bInChange(false)
+{
+ osl_atomic_increment(&m_refCount);
+ OSL_ENSURE(m_xDest.is(),"Dest is NULL!");
+ OSL_ENSURE(m_xSource.is(),"Source is NULL!");
+ if ( m_xDest.is() && m_xSource.is() )
+ {
+ try
+ {
+ m_xDestInfo = m_xDest->getPropertySetInfo();
+ m_xSourceInfo = m_xSource->getPropertySetInfo();
+ if ( _bReverse )
+ {
+ ::comphelper::copyProperties(m_xDest,m_xSource);
+ for (const auto& [rName, rPropConv] : m_aNameMap)
+ {
+ Property aProp = m_xSourceInfo->getPropertyByName(rName);
+ if (0 == (aProp.Attributes & PropertyAttribute::READONLY))
+ {
+ Any aValue = _xDest->getPropertyValue(rPropConv.first);
+ if ( 0 != (aProp.Attributes & PropertyAttribute::MAYBEVOID) || aValue.hasValue() )
+ _xSource->setPropertyValue(rName, rPropConv.second->operator()(rPropConv.first, aValue));
+ }
+ }
+ }
+ else
+ {
+ ::comphelper::copyProperties(m_xSource,m_xDest);
+ for (const auto& [rName, rPropConv] : m_aNameMap)
+ _xDest->setPropertyValue(rPropConv.first, rPropConv.second->operator()(rPropConv.first, _xSource->getPropertyValue(rName)));
+ }
+ startListening();
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ }
+ osl_atomic_decrement(&m_refCount);
+}
+
+OPropertyMediator::~OPropertyMediator()
+{
+}
+
+void SAL_CALL OPropertyMediator::propertyChange( const PropertyChangeEvent& evt )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if ( m_bInChange )
+ return;
+
+ m_bInChange = true;
+ try
+ {
+ bool bDest = (evt.Source == m_xDest);
+ Reference<XPropertySet> xProp = bDest ? m_xSource : m_xDest;
+ Reference<XPropertySetInfo> xPropInfo = bDest ? m_xSourceInfo : m_xDestInfo;
+ if ( xProp.is() && xPropInfo.is() )
+ {
+ if ( xPropInfo->hasPropertyByName(evt.PropertyName) )
+ xProp->setPropertyValue(evt.PropertyName,evt.NewValue);
+ else
+ {
+ TPropertyNamePair::const_iterator aFind = m_aNameMap.find(evt.PropertyName);
+ OUString sPropName;
+ if ( aFind != m_aNameMap.end() )
+ sPropName = aFind->second.first;
+ else
+ {
+ aFind = ::std::find_if(
+ m_aNameMap.begin(),
+ m_aNameMap.end(),
+ [&evt] (const TPropertyNamePair::value_type& namePair) {
+ return namePair.second.first == evt.PropertyName;
+ });
+ if ( aFind != m_aNameMap.end() )
+ sPropName = aFind->first;
+ }
+ if (aFind != m_aNameMap.end() && !sPropName.isEmpty() && xPropInfo->hasPropertyByName(sPropName))
+ xProp->setPropertyValue(sPropName,aFind->second.second->operator()(sPropName,evt.NewValue));
+ else if ( evt.PropertyName == PROPERTY_CHARFONTNAME
+ || evt.PropertyName == PROPERTY_CHARFONTSTYLENAME
+ || evt.PropertyName == PROPERTY_CHARSTRIKEOUT
+ || evt.PropertyName == PROPERTY_CHARWORDMODE
+ || evt.PropertyName == PROPERTY_CHARROTATION
+ || evt.PropertyName == PROPERTY_CHARSCALEWIDTH
+ || evt.PropertyName == PROPERTY_CHARFONTFAMILY
+ || evt.PropertyName == PROPERTY_CHARFONTCHARSET
+ || evt.PropertyName == PROPERTY_CHARFONTPITCH
+ || evt.PropertyName == PROPERTY_CHARHEIGHT
+ || evt.PropertyName == PROPERTY_CHARUNDERLINE
+ || evt.PropertyName == PROPERTY_CHARWEIGHT
+ || evt.PropertyName == PROPERTY_CHARPOSTURE)
+ {
+ xProp->setPropertyValue(PROPERTY_FONTDESCRIPTOR,m_xSource->getPropertyValue(PROPERTY_FONTDESCRIPTOR));
+ }
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "reportdesign", "");
+ }
+ m_bInChange = false;
+}
+
+void SAL_CALL OPropertyMediator::disposing( const css::lang::EventObject& /*_rSource*/ )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ disposing();
+}
+
+void SAL_CALL OPropertyMediator::disposing()
+{
+ stopListening();
+ m_xSource.clear();
+ m_xSourceInfo.clear();
+ m_xDest.clear();
+ m_xDestInfo.clear();
+}
+
+void OPropertyMediator::stopListening()
+{
+ if ( m_xSource.is() )
+ m_xSource->removePropertyChangeListener(OUString(), this);
+ if ( m_xDest.is() )
+ m_xDest->removePropertyChangeListener(OUString(), this);
+}
+
+void OPropertyMediator::startListening()
+{
+ if ( m_xSource.is() )
+ m_xSource->addPropertyChangeListener(OUString(), this);
+ if ( m_xDest.is() )
+ m_xDest->addPropertyChangeListener(OUString(), this);
+}
+
+
+} // namespace dbaccess
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/ReportDrawPage.cxx b/reportdesign/source/core/sdr/ReportDrawPage.cxx
new file mode 100644
index 000000000..b89c3dac2
--- /dev/null
+++ b/reportdesign/source/core/sdr/ReportDrawPage.cxx
@@ -0,0 +1,149 @@
+/* -*- 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 <ReportDrawPage.hxx>
+#include <RptObject.hxx>
+#include <RptModel.hxx>
+#include <strings.hxx>
+#include <comphelper/mimeconfighelper.hxx>
+#include <comphelper/embeddedobjectcontainer.hxx>
+
+#include <svx/svdmodel.hxx>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <tools/diagnose_ex.h>
+#include <svx/unoshape.hxx>
+#include <svx/svdpage.hxx>
+
+namespace reportdesign
+{
+ using namespace ::com::sun::star;
+ using namespace rptui;
+
+OReportDrawPage::OReportDrawPage(SdrPage* _pPage
+ ,const uno::Reference< report::XSection >& _xSection)
+: SvxDrawPage(_pPage)
+,m_xSection(_xSection)
+{
+}
+
+SdrObject* OReportDrawPage::CreateSdrObject_(const uno::Reference< drawing::XShape > & xDescr)
+{
+ uno::Reference< report::XReportComponent> xReportComponent(xDescr,uno::UNO_QUERY);
+ if ( xReportComponent.is() )
+ {
+ return OObjectBase::createObject(
+ GetSdrPage()->getSdrModelFromSdrPage(),
+ xReportComponent);
+ }
+
+ return SvxDrawPage::CreateSdrObject_( xDescr );
+}
+
+uno::Reference< drawing::XShape > OReportDrawPage::CreateShape( SdrObject *pObj ) const
+{
+ OObjectBase* pBaseObj = dynamic_cast<OObjectBase*>(pObj);
+ if ( !pBaseObj )
+ return SvxDrawPage::CreateShape( pObj );
+
+ uno::Reference< report::XSection> xSection = m_xSection;
+ uno::Reference< lang::XMultiServiceFactory> xFactory;
+ if ( xSection.is() )
+ xFactory.set(xSection->getReportDefinition(),uno::UNO_QUERY);
+ uno::Reference< drawing::XShape > xRet;
+ uno::Reference< drawing::XShape > xShape;
+ if ( xFactory.is() )
+ {
+ bool bChangeOrientation = false;
+ const OUString& sServiceName = pBaseObj->getServiceName();
+ OSL_ENSURE(!sServiceName.isEmpty(),"No Service Name given!");
+
+ if (dynamic_cast< const OUnoObject* >(pObj) != nullptr)
+ {
+ OUnoObject& rUnoObj = dynamic_cast<OUnoObject&>(*pObj);
+ if (rUnoObj.GetObjIdentifier() == SdrObjKind::ReportDesignFixedText)
+ {
+ uno::Reference<beans::XPropertySet> xControlModel(rUnoObj.GetUnoControlModel(),uno::UNO_QUERY);
+ if ( xControlModel.is() )
+ xControlModel->setPropertyValue( PROPERTY_MULTILINE,uno::Any(true));
+ }
+ else
+ bChangeOrientation = rUnoObj.GetObjIdentifier() == SdrObjKind::ReportDesignHorizontalFixedLine;
+ rtl::Reference<SvxShapeControl> pShape = new SvxShapeControl( pObj );
+ xShape = static_cast<SvxShape_UnoImplHelper *>(pShape.get());
+ pShape->setShapeKind(pObj->GetObjIdentifier());
+ }
+ else if (dynamic_cast< const OCustomShape* >(pObj) != nullptr)
+ {
+ rtl::Reference<SvxCustomShape> pShape = new SvxCustomShape( pObj );
+ xShape = pShape;
+ pShape->setShapeKind(pObj->GetObjIdentifier());
+ }
+ else if (dynamic_cast< const SdrOle2Obj* >(pObj) != nullptr)
+ {
+ SdrOle2Obj& rOle2Obj = dynamic_cast<SdrOle2Obj&>(*pObj);
+ if (!rOle2Obj.GetObjRef().is())
+ {
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+ uno::Reference < embed::XEmbeddedObject > xObj;
+ OUString sName;
+ xObj = pObj->getSdrModelFromSdrObject().GetPersist()->getEmbeddedObjectContainer().CreateEmbeddedObject(
+ ::comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(
+ u"80243D39-6741-46C5-926E-069164FF87BB"), sName );
+ OSL_ENSURE(xObj.is(),"Embedded Object could not be created!");
+
+ /**************************************************
+ * The empty OLE object gets a new IPObj
+ **************************************************/
+ pObj->SetEmptyPresObj(false);
+ rOle2Obj.SetOutlinerParaObject(std::nullopt);
+ rOle2Obj.SetObjRef(xObj);
+ rOle2Obj.SetPersistName(sName);
+ rOle2Obj.SetName(sName);
+ rOle2Obj.SetAspect(nAspect);
+ tools::Rectangle aRect = rOle2Obj.GetLogicRect();
+
+ Size aTmp = aRect.GetSize();
+ awt::Size aSz( aTmp.Width(), aTmp.Height() );
+ xObj->setVisualAreaSize( nAspect, aSz );
+ }
+ rtl::Reference<SvxOle2Shape> pShape = new SvxOle2Shape( pObj );
+ xShape = pShape;
+ pShape->setShapeKind(pObj->GetObjIdentifier());
+ }
+
+ if ( !xShape.is() )
+ xShape.set( SvxDrawPage::CreateShape( pObj ) );
+
+ try
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(pObj->getSdrModelFromSdrObject()));
+ xRet.set( rRptModel.createShape(sServiceName,xShape,bChangeOrientation ? 0 : 1), uno::UNO_QUERY_THROW );
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ }
+
+ return xRet;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/ReportUndoFactory.cxx b/reportdesign/source/core/sdr/ReportUndoFactory.cxx
new file mode 100644
index 000000000..1c36d836b
--- /dev/null
+++ b/reportdesign/source/core/sdr/ReportUndoFactory.cxx
@@ -0,0 +1,157 @@
+/* -*- 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 <ReportUndoFactory.hxx>
+#include <RptObject.hxx>
+#include <UndoActions.hxx>
+#include <strings.hrc>
+
+namespace rptui
+{
+ using namespace ::com::sun::star;
+
+static std::unique_ptr<SdrUndoAction> lcl_createUndo(SdrObject& rObject, Action _eAction, TranslateId pCommentId)
+{
+ OObjectBase* pObj = dynamic_cast<OObjectBase*>(&rObject);
+ if ( !pObj )
+ return nullptr;
+ uno::Reference< report::XReportComponent> xReportComponent = pObj->getReportComponent();
+ uno::Reference< report::XSection> xSection = pObj->getSection();
+ uno::Reference< report::XGroup> xGroup = xSection->getGroup();
+ if ( xGroup.is() )
+ return std::make_unique<OUndoGroupSectionAction>(rObject.getSdrModelFromSdrObject(),_eAction,OGroupHelper::getMemberFunction(xSection),xGroup,xReportComponent,pCommentId);
+ else
+ return std::make_unique<OUndoReportSectionAction>(rObject.getSdrModelFromSdrObject(),_eAction,OReportHelper::getMemberFunction(xSection),xSection->getReportDefinition(),xReportComponent,pCommentId);
+}
+
+
+OReportUndoFactory::OReportUndoFactory() : m_pUndoFactory(new SdrUndoFactory)
+{
+}
+
+OReportUndoFactory::~OReportUndoFactory()
+{
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoMoveObject( SdrObject& rObject, const Size& rDist )
+{
+ return m_pUndoFactory->CreateUndoMoveObject( rObject, rDist );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoGeoObject( SdrObject& rObject )
+{
+ return m_pUndoFactory->CreateUndoGeoObject( rObject );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText )
+{
+ return m_pUndoFactory->CreateUndoAttrObject( rObject, bStyleSheet1, bSaveText );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoRemoveObject(SdrObject& rObject)
+{
+ return m_pUndoFactory->CreateUndoRemoveObject(rObject);
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoInsertObject( SdrObject& rObject, bool /*bOrdNumDirect*/ )
+{
+ return lcl_createUndo(rObject,rptui::Inserted,RID_STR_UNDO_INSERT_CONTROL);
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoDeleteObject( SdrObject& rObject, bool /*bOrdNumDirect*/ )
+{
+ return lcl_createUndo(rObject,rptui::Removed,RID_STR_UNDO_DELETE_CONTROL);
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoNewObject( SdrObject& rObject, bool /*bOrdNumDirect*/ )
+{
+ return lcl_createUndo(rObject,rptui::Inserted,RID_STR_UNDO_INSERT_CONTROL);
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoCopyObject( SdrObject& rObject, bool bOrdNumDirect )
+{
+ return m_pUndoFactory->CreateUndoCopyObject( rObject, bOrdNumDirect );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoObjectOrdNum( SdrObject& rObject, sal_uInt32 nOldOrdNum1, sal_uInt32 nNewOrdNum1)
+{
+ return m_pUndoFactory->CreateUndoObjectOrdNum( rObject, nOldOrdNum1, nNewOrdNum1 );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject )
+{
+ return m_pUndoFactory->CreateUndoReplaceObject( rOldObject, rNewObject );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoObjectLayerChange( SdrObject& rObject, SdrLayerID aOldLayer, SdrLayerID aNewLayer )
+{
+ return m_pUndoFactory->CreateUndoObjectLayerChange( rObject, aOldLayer, aNewLayer );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoObjectSetText( SdrObject& rNewObj, sal_Int32 nText )
+{
+ return m_pUndoFactory->CreateUndoObjectSetText( rNewObj, nText );
+}
+
+// layer
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoNewLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel)
+{
+ return m_pUndoFactory->CreateUndoNewLayer( nLayerNum, rNewLayerAdmin, rNewModel );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoDeleteLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel)
+{
+ return m_pUndoFactory->CreateUndoDeleteLayer( nLayerNum, rNewLayerAdmin, rNewModel );
+}
+
+// page
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoDeletePage(SdrPage& rPage)
+{
+ return m_pUndoFactory->CreateUndoDeletePage(rPage);
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoNewPage(SdrPage& rPage)
+{
+ return m_pUndoFactory->CreateUndoNewPage( rPage );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoCopyPage(SdrPage& rPage)
+{
+ return m_pUndoFactory->CreateUndoCopyPage( rPage );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoSetPageNum(SdrPage& rNewPg, sal_uInt16 nOldPageNum1, sal_uInt16 nNewPageNum1)
+{
+ return m_pUndoFactory->CreateUndoSetPageNum( rNewPg, nOldPageNum1, nNewPageNum1 );
+}
+ // master page
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoPageRemoveMasterPage(SdrPage& rChangedPage)
+{
+ return m_pUndoFactory->CreateUndoPageRemoveMasterPage( rChangedPage );
+}
+
+std::unique_ptr<SdrUndoAction> OReportUndoFactory::CreateUndoPageChangeMasterPage(SdrPage& rChangedPage)
+{
+ return m_pUndoFactory->CreateUndoPageChangeMasterPage(rChangedPage);
+}
+
+
+} //rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/RptModel.cxx b/reportdesign/source/core/sdr/RptModel.cxx
new file mode 100644
index 000000000..e7fa935f8
--- /dev/null
+++ b/reportdesign/source/core/sdr/RptModel.cxx
@@ -0,0 +1,187 @@
+/* -*- 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 <RptModel.hxx>
+#include <RptPage.hxx>
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+#include <vcl/svapp.hxx>
+
+#include <UndoEnv.hxx>
+#include <ReportUndoFactory.hxx>
+#include <ReportDefinition.hxx>
+
+#include <RptDef.hxx>
+#include <strings.hxx>
+#include <FixedLine.hxx>
+#include <FormattedField.hxx>
+#include <FixedText.hxx>
+#include <ImageControl.hxx>
+#include <Shape.hxx>
+
+namespace rptui
+{
+using namespace reportdesign;
+using namespace com::sun::star;
+
+
+OReportModel::OReportModel(::reportdesign::OReportDefinition* _pReportDefinition)
+: SdrModel(
+ nullptr,
+ _pReportDefinition)
+ ,m_pController(nullptr)
+ ,m_pReportDefinition(_pReportDefinition)
+{
+ m_xUndoEnv = new OXUndoEnvironment(*this);
+ SetSdrUndoFactory(new OReportUndoFactory);
+}
+
+
+OReportModel::~OReportModel()
+{
+ detachController();
+}
+
+void OReportModel::detachController()
+{
+ m_pReportDefinition = nullptr;
+ m_pController = nullptr;
+ m_xUndoEnv->EndListening( *this );
+ ClearUndoBuffer();
+ m_xUndoEnv->Clear(OXUndoEnvironment::Accessor());
+}
+
+rtl::Reference<SdrPage> OReportModel::AllocPage(bool /*bMasterPage*/)
+{
+ OSL_FAIL("Who called me!");
+ return nullptr;
+}
+
+
+void OReportModel::SetChanged( bool bChanged )
+{
+ SdrModel::SetChanged( bChanged );
+ SetModified( bChanged );
+}
+
+
+void OReportModel::SetModified(bool _bModified)
+{
+ if ( m_pController )
+ m_pController->setModified(_bModified);
+}
+
+rtl::Reference<SdrPage> OReportModel::RemovePage(sal_uInt16 nPgNum)
+{
+ rtl::Reference<OReportPage> pPage = dynamic_cast<OReportPage*>(SdrModel::RemovePage(nPgNum).get());
+ return pPage;
+}
+
+OReportPage* OReportModel::createNewPage(const uno::Reference< report::XSection >& _xSection)
+{
+ SolarMutexGuard aSolarGuard;
+ rtl::Reference<OReportPage> pPage = new OReportPage( *this ,_xSection);
+ InsertPage(pPage.get());
+ m_xUndoEnv->AddSection(_xSection);
+ return pPage.get();
+}
+
+OReportPage* OReportModel::getPage(const uno::Reference< report::XSection >& _xSection)
+{
+ OReportPage* pPage = nullptr;
+ sal_uInt16 nCount = GetPageCount();
+ for (sal_uInt16 i = 0; i < nCount && !pPage ; ++i)
+ {
+ OReportPage* pRptPage = dynamic_cast<OReportPage*>( GetPage(i) );
+ if ( pRptPage && pRptPage->getSection() == _xSection )
+ pPage = pRptPage;
+ }
+ return pPage;
+}
+
+SvxNumType OReportModel::GetPageNumType() const
+{
+ uno::Reference< report::XReportDefinition > xReportDefinition( getReportDefinition() );
+ if ( xReportDefinition.is() )
+ return static_cast<SvxNumType>(getStyleProperty<sal_Int16>(xReportDefinition,PROPERTY_NUMBERINGTYPE));
+ return SVX_NUM_ARABIC;
+}
+
+
+uno::Reference< report::XReportDefinition > OReportModel::getReportDefinition() const
+{
+ uno::Reference< report::XReportDefinition > xReportDefinition = m_pReportDefinition;
+ OSL_ENSURE( xReportDefinition.is(), "OReportModel::getReportDefinition: invalid model at our controller!" );
+ return xReportDefinition;
+}
+
+uno::Reference< uno::XInterface > OReportModel::createUnoModel()
+{
+ return uno::Reference< uno::XInterface >(getReportDefinition(),uno::UNO_QUERY);
+}
+
+uno::Reference< uno::XInterface > OReportModel::createShape(const OUString& aServiceSpecifier,uno::Reference< drawing::XShape >& _rShape,sal_Int32 nOrientation)
+{
+ uno::Reference< uno::XInterface > xRet;
+ if ( _rShape.is() )
+ {
+ if ( aServiceSpecifier == SERVICE_FORMATTEDFIELD )
+ {
+ uno::Reference<report::XFormattedField> xProp = new OFormattedField(m_pReportDefinition->getContext(),m_pReportDefinition,_rShape);
+ xRet = xProp;
+ if ( _rShape.is() )
+ throw uno::Exception("no shape", nullptr);
+ xProp->setPropertyValue( PROPERTY_FORMATSSUPPLIER, uno::Any(uno::Reference< util::XNumberFormatsSupplier >(*m_pReportDefinition,uno::UNO_QUERY)) );
+ }
+ else if ( aServiceSpecifier == SERVICE_FIXEDTEXT)
+ {
+ xRet = static_cast<cppu::OWeakObject*>(new OFixedText(m_pReportDefinition->getContext(),m_pReportDefinition,_rShape));
+ if ( _rShape.is() )
+ throw uno::Exception("no shape", nullptr);
+ }
+ else if ( aServiceSpecifier == SERVICE_FIXEDLINE)
+ {
+ xRet = static_cast<cppu::OWeakObject*>(new OFixedLine(m_pReportDefinition->getContext(),m_pReportDefinition,_rShape,nOrientation));
+ if ( _rShape.is() )
+ throw uno::Exception("no shape", nullptr);
+ }
+ else if ( aServiceSpecifier == SERVICE_IMAGECONTROL )
+ {
+ xRet = static_cast<cppu::OWeakObject*>(new OImageControl(m_pReportDefinition->getContext(),m_pReportDefinition,_rShape));
+ if ( _rShape.is() )
+ throw uno::Exception("no shape", nullptr);
+ }
+ else if ( aServiceSpecifier == SERVICE_REPORTDEFINITION )
+ {
+ xRet = static_cast<cppu::OWeakObject*>(new OReportDefinition(m_pReportDefinition->getContext(),m_pReportDefinition,_rShape));
+ if ( _rShape.is() )
+ throw uno::Exception("no shape", nullptr);
+ }
+ else if ( _rShape.is() )
+ {
+ xRet = static_cast<cppu::OWeakObject*>(new OShape(m_pReportDefinition->getContext(),m_pReportDefinition,_rShape,aServiceSpecifier));
+ if ( _rShape.is() )
+ throw uno::Exception("no shape", nullptr);
+ }
+ }
+ return xRet;
+}
+
+} //rptui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/RptObject.cxx b/reportdesign/source/core/sdr/RptObject.cxx
new file mode 100644
index 000000000..1972e892e
--- /dev/null
+++ b/reportdesign/source/core/sdr/RptObject.cxx
@@ -0,0 +1,1219 @@
+/* -*- 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 <RptObject.hxx>
+#include <algorithm>
+
+#include <RptDef.hxx>
+#include <svx/unoshape.hxx>
+#include <RptModel.hxx>
+#include <RptObjectListener.hxx>
+#include <RptPage.hxx>
+
+#include <strings.hxx>
+#include <svtools/embedhlp.hxx>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/XComponentSupplier.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/report/XFixedLine.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/report/XFormattedField.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/property.hxx>
+#include <svx/svdundo.hxx>
+#include <tools/diagnose_ex.h>
+#include <PropertyForward.hxx>
+#include <UndoEnv.hxx>
+
+namespace rptui
+{
+
+using namespace ::com::sun::star;
+using namespace uno;
+using namespace beans;
+using namespace reportdesign;
+using namespace container;
+using namespace report;
+
+SdrObjKind OObjectBase::getObjectType(const uno::Reference< report::XReportComponent>& _xComponent)
+{
+ uno::Reference< lang::XServiceInfo > xServiceInfo( _xComponent , uno::UNO_QUERY );
+ OSL_ENSURE(xServiceInfo.is(),"Who deletes the XServiceInfo interface!");
+ if ( !xServiceInfo )
+ return SdrObjKind::NONE;
+
+ if ( xServiceInfo->supportsService( SERVICE_FIXEDTEXT ))
+ return SdrObjKind::ReportDesignFixedText;
+ if ( xServiceInfo->supportsService( SERVICE_FIXEDLINE ))
+ {
+ uno::Reference< report::XFixedLine> xFixedLine(_xComponent,uno::UNO_QUERY);
+ return xFixedLine->getOrientation() ? SdrObjKind::ReportDesignHorizontalFixedLine : SdrObjKind::ReportDesignVerticalFixedLine;
+ }
+ if ( xServiceInfo->supportsService( SERVICE_IMAGECONTROL))
+ return SdrObjKind::ReportDesignImageControl;
+ if ( xServiceInfo->supportsService( SERVICE_FORMATTEDFIELD ))
+ return SdrObjKind::ReportDesignFormattedField;
+ if ( xServiceInfo->supportsService("com.sun.star.drawing.OLE2Shape") )
+ return SdrObjKind::OLE2;
+ if ( xServiceInfo->supportsService( SERVICE_SHAPE ))
+ return SdrObjKind::CustomShape;
+ if ( xServiceInfo->supportsService( SERVICE_REPORTDEFINITION ) )
+ return SdrObjKind::ReportDesignSubReport;
+ return SdrObjKind::OLE2;
+}
+
+SdrObject* OObjectBase::createObject(
+ SdrModel& rTargetModel,
+ const uno::Reference< report::XReportComponent>& _xComponent)
+{
+ SdrObject* pNewObj = nullptr;
+ SdrObjKind nType = OObjectBase::getObjectType(_xComponent);
+ switch( nType )
+ {
+ case SdrObjKind::ReportDesignFixedText:
+ {
+ OUnoObject* pUnoObj = new OUnoObject(
+ rTargetModel,
+ _xComponent,
+ OUString("com.sun.star.form.component.FixedText"),
+ SdrObjKind::ReportDesignFixedText);
+ pNewObj = pUnoObj;
+
+ uno::Reference<beans::XPropertySet> xControlModel(pUnoObj->GetUnoControlModel(),uno::UNO_QUERY);
+ if ( xControlModel.is() )
+ xControlModel->setPropertyValue( PROPERTY_MULTILINE,uno::Any(true));
+ }
+ break;
+ case SdrObjKind::ReportDesignImageControl:
+ pNewObj = new OUnoObject(
+ rTargetModel,
+ _xComponent,
+ OUString("com.sun.star.form.component.DatabaseImageControl"),
+ SdrObjKind::ReportDesignImageControl);
+ break;
+ case SdrObjKind::ReportDesignFormattedField:
+ pNewObj = new OUnoObject(
+ rTargetModel,
+ _xComponent,
+ OUString("com.sun.star.form.component.FormattedField"),
+ SdrObjKind::ReportDesignFormattedField);
+ break;
+ case SdrObjKind::ReportDesignHorizontalFixedLine:
+ case SdrObjKind::ReportDesignVerticalFixedLine:
+ pNewObj = new OUnoObject(
+ rTargetModel,
+ _xComponent,
+ OUString("com.sun.star.awt.UnoControlFixedLineModel"),
+ nType);
+ break;
+ case SdrObjKind::CustomShape:
+ pNewObj = OCustomShape::Create(
+ rTargetModel,
+ _xComponent);
+ try
+ {
+ bool bOpaque = false;
+ _xComponent->getPropertyValue(PROPERTY_OPAQUE) >>= bOpaque;
+ pNewObj->NbcSetLayer(bOpaque ? RPT_LAYER_FRONT : RPT_LAYER_BACK);
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ break;
+ case SdrObjKind::ReportDesignSubReport:
+ case SdrObjKind::OLE2:
+ pNewObj = OOle2Obj::Create(
+ rTargetModel,
+ _xComponent,
+ nType);
+ break;
+ default:
+ OSL_FAIL("Unknown object id");
+ break;
+ }
+
+ if ( pNewObj )
+ pNewObj->SetDoNotInsertIntoPageAutomatically( true );
+
+ ensureSdrObjectOwnership( _xComponent );
+
+ return pNewObj;
+}
+
+namespace
+{
+ class ParaAdjust : public AnyConverter
+ {
+ public:
+ virtual css::uno::Any operator() (const OUString& _sPropertyName,const css::uno::Any& lhs) const override
+ {
+ uno::Any aRet;
+ if (_sPropertyName == PROPERTY_PARAADJUST)
+ {
+ sal_Int16 nTextAlign = 0;
+ lhs >>= nTextAlign;
+ style::ParagraphAdjust eAdjust;
+ switch(nTextAlign)
+ {
+ case awt::TextAlign::LEFT:
+ eAdjust = style::ParagraphAdjust_LEFT;
+ break;
+ case awt::TextAlign::CENTER:
+ eAdjust = style::ParagraphAdjust_CENTER;
+ break;
+ case awt::TextAlign::RIGHT:
+ eAdjust = style::ParagraphAdjust_RIGHT;
+ break;
+ default:
+ OSL_FAIL("Illegal text alignment value!");
+ break;
+ }
+ aRet <<= eAdjust;
+ }
+ else
+ {
+ sal_Int16 nTextAlign = 0;
+ sal_Int16 eParagraphAdjust = 0;
+ lhs >>= eParagraphAdjust;
+ switch(static_cast<style::ParagraphAdjust>(eParagraphAdjust))
+ {
+ case style::ParagraphAdjust_LEFT:
+ case style::ParagraphAdjust_BLOCK:
+ nTextAlign = awt::TextAlign::LEFT;
+ break;
+ case style::ParagraphAdjust_CENTER:
+ nTextAlign = awt::TextAlign::CENTER;
+ break;
+ case style::ParagraphAdjust_RIGHT:
+ nTextAlign = awt::TextAlign::RIGHT;
+ break;
+ default:
+ OSL_FAIL("Illegal text alignment value!");
+ break;
+ }
+ aRet <<= nTextAlign;
+ }
+ return aRet;
+ }
+ };
+}
+
+const TPropertyNamePair& getPropertyNameMap(SdrObjKind _nObjectId)
+{
+ switch(_nObjectId)
+ {
+ case SdrObjKind::ReportDesignImageControl:
+ {
+ static TPropertyNamePair s_aNameMap = []()
+ {
+ auto aNoConverter = std::make_shared<AnyConverter>();
+ TPropertyNamePair tmp;
+ tmp.emplace(PROPERTY_CONTROLBACKGROUND,TPropertyConverter(PROPERTY_BACKGROUNDCOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBORDER,TPropertyConverter(PROPERTY_BORDER,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBORDERCOLOR,TPropertyConverter(PROPERTY_BORDERCOLOR,aNoConverter));
+ return tmp;
+ }();
+ return s_aNameMap;
+ }
+
+ case SdrObjKind::ReportDesignFixedText:
+ {
+ static TPropertyNamePair s_aNameMap = []()
+ {
+ auto aNoConverter = std::make_shared<AnyConverter>();
+ TPropertyNamePair tmp;
+ tmp.emplace(PROPERTY_CHARCOLOR,TPropertyConverter(PROPERTY_TEXTCOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBACKGROUND,TPropertyConverter(PROPERTY_BACKGROUNDCOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CHARUNDERLINECOLOR,TPropertyConverter(PROPERTY_TEXTLINECOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CHARRELIEF,TPropertyConverter(PROPERTY_FONTRELIEF,aNoConverter));
+ tmp.emplace(PROPERTY_CHARFONTHEIGHT,TPropertyConverter(PROPERTY_FONTHEIGHT,aNoConverter));
+ tmp.emplace(PROPERTY_CHARSTRIKEOUT,TPropertyConverter(PROPERTY_FONTSTRIKEOUT,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLTEXTEMPHASISMARK,TPropertyConverter(PROPERTY_FONTEMPHASISMARK,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBORDER,TPropertyConverter(PROPERTY_BORDER,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBORDERCOLOR,TPropertyConverter(PROPERTY_BORDERCOLOR,aNoConverter));
+
+ auto aParaAdjust = std::make_shared<ParaAdjust>();
+ tmp.emplace(PROPERTY_PARAADJUST,TPropertyConverter(PROPERTY_ALIGN,aParaAdjust));
+ return tmp;
+ }();
+ return s_aNameMap;
+ }
+ case SdrObjKind::ReportDesignFormattedField:
+ {
+ static TPropertyNamePair s_aNameMap = []()
+ {
+ auto aNoConverter = std::make_shared<AnyConverter>();
+ TPropertyNamePair tmp;
+ tmp.emplace(PROPERTY_CHARCOLOR,TPropertyConverter(PROPERTY_TEXTCOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBACKGROUND,TPropertyConverter(PROPERTY_BACKGROUNDCOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CHARUNDERLINECOLOR,TPropertyConverter(PROPERTY_TEXTLINECOLOR,aNoConverter));
+ tmp.emplace(PROPERTY_CHARRELIEF,TPropertyConverter(PROPERTY_FONTRELIEF,aNoConverter));
+ tmp.emplace(PROPERTY_CHARFONTHEIGHT,TPropertyConverter(PROPERTY_FONTHEIGHT,aNoConverter));
+ tmp.emplace(PROPERTY_CHARSTRIKEOUT,TPropertyConverter(PROPERTY_FONTSTRIKEOUT,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLTEXTEMPHASISMARK,TPropertyConverter(PROPERTY_FONTEMPHASISMARK,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBORDER,TPropertyConverter(PROPERTY_BORDER,aNoConverter));
+ tmp.emplace(PROPERTY_CONTROLBORDERCOLOR,TPropertyConverter(PROPERTY_BORDERCOLOR,aNoConverter));
+ auto aParaAdjust = std::make_shared<ParaAdjust>();
+ tmp.emplace(PROPERTY_PARAADJUST,TPropertyConverter(PROPERTY_ALIGN,aParaAdjust));
+ return tmp;
+ }();
+ return s_aNameMap;
+ }
+
+ case SdrObjKind::CustomShape:
+ {
+ static TPropertyNamePair s_aNameMap = []()
+ {
+ auto aNoConverter = std::make_shared<AnyConverter>();
+ TPropertyNamePair tmp;
+ tmp.emplace(OUString("FillColor"),TPropertyConverter(PROPERTY_CONTROLBACKGROUND,aNoConverter));
+ tmp.emplace(PROPERTY_PARAADJUST,TPropertyConverter(PROPERTY_ALIGN,aNoConverter));
+ return tmp;
+ }();
+ return s_aNameMap;
+ }
+
+ default:
+ break;
+ }
+ static TPropertyNamePair s_aEmptyNameMap;
+ return s_aEmptyNameMap;
+}
+
+
+OObjectBase::OObjectBase(const uno::Reference< report::XReportComponent>& _xComponent)
+:m_bIsListening(false)
+{
+ m_xReportComponent = _xComponent;
+}
+
+OObjectBase::OObjectBase(const OUString& _sComponentName)
+:m_sComponentName(_sComponentName)
+,m_bIsListening(false)
+{
+}
+
+OObjectBase::~OObjectBase()
+{
+ m_xMediator.clear();
+ if ( isListening() )
+ EndListening();
+ m_xReportComponent.clear();
+}
+
+uno::Reference< report::XSection> OObjectBase::getSection() const
+{
+ uno::Reference< report::XSection> xSection;
+ OReportPage* pPage = dynamic_cast<OReportPage*>(GetImplPage());
+ if ( pPage )
+ xSection = pPage->getSection();
+ return xSection;
+}
+
+
+uno::Reference< beans::XPropertySet> OObjectBase::getAwtComponent()
+{
+ return uno::Reference< beans::XPropertySet>();
+}
+
+void OObjectBase::StartListening()
+{
+ OSL_ENSURE(!isListening(), "OUnoObject::StartListening: already listening!");
+
+ if ( !isListening() && m_xReportComponent.is() )
+ {
+ m_bIsListening = true;
+
+ if ( !m_xPropertyChangeListener.is() )
+ {
+ m_xPropertyChangeListener = new OObjectListener( this );
+ // register listener to all properties
+ m_xReportComponent->addPropertyChangeListener( OUString() , m_xPropertyChangeListener );
+ }
+ }
+}
+
+void OObjectBase::EndListening()
+{
+ OSL_ENSURE(!m_xReportComponent.is() || isListening(), "OUnoObject::EndListening: not listening currently!");
+
+ if ( isListening() && m_xReportComponent.is() )
+ {
+ // XPropertyChangeListener
+ if ( m_xPropertyChangeListener.is() )
+ {
+ // remove listener
+ try
+ {
+ m_xReportComponent->removePropertyChangeListener( OUString() , m_xPropertyChangeListener );
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION( "package", "OObjectBase::EndListening");
+ }
+ }
+ m_xPropertyChangeListener.clear();
+ }
+ m_bIsListening = false;
+}
+
+void OObjectBase::SetPropsFromRect(const tools::Rectangle& _rRect)
+{
+ // set properties
+ OReportPage* pPage = dynamic_cast<OReportPage*>(GetImplPage());
+ if ( pPage && !_rRect.IsEmpty() )
+ {
+ const uno::Reference<report::XSection>& xSection = pPage->getSection();
+ assert(_rRect.getHeight() >= 0);
+ const sal_uInt32 newHeight( ::std::max(tools::Long(0), _rRect.getHeight()+_rRect.Top()) );
+ if ( xSection.is() && ( newHeight > xSection->getHeight() ) )
+ xSection->setHeight( newHeight );
+
+ // TODO
+ //pModel->GetRefDevice()->Invalidate(InvalidateFlags::Children);
+ }
+}
+
+void OObjectBase::_propertyChange( const beans::PropertyChangeEvent& /*evt*/ )
+{
+}
+
+bool OObjectBase::supportsService( const OUString& _sServiceName ) const
+{
+ // TODO: cache xServiceInfo as member?
+ Reference< lang::XServiceInfo > xServiceInfo( m_xReportComponent , UNO_QUERY );
+
+ if ( xServiceInfo.is() )
+ return cppu::supportsService(xServiceInfo.get(), _sServiceName);
+ else
+ return false;
+}
+
+
+void OObjectBase::ensureSdrObjectOwnership( const uno::Reference< uno::XInterface >& _rxShape )
+{
+ // UNDO in the report designer is implemented at the level of the XShapes, not
+ // at the level of SdrObjects. That is, if an object is removed from the report
+ // design, then this happens by removing the XShape from the UNO DrawPage, and
+ // putting this XShape (resp. the ReportComponent which wraps it) into an UNDO
+ // action.
+ // Unfortunately, the SvxDrawPage implementation usually deletes SdrObjects
+ // which are removed from it, which is deadly for us. To prevent this,
+ // we give the XShape implementation the ownership of the SdrObject, which
+ // ensures the SvxDrawPage won't delete it.
+ SvxShape* pShape = comphelper::getFromUnoTunnel<SvxShape>( _rxShape );
+ OSL_ENSURE( pShape, "OObjectBase::ensureSdrObjectOwnership: can't access the SvxShape!" );
+ if ( pShape )
+ {
+ OSL_ENSURE( !pShape->HasSdrObjectOwnership(), "OObjectBase::ensureSdrObjectOwnership: called twice?" );
+ pShape->TakeSdrObjectOwnership();
+ }
+}
+
+
+uno::Reference< drawing::XShape > OObjectBase::getUnoShapeOf( SdrObject& _rSdrObject )
+{
+ uno::Reference< drawing::XShape > xShape( _rSdrObject.getWeakUnoShape() );
+ if ( xShape.is() )
+ return xShape;
+
+ xShape = _rSdrObject.SdrObject::getUnoShape();
+ if ( !xShape.is() )
+ return xShape;
+
+ ensureSdrObjectOwnership( xShape );
+
+ m_xKeepShapeAlive = xShape;
+ return xShape;
+}
+
+OCustomShape::OCustomShape(
+ SdrModel& rSdrModel,
+ const uno::Reference< report::XReportComponent>& _xComponent)
+: SdrObjCustomShape(rSdrModel)
+ ,OObjectBase(_xComponent)
+{
+ setUnoShape( uno::Reference< drawing::XShape >(_xComponent,uno::UNO_QUERY_THROW) );
+ m_bIsListening = true;
+}
+
+OCustomShape::OCustomShape(
+ SdrModel& rSdrModel,
+ const OUString& _sComponentName)
+: SdrObjCustomShape(rSdrModel)
+ ,OObjectBase(_sComponentName)
+{
+ m_bIsListening = true;
+}
+
+
+OCustomShape::~OCustomShape()
+{
+}
+
+SdrObjKind OCustomShape::GetObjIdentifier() const
+{
+ return SdrObjKind::CustomShape;
+}
+
+SdrInventor OCustomShape::GetObjInventor() const
+{
+ return SdrInventor::ReportDesign;
+}
+
+SdrPage* OCustomShape::GetImplPage() const
+{
+ return getSdrPageFromSdrObject();
+}
+
+void OCustomShape::NbcMove( const Size& rSize )
+{
+ if ( m_bIsListening )
+ {
+ m_bIsListening = false;
+
+ if ( m_xReportComponent.is() )
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+ m_xReportComponent->setPositionX(m_xReportComponent->getPositionX() + rSize.Width());
+ m_xReportComponent->setPositionY(m_xReportComponent->getPositionY() + rSize.Height());
+ }
+
+ // set geometry properties
+ SetPropsFromRect(GetSnapRect());
+
+ m_bIsListening = true;
+ }
+ else
+ SdrObjCustomShape::NbcMove( rSize );
+}
+
+void OCustomShape::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
+{
+ SdrObjCustomShape::NbcResize( rRef, xFract, yFract );
+
+ SetPropsFromRect(GetSnapRect());
+}
+
+void OCustomShape::NbcSetLogicRect(const tools::Rectangle& rRect)
+{
+ SdrObjCustomShape::NbcSetLogicRect(rRect);
+ SetPropsFromRect(rRect);
+}
+
+bool OCustomShape::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
+{
+ bool bResult = SdrObjCustomShape::EndCreate(rStat, eCmd);
+ if ( bResult )
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+
+ if ( !m_xReportComponent.is() )
+ m_xReportComponent.set(getUnoShape(),uno::UNO_QUERY);
+
+ SetPropsFromRect(GetSnapRect());
+ }
+
+ return bResult;
+}
+
+
+uno::Reference< beans::XPropertySet> OCustomShape::getAwtComponent()
+{
+ return m_xReportComponent;
+}
+
+
+uno::Reference< drawing::XShape > OCustomShape::getUnoShape()
+{
+ uno::Reference<drawing::XShape> xShape = OObjectBase::getUnoShapeOf( *this );
+ if ( !m_xReportComponent.is() )
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+ m_xReportComponent.set(xShape,uno::UNO_QUERY);
+ }
+ return xShape;
+}
+
+void OCustomShape::setUnoShape( const uno::Reference< drawing::XShape >& rxUnoShape )
+{
+ SdrObjCustomShape::setUnoShape( rxUnoShape );
+ releaseUnoShape();
+ m_xReportComponent.clear();
+}
+
+OUnoObject::OUnoObject(
+ SdrModel& rSdrModel,
+ const OUString& _sComponentName,
+ const OUString& rModelName,
+ SdrObjKind _nObjectType)
+: SdrUnoObj(rSdrModel, rModelName)
+ ,OObjectBase(_sComponentName)
+ ,m_nObjectType(_nObjectType)
+ // tdf#119067
+ ,m_bSetDefaultLabel(false)
+{
+ if ( !rModelName.isEmpty() )
+ impl_initializeModel_nothrow();
+}
+
+OUnoObject::OUnoObject(
+ SdrModel& rSdrModel, OUnoObject const & rSource)
+: SdrUnoObj(rSdrModel, rSource)
+ ,OObjectBase(rSource.getServiceName())
+ ,m_nObjectType(rSource.m_nObjectType)
+ // tdf#119067
+ ,m_bSetDefaultLabel(rSource.m_bSetDefaultLabel)
+{
+ if ( !rSource.getUnoControlModelTypeName().isEmpty() )
+ impl_initializeModel_nothrow();
+ Reference<XPropertySet> xSource(const_cast<OUnoObject&>(rSource).getUnoShape(), uno::UNO_QUERY);
+ Reference<XPropertySet> xDest(getUnoShape(), uno::UNO_QUERY);
+ if ( xSource.is() && xDest.is() )
+ comphelper::copyProperties(xSource, xDest);
+}
+
+OUnoObject::OUnoObject(
+ SdrModel& rSdrModel,
+ const uno::Reference< report::XReportComponent>& _xComponent,
+ const OUString& rModelName,
+ SdrObjKind _nObjectType)
+: SdrUnoObj(rSdrModel, rModelName)
+ ,OObjectBase(_xComponent)
+ ,m_nObjectType(_nObjectType)
+ // tdf#119067
+ ,m_bSetDefaultLabel(false)
+{
+ setUnoShape( uno::Reference< drawing::XShape >( _xComponent, uno::UNO_QUERY_THROW ) );
+
+ if ( !rModelName.isEmpty() )
+ impl_initializeModel_nothrow();
+
+}
+
+OUnoObject::~OUnoObject()
+{
+}
+
+void OUnoObject::impl_initializeModel_nothrow()
+{
+ try
+ {
+ Reference< XFormattedField > xFormatted( m_xReportComponent, UNO_QUERY );
+ if ( xFormatted.is() )
+ {
+ const Reference< XPropertySet > xModelProps( GetUnoControlModel(), UNO_QUERY_THROW );
+ xModelProps->setPropertyValue( "TreatAsNumber", Any( false ) );
+ xModelProps->setPropertyValue( PROPERTY_VERTICALALIGN,m_xReportComponent->getPropertyValue(PROPERTY_VERTICALALIGN));
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+}
+
+SdrObjKind OUnoObject::GetObjIdentifier() const
+{
+ return m_nObjectType;
+}
+
+SdrInventor OUnoObject::GetObjInventor() const
+{
+ return SdrInventor::ReportDesign;
+}
+
+SdrPage* OUnoObject::GetImplPage() const
+{
+ return getSdrPageFromSdrObject();
+}
+
+void OUnoObject::NbcMove( const Size& rSize )
+{
+
+ if ( m_bIsListening )
+ {
+ // stop listening
+ OObjectBase::EndListening();
+
+ bool bPositionFixed = false;
+ Size aUndoSize(0,0);
+ if ( m_xReportComponent.is() )
+ {
+ bool bUndoMode = false;
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+
+ if (rRptModel.GetUndoEnv().IsUndoMode())
+ {
+ // if we are locked from outside, then we must not handle wrong moves, we are in UNDO mode
+ bUndoMode = true;
+ }
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+
+ // LLA: why there exists getPositionX and getPositionY and NOT getPosition() which return a Point?
+ int nNewX = m_xReportComponent->getPositionX() + rSize.Width();
+ m_xReportComponent->setPositionX(nNewX);
+ int nNewY = m_xReportComponent->getPositionY() + rSize.Height();
+ if (nNewY < 0 && !bUndoMode)
+ {
+ aUndoSize.setHeight( abs(nNewY) );
+ bPositionFixed = true;
+ nNewY = 0;
+ }
+ m_xReportComponent->setPositionY(nNewY);
+ }
+ if (bPositionFixed)
+ {
+ getSdrModelFromSdrObject().AddUndo(getSdrModelFromSdrObject().GetSdrUndoFactory().CreateUndoMoveObject(*this, aUndoSize));
+ }
+ // set geometry properties
+ SetPropsFromRect(GetLogicRect());
+
+ // start listening
+ OObjectBase::StartListening();
+ }
+ else
+ SdrUnoObj::NbcMove( rSize );
+}
+
+
+void OUnoObject::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
+{
+ SdrUnoObj::NbcResize( rRef, xFract, yFract );
+
+ // stop listening
+ OObjectBase::EndListening();
+
+ // set geometry properties
+ SetPropsFromRect(GetLogicRect());
+
+ // start listening
+ OObjectBase::StartListening();
+}
+
+void OUnoObject::NbcSetLogicRect(const tools::Rectangle& rRect)
+{
+ SdrUnoObj::NbcSetLogicRect(rRect);
+ // stop listening
+ OObjectBase::EndListening();
+
+ // set geometry properties
+ SetPropsFromRect(rRect);
+
+ // start listening
+ OObjectBase::StartListening();
+}
+
+bool OUnoObject::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
+{
+ const bool bResult(SdrUnoObj::EndCreate(rStat, eCmd));
+
+ if(bResult)
+ {
+ // tdf#118730 remember if this object was created interactively (due to ::EndCreate being called)
+ m_bSetDefaultLabel = true;
+
+ // set geometry properties
+ SetPropsFromRect(GetLogicRect());
+ }
+
+ return bResult;
+}
+
+OUString OUnoObject::GetDefaultName(const OUnoObject* _pObj)
+{
+ OUString aDefaultName = "HERE WE HAVE TO INSERT OUR NAME!";
+ if ( _pObj->supportsService( SERVICE_FIXEDTEXT ) )
+ {
+ aDefaultName = RID_STR_CLASS_FIXEDTEXT;
+ }
+ else if ( _pObj->supportsService( SERVICE_FIXEDLINE ) )
+ {
+ aDefaultName = RID_STR_CLASS_FIXEDLINE;
+ }
+ else if ( _pObj->supportsService( SERVICE_IMAGECONTROL ) )
+ {
+ aDefaultName = RID_STR_CLASS_IMAGECONTROL;
+ }
+ else if ( _pObj->supportsService( SERVICE_FORMATTEDFIELD ) )
+ {
+ aDefaultName = RID_STR_CLASS_FORMATTEDFIELD;
+ }
+
+ return aDefaultName;
+}
+
+void OUnoObject::_propertyChange( const beans::PropertyChangeEvent& evt )
+{
+ OObjectBase::_propertyChange(evt);
+ if (!isListening())
+ return;
+
+ if ( evt.PropertyName == PROPERTY_CHARCOLOR )
+ {
+ Reference<XPropertySet> xControlModel(GetUnoControlModel(),uno::UNO_QUERY);
+ if ( xControlModel.is() )
+ {
+ OObjectBase::EndListening();
+ try
+ {
+ xControlModel->setPropertyValue(PROPERTY_TEXTCOLOR,evt.NewValue);
+ }
+ catch(uno::Exception&)
+ {
+ }
+ OObjectBase::StartListening();
+ }
+ }
+ else if ( evt.PropertyName == PROPERTY_NAME )
+ {
+ Reference<XPropertySet> xControlModel(GetUnoControlModel(),uno::UNO_QUERY);
+ if ( xControlModel.is() && xControlModel->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME) )
+ {
+ // get old name
+ OUString aOldName;
+ evt.OldValue >>= aOldName;
+
+ // get new name
+ OUString aNewName;
+ evt.NewValue >>= aNewName;
+
+ if ( aNewName != aOldName )
+ {
+ // set old name property
+ OObjectBase::EndListening();
+ if ( m_xMediator.is() )
+ m_xMediator->stopListening();
+ try
+ {
+ xControlModel->setPropertyValue( PROPERTY_NAME, evt.NewValue );
+ }
+ catch(uno::Exception&)
+ {
+ }
+ if ( m_xMediator.is() )
+ m_xMediator->startListening();
+ OObjectBase::StartListening();
+ }
+ }
+ }
+}
+
+void OUnoObject::CreateMediator(bool _bReverse)
+{
+ if ( m_xMediator.is() )
+ return;
+
+ // tdf#118730 Directly do things formerly done in
+ // OUnoObject::impl_setReportComponent_nothrow here
+ if(!m_xReportComponent.is())
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ OXUndoEnvironment::OUndoEnvLock aLock( rRptModel.GetUndoEnv() );
+ m_xReportComponent.set(getUnoShape(),uno::UNO_QUERY);
+
+ impl_initializeModel_nothrow();
+ }
+
+ if(m_xReportComponent.is() && m_bSetDefaultLabel)
+ {
+ // tdf#118730 Directly do things formerly done in
+ // OUnoObject::EndCreate here
+ // tdf#119067 ...but *only* if result of interactive
+ // creation in Report DesignView
+ m_bSetDefaultLabel = false;
+
+ try
+ {
+ if ( supportsService( SERVICE_FIXEDTEXT ) )
+ {
+ m_xReportComponent->setPropertyValue(
+ PROPERTY_LABEL,
+ uno::Any(GetDefaultName(this)));
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ }
+
+ if(!m_xMediator.is() && m_xReportComponent.is())
+ {
+ Reference<XPropertySet> xControlModel(GetUnoControlModel(),uno::UNO_QUERY);
+
+ if(xControlModel.is())
+ {
+ m_xMediator = new OPropertyMediator(
+ m_xReportComponent,
+ xControlModel,
+ TPropertyNamePair(getPropertyNameMap(GetObjIdentifier())),
+ _bReverse);
+ }
+ }
+
+ OObjectBase::StartListening();
+}
+
+uno::Reference< beans::XPropertySet> OUnoObject::getAwtComponent()
+{
+ return Reference<XPropertySet>(GetUnoControlModel(),uno::UNO_QUERY);
+}
+
+
+uno::Reference< drawing::XShape > OUnoObject::getUnoShape()
+{
+ return OObjectBase::getUnoShapeOf( *this );
+}
+
+void OUnoObject::setUnoShape( const uno::Reference< drawing::XShape >& rxUnoShape )
+{
+ SdrUnoObj::setUnoShape( rxUnoShape );
+ releaseUnoShape();
+}
+
+OUnoObject* OUnoObject::CloneSdrObject(SdrModel& rTargetModel) const
+{
+ return new OUnoObject(rTargetModel, *this);
+}
+
+// OOle2Obj
+OOle2Obj::OOle2Obj(
+ SdrModel& rSdrModel,
+ const uno::Reference< report::XReportComponent>& _xComponent,
+ SdrObjKind _nType)
+: SdrOle2Obj(rSdrModel)
+ ,OObjectBase(_xComponent)
+ ,m_nType(_nType)
+ ,m_bOnlyOnce(true)
+{
+ setUnoShape( uno::Reference< drawing::XShape >( _xComponent, uno::UNO_QUERY_THROW ) );
+ m_bIsListening = true;
+}
+
+OOle2Obj::OOle2Obj(
+ SdrModel& rSdrModel,
+ const OUString& _sComponentName,
+ SdrObjKind _nType)
+: SdrOle2Obj(rSdrModel)
+ ,OObjectBase(_sComponentName)
+ ,m_nType(_nType)
+ ,m_bOnlyOnce(true)
+{
+ m_bIsListening = true;
+}
+
+static uno::Reference< chart2::data::XDatabaseDataProvider > lcl_getDataProvider(const uno::Reference < embed::XEmbeddedObject >& _xObj);
+
+OOle2Obj::OOle2Obj(SdrModel& rSdrModel, OOle2Obj const & rSource)
+: SdrOle2Obj(rSdrModel, rSource)
+ ,OObjectBase(rSource.getServiceName())
+ ,m_nType(rSource.m_nType)
+ ,m_bOnlyOnce(rSource.m_bOnlyOnce)
+{
+ m_bIsListening = true;
+
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ svt::EmbeddedObjectRef::TryRunningState( GetObjRef() );
+ impl_createDataProvider_nothrow(rRptModel.getReportDefinition());
+
+ uno::Reference< chart2::data::XDatabaseDataProvider > xSource( lcl_getDataProvider(rSource.GetObjRef()) );
+ uno::Reference< chart2::data::XDatabaseDataProvider > xDest( lcl_getDataProvider(GetObjRef()) );
+ if ( xSource.is() && xDest.is() )
+ comphelper::copyProperties(xSource, xDest);
+
+ initializeChart(rRptModel.getReportDefinition());
+}
+
+OOle2Obj::~OOle2Obj()
+{
+}
+
+SdrObjKind OOle2Obj::GetObjIdentifier() const
+{
+ return m_nType;
+}
+
+SdrInventor OOle2Obj::GetObjInventor() const
+{
+ return SdrInventor::ReportDesign;
+}
+
+SdrPage* OOle2Obj::GetImplPage() const
+{
+ return getSdrPageFromSdrObject();
+}
+
+void OOle2Obj::NbcMove( const Size& rSize )
+{
+
+ if ( m_bIsListening )
+ {
+ // stop listening
+ OObjectBase::EndListening();
+
+ bool bPositionFixed = false;
+ Size aUndoSize(0,0);
+ if ( m_xReportComponent.is() )
+ {
+ bool bUndoMode = false;
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+
+ if (rRptModel.GetUndoEnv().IsUndoMode())
+ {
+ // if we are locked from outside, then we must not handle wrong moves, we are in UNDO mode
+ bUndoMode = true;
+ }
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+
+ // LLA: why there exists getPositionX and getPositionY and NOT getPosition() which return a Point?
+ int nNewX = m_xReportComponent->getPositionX() + rSize.Width();
+ // can this hinder us to set components outside the area?
+ // if (nNewX < 0)
+ // {
+ // nNewX = 0;
+ // }
+ m_xReportComponent->setPositionX(nNewX);
+ int nNewY = m_xReportComponent->getPositionY() + rSize.Height();
+ if (nNewY < 0 && !bUndoMode)
+ {
+ aUndoSize.setHeight( abs(nNewY) );
+ bPositionFixed = true;
+ nNewY = 0;
+ }
+ m_xReportComponent->setPositionY(nNewY);
+ }
+ if (bPositionFixed)
+ {
+ getSdrModelFromSdrObject().AddUndo(getSdrModelFromSdrObject().GetSdrUndoFactory().CreateUndoMoveObject(*this, aUndoSize));
+ }
+ // set geometry properties
+ SetPropsFromRect(GetLogicRect());
+
+ // start listening
+ OObjectBase::StartListening();
+ }
+ else
+ SdrOle2Obj::NbcMove( rSize );
+}
+
+
+void OOle2Obj::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
+{
+ SdrOle2Obj::NbcResize( rRef, xFract, yFract );
+
+ // stop listening
+ OObjectBase::EndListening();
+
+ // set geometry properties
+ SetPropsFromRect(GetLogicRect());
+
+ // start listening
+ OObjectBase::StartListening();
+}
+
+void OOle2Obj::NbcSetLogicRect(const tools::Rectangle& rRect)
+{
+ SdrOle2Obj::NbcSetLogicRect(rRect);
+ // stop listening
+ OObjectBase::EndListening();
+
+ // set geometry properties
+ SetPropsFromRect(rRect);
+
+ // start listening
+ OObjectBase::StartListening();
+}
+
+
+bool OOle2Obj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
+{
+ bool bResult = SdrOle2Obj::EndCreate(rStat, eCmd);
+ if ( bResult )
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+
+ if ( !m_xReportComponent.is() )
+ m_xReportComponent.set(getUnoShape(),uno::UNO_QUERY);
+
+ // set geometry properties
+ SetPropsFromRect(GetLogicRect());
+ }
+
+ return bResult;
+}
+
+uno::Reference< beans::XPropertySet> OOle2Obj::getAwtComponent()
+{
+ return m_xReportComponent;
+}
+
+
+uno::Reference< drawing::XShape > OOle2Obj::getUnoShape()
+{
+ uno::Reference< drawing::XShape> xShape = OObjectBase::getUnoShapeOf( *this );
+ if ( !m_xReportComponent.is() )
+ {
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv());
+ m_xReportComponent.set(xShape,uno::UNO_QUERY);
+ }
+ return xShape;
+}
+
+void OOle2Obj::setUnoShape( const uno::Reference< drawing::XShape >& rxUnoShape )
+{
+ SdrOle2Obj::setUnoShape( rxUnoShape );
+ releaseUnoShape();
+ m_xReportComponent.clear();
+}
+
+
+static uno::Reference< chart2::data::XDatabaseDataProvider > lcl_getDataProvider(const uno::Reference < embed::XEmbeddedObject >& _xObj)
+{
+ uno::Reference< chart2::data::XDatabaseDataProvider > xSource;
+ uno::Reference< embed::XComponentSupplier > xCompSupp(_xObj);
+ if( xCompSupp.is())
+ {
+ uno::Reference< chart2::XChartDocument> xChartDoc( xCompSupp->getComponent(), uno::UNO_QUERY );
+ if ( xChartDoc.is() )
+ {
+ xSource.set(xChartDoc->getDataProvider(),uno::UNO_QUERY);
+ }
+ }
+ return xSource;
+}
+
+// Clone() should make a complete copy of the object.
+OOle2Obj* OOle2Obj::CloneSdrObject(SdrModel& rTargetModel) const
+{
+ return new OOle2Obj(rTargetModel, *this);
+}
+
+void OOle2Obj::impl_createDataProvider_nothrow(const uno::Reference< frame::XModel>& _xModel)
+{
+ try
+ {
+ uno::Reference < embed::XEmbeddedObject > xObj = GetObjRef();
+ uno::Reference< chart2::data::XDataReceiver > xReceiver;
+ uno::Reference< embed::XComponentSupplier > xCompSupp( xObj );
+ if( xCompSupp.is())
+ xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
+ OSL_ASSERT( xReceiver.is());
+ if( xReceiver.is() )
+ {
+ uno::Reference< lang::XMultiServiceFactory> xFac(_xModel,uno::UNO_QUERY);
+ uno::Reference< chart2::data::XDatabaseDataProvider > xDataProvider( xFac->createInstance("com.sun.star.chart2.data.DataProvider"),uno::UNO_QUERY);
+ xReceiver->attachDataProvider( xDataProvider );
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ }
+}
+
+void OOle2Obj::initializeOle()
+{
+ if ( !m_bOnlyOnce )
+ return;
+
+ m_bOnlyOnce = false;
+ uno::Reference < embed::XEmbeddedObject > xObj = GetObjRef();
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ rRptModel.GetUndoEnv().AddElement(lcl_getDataProvider(xObj));
+
+ uno::Reference< embed::XComponentSupplier > xCompSupp( xObj );
+ if( xCompSupp.is() )
+ {
+ uno::Reference< beans::XPropertySet > xChartProps( xCompSupp->getComponent(), uno::UNO_QUERY );
+ if ( xChartProps.is() )
+ xChartProps->setPropertyValue("NullDate",
+ uno::Any(util::DateTime(0,0,0,0,30,12,1899,false)));
+ }
+}
+
+void OOle2Obj::initializeChart( const uno::Reference< frame::XModel>& _xModel)
+{
+ uno::Reference < embed::XEmbeddedObject > xObj = GetObjRef();
+ uno::Reference< chart2::data::XDataReceiver > xReceiver;
+ uno::Reference< embed::XComponentSupplier > xCompSupp( xObj );
+ if( xCompSupp.is())
+ xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
+ OSL_ASSERT( xReceiver.is());
+ if( !xReceiver.is() )
+ return;
+
+ // lock the model to suppress any internal updates
+ uno::Reference< frame::XModel > xChartModel( xReceiver, uno::UNO_QUERY );
+ if( xChartModel.is() )
+ xChartModel->lockControllers();
+
+ if ( !lcl_getDataProvider(xObj).is() )
+ impl_createDataProvider_nothrow(_xModel);
+
+ OReportModel& rRptModel(static_cast< OReportModel& >(getSdrModelFromSdrObject()));
+ rRptModel.GetUndoEnv().AddElement(lcl_getDataProvider(xObj));
+
+ ::comphelper::NamedValueCollection aArgs;
+ aArgs.put( "CellRangeRepresentation", uno::Any( OUString( "all" ) ) );
+ aArgs.put( "HasCategories", uno::Any( true ) );
+ aArgs.put( "FirstCellAsLabel", uno::Any( true ) );
+ aArgs.put( "DataRowSource", uno::Any( chart::ChartDataRowSource_COLUMNS ) );
+ xReceiver->setArguments( aArgs.getPropertyValues() );
+
+ if( xChartModel.is() )
+ xChartModel->unlockControllers();
+}
+
+uno::Reference< style::XStyle> getUsedStyle(const uno::Reference< report::XReportDefinition>& _xReport)
+{
+ uno::Reference<container::XNameAccess> xStyles = _xReport->getStyleFamilies();
+ uno::Reference<container::XNameAccess> xPageStyles(xStyles->getByName("PageStyles"),uno::UNO_QUERY);
+
+ uno::Reference< style::XStyle> xReturn;
+ const uno::Sequence< OUString> aSeq = xPageStyles->getElementNames();
+ for(const OUString& rName : aSeq)
+ {
+ uno::Reference< style::XStyle> xStyle(xPageStyles->getByName(rName),uno::UNO_QUERY);
+ if ( xStyle->isInUse() )
+ {
+ xReturn = xStyle;
+ break;
+ }
+ }
+ return xReturn;
+}
+
+
+} // rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/RptObjectListener.cxx b/reportdesign/source/core/sdr/RptObjectListener.cxx
new file mode 100644
index 000000000..0cc6a42b2
--- /dev/null
+++ b/reportdesign/source/core/sdr/RptObjectListener.cxx
@@ -0,0 +1,69 @@
+/* -*- 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 <RptObjectListener.hxx>
+#include <RptObject.hxx>
+
+namespace rptui
+{
+
+// OObjectListener
+
+
+OObjectListener::OObjectListener(OObjectBase* _pObject)
+ :m_pObject(_pObject)
+{
+}
+
+
+OObjectListener::~OObjectListener()
+{
+}
+
+// XEventListener
+
+
+void SAL_CALL OObjectListener::disposing( const css::lang::EventObject& )
+{
+}
+
+// XPropertyChangeListener
+
+
+void SAL_CALL OObjectListener::propertyChange( const css::beans::PropertyChangeEvent& evt )
+{
+ m_pObject->_propertyChange( evt );
+}
+
+
+// DlgEdHint
+
+
+DlgEdHint::DlgEdHint(DlgEdHintKind eHint)
+ : eHintKind(eHint)
+{
+}
+
+
+DlgEdHint::~DlgEdHint()
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/RptPage.cxx b/reportdesign/source/core/sdr/RptPage.cxx
new file mode 100644
index 000000000..1ad1cb8e1
--- /dev/null
+++ b/reportdesign/source/core/sdr/RptPage.cxx
@@ -0,0 +1,192 @@
+/* -*- 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 <RptPage.hxx>
+#include <RptModel.hxx>
+#include <Section.hxx>
+#include <RptObject.hxx>
+#include <ReportDrawPage.hxx>
+
+namespace rptui
+{
+using namespace ::com::sun::star;
+
+OReportPage::OReportPage(
+ OReportModel& _rModel,
+ const uno::Reference< report::XSection >& _xSection)
+: SdrPage(_rModel, false/*bMasterPage*/)
+ ,rModel(_rModel)
+ ,m_xSection(_xSection)
+ ,m_bSpecialInsertMode(false)
+{
+}
+
+OReportPage::~OReportPage()
+{
+}
+
+rtl::Reference<SdrPage> OReportPage::CloneSdrPage(SdrModel& rTargetModel) const
+{
+ OReportModel& rOReportModel(static_cast< OReportModel& >(rTargetModel));
+ rtl::Reference<OReportPage> pClonedOReportPage(
+ new OReportPage(
+ rOReportModel,
+ m_xSection));
+ pClonedOReportPage->SdrPage::lateInit(*this);
+ return pClonedOReportPage;
+}
+
+
+size_t OReportPage::getIndexOf(const uno::Reference< report::XReportComponent >& _xObject)
+{
+ const size_t nCount = GetObjCount();
+ size_t i = 0;
+ for (; i < nCount; ++i)
+ {
+ OObjectBase* pObj = dynamic_cast<OObjectBase*>(GetObj(i));
+ OSL_ENSURE(pObj,"Invalid object found!");
+ if ( pObj && pObj->getReportComponent() == _xObject )
+ {
+ break;
+ }
+ }
+ return i;
+}
+
+void OReportPage::removeSdrObject(const uno::Reference< report::XReportComponent >& _xObject)
+{
+ size_t nPos = getIndexOf(_xObject);
+ if ( nPos < GetObjCount() )
+ {
+ OObjectBase* pBase = dynamic_cast<OObjectBase*>(GetObj(nPos));
+ OSL_ENSURE(pBase,"Why is this not an OObjectBase?");
+ if ( pBase )
+ pBase->EndListening();
+ RemoveObject(nPos);
+ }
+}
+
+SdrObject* OReportPage::RemoveObject(size_t nObjNum)
+{
+ SdrObject* pObj = SdrPage::RemoveObject(nObjNum);
+ if (getSpecialMode())
+ {
+ return pObj;
+ }
+
+ // this code is evil, but what else shall I do
+ reportdesign::OSection* pSection = comphelper::getFromUnoTunnel<reportdesign::OSection>(m_xSection);
+ uno::Reference< drawing::XShape> xShape(pObj->getUnoShape(),uno::UNO_QUERY);
+ pSection->notifyElementRemoved(xShape);
+ if (dynamic_cast< const OUnoObject *>( pObj ) != nullptr)
+ {
+ OUnoObject& rUnoObj = dynamic_cast<OUnoObject&>(*pObj);
+ uno::Reference< container::XChild> xChild(rUnoObj.GetUnoControlModel(),uno::UNO_QUERY);
+ if ( xChild.is() )
+ xChild->setParent(nullptr);
+ }
+ return pObj;
+}
+
+void OReportPage::insertObject(const uno::Reference< report::XReportComponent >& _xObject)
+{
+ OSL_ENSURE(_xObject.is(),"Object is not valid to create a SdrObject!");
+ if ( !_xObject.is() )
+ return;
+ size_t nPos = getIndexOf(_xObject);
+ if ( nPos < GetObjCount() )
+ return; // Object already in list
+
+ OObjectBase* pObject = dynamic_cast< OObjectBase* >(SdrObject::getSdrObjectFromXShape( _xObject ));
+ OSL_ENSURE( pObject, "OReportPage::insertObject: no implementation object found for the given shape/component!" );
+ if ( pObject )
+ pObject->StartListening();
+}
+
+
+uno::Reference< uno::XInterface > OReportPage::createUnoPage()
+{
+ return static_cast<cppu::OWeakObject*>( new reportdesign::OReportDrawPage(this,m_xSection) );
+}
+
+void OReportPage::removeTempObject(SdrObject const *_pToRemoveObj)
+{
+ if (_pToRemoveObj)
+ {
+ for (size_t i=0; i<GetObjCount(); ++i)
+ {
+ SdrObject *aObj = GetObj(i);
+ if (aObj && aObj == _pToRemoveObj)
+ {
+ (void) RemoveObject(i);
+ break;
+ }
+ }
+ }
+}
+
+void OReportPage::resetSpecialMode()
+{
+ const bool bChanged = rModel.IsChanged();
+
+ for (const auto& pTemporaryObject : m_aTemporaryObjectList)
+ {
+ removeTempObject(pTemporaryObject);
+ }
+ m_aTemporaryObjectList.clear();
+ rModel.SetChanged(bChanged);
+
+ m_bSpecialInsertMode = false;
+}
+
+void OReportPage::NbcInsertObject(SdrObject* pObj, size_t nPos)
+{
+ SdrPage::NbcInsertObject(pObj, nPos);
+
+ OUnoObject* pUnoObj = dynamic_cast< OUnoObject* >( pObj );
+ if (getSpecialMode())
+ {
+ m_aTemporaryObjectList.push_back(pObj);
+ return;
+ }
+
+ if ( pUnoObj )
+ {
+ pUnoObj->CreateMediator();
+ uno::Reference< container::XChild> xChild(pUnoObj->GetUnoControlModel(),uno::UNO_QUERY);
+ if ( xChild.is() && !xChild->getParent().is() )
+ xChild->setParent(m_xSection);
+ }
+
+ // this code is evil, but what else shall I do
+ reportdesign::OSection* pSection = comphelper::getFromUnoTunnel<reportdesign::OSection>(m_xSection);
+ uno::Reference< drawing::XShape> xShape(pObj->getUnoShape(),uno::UNO_QUERY);
+ pSection->notifyElementAdded(xShape);
+
+ // now that the shape is inserted into its structures, we can allow the OObjectBase
+ // to release the reference to it
+ OObjectBase* pObjectBase = dynamic_cast< OObjectBase* >( pObj );
+ OSL_ENSURE( pObjectBase, "OReportPage::NbcInsertObject: what is being inserted here?" );
+ if ( pObjectBase )
+ pObjectBase->releaseUnoShape();
+}
+
+} // rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/UndoActions.cxx b/reportdesign/source/core/sdr/UndoActions.cxx
new file mode 100644
index 000000000..78d59e541
--- /dev/null
+++ b/reportdesign/source/core/sdr/UndoActions.cxx
@@ -0,0 +1,407 @@
+/* -*- 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 <UndoActions.hxx>
+#include <UndoEnv.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <RptModel.hxx>
+
+#include <com/sun/star/container/XChild.hpp>
+
+#include <comphelper/types.hxx>
+#include <tools/diagnose_ex.h>
+#include <utility>
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+#include <svx/unoshape.hxx>
+
+namespace rptui
+{
+ using namespace ::com::sun::star;
+ using namespace uno;
+ using namespace lang;
+ using namespace script;
+ using namespace beans;
+ using namespace awt;
+ using namespace util;
+ using namespace container;
+ using namespace report;
+
+::std::function<uno::Reference<report::XSection>(OGroupHelper *)> OGroupHelper::getMemberFunction(const Reference< XSection >& _xSection)
+{
+ ::std::function<uno::Reference<report::XSection>(OGroupHelper *)> pMemFunSection = ::std::mem_fn(&OGroupHelper::getFooter);
+ uno::Reference< report::XGroup> xGroup = _xSection->getGroup();
+ if ( xGroup->getHeaderOn() && xGroup->getHeader() == _xSection )
+ pMemFunSection = ::std::mem_fn(&OGroupHelper::getHeader);
+ return pMemFunSection;
+}
+
+::std::function<uno::Reference<report::XSection>(OReportHelper *)> OReportHelper::getMemberFunction(const Reference< XSection >& _xSection)
+{
+ uno::Reference< report::XReportDefinition> xReportDefinition(_xSection->getReportDefinition());
+ ::std::function<uno::Reference<report::XSection>(OReportHelper *)> pMemFunSection = ::std::mem_fn(&OReportHelper::getReportFooter);
+ if ( xReportDefinition->getReportHeaderOn() && xReportDefinition->getReportHeader() == _xSection )
+ pMemFunSection = ::std::mem_fn(&OReportHelper::getReportHeader);
+ else if ( xReportDefinition->getPageHeaderOn() && xReportDefinition->getPageHeader() == _xSection )
+ pMemFunSection = ::std::mem_fn(&OReportHelper::getPageHeader);
+ else if ( xReportDefinition->getPageFooterOn() && xReportDefinition->getPageFooter() == _xSection )
+ pMemFunSection = ::std::mem_fn(&OReportHelper::getPageFooter);
+ else if ( xReportDefinition->getDetail() == _xSection )
+ pMemFunSection = ::std::mem_fn(&OReportHelper::getDetail);
+ return pMemFunSection;
+}
+
+
+OCommentUndoAction::OCommentUndoAction(SdrModel& _rMod, TranslateId pCommentID)
+ :SdrUndoAction(_rMod)
+{
+ m_pController = static_cast< OReportModel& >( _rMod ).getController();
+ if (pCommentID)
+ m_strComment = RptResId(pCommentID);
+}
+OCommentUndoAction::~OCommentUndoAction()
+{
+}
+
+void OCommentUndoAction::Undo()
+{
+}
+
+void OCommentUndoAction::Redo()
+{
+}
+
+OUndoContainerAction::OUndoContainerAction(SdrModel& _rMod
+ ,Action _eAction
+ ,const uno::Reference< container::XIndexContainer >& rContainer
+ ,const Reference< XInterface > & xElem
+ ,TranslateId pCommentId)
+ :OCommentUndoAction(_rMod, pCommentId)
+ ,m_xElement(xElem)
+ ,m_xContainer(rContainer)
+ ,m_eAction( _eAction )
+{
+ // normalize
+ if ( m_eAction == Removed )
+ // we now own the element
+ m_xOwnElement = m_xElement;
+}
+
+OUndoContainerAction::~OUndoContainerAction()
+{
+ // if we own the object...
+ Reference< XComponent > xComp( m_xOwnElement, UNO_QUERY );
+ if ( !xComp.is() )
+ return;
+
+ // and the object does not have a parent
+ Reference< XChild > xChild( m_xOwnElement, UNO_QUERY );
+ if ( !xChild.is() || xChild->getParent().is() )
+ return;
+
+ OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
+ rEnv.RemoveElement( m_xOwnElement );
+
+#if OSL_DEBUG_LEVEL > 0
+ SvxShape* pShape = comphelper::getFromUnoTunnel<SvxShape>( xChild );
+ SdrObject* pObject = pShape ? pShape->GetSdrObject() : nullptr;
+ OSL_ENSURE( pObject == nullptr || (pShape->HasSdrObjectOwnership() && !pObject->IsInserted()),
+ "OUndoContainerAction::~OUndoContainerAction: inconsistency in the shape/object ownership!" );
+#endif
+ // -> dispose it
+ try
+ {
+ comphelper::disposeComponent( xComp );
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+}
+
+void OUndoContainerAction::implReInsert( )
+{
+ if ( m_xContainer.is() )
+ {
+ // insert the element
+ m_xContainer->insertByIndex( m_xContainer->getCount(),uno::Any(m_xElement) );
+ }
+ // we don't own the object anymore
+ m_xOwnElement = nullptr;
+}
+
+
+void OUndoContainerAction::implReRemove( )
+{
+ OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
+ try
+ {
+ OXUndoEnvironment::OUndoEnvLock aLock(rEnv);
+ if ( m_xContainer.is() )
+ {
+ const sal_Int32 nCount = m_xContainer->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference< uno::XInterface> xObj(m_xContainer->getByIndex(i),uno::UNO_QUERY);
+ if ( xObj == m_xElement )
+ {
+ m_xContainer->removeByIndex( i );
+ break;
+ }
+ }
+ }
+ }
+ catch(uno::Exception&){}
+ // from now on, we own this object
+ m_xOwnElement = m_xElement;
+}
+
+
+void OUndoContainerAction::Undo()
+{
+ if ( !m_xElement.is() )
+ return;
+
+ // prevents that an undo action will be created for elementInserted
+ try
+ {
+ switch ( m_eAction )
+ {
+ case Inserted:
+ implReRemove();
+ break;
+
+ case Removed:
+ implReInsert();
+ break;
+ default:
+ OSL_FAIL("Illegal case value");
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "reportdesign", "OUndoContainerAction::Undo" );
+ }
+}
+
+
+void OUndoContainerAction::Redo()
+{
+ if ( !m_xElement.is() )
+ return;
+
+ try
+ {
+ switch ( m_eAction )
+ {
+ case Inserted:
+ implReInsert();
+ break;
+
+ case Removed:
+ implReRemove();
+ break;
+ default:
+ OSL_FAIL("Illegal case value");
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "reportdesign", "OUndoContainerAction::Redo" );
+ }
+}
+
+OUndoGroupSectionAction::OUndoGroupSectionAction(
+ SdrModel& _rMod, Action _eAction,
+ ::std::function<uno::Reference<report::XSection>(OGroupHelper*)> _pMemberFunction,
+ const uno::Reference<report::XGroup>& _xGroup, const Reference<XInterface>& xElem,
+ TranslateId pCommentId)
+ : OUndoContainerAction(_rMod, _eAction, nullptr, xElem, pCommentId)
+ , m_aGroupHelper(_xGroup)
+ , m_pMemberFunction(std::move(_pMemberFunction))
+{
+}
+
+void OUndoGroupSectionAction::implReInsert( )
+{
+ OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
+ try
+ {
+ OXUndoEnvironment::OUndoEnvLock aLock(rEnv);
+ uno::Reference< report::XSection> xSection = m_pMemberFunction(&m_aGroupHelper);
+ if ( xSection.is() )
+ xSection->add(uno::Reference< drawing::XShape>(m_xElement,uno::UNO_QUERY));
+ }
+ catch(uno::Exception&){}
+
+ // we don't own the object anymore
+ m_xOwnElement = nullptr;
+}
+
+
+void OUndoGroupSectionAction::implReRemove( )
+{
+ OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
+ try
+ {
+ OXUndoEnvironment::OUndoEnvLock aLock(rEnv);
+ uno::Reference< report::XSection> xSection = m_pMemberFunction(&m_aGroupHelper);
+ if ( xSection.is() )
+ xSection->remove(uno::Reference< drawing::XShape>(m_xElement,uno::UNO_QUERY));
+ }
+ catch(uno::Exception&){}
+
+ // from now on, we own this object
+ m_xOwnElement = m_xElement;
+}
+
+OUndoReportSectionAction::OUndoReportSectionAction(
+ SdrModel& _rMod, Action _eAction,
+ ::std::function<uno::Reference<report::XSection>(OReportHelper*)> _pMemberFunction,
+ const uno::Reference<report::XReportDefinition>& _xReport, const Reference<XInterface>& xElem,
+ TranslateId pCommentId)
+ : OUndoContainerAction(_rMod, _eAction, nullptr, xElem, pCommentId)
+ , m_aReportHelper(_xReport)
+ , m_pMemberFunction(std::move(_pMemberFunction))
+{
+}
+
+void OUndoReportSectionAction::implReInsert( )
+{
+ OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
+ try
+ {
+ OXUndoEnvironment::OUndoEnvLock aLock(rEnv);
+ uno::Reference< report::XSection> xSection = m_pMemberFunction(&m_aReportHelper);
+ if ( xSection.is() )
+ {
+ uno::Reference< drawing::XShape> xShape(m_xElement,uno::UNO_QUERY_THROW);
+ awt::Point aPos = xShape->getPosition();
+ awt::Size aSize = xShape->getSize();
+ xSection->add(xShape);
+ xShape->setPosition( aPos );
+ xShape->setSize( aSize );
+ }
+ }
+ catch(uno::Exception&){}
+ // we don't own the object anymore
+ m_xOwnElement = nullptr;
+}
+
+
+void OUndoReportSectionAction::implReRemove( )
+{
+ OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
+ try
+ {
+ OXUndoEnvironment::OUndoEnvLock aLock(rEnv);
+ uno::Reference< report::XSection> xSection = m_pMemberFunction(&m_aReportHelper);
+ if ( xSection.is() )
+ xSection->remove(uno::Reference< drawing::XShape>(m_xElement,uno::UNO_QUERY));
+ }
+ catch(uno::Exception&){}
+ // from now on, we own this object
+ m_xOwnElement = m_xElement;
+}
+
+ORptUndoPropertyAction::ORptUndoPropertyAction(SdrModel& rNewMod, const PropertyChangeEvent& evt)
+ :OCommentUndoAction(rNewMod,{})
+ ,m_xObj(evt.Source, UNO_QUERY)
+ ,m_aPropertyName(evt.PropertyName)
+ ,m_aNewValue(evt.NewValue)
+ ,m_aOldValue(evt.OldValue)
+{
+}
+
+void ORptUndoPropertyAction::Undo()
+{
+ setProperty(true);
+}
+
+
+void ORptUndoPropertyAction::Redo()
+{
+ setProperty(false);
+}
+
+Reference< XPropertySet> ORptUndoPropertyAction::getObject()
+{
+ return m_xObj;
+}
+
+void ORptUndoPropertyAction::setProperty(bool _bOld)
+{
+ Reference< XPropertySet> xObj = getObject();
+
+ if (xObj.is() )
+ {
+ try
+ {
+ xObj->setPropertyValue( m_aPropertyName, _bOld ? m_aOldValue : m_aNewValue );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "reportdesign", "ORptUndoPropertyAction::Redo" );
+ }
+ }
+}
+
+OUString ORptUndoPropertyAction::GetComment() const
+{
+ OUString aStr( RptResId(RID_STR_UNDO_PROPERTY) );
+
+ return aStr.replaceFirst("#", m_aPropertyName);
+}
+
+OUndoPropertyGroupSectionAction::OUndoPropertyGroupSectionAction(
+ SdrModel& _rMod, const PropertyChangeEvent& evt,
+ ::std::function<uno::Reference<report::XSection>(OGroupHelper*)> _pMemberFunction,
+ const uno::Reference<report::XGroup>& _xGroup)
+ : ORptUndoPropertyAction(_rMod, evt)
+ , m_aGroupHelper(_xGroup)
+ , m_pMemberFunction(std::move(_pMemberFunction))
+{
+}
+
+Reference< XPropertySet> OUndoPropertyGroupSectionAction::getObject()
+{
+ return m_pMemberFunction(&m_aGroupHelper);
+}
+
+OUndoPropertyReportSectionAction::OUndoPropertyReportSectionAction(
+ SdrModel& _rMod, const PropertyChangeEvent& evt,
+ ::std::function<uno::Reference<report::XSection>(OReportHelper*)> _pMemberFunction,
+ const uno::Reference<report::XReportDefinition>& _xReport)
+ : ORptUndoPropertyAction(_rMod, evt)
+ , m_aReportHelper(_xReport)
+ , m_pMemberFunction(std::move(_pMemberFunction))
+{
+}
+
+Reference< XPropertySet> OUndoPropertyReportSectionAction::getObject()
+{
+ return m_pMemberFunction(&m_aReportHelper);
+}
+
+} // rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/UndoEnv.cxx b/reportdesign/source/core/sdr/UndoEnv.cxx
new file mode 100644
index 000000000..2585d4a20
--- /dev/null
+++ b/reportdesign/source/core/sdr/UndoEnv.cxx
@@ -0,0 +1,619 @@
+/* -*- 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 <UndoActions.hxx>
+#include <UndoEnv.hxx>
+#include "formatnormalizer.hxx"
+#include <conditionupdater.hxx>
+#include <RptPage.hxx>
+#include <strings.hrc>
+#include <RptModel.hxx>
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/beans/theIntrospection.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/beans/XIntrospectionAccess.hpp>
+#include <com/sun/star/beans/XIntrospection.hpp>
+
+#include <svl/hint.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+#include <osl/mutex.hxx>
+
+#include <unordered_map>
+
+namespace rptui
+{
+ using namespace ::com::sun::star;
+ using namespace uno;
+ using namespace lang;
+ using namespace script;
+ using namespace beans;
+ using namespace awt;
+ using namespace util;
+ using namespace container;
+ using namespace report;
+
+namespace {
+
+struct PropertyInfo
+{
+ bool bIsReadonlyOrTransient;
+
+ explicit PropertyInfo( const bool i_bIsTransientOrReadOnly )
+ :bIsReadonlyOrTransient( i_bIsTransientOrReadOnly )
+ {
+ }
+};
+
+}
+
+typedef std::unordered_map< OUString, PropertyInfo > PropertiesInfo;
+
+namespace {
+
+struct ObjectInfo
+{
+ PropertiesInfo aProperties;
+ Reference< XPropertySet > xPropertyIntrospection;
+
+ ObjectInfo()
+ {
+ }
+};
+
+}
+
+typedef ::std::map< Reference< XPropertySet >, ObjectInfo > PropertySetInfoCache;
+
+
+class OXUndoEnvironmentImpl
+{
+public:
+ OReportModel& m_rModel;
+ PropertySetInfoCache m_aPropertySetCache;
+ FormatNormalizer m_aFormatNormalizer;
+ ConditionUpdater m_aConditionUpdater;
+ ::osl::Mutex m_aMutex;
+ ::std::vector< uno::Reference< container::XChild> > m_aSections;
+ Reference< XIntrospection > m_xIntrospection;
+ oslInterlockedCount m_nLocks;
+ bool m_bReadOnly;
+ bool m_bIsUndo;
+
+ explicit OXUndoEnvironmentImpl(OReportModel& _rModel);
+ OXUndoEnvironmentImpl(const OXUndoEnvironmentImpl&) = delete;
+ OXUndoEnvironmentImpl& operator=(const OXUndoEnvironmentImpl&) = delete;
+};
+
+OXUndoEnvironmentImpl::OXUndoEnvironmentImpl(OReportModel& _rModel) : m_rModel(_rModel)
+ ,m_aFormatNormalizer( _rModel )
+ ,m_nLocks(0)
+ ,m_bReadOnly(false)
+ ,m_bIsUndo(false)
+{
+}
+
+
+OXUndoEnvironment::OXUndoEnvironment(OReportModel& _rModel)
+ :m_pImpl(new OXUndoEnvironmentImpl(_rModel) )
+{
+ StartListening(m_pImpl->m_rModel);
+}
+
+
+OXUndoEnvironment::~OXUndoEnvironment()
+{
+}
+
+void OXUndoEnvironment::Lock()
+{
+ OSL_ENSURE(m_refCount,"Illegal call to dead object!");
+ osl_atomic_increment( &m_pImpl->m_nLocks );
+}
+void OXUndoEnvironment::UnLock()
+{
+ OSL_ENSURE(m_refCount,"Illegal call to dead object!");
+
+ osl_atomic_decrement( &m_pImpl->m_nLocks );
+}
+bool OXUndoEnvironment::IsLocked() const { return m_pImpl->m_nLocks != 0; }
+
+void OXUndoEnvironment::RemoveSection(OReportPage const * _pPage)
+{
+ if ( _pPage )
+ {
+ Reference< XInterface > xSection(_pPage->getSection());
+ if ( xSection.is() )
+ RemoveElement( xSection );
+ }
+}
+
+void OXUndoEnvironment::Clear(const Accessor& /*_r*/)
+{
+ OUndoEnvLock aLock(*this);
+
+ m_pImpl->m_aPropertySetCache.clear();
+
+ sal_uInt16 nCount = m_pImpl->m_rModel.GetPageCount();
+ sal_uInt16 i;
+ for (i = 0; i < nCount; i++)
+ {
+ OReportPage* pPage = dynamic_cast<OReportPage*>( m_pImpl->m_rModel.GetPage(i) );
+ RemoveSection(pPage);
+ }
+
+ nCount = m_pImpl->m_rModel.GetMasterPageCount();
+ for (i = 0; i < nCount; i++)
+ {
+ OReportPage* pPage = dynamic_cast<OReportPage*>( m_pImpl->m_rModel.GetMasterPage(i) );
+ RemoveSection(pPage);
+ }
+
+ m_pImpl->m_aSections.clear();
+
+ if (IsListening(m_pImpl->m_rModel))
+ EndListening(m_pImpl->m_rModel);
+}
+
+
+void OXUndoEnvironment::ModeChanged()
+{
+ m_pImpl->m_bReadOnly = !m_pImpl->m_bReadOnly;
+
+ if (!m_pImpl->m_bReadOnly)
+ StartListening(m_pImpl->m_rModel);
+ else
+ EndListening(m_pImpl->m_rModel);
+}
+
+
+void OXUndoEnvironment::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ if (rHint.GetId() == SfxHintId::ModeChanged )
+ ModeChanged();
+}
+
+// XEventListener
+
+void SAL_CALL OXUndoEnvironment::disposing(const EventObject& e)
+{
+ // check if it's an object we have cached information about
+ Reference< XPropertySet > xSourceSet(e.Source, UNO_QUERY);
+ if ( xSourceSet.is() )
+ {
+ uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY);
+ if ( xSection.is() )
+ RemoveSection(xSection);
+ else
+ RemoveElement(xSourceSet);
+ }
+}
+
+// XPropertyChangeListener
+
+void SAL_CALL OXUndoEnvironment::propertyChange( const PropertyChangeEvent& _rEvent )
+{
+
+ ::osl::ClearableMutexGuard aGuard( m_pImpl->m_aMutex );
+
+ if ( IsLocked() )
+ return;
+
+ Reference< XPropertySet > xSet( _rEvent.Source, UNO_QUERY );
+ if (!xSet.is())
+ return;
+
+ dbaui::DBSubComponentController* pController = m_pImpl->m_rModel.getController();
+ if ( !pController )
+ return;
+
+ // no Undo for transient and readonly props.
+ // let's see if we know something about the set
+ PropertySetInfoCache::iterator objectPos = m_pImpl->m_aPropertySetCache.find(xSet);
+ if (objectPos == m_pImpl->m_aPropertySetCache.end())
+ {
+ objectPos = m_pImpl->m_aPropertySetCache.emplace( xSet, ObjectInfo() ).first;
+ DBG_ASSERT(objectPos != m_pImpl->m_aPropertySetCache.end(), "OXUndoEnvironment::propertyChange : just inserted it... why it's not there?");
+ }
+ if ( objectPos == m_pImpl->m_aPropertySetCache.end() )
+ return;
+
+ // now we have access to the cached info about the set
+ // let's see what we know about the property
+ ObjectInfo& rObjectInfo = objectPos->second;
+ PropertiesInfo::const_iterator aPropertyPos = rObjectInfo.aProperties.find( _rEvent.PropertyName );
+ if ( aPropertyPos == rObjectInfo.aProperties.end() )
+ { // nothing 'til now... have to change this...
+ // the attributes
+ Reference< XPropertySetInfo > xPSI( xSet->getPropertySetInfo(), UNO_SET_THROW );
+ sal_Int32 nPropertyAttributes = 0;
+ try
+ {
+ if ( xPSI->hasPropertyByName( _rEvent.PropertyName ) )
+ {
+ nPropertyAttributes = xPSI->getPropertyByName( _rEvent.PropertyName ).Attributes;
+ }
+ else
+ {
+ // it's perfectly valid for a component to notify a change in a property which it doesn't have - as long
+ // as it has an attribute with this name
+ if ( !rObjectInfo.xPropertyIntrospection.is() )
+ {
+ if ( !m_pImpl->m_xIntrospection.is() )
+ {
+ m_pImpl->m_xIntrospection = theIntrospection::get( m_pImpl->m_rModel.getController()->getORB() );
+ }
+ Reference< XIntrospectionAccess > xIntrospection(
+ m_pImpl->m_xIntrospection->inspect( Any( _rEvent.Source ) ),
+ UNO_SET_THROW
+ );
+ rObjectInfo.xPropertyIntrospection.set( xIntrospection->queryAdapter( cppu::UnoType<XPropertySet>::get() ), UNO_QUERY_THROW );
+ }
+ if ( rObjectInfo.xPropertyIntrospection.is() )
+ {
+ xPSI.set( rObjectInfo.xPropertyIntrospection->getPropertySetInfo(), UNO_SET_THROW );
+ nPropertyAttributes = xPSI->getPropertyByName( _rEvent.PropertyName ).Attributes;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ const bool bTransReadOnly =
+ ( ( nPropertyAttributes & PropertyAttribute::READONLY ) != 0 )
+ || ( ( nPropertyAttributes & PropertyAttribute::TRANSIENT ) != 0 );
+
+ // insert the new entry
+ aPropertyPos = rObjectInfo.aProperties.emplace(
+ _rEvent.PropertyName,
+ PropertyInfo( bTransReadOnly )
+ ).first;
+ DBG_ASSERT(aPropertyPos != rObjectInfo.aProperties.end(), "OXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
+ }
+
+ implSetModified();
+
+ // now we have access to the cached info about the property affected
+ // and are able to decide whether or not we need an undo action
+
+ // no UNDO for transient/readonly properties
+ if ( aPropertyPos->second.bIsReadonlyOrTransient )
+ return;
+
+ // give components with sub responsibilities a chance
+ m_pImpl->m_aFormatNormalizer.notifyPropertyChange( _rEvent );
+ m_pImpl->m_aConditionUpdater.notifyPropertyChange( _rEvent );
+
+ aGuard.clear();
+ // TODO: this is a potential race condition: two threads here could in theory
+ // add their undo actions out-of-order
+
+ SolarMutexGuard aSolarGuard;
+ std::unique_ptr<ORptUndoPropertyAction> pUndo;
+ try
+ {
+ uno::Reference< report::XSection> xSection( xSet, uno::UNO_QUERY );
+ if ( xSection.is() )
+ {
+ uno::Reference< report::XGroup> xGroup = xSection->getGroup();
+ if ( xGroup.is() )
+ pUndo.reset(new OUndoPropertyGroupSectionAction( m_pImpl->m_rModel, _rEvent, OGroupHelper::getMemberFunction( xSection ), xGroup ));
+ else
+ pUndo.reset(new OUndoPropertyReportSectionAction( m_pImpl->m_rModel, _rEvent, OReportHelper::getMemberFunction( xSection ), xSection->getReportDefinition() ));
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+
+ if ( pUndo == nullptr )
+ pUndo.reset(new ORptUndoPropertyAction( m_pImpl->m_rModel, _rEvent ));
+
+ m_pImpl->m_rModel.GetSdrUndoManager()->AddUndoAction( std::move(pUndo) );
+ pController->InvalidateAll();
+}
+
+::std::vector< uno::Reference< container::XChild> >::const_iterator OXUndoEnvironment::getSection(const Reference<container::XChild>& _xContainer) const
+{
+ ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = m_pImpl->m_aSections.end();
+ if ( _xContainer.is() )
+ {
+ aFind = ::std::find(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),_xContainer);
+
+ if ( aFind == m_pImpl->m_aSections.end() )
+ {
+ Reference<container::XChild> xParent(_xContainer->getParent(),uno::UNO_QUERY);
+ aFind = getSection(xParent);
+ }
+ }
+ return aFind;
+}
+// XContainerListener
+
+void SAL_CALL OXUndoEnvironment::elementInserted(const ContainerEvent& evt)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
+
+ // new listener object
+ Reference< uno::XInterface > xIface( evt.Element, UNO_QUERY );
+ if ( !IsLocked() )
+ {
+ Reference< report::XReportComponent > xReportComponent( xIface, UNO_QUERY );
+ if ( xReportComponent.is() )
+ {
+ Reference< report::XSection > xContainer(evt.Source,uno::UNO_QUERY);
+
+ ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = getSection(xContainer);
+
+ if ( aFind != m_pImpl->m_aSections.end() )
+ {
+ OUndoEnvLock aLock(*this);
+ try
+ {
+ OReportPage* pPage = m_pImpl->m_rModel.getPage(uno::Reference< report::XSection>(*aFind,uno::UNO_QUERY));
+ OSL_ENSURE(pPage,"No page could be found for section!");
+ if ( pPage )
+ pPage->insertObject(xReportComponent);
+ }
+ catch(uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+
+ }
+ }
+ else
+ {
+ uno::Reference< report::XFunctions> xContainer(evt.Source,uno::UNO_QUERY);
+ if ( xContainer.is() )
+ {
+ m_pImpl->m_rModel.GetSdrUndoManager()->AddUndoAction(
+ std::make_unique<OUndoContainerAction>( m_pImpl->m_rModel, rptui::Inserted, xContainer.get(),
+ xIface, RID_STR_UNDO_ADDFUNCTION ) );
+ }
+ }
+ }
+
+ AddElement(xIface);
+
+ implSetModified();
+}
+
+
+void OXUndoEnvironment::implSetModified()
+{
+ m_pImpl->m_rModel.SetModified( true );
+}
+
+
+void SAL_CALL OXUndoEnvironment::elementReplaced(const ContainerEvent& evt)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
+
+ Reference< XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY);
+ OSL_ENSURE(xIface.is(), "OXUndoEnvironment::elementReplaced: invalid container notification!");
+ RemoveElement(xIface);
+
+ xIface.set(evt.Element,uno::UNO_QUERY);
+ AddElement(xIface);
+
+ implSetModified();
+}
+
+
+void SAL_CALL OXUndoEnvironment::elementRemoved(const ContainerEvent& evt)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
+
+ Reference< uno::XInterface > xIface( evt.Element, UNO_QUERY );
+ if ( !IsLocked() )
+ {
+ Reference< report::XSection > xContainer(evt.Source,uno::UNO_QUERY);
+ ::std::vector< uno::Reference< container::XChild> >::const_iterator aFind = getSection(xContainer);
+
+ Reference< report::XReportComponent > xReportComponent( xIface, UNO_QUERY );
+ if ( aFind != m_pImpl->m_aSections.end() && xReportComponent.is() )
+ {
+ OXUndoEnvironment::OUndoEnvLock aLock(*this);
+ try
+ {
+ OReportPage* pPage = m_pImpl->m_rModel.getPage(uno::Reference< report::XSection >( *aFind, uno::UNO_QUERY_THROW ) );
+ OSL_ENSURE( pPage, "OXUndoEnvironment::elementRemoved: no page for the section!" );
+ if ( pPage )
+ pPage->removeSdrObject(xReportComponent);
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ }
+ else
+ {
+ uno::Reference< report::XFunctions> xFunctions(evt.Source,uno::UNO_QUERY);
+ if ( xFunctions.is() )
+ {
+ m_pImpl->m_rModel.GetSdrUndoManager()->AddUndoAction( std::make_unique<OUndoContainerAction>(
+ m_pImpl->m_rModel, rptui::Removed, xFunctions.get(), xIface, RID_STR_UNDO_ADDFUNCTION ) );
+ }
+ }
+ }
+
+ if ( xIface.is() )
+ RemoveElement(xIface);
+
+ implSetModified();
+}
+
+
+void SAL_CALL OXUndoEnvironment::modified( const EventObject& /*aEvent*/ )
+{
+ implSetModified();
+}
+
+
+void OXUndoEnvironment::AddSection(const Reference< report::XSection > & _xSection)
+{
+ OUndoEnvLock aLock(*this);
+ try
+ {
+ uno::Reference<container::XChild> xChild = _xSection;
+ m_pImpl->m_aSections.push_back(xChild);
+ Reference< XInterface > xInt(_xSection);
+ AddElement(xInt);
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+}
+
+
+void OXUndoEnvironment::RemoveSection(const Reference< report::XSection > & _xSection)
+{
+ OUndoEnvLock aLock(*this);
+ try
+ {
+ uno::Reference<container::XChild> xChild(_xSection);
+ m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(),
+ xChild), m_pImpl->m_aSections.end());
+ Reference< XInterface > xInt(_xSection);
+ RemoveElement(xInt);
+ }
+ catch(uno::Exception&){}
+}
+
+
+void OXUndoEnvironment::switchListening( const Reference< XIndexAccess >& _rxContainer, bool _bStartListening )
+{
+ OSL_PRECOND( _rxContainer.is(), "OXUndoEnvironment::switchListening: invalid container!" );
+ if ( !_rxContainer.is() )
+ return;
+
+ try
+ {
+ // also handle all children of this element
+ Reference< XInterface > xInterface;
+ sal_Int32 nCount = _rxContainer->getCount();
+ for(sal_Int32 i = 0;i != nCount;++i)
+ {
+ xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY);
+ if ( _bStartListening )
+ AddElement( xInterface );
+ else
+ RemoveElement( xInterface );
+ }
+
+ // be notified of any changes in the container elements
+ Reference< XContainer > xSimpleContainer( _rxContainer, UNO_QUERY );
+ if ( xSimpleContainer.is() )
+ {
+ if ( _bStartListening )
+ xSimpleContainer->addContainerListener( this );
+ else
+ xSimpleContainer->removeContainerListener( this );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+}
+
+
+void OXUndoEnvironment::switchListening( const Reference< XInterface >& _rxObject, bool _bStartListening )
+{
+ OSL_PRECOND( _rxObject.is(), "OXUndoEnvironment::switchListening: how should I listen at a NULL object?" );
+
+ try
+ {
+ if ( !m_pImpl->m_bReadOnly )
+ {
+ Reference< XPropertySet > xProps( _rxObject, UNO_QUERY );
+ if ( xProps.is() )
+ {
+ if ( _bStartListening )
+ xProps->addPropertyChangeListener( OUString(), this );
+ else
+ xProps->removePropertyChangeListener( OUString(), this );
+ }
+ }
+
+ Reference< XModifyBroadcaster > xBroadcaster( _rxObject, UNO_QUERY );
+ if ( xBroadcaster.is() )
+ {
+ if ( _bStartListening )
+ xBroadcaster->addModifyListener( this );
+ else
+ xBroadcaster->removeModifyListener( this );
+ }
+ }
+ catch( const Exception& )
+ {
+ }
+}
+
+
+void OXUndoEnvironment::AddElement(const Reference< XInterface >& _rxElement )
+{
+ if ( !IsLocked() )
+ m_pImpl->m_aFormatNormalizer.notifyElementInserted( _rxElement );
+
+ // if it's a container, start listening at all elements
+ Reference< XIndexAccess > xContainer( _rxElement, UNO_QUERY );
+ if ( xContainer.is() )
+ switchListening( xContainer, true );
+
+ switchListening( _rxElement, true );
+}
+
+
+void OXUndoEnvironment::RemoveElement(const Reference< XInterface >& _rxElement)
+{
+ uno::Reference<beans::XPropertySet> xProp(_rxElement,uno::UNO_QUERY);
+ if (!m_pImpl->m_aPropertySetCache.empty())
+ m_pImpl->m_aPropertySetCache.erase(xProp);
+ switchListening( _rxElement, false );
+
+ Reference< XIndexAccess > xContainer( _rxElement, UNO_QUERY );
+ if ( xContainer.is() )
+ switchListening( xContainer, false );
+}
+
+void OXUndoEnvironment::SetUndoMode(bool _bUndo)
+{
+ m_pImpl->m_bIsUndo = _bUndo;
+}
+
+bool OXUndoEnvironment::IsUndoMode() const
+{
+ return m_pImpl->m_bIsUndo;
+}
+
+} // rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/formatnormalizer.cxx b/reportdesign/source/core/sdr/formatnormalizer.cxx
new file mode 100644
index 000000000..ae576bc40
--- /dev/null
+++ b/reportdesign/source/core/sdr/formatnormalizer.cxx
@@ -0,0 +1,258 @@
+/* -*- 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 "formatnormalizer.hxx"
+#include <RptModel.hxx>
+
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdb/XParametersSupplier.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+#include <unotools/syslocale.hxx>
+#include <connectivity/statementcomposer.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+#include <i18nlangtag/languagetag.hxx>
+
+
+namespace rptui
+{
+
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::report::XFormattedField;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::sdb::XSingleSelectQueryComposer;
+ using ::com::sun::star::sdbcx::XColumnsSupplier;
+ using ::com::sun::star::container::XIndexAccess;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::sdb::XParametersSupplier;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::util::XNumberFormatTypes;
+
+
+ //= FormatNormalizer
+
+
+ FormatNormalizer::FormatNormalizer( const OReportModel& _rModel )
+ :m_rModel( _rModel )
+ ,m_bFieldListDirty( true )
+ {
+ }
+
+
+ FormatNormalizer::~FormatNormalizer()
+ {
+ }
+
+
+ void FormatNormalizer::notifyPropertyChange( const css::beans::PropertyChangeEvent& _rEvent )
+ {
+ if ( !impl_lateInit() )
+ return;
+
+ if ( ( _rEvent.Source == m_xReportDefinition ) && m_xReportDefinition.is() )
+ {
+ impl_onDefinitionPropertyChange( _rEvent.PropertyName );
+ return;
+ }
+
+ Reference< XFormattedField > xFormatted( _rEvent.Source, UNO_QUERY );
+ if ( xFormatted.is() )
+ impl_onFormattedProperttyChange( xFormatted, _rEvent.PropertyName );
+ }
+
+
+ void FormatNormalizer::notifyElementInserted( const css::uno::Reference< css::uno::XInterface >& _rxElement )
+ {
+ if ( !impl_lateInit() )
+ return;
+
+ Reference< XFormattedField > xFormatted( _rxElement, UNO_QUERY );
+ if ( !xFormatted.is() )
+ return;
+
+ impl_adjustFormatToDataFieldType_nothrow( xFormatted );
+ }
+
+
+ bool FormatNormalizer::impl_lateInit()
+ {
+ if ( m_xReportDefinition.is() )
+ return true;
+
+ m_xReportDefinition = m_rModel.getReportDefinition();
+ return m_xReportDefinition.is();
+ }
+
+
+ void FormatNormalizer::impl_onDefinitionPropertyChange( std::u16string_view _rChangedPropName )
+ {
+ if ( _rChangedPropName != u"Command" && _rChangedPropName != u"CommandType" && _rChangedPropName != u"EscapeProcessing" )
+ // nothing we're interested in
+ return;
+ m_bFieldListDirty = true;
+ }
+
+
+ void FormatNormalizer::impl_onFormattedProperttyChange( const Reference< XFormattedField >& _rxFormatted, std::u16string_view _rChangedPropName )
+ {
+ if ( _rChangedPropName != u"DataField" )
+ // nothing we're interested in
+ return;
+
+ impl_adjustFormatToDataFieldType_nothrow( _rxFormatted );
+ }
+
+
+ namespace
+ {
+ void lcl_collectFields_throw( const Reference< XIndexAccess >& _rxColumns, FormatNormalizer::FieldList& _inout_rFields )
+ {
+ try
+ {
+ sal_Int32 nCount( _rxColumns->getCount() );
+ _inout_rFields.reserve( _inout_rFields.size() + static_cast<size_t>(nCount) );
+
+ Reference< XPropertySet > xColumn;
+ FormatNormalizer::Field aField;
+
+ for ( sal_Int32 i=0; i<nCount; ++i )
+ {
+ xColumn.set( _rxColumns->getByIndex( i ), UNO_QUERY_THROW );
+ OSL_VERIFY( xColumn->getPropertyValue("Name") >>= aField.sName );
+ OSL_VERIFY( xColumn->getPropertyValue("Type") >>= aField.nDataType );
+ OSL_VERIFY( xColumn->getPropertyValue("Scale") >>= aField.nScale );
+ OSL_VERIFY( xColumn->getPropertyValue("IsCurrency") >>= aField.bIsCurrency );
+ _inout_rFields.push_back( aField );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ }
+ }
+
+
+ bool FormatNormalizer::impl_ensureUpToDateFieldList_nothrow()
+ {
+ if ( !m_bFieldListDirty )
+ return true;
+ m_aFields.resize( 0 );
+
+ OSL_PRECOND( m_xReportDefinition.is(), "FormatNormalizer::impl_ensureUpToDateFieldList_nothrow: no report definition!" );
+ if ( !m_xReportDefinition.is() )
+ return false;
+
+ ::dbaui::DBSubComponentController* pController( m_rModel.getController() );
+ OSL_ENSURE( pController, "FormatNormalizer::impl_ensureUpToDateFieldList_nothrow: no controller? how can *this* happen?!" );
+ if ( !pController )
+ return false;
+
+ try
+ {
+ ::dbtools::StatementComposer aComposer( pController->getConnection(), m_xReportDefinition->getCommand(),
+ m_xReportDefinition->getCommandType(), m_xReportDefinition->getEscapeProcessing() );
+
+ Reference< XSingleSelectQueryComposer > xComposer( aComposer.getComposer() );
+ if ( !xComposer.is() )
+ return false;
+
+
+ Reference< XColumnsSupplier > xSuppCols( xComposer, UNO_QUERY_THROW );
+ Reference< XIndexAccess > xColumns( xSuppCols->getColumns(), UNO_QUERY_THROW );
+ lcl_collectFields_throw( xColumns, m_aFields );
+
+ Reference< XParametersSupplier > xSuppParams( xComposer, UNO_QUERY_THROW );
+ Reference< XIndexAccess > xParams( xSuppParams->getParameters(), css::uno::UNO_SET_THROW );
+ lcl_collectFields_throw( xParams, m_aFields );
+ }
+ catch( const SQLException& )
+ {
+ // silence it. This might happen for instance when the user sets a non-existent table,
+ // or things like this
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+
+ m_bFieldListDirty = false;
+ return true;
+ }
+
+
+ void FormatNormalizer::impl_adjustFormatToDataFieldType_nothrow( const Reference< XFormattedField >& _rxFormatted )
+ {
+ if ( !impl_ensureUpToDateFieldList_nothrow() )
+ // unable to obtain a recent field list
+ return;
+
+ try
+ {
+ sal_Int32 nFormatKey = _rxFormatted->getFormatKey();
+ if ( nFormatKey != 0 )
+ // it's not the "standard numeric" format -> not interested in
+ return;
+
+ OUString sDataField( _rxFormatted->getDataField() );
+ static const OUStringLiteral sFieldPrefix( u"field:[" );
+ if ( sDataField.indexOf( sFieldPrefix ) != 0 )
+ // not bound to a table field
+ // TODO: we might also do this kind of thing for functions and expressions ...
+ return;
+ if ( !sDataField.endsWith("]") )
+ {
+ // last character is not the closing brace
+ OSL_FAIL( "FormatNormalizer::impl_adjustFormatToDataFieldType_nothrow: suspicious data field value!" );
+ return;
+ }
+ sDataField = sDataField.copy( sFieldPrefix.getLength(), sDataField.getLength() - sFieldPrefix.getLength() - 1 );
+
+ FieldList::const_iterator field = std::find_if(m_aFields.begin(), m_aFields.end(),
+ [&sDataField](const Field& rField) { return rField.sName == sDataField; });
+ if ( field == m_aFields.end() )
+ // unknown field
+ return;
+
+ Reference< XNumberFormatsSupplier > xSuppNumFmts( _rxFormatted->getFormatsSupplier(), css::uno::UNO_SET_THROW );
+ Reference< XNumberFormatTypes > xNumFmtTypes( xSuppNumFmts->getNumberFormats(), UNO_QUERY_THROW );
+
+ nFormatKey = ::dbtools::getDefaultNumberFormat( field->nDataType, field->nScale, field->bIsCurrency, xNumFmtTypes,
+ SvtSysLocale().GetLanguageTag().getLocale() );
+ _rxFormatted->setFormatKey( nFormatKey );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("reportdesign");
+ }
+ }
+
+
+} // namespace rptui
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/reportdesign/source/core/sdr/formatnormalizer.hxx b/reportdesign/source/core/sdr/formatnormalizer.hxx
new file mode 100644
index 000000000..0ed30df3e
--- /dev/null
+++ b/reportdesign/source/core/sdr/formatnormalizer.hxx
@@ -0,0 +1,86 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_REPORTDESIGN_SOURCE_CORE_SDR_FORMATNORMALIZER_HXX
+#define INCLUDED_REPORTDESIGN_SOURCE_CORE_SDR_FORMATNORMALIZER_HXX
+
+#include <com/sun/star/report/XReportDefinition.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/report/XFormattedField.hpp>
+
+#include <vector>
+
+
+namespace rptui
+{
+
+
+ class OReportModel;
+
+ //= FormatNormalizer
+
+ class FormatNormalizer
+ {
+ public:
+ struct Field
+ {
+ OUString sName;
+ sal_Int32 nDataType;
+ sal_Int32 nScale;
+ bool bIsCurrency;
+
+ Field() : sName(), nDataType( 0 ), nScale( 0 ), bIsCurrency( false ) { }
+ };
+ typedef ::std::vector< Field > FieldList;
+
+ private:
+ const OReportModel& m_rModel;
+ css::uno::Reference< css::report::XReportDefinition > m_xReportDefinition;
+
+ /// is our field list dirty?
+ FieldList m_aFields;
+ bool m_bFieldListDirty;
+
+ public:
+ explicit FormatNormalizer( const OReportModel& _rModel );
+ ~FormatNormalizer();
+ FormatNormalizer(const FormatNormalizer&) = delete;
+ FormatNormalizer& operator=(const FormatNormalizer&) = delete;
+
+ void notifyPropertyChange( const css::beans::PropertyChangeEvent& _rEvent );
+ void notifyElementInserted( const css::uno::Reference< css::uno::XInterface >& _rxElement );
+
+ private:
+ bool impl_lateInit();
+
+ void impl_onDefinitionPropertyChange( std::u16string_view _rChangedPropName );
+ void impl_onFormattedProperttyChange( const css::uno::Reference< css::report::XFormattedField >& _rxFormatted, std::u16string_view _rChangedPropName );
+
+ bool impl_ensureUpToDateFieldList_nothrow();
+
+ void impl_adjustFormatToDataFieldType_nothrow( const css::uno::Reference< css::report::XFormattedField >& _rxFormatted );
+ };
+
+
+} // namespace rptui
+
+
+#endif // INCLUDED_REPORTDESIGN_SOURCE_CORE_SDR_FORMATNORMALIZER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */