summaryrefslogtreecommitdiff
path: root/svx/source/form/fmpgeimp.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/form/fmpgeimp.cxx')
-rw-r--r--svx/source/form/fmpgeimp.cxx301
1 files changed, 163 insertions, 138 deletions
diff --git a/svx/source/form/fmpgeimp.cxx b/svx/source/form/fmpgeimp.cxx
index 29fc384674ac..b50c72fd261c 100644
--- a/svx/source/form/fmpgeimp.cxx
+++ b/svx/source/form/fmpgeimp.cxx
@@ -32,31 +32,25 @@
#include "precompiled_svx.hxx"
#include "svxerr.hxx"
#include "fmpgeimp.hxx"
-#include <com/sun/star/sdb/CommandType.hpp>
-#include <com/sun/star/io/XObjectInputStream.hpp>
-#include <com/sun/star/io/XPersistObject.hpp>
-#include <com/sun/star/io/XObjectOutputStream.hpp>
-#include <com/sun/star/io/XActiveDataSink.hpp>
-#include <com/sun/star/io/XActiveDataSource.hpp>
-#include <com/sun/star/io/XMarkableStream.hpp>
-#include <sfx2/objsh.hxx>
#include "fmundo.hxx"
#include "fmtools.hxx"
-#ifndef _SVX_FMPROP_HRC
#include "fmprop.hrc"
-#endif
-#include <svx/fmglob.hxx>
#include "fmservs.hxx"
-
-// #include "fmstream.hxx"
#include "fmobj.hxx"
+#include "svditer.hxx"
+#include "fmresids.hrc"
+#include "dbtoolsclient.hxx"
+#include "treevisitor.hxx"
+
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+
+#include <sfx2/objsh.hxx>
+#include <svx/fmglob.hxx>
#include <svx/fmpage.hxx>
#include <svx/fmmodel.hxx>
#include <tools/resid.hxx>
#include <tools/diagnose_ex.h>
-#include "svditer.hxx"
-
-#include "fmresids.hrc"
#include <tools/shl.hxx>
#include <vcl/stdtext.hxx>
#include <svx/dialmgr.hxx>
@@ -64,7 +58,6 @@
#include <comphelper/uno3.hxx>
#include <comphelper/types.hxx>
#include <unotools/streamwrap.hxx>
-#include "dbtoolsclient.hxx"
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
@@ -73,6 +66,8 @@ using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::form;
+using ::com::sun::star::util::XCloneable;
+using ::com::sun::star::awt::XControlModel;
using namespace ::svxform;
DBG_NAME(FmFormPageImpl)
@@ -86,54 +81,159 @@ FmFormPageImpl::FmFormPageImpl(FmFormPage* _pPage)
}
//------------------------------------------------------------------------------
+namespace
+{
+ typedef Reference< XInterface > FormComponent;
+
+ class FormComponentInfo
+ {
+ public:
+ size_t childCount( const FormComponent& _component ) const
+ {
+ Reference< XIndexAccess > xContainer( _component, UNO_QUERY );
+ if ( xContainer.is() )
+ return xContainer->getCount();
+ return 0;
+ }
+
+ FormComponent getChild( const FormComponent& _component, size_t _index ) const
+ {
+ Reference< XIndexAccess > xContainer( _component, UNO_QUERY_THROW );
+ return FormComponent( xContainer->getByIndex( _index ), UNO_QUERY );
+ }
+ };
+
+ typedef ::std::pair< FormComponent, FormComponent > FormComponentPair;
+
+ class FormHierarchyComparator
+ {
+ public:
+ FormHierarchyComparator()
+ {
+ }
+
+ size_t childCount( const FormComponentPair& _components ) const
+ {
+ size_t lhsCount = m_aComponentInfo.childCount( _components.first );
+ size_t rhsCount = m_aComponentInfo.childCount( _components.second );
+ if ( lhsCount != rhsCount )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Found inconsistent form component hierarchies (1)!" ) ), NULL );
+ return lhsCount;
+ }
+
+ FormComponentPair getChild( const FormComponentPair& _components, size_t _index ) const
+ {
+ return FormComponentPair(
+ m_aComponentInfo.getChild( _components.first, _index ),
+ m_aComponentInfo.getChild( _components.second, _index )
+ );
+ }
+ private:
+ FormComponentInfo m_aComponentInfo;
+ };
+
+ typedef ::std::map< Reference< XControlModel >, Reference< XControlModel >, ::comphelper::OInterfaceCompare< XControlModel > > MapControlModels;
+
+ class FormComponentAssignment
+ {
+ public:
+ FormComponentAssignment( MapControlModels& _out_controlModelMap )
+ :m_rControlModelMap( _out_controlModelMap )
+ {
+ }
+
+ void process( const FormComponentPair& _component )
+ {
+ Reference< XControlModel > lhsControlModel( _component.first, UNO_QUERY );
+ Reference< XControlModel > rhsControlModel( _component.second, UNO_QUERY );
+ if ( lhsControlModel.is() != rhsControlModel.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Found inconsistent form component hierarchies (2)!" ) ), NULL );
+
+ if ( lhsControlModel.is() )
+ m_rControlModelMap[ lhsControlModel ] = rhsControlModel;
+ }
+
+ private:
+ MapControlModels& m_rControlModelMap;
+ };
+}
+
+//------------------------------------------------------------------------------
FmFormPageImpl::FmFormPageImpl(FmFormPage* _pPage, const FmFormPageImpl& rImpl)
- :pPage(_pPage)
- ,m_bFirstActivation( sal_True )
- ,m_bAttemptedFormCreation( false )
+ :pPage(_pPage)
+ ,m_bFirstActivation( sal_True )
+ ,m_bAttemptedFormCreation( false )
{
DBG_CTOR(FmFormPageImpl,NULL);
- OSL_ENSURE( false, "FmFormPageImpl::FmFormPageImpl: I'm pretty sure the below code isn't valid anymore ..." );
- // streaming of form/controls is not a supported operation anymore, in that it is not guaranteed
- // that really everything is copied. XCloneable should be used instead.
+ // clone the Forms collection
+ Reference< XCloneable > xCloneable( const_cast< FmFormPageImpl& >( rImpl ).getForms( false ), UNO_QUERY );
+ if ( !xCloneable.is() )
+ {
+ // great, nothing to do
+ OSL_ENSURE( !const_cast< FmFormPageImpl& >( rImpl ).getForms( false ).is(), "FmFormPageImpl::FmFormPageImpl: a non-cloneable forms container!?" );
+ return;
+ }
+ try
+ {
+ m_xForms.set( xCloneable->createClone(), UNO_QUERY_THROW );
- // copy it by streaming
- // creating a pipe
- Reference< ::com::sun::star::io::XOutputStream > xOutPipe(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY);
- Reference< ::com::sun::star::io::XInputStream > xInPipe(xOutPipe, UNO_QUERY);
+ // create a mapping between the original control models and their clones
+ MapControlModels aModelAssignment;
- // creating the mark streams
- Reference< ::com::sun::star::io::XInputStream > xMarkIn(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.io.MarkableInputStream")), UNO_QUERY);
- Reference< ::com::sun::star::io::XActiveDataSink > xMarkSink(xMarkIn, UNO_QUERY);
+ typedef TreeVisitor< FormComponentPair, FormHierarchyComparator, FormComponentAssignment > FormComponentVisitor;
+ FormComponentVisitor aVisitor = FormComponentVisitor( FormHierarchyComparator() );
- Reference< ::com::sun::star::io::XOutputStream > xMarkOut(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.io.MarkableOutputStream")), UNO_QUERY);
- Reference< ::com::sun::star::io::XActiveDataSource > xMarkSource(xMarkOut, UNO_QUERY);
+ FormComponentAssignment aAssignmentProcessor( aModelAssignment );
+ aVisitor.process( FormComponentPair( xCloneable, m_xForms ), aAssignmentProcessor );
- // connect pipe and sink
- Reference< ::com::sun::star::io::XActiveDataSink > xSink(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.io.ObjectInputStream")), UNO_QUERY);
+ // assign the cloned models to their SdrObjects
+ SdrObjListIter aForeignIter( *rImpl.pPage );
+ SdrObjListIter aOwnIter( *pPage );
- // connect pipe and source
- Reference< ::com::sun::star::io::XActiveDataSource > xSource(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.io.ObjectOutputStream")), UNO_QUERY);
+ OSL_ENSURE( aForeignIter.IsMore() == aOwnIter.IsMore(), "FmFormPageImpl::FmFormPageImpl: inconsistent number of objects (1)!" );
+ while ( aForeignIter.IsMore() && aOwnIter.IsMore() )
+ {
+ FmFormObj* pForeignObj = dynamic_cast< FmFormObj* >( aForeignIter.Next() );
+ FmFormObj* pOwnObj = dynamic_cast< FmFormObj* >( aOwnIter.Next() );
- Reference< ::com::sun::star::io::XObjectOutputStream > xOutStrm(xSource, UNO_QUERY);
- Reference< ::com::sun::star::io::XObjectInputStream > xInStrm(xSink, UNO_QUERY);
+ bool bForeignIsForm = pForeignObj && ( pForeignObj->GetObjInventor() == FmFormInventor );
+ bool bOwnIsForm = pOwnObj && ( pOwnObj->GetObjInventor() == FmFormInventor );
- if (xMarkSink.is() && xMarkSource.is() && xSink.is() && xSource.is() && xOutStrm.is() && xInStrm.is())
+ if ( bForeignIsForm != bOwnIsForm )
+ {
+ OSL_ENSURE( false, "FmFormPageImpl::FmFormPageImpl: inconsistent ordering of objects!" );
+ // don't attempt to do further assignments, something's completely messed up
+ break;
+ }
+ if ( !bForeignIsForm )
+ // no form control -> next round
+ continue;
+
+ Reference< XControlModel > xForeignModel( pForeignObj->GetUnoControlModel() );
+ OSL_ENSURE( xForeignModel.is(), "FmFormPageImpl::FmFormPageImpl: control shape without control!" );
+ if ( !xForeignModel.is() )
+ // the SdrObject does not have a UNO Control Model. This is pathological, but well ... So the cloned
+ // SdrObject will also not have a UNO Control Model.
+ continue;
+
+ OSL_ENSURE( !pOwnObj->GetUnoControlModel().is(), "FmFormPageImpl::FmFormPageImpl: there already is a control model for the target object!" );
+
+ MapControlModels::const_iterator assignment = aModelAssignment.find( xForeignModel );
+ OSL_ENSURE( assignment != aModelAssignment.end(), "FmFormPageImpl::FmFormPageImpl: no clone found for this model!" );
+ if ( assignment == aModelAssignment.end() )
+ // the source SdrObject has a model, but it is not part of the model hierarchy in rImpl.getForms().
+ // Pathological, too ...
+ continue;
+
+ pOwnObj->SetUnoControlModel( assignment->second );
+ }
+ OSL_ENSURE( aForeignIter.IsMore() == aOwnIter.IsMore(), "FmFormPageImpl::FmFormPageImpl: inconsistent number of objects (2)!" );
+ }
+ catch( const Exception& )
{
- xMarkSink->setInputStream(xInPipe);
- xMarkSource->setOutputStream(xOutPipe);
- xSink->setInputStream(xMarkIn);
- xSource->setOutputStream(xMarkOut);
-
- // write the objects to source
- rImpl.write(xOutStrm);
- xOutStrm->closeOutput();
-
- // read them
- read(xInStrm);
- xInStrm->closeInput();
+ DBG_UNHANDLED_EXCEPTION();
}
- // what to do else ?
}
//------------------------------------------------------------------------------
@@ -458,6 +558,17 @@ Reference< XForm > FmFormPageImpl::findFormForDataSource(
//------------------------------------------------------------------------------
::rtl::OUString FmFormPageImpl::setUniqueName(const Reference< XFormComponent > & xFormComponent, const Reference< XForm > & xControls)
{
+#if OSL_DEBUG_LEVEL > 0
+ try
+ {
+ Reference< XChild > xChild( xFormComponent, UNO_QUERY_THROW );
+ OSL_ENSURE( !xChild->getParent().is(), "FmFormPageImpl::setUniqueName: to be called before insertion!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+#endif
::rtl::OUString sName;
Reference< ::com::sun::star::beans::XPropertySet > xSet(xFormComponent, UNO_QUERY);
if (xSet.is())
@@ -554,89 +665,3 @@ UniString FmFormPageImpl::getDefaultName( sal_Int16 _nClassId, const Reference<
return sName;
}
-//------------------------------------------------------------------------------
-void FmFormPageImpl::write(const Reference< ::com::sun::star::io::XObjectOutputStream > & xOutStrm) const
-{
- Reference< ::com::sun::star::io::XMarkableStream > xMarkStrm(xOutStrm, UNO_QUERY);
- if (!xMarkStrm.is())
- return; // exception
-
- // sortieren der objectlist nach der Reihenfolge
- FmObjectList aList;
- fillList(aList, *pPage, sal_True);
-
- // schreiben aller forms
- Reference< ::com::sun::star::io::XPersistObject > xAsPersist( const_cast< FmFormPageImpl* >( this )->getForms(), UNO_QUERY);
- if (xAsPersist.is())
- xAsPersist->write(xOutStrm);
- // don't use the writeObject of the stream, as this wouldn't be compatible with older documents
-
- // objectliste einfuegen
- sal_Int32 nLength = aList.Count();
-
- // schreiben der laenge
- xOutStrm->writeLong(nLength);
-
- for (sal_Int32 i = 0; i < nLength; i++)
- {
- // schreiben des Objects mit Marke
- // Marke um an den Anfang zu springen
- Reference< ::com::sun::star::io::XPersistObject > xObj(aList.GetObject(i)->GetUnoControlModel(), UNO_QUERY);
- if (xObj.is())
- {
- xOutStrm->writeObject(xObj);
- }
- else
- {
- ;// exception
- }
- }
-}
-
-//------------------------------------------------------------------------------
-void FmFormPageImpl::read(const Reference< ::com::sun::star::io::XObjectInputStream > & xInStrm)
-{
- Reference< ::com::sun::star::io::XMarkableStream > xMarkStrm(xInStrm, UNO_QUERY);
- if (!xMarkStrm.is())
- return; // exception
-
- // sortieren der objectlist nach der Reihenfolge
- FmObjectList aList;
- fillList(aList, *pPage, sal_False);
-
- // lesen aller forms
- Reference< ::com::sun::star::io::XPersistObject > xAsPersist( getForms(), UNO_QUERY );
- if (xAsPersist.is())
- xAsPersist->read(xInStrm);
- // don't use the readObject of the stream, as this wouldn't be compatible with older documents
-
- // Zuordnung der Formobjekte zu den FormComponents
- sal_Int32 nLength = xInStrm->readLong();
- DBG_ASSERT(nLength == (sal_Int32) aList.Count(), "Fehler beim Lesen der UnoModels");
- for (sal_Int32 i = 0; i < nLength; i++)
- {
- Reference< ::com::sun::star::awt::XControlModel > xRef(xInStrm->readObject(), UNO_QUERY);
- if (i < (sal_Int32)aList.Count())
- aList.GetObject(i)->SetUnoControlModel(xRef);
- }
-}
-
-//------------------------------------------------------------------------------
-void FmFormPageImpl::fillList(FmObjectList& rList, const SdrObjList& rObjList, sal_Bool bConnected) const
-{
- SdrObjListIter aIter(rObjList);
- while (aIter.IsMore())
- {
- SdrObject* pObj = aIter.Next();
- if (pObj && pObj->GetObjInventor() == FmFormInventor)
- {
- FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
- DBG_ASSERT(!bConnected || pFormObj->GetUnoControlModel().is(), "Controlshape ohne Control");
- if (!bConnected || pFormObj->GetUnoControlModel().is())
- rList.Insert(pFormObj, LIST_APPEND);
-
- }
- }
-}
-
-